Files
krow-worker-app/lib/widgets/week_strip.dart
2026-09-17 22:26:11 +05:30

144 lines
4.1 KiB
Dart

import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import '../core/theme.dart';
/// Seven-day selector. A dot under a day marks something booked or set.
class WeekStrip extends StatelessWidget {
const WeekStrip({
super.key,
required this.days,
required this.selected,
required this.onSelect,
this.marked = const {},
});
final List<DateTime> days;
final DateTime selected;
final ValueChanged<DateTime> onSelect;
/// Day indices (0..6) that carry a marker dot.
final Set<int> marked;
@override
Widget build(BuildContext context) {
final dow = DateFormat('EEE');
return Row(
children: [
for (var i = 0; i < days.length; i++) ...[
if (i > 0) const SizedBox(width: 7),
Expanded(
child: _DayCell(
day: days[i],
label: dow.format(days[i]),
selected:
days[i].day == selected.day &&
days[i].month == selected.month,
marked: marked.contains(i),
onTap: () => onSelect(days[i]),
),
),
],
],
);
}
}
class _DayCell extends StatelessWidget {
const _DayCell({
required this.day,
required this.label,
required this.selected,
required this.marked,
required this.onTap,
});
final DateTime day;
final String label;
final bool selected;
final bool marked;
final VoidCallback onTap;
static const _duration = Duration(milliseconds: 260);
static const _curve = Curves.easeOutCubic;
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: onTap,
// Colour is animated rather than swapped so moving along the week reads
// as one continuous selection rather than a series of flashes.
child: AnimatedContainer(
duration: _duration,
curve: _curve,
height: 64,
decoration: BoxDecoration(
color: selected ? KrowPalette.blue : Colors.white,
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: selected ? KrowPalette.blue : KrowPalette.line,
),
boxShadow: selected
? [
BoxShadow(
color: KrowPalette.blue.withValues(alpha: 0.26),
blurRadius: 12,
offset: const Offset(0, 4),
),
]
: null,
),
child: Stack(
alignment: Alignment.center,
children: [
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
AnimatedDefaultTextStyle(
duration: _duration,
curve: _curve,
style: TextStyle(
fontSize: 9,
fontWeight: FontWeight.w600,
letterSpacing: 0.8,
color: selected ? Colors.white70 : const Color(0xFF949FA5),
),
child: Text(label.toUpperCase()),
),
const SizedBox(height: 2),
AnimatedDefaultTextStyle(
duration: _duration,
curve: _curve,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w700,
color: selected ? Colors.white : KrowPalette.ink,
),
child: Text('${day.day}'),
),
],
),
Positioned(
bottom: 8,
child: AnimatedScale(
scale: marked ? 1 : 0,
duration: _duration,
curve: Curves.easeOutBack,
child: AnimatedContainer(
duration: _duration,
width: 5,
height: 5,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: selected ? KrowPalette.yellow : KrowPalette.blue,
),
),
),
),
],
),
),
);
}
}