Add centralized DateUtils and enhance contractor detail views
- Add DateUtils.kt for shared Kotlin date formatting with formatDate, formatDateMedium, formatDateTime, formatRelativeDate, and isOverdue - Add DateUtils.swift for iOS with matching date formatting functions - Enhance ContractorDetailScreen (Android) with quick action buttons (call, email, website, directions), clickable contact rows, residence association, statistics section, and metadata - Enhance ContractorDetailView (iOS) with same features, refactored into smaller @ViewBuilder functions to fix Swift compiler type-check timeout - Fix empty string handling in iOS - check !isEmpty in addition to != nil for optional fields like phone, email, website, address - Update various task and document views to use centralized DateUtils 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -16,6 +16,7 @@ import com.example.casera.models.TaskCompletionResponse
|
||||
import com.example.casera.models.TaskCompletion
|
||||
import com.example.casera.network.ApiResult
|
||||
import com.example.casera.network.APILayer
|
||||
import com.example.casera.util.DateUtils
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
/**
|
||||
@@ -259,7 +260,7 @@ private fun CompletionHistoryCard(completion: TaskCompletionResponse) {
|
||||
) {
|
||||
Column {
|
||||
Text(
|
||||
text = formatCompletionDate(completion.completedAt),
|
||||
text = DateUtils.formatDateMedium(completion.completedAt),
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
fontWeight = FontWeight.Bold,
|
||||
color = MaterialTheme.colorScheme.onSurface
|
||||
@@ -377,26 +378,3 @@ private fun CompletionHistoryCard(completion: TaskCompletionResponse) {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun formatCompletionDate(dateString: String): String {
|
||||
// Try to parse and format the date
|
||||
return try {
|
||||
val parts = dateString.split("T")
|
||||
if (parts.isNotEmpty()) {
|
||||
val dateParts = parts[0].split("-")
|
||||
if (dateParts.size == 3) {
|
||||
val year = dateParts[0]
|
||||
val month = dateParts[1].toIntOrNull() ?: 1
|
||||
val day = dateParts[2].toIntOrNull() ?: 1
|
||||
val monthNames = listOf("", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")
|
||||
"${monthNames.getOrElse(month) { "Jan" }} $day, $year"
|
||||
} else {
|
||||
dateString
|
||||
}
|
||||
} else {
|
||||
dateString
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
dateString
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.example.casera.util.DateUtils
|
||||
import org.jetbrains.compose.ui.tooling.preview.Preview
|
||||
|
||||
@Composable
|
||||
@@ -77,7 +78,7 @@ fun SimpleTaskListItem(
|
||||
)
|
||||
if (dueDate != null) {
|
||||
Text(
|
||||
text = "Due: $dueDate",
|
||||
text = "Due: ${DateUtils.formatDate(dueDate)}",
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = if (isOverdue)
|
||||
MaterialTheme.colorScheme.error
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.example.casera.models.TaskPriority
|
||||
import com.example.casera.models.TaskFrequency
|
||||
import com.example.casera.models.TaskStatus
|
||||
import com.example.casera.models.TaskCompletion
|
||||
import com.example.casera.util.DateUtils
|
||||
import org.jetbrains.compose.ui.tooling.preview.Preview
|
||||
|
||||
@Composable
|
||||
@@ -167,7 +168,7 @@ fun TaskCard(
|
||||
tint = MaterialTheme.colorScheme.onSurfaceVariant
|
||||
)
|
||||
Text(
|
||||
text = task.nextScheduledDate ?: task.dueDate ?: "N/A",
|
||||
text = DateUtils.formatDate(task.nextScheduledDate ?: task.dueDate) ?: "N/A",
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user