/// Renders the Task Selection Modal widget for the FocusFlow Flutter UI. library; import 'package:flutter/material.dart'; import '../models/today_screen_models.dart'; import '../theme/focus_flow_tokens.dart'; import 'timeline/difficulty_bars.dart'; import 'timeline/reward_icon.dart'; class TaskSelectionModal extends StatelessWidget { const TaskSelectionModal({ required this.card, required this.onClose, super.key, }); final TimelineCardModel card; final VoidCallback onClose; @override Widget build(BuildContext context) { final accent = _accentFor(card.visualKind); return Material( color: Colors.transparent, child: Container( key: const ValueKey('task-selection-modal'), width: 548, padding: const EdgeInsets.fromLTRB(24, 22, 24, 20), decoration: BoxDecoration( color: FocusFlowTokens.elevatedPanel.withValues(alpha: 0.98), borderRadius: BorderRadius.circular(FocusFlowTokens.modalRadius), border: Border.all(color: accent.withValues(alpha: 0.86)), ), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Container( width: 44, height: 44, decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all(color: accent, width: 4), ), ), const SizedBox(width: 28), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( card.title, style: const TextStyle( color: FocusFlowTokens.textPrimary, fontSize: FocusFlowTokens.modalTitleSize, fontWeight: FontWeight.w800, ), ), const SizedBox(height: 6), Text( '${card.typeLabel} - ${card.timeText}', style: const TextStyle( color: FocusFlowTokens.textMuted, fontSize: 17, ), ), ], ), ), IconButton( key: const ValueKey('close-task-modal'), onPressed: onClose, style: IconButton.styleFrom( backgroundColor: FocusFlowTokens.glassPanelStrong, foregroundColor: FocusFlowTokens.textPrimary, ), icon: const Icon(Icons.close), ), ], ), const SizedBox(height: 26), Row( children: [ Expanded( child: _InfoTile( label: card.rewardLabel, child: RewardIcon(color: FocusFlowTokens.accentMagenta), ), ), const SizedBox(width: 28), Expanded( child: _InfoTile( label: card.effortLabel, child: DifficultyBars( difficulty: card.difficultyIconToken, color: FocusFlowTokens.restPurple, ), ), ), ], ), const SizedBox(height: 30), GridView.count( crossAxisCount: 2, crossAxisSpacing: 26, mainAxisSpacing: 16, childAspectRatio: 4.1, shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), children: const [ _ActionButton(icon: Icons.check, label: 'Done'), _ActionButton(icon: Icons.arrow_forward, label: 'Push'), _ActionButton( icon: Icons.inventory_2_outlined, label: 'Move to Backlog', ), _ActionButton(icon: Icons.apps, label: 'Break up'), ], ), const SizedBox(height: 14), const Text( 'Options apply after confirmation.', style: TextStyle(color: FocusFlowTokens.textMuted, fontSize: 14), ), ], ), ), ); } } class _InfoTile extends StatelessWidget { const _InfoTile({required this.child, required this.label}); final Widget child; final String label; @override Widget build(BuildContext context) { return Container( height: 58, padding: const EdgeInsets.symmetric(horizontal: 16), decoration: BoxDecoration( borderRadius: BorderRadius.circular(FocusFlowTokens.smallButtonRadius), border: Border.all(color: FocusFlowTokens.subtleBorder), ), child: Row( children: [ child, const SizedBox(width: 18), Flexible( child: Text( label, maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle( color: FocusFlowTokens.textPrimary, fontSize: 17, fontWeight: FontWeight.w700, ), ), ), ], ), ); } } class _ActionButton extends StatelessWidget { const _ActionButton({required this.icon, required this.label}); final IconData icon; final String label; @override Widget build(BuildContext context) { return OutlinedButton.icon( onPressed: () {}, style: OutlinedButton.styleFrom( foregroundColor: FocusFlowTokens.textPrimary, side: const BorderSide(color: FocusFlowTokens.subtleBorder), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular( FocusFlowTokens.smallButtonRadius, ), ), ), icon: Icon(icon), label: Text( label, style: const TextStyle( fontSize: FocusFlowTokens.modalButtonSize, fontWeight: FontWeight.w700, ), ), ); } } Color _accentFor(TaskVisualKind kind) { return switch (kind) { TaskVisualKind.flexible => FocusFlowTokens.flexibleGreen, TaskVisualKind.required => FocusFlowTokens.requiredPink, TaskVisualKind.appointment => FocusFlowTokens.appointmentBlue, TaskVisualKind.freeSlot => FocusFlowTokens.restPurple, TaskVisualKind.completedSurprise => FocusFlowTokens.completedGray, }; }