TimeRecord Model

Definition

struct TimeRecord: Identifiable, Codable {
    let id: UUID
    var startTime: Date
    var endTime: Date?      // nil = running timer
    var tagId: UUID?        // nil = untagged
    var comment: String?
    var images: [String]    // filenames of attached images
}

JSON Format

{
  "id": "uuid-string",
  "startTime": "2024-01-15T09:30:00Z",
  "endTime": "2024-01-15T11:45:00Z",
  "tagId": "uuid-string",
  "comment": "Working on feature X",
  "images": ["uuid-string_0.jpg", "uuid-string_1.jpg"]
}

Note: The images field is optional in JSON for backward compatibility. Old records without the field will decode with an empty array.

File Naming

YYYY-MM-DD_HHmmss.json based on startTime

Storage Path

records/YYYY/MM/YYYY-MM-DD_HHmmss.json

Business Rules

  • Multiple concurrent running timers allowed
  • Overlapping records are valid
  • tagId is optional (untagged records valid)
  • endTime is optional (nil = running)
  • images array is optional (old records without images field decode with empty array)

Image Storage

Images are stored in the same directory as the JSON record:

  • Path: records/YYYY/MM/ (same as record JSON)
  • Naming: {record-id}_{index}.{ext}
    • Example: 550e8400-e29b-41d4-a716-446655440000_0.jpg
  • Supported formats: JPEG, PNG, HEIF
  • Processing: Resized to max 1920px width/height, compressed to 80% JPEG quality
  • When a record is deleted, all its images are automatically deleted

Related

Data

  • 201-tag - Tag reference for categorization

Services

UI

Reports