import 'package:flutter/material.dart'; import '../models/work_day.dart'; /// Kurzcode-Liste & Label const List kAbsenceCodes = ['G', 'K', 'U', 'SU', 'T']; String codeLabel(String code) { switch (code) { case 'G': return 'Gleitzeit'; case 'K': return 'Krankenstand'; case 'U': return 'Urlaub'; case 'SU': return 'Sonderurlaub'; case 'T': return 'Training'; default: return code; } } /// Zeit-Helfer TimeOfDay? parseDbTime(String? hhmmss) { if (hhmmss == null || hhmmss.isEmpty) return null; final parts = hhmmss.split(':'); if (parts.length < 2) return null; final h = int.tryParse(parts[0]) ?? 0; final m = int.tryParse(parts[1]) ?? 0; return TimeOfDay(hour: h, minute: m); } String fmtTimeOfDay(TimeOfDay? t) { if (t == null) return ''; final hh = t.hour.toString().padLeft(2, '0'); final mm = t.minute.toString().padLeft(2, '0'); return '$hh:$mm'; } TimeOfDay? parseTextHHMM(String s) { if (s.length != 5 || s[2] != ':') return null; final h = int.tryParse(s.substring(0, 2)); final m = int.tryParse(s.substring(3, 5)); if (h == null || m == null) return null; if (h < 0 || h > 23 || m < 0 || m > 59) return null; return TimeOfDay(hour: h, minute: m); } String minutesToHHMM(int minutes) { final sign = minutes < 0 ? '-' : ''; final m = minutes.abs(); final hh = (m ~/ 60).toString().padLeft(2, '0'); final mm = (m % 60).toString().padLeft(2, '0'); return '$sign$hh:$mm'; } String minutesToSignedHHMM(int minutes) => minutesToHHMM(minutes); /// Datums-Formatierungen String ymd(DateTime d) => '${d.year.toString().padLeft(4, '0')}-${d.month.toString().padLeft(2, '0')}-${d.day.toString().padLeft(2, '0')}'; const _weekdayShort = ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So']; String _shortWeekday(DateTime d) => _weekdayShort[(d.weekday - 1) % 7]; String _shortDate(DateTime d) => '${d.day.toString().padLeft(2, '0')}.${d.month.toString().padLeft(2, '0')}.'; /// Links in der Tabelle (Tag vor Datum) String rightDayLabel(DateTime d) => '${_shortWeekday(d)} ${_shortDate(d)}'; /// Rechts in der Tabelle (Datum vor Tag) String leftDayLabel(DateTime d) => '${_shortDate(d)} ${_shortWeekday(d)}'; const _monthNames = [ 'Jänner', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember' ]; String monthTitle(DateTime m) => '${_monthNames[m.month - 1]} ${m.year}'; /// Füllt den kompletten Monat mit leeren Tagen, ersetzt vorhandene Einträge List fillMonth(DateTime monthStart, List fromApi) { final m0 = DateTime(monthStart.year, monthStart.month, 1); final m1 = DateTime(monthStart.year, monthStart.month + 1, 1); final byDay = {for (final d in fromApi) ymd(d.date): d}; final days = []; for (DateTime d = m0; d.isBefore(m1); d = d.add(const Duration(days: 1))) { final k = ymd(d); if (byDay.containsKey(k)) { final v = byDay[k]!; days.add(WorkDay( date: d, intervals: v.intervals, targetMinutes: v.targetMinutes, code: v.code, )); } else { days.add(WorkDay(date: d, intervals: const [], targetMinutes: 0, code: null)); } } return days; }