Files
unionflow-server-api/unionflow-mobile-apps/lib/features/dashboard/presentation/widgets/navigation_cards.dart
2025-08-20 21:00:35 +00:00

281 lines
9.1 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import '../../../../shared/theme/app_theme.dart';
import '../../../../core/utils/responsive_utils.dart';
class NavigationCards extends StatelessWidget {
final Function(int)? onNavigateToTab;
const NavigationCards({
super.key,
this.onNavigateToTab,
});
@override
Widget build(BuildContext context) {
ResponsiveUtils.init(context);
return Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.08),
blurRadius: 15,
offset: const Offset(0, 4),
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Padding(
padding: EdgeInsets.all(20),
child: Row(
children: [
Icon(
Icons.dashboard_customize,
color: AppTheme.primaryColor,
size: 20,
),
SizedBox(width: 8),
Text(
'Accès rapide aux modules',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: AppTheme.textPrimary,
),
),
],
),
),
Padding(
padding: const EdgeInsets.fromLTRB(20, 0, 20, 20),
child: GridView.count(
crossAxisCount: 2,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
crossAxisSpacing: 12,
mainAxisSpacing: 12,
childAspectRatio: 1.1,
children: [
_buildNavigationCard(
context,
title: 'Membres',
subtitle: '1,247 membres',
icon: Icons.people_rounded,
color: AppTheme.secondaryColor,
onTap: () => _navigateToModule(context, 1, 'Membres'),
badge: '+5 cette semaine',
),
_buildNavigationCard(
context,
title: 'Cotisations',
subtitle: '89.5% à jour',
icon: Icons.payment_rounded,
color: AppTheme.accentColor,
onTap: () => _navigateToModule(context, 2, 'Cotisations'),
badge: '15 en retard',
badgeColor: AppTheme.warningColor,
),
_buildNavigationCard(
context,
title: 'Événements',
subtitle: '3 à venir',
icon: Icons.event_rounded,
color: AppTheme.warningColor,
onTap: () => _navigateToModule(context, 3, 'Événements'),
badge: 'AG dans 5 jours',
),
_buildNavigationCard(
context,
title: 'Finances',
subtitle: '€45,890',
icon: Icons.account_balance_rounded,
color: AppTheme.primaryColor,
onTap: () => _navigateToModule(context, 4, 'Finances'),
badge: '+12.8% ce mois',
badgeColor: AppTheme.successColor,
),
],
),
),
],
),
);
}
Widget _buildNavigationCard(
BuildContext context, {
required String title,
required String subtitle,
required IconData icon,
required Color color,
required VoidCallback onTap,
String? badge,
Color? badgeColor,
}) {
return Material(
color: Colors.transparent,
child: InkWell(
onTap: () {
HapticFeedback.lightImpact();
onTap();
},
borderRadius: BorderRadius.circular(12),
child: Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
border: Border.all(
color: color.withOpacity(0.2),
width: 1,
),
borderRadius: BorderRadius.circular(12),
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
color.withOpacity(0.05),
color.withOpacity(0.02),
],
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Header avec icône et badge
Row(
children: [
Flexible(
child: Container(
width: ResponsiveUtils.iconSize(8),
height: ResponsiveUtils.iconSize(8),
decoration: BoxDecoration(
color: color.withOpacity(0.15),
borderRadius: BorderRadius.circular(ResponsiveUtils.iconSize(4)),
),
child: Icon(
icon,
color: color,
size: ResponsiveUtils.iconSize(4.5),
),
),
),
const Spacer(),
if (badge != null)
Flexible(
child: Container(
padding: ResponsiveUtils.paddingSymmetric(
horizontal: 1.5,
vertical: 0.3,
),
decoration: BoxDecoration(
color: (badgeColor ?? AppTheme.successColor).withOpacity(0.1),
borderRadius: ResponsiveUtils.borderRadius(2),
border: Border.all(
color: (badgeColor ?? AppTheme.successColor).withOpacity(0.3),
width: 0.5,
),
),
child: Text(
badge,
style: TextStyle(
color: badgeColor ?? AppTheme.successColor,
fontSize: 2.5.fs,
fontWeight: FontWeight.w600,
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
),
],
),
const Spacer(),
// Contenu principal
Text(
title,
style: TextStyle(
fontSize: ResponsiveUtils.adaptive(
small: 4.fs,
medium: 3.8.fs,
large: 3.6.fs,
),
fontWeight: FontWeight.bold,
color: AppTheme.textPrimary,
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
SizedBox(height: 1.hp),
Text(
subtitle,
style: TextStyle(
fontSize: ResponsiveUtils.adaptive(
small: 3.2.fs,
medium: 3.fs,
large: 2.8.fs,
),
color: AppTheme.textSecondary,
),
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
const SizedBox(height: 8),
// Flèche d'action
Row(
children: [
Text(
'Gérer',
style: TextStyle(
fontSize: 12,
color: color,
fontWeight: FontWeight.w600,
),
),
const SizedBox(width: 4),
Icon(
Icons.arrow_forward_ios,
size: 12,
color: color,
),
],
),
],
),
),
),
);
}
void _navigateToModule(BuildContext context, int tabIndex, String moduleName) {
// Si onNavigateToTab est fourni, l'utiliser pour naviguer vers l'onglet
if (onNavigateToTab != null) {
onNavigateToTab!(tabIndex);
} else {
// Sinon, afficher un message temporaire
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Navigation vers $moduleName'),
backgroundColor: AppTheme.primaryColor,
behavior: SnackBarBehavior.floating,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
action: SnackBarAction(
label: 'OK',
textColor: Colors.white,
onPressed: () {
ScaffoldMessenger.of(context).hideCurrentSnackBar();
},
),
),
);
}
}
}