chore: استيراد أولي من سيرو (ecfe7568) — بلا أي تعديل

نسخة كاملة من مستودع سيرو عند ecfe7568 لتكون أساس تطبيق «انطلق».
نُسخ المتعقَّب في git فقط (12,509 ملفاً / 302 م.ب) بـ git archive، لا
`cp -r` — فاستُثنيت تلقائياً مخلفات البناء (build · node_modules ·
.dart_tool · .gradle · Pods ≈ 10.7 غ.ب) وكل ما يستثنيه .gitignore.

هذا الكوميت **بلا أي تعديل عمداً** حتى يكون كل ما يليه فرقاً مقروءاً
مقابل سيرو الأصلي. سيرو نفسه لم يُمسّ.

⚠️ لا يبني بعد: `.env` و`lib/env/env.g.dart` غير متعقَّبين في سيرو (وهذا
صحيح — أسرار لكل مستأجر). كل تطبيق فلاتر هنا يحتاج .env خاصاً بانطلق ثم
توليد env.g.dart عبر build_runner. لا تُنسخ أسرار سيرو.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Hamza-Ayed
2026-07-27 05:10:29 +03:00
co-authored by Claude Opus 5
commit 92dc6b3641
3654 changed files with 896478 additions and 0 deletions
@@ -0,0 +1,63 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../constant/colors.dart';
class MyCircleContainer extends StatelessWidget {
final Widget child;
final Color backgroundColor;
final Color borderColor;
MyCircleContainer({
Key? key,
required this.child,
this.backgroundColor = AppColor.secondaryColor,
this.borderColor = AppColor.accentColor,
}) : super(key: key);
final controller = Get.put(CircleController());
@override
Widget build(BuildContext context) {
return GetBuilder<CircleController>(
builder: ((controller) => GestureDetector(
onTap: () {
controller.changeColor();
},
child: AnimatedContainer(
onEnd: () {
controller.onEnd();
},
duration: const Duration(milliseconds: 300),
width: controller.size,
height: controller.size,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: controller.backgroundColor,
border: Border.all(
color: borderColor,
width: 1,
),
),
child: Center(child: child),
),
)));
}
}
class CircleController extends GetxController {
Color backgroundColor = AppColor.secondaryColor;
double size = 40;
void changeColor() {
backgroundColor = backgroundColor == AppColor.secondaryColor
? AppColor.accentColor
: AppColor.secondaryColor;
size = 60;
update();
}
void onEnd() {
size = 40;
update();
}
}
@@ -0,0 +1,70 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:vibration/vibration.dart';
import '../../constant/box_name.dart';
import '../../constant/colors.dart';
import '../../constant/style.dart';
import '../../main.dart';
class MyElevatedButton extends StatelessWidget {
final String title;
final VoidCallback onPressed;
final Color kolor;
final int vibrateDuration;
final bool loading;
final Widget? child;
const MyElevatedButton({
Key? key,
required this.title,
required this.onPressed,
this.kolor = AppColor.primaryColor,
this.vibrateDuration = 100,
this.loading = false,
this.child,
}) : super(key: key);
@override
Widget build(BuildContext context) {
bool vibrate = box.read(BoxName.isvibrate) ?? true;
return ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: kolor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12.0),
),
),
onPressed: loading
? null
: () async {
if (vibrate == true) {
if (Platform.isIOS) {
HapticFeedback.selectionClick();
} else if (Platform.isAndroid) {
await Vibration.vibrate(duration: vibrateDuration);
} else {}
}
onPressed();
},
child: loading
? const SizedBox(
height: 20,
width: 20,
child: CircularProgressIndicator(
color: Colors.white,
strokeWidth: 2,
),
)
: child ??
Text(
title.tr,
textAlign: TextAlign.center,
style: AppStyle.title.copyWith(color: AppColor.secondaryColor),
),
);
}
}
@@ -0,0 +1,66 @@
import 'package:flutter/material.dart';
import '../../constant/colors.dart';
import '../../constant/style.dart';
class IconWidgetMenu extends StatelessWidget {
const IconWidgetMenu({
Key? key,
required this.onpressed,
required this.icon,
required this.title,
}) : super(key: key);
final VoidCallback onpressed;
final IconData icon;
final String title;
@override
Widget build(BuildContext context) {
return InkWell(
onTap: onpressed,
child: Padding(
padding: const EdgeInsets.only(top: 1),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: 50,
decoration: const BoxDecoration(
color: AppColor.secondaryColor,
shape: BoxShape.circle,
// boxShadow: [
// BoxShadow(
// color: AppColor.secondaryColor,
// offset: Offset(-2, -2),
// blurRadius: 0,
// spreadRadius: 0,
// blurStyle: BlurStyle.outer,
// ),
// BoxShadow(
// color: AppColor.accentColor,
// offset: Offset(3, 3),
// blurRadius: 0,
// spreadRadius: 0,
// blurStyle: BlurStyle.outer,
// ),
// ],
),
child: Center(
child: Icon(
icon,
size: 30,
color: AppColor.primaryColor,
),
),
),
Text(
title,
style: AppStyle.subtitle.copyWith(color: AppColor.secondaryColor),
)
],
),
),
);
}
}
@@ -0,0 +1,40 @@
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../constant/colors.dart';
import '../../constant/style.dart';
import 'elevated_btn.dart';
class MyDialog extends GetxController {
void getDialog(
String title, String? midTitle, Widget widget, VoidCallback onPressed) {
// final textToSpeechController = Get.put(TextToSpeechController());
Get.defaultDialog(
title: title,
titleStyle: AppStyle.title,
middleTextStyle: AppStyle.title,
content: Column(
children: [
// IconButton(
// onPressed: () async {
// // await textToSpeechController.speakText(title ?? midTitle!);
// },
// icon: const Icon(Icons.headphones)),
widget
],
),
confirm: MyElevatedButton(
title: 'Ok'.tr,
onPressed: onPressed,
kolor: AppColor.greenColor,
),
cancel: MyElevatedButton(
title: 'Cancel'.tr,
kolor: AppColor.redColor,
onPressed: () {
Get.back();
}));
}
}
@@ -0,0 +1,51 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../constant/colors.dart';
import '../../constant/style.dart';
class MyScaffold extends StatelessWidget {
const MyScaffold({
super.key,
required this.title,
this.action = const Icon(
Icons.clear,
color: AppColor.secondaryColor,
),
required this.isleading,
required this.body,
});
final String title;
final List<Widget> body;
final Widget action;
final bool isleading;
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppColor.secondaryColor,
appBar: AppBar(
backgroundColor: AppColor.secondaryColor,
elevation: 0,
leading: isleading
? IconButton(
onPressed: () {
Get.back();
},
icon: const Icon(
Icons.arrow_back_ios_new,
color: AppColor.primaryColor,
),
)
: const SizedBox(),
actions: [action],
title: Text(
title,
style: AppStyle.title
.copyWith(fontSize: 20, fontWeight: FontWeight.bold),
),
),
body: SafeArea(child: Stack(children: body)));
}
}
@@ -0,0 +1,69 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../constant/colors.dart';
import '../../constant/style.dart';
class MyTextForm extends StatelessWidget {
const MyTextForm({
super.key,
required this.controller,
required this.label,
required this.hint,
required this.type,
this.validator,
});
final TextEditingController controller;
final String label, hint;
final TextInputType type;
final String? Function(String?)? validator;
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(bottom: 10),
child: SizedBox(
width: Get.width * .8,
child: TextFormField(
keyboardType: type,
cursorColor: AppColor.accentColor,
controller: controller,
decoration: InputDecoration(
focusedBorder: OutlineInputBorder(
borderSide: const BorderSide(
color: AppColor.primaryColor,
width: 2.0,
),
borderRadius: BorderRadius.circular(10),
),
focusColor: AppColor.accentColor,
fillColor: AppColor.accentColor,
border: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12))),
labelText: label.tr,
hintText: hint.tr,
hintStyle: AppStyle.title,
labelStyle: AppStyle.title,
),
validator: validator ?? (value) {
if (value == null || value.isEmpty) {
return '${'Please enter'.tr} $label.'.tr;
}
if (type == TextInputType.emailAddress) {
if (!value.contains('@')) {
return 'Please enter a valid email.'.tr;
}
} else if (type == TextInputType.phone) {
if (value.length > 14) {
return 'Please enter a valid phone number.'.tr;
}
}
return null;
},
),
),
);
}
}
@@ -0,0 +1,301 @@
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import '../../constant/colors.dart';
class MyCircularProgressIndicator extends StatelessWidget {
final Color backgroundColor;
const MyCircularProgressIndicator({
super.key,
this.backgroundColor = Colors.transparent,
});
@override
Widget build(BuildContext context) {
return Center(
child: Container(
width: 110,
height: 110,
decoration: BoxDecoration(
color: backgroundColor,
shape: BoxShape.circle,
),
child: Stack(
children: [
const Center(child: CircularProgressIndicator()),
Column(
children: [
Align(
alignment: Alignment.center,
child: Image.asset('assets/images/logo.png'),
),
],
),
],
),
),
);
}
}
enum _SnackVariant { success, error, info, warning }
extension _VariantProps on _SnackVariant {
Color get baseColor => switch (this) {
_SnackVariant.success => const Color(0xFF1A9E5C),
_SnackVariant.error => const Color(0xFFD93025),
_SnackVariant.info => const Color(0xFF1A73E8),
_SnackVariant.warning => const Color(0xFFF29900),
};
Color get surfaceColor => switch (this) {
_SnackVariant.success => const Color(0xFFF0FBF5),
_SnackVariant.error => const Color(0xFFFEF2F1),
_SnackVariant.info => const Color(0xFFF0F6FF),
_SnackVariant.warning => const Color(0xFFFFF8E6),
};
IconData get icon => switch (this) {
_SnackVariant.success => Icons.check_circle_rounded,
_SnackVariant.error => Icons.error_rounded,
_SnackVariant.info => Icons.info_rounded,
_SnackVariant.warning => Icons.warning_amber_rounded,
};
String get label => switch (this) {
_SnackVariant.success => 'Success',
_SnackVariant.error => 'Error',
_SnackVariant.info => 'Info',
_SnackVariant.warning => 'Warning',
};
}
class _SnackContent extends StatefulWidget {
final String message;
final _SnackVariant variant;
const _SnackContent({required this.message, required this.variant});
@override
State<_SnackContent> createState() => _SnackContentState();
}
class _SnackContentState extends State<_SnackContent>
with TickerProviderStateMixin {
late final AnimationController _ctrl;
late final AnimationController _scaleCtrl;
late final Animation<double> _scaleAnim;
late final Animation<double> _progressAnim;
static const Duration _displayDuration = Duration(seconds: 4);
@override
void initState() {
super.initState();
_ctrl = AnimationController(vsync: this, duration: _displayDuration);
_scaleCtrl = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 500),
);
_scaleAnim = CurvedAnimation(
parent: _scaleCtrl,
curve: Curves.elasticOut,
);
_progressAnim = Tween<double>(begin: 1.0, end: 0.0).animate(
CurvedAnimation(parent: _ctrl, curve: Curves.linear),
);
_scaleCtrl.forward();
_ctrl.forward();
}
@override
void dispose() {
_ctrl.dispose();
_scaleCtrl.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final v = widget.variant;
final accent = v.baseColor;
final surface = v.surfaceColor;
return Container(
margin: const EdgeInsets.symmetric(horizontal: 14, vertical: 8),
decoration: BoxDecoration(
color: surface,
borderRadius: BorderRadius.circular(18),
border: Border.all(color: accent.withAlpha(46), width: 1.2),
boxShadow: [
BoxShadow(
color: accent.withAlpha(31),
blurRadius: 20,
spreadRadius: -2,
offset: const Offset(0, 6),
),
BoxShadow(
color: Colors.black.withAlpha(15),
blurRadius: 10,
offset: const Offset(0, 2),
),
],
),
child: ClipRRect(
borderRadius: BorderRadius.circular(18),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding: const EdgeInsets.fromLTRB(14, 14, 10, 12),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ScaleTransition(
scale: _scaleAnim,
child: Container(
width: 40,
height: 40,
decoration: BoxDecoration(
color: accent.withAlpha(31),
shape: BoxShape.circle,
),
child: Icon(v.icon, color: accent, size: 22),
),
),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(
v.label.tr,
style: TextStyle(
color: accent,
fontSize: 13,
fontWeight: FontWeight.w700,
letterSpacing: 0.2,
),
),
const SizedBox(height: 3),
Text(
widget.message,
style: const TextStyle(
color: Color(0xFF424242),
fontSize: 13.5,
height: 1.4,
fontWeight: FontWeight.w400,
),
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
],
),
),
GestureDetector(
onTap: () {
HapticFeedback.lightImpact();
_closeSnackbar(context);
},
child: Container(
width: 30,
height: 30,
margin: const EdgeInsets.only(left: 6),
decoration: BoxDecoration(
color: Colors.grey.withAlpha(25),
shape: BoxShape.circle,
),
child: Icon(
Icons.close_rounded,
size: 16,
color: Colors.grey[500],
),
),
),
],
),
),
AnimatedBuilder(
animation: _progressAnim,
builder: (_, __) => Stack(
children: [
Container(height: 3, color: accent.withAlpha(20)),
FractionallySizedBox(
widthFactor: _progressAnim.value,
child: Container(
height: 3,
decoration: BoxDecoration(
color: accent.withAlpha(115),
borderRadius: const BorderRadius.only(
topRight: Radius.circular(4),
bottomRight: Radius.circular(4),
),
),
),
),
],
),
),
],
),
),
);
}
void _closeSnackbar(BuildContext context) {
ScaffoldMessenger.maybeOf(context)?.hideCurrentSnackBar();
}
}
int _retryCount = 0;
void _show(_SnackVariant variant, String message) {
if (Get.context == null) {
if (_retryCount < 3) {
_retryCount++;
WidgetsBinding.instance.addPostFrameCallback((_) => _show(variant, message));
}
return;
}
_retryCount = 0;
final context = Get.context;
if (context == null) return;
final messenger = ScaffoldMessenger.maybeOf(context);
if (messenger == null) return;
messenger.clearSnackBars();
switch (variant) {
case _SnackVariant.error:
case _SnackVariant.warning:
HapticFeedback.mediumImpact();
case _SnackVariant.success:
HapticFeedback.lightImpact();
case _SnackVariant.info:
HapticFeedback.selectionClick();
}
messenger.showSnackBar(
SnackBar(
content: _SnackContent(message: message, variant: variant),
backgroundColor: Colors.transparent,
elevation: 0,
margin: EdgeInsets.zero,
padding: EdgeInsets.zero,
behavior: SnackBarBehavior.floating,
duration: const Duration(seconds: 4),
dismissDirection: DismissDirection.up,
),
);
}
void mySnackbarSuccess(String message) => _show(_SnackVariant.success, message);
void mySnackbarError(String message) => _show(_SnackVariant.error, message);
void mySnackbarInfo(String message) => _show(_SnackVariant.info, message);
void mySnackbarWarning(String message) => _show(_SnackVariant.warning, message);