wip
This commit is contained in:
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user