Initial commit: Implement base health and cycle tracking application.
- Set up Android project structure with Gradle 8.7, Kotlin 2.0, and Hilt.
- Implement Room database with entities for Profiles, Day Logs, Conditions, Cycle Records, and Intimacy Logs.
- Integrate Jetpack Compose for the UI layer including Navigation and Material3.
- Develop a cycle prediction engine to calculate menstruation, fertile windows, and ovulation based on user history.
- Implement core screens:
- **Onboarding:** Initial profile setup for female/male users.
- **Calendar:** Monthly view showing cycle phases, logged symptoms, and intimacy records.
- **Day Detail:** Detailed logging for symptoms (with ratings), period status, notes, and intimacy encounters.
- **Cycle Insights:** Visualization of cycle phases and historical cycle length trends.
- **Health Trends:** Frequency and recurrence analysis of logged health conditions over various time ranges.
- **Settings:** Profile management, data clearing, and app theme configuration.
- Add DataStore for managing user preferences such as active profile and onboarding status.
Signed-off-by: whitlocktech <whitlocktech@gmail.com>
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
package com.hsdiary.ui.components
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
data class ProfileSwitchItem(
|
||||
val id: Long,
|
||||
val name: String,
|
||||
val avatarColor: Color,
|
||||
val isActive: Boolean
|
||||
)
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun ProfileSwitchSheet(
|
||||
profiles: List<ProfileSwitchItem>,
|
||||
onProfileSelected: (Long) -> Unit,
|
||||
onDismiss: () -> Unit
|
||||
) {
|
||||
var confirmTarget by remember { mutableStateOf<ProfileSwitchItem?>(null) }
|
||||
|
||||
ModalBottomSheet(onDismissRequest = onDismiss) {
|
||||
Column(modifier = Modifier.padding(horizontal = 24.dp).padding(bottom = 32.dp)) {
|
||||
Text(
|
||||
text = "Switch Profile",
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
modifier = Modifier.padding(bottom = 16.dp)
|
||||
)
|
||||
profiles.forEach { profile ->
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable {
|
||||
if (!profile.isActive) confirmTarget = profile
|
||||
else onDismiss()
|
||||
}
|
||||
.padding(vertical = 12.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(16.dp)
|
||||
) {
|
||||
AvatarDot(name = profile.name, avatarColor = profile.avatarColor)
|
||||
Text(
|
||||
text = profile.name,
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
modifier = Modifier.weight(1f)
|
||||
)
|
||||
if (profile.isActive) {
|
||||
Badge { Text("Active") }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
confirmTarget?.let { target ->
|
||||
AlertDialog(
|
||||
onDismissRequest = { confirmTarget = null },
|
||||
title = { Text("Switch Profile") },
|
||||
text = { Text("Switch to ${target.name}?") },
|
||||
confirmButton = {
|
||||
TextButton(onClick = {
|
||||
onProfileSelected(target.id)
|
||||
confirmTarget = null
|
||||
onDismiss()
|
||||
}) { Text("Switch") }
|
||||
},
|
||||
dismissButton = {
|
||||
TextButton(onClick = { confirmTarget = null }) { Text("Cancel") }
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user