Files
honeyDueKMP/iosApp/iosApp/Subviews/Task/TaskCard.swift
Trey t 7dce211681 wip
2025-11-08 16:02:01 -06:00

199 lines
7.2 KiB
Swift

import SwiftUI
import ComposeApp
struct TaskCard: View {
let task: TaskDetail
let onEdit: () -> Void
let onCancel: (() -> Void)?
let onUncancel: (() -> Void)?
let onMarkInProgress: (() -> Void)?
let onComplete: (() -> Void)?
let onArchive: (() -> Void)?
let onUnarchive: (() -> Void)?
var body: some View {
VStack(alignment: .leading, spacing: 12) {
HStack {
VStack(alignment: .leading, spacing: 4) {
Text(task.title)
.font(.headline)
.foregroundColor(.primary)
if let status = task.status {
StatusBadge(status: status.name)
}
}
Spacer()
PriorityBadge(priority: task.priority.name)
}
if let description = task.description_, !description.isEmpty {
Text(description)
.font(.subheadline)
.foregroundColor(.secondary)
.lineLimit(2)
}
HStack {
Label(task.frequency.displayName, systemImage: "repeat")
.font(.caption)
.foregroundColor(.secondary)
Spacer()
if let due_date = task.dueDate {
Label(formatDate(due_date), systemImage: "calendar")
.font(.caption)
.foregroundColor(.secondary)
}
}
if task.completions.count > 0 {
Divider()
HStack {
Image(systemName: "checkmark.circle")
.foregroundColor(.green)
Text("Completed \(task.completions.count) time\(task.completions.count == 1 ? "" : "s")")
.font(.caption)
.foregroundColor(.secondary)
}
}
if task.showCompletedButton {
VStack(spacing: 8) {
if let onMarkInProgress = onMarkInProgress, task.status?.name != "in_progress" {
Button(action: onMarkInProgress) {
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(.orange)
}
if task.showCompletedButton, let onComplete = onComplete {
Button(action: onComplete) {
HStack {
Image(systemName: "checkmark.circle.fill")
.resizable()
.frame(width: 18, height: 18)
Text("Complete")
.font(.subheadline.weight(.semibold))
}
.frame(maxWidth: .infinity)
}
.buttonStyle(.borderedProminent)
}
}
}
VStack(spacing: 8) {
Button(action: onEdit) {
Label("Edit", systemImage: "pencil")
.font(.subheadline)
.frame(maxWidth: .infinity)
}
.buttonStyle(.bordered)
if let onCancel = onCancel {
Button(action: onCancel) {
Label("Cancel", systemImage: "xmark.circle")
.font(.subheadline)
.frame(maxWidth: .infinity)
}
.buttonStyle(.bordered)
.tint(.red)
} else if let onUncancel = onUncancel {
Button(action: onUncancel) {
Label("Restore", systemImage: "arrow.uturn.backward")
.font(.subheadline)
.frame(maxWidth: .infinity)
}
.buttonStyle(.borderedProminent)
.tint(.blue)
}
if task.archived {
if let onUnarchive = onUnarchive {
Button(action: onUnarchive) {
Label("Unarchive", systemImage: "tray.and.arrow.up")
.font(.subheadline)
.frame(maxWidth: .infinity)
}
.buttonStyle(.bordered)
.tint(.blue)
}
} else {
if let onArchive = onArchive {
Button(action: onArchive) {
Label("Archive", systemImage: "archivebox")
.font(.subheadline)
.frame(maxWidth: .infinity)
}
.buttonStyle(.bordered)
.tint(.gray)
}
}
}
}
.padding(16)
.background(Color(.systemBackground))
.cornerRadius(12)
.shadow(color: Color.black.opacity(0.05), radius: 3, x: 0, y: 2)
}
private func formatDate(_ dateString: String) -> String {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
if let date = formatter.date(from: dateString) {
formatter.dateStyle = .medium
return formatter.string(from: date)
}
return dateString
}
}
#Preview {
VStack(spacing: 16) {
TaskCard(
task: TaskDetail(
id: 1,
residence: 1,
title: "Clean Gutters",
description: "Remove all debris from gutters",
category: TaskCategory(id: 1, name: "maintenance", description: ""),
priority: TaskPriority(id: 2, name: "medium", displayName: "", description: ""),
frequency: TaskFrequency(id: 1, name: "monthly", lookupName: "", displayName: "30", daySpan: 0, notifyDays: 0),
status: TaskStatus(id: 1, name: "pending", displayName: "", description: ""),
dueDate: "2024-12-15",
estimatedCost: "150.00",
actualCost: nil,
notes: nil,
archived: false,
createdAt: "2024-01-01T00:00:00Z",
updatedAt: "2024-01-01T00:00:00Z",
nextScheduledDate: nil,
showCompletedButton: true,
completions: []
),
onEdit: {},
onCancel: {},
onUncancel: nil,
onMarkInProgress: {},
onComplete: {},
onArchive: {},
onUnarchive: {}
)
}
.padding()
.background(Color(.systemGroupedBackground))
}