feat(vacaciones): add vacation range manager screen

Add the Vacaciones manager screen per design ADR-6: an active-range
hero (name, days-remaining countdown, determinate progress bar, and a
per-alarm pause-impact line), a "PROGRAMADOS" upcoming-ranges list, an
"Add range" CTA, and a "Rangos pasados" history section. This is the
real destination WU8's Alarmas-root summary row pushes to, replacing
WU8's own temporary placeholder (_PantallaVacacionesTemporal, now
deleted).

EstadoAlarmas gains 4 pure query methods (rangoVacacionesActivo,
vacacionesProximas, vacacionesPasadas, impactoDeRango) -- read-only
over _alarmas/_vacaciones, no writes, no rescheduling, no native
bridge calls. impactoDeRango mirrors ServicioProgramacionAlarmas's own
pause predicate exactly, so the screen never disagrees with the
scheduler about which alarms are paused. ImpactoVacaciones joins
RangoVacaciones in alarma_musical.dart.

The add-range form (_EditorVacacionesSheet, _PickerButton) moved
verbatim from pantalla_alarmas.dart to its one remaining consumer.
estado_alarmas.dart's scheduling/snooze paths and the ringing screen's
dismiss guard are untouched; both test files pass unmodified.

New ARB keys (en/es only; other 11 locales are WU18's job):
vacationImpact{Paused,Continues}Label, vacationUpcomingSectionTitle,
vacationPastSectionTitle, addVacationRangeCta,
vacationNoActiveRangeHint.
This commit is contained in:
2026-07-29 10:49:51 +02:00
parent a09d614f52
commit 9dfcf0b428
23 changed files with 1432 additions and 390 deletions
+36
View File
@@ -1874,6 +1874,42 @@ abstract class AppLocalizations {
/// **'Próximo rango en {days} días'**
String vacationSummaryUpcomingCountdown(int days);
/// No description provided for @vacationImpactPausedLabel.
///
/// In es, this message translates to:
/// **'Pausa: {times}'**
String vacationImpactPausedLabel(Object times);
/// No description provided for @vacationImpactContinuesLabel.
///
/// In es, this message translates to:
/// **'Sigue sonando: {times}'**
String vacationImpactContinuesLabel(Object times);
/// No description provided for @vacationUpcomingSectionTitle.
///
/// In es, this message translates to:
/// **'PROGRAMADOS'**
String get vacationUpcomingSectionTitle;
/// No description provided for @vacationPastSectionTitle.
///
/// In es, this message translates to:
/// **'Rangos pasados'**
String get vacationPastSectionTitle;
/// No description provided for @addVacationRangeCta.
///
/// In es, this message translates to:
/// **'Añadir rango'**
String get addVacationRangeCta;
/// No description provided for @vacationNoActiveRangeHint.
///
/// In es, this message translates to:
/// **'No hay un rango de vacaciones activo ahora mismo.'**
String get vacationNoActiveRangeHint;
/// No description provided for @vacationsDefaultName.
///
/// In es, this message translates to: