Spaces:
Configuration error
Configuration error
| import 'package:flutter/material.dart'; | |
| import 'package:flutter/services.dart'; | |
| import 'package:smart_attendance_app/app/theme.dart'; | |
| import 'package:smart_attendance_app/shared/widgets/glass_card.dart'; | |
| /// Grid tile for the "More" tab quick-actions section. | |
| /// Displays icon + label + optional subtitle and notification badge. | |
| class MenuGridItem extends StatelessWidget { | |
| final IconData icon; | |
| final String label; | |
| final String? subtitle; | |
| final Color iconColor; | |
| final int badgeCount; | |
| final VoidCallback? onTap; | |
| const MenuGridItem({ | |
| super.key, | |
| required this.icon, | |
| required this.label, | |
| this.subtitle, | |
| this.iconColor = SasColors.accentEmerald, | |
| this.badgeCount = 0, | |
| this.onTap, | |
| }); | |
| Widget build(BuildContext context) { | |
| return GlassCard( | |
| onTap: onTap != null | |
| ? () { | |
| HapticFeedback.selectionClick(); | |
| onTap!(); | |
| } | |
| : null, | |
| padding: const EdgeInsets.all(16), | |
| child: Column( | |
| crossAxisAlignment: CrossAxisAlignment.start, | |
| children: [ | |
| Row( | |
| mainAxisAlignment: MainAxisAlignment.spaceBetween, | |
| children: [ | |
| Container( | |
| padding: const EdgeInsets.all(10), | |
| decoration: BoxDecoration( | |
| color: iconColor.withValues(alpha: 0.12), | |
| borderRadius: SasRadius.mdAll, | |
| border: Border.all( | |
| color: iconColor.withValues(alpha: 0.25), | |
| ), | |
| ), | |
| child: Icon(icon, color: iconColor, size: 20), | |
| ), | |
| if (badgeCount > 0) | |
| Container( | |
| padding: const EdgeInsets.symmetric( | |
| horizontal: 7, | |
| vertical: 3, | |
| ), | |
| decoration: BoxDecoration( | |
| color: SasColors.danger, | |
| borderRadius: SasRadius.xlAll, | |
| boxShadow: [ | |
| BoxShadow( | |
| color: SasColors.danger.withValues(alpha: 0.3), | |
| blurRadius: 6, | |
| spreadRadius: 1, | |
| ), | |
| ], | |
| ), | |
| child: Text( | |
| badgeCount > 99 ? '99+' : '$badgeCount', | |
| style: const TextStyle( | |
| color: Colors.white, | |
| fontSize: 10, | |
| fontWeight: FontWeight.w800, | |
| ), | |
| ), | |
| ), | |
| ], | |
| ), | |
| const SizedBox(height: SasSpacing.md), | |
| Text( | |
| label, | |
| style: const TextStyle( | |
| fontWeight: FontWeight.w700, | |
| fontSize: 14, | |
| color: SasColors.textPrimary, | |
| ), | |
| ), | |
| if (subtitle != null) ...[ | |
| const SizedBox(height: 3), | |
| Text( | |
| subtitle!, | |
| style: const TextStyle( | |
| color: SasColors.textMuted, | |
| fontSize: 11, | |
| fontWeight: FontWeight.w500, | |
| ), | |
| ), | |
| ], | |
| ], | |
| ), | |
| ); | |
| } | |
| } | |