Files
timetracker/ios/TimeTracker/TimeTracker/Models/TimeEntry.swift
Simon Franken f42de3353c Fix iOS time display and add timer unit labels
Times were always showing 0 because ISO8601DateFormatter with default
options does not parse fractional seconds, but Prisma/Node.js serialises
dates as "2026-02-20T09:00:00.000Z" (with .000). Every date(from:) call
silently returned nil, so elapsedTime and duration always fell back to 0.

- Date+Extensions: fromISO8601 now tries .withFractionalSeconds first,
  then falls back to whole seconds — single place to maintain
- OngoingTimer.elapsedTime: use Date.fromISO8601() instead of bare formatter
- TimeEntry.duration: use Date.fromISO8601() instead of bare formatters
- TimerView: add TimerUnitLabels view showing h/min/sec column headers
  under the monospaced clock digits
2026-02-20 14:53:30 +01:00

90 lines
2.3 KiB
Swift

import Foundation
struct TimeEntry: Codable, Identifiable, Equatable {
let id: String
let startTime: String
let endTime: String
let description: String?
let projectId: String
let project: ProjectReference
let createdAt: String
let updatedAt: String
var duration: TimeInterval {
guard let start = Date.fromISO8601(startTime),
let end = Date.fromISO8601(endTime) else { return 0 }
return end.timeIntervalSince(start)
}
}
struct ProjectReference: Codable, Equatable {
let id: String
let name: String
let color: String?
let client: ClientReference
}
struct TimeEntryListResponse: Codable {
let entries: [TimeEntry]
let pagination: Pagination
}
struct Pagination: Codable, Equatable {
let page: Int
let limit: Int
let total: Int
let totalPages: Int
}
struct TimeEntryFilters: Codable {
var startDate: String?
var endDate: String?
var projectId: String?
var clientId: String?
var page: Int?
var limit: Int?
init(
startDate: Date? = nil,
endDate: Date? = nil,
projectId: String? = nil,
clientId: String? = nil,
page: Int = 1,
limit: Int = 20
) {
let formatter = ISO8601DateFormatter()
formatter.formatOptions = [.withFullDate]
self.startDate = startDate.map { formatter.string(from: $0) }
self.endDate = endDate.map { formatter.string(from: $0) }
self.projectId = projectId
self.clientId = clientId
self.page = page
self.limit = limit
}
}
struct CreateTimeEntryInput: Codable {
let startTime: String
let endTime: String
let description: String?
let projectId: String
init(startTime: Date, endTime: Date, description: String? = nil, projectId: String) {
let formatter = ISO8601DateFormatter()
formatter.formatOptions = [.withInternetDateTime]
self.startTime = formatter.string(from: startTime)
self.endTime = formatter.string(from: endTime)
self.description = description
self.projectId = projectId
}
}
struct UpdateTimeEntryInput: Codable {
let startTime: String?
let endTime: String?
let description: String?
let projectId: String?
}