Add delete confirmation dialogs for clients, projects, and time entries

- Add confirmation alert when deleting clients with warning about
deleted dependencies (projects and time entries)
- Add confirmation alert when deleting projects with warning about
deleted time entries
- Add confirmation alert when deleting time entries
- All alerts include item name and emphasize action cannot be undone
This commit is contained in:
2026-02-20 15:32:40 +01:00
parent f42de3353c
commit a39f8b07df
3 changed files with 45 additions and 12 deletions

View File

@@ -3,6 +3,8 @@ import SwiftUI
struct ClientsView: View { struct ClientsView: View {
@StateObject private var viewModel = ClientsViewModel() @StateObject private var viewModel = ClientsViewModel()
@State private var showAddClient = false @State private var showAddClient = false
@State private var clientToDelete: Client?
@State private var showDeleteConfirmation = false
var body: some View { var body: some View {
NavigationStack { NavigationStack {
@@ -52,13 +54,22 @@ struct ClientsView: View {
ClientRow(client: client) ClientRow(client: client)
} }
.onDelete { indexSet in .onDelete { indexSet in
Task { if let index = indexSet.first {
for index in indexSet { clientToDelete = viewModel.clients[index]
await viewModel.deleteClient(viewModel.clients[index]) showDeleteConfirmation = true
}
} }
} }
} }
.alert("Delete Client?", isPresented: $showDeleteConfirmation, presenting: clientToDelete) { client in
Button("Cancel", role: .cancel) {}
Button("Delete", role: .destructive) {
Task {
await viewModel.deleteClient(client)
}
}
} message: { client in
Text("This will permanently delete '\(client.name)' and all related projects and time entries. This action cannot be undone.")
}
.refreshable { .refreshable {
await viewModel.loadClients() await viewModel.loadClients()
} }

View File

@@ -3,6 +3,8 @@ import SwiftUI
struct ProjectsView: View { struct ProjectsView: View {
@StateObject private var viewModel = ProjectsViewModel() @StateObject private var viewModel = ProjectsViewModel()
@State private var showAddProject = false @State private var showAddProject = false
@State private var projectToDelete: Project?
@State private var showDeleteConfirmation = false
var body: some View { var body: some View {
NavigationStack { NavigationStack {
@@ -60,13 +62,22 @@ struct ProjectsView: View {
ProjectRow(project: project) ProjectRow(project: project)
} }
.onDelete { indexSet in .onDelete { indexSet in
Task { if let index = indexSet.first {
for index in indexSet { projectToDelete = viewModel.projects[index]
await viewModel.deleteProject(viewModel.projects[index]) showDeleteConfirmation = true
}
} }
} }
} }
.alert("Delete Project?", isPresented: $showDeleteConfirmation, presenting: projectToDelete) { project in
Button("Cancel", role: .cancel) {}
Button("Delete", role: .destructive) {
Task {
await viewModel.deleteProject(project)
}
}
} message: { project in
Text("This will permanently delete '\(project.name)' and all related time entries. This action cannot be undone.")
}
.refreshable { .refreshable {
await viewModel.loadData() await viewModel.loadData()
} }

View File

@@ -3,6 +3,8 @@ import SwiftUI
struct TimeEntriesView: View { struct TimeEntriesView: View {
@StateObject private var viewModel = TimeEntriesViewModel() @StateObject private var viewModel = TimeEntriesViewModel()
@State private var showAddEntry = false @State private var showAddEntry = false
@State private var entryToDelete: TimeEntry?
@State private var showDeleteConfirmation = false
var body: some View { var body: some View {
NavigationStack { NavigationStack {
@@ -50,13 +52,22 @@ struct TimeEntriesView: View {
TimeEntryRow(entry: entry) TimeEntryRow(entry: entry)
} }
.onDelete { indexSet in .onDelete { indexSet in
Task { if let index = indexSet.first {
for index in indexSet { entryToDelete = viewModel.entries[index]
await viewModel.deleteEntry(viewModel.entries[index]) showDeleteConfirmation = true
}
} }
} }
} }
.alert("Delete Time Entry?", isPresented: $showDeleteConfirmation, presenting: entryToDelete) { entry in
Button("Cancel", role: .cancel) {}
Button("Delete", role: .destructive) {
Task {
await viewModel.deleteEntry(entry)
}
}
} message: { entry in
Text("This will permanently delete the time entry for '\(entry.project.name)'. This action cannot be undone.")
}
.refreshable { .refreshable {
await viewModel.loadEntries() await viewModel.loadEntries()
} }