import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:hive_flutter/hive_flutter.dart'; import '../models/task_item.dart'; import '../services/database_service.dart'; import '../widgets/elegant_header.dart'; import '../widgets/task_tile.dart'; import 'focus_timer_page.dart'; class DailyFocusPage extends StatefulWidget { const DailyFocusPage({super.key}); @override State createState() => _DailyFocusPageState(); } class _DailyFocusPageState extends State { late Box _tasksBox; @override void initState() { super.initState(); _tasksBox = DatabaseService.getTasksBox(); } List _getSortedTasks() { final tasks = _tasksBox.values.toList(); tasks.sort((a, b) => a.sortIndex.compareTo(b.sortIndex)); return tasks; } @override Widget build(BuildContext context) { return ValueListenableBuilder( valueListenable: _tasksBox.listenable(), builder: (context, Box box, _) { final allTasks = _getSortedTasks(); final essenceTasks = allTasks.take(3).toList(); final backlogTasks = allTasks.skip(3).toList(); final completedCount = allTasks.where((t) => t.isCompleted).length; return Scaffold( body: SafeArea( bottom: false, child: Column( children: [ const ElegantHeader(), Expanded( child: CustomScrollView( physics: const BouncingScrollPhysics(), slivers: [ // Header Section SliverPadding( padding: const EdgeInsets.fromLTRB(28, 10, 28, 30), sliver: SliverToBoxAdapter( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "Good Morning.", style: TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: Colors.grey.shade400, letterSpacing: 1, ), ), const SizedBox(height: 8), const Text( "Your Essence.", style: TextStyle( fontSize: 40, fontWeight: FontWeight.w900, color: Colors.black, height: 1.1, letterSpacing: -1, ), ), const SizedBox(height: 20), // Progress Bar Stack( children: [ Container( height: 4, width: 100, decoration: BoxDecoration( color: Colors.grey.shade200, borderRadius: BorderRadius.circular(2), ), ), AnimatedContainer( duration: const Duration(milliseconds: 500), height: 4, width: allTasks.isEmpty ? 0 : (100 * (completedCount / allTasks.length)), decoration: BoxDecoration( color: const Color(0xFFFF7F50), borderRadius: BorderRadius.circular(2), ), ), ], ), const SizedBox(height: 8), Text( "$completedCount / ${allTasks.length} Completed", style: TextStyle( fontSize: 11, color: Colors.grey.shade500, ), ), ], ), ), ), // Essence (Top 3) if (essenceTasks.isNotEmpty) SliverReorderableList( itemCount: essenceTasks.length, onReorder: (old, newIdx) => _onReorder(allTasks, old, newIdx), itemBuilder: (context, index) { final task = essenceTasks[index]; return ReorderableDragStartListener( key: ValueKey(task.id), index: index, child: TaskTile( task: task, index: index, isPriority: true, isTopOne: index == 0, onTap: () => _showTaskDetails(context, task), onFocusTap: index == 0 ? () => _startFocusMode(context, task) : null, onDismissed: () => _tasksBox.delete(task.id), ), ); }, ), // Backlog Divider if (backlogTasks.isNotEmpty) SliverPadding( padding: const EdgeInsets.fromLTRB(28, 40, 28, 15), sliver: SliverToBoxAdapter( child: Row( children: [ Text( "UP NEXT", style: TextStyle( fontSize: 11, fontWeight: FontWeight.w800, color: Colors.grey.shade300, letterSpacing: 1.2, ), ), const SizedBox(width: 10), Expanded( child: Divider(color: Colors.grey.shade100), ), ], ), ), ), // Backlog List SliverList( delegate: SliverChildBuilderDelegate( (context, index) { final actualIndex = index + 3; return TaskTile( task: backlogTasks[index], index: actualIndex, isPriority: false, onTap: () => _showTaskDetails(context, backlogTasks[index]), onDismissed: () => _tasksBox.delete(backlogTasks[index].id), ); }, childCount: backlogTasks.length, ), ), const SliverToBoxAdapter(child: SizedBox(height: 120)), ], ), ), ], ), ), floatingActionButton: FloatingActionButton.extended( onPressed: () => _showAddTaskModal(context), backgroundColor: Colors.black, elevation: 8, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(30), ), label: const Row( children: [ Icon(Icons.add, color: Colors.white, size: 20), SizedBox(width: 8), Text( "New Task", style: TextStyle( color: Colors.white, fontWeight: FontWeight.bold, ), ), ], ), ), ); }, ); } void _onReorder(List allTasks, int oldIndex, int newIndex) async { if (newIndex > oldIndex) newIndex -= 1; final item = allTasks.removeAt(oldIndex); allTasks.insert(newIndex, item); for (int i = 0; i < allTasks.length; i++) { final task = allTasks[i]; task.sortIndex = i; await _tasksBox.put(task.id, task); } HapticFeedback.selectionClick(); } void _showAddTaskModal(BuildContext context) { showModalBottomSheet( context: context, isScrollControlled: true, builder: (context) => Padding( padding: EdgeInsets.only( bottom: MediaQuery.of(context).viewInsets.bottom, ), child: Container( padding: const EdgeInsets.all(28), height: 220, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "What is essential?", style: TextStyle( fontSize: 14, fontWeight: FontWeight.bold, color: Colors.grey.shade400, ), ), const SizedBox(height: 12), TextField( autofocus: true, decoration: InputDecoration( hintText: "Enter task name...", hintStyle: TextStyle( color: Colors.grey.shade300, fontSize: 22, fontWeight: FontWeight.w500, ), border: InputBorder.none, ), style: const TextStyle( fontSize: 22, fontWeight: FontWeight.w600, ), onSubmitted: (value) { if (value.isNotEmpty) { final newId = DateTime.now().millisecondsSinceEpoch.toString(); final newTask = TaskItem( id: newId, title: value, createdAt: DateTime.now(), sortIndex: _tasksBox.length, ); _tasksBox.put(newId, newTask); Navigator.pop(context); } }, ), ], ), ), ), ); } void _showTaskDetails(BuildContext context, TaskItem task) { showModalBottomSheet( context: context, isScrollControlled: true, useRootNavigator: true, builder: (_) => DraggableScrollableSheet( initialChildSize: 0.55, minChildSize: 0.4, maxChildSize: 0.9, expand: false, builder: (_, controller) => Container( padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), child: ListView( controller: controller, children: [ Center( child: Container( width: 40, height: 4, decoration: BoxDecoration( color: Colors.grey.shade200, borderRadius: BorderRadius.circular(2), ), ), ), const SizedBox(height: 30), TextFormField( initialValue: task.title, style: const TextStyle( fontSize: 22, fontWeight: FontWeight.bold, ), decoration: const InputDecoration(border: InputBorder.none), onChanged: (val) { task.title = val; _tasksBox.put(task.id, task); }, ), const SizedBox(height: 20), _buildEditableDetail(Icons.sort, "Note", task.notes ?? "", (val) { task.notes = val; _tasksBox.put(task.id, task); }), const SizedBox(height: 30), ElevatedButton( onPressed: () { task.isCompleted = !task.isCompleted; _tasksBox.put(task.id, task); Navigator.pop(context); }, style: ElevatedButton.styleFrom( backgroundColor: task.isCompleted ? Colors.grey.shade300 : Colors.black, padding: const EdgeInsets.symmetric(vertical: 16), elevation: 0, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), ), ), child: Text( task.isCompleted ? "Mark as Incomplete" : "Complete Task", style: TextStyle( color: task.isCompleted ? Colors.black54 : Colors.white, fontWeight: FontWeight.bold, ), ), ), TextButton( onPressed: () { _tasksBox.delete(task.id); Navigator.pop(context); }, child: const Text( "Delete", style: TextStyle(color: Colors.redAccent), ), ) ], ), ), ), ); } Widget _buildEditableDetail( IconData icon, String label, String value, Function(String) onChange, ) { return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.grey.shade50, borderRadius: BorderRadius.circular(16), ), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Icon(icon, size: 20, color: Colors.grey.shade400), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( label, style: TextStyle( fontSize: 12, fontWeight: FontWeight.bold, color: Colors.grey.shade400, ), ), TextFormField( initialValue: value, maxLines: null, decoration: const InputDecoration( hintText: "Tap to add details...", border: InputBorder.none, isDense: true, ), style: const TextStyle(fontSize: 15, height: 1.5), onChanged: onChange, ), ], ), ), ], ), ); } void _startFocusMode(BuildContext context, TaskItem task) { Navigator.of(context).push( PageRouteBuilder( pageBuilder: (context, animation, secondaryAnimation) => FocusTimerPage(task: task), transitionsBuilder: (context, animation, secondaryAnimation, child) { return FadeTransition(opacity: animation, child: child); }, ), ); } }