feat: add categories to windows sidebar and refresh data on stat card navigation
This commit is contained in:
1 parent
dae724a41d
commit
7fa6c1140e
2 files changed
+93
-37
No files matched your search
@@ -125,13 +125,13 @@ class _WindowsSidebarLayoutState extends ConsumerState<WindowsSidebarLayout> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final allTabs = [
|
||||
{'label': 'Dashboard', 'icon': Icons.dashboard, 'activeIcon': Icons.dashboard, 'screen': const DashboardScreen(), 'roles': ['admin', 'teacher']},
|
||||
{'label': 'Students', 'icon': Icons.people, 'activeIcon': Icons.people, 'screen': StudentsScreen(userRole: widget.userRole), 'roles': ['admin', 'teacher']},
|
||||
{'label': 'Documents', 'icon': Icons.folder, 'activeIcon': Icons.folder, 'screen': DocumentsScreen(userRole: widget.userRole), 'roles': ['admin', 'teacher']},
|
||||
{'label': 'Archives', 'icon': Icons.archive, 'activeIcon': Icons.archive, 'screen': ArchivesScreen(userRole: widget.userRole), 'roles': ['admin']},
|
||||
{'label': 'Reports', 'icon': Icons.bar_chart, 'activeIcon': Icons.bar_chart, 'screen': ReportsScreen(userRole: widget.userRole), 'roles': ['admin']},
|
||||
{'label': 'Users', 'icon': Icons.manage_accounts, 'activeIcon': Icons.manage_accounts, 'screen': const UsersScreen(), 'roles': ['admin']},
|
||||
{'label': 'Settings', 'icon': Icons.settings, 'activeIcon': Icons.settings, 'screen': SettingsScreen(userRole: widget.userRole), 'roles': ['admin', 'teacher']},
|
||||
{'category': 'Main Menu', 'label': 'Dashboard', 'icon': Icons.dashboard, 'activeIcon': Icons.dashboard, 'screen': const DashboardScreen(), 'roles': ['admin', 'teacher']},
|
||||
{'category': 'Main Menu', 'label': 'Students', 'icon': Icons.people, 'activeIcon': Icons.people, 'screen': StudentsScreen(userRole: widget.userRole), 'roles': ['admin', 'teacher']},
|
||||
{'category': 'Main Menu', 'label': 'Documents', 'icon': Icons.folder, 'activeIcon': Icons.folder, 'screen': DocumentsScreen(userRole: widget.userRole), 'roles': ['admin', 'teacher']},
|
||||
{'category': 'Management', 'label': 'Archives', 'icon': Icons.archive, 'activeIcon': Icons.archive, 'screen': ArchivesScreen(userRole: widget.userRole), 'roles': ['admin']},
|
||||
{'category': 'Management', 'label': 'Reports', 'icon': Icons.bar_chart, 'activeIcon': Icons.bar_chart, 'screen': ReportsScreen(userRole: widget.userRole), 'roles': ['admin']},
|
||||
{'category': 'Management', 'label': 'Users', 'icon': Icons.manage_accounts, 'activeIcon': Icons.manage_accounts, 'screen': const UsersScreen(), 'roles': ['admin']},
|
||||
{'category': 'System', 'label': 'Settings', 'icon': Icons.settings, 'activeIcon': Icons.settings, 'screen': SettingsScreen(userRole: widget.userRole), 'roles': ['admin', 'teacher']},
|
||||
];
|
||||
final tabs = allTabs.where((tab) => (tab['roles'] as List<String>).contains(widget.userRole)).toList();
|
||||
|
||||
@@ -286,35 +286,62 @@ class _WindowsSidebarLayoutState extends ConsumerState<WindowsSidebarLayout> {
|
||||
final tab = tabs[index];
|
||||
final isSelected = currentIndex == index;
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: AppSizes.p8),
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
child: ListTile(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(AppSizes.radiusMedium),
|
||||
),
|
||||
selected: isSelected,
|
||||
selectedTileColor: Colors.white.withOpacity(0.15), // Soft highlight
|
||||
leading: Icon(
|
||||
(isSelected ? tab['activeIcon'] ?? tab['icon'] : tab['icon']) as IconData,
|
||||
color: isSelected ? Colors.white : Colors.white70,
|
||||
),
|
||||
title: Text(
|
||||
tab['label'] as String,
|
||||
style: TextStyle(
|
||||
fontWeight: isSelected ? FontWeight.bold : FontWeight.w500,
|
||||
color: isSelected ? Colors.white : Colors.white70,
|
||||
fontSize: 15,
|
||||
final String? category = tab['category'] as String?;
|
||||
final String? previousCategory = index > 0 ? tabs[index - 1]['category'] as String? : null;
|
||||
|
||||
final bool showCategory = category != null && category != previousCategory;
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (showCategory) ...[
|
||||
if (index > 0) const SizedBox(height: 8),
|
||||
if (index > 0) const Divider(height: 1, color: Colors.white24),
|
||||
if (index > 0) const SizedBox(height: 16),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 12, bottom: 8),
|
||||
child: Text(
|
||||
category.toUpperCase(),
|
||||
style: const TextStyle(
|
||||
color: Colors.white54,
|
||||
fontSize: 11,
|
||||
fontWeight: FontWeight.bold,
|
||||
letterSpacing: 1.2,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: AppSizes.p8),
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
child: ListTile(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(AppSizes.radiusMedium),
|
||||
),
|
||||
selected: isSelected,
|
||||
selectedTileColor: Colors.white.withOpacity(0.15), // Soft highlight
|
||||
leading: Icon(
|
||||
(isSelected ? tab['activeIcon'] ?? tab['icon'] : tab['icon']) as IconData,
|
||||
color: isSelected ? Colors.white : Colors.white70,
|
||||
),
|
||||
title: Text(
|
||||
tab['label'] as String,
|
||||
style: TextStyle(
|
||||
fontWeight: isSelected ? FontWeight.bold : FontWeight.w500,
|
||||
color: isSelected ? Colors.white : Colors.white70,
|
||||
fontSize: 15,
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
ref.read(activeTabProvider.notifier).setTab(tab['label'] as String);
|
||||
|
||||
_reloadTabContent(tab['label'] as String);
|
||||
},
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
ref.read(activeTabProvider.notifier).setTab(tab['label'] as String);
|
||||
|
||||
_reloadTabContent(tab['label'] as String);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
@@ -6,6 +6,8 @@ import '../../shared/cards/stat_card.dart';
|
||||
import '../../providers/dashboard_provider.dart';
|
||||
import '../../providers/auth_provider.dart';
|
||||
import '../../providers/student_provider.dart';
|
||||
import '../../providers/users_provider.dart';
|
||||
import '../../providers/document_provider.dart';
|
||||
import '../../providers/navigation_provider.dart';
|
||||
import '../../providers/notification_provider.dart';
|
||||
import '../../../domain/entities/dashboard_models.dart';
|
||||
@@ -631,7 +633,11 @@ class _DashboardScreenState extends ConsumerState<DashboardScreen> {
|
||||
title: 'Total Students',
|
||||
value: stats.totalStudents.toString(),
|
||||
icon: Icons.school,
|
||||
onTap: () => ref.read(activeTabProvider.notifier).setTab('Students'),
|
||||
onTap: () {
|
||||
ref.read(studentQueryProvider.notifier).reset();
|
||||
ref.invalidate(studentPageProvider);
|
||||
ref.read(activeTabProvider.notifier).setTab('Students');
|
||||
},
|
||||
),
|
||||
if (isAdmin)
|
||||
StatCard(
|
||||
@@ -639,10 +645,33 @@ class _DashboardScreenState extends ConsumerState<DashboardScreen> {
|
||||
value: stats.activeUsers.toString(),
|
||||
icon: Icons.badge,
|
||||
iconColor: Colors.blue,
|
||||
onTap: () => ref.read(activeTabProvider.notifier).setTab('Users'),
|
||||
onTap: () {
|
||||
ref.invalidate(usersProvider);
|
||||
ref.read(activeTabProvider.notifier).setTab('Users');
|
||||
},
|
||||
),
|
||||
StatCard(title: 'Complete Docs', value: stats.completedDocuments.toString(), icon: Icons.task_alt, iconColor: AppColors.primaryGreen),
|
||||
StatCard(title: 'Missing Docs', value: stats.missingDocuments.toString(), icon: Icons.folder_off, iconColor: Colors.orange),
|
||||
StatCard(
|
||||
title: 'Complete Docs',
|
||||
value: stats.completedDocuments.toString(),
|
||||
icon: Icons.task_alt,
|
||||
iconColor: AppColors.primaryGreen,
|
||||
onTap: () {
|
||||
ref.invalidate(foldersProvider);
|
||||
ref.invalidate(documentPageProvider);
|
||||
ref.read(activeTabProvider.notifier).setTab('Documents');
|
||||
},
|
||||
),
|
||||
StatCard(
|
||||
title: 'Missing Docs',
|
||||
value: stats.missingDocuments.toString(),
|
||||
icon: Icons.folder_off,
|
||||
iconColor: Colors.orange,
|
||||
onTap: () {
|
||||
ref.invalidate(foldersProvider);
|
||||
ref.invalidate(documentPageProvider);
|
||||
ref.read(activeTabProvider.notifier).setTab('Documents');
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user