Apply consistent branding colors (BlueGreen, Cerulean, BrightAmber, PrimaryScarlet, cream backgrounds) to all screens, components, buttons, icons, and text throughout the app. Update all Form/List views with proper list row backgrounds to ensure visual consistency with card-based layouts. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
204 lines
5.8 KiB
Swift
204 lines
5.8 KiB
Swift
import SwiftUI
|
|
import ComposeApp
|
|
|
|
// MARK: - Edit Task Button
|
|
struct EditTaskButton: View {
|
|
let taskId: Int32
|
|
let onCompletion: () -> Void
|
|
let onError: (String) -> Void
|
|
|
|
var body: some View {
|
|
Button(action: {
|
|
// Edit navigates to edit screen - handled by parent
|
|
onCompletion()
|
|
}) {
|
|
Label("Edit", systemImage: "pencil")
|
|
.font(.subheadline)
|
|
.frame(maxWidth: .infinity)
|
|
}
|
|
.buttonStyle(.bordered)
|
|
}
|
|
}
|
|
|
|
// MARK: - Cancel Task Button
|
|
struct CancelTaskButton: View {
|
|
let taskId: Int32
|
|
let onCompletion: () -> Void
|
|
let onError: (String) -> Void
|
|
|
|
@StateObject private var viewModel = TaskViewModel()
|
|
@State private var showConfirmation = false
|
|
|
|
var body: some View {
|
|
Button(action: {
|
|
showConfirmation = true
|
|
}) {
|
|
Label("Cancel", systemImage: "xmark.circle")
|
|
.font(.subheadline)
|
|
.frame(maxWidth: .infinity)
|
|
}
|
|
.buttonStyle(.bordered)
|
|
.tint(Color.appError)
|
|
.alert("Cancel Task", isPresented: $showConfirmation) {
|
|
Button("Cancel", role: .cancel) { }
|
|
Button("Cancel Task", role: .destructive) {
|
|
viewModel.cancelTask(id: taskId) { success in
|
|
if success {
|
|
onCompletion()
|
|
} else {
|
|
onError("Failed to cancel task")
|
|
}
|
|
}
|
|
}
|
|
} message: {
|
|
Text("Are you sure you want to cancel this task? This action cannot be undone.")
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - Uncancel (Restore) Task Button
|
|
struct UncancelTaskButton: View {
|
|
let taskId: Int32
|
|
let onCompletion: () -> Void
|
|
let onError: (String) -> Void
|
|
|
|
@StateObject private var viewModel = TaskViewModel()
|
|
|
|
var body: some View {
|
|
Button(action: {
|
|
viewModel.uncancelTask(id: taskId) { success in
|
|
if success {
|
|
onCompletion()
|
|
} else {
|
|
onError("Failed to restore task")
|
|
}
|
|
}
|
|
}) {
|
|
Label("Restore", systemImage: "arrow.uturn.backward")
|
|
.font(.subheadline)
|
|
.frame(maxWidth: .infinity)
|
|
}
|
|
.buttonStyle(.borderedProminent)
|
|
.tint(Color.appPrimary)
|
|
}
|
|
}
|
|
|
|
// MARK: - Mark In Progress Button
|
|
struct MarkInProgressButton: View {
|
|
let taskId: Int32
|
|
let onCompletion: () -> Void
|
|
let onError: (String) -> Void
|
|
|
|
@StateObject private var viewModel = TaskViewModel()
|
|
|
|
var body: some View {
|
|
Button(action: {
|
|
viewModel.markInProgress(id: taskId) { success in
|
|
if success {
|
|
onCompletion()
|
|
} else {
|
|
onError("Failed to mark task in progress")
|
|
}
|
|
}
|
|
}) {
|
|
HStack {
|
|
Image(systemName: "play.circle.fill")
|
|
.resizable()
|
|
.frame(width: 18, height: 18)
|
|
Text("In Progress")
|
|
.font(.subheadline.weight(.semibold))
|
|
}
|
|
.frame(maxWidth: .infinity)
|
|
}
|
|
.buttonStyle(.bordered)
|
|
.tint(Color.appAccent)
|
|
}
|
|
}
|
|
|
|
// MARK: - Complete Task Button
|
|
struct CompleteTaskButton: View {
|
|
let taskId: Int32
|
|
let onCompletion: () -> Void
|
|
let onError: (String) -> Void
|
|
|
|
var body: some View {
|
|
Button(action: {
|
|
// Complete shows dialog - handled by parent
|
|
onCompletion()
|
|
}) {
|
|
HStack {
|
|
Image(systemName: "checkmark.circle.fill")
|
|
.resizable()
|
|
.frame(width: 18, height: 18)
|
|
Text("Complete")
|
|
.font(.subheadline.weight(.semibold))
|
|
}
|
|
.frame(maxWidth: .infinity)
|
|
}
|
|
.buttonStyle(.borderedProminent)
|
|
}
|
|
}
|
|
|
|
// MARK: - Archive Task Button
|
|
struct ArchiveTaskButton: View {
|
|
let taskId: Int32
|
|
let onCompletion: () -> Void
|
|
let onError: (String) -> Void
|
|
|
|
@StateObject private var viewModel = TaskViewModel()
|
|
@State private var showConfirmation = false
|
|
|
|
var body: some View {
|
|
Button(action: {
|
|
showConfirmation = true
|
|
}) {
|
|
Label("Archive", systemImage: "archivebox")
|
|
.font(.subheadline)
|
|
.frame(maxWidth: .infinity)
|
|
}
|
|
.buttonStyle(.bordered)
|
|
.tint(.gray)
|
|
.alert("Archive Task", isPresented: $showConfirmation) {
|
|
Button("Cancel", role: .cancel) { }
|
|
Button("Archive", role: .destructive) {
|
|
viewModel.archiveTask(id: taskId) { success in
|
|
if success {
|
|
onCompletion()
|
|
} else {
|
|
onError("Failed to archive task")
|
|
}
|
|
}
|
|
}
|
|
} message: {
|
|
Text("Are you sure you want to archive this task? You can unarchive it later from archived tasks.")
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - Unarchive Task Button
|
|
struct UnarchiveTaskButton: View {
|
|
let taskId: Int32
|
|
let onCompletion: () -> Void
|
|
let onError: (String) -> Void
|
|
|
|
@StateObject private var viewModel = TaskViewModel()
|
|
|
|
var body: some View {
|
|
Button(action: {
|
|
viewModel.unarchiveTask(id: taskId) { success in
|
|
if success {
|
|
onCompletion()
|
|
} else {
|
|
onError("Failed to unarchive task")
|
|
}
|
|
}
|
|
}) {
|
|
Label("Unarchive", systemImage: "tray.and.arrow.up")
|
|
.font(.subheadline)
|
|
.frame(maxWidth: .infinity)
|
|
}
|
|
.buttonStyle(.bordered)
|
|
.tint(Color.appPrimary)
|
|
}
|
|
}
|