fix(vacaciones): replace the progress bar with the prototype's date pair
Item 21 / audit 9b.4-9b.5 (t4:451-462, 469-479): the active vacation range showed a LinearProgressIndicator the prototype never draws. Replace it with the screen's real signature element -- a start/end date pair (day+month, weekday, connector rule) -- reused with a flat connector for the "programados"/"pasados" rows, replacing their plain ListTiles with proper cards.
This commit is contained in:
@@ -11,3 +11,14 @@ import 'package:intl/intl.dart';
|
|||||||
/// this safely.
|
/// this safely.
|
||||||
String fechaCortaLocalizada(String localeTag, DateTime fecha) =>
|
String fechaCortaLocalizada(String localeTag, DateTime fecha) =>
|
||||||
DateFormat.yMd(localeTag).format(fecha);
|
DateFormat.yMd(localeTag).format(fecha);
|
||||||
|
|
||||||
|
/// Day + abbreviated month, locale-aware (e.g. "28 jul" for `es`, "Jul 28"
|
||||||
|
/// for `en`) — item 21 / audit 9b.4 (t4:459), the big digit half of the
|
||||||
|
/// vacation screen's date-pair.
|
||||||
|
String diaMesLocalizado(String localeTag, DateTime fecha) =>
|
||||||
|
DateFormat.MMMd(localeTag).format(fecha);
|
||||||
|
|
||||||
|
/// Full weekday name, locale-aware (e.g. "lunes"/"Monday") — item 21 /
|
||||||
|
/// audit 9b.4 (t4:459), the small caption under the day-month.
|
||||||
|
String nombreDiaSemanaLocalizado(String localeTag, DateTime fecha) =>
|
||||||
|
DateFormat.EEEE(localeTag).format(fecha);
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import '../l10n/formato_fechas.dart';
|
|||||||
import '../l10n/gen/app_localizations.dart';
|
import '../l10n/gen/app_localizations.dart';
|
||||||
import '../modelos/alarma_musical.dart';
|
import '../modelos/alarma_musical.dart';
|
||||||
import '../tema/pluriwave_theme.dart';
|
import '../tema/pluriwave_theme.dart';
|
||||||
|
import '../tema/pluriwave_tokens.dart';
|
||||||
import '../widgets/pluri_glass_surface.dart';
|
import '../widgets/pluri_glass_surface.dart';
|
||||||
import '../widgets/pluri_layout.dart';
|
import '../widgets/pluri_layout.dart';
|
||||||
import '../widgets/pluri_push_scaffold.dart';
|
import '../widgets/pluri_push_scaffold.dart';
|
||||||
@@ -68,7 +69,8 @@ class PantallaVacaciones extends StatelessWidget {
|
|||||||
|
|
||||||
/// Active-range hero: name, days-remaining countdown (reusing WU8's own
|
/// Active-range hero: name, days-remaining countdown (reusing WU8's own
|
||||||
/// `vacationSummaryActiveCountdown` string — same concept, bigger stage),
|
/// `vacationSummaryActiveCountdown` string — same concept, bigger stage),
|
||||||
/// a determinate progress bar, and the per-alarm impact line(s) from
|
/// a start/end date pair (item 21 / audit 9b.4, replacing the former
|
||||||
|
/// determinate progress bar), and the per-alarm impact line(s) from
|
||||||
/// `EstadoAlarmas.impactoDeRango`.
|
/// `EstadoAlarmas.impactoDeRango`.
|
||||||
class _HeroRangoActivo extends StatelessWidget {
|
class _HeroRangoActivo extends StatelessWidget {
|
||||||
const _HeroRangoActivo({required this.estado, required this.rango});
|
const _HeroRangoActivo({required this.estado, required this.rango});
|
||||||
@@ -83,6 +85,7 @@ class _HeroRangoActivo extends StatelessWidget {
|
|||||||
final hoyDia = DateTime(hoy.year, hoy.month, hoy.day);
|
final hoyDia = DateTime(hoy.year, hoy.month, hoy.day);
|
||||||
final diasRestantes = rango.finDia.difference(hoyDia).inDays;
|
final diasRestantes = rango.finDia.difference(hoyDia).inDays;
|
||||||
final impacto = estado.impactoDeRango(rango);
|
final impacto = estado.impactoDeRango(rango);
|
||||||
|
final type = context.pluriType;
|
||||||
|
|
||||||
return PluriGlassSurface(
|
return PluriGlassSurface(
|
||||||
glowColor: context.pluriTokens.electricMagenta.withValues(alpha: 0.24),
|
glowColor: context.pluriTokens.electricMagenta.withValues(alpha: 0.24),
|
||||||
@@ -96,14 +99,24 @@ class _HeroRangoActivo extends StatelessWidget {
|
|||||||
).textTheme.titleLarge?.copyWith(fontWeight: FontWeight.w900),
|
).textTheme.titleLarge?.copyWith(fontWeight: FontWeight.w900),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 4),
|
const SizedBox(height: 4),
|
||||||
Text(l10n.vacationSummaryActiveCountdown(diasRestantes)),
|
// Item 21 / audit 9b.4 (t4:454): the "active now" caption is a
|
||||||
const SizedBox(height: 10),
|
// teal eyebrow, not default body text.
|
||||||
ClipRRect(
|
Text(
|
||||||
borderRadius: BorderRadius.circular(999),
|
l10n.vacationSummaryActiveCountdown(diasRestantes),
|
||||||
child: LinearProgressIndicator(value: _progreso(hoyDia)),
|
style: type.eyebrowLabel.copyWith(color: PluriWaveTokens.brand),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
// Item 21 / audit 9b.4 (t4:451-462): the screen's signature
|
||||||
|
// element is a start/end date pair joined by a gradient rule —
|
||||||
|
// the prototype never draws a determinate progress bar here.
|
||||||
|
_ParFechasVacaciones(
|
||||||
|
inicio: rango.inicioDia,
|
||||||
|
fin: rango.finDia,
|
||||||
|
destacado: true,
|
||||||
|
reglaKey: const ValueKey('vacaciones-regla-activo'),
|
||||||
),
|
),
|
||||||
if (impacto.pausadas.isNotEmpty) ...[
|
if (impacto.pausadas.isNotEmpty) ...[
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 12),
|
||||||
Text(l10n.vacationImpactPausedLabel(_horas(impacto.pausadas))),
|
Text(l10n.vacationImpactPausedLabel(_horas(impacto.pausadas))),
|
||||||
],
|
],
|
||||||
if (impacto.noAfectadas.isNotEmpty) ...[
|
if (impacto.noAfectadas.isNotEmpty) ...[
|
||||||
@@ -117,13 +130,6 @@ class _HeroRangoActivo extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
double _progreso(DateTime hoyDia) {
|
|
||||||
final totalDias = rango.finDia.difference(rango.inicioDia).inDays + 1;
|
|
||||||
if (totalDias <= 0) return 0;
|
|
||||||
final transcurridos = hoyDia.difference(rango.inicioDia).inDays + 1;
|
|
||||||
return (transcurridos / totalDias).clamp(0.0, 1.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
String _horas(List<AlarmaMusical> alarmas) => alarmas
|
String _horas(List<AlarmaMusical> alarmas) => alarmas
|
||||||
.map(
|
.map(
|
||||||
(a) =>
|
(a) =>
|
||||||
@@ -148,12 +154,29 @@ class _SeccionProgramados extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
Text(l10n.vacationUpcomingSectionTitle, style: type.eyebrowLabel),
|
Text(l10n.vacationUpcomingSectionTitle, style: type.eyebrowLabel),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
|
// Item 21 / audit 9b.5 (t4:469-479, gap:10 at t4:468): a date-pair
|
||||||
|
// card per row, not a ListTile — the same connector widget the
|
||||||
|
// active hero uses, just not `destacado`.
|
||||||
|
PluriPanelColumn(
|
||||||
|
gap: 10,
|
||||||
|
children: [
|
||||||
for (final rango in proximas)
|
for (final rango in proximas)
|
||||||
ListTile(
|
_TarjetaRangoVacaciones(
|
||||||
contentPadding: EdgeInsets.zero,
|
rango: rango,
|
||||||
leading: const Icon(Icons.event_rounded),
|
// Reuses the existing "Next range in {days} days" string
|
||||||
title: Text(localizedVacationName(l10n, rango.nombre)),
|
// (already shipped, already translated) as the header
|
||||||
subtitle: Text(_rangoFechas(l10n, rango)),
|
// eyebrow — the prototype's own header text ("EMPIEZA EN
|
||||||
|
// 1 DIA - 15 DIAS") pairs a start countdown with a
|
||||||
|
// duration count; only the countdown half has a
|
||||||
|
// corresponding ARB string today, so that's the honest
|
||||||
|
// subset delivered here.
|
||||||
|
encabezado: l10n.vacationSummaryUpcomingCountdown(
|
||||||
|
rango.inicioDia
|
||||||
|
.difference(DateTime.now().dateOnly())
|
||||||
|
.inDays,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -177,12 +200,14 @@ class _SeccionRangosPasados extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
Text(l10n.vacationPastSectionTitle, style: type.eyebrowLabel),
|
Text(l10n.vacationPastSectionTitle, style: type.eyebrowLabel),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
|
// No prototype-specified header text exists for an already-ended
|
||||||
|
// range, so `encabezado` is omitted rather than invented.
|
||||||
|
PluriPanelColumn(
|
||||||
|
gap: 10,
|
||||||
|
children: [
|
||||||
for (final rango in pasadas)
|
for (final rango in pasadas)
|
||||||
ListTile(
|
_TarjetaRangoVacaciones(rango: rango),
|
||||||
contentPadding: EdgeInsets.zero,
|
],
|
||||||
leading: const Icon(Icons.history_rounded),
|
|
||||||
title: Text(localizedVacationName(l10n, rango.nombre)),
|
|
||||||
subtitle: Text(_rangoFechas(l10n, rango)),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -190,9 +215,182 @@ class _SeccionRangosPasados extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String _rangoFechas(AppLocalizations l10n, RangoVacaciones rango) =>
|
extension _SoloFecha on DateTime {
|
||||||
'${fechaCortaLocalizada(l10n.localeName, rango.inicioDia)} → '
|
DateTime dateOnly() => DateTime(year, month, day);
|
||||||
'${fechaCortaLocalizada(l10n.localeName, rango.finDia)}';
|
}
|
||||||
|
|
||||||
|
/// Item 21 / audit 9b.5 (t4:469-479): the shared card for both "programados"
|
||||||
|
/// and "pasados" rows — radius 20, opaque `listSurface`, the same date-pair
|
||||||
|
/// connector the active hero uses (flat, not gradient), and a label row
|
||||||
|
/// (icon + range name) matching the prototype's "Verano"/"Puente" caption
|
||||||
|
/// (t4:478).
|
||||||
|
class _TarjetaRangoVacaciones extends StatelessWidget {
|
||||||
|
const _TarjetaRangoVacaciones({required this.rango, this.encabezado});
|
||||||
|
|
||||||
|
final RangoVacaciones rango;
|
||||||
|
final String? encabezado;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final l10n = AppLocalizations.of(context);
|
||||||
|
final t = context.pluriTokens;
|
||||||
|
final type = context.pluriType;
|
||||||
|
return DecoratedBox(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: t.listSurface,
|
||||||
|
borderRadius: BorderRadius.circular(20),
|
||||||
|
border: Border.all(color: Colors.white.withValues(alpha: 0.08)),
|
||||||
|
),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 15),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
if (encabezado != null) ...[
|
||||||
|
Text(
|
||||||
|
encabezado!,
|
||||||
|
style: type.eyebrowLabel.copyWith(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.onSurface.withValues(alpha: 0.5),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 11),
|
||||||
|
],
|
||||||
|
_ParFechasVacaciones(
|
||||||
|
inicio: rango.inicioDia,
|
||||||
|
fin: rango.finDia,
|
||||||
|
destacado: false,
|
||||||
|
reglaKey: ValueKey('vacaciones-regla-${rango.id}'),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
Icons.label_outline_rounded,
|
||||||
|
size: 17,
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.onSurface.withValues(alpha: 0.6),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
localizedVacationName(l10n, rango.nombre),
|
||||||
|
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.onSurface.withValues(alpha: 0.6),
|
||||||
|
),
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Item 21 / audit 9b.4 + 9b.5 (t4:459-461, 473-475): a start/end date pair
|
||||||
|
/// joined by a connector rule — the vacation screen's one recurring motif,
|
||||||
|
/// shared by the active hero (`destacado: true`, brand-teal gradient rule)
|
||||||
|
/// and every scheduled/past row (`destacado: false`, flat translucent rule).
|
||||||
|
class _ParFechasVacaciones extends StatelessWidget {
|
||||||
|
const _ParFechasVacaciones({
|
||||||
|
required this.inicio,
|
||||||
|
required this.fin,
|
||||||
|
required this.destacado,
|
||||||
|
required this.reglaKey,
|
||||||
|
});
|
||||||
|
|
||||||
|
final DateTime inicio;
|
||||||
|
final DateTime fin;
|
||||||
|
final bool destacado;
|
||||||
|
final Key reglaKey;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final locale = AppLocalizations.of(context).localeName;
|
||||||
|
return Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
_BloqueFecha(fecha: inicio, locale: locale, alinearDerecha: false),
|
||||||
|
const SizedBox(width: 12),
|
||||||
|
Expanded(
|
||||||
|
child: DecoratedBox(
|
||||||
|
key: reglaKey,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(1),
|
||||||
|
gradient:
|
||||||
|
destacado
|
||||||
|
? LinearGradient(
|
||||||
|
colors: [
|
||||||
|
PluriWaveTokens.brand,
|
||||||
|
PluriWaveTokens.brand.withValues(alpha: 0.3),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
color: destacado ? null : Colors.white.withValues(alpha: 0.14),
|
||||||
|
),
|
||||||
|
child: const SizedBox(height: 2),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 12),
|
||||||
|
_BloqueFecha(fecha: fin, locale: locale, alinearDerecha: true),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _BloqueFecha extends StatelessWidget {
|
||||||
|
const _BloqueFecha({
|
||||||
|
required this.fecha,
|
||||||
|
required this.locale,
|
||||||
|
required this.alinearDerecha,
|
||||||
|
});
|
||||||
|
|
||||||
|
final DateTime fecha;
|
||||||
|
final String locale;
|
||||||
|
final bool alinearDerecha;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment:
|
||||||
|
alinearDerecha ? CrossAxisAlignment.end : CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
// t4:459: 26px/w800/ls-1/lh1.
|
||||||
|
Text(
|
||||||
|
diaMesLocalizado(locale, fecha),
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 26,
|
||||||
|
fontWeight: FontWeight.w800,
|
||||||
|
letterSpacing: -1,
|
||||||
|
height: 1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 2),
|
||||||
|
// t4:459: 11px/w700/rgba(242,247,250,.5).
|
||||||
|
Text(
|
||||||
|
nombreDiaSemanaLocalizado(locale, fecha),
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 11,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.onSurface.withValues(alpha: 0.5),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Add-range form. Moved verbatim from `pantalla_alarmas.dart` (WU8's
|
/// Add-range form. Moved verbatim from `pantalla_alarmas.dart` (WU8's
|
||||||
/// `_PantallaVacacionesTemporal` used it as a placeholder push target; now
|
/// `_PantallaVacacionesTemporal` used it as a placeholder push target; now
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:pluriwave/estado/estado_alarmas.dart';
|
import 'package:pluriwave/estado/estado_alarmas.dart';
|
||||||
|
import 'package:pluriwave/l10n/formato_fechas.dart';
|
||||||
import 'package:pluriwave/l10n/gen/app_localizations.dart';
|
import 'package:pluriwave/l10n/gen/app_localizations.dart';
|
||||||
import 'package:pluriwave/modelos/alarma_musical.dart';
|
import 'package:pluriwave/modelos/alarma_musical.dart';
|
||||||
import 'package:pluriwave/pantallas/pantalla_vacaciones.dart';
|
import 'package:pluriwave/pantallas/pantalla_vacaciones.dart';
|
||||||
@@ -221,4 +222,125 @@ void main() {
|
|||||||
|
|
||||||
expect(find.text(l10n.newVacationRangeTitle), findsOneWidget);
|
expect(find.text(l10n.newVacationRangeTitle), findsOneWidget);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Item 21 / audit 9b.4-9b.5 (t4:451-462, 469-479): the screen's signature
|
||||||
|
// element is a start/end date pair, never a determinate progress bar.
|
||||||
|
testWidgets(
|
||||||
|
'el rango activo muestra el par de fechas, no una barra de progreso',
|
||||||
|
(tester) async {
|
||||||
|
final inicio = _hoyDia.subtract(const Duration(days: 3));
|
||||||
|
final fin = _hoyDia.add(const Duration(days: 5));
|
||||||
|
final estado = await _crearEstado(
|
||||||
|
vacaciones: [
|
||||||
|
RangoVacaciones(
|
||||||
|
id: 'v1',
|
||||||
|
nombre: 'Julio activo',
|
||||||
|
inicio: inicio,
|
||||||
|
fin: fin,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
addTearDown(estado.dispose);
|
||||||
|
|
||||||
|
await tester.pumpWidget(_buildScreen(estado));
|
||||||
|
await _pumpEstable(tester);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
find.byType(LinearProgressIndicator),
|
||||||
|
findsNothing,
|
||||||
|
reason:
|
||||||
|
't4:451-462 replaces the progress bar with a start/end date '
|
||||||
|
'pair — the screen\'s signature element',
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(find.text(diaMesLocalizado('es', inicio)), findsOneWidget);
|
||||||
|
expect(find.text(diaMesLocalizado('es', fin)), findsOneWidget);
|
||||||
|
expect(
|
||||||
|
find.text(nombreDiaSemanaLocalizado('es', inicio)),
|
||||||
|
findsOneWidget,
|
||||||
|
);
|
||||||
|
expect(find.text(nombreDiaSemanaLocalizado('es', fin)), findsOneWidget);
|
||||||
|
|
||||||
|
final fechaTexto = tester.widget<Text>(
|
||||||
|
find.text(diaMesLocalizado('es', inicio)),
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
fechaTexto.style?.fontSize,
|
||||||
|
26,
|
||||||
|
reason: 't4:459 the date digits are 26px/w800/ls-1',
|
||||||
|
);
|
||||||
|
expect(fechaTexto.style?.fontWeight, FontWeight.w800);
|
||||||
|
|
||||||
|
final diaSemanaTexto = tester.widget<Text>(
|
||||||
|
find.text(nombreDiaSemanaLocalizado('es', inicio)),
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
diaSemanaTexto.style?.fontSize,
|
||||||
|
11,
|
||||||
|
reason: 't4:459 the weekday caption is 11px/w700/50%',
|
||||||
|
);
|
||||||
|
expect(diaSemanaTexto.style?.fontWeight, FontWeight.w700);
|
||||||
|
|
||||||
|
final regla = tester.widget<DecoratedBox>(
|
||||||
|
find.byKey(const ValueKey('vacaciones-regla-activo')),
|
||||||
|
);
|
||||||
|
final decoration = regla.decoration as BoxDecoration;
|
||||||
|
expect(
|
||||||
|
decoration.gradient,
|
||||||
|
isNotNull,
|
||||||
|
reason:
|
||||||
|
't4:460 the active range connector is a brand-teal gradient, '
|
||||||
|
'not the flat rgba(255,255,255,.14) used by scheduled rows',
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
testWidgets(
|
||||||
|
'un rango programado usa el mismo par de fechas, con una regla plana y '
|
||||||
|
'una fila de etiqueta con el nombre del rango',
|
||||||
|
(tester) async {
|
||||||
|
final inicio = _hoyDia.add(const Duration(days: 20));
|
||||||
|
final fin = _hoyDia.add(const Duration(days: 25));
|
||||||
|
final estado = await _crearEstado(
|
||||||
|
vacaciones: [
|
||||||
|
RangoVacaciones(id: 'f2', nombre: 'Verano', inicio: inicio, fin: fin),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
addTearDown(estado.dispose);
|
||||||
|
|
||||||
|
await tester.pumpWidget(_buildScreen(estado));
|
||||||
|
await _pumpEstable(tester);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
find.descendant(
|
||||||
|
of: find.byType(PantallaVacaciones),
|
||||||
|
matching: find.byType(ListTile),
|
||||||
|
),
|
||||||
|
findsNothing,
|
||||||
|
reason: '9b.5 (t4:469-479) replaces the ListTile row with a card',
|
||||||
|
);
|
||||||
|
expect(find.text(diaMesLocalizado('es', inicio)), findsOneWidget);
|
||||||
|
expect(find.text(diaMesLocalizado('es', fin)), findsOneWidget);
|
||||||
|
expect(
|
||||||
|
find.text('Verano'),
|
||||||
|
findsOneWidget,
|
||||||
|
reason:
|
||||||
|
't4:478 the label row shows the range name next to a '
|
||||||
|
'"label" icon',
|
||||||
|
);
|
||||||
|
|
||||||
|
final regla = tester.widget<DecoratedBox>(
|
||||||
|
find.byKey(const ValueKey('vacaciones-regla-f2')),
|
||||||
|
);
|
||||||
|
final decoration = regla.decoration as BoxDecoration;
|
||||||
|
expect(decoration.gradient, isNull);
|
||||||
|
expect(
|
||||||
|
decoration.color,
|
||||||
|
Colors.white.withValues(alpha: 0.14),
|
||||||
|
reason:
|
||||||
|
't4:474 scheduled/past rows use a flat rgba(255,255,255,.14) '
|
||||||
|
'connector, not the active gradient',
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user