import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import '../about/external/data/Commitment.dart'; import '../about/internal/application/CommitmentClass.dart'; import '../about/internal/application/Standing.dart'; import 'Colors.dart'; /// Formatting and small shared derivations. Anything a screen would otherwise /// inline twice belongs here. /// "Mon 06:00–08:00" — the window, which is the whole point. String formatWindow(Commitment commitment) { if (commitment.dueStart == null || commitment.dueEnd == null) { return "No window set"; } final DateFormat day = DateFormat('EEE'); final DateFormat time = DateFormat('HH:mm'); final String startDay = day.format(commitment.dueStart!); final String startTime = time.format(commitment.dueStart!); final String endTime = time.format(commitment.dueEnd!); final bool sameDay = commitment.dueStart!.day == commitment.dueEnd!.day && commitment.dueStart!.month == commitment.dueEnd!.month; if (sameDay) { return "$startDay $startTime–$endTime"; } return "$startDay $startTime – ${day.format(commitment.dueEnd!)} $endTime"; } String formatDate(DateTime? value) { if (value == null) { return ""; } return DateFormat('d MMM yyyy').format(value); } String formatDateTime(DateTime? value) { if (value == null) { return ""; } return DateFormat('d MMM, HH:mm').format(value); } /// "3h 20m" from raw minutes. String formatMinutes(num minutes) { final int total = minutes.round(); if (total < 60) { return "${total}m"; } final int hours = total ~/ 60; final int remainder = total % 60; if (remainder == 0) { return "${hours}h"; } return "${hours}h ${remainder}m"; } /// "12:04" from raw seconds — for the proof timer and rest clocks. String formatClock(int seconds) { final int safe = seconds < 0 ? 0 : seconds; final int minutes = safe ~/ 60; final int remainder = safe % 60; return "${minutes.toString().padLeft(2, '0')}:${remainder.toString().padLeft(2, '0')}"; } /// Debt is shown to one decimal — precise enough to move visibly when you /// clear something, coarse enough not to look like a lie. String formatDebt(double debt) { return debt.toStringAsFixed(1); } /// "2 days overdue", "Due in 40m", "Window closes in 3h". String overdueLabel(Commitment commitment) { if (commitment.dueEnd == null) { return ""; } final Duration difference = DateTime.now().difference(commitment.dueEnd!); if (difference.isNegative) { final Duration remaining = difference.abs(); if (remaining.inHours < 1) { return "Closes in ${remaining.inMinutes}m"; } if (remaining.inDays < 1) { return "Closes in ${remaining.inHours}h"; } return "Closes in ${remaining.inDays}d"; } if (difference.inHours < 1) { return "${difference.inMinutes}m overdue"; } if (difference.inDays < 1) { return "${difference.inHours}h overdue"; } if (difference.inDays == 1) { return "1 day overdue"; } return "${difference.inDays} days overdue"; } Color standingColor(Standing standing) { switch (standing) { case Standing.Good: return colorStandingGood; case Standing.Warned: return colorStandingWarned; case Standing.Grounded: return colorStandingGrounded; case Standing.Lockdown: return colorStandingLockdown; } } Color standingBackground(Standing standing) { switch (standing) { case Standing.Good: return colorStandingGoodBg; case Standing.Warned: return colorStandingWarnedBg; case Standing.Grounded: return colorStandingGroundedBg; case Standing.Lockdown: return colorStandingLockdownBg; } } Color classColor(CommitmentClass value) { switch (value) { case CommitmentClass.NonNegotiable: return colorClassNonNegotiable; case CommitmentClass.Standard: return colorClassStandard; case CommitmentClass.Elective: return colorClassElective; } } Color classBackground(CommitmentClass value) { switch (value) { case CommitmentClass.NonNegotiable: return colorClassNonNegotiableBg; case CommitmentClass.Standard: return colorClassStandardBg; case CommitmentClass.Elective: return colorClassElectiveBg; } } /// The weekday name for a 1..7 index. String weekdayName(int weekday) { const List names = [ "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday", ]; if (weekday < 1 || weekday > 7) { return ""; } return names[weekday - 1]; } /// "7pm" for an hour-of-day index. String hourLabel(int hour) { if (hour < 0) { return ""; } if (hour == 0) { return "midnight"; } if (hour < 12) { return "${hour}am"; } if (hour == 12) { return "noon"; } return "${hour - 12}pm"; }