focus-flow/apps/focus_flow_flutter/lib/widgets/timeline/timeline_view.dart

70 lines
2.1 KiB
Dart

import 'package:flutter/material.dart';
import '../../models/today_screen_models.dart';
import '../../theme/focus_flow_tokens.dart';
import 'task_timeline_card.dart';
import 'timeline_axis.dart';
import 'timeline_geometry.dart';
class TimelineView extends StatelessWidget {
const TimelineView({
required this.cards,
required this.range,
required this.onCardSelected,
super.key,
});
final List<TimelineCardModel> cards;
final TimelineRangeModel range;
final ValueChanged<TimelineCardModel> onCardSelected;
@override
Widget build(BuildContext context) {
final geometry = TimelineGeometry(
visibleStart: TimeOfDay(
hour: range.startMinutes ~/ 60,
minute: range.startMinutes % 60,
),
visibleEnd: TimeOfDay(
hour: range.endMinutes ~/ 60,
minute: range.endMinutes % 60,
),
pixelsPerMinute: 2.45,
minCardHeight: 88,
);
final contentHeight = geometry.totalHeight + 24;
return SingleChildScrollView(
child: SizedBox(
height: contentHeight,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TimelineAxis(geometry: geometry),
const SizedBox(width: 18),
Expanded(
child: Stack(
clipBehavior: Clip.none,
children: [
Positioned.fill(child: TimelineGrid(geometry: geometry)),
for (final card in cards)
Positioned(
top: geometry.yForMinutesSinceMidnight(card.startMinutes),
left: FocusFlowTokens.cardHorizontalPadding,
right: 0,
height: geometry.heightForDuration(
card.endMinutes - card.startMinutes,
),
child: TaskTimelineCard(
card: card,
onTap: () => onCardSelected(card),
),
),
],
),
),
],
),
),
);
}
}