This commit is contained in:
Trey t
2025-11-04 11:42:00 -06:00
parent de1c7931e9
commit ba27ddda71
11 changed files with 323 additions and 117 deletions

View File

@@ -10,7 +10,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.unit.dp
import com.mycrib.shared.models.TaskCompletionCreateRequest
import kotlin.time.Clock
import kotlinx.datetime.Clock
import kotlin.time.ExperimentalTime
@OptIn(ExperimentalMaterial3Api::class)
@@ -106,7 +106,6 @@ fun CompleteTaskDialog(
// Helper function to get current date/time in ISO format
@OptIn(ExperimentalTime::class)
private fun getCurrentDateTime(): String {
// This is a simplified version - in production you'd use kotlinx.datetime
val now = Clock.System.now()
val now = kotlin.time.Clock.System.now()
return now.toString()
}

View File

@@ -371,84 +371,86 @@ fun TaskCard(
}
}
// Show completions
if (task.completions.isNotEmpty()) {
Divider(modifier = Modifier.padding(vertical = 8.dp))
Text(
text = "Completions (${task.completions.size})",
style = MaterialTheme.typography.titleSmall,
color = MaterialTheme.colorScheme.primary
)
if (!task.frequency.equals("once")) {
// Show completions
if (task.completions.isNotEmpty()) {
Divider(modifier = Modifier.padding(vertical = 8.dp))
Text(
text = "Completions (${task.completions.size})",
style = MaterialTheme.typography.titleSmall,
color = MaterialTheme.colorScheme.primary
)
task.completions.forEach { completion ->
Spacer(modifier = Modifier.height(8.dp))
Surface(
color = MaterialTheme.colorScheme.surfaceVariant,
shape = MaterialTheme.shapes.small
) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(12.dp)
task.completions.forEach { completion ->
Spacer(modifier = Modifier.height(8.dp))
Surface(
color = MaterialTheme.colorScheme.surfaceVariant,
shape = MaterialTheme.shapes.small
) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
Column(
modifier = Modifier
.fillMaxWidth()
.padding(12.dp)
) {
Text(
text = completion.completionDate.split("T")[0],
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.primary
)
completion.rating?.let { rating ->
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
) {
Text(
text = "$rating",
text = completion.completionDate.split("T")[0],
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.tertiary
color = MaterialTheme.colorScheme.primary
)
completion.rating?.let { rating ->
Text(
text = "$rating",
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.tertiary
)
}
}
completion.completedByName?.let {
Text(
text = "By: $it",
style = MaterialTheme.typography.bodySmall
)
}
}
completion.completedByName?.let {
Text(
text = "By: $it",
style = MaterialTheme.typography.bodySmall
)
}
completion.actualCost?.let {
Text(
text = "Cost: $$it",
style = MaterialTheme.typography.bodySmall
)
}
completion.actualCost?.let {
Text(
text = "Cost: $$it",
style = MaterialTheme.typography.bodySmall
)
}
completion.notes?.let {
Spacer(modifier = Modifier.height(4.dp))
Text(
text = it,
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
completion.notes?.let {
Spacer(modifier = Modifier.height(4.dp))
Text(
text = it,
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
}
}
}
}
}
// Complete task button
Spacer(modifier = Modifier.height(8.dp))
Button(
onClick = onCompleteClick,
modifier = Modifier.fillMaxWidth()
) {
Icon(
Icons.Default.CheckCircle,
contentDescription = null,
modifier = Modifier.size(18.dp)
)
Spacer(modifier = Modifier.width(8.dp))
Text("Complete Task")
// Complete task button
Spacer(modifier = Modifier.height(8.dp))
Button(
onClick = onCompleteClick,
modifier = Modifier.fillMaxWidth()
) {
Icon(
Icons.Default.CheckCircle,
contentDescription = null,
modifier = Modifier.size(18.dp)
)
Spacer(modifier = Modifier.width(8.dp))
Text("Complete Task")
}
}
}
}

View File

@@ -21,10 +21,10 @@ fun ResidencesScreen(
onAddResidence: () -> Unit,
viewModel: ResidenceViewModel = viewModel { ResidenceViewModel() }
) {
val residencesState by viewModel.residencesState.collectAsState()
val myResidencesState by viewModel.myResidencesState.collectAsState()
LaunchedEffect(Unit) {
viewModel.loadResidences()
viewModel.loadMyResidences()
}
Scaffold(
@@ -39,7 +39,7 @@ fun ResidencesScreen(
)
}
) { paddingValues ->
when (residencesState) {
when (myResidencesState) {
is ApiResult.Loading -> {
Box(
modifier = Modifier
@@ -59,19 +59,19 @@ fun ResidencesScreen(
) {
Column(horizontalAlignment = androidx.compose.ui.Alignment.CenterHorizontally) {
Text(
text = "Error: ${(residencesState as ApiResult.Error).message}",
text = "Error: ${(myResidencesState as ApiResult.Error).message}",
color = MaterialTheme.colorScheme.error
)
Spacer(modifier = Modifier.height(8.dp))
Button(onClick = { viewModel.loadResidences() }) {
Button(onClick = { viewModel.loadMyResidences() }) {
Text("Retry")
}
}
}
}
is ApiResult.Success -> {
val residences = (residencesState as ApiResult.Success).data
if (residences.isEmpty()) {
val response = (myResidencesState as ApiResult.Success).data
if (response.residences.isEmpty()) {
Box(
modifier = Modifier
.fillMaxSize()
@@ -86,9 +86,92 @@ fun ResidencesScreen(
.fillMaxSize()
.padding(paddingValues),
contentPadding = PaddingValues(16.dp),
verticalArrangement = Arrangement.spacedBy(8.dp)
verticalArrangement = Arrangement.spacedBy(12.dp)
) {
items(residences) { residence ->
// Summary Card
item {
Card(
modifier = Modifier.fillMaxWidth(),
colors = CardDefaults.cardColors(
containerColor = MaterialTheme.colorScheme.primaryContainer
)
) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
) {
Text(
text = "Summary",
style = MaterialTheme.typography.titleMedium,
color = MaterialTheme.colorScheme.onPrimaryContainer
)
Spacer(modifier = Modifier.height(8.dp))
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
) {
Column {
Text(
text = "${response.summary.totalResidences}",
style = MaterialTheme.typography.headlineMedium,
color = MaterialTheme.colorScheme.onPrimaryContainer
)
Text(
text = "Properties",
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onPrimaryContainer
)
}
Column {
Text(
text = "${response.summary.totalTasks}",
style = MaterialTheme.typography.headlineMedium,
color = MaterialTheme.colorScheme.onPrimaryContainer
)
Text(
text = "Total Tasks",
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onPrimaryContainer
)
}
}
Spacer(modifier = Modifier.height(8.dp))
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
) {
Column {
Text(
text = "${response.summary.tasksDueNextWeek}",
style = MaterialTheme.typography.titleLarge,
color = MaterialTheme.colorScheme.onPrimaryContainer
)
Text(
text = "Due This Week",
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onPrimaryContainer
)
}
Column {
Text(
text = "${response.summary.tasksDueNextMonth}",
style = MaterialTheme.typography.titleLarge,
color = MaterialTheme.colorScheme.onPrimaryContainer
)
Text(
text = "Due This Month",
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onPrimaryContainer
)
}
}
}
}
}
// Residences
items(response.residences) { residence ->
Card(
modifier = Modifier
.fillMaxWidth()
@@ -100,7 +183,7 @@ fun ResidencesScreen(
.padding(16.dp)
) {
Text(
text = residence.name ?: "Unnamed Property",
text = residence.name,
style = MaterialTheme.typography.titleMedium
)
Text(
@@ -108,11 +191,33 @@ fun ResidencesScreen(
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
if (residence.propertyType != null) {
Text(
text = residence.propertyType.replaceFirstChar { it.uppercase() },
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.primary
)
// Task Summary
Spacer(modifier = Modifier.height(8.dp))
Divider()
Spacer(modifier = Modifier.height(8.dp))
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
) {
Text(
text = residence.propertyType.replaceFirstChar { it.uppercase() },
text = "Tasks: ${residence.taskSummary.total}",
style = MaterialTheme.typography.bodySmall
)
Text(
text = "Completed: ${residence.taskSummary.completed}",
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.primary
color = MaterialTheme.colorScheme.tertiary
)
Text(
text = "Pending: ${residence.taskSummary.pending}",
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.error
)
}
}