import SwiftUI struct TaskListScreen: View { var businessName: String = "" @EnvironmentObject var appState: AppState @State private var tasks: [WorkTask] = [] @State private var isLoading = true @State private var error: String? @State private var lastRefresh = Date() @State private var selectedTask: WorkTask? @State private var showingMyTasks = false private let refreshTimer = Timer.publish(every: 3, on: .main, in: .common).autoconnect() var body: some View { ZStack(alignment: .bottomTrailing) { Group { if isLoading { LoadingView() } else if let error = error { ErrorView(message: error) { loadTasks() } } else if tasks.isEmpty { emptyView } else { taskListView } } .frame(maxWidth: .infinity, maxHeight: .infinity) Button { showingMyTasks = true } label: { Image(systemName: "checkmark.circle.fill") .font(.title3) .padding(12) .background(Color.payfritGreen) .foregroundColor(.white) .clipShape(Circle()) .shadow(radius: 4) } .padding(.trailing, 16) .padding(.bottom, 16) } .navigationTitle(businessName.isEmpty ? "Available Tasks" : businessName) .toolbar { ToolbarItem(placement: .navigationBarTrailing) { Button { loadTasks() } label: { Image(systemName: "arrow.clockwise") } } ToolbarItem(placement: .navigationBarTrailing) { Menu { Label(appState.userName ?? "Worker", systemImage: "person.circle") .disabled(true) Divider() Button { showingMyTasks = true } label: { Label("My Tasks", systemImage: "checkmark.circle") } Button(role: .destructive) { logout() } label: { Label("Logout", systemImage: "rectangle.portrait.and.arrow.right") } } label: { Image(systemName: "ellipsis.circle") } } } .navigationDestination(isPresented: $showingMyTasks) { MyTasksScreen() } .task { loadTasks() } .onAppear { loadTasks(silent: true) } .onReceive(refreshTimer) { _ in loadTasks(silent: true) } } // MARK: - List private var taskListView: some View { List(tasks) { task in NavigationLink { TaskDetailScreen(task: task, showAcceptButton: true) } label: { taskRow(task) } } .listStyle(.plain) .refreshable { loadTasks() } } private func taskRow(_ task: WorkTask) -> some View { HStack(spacing: 12) { // Left color bar Rectangle() .fill(task.color) .frame(width: 4) .cornerRadius(2) // Task type icon - uses task type color ZStack { RoundedRectangle(cornerRadius: 10) .fill(task.color.opacity(0.15)) .frame(width: 40, height: 40) Image(systemName: task.isChat ? "bubble.left.and.bubble.right.fill" : "doc.text.fill") .foregroundColor(task.color) .font(.subheadline) } VStack(alignment: .leading, spacing: 4) { Text(task.title) .font(.callout.weight(.semibold)) if !task.locationDisplay.isEmpty { HStack(spacing: 4) { Image(systemName: task.deliveryAddress.isEmpty ? "mappin.circle" : "bicycle") .font(.caption2) .foregroundColor(task.color) Text(task.locationDisplay) .font(.caption) .foregroundColor(.secondary) .lineLimit(1) } } else if !task.details.isEmpty { Text(task.details) .font(.caption) .foregroundColor(.secondary) .lineLimit(1) } HStack(spacing: 8) { Text(task.categoryName) .font(.caption2) .fontWeight(.medium) .foregroundColor(task.color) .padding(.horizontal, 6) .padding(.vertical, 2) .background(task.color.opacity(0.2)) .cornerRadius(8) if task.isChat { HStack(spacing: 4) { Image(systemName: "bubble.left.fill") .font(.caption2) Text("Chat") .font(.caption2) .fontWeight(.medium) } .foregroundColor(task.color) .padding(.horizontal, 6) .padding(.vertical, 2) .background(task.color.opacity(0.15)) .cornerRadius(8) } if task.isCash && task.orderTotal > 0 { Text(String(format: "$%.2f", task.orderTotal / 100)) .font(.caption2.bold()) .foregroundColor(.white) .padding(.horizontal, 6) .padding(.vertical, 2) .background(Color(red: 0.13, green: 0.55, blue: 0.13)) .clipShape(Capsule()) } Text(task.timeAgo) .font(.caption2) .foregroundColor(.secondary) } } Spacer() if task.isChat { Image(systemName: "bubble.right.fill") .foregroundColor(task.color) .font(.body) } else { Image(systemName: "chevron.right") .foregroundColor(.secondary) .font(.caption) } } .padding(.vertical, 4) } // MARK: - Empty / Error private var emptyView: some View { VStack(spacing: 16) { Image(systemName: "checkmark.circle") .font(.system(size: 64)) .foregroundColor(.secondary) Text("No pending tasks") .font(.title3) .foregroundColor(.secondary) Text("Check back soon!") .foregroundColor(.secondary) } } // MARK: - Actions private func loadTasks(silent: Bool = false) { if !silent { isLoading = true error = nil } Task { do { let result = try await APIService.shared.listPendingTasks() tasks = result isLoading = false lastRefresh = Date() } catch { if !silent { self.error = error.localizedDescription isLoading = false } } } } private func logout() { Task { await APIService.shared.logout() await AuthStorage.shared.clearAuth() appState.clearAuth() } } }