Added comprehensive usage documentation for dynamic task summary components and updated TaskApi to rely on backend's default threshold value. **Changes:** **New: TASK_SUMMARY_USAGE.md** - Complete Android usage guide for TaskSummaryCard component - Examples of basic usage, filtering categories, and customization - Documents all available categories and their metadata - Shows how to use dynamic task summary in different screens **New: iosApp/TASK_SUMMARY_USAGE_IOS.md** - Complete iOS usage guide for TaskSummaryCard SwiftUI component - Examples for ResidenceDetailView, ResidenceCard, and HomeScreen - Documents SF Symbol icon usage and color parsing - Integration examples and troubleshooting tips **New: TaskConstants.kt** - Created client-side constants file (currently unused) - Contains TASK_CURRENT_THRESHOLD_DAYS = 29 - Available for future use if client needs local threshold **Updated: TaskApi.kt** - Changed days parameter from `days: Int = 30` to `days: Int? = null` - Now only sends days parameter to backend if explicitly provided - Allows backend's default threshold (29 days) to be used - Applied to both getTasks() and getTasksByResidence() **Updated: ApiConfig.kt** - Minor configuration update **Benefits:** ✅ Comprehensive documentation for both platforms ✅ Apps now use backend's default threshold value ✅ Cleaner API calls without unnecessary parameters ✅ Client can still override threshold if needed ✅ Documentation includes troubleshooting and best practices 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
260 lines
6.0 KiB
Markdown
260 lines
6.0 KiB
Markdown
# Task Summary Component Usage
|
|
|
|
## Overview
|
|
|
|
The `TaskSummaryCard` component displays task statistics dynamically based on backend data. The backend provides all metadata (icons, colors, display names), making the UI fully data-driven.
|
|
|
|
## Backend Structure
|
|
|
|
The backend returns task summaries in this format:
|
|
|
|
```json
|
|
{
|
|
"total": 25,
|
|
"categories": [
|
|
{
|
|
"name": "overdue_tasks",
|
|
"display_name": "Overdue",
|
|
"icons": {
|
|
"ios": "exclamationmark.triangle",
|
|
"android": "Warning",
|
|
"web": "exclamation-triangle"
|
|
},
|
|
"color": "#FF3B30",
|
|
"count": 3
|
|
},
|
|
{
|
|
"name": "current_tasks",
|
|
"display_name": "Current",
|
|
"icons": {
|
|
"ios": "calendar",
|
|
"android": "CalendarToday",
|
|
"web": "calendar"
|
|
},
|
|
"color": "#007AFF",
|
|
"count": 8
|
|
},
|
|
// ... more categories
|
|
]
|
|
}
|
|
```
|
|
|
|
## Model Classes
|
|
|
|
The app models are defined in `Residence.kt`:
|
|
|
|
```kotlin
|
|
@Serializable
|
|
data class TaskCategoryIcon(
|
|
val ios: String,
|
|
val android: String,
|
|
val web: String
|
|
)
|
|
|
|
@Serializable
|
|
data class TaskCategory(
|
|
val name: String,
|
|
@SerialName("display_name") val displayName: String,
|
|
val icons: TaskCategoryIcon,
|
|
val color: String,
|
|
val count: Int
|
|
)
|
|
|
|
@Serializable
|
|
data class TaskSummary(
|
|
val total: Int,
|
|
val categories: List<TaskCategory>
|
|
)
|
|
```
|
|
|
|
## Usage Examples
|
|
|
|
### Example 1: Show All Categories
|
|
|
|
```kotlin
|
|
@Composable
|
|
fun ResidenceDetailScreen(residence: ResidenceWithTasks) {
|
|
Column {
|
|
// Other residence details...
|
|
|
|
TaskSummaryCard(
|
|
taskSummary = residence.taskSummary
|
|
)
|
|
}
|
|
}
|
|
```
|
|
|
|
### Example 2: Show Only Specific Categories
|
|
|
|
For the main residence view, you might want to show only certain categories:
|
|
|
|
```kotlin
|
|
@Composable
|
|
fun ResidenceCard(residence: ResidenceSummary) {
|
|
Card {
|
|
Column {
|
|
Text(text = residence.name)
|
|
|
|
// Only show overdue, current, and in_progress
|
|
TaskSummaryCard(
|
|
taskSummary = residence.taskSummary,
|
|
visibleCategories = listOf(
|
|
"overdue_tasks",
|
|
"current_tasks",
|
|
"in_progress_tasks"
|
|
)
|
|
)
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Example 3: Custom Styling
|
|
|
|
```kotlin
|
|
TaskSummaryCard(
|
|
taskSummary = residence.taskSummary,
|
|
modifier = Modifier
|
|
.fillMaxWidth()
|
|
.padding(16.dp),
|
|
visibleCategories = listOf("overdue_tasks", "current_tasks")
|
|
)
|
|
```
|
|
|
|
## Available Categories
|
|
|
|
The backend defines these categories (in `task/constants.py`):
|
|
|
|
1. **overdue_tasks** - Red (#FF3B30) - Tasks past their due date
|
|
2. **current_tasks** - Blue (#007AFF) - Tasks due within threshold (29 days)
|
|
3. **in_progress_tasks** - Orange (#FF9500) - Tasks being worked on
|
|
4. **backlog_tasks** - Purple (#5856D6) - Tasks beyond current threshold
|
|
5. **done_tasks** - Green (#34C759) - Completed tasks
|
|
6. **archived_tasks** - Gray (#8E8E93) - Archived tasks
|
|
|
|
## Customization
|
|
|
|
### Filtering Categories
|
|
|
|
Use the `visibleCategories` parameter to control which categories appear:
|
|
|
|
```kotlin
|
|
// Show only active task categories
|
|
TaskSummaryCard(
|
|
taskSummary = taskSummary,
|
|
visibleCategories = listOf(
|
|
"overdue_tasks",
|
|
"current_tasks",
|
|
"in_progress_tasks",
|
|
"backlog_tasks"
|
|
)
|
|
)
|
|
```
|
|
|
|
### Styling
|
|
|
|
The component uses Material Design 3 theming. Customize via modifier:
|
|
|
|
```kotlin
|
|
TaskSummaryCard(
|
|
taskSummary = taskSummary,
|
|
modifier = Modifier
|
|
.padding(horizontal = 16.dp)
|
|
.shadow(4.dp, RoundedCornerShape(12.dp))
|
|
)
|
|
```
|
|
|
|
## iOS Implementation
|
|
|
|
For iOS (SwiftUI), create a similar component:
|
|
|
|
```swift
|
|
struct TaskSummaryCard: View {
|
|
let taskSummary: TaskSummary
|
|
let visibleCategories: [String]?
|
|
|
|
var body: some View {
|
|
VStack(alignment: .leading, spacing: 12) {
|
|
Text("Tasks")
|
|
.font(.headline)
|
|
|
|
ForEach(filteredCategories, id: \.name) { category in
|
|
TaskCategoryRow(category: category)
|
|
}
|
|
}
|
|
.padding()
|
|
.background(Color(.systemBackground))
|
|
.cornerRadius(12)
|
|
.shadow(radius: 2)
|
|
}
|
|
|
|
var filteredCategories: [TaskCategory] {
|
|
if let visible = visibleCategories {
|
|
return taskSummary.categories.filter { visible.contains($0.name) }
|
|
}
|
|
return taskSummary.categories
|
|
}
|
|
}
|
|
|
|
struct TaskCategoryRow: View {
|
|
let category: TaskCategory
|
|
|
|
var body: some View {
|
|
HStack {
|
|
// Use SF Symbol from category.icons.ios
|
|
Image(systemName: category.icons.ios)
|
|
.foregroundColor(Color(hex: category.color))
|
|
|
|
Text(category.displayName)
|
|
.font(.body)
|
|
|
|
Spacer()
|
|
|
|
Text("\(category.count)")
|
|
.font(.headline)
|
|
.foregroundColor(.white)
|
|
.padding(.horizontal, 12)
|
|
.padding(.vertical, 4)
|
|
.background(Color(hex: category.color))
|
|
.cornerRadius(12)
|
|
}
|
|
.padding(12)
|
|
.background(Color(hex: category.color).opacity(0.1))
|
|
.cornerRadius(8)
|
|
}
|
|
}
|
|
```
|
|
|
|
## Benefits
|
|
|
|
✅ **Data-Driven**: All icons, colors, and names come from backend
|
|
✅ **Single Source of Truth**: Change values in `task/constants.py` to update everywhere
|
|
✅ **Flexible**: Easy to show different categories in different screens
|
|
✅ **Consistent**: Same categorization logic across all platforms
|
|
✅ **Maintainable**: No hardcoded UI values in app code
|
|
|
|
## Migration from Old TaskSummary
|
|
|
|
If you have existing code using the old TaskSummary structure:
|
|
|
|
**Old:**
|
|
```kotlin
|
|
Text("Overdue: ${taskSummary.overdue}")
|
|
Text("Pending: ${taskSummary.pending}")
|
|
Text("Completed: ${taskSummary.completed}")
|
|
```
|
|
|
|
**New:**
|
|
```kotlin
|
|
TaskSummaryCard(
|
|
taskSummary = taskSummary,
|
|
visibleCategories = listOf("overdue_tasks", "current_tasks", "done_tasks")
|
|
)
|
|
```
|
|
|
|
Or access categories programmatically:
|
|
```kotlin
|
|
val overdueCount = taskSummary.categories
|
|
.find { it.name == "overdue_tasks" }?.count ?: 0
|
|
```
|