Tagebuch + Heim-Tab mit täglichem Background

Tagebuch (Diary):
- DiaryEntry + DiaryMedia + DiaryCreateBody DTOs
- TagebuchView: Liste der Einträge für aktiven Hund mit Titel, Text,
  Ortsname, Meilenstein-Stern, Foto-Strip
- AddDiaryEntrySheet: Titel/Text/Datum/Meilenstein/Ort/Tags +
  PhotosPicker, nach POST /api/dogs/{id}/diary werden Fotos einzeln
  via POST /api/dogs/{id}/diary/{entry_id}/media hochgeladen (mit
  ImageResize.resizedJPEG)

Heim-Tab als neuer 1. Tab:
- DashboardSnapshot DTO für /api/dogs/{id}/welcome-dashboard
- ActiveDogStore (@Observable + UserDefaults("activeDogId")): hält
  den aktiven Hund app-weit
- HeimView: tägliches Hintergrundfoto aus random_photo.url (rotiert
  pro Tag, vom Backend gewählt), Gradient zur Lesbarkeit, Tagezeit-
  Begrüßung mit User-Namen, Hund-Picker (Menu), Info-Karten für
  letzten Eintrag/nächsten Termin/Gewicht/Eintragszahl,
  Quick-Action-Buttons (Tagebuch, Wetter, Erste Hilfe)

Reorganisation:
- 5 Tabs: Heim, Touren, Aufnehmen, Statistik, Mehr
- Hunde-Liste wandert in Mehr → "Hund & Alltag"
- Tagebuch in Mehr → "Hund & Alltag" + erreichbar von Heim
This commit is contained in:
rene 2026-05-30 12:22:51 +02:00
parent 68b084be97
commit f054b2a07f
8 changed files with 712 additions and 3 deletions

View file

@ -185,6 +185,76 @@ struct LostDogCreateBody: Encodable {
let dogId: Int?
}
// MARK: - Diary (Tagebuch)
struct DiaryEntry: Decodable, Identifiable {
let id: Int
let dogId: Int?
let datum: String?
let typ: String?
let titel: String?
let text: String?
let tags: [String]?
let gpsLat: Double?
let gpsLon: Double?
let locationName: String?
let isMilestone: Bool?
let media: [DiaryMedia]?
let createdAt: String?
}
struct DiaryMedia: Decodable, Identifiable {
let id: Int
let url: String
let mediaType: String?
let imgWidth: Int?
let imgHeight: Int?
}
struct DiaryCreateBody: Encodable {
let datum: String?
let typ: String
let titel: String?
let text: String?
let tags: [String]?
let gpsLat: Double?
let gpsLon: Double?
let locationName: String?
let isMilestone: Bool
}
// MARK: - Welcome Dashboard
struct DashboardSnapshot: Decodable {
let randomPhoto: DashboardPhoto?
let lastDiary: DashboardLastDiary?
let nextAppointment: DashboardNextAppointment?
let lastWeight: DashboardLastWeight?
let diaryCount: Int?
}
struct DashboardPhoto: Decodable {
let url: String
let previewUrl: String?
}
struct DashboardLastDiary: Decodable {
let titel: String?
let datum: String?
}
struct DashboardNextAppointment: Decodable {
let bezeichnung: String?
let naechstes: String?
let typ: String?
}
struct DashboardLastWeight: Decodable {
let wert: Double?
let einheit: String?
let datum: String?
}
// MARK: - Weather
struct WeatherForecast: Decodable {