wip
This commit is contained in:
@@ -11,21 +11,21 @@ struct AllTasksView: View {
|
||||
@State private var showEditTask = false
|
||||
@State private var selectedTaskForEdit: TaskDetail?
|
||||
@State private var selectedTaskForComplete: TaskDetail?
|
||||
|
||||
|
||||
private var hasNoTasks: Bool {
|
||||
guard let response = tasksResponse else { return true }
|
||||
return response.columns.allSatisfy { $0.tasks.isEmpty }
|
||||
}
|
||||
|
||||
|
||||
private var hasTasks: Bool {
|
||||
!hasNoTasks
|
||||
}
|
||||
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
Color(.systemGroupedBackground)
|
||||
.ignoresSafeArea()
|
||||
|
||||
|
||||
if isLoadingTasks {
|
||||
ProgressView()
|
||||
} else if let error = tasksError {
|
||||
@@ -37,20 +37,20 @@ struct AllTasksView: View {
|
||||
// Empty state with big button
|
||||
VStack(spacing: 24) {
|
||||
Spacer()
|
||||
|
||||
|
||||
Image(systemName: "checklist")
|
||||
.font(.system(size: 64))
|
||||
.foregroundStyle(.blue.opacity(0.6))
|
||||
|
||||
|
||||
Text("No tasks yet")
|
||||
.font(.title2)
|
||||
.fontWeight(.semibold)
|
||||
|
||||
|
||||
Text("Create your first task to get started")
|
||||
.font(.body)
|
||||
.foregroundColor(.secondary)
|
||||
.multilineTextAlignment(.center)
|
||||
|
||||
|
||||
Button(action: {
|
||||
showAddTask = true
|
||||
}) {
|
||||
@@ -66,13 +66,13 @@ struct AllTasksView: View {
|
||||
.controlSize(.large)
|
||||
.padding(.horizontal, 48)
|
||||
.disabled(residenceViewModel.myResidences?.residences.isEmpty ?? true)
|
||||
|
||||
|
||||
if residenceViewModel.myResidences?.residences.isEmpty ?? true {
|
||||
Text("Add a property first from the Residences tab")
|
||||
.font(.caption)
|
||||
.foregroundColor(.red)
|
||||
}
|
||||
|
||||
|
||||
Spacer()
|
||||
}
|
||||
.padding()
|
||||
@@ -175,13 +175,13 @@ struct AllTasksView: View {
|
||||
residenceViewModel.loadMyResidences()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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<TaskColumnsResponse> {
|
||||
@@ -208,16 +208,16 @@ struct DynamicTaskColumnView: View {
|
||||
let onCompleteTask: (TaskDetail) -> Void
|
||||
let onArchiveTask: (Int32) -> Void
|
||||
let onUnarchiveTask: (Int32) -> Void
|
||||
|
||||
|
||||
// Get icon from API response, with fallback
|
||||
private var columnIcon: String {
|
||||
column.icons["ios"] ?? "list.bullet"
|
||||
}
|
||||
|
||||
|
||||
private var columnColor: Color {
|
||||
Color(hex: column.color) ?? .primary
|
||||
}
|
||||
|
||||
|
||||
var body: some View {
|
||||
VStack(spacing: 0) {
|
||||
ScrollView {
|
||||
@@ -227,13 +227,13 @@ struct DynamicTaskColumnView: View {
|
||||
Image(systemName: columnIcon)
|
||||
.font(.headline)
|
||||
.foregroundColor(columnColor)
|
||||
|
||||
|
||||
Text(column.displayName)
|
||||
.font(.headline)
|
||||
.foregroundColor(columnColor)
|
||||
|
||||
|
||||
Spacer()
|
||||
|
||||
|
||||
Text("\(column.count)")
|
||||
.font(.caption)
|
||||
.fontWeight(.semibold)
|
||||
@@ -243,13 +243,13 @@ struct DynamicTaskColumnView: View {
|
||||
.background(columnColor)
|
||||
.cornerRadius(12)
|
||||
}
|
||||
|
||||
|
||||
if column.tasks.isEmpty {
|
||||
VStack(spacing: 8) {
|
||||
Image(systemName: columnIcon)
|
||||
.font(.system(size: 40))
|
||||
.foregroundColor(columnColor.opacity(0.3))
|
||||
|
||||
|
||||
Text("No tasks")
|
||||
.font(.caption)
|
||||
.foregroundColor(.secondary)
|
||||
@@ -288,7 +288,7 @@ struct DynamicTaskCard: View {
|
||||
let onComplete: () -> Void
|
||||
let onArchive: () -> Void
|
||||
let onUnarchive: () -> Void
|
||||
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading, spacing: 12) {
|
||||
HStack {
|
||||
@@ -296,39 +296,41 @@ struct DynamicTaskCard: View {
|
||||
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()
|
||||
|
||||
Label(formatDate(task.dueDate), systemImage: "calendar")
|
||||
.font(.caption)
|
||||
.foregroundColor(.secondary)
|
||||
|
||||
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)
|
||||
@@ -337,7 +339,7 @@ struct DynamicTaskCard: View {
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Render buttons based on buttonTypes array
|
||||
VStack(spacing: 8) {
|
||||
ForEach(Array(buttonTypes.enumerated()), id: \.offset) { index, buttonType in
|
||||
@@ -350,7 +352,7 @@ struct DynamicTaskCard: View {
|
||||
.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"
|
||||
@@ -360,7 +362,7 @@ struct DynamicTaskCard: View {
|
||||
}
|
||||
return dateString
|
||||
}
|
||||
|
||||
|
||||
@ViewBuilder
|
||||
private func renderButton(for buttonType: String) -> some View {
|
||||
switch buttonType {
|
||||
@@ -436,7 +438,7 @@ extension View {
|
||||
struct RoundedCorner: Shape {
|
||||
var radius: CGFloat = .infinity
|
||||
var corners: UIRectCorner = .allCorners
|
||||
|
||||
|
||||
func path(in rect: CGRect) -> Path {
|
||||
let path = UIBezierPath(
|
||||
roundedRect: rect,
|
||||
@@ -505,7 +507,7 @@ extension Color {
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
self.init(
|
||||
.sRGB,
|
||||
red: Double(r) / 255,
|
||||
|
||||
Reference in New Issue
Block a user