focus-flow/apps/focus_flow_flutter/lib/widgets/today_pane.dart

83 lines
2.6 KiB
Dart

/// Renders the Today Pane widget for the FocusFlow Flutter UI.
library;
import 'package:flutter/material.dart';
import 'package:scheduler_core/scheduler_core.dart';
import '../controllers/scheduler_command_controller.dart';
import '../controllers/scheduler_read_controller.dart';
import 'read_state_view.dart';
import 'schedule_components.dart';
/// Read-driven pane that renders the Today view and optional commands.
class TodayPane extends StatelessWidget {
/// Creates a Today pane from a read [controller].
const TodayPane({
required this.controller,
this.commandController,
super.key,
});
/// Controller that loads Today state.
final UiReadController<TodayState> controller;
/// Optional command controller for Today actions.
final SchedulerCommandController? commandController;
@override
Widget build(BuildContext context) {
return ReadStateView<TodayState>(
controller: controller,
title: 'Today',
emptyTitle: 'Today is clear',
emptyMessage: 'No scheduled work is waiting in this view.',
dataBuilder: (context, state) =>
TodayContent(state: state, commandController: commandController),
);
}
}
/// Populated Today view for a loaded Today state.
class TodayContent extends StatelessWidget {
/// Creates Today content for [state].
const TodayContent({required this.state, this.commandController, super.key});
/// Loaded Today state to display.
final TodayState state;
/// Optional command controller for completing tasks.
final SchedulerCommandController? commandController;
@override
Widget build(BuildContext context) {
return ListView(
padding: const EdgeInsets.all(16),
children: [
Text('Today', style: Theme.of(context).textTheme.headlineMedium),
const SizedBox(height: 12),
for (final notice in state.pendingNotices)
NoticeBanner(message: notice.message),
CompactPanel(items: state.compactState.compactItems),
Text('Timeline', style: Theme.of(context).textTheme.titleMedium),
const SizedBox(height: 8),
for (final item in state.timelineItems)
TimelineRow(
item: item,
onDone: _canComplete(item) && commandController != null
? () {
return commandController!.completeFlexibleTask(
taskId: item.taskId!,
);
}
: null,
),
],
);
}
bool _canComplete(TodayTimelineItem item) {
return item.taskType == TaskType.flexible &&
item.taskStatus == TaskStatus.planned &&
item.taskId != null;
}
}