import SwiftUI import ComposeApp struct TasksSection: View { let tasksResponse: TaskColumnsResponse let onEditTask: (TaskResponse) -> Void let onCancelTask: (TaskResponse) -> Void let onUncancelTask: (Int32) -> Void let onMarkInProgress: (Int32) -> Void let onCompleteTask: (TaskResponse) -> Void let onArchiveTask: (TaskResponse) -> Void let onUnarchiveTask: (Int32) -> Void private var hasNoTasks: Bool { tasksResponse.columns.allSatisfy { $0.tasks.isEmpty } } var body: some View { VStack(alignment: .leading, spacing: 12) { Text("Tasks") .font(.title2) .fontWeight(.bold) .foregroundColor(Color.appTextPrimary) if hasNoTasks { EmptyTasksView() } else { GeometryReader { geometry in ScrollView(.horizontal, showsIndicators: false) { LazyHStack(spacing: 16) { // Dynamically create columns from response ForEach(Array(tasksResponse.columns.enumerated()), id: \.element.name) { index, column in DynamicTaskColumnView( column: column, onEditTask: { task in onEditTask(task) }, onCancelTask: { task in onCancelTask(task) }, onUncancelTask: { taskId in onUncancelTask(taskId) }, onMarkInProgress: { taskId in onMarkInProgress(taskId) }, onCompleteTask: { task in onCompleteTask(task) }, onArchiveTask: { task in onArchiveTask(task) }, onUnarchiveTask: { taskId in onUnarchiveTask(taskId) } ) .frame(width: geometry.size.width - 48) } } .scrollTargetLayout() .padding(.horizontal, 16) } .scrollTargetBehavior(.viewAligned) } .frame(height: 500) } } } } #Preview { TasksSection( tasksResponse: TaskColumnsResponse( columns: [ TaskColumn( name: "upcoming_tasks", displayName: "Upcoming", buttonTypes: ["edit", "cancel", "uncancel", "mark_in_progress", "complete", "archive"], icons: ["ios": "calendar", "android": "CalendarToday", "web": "calendar"], color: "#007AFF", tasks: [ TaskResponse( id: 1, residenceId: 1, createdById: 1, createdBy: nil, assignedToId: nil, assignedTo: nil, title: "Clean Gutters", description: "Remove all debris", categoryId: 1, category: TaskCategory(id: 1, name: "maintenance", description: "", icon: "", color: "", displayOrder: 0), priorityId: 2, priority: TaskPriority(id: 2, name: "medium", level: 2, color: "", displayOrder: 0), inProgress: false, frequencyId: 1, frequency: TaskFrequency(id: 1, name: "monthly", days: 30, displayOrder: 0), dueDate: "2024-12-15", estimatedCost: 150.00, actualCost: nil, contractorId: nil, isCancelled: false, isArchived: false, parentTaskId: nil, completionCount: 0, kanbanColumn: nil, completions: [], createdAt: "2024-01-01T00:00:00Z", updatedAt: "2024-01-01T00:00:00Z" ) ], count: 1 ), TaskColumn( name: "done_tasks", displayName: "Done", buttonTypes: ["edit", "archive"], icons: ["ios": "checkmark.circle", "android": "CheckCircle", "web": "check-circle"], color: "#34C759", tasks: [ TaskResponse( id: 2, residenceId: 1, createdById: 1, createdBy: nil, assignedToId: nil, assignedTo: nil, title: "Fix Leaky Faucet", description: "Kitchen sink fixed", categoryId: 2, category: TaskCategory(id: 2, name: "plumbing", description: "", icon: "", color: "", displayOrder: 0), priorityId: 3, priority: TaskPriority(id: 3, name: "high", level: 3, color: "", displayOrder: 0), inProgress: false, frequencyId: 6, frequency: TaskFrequency(id: 6, name: "once", days: nil, displayOrder: 0), dueDate: "2024-11-01", estimatedCost: 200.00, actualCost: nil, contractorId: nil, isCancelled: false, isArchived: false, parentTaskId: nil, completionCount: 3, kanbanColumn: nil, completions: [], createdAt: "2024-10-01T00:00:00Z", updatedAt: "2024-11-05T00:00:00Z" ) ], count: 1 ) ], daysThreshold: 30, residenceId: "1", summary: nil ), onEditTask: { _ in }, onCancelTask: { _ in }, onUncancelTask: { _ in }, onMarkInProgress: { _ in }, onCompleteTask: { _ in }, onArchiveTask: { _ in }, onUnarchiveTask: { _ in } ) .padding() }