1+ import 'package:flutter/material.dart' ;
2+ import '../../../../core/theme/app_colors.dart' ;
3+ import '../../../tasks/model/task_model.dart' ;
4+ import '../widgets/statistics_widgets.dart' ;
5+
6+ class StatisticsScreen extends StatefulWidget {
7+ const StatisticsScreen ({super .key});
8+
9+ @override
10+ State <StatisticsScreen > createState () => _StatisticsScreenState ();
11+ }
12+
13+ class _StatisticsScreenState extends State <StatisticsScreen > {
14+ // Biến lưu trữ ngày đang được chọn trên biểu đồ (0 = T2, 1 = T3, 2 = T4...)
15+ int _selectedDayIndex = 2 ; // Mặc định chọn T4 (Index 2) giống trong thiết kế
16+
17+ // Dữ liệu giả lập phân loại theo ngày (0 đến 6)
18+ late Map <int , List <TaskModel >> _tasksByDay;
19+
20+ @override
21+ void initState () {
22+ super .initState ();
23+ // Tạo mock data cho một vài ngày để test
24+ _tasksByDay = {
25+ 0 : [ // Thứ 2
26+ TaskModel (id: 'stat_t2_1' , title: 'Họp team đầu tuần' , description: 'Lên kế hoạch Sprint mới.' , category: 'Development' , startTime: const TimeOfDay (hour: 9 , minute: 0 ), endTime: const TimeOfDay (hour: 10 , minute: 0 ), date: DateTime .now ()),
27+ ],
28+ 1 : [ // Thứ 3
29+ TaskModel (id: 'stat_t3_1' , title: 'Fix bug UI' , description: 'Sửa lỗi hiển thị trên iOS.' , category: 'Development' , startTime: const TimeOfDay (hour: 14 , minute: 0 ), endTime: const TimeOfDay (hour: 16 , minute: 0 ), date: DateTime .now ()),
30+ TaskModel (id: 'stat_t3_2' , title: 'Đọc tài liệu Flutter' , description: 'Nghiên cứu State Management.' , category: 'Research' , startTime: const TimeOfDay (hour: 20 , minute: 0 ), endTime: const TimeOfDay (hour: 21 , minute: 0 ), date: DateTime .now ()),
31+ ],
32+ 2 : [ // Thứ 4 (Mặc định)
33+ TaskModel (id: 'stat_t4_1' , title: 'Thiết kế UI màn hình Dashboard' , description: 'Hoàn thành bản thiết kế Figma.' , category: 'Design' , startTime: const TimeOfDay (hour: 10 , minute: 30 ), endTime: const TimeOfDay (hour: 11 , minute: 30 ), date: DateTime .now ()),
34+ TaskModel (id: 'stat_t4_2' , title: 'Học tiếng Anh - 30 phút' , description: 'Ôn tập 50 từ vựng chuyên ngành IT qua Anki.' , category: 'Research' , startTime: const TimeOfDay (hour: 8 , minute: 15 ), endTime: const TimeOfDay (hour: 8 , minute: 45 ), date: DateTime .now ()),
35+ TaskModel (id: 'stat_t4_3' , title: 'Gửi báo cáo tuần cho sếp' , description: 'Tổng hợp tiến độ dự án.' , category: 'Development' , startTime: const TimeOfDay (hour: 7 , minute: 45 ), endTime: const TimeOfDay (hour: 8 , minute: 0 ), date: DateTime .now ()),
36+ ],
37+ };
38+ }
39+
40+ // Hàm hỗ trợ chọn Icon dựa theo Category để UI sinh động hơn
41+ Icon _getIconForCategory (String category) {
42+ switch (category) {
43+ case 'Design' : return const Icon (Icons .checklist_rtl_rounded, color: AppColors .primaryBlue);
44+ case 'Research' : return const Icon (Icons .timer_outlined, color: Color (0xFFE67E22 ));
45+ case 'Development' : return const Icon (Icons .calendar_month_outlined, color: Color (0xFF9B59B6 ));
46+ default : return const Icon (Icons .task_alt_rounded, color: Colors .green);
47+ }
48+ }
49+
50+ @override
51+ Widget build (BuildContext context) {
52+ // Lấy danh sách task của ngày đang chọn (nếu không có thì trả về list rỗng)
53+ List <TaskModel > currentTasks = _tasksByDay[_selectedDayIndex] ?? [];
54+
55+ return Scaffold (
56+ backgroundColor: const Color (0xFFF4F6F9 ),
57+ body: SafeArea (
58+ child: SingleChildScrollView (
59+ padding: const EdgeInsets .symmetric (horizontal: 20 , vertical: 20 ),
60+ child: Column (
61+ crossAxisAlignment: CrossAxisAlignment .start,
62+ children: [
63+ // Header
64+ Row (
65+ mainAxisAlignment: MainAxisAlignment .spaceBetween,
66+ children: [
67+ const Row (
68+ children: [
69+ CircleAvatar (radius: 22 , backgroundImage: NetworkImage ('https://i.pravatar.cc/150?u=a042581f4e29026704d' )),
70+ SizedBox (width: 15 ),
71+ Text ('Thống kê' , style: TextStyle (fontSize: 24 , fontWeight: FontWeight .bold, color: Color (0xFF2C3E50 ))),
72+ ],
73+ ),
74+ Container (
75+ padding: const EdgeInsets .all (10 ),
76+ decoration: const BoxDecoration (color: Colors .white, shape: BoxShape .circle),
77+ child: const Icon (Icons .notifications_none_rounded, color: AppColors .primaryBlue),
78+ )
79+ ],
80+ ),
81+ const SizedBox (height: 30 ),
82+
83+ const DailyProgressCard (),
84+ const SizedBox (height: 25 ),
85+
86+ // Truyền State vào WeeklyChartCard
87+ WeeklyChartCard (
88+ selectedIndex: _selectedDayIndex,
89+ onDaySelected: (index) {
90+ setState (() {
91+ _selectedDayIndex = index; // Cập nhật lại UI khi chọn ngày khác
92+ });
93+ },
94+ ),
95+ const SizedBox (height: 30 ),
96+
97+ Row (
98+ mainAxisAlignment: MainAxisAlignment .spaceBetween,
99+ children: [
100+ const Text ('Hoàn thành gần đây' , style: TextStyle (fontSize: 18 , fontWeight: FontWeight .bold, color: Color (0xFF2C3E50 ))),
101+ Text ('Xem tất cả' , style: TextStyle (fontSize: 14 , fontWeight: FontWeight .w600, color: AppColors .primaryBlue)),
102+ ],
103+ ),
104+ const SizedBox (height: 15 ),
105+
106+ // Render danh sách Task kèm hiệu ứng đổi mới
107+ AnimatedSwitcher (
108+ duration: const Duration (milliseconds: 300 ),
109+ child: currentTasks.isEmpty
110+ ? Container (
111+ key: ValueKey ('empty_$_selectedDayIndex ' ),
112+ padding: const EdgeInsets .all (30 ),
113+ alignment: Alignment .center,
114+ child: Text ('Không có công việc nào hoàn thành vào ngày này.' ,
115+ style: TextStyle (color: Colors .grey.shade500), textAlign: TextAlign .center),
116+ )
117+ : Column (
118+ key: ValueKey ('list_$_selectedDayIndex ' ),
119+ children: currentTasks.map ((task) {
120+ return CompletedTaskCard (
121+ task: task,
122+ icon: _getIconForCategory (task.category),
123+ );
124+ }).toList (),
125+ ),
126+ ),
127+
128+ const SizedBox (height: 80 ),
129+ ],
130+ ),
131+ ),
132+ ),
133+ );
134+ }
135+ }
0 commit comments