Dritter Aufgabentyp repotting im Intervall-Modell: optionales repottingIntervalMonths + lastRepotted/By am Pflanzenprofil, Formular mit Intervall-Feld und Datums-Auswahl, Umtopf-Zeile im Detail, Aufgaben in Checkliste und Sammel-Push (reminders.ts gespiegelt), Sitter dürfen bestätigen (Rules-Allowlist). Monats-Arithmetik kürzt den 31. auf den Monatsletzten. Ende-zu-Ende-Widget-Test. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
109 lines
3.6 KiB
Dart
109 lines
3.6 KiB
Dart
import 'package:flutter/foundation.dart';
|
||
|
||
/// Eine Pflanze im Haushalt.
|
||
///
|
||
/// Das Modell ist bewusst haushaltszentriert gedacht: Sobald das
|
||
/// Firebase-Backend angebunden ist, leben Pflanzen unter
|
||
/// `households/{householdId}/plants/{plantId}`.
|
||
@immutable
|
||
class Plant {
|
||
const Plant({
|
||
required this.id,
|
||
required this.nickname,
|
||
required this.species,
|
||
required this.wateringIntervalDays,
|
||
required this.fertilizingIntervalDays,
|
||
this.locationId,
|
||
this.description = '',
|
||
this.careNotes = '',
|
||
this.photoUrl,
|
||
this.lastWatered,
|
||
this.lastFertilized,
|
||
this.lastWateredBy,
|
||
this.lastFertilizedBy,
|
||
this.repottingIntervalMonths,
|
||
this.lastRepotted,
|
||
this.lastRepottedBy,
|
||
});
|
||
|
||
final String id;
|
||
|
||
/// Vom Nutzer vergebener Name, z. B. "Omas Monstera".
|
||
final String nickname;
|
||
|
||
/// Pflanzenart (deutsch und/oder botanisch). Wird später von der
|
||
/// PlantNet-Erkennung befüllt, kann aber auch frei eingegeben werden.
|
||
final String species;
|
||
|
||
/// Referenz auf einen Stellplatz des Haushalts (optional).
|
||
final String? locationId;
|
||
|
||
/// Beschreibung und Pflegehinweise – von der KI erzeugt oder leer.
|
||
final String description;
|
||
final String careNotes;
|
||
|
||
/// Download-URL des Pflanzenfotos in Firebase Storage (optional).
|
||
final String? photoUrl;
|
||
|
||
final int wateringIntervalDays;
|
||
final int fertilizingIntervalDays;
|
||
|
||
/// `null` bedeutet: noch nie erledigt → Aufgabe ist sofort fällig.
|
||
final DateTime? lastWatered;
|
||
final DateTime? lastFertilized;
|
||
|
||
/// Wer zuletzt bestätigt hat (Anzeigename) – für den Haushalt sichtbar.
|
||
final String? lastWateredBy;
|
||
final String? lastFertilizedBy;
|
||
|
||
/// Umtopf-Erinnerung (V3), optional: `null` = keine Erinnerung gewünscht.
|
||
/// Bei gesetztem Intervall und `lastRepotted == null` ist die Aufgabe
|
||
/// sofort fällig (wie bei Gießen/Düngen: „noch nie erledigt").
|
||
final int? repottingIntervalMonths;
|
||
final DateTime? lastRepotted;
|
||
final String? lastRepottedBy;
|
||
|
||
Plant copyWith({
|
||
String? nickname,
|
||
String? species,
|
||
String? Function()? locationId,
|
||
String? description,
|
||
String? careNotes,
|
||
String? photoUrl,
|
||
int? wateringIntervalDays,
|
||
int? fertilizingIntervalDays,
|
||
DateTime? lastWatered,
|
||
DateTime? lastFertilized,
|
||
String? lastWateredBy,
|
||
String? lastFertilizedBy,
|
||
// Als Getter, damit sich die Felder auch auf null zurücksetzen lassen
|
||
// (Intervall entfernen = Erinnerung abschalten).
|
||
int? Function()? repottingIntervalMonths,
|
||
DateTime? Function()? lastRepotted,
|
||
}) {
|
||
return Plant(
|
||
id: id,
|
||
nickname: nickname ?? this.nickname,
|
||
species: species ?? this.species,
|
||
locationId: locationId != null ? locationId() : this.locationId,
|
||
description: description ?? this.description,
|
||
careNotes: careNotes ?? this.careNotes,
|
||
photoUrl: photoUrl ?? this.photoUrl,
|
||
wateringIntervalDays: wateringIntervalDays ?? this.wateringIntervalDays,
|
||
fertilizingIntervalDays:
|
||
fertilizingIntervalDays ?? this.fertilizingIntervalDays,
|
||
lastWatered: lastWatered ?? this.lastWatered,
|
||
lastFertilized: lastFertilized ?? this.lastFertilized,
|
||
lastWateredBy: lastWateredBy ?? this.lastWateredBy,
|
||
lastFertilizedBy: lastFertilizedBy ?? this.lastFertilizedBy,
|
||
repottingIntervalMonths: repottingIntervalMonths != null
|
||
? repottingIntervalMonths()
|
||
: this.repottingIntervalMonths,
|
||
lastRepotted:
|
||
lastRepotted != null ? lastRepotted() : this.lastRepotted,
|
||
// Bewusst nicht per copyWith änderbar — wird nur beim Bestätigen
|
||
// einer Umtopf-Aufgabe direkt in Firestore gesetzt.
|
||
lastRepottedBy: lastRepottedBy,
|
||
);
|
||
}
|
||
}
|