Refine period tracking logic and UI feedback in DayDetailScreen.
- Update `DayDetailUiState` to include `hasActiveCycle` and `cycleStartDate` to better track ongoing cycles.
- Replace `periodActive` check with `hasActiveCycle` for displaying the "Period day" badge and toggle icons.
- Improve validation for the "Period ended" action:
- Enable the chip only if a cycle is active and the current date is after the cycle's start date.
- Update `DayDetailViewModel` to accurately calculate `periodDayNumber` and cycle status by fetching records from the repository.
- Ensure period state is correctly reset or initialized when toggling period start/end.
Signed-off-by: whitlocktech <whitlocktech@gmail.com>
This commit is contained in:
@@ -152,7 +152,7 @@ private fun CycleSection(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Period day-of-period badge
|
// Period day-of-period badge
|
||||||
if (state.periodActive && state.periodDayNumber > 0) {
|
if (state.hasActiveCycle && state.periodDayNumber > 0) {
|
||||||
Text(
|
Text(
|
||||||
"Period day ${state.periodDayNumber}",
|
"Period day ${state.periodDayNumber}",
|
||||||
style = MaterialTheme.typography.bodySmall,
|
style = MaterialTheme.typography.bodySmall,
|
||||||
@@ -171,7 +171,7 @@ private fun CycleSection(
|
|||||||
label = { Text("Period started") },
|
label = { Text("Period started") },
|
||||||
leadingIcon = {
|
leadingIcon = {
|
||||||
Icon(
|
Icon(
|
||||||
if (state.isPeriodStart) Icons.Default.Check else Icons.Default.PlayArrow,
|
if (state.isPeriodStart || state.hasActiveCycle) Icons.Default.Check else Icons.Default.PlayArrow,
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
modifier = Modifier.size(16.dp)
|
modifier = Modifier.size(16.dp)
|
||||||
)
|
)
|
||||||
@@ -180,7 +180,8 @@ private fun CycleSection(
|
|||||||
FilterChip(
|
FilterChip(
|
||||||
selected = state.isPeriodEnd,
|
selected = state.isPeriodEnd,
|
||||||
onClick = onTogglePeriodEnd,
|
onClick = onTogglePeriodEnd,
|
||||||
enabled = state.isPeriodStart || state.periodActive || state.isPeriodEnd,
|
enabled = state.isPeriodEnd ||
|
||||||
|
(state.hasActiveCycle && state.cycleStartDate != null && state.date > state.cycleStartDate),
|
||||||
label = { Text("Period ended") },
|
label = { Text("Period ended") },
|
||||||
leadingIcon = {
|
leadingIcon = {
|
||||||
Icon(
|
Icon(
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ data class DayDetailUiState(
|
|||||||
val isPeriodStart: Boolean = false,
|
val isPeriodStart: Boolean = false,
|
||||||
val isPeriodEnd: Boolean = false,
|
val isPeriodEnd: Boolean = false,
|
||||||
val periodDayNumber: Int = 0, // day-of-period for this date (1 = first day)
|
val periodDayNumber: Int = 0, // day-of-period for this date (1 = first day)
|
||||||
|
val hasActiveCycle: Boolean = false, // a cycle record spans this date (start logged, regardless of which day)
|
||||||
|
val cycleStartDate: LocalDate? = null,
|
||||||
val notes: String = "",
|
val notes: String = "",
|
||||||
val conditions: Map<String, Int> = emptyMap(),
|
val conditions: Map<String, Int> = emptyMap(),
|
||||||
val definitions: List<ConditionDefinitionEntity> = emptyList(),
|
val definitions: List<ConditionDefinitionEntity> = emptyList(),
|
||||||
@@ -88,12 +90,11 @@ class DayDetailViewModel @Inject constructor(
|
|||||||
val isPeriodStart = isFemale && cycleRepository.isPeriodStart(activeProfile.id, dateStr)
|
val isPeriodStart = isFemale && cycleRepository.isPeriodStart(activeProfile.id, dateStr)
|
||||||
val isPeriodEnd = isFemale && cycleRepository.isPeriodEnd(activeProfile.id, dateStr)
|
val isPeriodEnd = isFemale && cycleRepository.isPeriodEnd(activeProfile.id, dateStr)
|
||||||
|
|
||||||
// Calculate day-of-period: how many days from the period start to this date
|
val cycleRecord = if (isFemale) cycleRepository.getRecordContainingDate(activeProfile.id, dateStr) else null
|
||||||
val periodDayNumber = if (isFemale && dayLog.periodActive) {
|
val hasActiveCycle = cycleRecord != null
|
||||||
val record = cycleRepository.getRecordContainingDate(activeProfile.id, dateStr)
|
val cycleStartDate = cycleRecord?.let { LocalDate.parse(it.cycleStart) }
|
||||||
if (record != null) {
|
val periodDayNumber = if (cycleRecord != null) {
|
||||||
(date.toEpochDay() - LocalDate.parse(record.cycleStart).toEpochDay()).toInt() + 1
|
(date.toEpochDay() - LocalDate.parse(cycleRecord.cycleStart).toEpochDay()).toInt() + 1
|
||||||
} else 0
|
|
||||||
} else 0
|
} else 0
|
||||||
|
|
||||||
_uiState.value = DayDetailUiState(
|
_uiState.value = DayDetailUiState(
|
||||||
@@ -105,6 +106,8 @@ class DayDetailViewModel @Inject constructor(
|
|||||||
isPeriodStart = isPeriodStart,
|
isPeriodStart = isPeriodStart,
|
||||||
isPeriodEnd = isPeriodEnd,
|
isPeriodEnd = isPeriodEnd,
|
||||||
periodDayNumber = periodDayNumber,
|
periodDayNumber = periodDayNumber,
|
||||||
|
hasActiveCycle = hasActiveCycle,
|
||||||
|
cycleStartDate = cycleStartDate,
|
||||||
notes = dayLog.notes ?: "",
|
notes = dayLog.notes ?: "",
|
||||||
conditions = conditions,
|
conditions = conditions,
|
||||||
definitions = defsToShow,
|
definitions = defsToShow,
|
||||||
@@ -136,6 +139,8 @@ class DayDetailViewModel @Inject constructor(
|
|||||||
periodActive = false,
|
periodActive = false,
|
||||||
dayLog = updatedLog,
|
dayLog = updatedLog,
|
||||||
periodDayNumber = 0,
|
periodDayNumber = 0,
|
||||||
|
hasActiveCycle = false,
|
||||||
|
cycleStartDate = null,
|
||||||
isDirty = true
|
isDirty = true
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
@@ -150,6 +155,8 @@ class DayDetailViewModel @Inject constructor(
|
|||||||
periodActive = true,
|
periodActive = true,
|
||||||
dayLog = updatedLog,
|
dayLog = updatedLog,
|
||||||
periodDayNumber = 1,
|
periodDayNumber = 1,
|
||||||
|
hasActiveCycle = true,
|
||||||
|
cycleStartDate = date,
|
||||||
isDirty = true
|
isDirty = true
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user