Skip to content

Commit

Permalink
Extract item
Browse files Browse the repository at this point in the history
  • Loading branch information
carstenhag committed Jan 30, 2025
1 parent c400611 commit b953703
Showing 1 changed file with 168 additions and 162 deletions.
330 changes: 168 additions & 162 deletions app/src/main/java/com/mensinator/app/symptoms/ManageSymptomScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.DpOffset
import androidx.compose.ui.unit.dp
import com.mensinator.app.R
import com.mensinator.app.data.ColorSource
import com.mensinator.app.data.Symptom
import com.mensinator.app.data.isActive
import com.mensinator.app.navigation.displayCutoutExcludingStatusBarsPadding
import com.mensinator.app.settings.ResourceMapper
Expand All @@ -28,8 +30,6 @@ import com.mensinator.app.ui.theme.UiConstants
import com.mensinator.app.ui.theme.isDarkMode
import org.koin.androidx.compose.koinViewModel

// TODO: Improve Composable structure

// TODO: Maybe delete savedSymptoms

private object SymptomScreenConstants {
Expand All @@ -43,7 +43,7 @@ fun ManageSymptomScreen(
setFabOnClick: (() -> Unit) -> Unit,
) {
val state = viewModel.viewState.collectAsState()
var savedSymptoms = state.value.allSymptoms
val symptoms = state.value.allSymptoms

LaunchedEffect(Unit) {
setFabOnClick { viewModel.showCreateSymptomDialog(true) }
Expand All @@ -60,163 +60,12 @@ fun ManageSymptomScreen(
verticalArrangement = Arrangement.spacedBy(16.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
savedSymptoms.forEach { symptom ->
var expanded by remember { mutableStateOf(false) }
var selectedColorName by remember { mutableStateOf(symptom.color) }
val selectedColor =
ColorSource.getColorMap(isDarkMode())[selectedColorName] ?: Color.Gray

val symptomDisplayName = ResourceMapper.getStringResourceOrCustom(symptom.name)
Card(
onClick = {
viewModel.setSymptomToRename(symptom)
},
modifier = Modifier.fillMaxWidth(),
shape = MaterialTheme.shapes.extraLarge,
) {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Start,
modifier = Modifier
.fillMaxWidth()
.padding(start = 10.dp, end = 10.dp)
) {
if (savedSymptoms.size > 1) {
IconButton(
onClick = {
val activeSymptoms = state.value.activeSymptoms
if (activeSymptoms.contains(symptom)) {
viewModel.setSymptomToDelete(symptom)
} else {
symptom.let { symptom ->
savedSymptoms = savedSymptoms.filter { it.id != symptom.id }
viewModel.deleteSymptom(symptom.id)
}
}
},
modifier = Modifier.size(20.dp)
) {
Icon(
Icons.Default.Close,
contentDescription = stringResource(id = R.string.close)
)
}
}
Spacer(modifier = Modifier.padding(start = 5.dp))
Text(
text = symptomDisplayName,
textAlign = TextAlign.Left,
modifier = Modifier.weight(1f) // Let the text expand to fill available space
)

//Color Picker Dropdown Menu
Box {
// Color Dropdown wrapped in a Box for alignment
Card(
onClick = { expanded = true }
) {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center,
) {
Box(
modifier = Modifier
.size(SymptomScreenConstants.colorCircleSize)
.clip(CircleShape)
.background(selectedColor),
)
Icon(
painter = painterResource(id = R.drawable.keyboard_arrow_down_24px),
contentDescription = stringResource(id = R.string.selection_color),
modifier = Modifier.wrapContentSize()
)
}
}

DropdownMenu(
offset = DpOffset(x = (-50).dp, y = (10).dp),
expanded = expanded,
onDismissRequest = { expanded = false },
modifier = Modifier
.wrapContentSize()
) {
// Retrieve the colorMap from DataSource
val colorMap = ColorSource.getColorMap(isDarkMode())

Column(
modifier = Modifier.wrapContentSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
ColorSource.colorsGroupedByHue.forEach { colorGroup ->
Row(
modifier = Modifier.wrapContentSize(),
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically
) {
colorGroup.forEach { colorName ->
val colorValue = colorMap[colorName]
if (colorValue != null) {
DropdownMenuItem(
modifier = Modifier
.size(SymptomScreenConstants.colorCircleSize * 2)
.clip(CircleShape),
onClick = {
selectedColorName = colorName
expanded = false
val updatedSymptom =
symptom.copy(color = colorName)
savedSymptoms = savedSymptoms.map {
if (it.id == symptom.id) updatedSymptom else it
}
// Save settings to the database
savedSymptoms.forEach { symptom ->
viewModel.updateSymptom(
symptom.id,
symptom.active,
symptom.color
)
}
},
text = {
Box(
modifier = Modifier
.size(SymptomScreenConstants.colorCircleSize)
.clip(CircleShape)
.background(colorValue) // Use the color from the map
)
}
)
}
}
}
}
}
}
}

Spacer(modifier = Modifier.weight(0.05f))

Switch(
checked = symptom.isActive,
onCheckedChange = { checked ->
val updatedSymptom = symptom.copy(active = if (checked) 1 else 0)
savedSymptoms = savedSymptoms.map {
if (it.id == symptom.id) updatedSymptom else it
}
// Save settings to the database
savedSymptoms.forEach { symptom ->
viewModel.updateSymptom(
symptom.id,
symptom.active,
symptom.color
)
}
},
)
Spacer(modifier = Modifier.weight(0.05f))
}
}
symptoms.forEach { symptom ->
SymptomItem(
viewModel = viewModel,
symptom = symptom,
showDeletionIcon = symptoms.size > 1
)
}
}

Expand All @@ -235,8 +84,7 @@ fun ManageSymptomScreen(
val symptomToRename = state.value.symptomToRename
if (symptomToRename != null) {
val symptomKey = ResourceMapper.getStringResourceId(symptomToRename.name)
val symptomDisplayName =
symptomKey?.let { stringResource(id = it) } ?: symptomToRename.name
val symptomDisplayName = symptomKey?.let { stringResource(id = it) } ?: symptomToRename.name

RenameSymptomDialog(
symptomDisplayName = symptomDisplayName,
Expand All @@ -263,3 +111,161 @@ fun ManageSymptomScreen(
)
}
}

@Composable
private fun SymptomItem(
viewModel: ManageSymptomsViewModel,
symptom: Symptom,
showDeletionIcon: Boolean
) {
val selectedColor = ColorSource.getColorMap(isDarkMode())[symptom.color] ?: Color.Gray
val symptomDisplayName = ResourceMapper.getStringResourceOrCustom(symptom.name)

Card(
onClick = {
viewModel.setSymptomToRename(symptom)
},
modifier = Modifier.fillMaxWidth(),
shape = MaterialTheme.shapes.extraLarge,
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 10.dp)
) {
if (showDeletionIcon) {
IconButton(
onClick = { viewModel.setSymptomToDelete(symptom) },
modifier = Modifier.size(20.dp)
) {
Icon(
imageVector = Icons.Default.Close,
contentDescription = stringResource(id = R.string.close)
)
}
}
Spacer(modifier = Modifier.padding(start = 5.dp))
Text(
text = symptomDisplayName,
textAlign = TextAlign.Left,
modifier = Modifier.weight(1f) // Let the text expand to fill available space
)

//Color Picker Dropdown Menu
ColorPicker(selectedColor, symptom, viewModel)

Spacer(modifier = Modifier.weight(0.05f))

Switch(
checked = symptom.isActive,
onCheckedChange = { checked ->
val updatedSymptom = symptom.copy(active = if (checked) 1 else 0)
viewModel.updateSymptom(
updatedSymptom.id,
updatedSymptom.active,
updatedSymptom.color
)
},
)
Spacer(modifier = Modifier.weight(0.05f))
}
}
}

@Composable
private fun ColorPicker(
selectedColor: Color,
symptom: Symptom,
viewModel: ManageSymptomsViewModel
) {
var expanded by remember { mutableStateOf(false) }

Box {
// Color Dropdown wrapped in a Box for alignment
Card(
onClick = { expanded = true }
) {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center,
) {
Box(
modifier = Modifier
.size(SymptomScreenConstants.colorCircleSize)
.clip(CircleShape)
.background(selectedColor),
)
Icon(
painter = painterResource(id = R.drawable.keyboard_arrow_down_24px),
contentDescription = stringResource(id = R.string.selection_color),
modifier = Modifier.wrapContentSize()
)
}
}

DropdownMenu(
offset = DpOffset(x = (-50).dp, y = (10).dp),
expanded = expanded,
onDismissRequest = { expanded = false },
modifier = Modifier.wrapContentSize()
) {
// Retrieve the colorMap from DataSource
val colorMap = ColorSource.getColorMap(isDarkMode())

Column(
modifier = Modifier.wrapContentSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
ColorSource.colorsGroupedByHue.forEach { colorGroup ->
Row(
modifier = Modifier.wrapContentSize(),
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically
) {
colorGroup.forEach { colorName ->
val colorValue = colorMap[colorName] ?: return@Row
DropdownMenuItem(
modifier = Modifier
.size(SymptomScreenConstants.colorCircleSize * 2)
.clip(CircleShape),
onClick = {
expanded = false
val updatedSymptom = symptom.copy(color = colorName)
viewModel.updateSymptom(
updatedSymptom.id,
updatedSymptom.active,
updatedSymptom.color
)
},
text = {
Box(
modifier = Modifier
.size(SymptomScreenConstants.colorCircleSize)
.clip(CircleShape)
.background(colorValue) // Use the color from the map
)
}
)
}
}
}
}
}
}
}


// TODO: Broken
@Preview(showBackground = true)
@Composable
private fun SymptomItemPreview() {
MensinatorTheme {
SymptomItem(
viewModel = koinViewModel(),
symptom = Symptom(1, "Medium flow", 1, "red"),
showDeletionIcon = true
)
}
}

0 comments on commit b953703

Please sign in to comment.