إصلاح أخطاء شاشة الكباتن من تحديث الذكاء الاصطناعي

This commit is contained in:
Hamza-Ayed
2026-07-26 13:15:45 +03:00
parent 4b5235c35c
commit 330dfc6dba
9 changed files with 1025 additions and 61 deletions
@@ -0,0 +1,483 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
class UnifiedAppBar extends StatelessWidget implements PreferredSizeWidget {
final String title;
final Widget? leading;
final List<Widget>? 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<Widget> tabs;
final TabController? tabController;
final Widget? leading;
final List<Widget>? 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<Widget>? 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!,
],
],
),
);
}
}