377 lines
13 KiB
Kotlin
377 lines
13 KiB
Kotlin
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>): 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<Float>{
|
|
val avgs = emptyList<Float>().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)
|
|
}
|
|
}
|
|
}
|