Files
patrickandClaude Sonnet 5 0b980d73bc feat(mobile): Flutter-App Grundgerüst (Login + Stempeln)
Employee-only App gegen bestehende Backend-API: Login inkl. TOTP-Schritt,
Ein-/Ausstempeln, Pause, Status "heute". Refresh-Token läuft nur als
HttpOnly-Cookie (Backend gibt ihn nie im Body zurück) → persistente
Cookie-Jar statt Secure-Storage-Refresh-Token. android/-Projektordner via
flutter create auf root@192.168.1.236 generiert, INTERNET-Permission
nachgetragen. Ungetestet auf echtem Gerät.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dzdm3EWeNdYFUuXFRJryA1
2026-09-09 22:59:22 +02:00

56 lines
1.5 KiB
Dart

/// Spiegelt backend/app/schemas/time_entry.py::TimeEntryOut.
class TimeEntry {
final String id;
final DateTime date;
final String startTime; // "HH:MM:SS"
final String? endTime;
final int breakMinutes;
final String? breakStart;
final String status; // EntryStatus: open/pending/approved/rejected
final String? note;
final double? workedHours;
TimeEntry({
required this.id,
required this.date,
required this.startTime,
this.endTime,
required this.breakMinutes,
this.breakStart,
required this.status,
this.note,
this.workedHours,
});
bool get isOpen => endTime == null;
bool get isOnBreak => breakStart != null;
factory TimeEntry.fromJson(Map<String, dynamic> json) {
return TimeEntry(
id: json['id'] as String,
date: DateTime.parse(json['date'] as String),
startTime: json['start_time'] as String,
endTime: json['end_time'] as String?,
breakMinutes: json['break_minutes'] as int? ?? 0,
breakStart: json['break_start'] as String?,
status: json['status'] as String,
note: json['note'] as String?,
workedHours: (json['worked_hours'] as num?)?.toDouble(),
);
}
}
class StampResult {
final TimeEntry entry;
final List<String> warnings;
StampResult({required this.entry, required this.warnings});
factory StampResult.fromJson(Map<String, dynamic> json) {
return StampResult(
entry: TimeEntry.fromJson(json['entry'] as Map<String, dynamic>),
warnings: (json['warnings'] as List<dynamic>? ?? []).cast<String>(),
);
}
}