Files
honeyDueKMP/iosApp/iosApp/Task/AllTasksView.swift
Trey t e24d1d8559 wip
2025-11-06 09:25:21 -06:00

268 lines
10 KiB
Swift

import SwiftUI
import ComposeApp
struct AllTasksView: View {
@StateObject private var taskViewModel = TaskViewModel()
@State private var tasksResponse: AllTasksResponse?
@State private var isLoadingTasks = false
@State private var tasksError: String?
@State private var showAddTask = false
@State private var showEditTask = false
@State private var selectedTaskForEdit: TaskDetail?
@State private var showInProgressTasks = false
@State private var showDoneTasks = false
@State private var showCompleteTask = false
@State private var selectedTaskForComplete: TaskDetail?
var body: some View {
ZStack {
Color(.systemGroupedBackground)
.ignoresSafeArea()
if isLoadingTasks {
ProgressView()
} else if let error = tasksError {
ErrorView(message: error) {
loadAllTasks()
}
} else if let tasksResponse = tasksResponse {
ScrollView {
VStack(spacing: 16) {
// Header Card
VStack(spacing: 12) {
Image(systemName: "checklist")
.font(.system(size: 48))
.foregroundStyle(.blue.gradient)
Text("All Tasks")
.font(.title)
.fontWeight(.bold)
Text("Tasks across all your properties")
.font(.subheadline)
.foregroundColor(.secondary)
}
.frame(maxWidth: .infinity)
.padding()
.background(Color(.systemBackground))
.cornerRadius(12)
.shadow(color: Color.black.opacity(0.05), radius: 5, x: 0, y: 2)
.padding(.horizontal)
.padding(.top)
// Tasks Section
AllTasksSectionView(
tasksResponse: tasksResponse,
showInProgressTasks: $showInProgressTasks,
showDoneTasks: $showDoneTasks,
onEditTask: { task in
selectedTaskForEdit = task
showEditTask = true
},
onCancelTask: { task in
taskViewModel.cancelTask(id: task.id) { _ in
loadAllTasks()
}
},
onUncancelTask: { task in
taskViewModel.uncancelTask(id: task.id) { _ in
loadAllTasks()
}
},
onMarkInProgress: { task in
taskViewModel.markInProgress(id: task.id) { success in
if success {
loadAllTasks()
}
}
},
onCompleteTask: { task in
selectedTaskForComplete = task
showCompleteTask = true
}
)
.padding(.horizontal)
}
.padding(.bottom)
}
}
}
.navigationTitle("All Tasks")
.navigationBarTitleDisplayMode(.inline)
.sheet(isPresented: $showEditTask) {
if let task = selectedTaskForEdit {
EditTaskView(task: task, isPresented: $showEditTask)
}
}
.sheet(isPresented: $showCompleteTask) {
if let task = selectedTaskForComplete {
CompleteTaskView(task: task, isPresented: $showCompleteTask) {
loadAllTasks()
}
}
}
.onChange(of: showEditTask) { isShowing in
if !isShowing {
loadAllTasks()
}
}
.onAppear {
loadAllTasks()
}
}
private func loadAllTasks() {
guard let token = TokenStorage.shared.getToken() else { return }
isLoadingTasks = true
tasksError = nil
let taskApi = TaskApi(client: ApiClient_iosKt.createHttpClient())
taskApi.getTasks(token: token, days: 30) { result, error in
if let successResult = result as? ApiResultSuccess<AllTasksResponse> {
self.tasksResponse = successResult.data
self.isLoadingTasks = false
} else if let errorResult = result as? ApiResultError {
self.tasksError = errorResult.message
self.isLoadingTasks = false
} else if let error = error {
self.tasksError = error.localizedDescription
self.isLoadingTasks = false
}
}
}
}
struct AllTasksSectionView: View {
let tasksResponse: AllTasksResponse
@Binding var showInProgressTasks: Bool
@Binding var showDoneTasks: Bool
let onEditTask: (TaskDetail) -> Void
let onCancelTask: (TaskDetail) -> Void
let onUncancelTask: (TaskDetail) -> Void
let onMarkInProgress: (TaskDetail) -> Void
let onCompleteTask: (TaskDetail) -> Void
var body: some View {
VStack(alignment: .leading, spacing: 12) {
// Task summary pills
HStack(spacing: 8) {
TaskPill(
count: Int32(tasksResponse.summary.upcoming),
label: "Upcoming",
color: .blue
)
TaskPill(
count: Int32(tasksResponse.summary.inProgress),
label: "In Progress",
color: .orange
)
TaskPill(
count: Int32(tasksResponse.summary.done),
label: "Done",
color: .green
)
}
.padding(.bottom, 4)
// Upcoming tasks
if !tasksResponse.upcomingTasks.isEmpty {
VStack(alignment: .leading, spacing: 8) {
Label("Upcoming (\(tasksResponse.upcomingTasks.count))", systemImage: "calendar")
.font(.headline)
.foregroundColor(.blue)
ForEach(tasksResponse.upcomingTasks, id: \.id) { task in
TaskCard(
task: task,
onEdit: { onEditTask(task) },
onCancel: { onCancelTask(task) },
onUncancel: { onUncancelTask(task) },
onMarkInProgress: { onMarkInProgress(task) },
onComplete: { onCompleteTask(task) }
)
}
}
}
// In Progress section (collapsible)
if !tasksResponse.inProgressTasks.isEmpty {
VStack(alignment: .leading, spacing: 8) {
HStack {
Label("In Progress (\(tasksResponse.inProgressTasks.count))", systemImage: "play.circle")
.font(.headline)
.foregroundColor(.orange)
Spacer()
Image(systemName: showInProgressTasks ? "chevron.up" : "chevron.down")
.foregroundColor(.secondary)
}
.contentShape(Rectangle())
.onTapGesture {
withAnimation {
showInProgressTasks.toggle()
}
}
if showInProgressTasks {
ForEach(tasksResponse.inProgressTasks, id: \.id) { task in
TaskCard(
task: task,
onEdit: { onEditTask(task) },
onCancel: { onCancelTask(task) },
onUncancel: { onUncancelTask(task) },
onMarkInProgress: nil,
onComplete: { onCompleteTask(task) }
)
}
}
}
}
// Done section (collapsible)
if !tasksResponse.doneTasks.isEmpty {
VStack(alignment: .leading, spacing: 8) {
HStack {
Label("Done (\(tasksResponse.doneTasks.count))", systemImage: "checkmark.circle")
.font(.headline)
.foregroundColor(.green)
Spacer()
Image(systemName: showDoneTasks ? "chevron.up" : "chevron.down")
.foregroundColor(.secondary)
}
.contentShape(Rectangle())
.onTapGesture {
withAnimation {
showDoneTasks.toggle()
}
}
if showDoneTasks {
ForEach(tasksResponse.doneTasks, id: \.id) { task in
TaskCard(
task: task,
onEdit: { onEditTask(task) },
onCancel: nil,
onUncancel: nil,
onMarkInProgress: nil,
onComplete: nil
)
}
}
}
}
}
}
}
#Preview {
NavigationView {
AllTasksView()
}
}