import 'package:flutter/material.dart'; import '../../../../core/theme/app_theme_extension.dart'; /// Layout variant for dashboard quick-action cards. enum DashboardActionCardLayout { vertical, horizontal } /// Reusable action card with flexible height and wrapping subtitles. class DashboardActionCard extends StatelessWidget { const DashboardActionCard({ super.key, required this.title, required this.subtitle, required this.icon, required this.onTap, this.layout = DashboardActionCardLayout.vertical, this.minHeight = 150, this.useGradient = false, this.badge, this.iconSize = 24, this.iconPadding = 10, this.titleFontSize, this.subtitleFontSize, this.padding, this.leadingIcon, this.onTapDisabled, }); final String title; final String subtitle; final IconData icon; final VoidCallback? onTap; final bool? onTapDisabled; final DashboardActionCardLayout layout; final double minHeight; final bool useGradient; final String? badge; final double iconSize; final double iconPadding; final double? titleFontSize; final double? subtitleFontSize; final EdgeInsetsGeometry? padding; final Widget? leadingIcon; @override Widget build(BuildContext context) { final cs = Theme.of(context).colorScheme; final extras = AppThemeExtras.of(context); final isHorizontal = layout == DashboardActionCardLayout.horizontal; final effectivePadding = padding ?? EdgeInsets.all(isHorizontal ? 16 : (useGradient ? 20 : 14)); final decoration = BoxDecoration( gradient: useGradient ? LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ extras.actionCardGradientStart, extras.actionCardGradientEnd, ], ) : null, color: useGradient ? null : cs.surface, borderRadius: BorderRadius.circular(minHeight <= 110 ? 12 : 16), border: useGradient ? null : Border.all(color: cs.outline.withOpacity(0.2), width: 1), boxShadow: [ BoxShadow( color: (useGradient ? cs.primary : cs.shadow).withOpacity( useGradient ? 0.3 : 0.05, ), blurRadius: useGradient ? 15 : 10, offset: Offset(0, useGradient ? 8 : 4), ), ], ); final titleColor = useGradient ? Colors.white : cs.onSurface; final subtitleColor = useGradient ? Colors.white : cs.onSurfaceVariant; final iconBgColor = useGradient ? Colors.white.withOpacity(0.2) : cs.primary.withOpacity(0.1); final iconColor = useGradient ? Colors.white : cs.primary; final effectiveMinHeight = minHeight > 0 ? minHeight : null; return ConstrainedBox( constraints: effectiveMinHeight != null ? BoxConstraints(minHeight: effectiveMinHeight) : const BoxConstraints(), child: Container( decoration: decoration, child: Material( color: Colors.transparent, child: InkWell( borderRadius: BorderRadius.circular(minHeight <= 110 ? 12 : 16), onTap: onTapDisabled == true ? null : onTap, child: Padding( padding: effectivePadding, child: isHorizontal ? _buildHorizontalContent( context, titleColor, subtitleColor, iconBgColor, iconColor, ) : _buildVerticalContent( context, titleColor, subtitleColor, iconBgColor, iconColor, ), ), ), ), ), ); } Widget _buildHorizontalContent( BuildContext context, Color titleColor, Color subtitleColor, Color iconBgColor, Color iconColor, ) { final cs = Theme.of(context).colorScheme; return Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ _iconBox(iconBgColor, iconColor), const SizedBox(width: 16), Expanded( child: _titleSubtitleColumn( titleColor, subtitleColor, titleSize: titleFontSize ?? 16, subtitleSize: subtitleFontSize ?? 13, ), ), Icon(Icons.arrow_forward_ios, color: cs.primary, size: 16), ], ); } Widget _buildVerticalContent( BuildContext context, Color titleColor, Color subtitleColor, Color iconBgColor, Color iconColor, ) { final cs = Theme.of(context).colorScheme; final isCompact = minHeight <= 130; return Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisSize: MainAxisSize.min, children: [ Row( children: [ leadingIcon ?? _iconBox(iconBgColor, iconColor), if (badge != null) ...[ const Spacer(), Container( padding: EdgeInsets.symmetric( horizontal: isCompact ? 6 : 10, vertical: isCompact ? 3 : 4, ), decoration: BoxDecoration( color: cs.secondary, borderRadius: BorderRadius.circular(isCompact ? 10 : 12), ), child: Text( badge!, style: TextStyle( color: Colors.white, fontSize: isCompact ? 9 : 10, fontWeight: FontWeight.bold, ), ), ), ], ], ), SizedBox(height: isCompact ? 8 : 12), _titleSubtitleColumn( titleColor, subtitleColor, titleSize: titleFontSize ?? (useGradient ? 18 : 16), subtitleSize: subtitleFontSize ?? (isCompact ? 11 : 12), ), ], ); } Widget _iconBox(Color bgColor, Color iconColor) { return Container( padding: EdgeInsets.all(iconPadding), decoration: BoxDecoration( color: bgColor, borderRadius: BorderRadius.circular(10), ), child: Icon(icon, color: iconColor, size: iconSize), ); } Widget _titleSubtitleColumn( Color titleColor, Color subtitleColor, { required double titleSize, required double subtitleSize, }) { return Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ Text( title, style: TextStyle( color: titleColor, fontSize: titleSize, fontWeight: FontWeight.bold, height: 1.2, ), ), if (subtitle.isNotEmpty) ...[ SizedBox(height: subtitleSize >= 13 ? 4 : 2), Text( subtitle, style: TextStyle( color: subtitleColor, fontSize: subtitleSize, height: 1.25, ), ), ], ], ); } } /// Surface-styled vertical card (Quiz, Criar Turma, etc.). class DashboardActionCardSurface extends StatelessWidget { const DashboardActionCardSurface({ super.key, required this.title, required this.subtitle, required this.icon, required this.onTap, this.minHeight = 150, this.iconColor, this.leadingWidget, this.onTapDisabled, this.titleFontSize = 14, this.subtitleFontSize = 11, this.iconSize = 20, this.padding = const EdgeInsets.all(12), }); final String title; final String subtitle; final IconData icon; final VoidCallback? onTap; final bool? onTapDisabled; final double minHeight; final Color? iconColor; final Widget? leadingWidget; final double titleFontSize; final double subtitleFontSize; final double iconSize; final EdgeInsetsGeometry padding; @override Widget build(BuildContext context) { final cs = Theme.of(context).colorScheme; final effectiveIconColor = iconColor ?? cs.secondary; return DashboardActionCard( title: title, subtitle: subtitle, icon: icon, onTap: onTap, onTapDisabled: onTapDisabled, minHeight: minHeight, useGradient: false, iconSize: iconSize, leadingIcon: leadingWidget ?? Container( padding: const EdgeInsets.all(10), decoration: BoxDecoration( color: effectiveIconColor.withOpacity(0.1), borderRadius: BorderRadius.circular(10), ), child: Icon(icon, color: effectiveIconColor, size: iconSize), ), titleFontSize: titleFontSize, subtitleFontSize: subtitleFontSize, padding: padding, ); } }