Files
multi-chrono-ios/MultiChrono/StopwatchDetailView.swift

149 lines
5.8 KiB
Swift

//
// StopwatchDetailView.swift
// MultiChrono
//
// Created by Beatrice Dellacà on 27/01/26.
//
import SwiftUI
struct StopwatchDetailView: View {
@ObservedObject var stopwatch: Stopwatch
let onSave: (String) -> Void
let onCancel: () -> Void
let onReset: () -> Void
@State private var draftName: String
@State private var isShowingResetAlert = false
private let dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy/MM/dd HH:mm:ss"
return formatter
}()
init(stopwatch: Stopwatch, onSave: @escaping (String) -> Void, onCancel: @escaping () -> Void, onReset: @escaping () -> Void) {
self.stopwatch = stopwatch
self.onSave = onSave
self.onCancel = onCancel
self.onReset = onReset
_draftName = State(initialValue: stopwatch.name)
}
var body: some View {
NavigationStack {
Form {
Section(header: Text("Name")) {
TextField("Enter name...", text: $draftName)
}
Section(header: Text("Laps")) {
if stopwatch.isRunning,
let currentStart = stopwatch.currentRunStartTime,
let currentDuration = stopwatch.currentRunDuration {
VStack(alignment: .leading, spacing: 4) {
HStack {
Text("Lap \(stopwatch.laps.count + 1)")
.font(.headline)
.foregroundStyle(.blue)
Spacer()
Text(Stopwatch.format(interval: currentDuration, format: AppSettings.shared.timeFormat))
.font(.system(.body, design: .monospaced))
.bold()
.foregroundStyle(.blue)
}
HStack {
Text("Current")
.font(.caption)
.foregroundStyle(.blue)
Spacer()
VStack(alignment: .trailing) {
Text(dateFormatter.string(from: currentStart))
Text("Running...")
}
}
.font(.system(.caption, design: .monospaced))
.foregroundStyle(.blue)
}
.padding(.vertical, 2)
}
if stopwatch.laps.isEmpty && !stopwatch.isRunning {
Text("No laps recorded yet.")
.foregroundStyle(.secondary)
} else {
List {
ForEach(stopwatch.laps) { lap in
VStack(alignment: .leading, spacing: 4) {
HStack {
Text("Lap \(lap.number)")
.font(.headline)
Spacer()
Text(Stopwatch.format(interval: lap.duration, format: AppSettings.shared.timeFormat))
.font(.system(.body, design: .monospaced))
.bold()
}
HStack {
Spacer()
VStack(alignment: .trailing) {
Text(dateFormatter.string(from: lap.startTime))
Text(dateFormatter.string(from: lap.endTime))
}
}
.font(.system(.caption, design: .monospaced))
.foregroundStyle(.secondary)
}
.padding(.vertical, 2)
}
}
}
}
Section {
Button(role: .destructive) {
isShowingResetAlert = true
} label: {
HStack {
Spacer()
Text("Reset Stopwatch")
Spacer()
}
}
}
}
.navigationTitle("Edit Stopwatch")
.navigationBarTitleDisplayMode(.inline)
.alert("Are you sure you want to reset the Stopwatch \(stopwatch.name)?", isPresented: $isShowingResetAlert) {
Button("Reset", role: .destructive) {
onReset()
}
Button("Cancel", role: .cancel) {}
}
.toolbar {
ToolbarItem(placement: .cancellationAction) {
Button("Cancel") {
onCancel()
}
}
ToolbarItem(placement: .confirmationAction) {
Button("Save") {
onSave(draftName)
}
.disabled(draftName.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty)
}
}
}
}
}
#Preview {
StopwatchDetailView(
stopwatch: Stopwatch(name: "Test Timer"),
onSave: { _ in },
onCancel: {},
onReset: {}
)
}