70 lines
2.1 KiB
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),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|