268 lines
10 KiB
Swift
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()
|
|
}
|
|
}
|