import 'package:flutter/material.dart'; import 'package:get/get.dart'; class UnifiedAppBar extends StatelessWidget implements PreferredSizeWidget { final String title; final Widget? leading; final List? actions; final Color? backgroundColor; final Color? foregroundColor; final double elevation; final bool centerTitle; final PreferredSizeWidget? bottom; final double toolbarHeight; const UnifiedAppBar({ super.key, required this.title, this.leading, this.actions, this.backgroundColor, this.foregroundColor, this.elevation = 0, this.centerTitle = false, this.bottom, this.toolbarHeight = kToolbarHeight + 34, }); @override Widget build(BuildContext context) { final cs = Theme.of(context).colorScheme; final bgColor = backgroundColor ?? cs.surface; return Container( height: toolbarHeight, padding: const EdgeInsets.fromLTRB(16, 50, 16, 16), decoration: BoxDecoration( color: bgColor, border: Border(bottom: BorderSide(color: cs.outline, width: 0.5)), ), child: SafeArea( bottom: false, child: Row( children: [ leading ?? GestureDetector( onTap: () => Get.back(), child: Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: cs.surfaceContainerHighest, borderRadius: BorderRadius.circular(10), border: Border.all(color: cs.outline), ), child: Icon( Icons.arrow_back_ios_new_rounded, color: cs.onSurfaceVariant, size: 16, ), ), ), const SizedBox(width: 12), Expanded( child: Text( title, style: TextStyle( color: foregroundColor ?? cs.onSurface, fontSize: 18, fontWeight: FontWeight.w700, ), maxLines: 1, overflow: TextOverflow.ellipsis, ), ), if (actions != null) ...actions!, ], ), ), ); } @override Size get preferredSize => Size.fromHeight(toolbarHeight); } class UnifiedAppBarWithTabs extends StatelessWidget implements PreferredSizeWidget { final String title; final List tabs; final TabController? tabController; final Widget? leading; final List? actions; final Color? backgroundColor; final Color? foregroundColor; final double elevation; final EdgeInsetsGeometry? tabPadding; const UnifiedAppBarWithTabs({ super.key, required this.title, required this.tabs, this.tabController, this.leading, this.actions, this.backgroundColor, this.foregroundColor, this.elevation = 0, this.tabPadding, }); @override Widget build(BuildContext context) { final cs = Theme.of(context).colorScheme; final bgColor = backgroundColor ?? cs.surface; return Container( height: kToolbarHeight + 34 + 48, padding: const EdgeInsets.fromLTRB(16, 50, 16, 16), decoration: BoxDecoration( color: bgColor, border: Border(bottom: BorderSide(color: cs.outline, width: 0.5)), ), child: SafeArea( bottom: false, child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ leading ?? GestureDetector( onTap: () => Get.back(), child: Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: cs.surfaceContainerHighest, borderRadius: BorderRadius.circular(10), border: Border.all(color: cs.outline), ), child: Icon( Icons.arrow_back_ios_new_rounded, color: cs.onSurfaceVariant, size: 16, ), ), ), const SizedBox(width: 12), Expanded( child: Text( title, style: TextStyle( color: foregroundColor ?? cs.onSurface, fontSize: 18, fontWeight: FontWeight.w700, ), maxLines: 1, overflow: TextOverflow.ellipsis, ), ), if (actions != null) ...actions!, ], ), const SizedBox(height: 8), Container( padding: tabPadding ?? const EdgeInsets.all(4), decoration: BoxDecoration( color: cs.surfaceContainerHighest, borderRadius: BorderRadius.circular(12), border: Border.all(color: cs.outline), ), child: TabBar( controller: tabController, isScrollable: true, indicator: BoxDecoration( color: cs.primary.withValues(alpha: 0.15), borderRadius: BorderRadius.circular(8), border: Border.all(color: cs.primary.withValues(alpha: 0.3)), ), indicatorSize: TabBarIndicatorSize.tab, dividerColor: Colors.transparent, labelColor: cs.primary, unselectedLabelColor: cs.onSurfaceVariant, labelStyle: const TextStyle(fontWeight: FontWeight.w700, fontSize: 13), unselectedLabelStyle: const TextStyle(fontWeight: FontWeight.w500, fontSize: 13), tabs: tabs, ), ), ], ), ), ); } @override Size get preferredSize => const Size.fromHeight(kToolbarHeight + 34 + 48); } class UnifiedScaffold extends StatelessWidget { final String title; final Widget body; final List? actions; final Widget? leading; final Color? backgroundColor; final bool extendBody; final FloatingActionButton? floatingActionButton; final FloatingActionButtonLocation? floatingActionButtonLocation; final PreferredSizeWidget? bottomNavigationBar; const UnifiedScaffold({ super.key, required this.title, required this.body, this.actions, this.leading, this.backgroundColor, this.extendBody = false, this.floatingActionButton, this.floatingActionButtonLocation, this.bottomNavigationBar, }); @override Widget build(BuildContext context) { final cs = Theme.of(context).colorScheme; return Scaffold( backgroundColor: backgroundColor ?? cs.surface, extendBody: extendBody, floatingActionButton: floatingActionButton, floatingActionButtonLocation: floatingActionButtonLocation, bottomNavigationBar: bottomNavigationBar, appBar: UnifiedAppBar( title: title, actions: actions, leading: leading, backgroundColor: backgroundColor, ), body: body, ); } } class UnifiedLoadingState extends StatelessWidget { final String? message; final Color? color; const UnifiedLoadingState({super.key, this.message, this.color}); @override Widget build(BuildContext context) { final cs = Theme.of(context).colorScheme; return Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ SizedBox( width: 40, height: 40, child: CircularProgressIndicator( color: color ?? cs.primary, strokeWidth: 2, backgroundColor: (color ?? cs.primary).withValues(alpha: 0.1), ), ), const SizedBox(height: 16), Text( message ?? 'جاري التحميل...', style: TextStyle(color: cs.onSurfaceVariant, fontSize: 13), ), ], ), ); } } class UnifiedEmptyState extends StatelessWidget { final IconData icon; final String title; final String? subtitle; final Widget? action; const UnifiedEmptyState({ super.key, required this.icon, required this.title, this.subtitle, this.action, }); @override Widget build(BuildContext context) { final cs = Theme.of(context).colorScheme; return Center( child: Padding( padding: const EdgeInsets.all(24), child: Column( mainAxisSize: MainAxisSize.min, children: [ Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: cs.surfaceContainerHighest, shape: BoxShape.circle, ), child: Icon(icon, size: 48, color: cs.onSurfaceVariant), ), const SizedBox(height: 16), Text( title, style: TextStyle(color: cs.onSurface, fontSize: 16, fontWeight: FontWeight.w600), textAlign: TextAlign.center, ), if (subtitle != null) ...[ const SizedBox(height: 8), Text( subtitle!, style: TextStyle(color: cs.onSurfaceVariant, fontSize: 13), textAlign: TextAlign.center, ), ], if (action != null) ...[ const SizedBox(height: 20), action!, ], ], ), ), ); } } class UnifiedStatCard extends StatelessWidget { final String label; final String value; final IconData icon; final Color color; final VoidCallback? onTap; final String? subtitle; const UnifiedStatCard({ super.key, required this.label, required this.value, required this.icon, required this.color, this.onTap, this.subtitle, }); @override Widget build(BuildContext context) { final cs = Theme.of(context).colorScheme; return Material( color: Colors.transparent, child: InkWell( onTap: onTap, borderRadius: BorderRadius.circular(16), splashColor: color.withValues(alpha: 0.1), highlightColor: color.withValues(alpha: 0.05), child: Container( width: 155, padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: cs.surfaceContainerHighest, borderRadius: BorderRadius.circular(16), border: Border.all(color: cs.outline), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Container( padding: const EdgeInsets.all(7), decoration: BoxDecoration( color: color.withValues(alpha: 0.12), borderRadius: BorderRadius.circular(9), ), child: Icon(icon, color: color, size: 16), ), Container( width: 6, height: 6, decoration: BoxDecoration( shape: BoxShape.circle, color: color.withValues(alpha: 0.6), ), ), ], ), const Spacer(), Text( value, style: TextStyle( color: cs.onSurface, fontSize: 20, fontWeight: FontWeight.w700, height: 1.1, ), overflow: TextOverflow.ellipsis, ), const SizedBox(height: 3), Text( label, style: TextStyle( color: cs.onSurfaceVariant, fontSize: 10, fontWeight: FontWeight.w500, ), overflow: TextOverflow.ellipsis, ), if (subtitle != null) ...[ const SizedBox(height: 2), Text( subtitle!, style: TextStyle( color: cs.onSurfaceVariant, fontSize: 9, fontWeight: FontWeight.w400, ), overflow: TextOverflow.ellipsis, ), ], ], ), ), ), ); } } class UnifiedSectionHeader extends StatelessWidget { final String title; final IconData? icon; final Color? iconColor; final Widget? trailing; const UnifiedSectionHeader({ super.key, required this.title, this.icon, this.iconColor, this.trailing, }); @override Widget build(BuildContext context) { final cs = Theme.of(context).colorScheme; return Padding( padding: const EdgeInsets.fromLTRB(20, 8, 20, 10), child: Row( children: [ Container( width: 3, height: 14, decoration: BoxDecoration( color: iconColor ?? cs.primary, borderRadius: BorderRadius.circular(2), ), ), const SizedBox(width: 8), if (icon != null) ...[ Icon(icon!, size: 16, color: iconColor ?? cs.primary), const SizedBox(width: 6), ], Text( title, style: TextStyle( color: cs.onSurfaceVariant, fontSize: 11, fontWeight: FontWeight.w600, letterSpacing: 1.2, ), ), if (trailing != null) ...[ const Spacer(), trailing!, ], ], ), ); } }