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:
2026-05-22 17:52:18 -05:00
parent 5b900a4823
commit cd276ed44c
2 changed files with 17 additions and 9 deletions

View File

@@ -152,7 +152,7 @@ private fun CycleSection(
}
// Period day-of-period badge
if (state.periodActive && state.periodDayNumber > 0) {
if (state.hasActiveCycle && state.periodDayNumber > 0) {
Text(
"Period day ${state.periodDayNumber}",
style = MaterialTheme.typography.bodySmall,
@@ -171,7 +171,7 @@ private fun CycleSection(
label = { Text("Period started") },
leadingIcon = {
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,
modifier = Modifier.size(16.dp)
)
@@ -180,7 +180,8 @@ private fun CycleSection(
FilterChip(
selected = state.isPeriodEnd,
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") },
leadingIcon = {
Icon(

View File

@@ -31,6 +31,8 @@ data class DayDetailUiState(
val isPeriodStart: Boolean = false,
val isPeriodEnd: Boolean = false,
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 conditions: Map<String, Int> = emptyMap(),
val definitions: List<ConditionDefinitionEntity> = emptyList(),
@@ -88,12 +90,11 @@ class DayDetailViewModel @Inject constructor(
val isPeriodStart = isFemale && cycleRepository.isPeriodStart(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 periodDayNumber = if (isFemale && dayLog.periodActive) {
val record = cycleRepository.getRecordContainingDate(activeProfile.id, dateStr)
if (record != null) {
(date.toEpochDay() - LocalDate.parse(record.cycleStart).toEpochDay()).toInt() + 1
} else 0
val cycleRecord = if (isFemale) cycleRepository.getRecordContainingDate(activeProfile.id, dateStr) else null
val hasActiveCycle = cycleRecord != null
val cycleStartDate = cycleRecord?.let { LocalDate.parse(it.cycleStart) }
val periodDayNumber = if (cycleRecord != null) {
(date.toEpochDay() - LocalDate.parse(cycleRecord.cycleStart).toEpochDay()).toInt() + 1
} else 0
_uiState.value = DayDetailUiState(
@@ -105,6 +106,8 @@ class DayDetailViewModel @Inject constructor(
isPeriodStart = isPeriodStart,
isPeriodEnd = isPeriodEnd,
periodDayNumber = periodDayNumber,
hasActiveCycle = hasActiveCycle,
cycleStartDate = cycleStartDate,
notes = dayLog.notes ?: "",
conditions = conditions,
definitions = defsToShow,
@@ -136,6 +139,8 @@ class DayDetailViewModel @Inject constructor(
periodActive = false,
dayLog = updatedLog,
periodDayNumber = 0,
hasActiveCycle = false,
cycleStartDate = null,
isDirty = true
)
} else {
@@ -150,6 +155,8 @@ class DayDetailViewModel @Inject constructor(
periodActive = true,
dayLog = updatedLog,
periodDayNumber = 1,
hasActiveCycle = true,
cycleStartDate = date,
isDirty = true
)
}