package com.schoolapp.cleverclass import android.content.Context import android.content.Intent import android.content.SharedPreferences import android.content.SharedPreferences.Editor import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ArrowBack import androidx.compose.material.icons.outlined.Delete import androidx.compose.material3.AlertDialog import androidx.compose.material3.BottomAppBar import androidx.compose.material3.Button import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.Divider import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import com.schoolapp.cleverclass.ui.theme.CleverClassTheme import com.schoolapp.cleverclass.ui.theme.TextOnColouredButton import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch private val subjects = listOf( "Mathe", "Deutsch", "Englisch", "Französisch", "Latein", "Physik", "Chemie", "Biologie", "Informatik", "Geographie", "Wirtschaft", "Geschichte", "Politik und Gesellschaft", "Ethik", "Evangelisch", "Katholisch", "Kunst", "Musik", "Sport" ) private val saWeights = listOf( 2, 2, 2, 2, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) private val colorsA = listOf( Color(0xFF536DFE), Color(0xFF18FFFF), Color(0xFF448AFF), Color(0xFF64FFDA), Color(0xFF40C4FF) ) private val colorsB = listOf( Color(0xFFFFFF00), Color(0xFFFFAB40), Color(0xFFFFD740), Color(0xFFEEFF41) ) private val colorsC = listOf( Color(0xFFFF5252), Color(0xFFFF4081), Color(0xFFFF6052), Color(0xFFFF6E40) ) class NotenActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { CleverClassTheme { Surface( modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background ) { NotenContent(activity = this) } } } } } // Content of Noten @OptIn(ExperimentalMaterial3Api::class) @Composable fun NotenContent(activity: ComponentActivity){ val sharedPreferences = activity.getSharedPreferences("gradeAverages", Context.MODE_PRIVATE) val editor = sharedPreferences.edit() var allAverage by remember { mutableStateOf(calculateAllAverage(loadAllAverages(sharedPreferences))) } var showDeleteConfirmation by remember { mutableStateOf(false) } Scaffold( topBar = { TopAppBar( colors = TopAppBarDefaults.centerAlignedTopAppBarColors(MaterialTheme.colorScheme.primaryContainer), title = { Text(text = "Noten", style = MaterialTheme.typography.headlineSmall, color = MaterialTheme.colorScheme.onPrimaryContainer )}, navigationIcon = { IconButton(onClick = { activity.finish() }) { Icon( imageVector = Icons.Filled.ArrowBack, contentDescription = null, modifier = Modifier.size(28.dp), tint = MaterialTheme.colorScheme.onPrimaryContainer ) } }, actions = { IconButton(onClick = { showDeleteConfirmation = true }) { Icon( imageVector = Icons.Outlined.Delete, contentDescription = null, modifier = Modifier.size(28.dp), tint = MaterialTheme.colorScheme.onPrimaryContainer ) } }, modifier = Modifier.fillMaxWidth() ) }, bottomBar = { BottomAppBar( containerColor = MaterialTheme.colorScheme.primaryContainer, modifier = Modifier .fillMaxWidth() .height(64.dp) ) { Row (modifier = Modifier .fillMaxWidth() .align(Alignment.CenterVertically)){ Spacer(modifier = Modifier.width(16.dp)) Text(text = "Gesamtschnitt:", style = MaterialTheme.typography.headlineSmall) Spacer(modifier = Modifier.weight(1f)) Text( text = "Ø" + formatFloat(allAverage), style = MaterialTheme.typography.headlineSmall) Spacer(modifier = Modifier.width(16.dp)) } } } ) {innerPadding -> Column( horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier .verticalScroll(rememberScrollState()) .padding(innerPadding) ) { GroopTitle("Hauptfächer", true) for (i in 0..4){ FachButton( color = colorsA[i], subject = subjects[i], saWeight = saWeights[i], activity = activity, sharedPreferences = sharedPreferences, onAvgChange = { allAverage = calculateAllAverage(loadAllAverages(sharedPreferences)) } ) } GroopTitle("Naturwissenschaften", false) for (i in 5..8){ FachButton( color = colorsB[i - 5], subject = subjects[i], saWeight = saWeights[i], activity = activity, sharedPreferences = sharedPreferences, onAvgChange = { allAverage = calculateAllAverage(loadAllAverages(sharedPreferences)) } ) } GroopTitle("Gesellschaftswissenschaften", false) for (i in 9..12){ FachButton( color = colorsC[i - 9], subject = subjects[i], saWeight = saWeights[i], activity = activity, sharedPreferences = sharedPreferences, onAvgChange = { allAverage = calculateAllAverage(loadAllAverages(sharedPreferences)) } ) } GroopTitle("Religionen", false) for (i in 13..15){ FachButton( color = colorsA[i - 13], subject = subjects[i], saWeight = saWeights[i], activity = activity, sharedPreferences = sharedPreferences, onAvgChange = { allAverage = calculateAllAverage(loadAllAverages(sharedPreferences)) } ) } GroopTitle("Sonstiges", false) for (i in 16..18){ FachButton( color = colorsB[i - 16], subject = subjects[i], saWeight = saWeights[i], activity = activity, sharedPreferences = sharedPreferences, onAvgChange = { allAverage = calculateAllAverage(loadAllAverages(sharedPreferences)) } ) } Spacer(modifier = Modifier.height(16.dp)) } } if (showDeleteConfirmation){ AlertDialog( onDismissRequest = { showDeleteConfirmation = false }, text = { Text(text = "Möchten Sie wirklich alle Noten aus Allen Fächern löschen?", color = MaterialTheme.colorScheme.onPrimaryContainer, style = MaterialTheme.typography.labelMedium) }, confirmButton = { Row(modifier = Modifier.fillMaxWidth()){ Text( text = "Bestätigen", color = MaterialTheme.colorScheme.secondary, style = MaterialTheme.typography.labelMedium, modifier = Modifier.clickable { deleteAll(editor, activity) showDeleteConfirmation = false } ) Spacer(modifier = Modifier.weight(1f)) Text( text = "Abbrechen", color = MaterialTheme.colorScheme.secondary, style = MaterialTheme.typography.labelMedium, modifier = Modifier.clickable { showDeleteConfirmation = false } ) } }, containerColor = MaterialTheme.colorScheme.primaryContainer ) } } @Composable fun FachButton( color : Color, subject : String, saWeight: Int, activity: ComponentActivity, sharedPreferences: SharedPreferences, onAvgChange: () -> Unit){ var avg by remember { mutableStateOf(sharedPreferences.getFloat(subject, 0.0f)) } Button( onClick = { val intent = Intent(activity, FachActivity::class.java).apply { putExtra(FachActivity.NAME_KEY, subject) putExtra(FachActivity.WEIGHT_KEY, saWeight) } activity.startActivity(intent) }, shape = RoundedCornerShape(40), colors = ButtonDefaults.outlinedButtonColors(containerColor = color), modifier = Modifier .fillMaxWidth() .height(64.dp) .padding(start = 16.dp, end = 16.dp, top = 16.dp) ) { Row(modifier = Modifier.fillMaxWidth()) { Text(text = subject, color = TextOnColouredButton, style = MaterialTheme.typography.labelMedium) Spacer(modifier = Modifier.weight(1f)) Text(text = if (avg != 0.0f) "Ø${formatFloat(avg)}" else "---", color = TextOnColouredButton, style = MaterialTheme.typography.labelMedium) } } // changes state when Shared Preference is updated val observer = remember { SharedPreferences.OnSharedPreferenceChangeListener { _, key -> if (key == subject) { avg = sharedPreferences.getFloat(subject, 0.0f) onAvgChange() } } } // handles observer creation and disposal DisposableEffect(Unit) { sharedPreferences.registerOnSharedPreferenceChangeListener(observer) onDispose { sharedPreferences.unregisterOnSharedPreferenceChangeListener(observer) } } } @Composable fun GroopTitle(name: String, top: Boolean){ if(!top) { Spacer(modifier = Modifier.height(32.dp)) Divider() } Spacer(modifier = Modifier.height(32.dp)) Text(text = name, style = MaterialTheme.typography.headlineSmall, color = MaterialTheme.colorScheme.onBackground) Spacer(modifier = Modifier.height(12.dp)) } fun calculateAllAverage(avgs: List): Float{ var total = 0.0f var number = 0 avgs.forEach{ avg -> if (avg != 0.0f && !avg.isNaN()){ total += avg number += 1 } } return (total / number) } fun loadAllAverages(sharedPreferences: SharedPreferences): List{ val avgs = emptyList().toMutableList() subjects.forEach { name -> avgs += sharedPreferences.getFloat(name, 0.0f) } return avgs } fun deleteAll(editor: Editor, context: Context){ subjects.forEach{name -> editor.putFloat(name, 0.0f).apply() CoroutineScope(Dispatchers.IO).launch { GradeStoreManager.saveGrades(context, emptyList(), name) } } }