Alignement design systeme OK

This commit is contained in:
DahoudG
2025-09-20 03:56:11 +00:00
parent a1214bc116
commit 96a17eadbd
34 changed files with 11720 additions and 766 deletions

View File

@@ -0,0 +1,43 @@
import 'package:go_router/go_router.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../auth/bloc/auth_bloc.dart';
import '../../features/auth/presentation/pages/login_page.dart';
import 'main_navigation_layout.dart';
/// Configuration du routeur principal de l'application
class AppRouter {
static final GoRouter router = GoRouter(
initialLocation: '/',
redirect: (context, state) {
final authState = context.read<AuthBloc>().state;
final isAuthenticated = authState is AuthAuthenticated;
final isOnLoginPage = state.matchedLocation == '/login';
// Si pas authentifié et pas sur la page de login, rediriger vers login
if (!isAuthenticated && !isOnLoginPage) {
return '/login';
}
// Si authentifié et sur la page de login, rediriger vers dashboard
if (isAuthenticated && isOnLoginPage) {
return '/';
}
return null; // Pas de redirection
},
routes: [
GoRoute(
path: '/login',
name: 'login',
builder: (context, state) => const LoginPage(),
),
GoRoute(
path: '/',
name: 'main',
builder: (context, state) => const MainNavigationLayout(),
),
],
);
}

View File

@@ -0,0 +1,419 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../auth/bloc/auth_bloc.dart';
import '../auth/models/user_role.dart';
import '../design_system/tokens/tokens.dart';
import '../../features/dashboard/presentation/pages/role_dashboards/role_dashboards.dart';
import '../../features/members/presentation/pages/members_page.dart';
import '../../features/events/presentation/pages/events_page.dart';
/// Layout principal avec navigation hybride
/// Bottom Navigation pour les sections principales + Drawer pour fonctions avancées
class MainNavigationLayout extends StatefulWidget {
const MainNavigationLayout({super.key});
@override
State<MainNavigationLayout> createState() => _MainNavigationLayoutState();
}
class _MainNavigationLayoutState extends State<MainNavigationLayout> {
int _selectedIndex = 0;
/// Obtient le dashboard approprié selon le rôle de l'utilisateur
Widget _getDashboardForRole(UserRole role) {
switch (role) {
case UserRole.superAdmin:
return const SuperAdminDashboard();
case UserRole.orgAdmin:
return const OrgAdminDashboard();
case UserRole.moderator:
return const ModeratorDashboard();
case UserRole.activeMember:
return const ActiveMemberDashboard();
case UserRole.simpleMember:
return const SimpleMemberDashboard();
case UserRole.visitor:
return const VisitorDashboard();
}
}
List<Widget> _getPages(UserRole role) {
return [
_getDashboardForRole(role),
const MembersPage(),
const EventsPage(),
const MorePage(), // Page "Plus" qui affiche les options avancées
];
}
@override
Widget build(BuildContext context) {
return BlocBuilder<AuthBloc, AuthState>(
builder: (context, state) {
if (state is! AuthAuthenticated) {
return const Scaffold(
body: Center(child: CircularProgressIndicator()),
);
}
return Scaffold(
body: IndexedStack(
index: _selectedIndex,
children: _getPages(state.effectiveRole),
),
bottomNavigationBar: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
currentIndex: _selectedIndex,
onTap: (index) {
setState(() {
_selectedIndex = index;
});
},
selectedItemColor: ColorTokens.primary,
unselectedItemColor: Colors.grey,
items: const [
BottomNavigationBarItem(
icon: Icon(Icons.dashboard),
label: 'Dashboard',
),
BottomNavigationBarItem(
icon: Icon(Icons.people),
label: 'Membres',
),
BottomNavigationBarItem(
icon: Icon(Icons.event),
label: 'Événements',
),
BottomNavigationBarItem(
icon: Icon(Icons.more_horiz),
label: 'Plus',
),
],
),
);
},
);
}
}
/// Page "Plus" avec les fonctions avancées selon le rôle
class MorePage extends StatelessWidget {
const MorePage({super.key});
@override
Widget build(BuildContext context) {
return BlocBuilder<AuthBloc, AuthState>(
builder: (context, state) {
if (state is! AuthAuthenticated) {
return Container(
color: const Color(0xFFF8F9FA),
child: const Center(child: CircularProgressIndicator()),
);
}
return Container(
color: const Color(0xFFF8F9FA),
child: SingleChildScrollView(
padding: const EdgeInsets.all(12),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Titre de la section
const Text(
'Plus d\'Options',
style: TextStyle(
fontWeight: FontWeight.bold,
color: Color(0xFF6C5CE7),
fontSize: 20,
),
),
const SizedBox(height: 12),
// Profil utilisateur
_buildUserProfile(state),
const SizedBox(height: 16),
// Options selon le rôle
..._buildRoleBasedOptions(state),
const SizedBox(height: 16),
// Options communes
..._buildCommonOptions(context),
],
),
),
);
},
);
}
Widget _buildUserProfile(AuthAuthenticated state) {
return Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 4,
offset: const Offset(0, 2),
),
],
),
child: Row(
children: [
Container(
width: 50,
height: 50,
decoration: BoxDecoration(
color: const Color(0xFF6C5CE7),
borderRadius: BorderRadius.circular(25),
),
child: Center(
child: Text(
state.user.firstName.isNotEmpty ? state.user.firstName[0].toUpperCase() : 'U',
style: const TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'${state.user.firstName} ${state.user.lastName}',
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: Color(0xFF374151),
),
),
const SizedBox(height: 2),
Text(
state.effectiveRole.displayName,
style: const TextStyle(
fontSize: 14,
color: Color(0xFF6C5CE7),
fontWeight: FontWeight.w500,
),
),
const SizedBox(height: 2),
Text(
state.user.email,
style: const TextStyle(
fontSize: 12,
color: Color(0xFF6B7280),
),
),
],
),
),
],
),
);
}
List<Widget> _buildRoleBasedOptions(AuthAuthenticated state) {
final options = <Widget>[];
// Options Super Admin
if (state.effectiveRole == UserRole.superAdmin) {
options.addAll([
_buildSectionTitle('Administration Système'),
_buildOptionTile(
icon: Icons.settings,
title: 'Paramètres Système',
subtitle: 'Configuration globale',
onTap: () {},
),
_buildOptionTile(
icon: Icons.backup,
title: 'Sauvegarde',
subtitle: 'Gestion des sauvegardes',
onTap: () {},
),
_buildOptionTile(
icon: Icons.analytics,
title: 'Logs Système',
subtitle: 'Surveillance et logs',
onTap: () {},
),
]);
}
// Options Admin Organisation
if (state.effectiveRole == UserRole.orgAdmin || state.effectiveRole == UserRole.superAdmin) {
options.addAll([
_buildSectionTitle('Administration'),
_buildOptionTile(
icon: Icons.business,
title: 'Gestion Organisation',
subtitle: 'Paramètres organisation',
onTap: () {},
),
_buildOptionTile(
icon: Icons.assessment,
title: 'Rapports',
subtitle: 'Rapports et statistiques',
onTap: () {},
),
]);
}
// Options RH
if (state.effectiveRole == UserRole.moderator || state.effectiveRole == UserRole.superAdmin) {
options.addAll([
_buildSectionTitle('Ressources Humaines'),
_buildOptionTile(
icon: Icons.people_alt,
title: 'Gestion RH',
subtitle: 'Outils RH avancés',
onTap: () {},
),
]);
}
return options;
}
List<Widget> _buildCommonOptions(BuildContext context) {
return [
_buildSectionTitle('Général'),
_buildOptionTile(
icon: Icons.person,
title: 'Mon Profil',
subtitle: 'Modifier mes informations',
onTap: () {},
),
_buildOptionTile(
icon: Icons.notifications,
title: 'Notifications',
subtitle: 'Gérer les notifications',
onTap: () {},
),
_buildOptionTile(
icon: Icons.help,
title: 'Aide & Support',
subtitle: 'Documentation et support',
onTap: () {},
),
_buildOptionTile(
icon: Icons.info,
title: 'À propos',
subtitle: 'Version et informations',
onTap: () {},
),
const SizedBox(height: 16),
_buildOptionTile(
icon: Icons.logout,
title: 'Déconnexion',
subtitle: 'Se déconnecter de l\'application',
color: Colors.red,
onTap: () {
context.read<AuthBloc>().add(AuthLogoutRequested());
},
),
];
}
Widget _buildSectionTitle(String title) {
return Padding(
padding: const EdgeInsets.only(
top: 16,
bottom: 8,
),
child: Text(
title,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: Color(0xFF6C5CE7),
),
),
);
}
Widget _buildOptionTile({
required IconData icon,
required String title,
required String subtitle,
required VoidCallback onTap,
Color? color,
}) {
return Container(
margin: const EdgeInsets.only(bottom: 8),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 4,
offset: const Offset(0, 2),
),
],
),
child: InkWell(
onTap: onTap,
borderRadius: BorderRadius.circular(8),
child: Padding(
padding: const EdgeInsets.all(12),
child: Row(
children: [
Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: (color ?? const Color(0xFF6C5CE7)).withOpacity(0.1),
borderRadius: BorderRadius.circular(6),
),
child: Icon(
icon,
color: color ?? const Color(0xFF6C5CE7),
size: 20,
),
),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
color: color ?? const Color(0xFF374151),
),
),
const SizedBox(height: 2),
Text(
subtitle,
style: const TextStyle(
fontSize: 12,
color: Color(0xFF6B7280),
),
),
],
),
),
const Icon(
Icons.chevron_right,
color: Color(0xFF6B7280),
size: 16,
),
],
),
),
),
);
}
}