Update: 2026-07-03 15:03:13

This commit is contained in:
Hamza-Ayed
2026-07-03 15:03:13 +03:00
parent 5ce6c00905
commit d06500a20f
7 changed files with 300 additions and 147 deletions
+6 -6
View File
@@ -129,6 +129,8 @@ PODS:
- nanopb/encode (= 3.30910.0) - nanopb/encode (= 3.30910.0)
- nanopb/decode (3.30910.0) - nanopb/decode (3.30910.0)
- nanopb/encode (3.30910.0) - nanopb/encode (3.30910.0)
- native_geofence (1.0.0):
- Flutter
- package_info_plus (0.4.5): - package_info_plus (0.4.5):
- Flutter - Flutter
- permission_handler_apple (9.4.8): - permission_handler_apple (9.4.8):
@@ -143,8 +145,6 @@ PODS:
- Flutter - Flutter
- share_plus (0.0.1): - share_plus (0.0.1):
- Flutter - Flutter
- sign_in_with_apple (0.0.1):
- Flutter
- sqflite_darwin (0.0.4): - sqflite_darwin (0.0.4):
- Flutter - Flutter
- FlutterMacOS - FlutterMacOS
@@ -186,13 +186,13 @@ DEPENDENCIES:
- local_auth_darwin (from `.symlinks/plugins/local_auth_darwin/darwin`) - local_auth_darwin (from `.symlinks/plugins/local_auth_darwin/darwin`)
- location (from `.symlinks/plugins/location/ios`) - location (from `.symlinks/plugins/location/ios`)
- maplibre_gl (from `.symlinks/plugins/maplibre_gl/ios`) - maplibre_gl (from `.symlinks/plugins/maplibre_gl/ios`)
- native_geofence (from `.symlinks/plugins/native_geofence/ios`)
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`) - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
- quick_actions_ios (from `.symlinks/plugins/quick_actions_ios/ios`) - quick_actions_ios (from `.symlinks/plugins/quick_actions_ios/ios`)
- record_ios (from `.symlinks/plugins/record_ios/ios`) - record_ios (from `.symlinks/plugins/record_ios/ios`)
- sensors_plus (from `.symlinks/plugins/sensors_plus/ios`) - sensors_plus (from `.symlinks/plugins/sensors_plus/ios`)
- share_plus (from `.symlinks/plugins/share_plus/ios`) - share_plus (from `.symlinks/plugins/share_plus/ios`)
- sign_in_with_apple (from `.symlinks/plugins/sign_in_with_apple/ios`)
- sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`) - sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
- vibration (from `.symlinks/plugins/vibration/ios`) - vibration (from `.symlinks/plugins/vibration/ios`)
@@ -266,6 +266,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/location/ios" :path: ".symlinks/plugins/location/ios"
maplibre_gl: maplibre_gl:
:path: ".symlinks/plugins/maplibre_gl/ios" :path: ".symlinks/plugins/maplibre_gl/ios"
native_geofence:
:path: ".symlinks/plugins/native_geofence/ios"
package_info_plus: package_info_plus:
:path: ".symlinks/plugins/package_info_plus/ios" :path: ".symlinks/plugins/package_info_plus/ios"
permission_handler_apple: permission_handler_apple:
@@ -278,8 +280,6 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/sensors_plus/ios" :path: ".symlinks/plugins/sensors_plus/ios"
share_plus: share_plus:
:path: ".symlinks/plugins/share_plus/ios" :path: ".symlinks/plugins/share_plus/ios"
sign_in_with_apple:
:path: ".symlinks/plugins/sign_in_with_apple/ios"
sqflite_darwin: sqflite_darwin:
:path: ".symlinks/plugins/sqflite_darwin/darwin" :path: ".symlinks/plugins/sqflite_darwin/darwin"
url_launcher_ios: url_launcher_ios:
@@ -330,6 +330,7 @@ SPEC CHECKSUMS:
MapLibre: 7f24faba45439f80ccb0f83393c29fa32cb81952 MapLibre: 7f24faba45439f80ccb0f83393c29fa32cb81952
maplibre_gl: a2114567cbd1065866614fbd34dfb75ab782aaa2 maplibre_gl: a2114567cbd1065866614fbd34dfb75ab782aaa2
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275 nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
native_geofence: 653ba9ea1aa7ff9b9a62a883b00d8df14d2945f6
package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499 package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
permission_handler_apple: 92d754bbaa7361d436db2d6c3c1c2a0fdcec462e permission_handler_apple: 92d754bbaa7361d436db2d6c3c1c2a0fdcec462e
PromisesObjC: 752c3227f599e3467650e47ea36f433eeb10c273 PromisesObjC: 752c3227f599e3467650e47ea36f433eeb10c273
@@ -338,7 +339,6 @@ SPEC CHECKSUMS:
record_ios: 980fd386a97a35987d0fce3dfda4b26a38c90f4c record_ios: 980fd386a97a35987d0fce3dfda4b26a38c90f4c
sensors_plus: 3c3bac724a2128c895623e03efd82cf0e94fd8e8 sensors_plus: 3c3bac724a2128c895623e03efd82cf0e94fd8e8
share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a
sign_in_with_apple: c5dcc141574c8c54d5ac99dd2163c0c72ad22418
sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0 sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
TOCropViewController: 797deaf39c90e6e9ddd848d88817f6b9a8a09888 TOCropViewController: 797deaf39c90e6e9ddd848d88817f6b9a8a09888
url_launcher_ios: 7a95fa5b60cc718a708b8f2966718e93db0cef1b url_launcher_ios: 7a95fa5b60cc718a708b8f2966718e93db0cef1b
@@ -646,7 +646,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.0; IPHONEOS_DEPLOYMENT_TARGET = 16.1;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos; SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos; SUPPORTED_PLATFORMS = iphoneos;
@@ -667,7 +667,7 @@
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = Siro; INFOPLIST_KEY_CFBundleDisplayName = Siro;
IPHONEOS_DEPLOYMENT_TARGET = 15.6; IPHONEOS_DEPLOYMENT_TARGET = 16.1;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
@@ -782,7 +782,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.0; IPHONEOS_DEPLOYMENT_TARGET = 16.1;
MTL_ENABLE_DEBUG_INFO = YES; MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos; SDKROOT = iphoneos;
@@ -833,7 +833,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.0; IPHONEOS_DEPLOYMENT_TARGET = 16.1;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos; SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos; SUPPORTED_PLATFORMS = iphoneos;
@@ -856,7 +856,7 @@
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = Siro; INFOPLIST_KEY_CFBundleDisplayName = Siro;
IPHONEOS_DEPLOYMENT_TARGET = 15.6; IPHONEOS_DEPLOYMENT_TARGET = 16.1;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
@@ -882,7 +882,7 @@
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = Siro; INFOPLIST_KEY_CFBundleDisplayName = Siro;
IPHONEOS_DEPLOYMENT_TARGET = 15.6; IPHONEOS_DEPLOYMENT_TARGET = 16.1;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
+5 -1
View File
@@ -1,6 +1,7 @@
import UIKit import UIKit
import Flutter import Flutter
import FirebaseCore import FirebaseCore
import native_geofence
@main @main
@objc class AppDelegate: FlutterAppDelegate { @objc class AppDelegate: FlutterAppDelegate {
@@ -10,7 +11,10 @@ import FirebaseCore
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool { ) -> Bool {
// --- 1. تسجيل callback الإضافات للخلفية (مطلوب لـ native_geofence) ---
NativeGeofencePlugin.setPluginRegistrantCallback { registry in
GeneratedPluginRegistrant.register(with: registry)
}
// --- 2. تهيئة Firebase --- // --- 2. تهيئة Firebase ---
FirebaseApp.configure() FirebaseApp.configure()
@@ -1723,4 +1723,34 @@ final Map<String, String> ar_eg = {
"Enter Code (e.g. AB1234)": "أدخل الكود (مثل: AB1234)", "Enter Code (e.g. AB1234)": "أدخل الكود (مثل: AB1234)",
"Link": "ربط", "Link": "ربط",
"Please enter a referral code": "من فضلك أدخل كود الإحالة", "Please enter a referral code": "من فضلك أدخل كود الإحالة",
// ========= Siro Prime =========
"Siro Prime": "سيرو برايم",
"Siro Prime Active": "سيرو برايم نشط",
"No surge pricing. Priority rides. Tap to learn more.": "بدون أسعار ذروة. أولوية في الرحلات. اضغط لمعرفة المزيد.",
"Valid until": "صالح حتى",
"Active until": "نشط حتى",
"What you get with Prime": "ما ستحصل عليه مع برايم",
"No Surge Pricing": "بلا أسعار ذروة",
"Never pay extra during peak hours. Your price stays fixed regardless of demand.": "لن تدفع أكثر في أوقات الذروة. سعرك ثابت بغض النظر عن الطلب.",
"Priority Matching": "أولوية في التطابق",
"Your ride request reaches drivers who have destinations near you first.": "طلب رحلتك يصل أولاً للسائقين المتجهين بالقرب منك.",
"Prime Badge": "شارة برايم",
"Drivers can see your Prime status, making them more likely to accept your request quickly.": "السائقون يرون حالة برايم لديك مما يزيد احتمال قبول طلبك بسرعة.",
"Save Every Ride": "وفّر في كل رحلة",
"During rush hours, surge pricing can add 50–200% to your fare. Prime protects you completely.": "في أوقات الذروة قد ترتفع الأسعار 50-200%. برايم يحميك تماماً.",
"Monthly Subscription": "اشتراك شهري",
"month": "شهر",
"Subscribe Now": "اشترك الآن",
"Already subscribed": "أنت مشترك بالفعل",
"The Premium Ride Experience": "تجربة ركوب مميزة",
"You are a Prime member!": "أنت عضو برايم!",
"You are now a Siro Prime member! Enjoy no surge pricing for 30 days.": "أنت الآن عضو سيرو برايم! استمتع بأسعار بدون ذروة لمدة 30 يوماً.",
"Great!": "رائع!",
"Insufficient Balance": "رصيد غير كافٍ",
"Your current balance": "رصيدك الحالي",
"Required": "المطلوب",
"Please top up your wallet to subscribe to Siro Prime.": "يرجى شحن محفظتك للاشتراك في سيرو برايم.",
"Top Up Wallet": "شحن المحفظة",
"• Subscription renews automatically every 30 days\n• Cancel anytime from your wallet page\n• Amount is deducted from your in-app wallet": "• يتجدد الاشتراك تلقائياً كل 30 يوماً\n• يمكن الإلغاء في أي وقت من صفحة المحفظة\n• يُخصم المبلغ من محفظتك داخل التطبيق",
}; };
@@ -1723,4 +1723,34 @@ final Map<String, String> ar_jo = {
"Enter Code (e.g. AB1234)": "أدخل الرمز (مثال: AB1234)", "Enter Code (e.g. AB1234)": "أدخل الرمز (مثال: AB1234)",
"Link": "ربط", "Link": "ربط",
"Please enter a referral code": "يرجى إدخال رمز الإحالة", "Please enter a referral code": "يرجى إدخال رمز الإحالة",
// ========= Siro Prime =========
"Siro Prime": "سيرو برايم",
"Siro Prime Active": "سيرو برايم نشط",
"No surge pricing. Priority rides. Tap to learn more.": "بدون أسعار ذروة. أولوية في الرحلات. اضغط لمعرفة المزيد.",
"Valid until": "صالح حتى",
"Active until": "نشط حتى",
"What you get with Prime": "ما ستحصل عليه مع برايم",
"No Surge Pricing": "بلا أسعار ذروة",
"Never pay extra during peak hours. Your price stays fixed regardless of demand.": "لن تدفع أكثر في أوقات الذروة. سعرك ثابت بغض النظر عن الطلب.",
"Priority Matching": "أولوية في التطابق",
"Your ride request reaches drivers who have destinations near you first.": "طلب رحلتك يصل أولاً للسائقين المتجهين بالقرب منك.",
"Prime Badge": "شارة برايم",
"Drivers can see your Prime status, making them more likely to accept your request quickly.": "السائقون يرون حالة برايم لديك مما يزيد احتمال قبول طلبك بسرعة.",
"Save Every Ride": "وفّر في كل رحلة",
"During rush hours, surge pricing can add 50–200% to your fare. Prime protects you completely.": "في أوقات الذروة قد ترتفع الأسعار 50-200%. برايم يحميك تماماً.",
"Monthly Subscription": "اشتراك شهري",
"month": "شهر",
"Subscribe Now": "اشترك الآن",
"Already subscribed": "أنت مشترك بالفعل",
"The Premium Ride Experience": "تجربة ركوب مميزة",
"You are a Prime member!": "أنت عضو برايم!",
"You are now a Siro Prime member! Enjoy no surge pricing for 30 days.": "أنت الآن عضو سيرو برايم! استمتع بأسعار بدون ذروة لمدة 30 يوماً.",
"Great!": "رائع!",
"Insufficient Balance": "رصيد غير كافٍ",
"Your current balance": "رصيدك الحالي",
"Required": "المطلوب",
"Please top up your wallet to subscribe to Siro Prime.": "يرجى شحن محفظتك للاشتراك في سيرو برايم.",
"Top Up Wallet": "شحن المحفظة",
"• Subscription renews automatically every 30 days\n• Cancel anytime from your wallet page\n• Amount is deducted from your in-app wallet": "• يتجدد الاشتراك تلقائياً كل 30 يوماً\n• يمكن الإلغاء في أي وقت من صفحة المحفظة\n• يُخصم المبلغ من محفظتك داخل التطبيق",
}; };
@@ -1723,4 +1723,34 @@ final Map<String, String> ar_sy = {
"Enter Code (e.g. AB1234)": "دخل الرمز (مثال: AB1234)", "Enter Code (e.g. AB1234)": "دخل الرمز (مثال: AB1234)",
"Link": "ربط", "Link": "ربط",
"Please enter a referral code": "دخل رمز الإحالة", "Please enter a referral code": "دخل رمز الإحالة",
// ========= Siro Prime =========
"Siro Prime": "سيرو برايم",
"Siro Prime Active": "سيرو برايم نشط",
"No surge pricing. Priority rides. Tap to learn more.": "بدون أسعار ذروة. أولوية في الرحلات. اضغط لمعرفة المزيد.",
"Valid until": "صالح حتى",
"Active until": "نشط حتى",
"What you get with Prime": "ما ستحصل عليه مع برايم",
"No Surge Pricing": "بلا أسعار ذروة",
"Never pay extra during peak hours. Your price stays fixed regardless of demand.": "لن تدفع أكثر في أوقات الذروة. سعرك ثابت بغض النظر عن الطلب.",
"Priority Matching": "أولوية في التطابق",
"Your ride request reaches drivers who have destinations near you first.": "طلب رحلتك يصل أولاً للسائقين المتجهين بالقرب منك.",
"Prime Badge": "شارة برايم",
"Drivers can see your Prime status, making them more likely to accept your request quickly.": "السائقون يرون حالة برايم لديك مما يزيد احتمال قبول طلبك بسرعة.",
"Save Every Ride": "وفّر في كل رحلة",
"During rush hours, surge pricing can add 50–200% to your fare. Prime protects you completely.": "في أوقات الذروة قد ترتفع الأسعار 50-200%. برايم يحميك تماماً.",
"Monthly Subscription": "اشتراك شهري",
"month": "شهر",
"Subscribe Now": "اشترك الآن",
"Already subscribed": "أنت مشترك بالفعل",
"The Premium Ride Experience": "تجربة ركوب مميزة",
"You are a Prime member!": "أنت عضو برايم!",
"You are now a Siro Prime member! Enjoy no surge pricing for 30 days.": "أنت الآن عضو سيرو برايم! استمتع بأسعار بدون ذروة لمدة 30 يوماً.",
"Great!": "رائع!",
"Insufficient Balance": "رصيد غير كافٍ",
"Your current balance": "رصيدك الحالي",
"Required": "المطلوب",
"Please top up your wallet to subscribe to Siro Prime.": "يرجى شحن محفظتك للاشتراك في سيرو برايم.",
"Top Up Wallet": "شحن المحفظة",
"• Subscription renews automatically every 30 days\n• Cancel anytime from your wallet page\n• Amount is deducted from your in-app wallet": "• يتجدد الاشتراك تلقائياً كل 30 يوماً\n• يمكن الإلغاء في أي وقت من صفحة المحفظة\n• يُخصم المبلغ من محفظتك داخل التطبيق",
}; };
@@ -1,6 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:siro_rider/constant/box_name.dart'; import 'package:siro_rider/constant/box_name.dart';
import 'package:siro_rider/constant/colors.dart';
import 'package:siro_rider/constant/style.dart';
import 'package:siro_rider/controller/payment/prime_controller.dart'; import 'package:siro_rider/controller/payment/prime_controller.dart';
import 'package:siro_rider/main.dart'; import 'package:siro_rider/main.dart';
import 'dart:math' as math; import 'dart:math' as math;
@@ -20,6 +22,10 @@ class _SiroPrimePageState extends State<SiroPrimePage>
final PrimeController ctrl = Get.find<PrimeController>(); final PrimeController ctrl = Get.find<PrimeController>();
// ── Brand gradient (ثابتة — Prime هوية مستقلة ضمن التطبيق) ──────
static const _primeGradient = [Color(0xFF7C3AED), Color(0xFFDB2777)];
static const _primeGradientStart = Color(0xFF7C3AED);
@override @override
void initState() { void initState() {
super.initState(); super.initState();
@@ -47,97 +53,113 @@ class _SiroPrimePageState extends State<SiroPrimePage>
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
// ── الخلفية تتكيف مع وضع التطبيق ────────────────────────────
final bool isDark = Get.isDarkMode;
final bgColor = isDark ? const Color(0xFF0D0D1A) : const Color(0xFFF0EFFA);
final surfaceColor = isDark ? const Color(0xFF1A1A2E) : Colors.white;
return Scaffold( return Scaffold(
backgroundColor: const Color(0xFF0D0D1A), backgroundColor: bgColor,
body: CustomScrollView( body: CustomScrollView(
slivers: [ slivers: [
// ─── Animated Header ──────────────────────────────────── // ─── SliverAppBar ────────────────────────────────────────
SliverAppBar( SliverAppBar(
expandedHeight: 280, expandedHeight: 270,
backgroundColor: Colors.transparent, backgroundColor:
isDark ? const Color(0xFF0D0D1A) : const Color(0xFFF0EFFA),
elevation: 0, elevation: 0,
pinned: true, pinned: true,
leading: IconButton( leading: IconButton(
icon: const Icon(Icons.arrow_back_ios_new, color: Colors.white), icon: Icon(Icons.arrow_back_ios_new,
color: isDark ? Colors.white : AppColor.primaryColor),
onPressed: () => Get.back(), onPressed: () => Get.back(),
), ),
flexibleSpace: FlexibleSpaceBar( flexibleSpace: FlexibleSpaceBar(
background: _buildHeader(), background: _buildHeader(isDark),
), ),
), ),
// ─── Content ───────────────────────────────────────────── // ─── Body ────────────────────────────────────────────────
SliverToBoxAdapter( SliverToBoxAdapter(
child: Padding( child: Padding(
padding: const EdgeInsets.all(20), padding: const EdgeInsets.symmetric(horizontal: 20),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
children: [ children: [
// Status Card const SizedBox(height: 4),
_buildStatusCard(), _buildStatusCard(surfaceColor, isDark),
const SizedBox(height: 28), const SizedBox(height: 24),
// Benefits Title // Benefits title
Text( Text(
'What you get with Prime'.tr, 'What you get with Prime'.tr,
style: const TextStyle( style: AppStyle.title.copyWith(
color: Colors.white, color: AppColor.writeColor,
fontSize: 20, fontSize: 18,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
), ),
const SizedBox(height: 16), const SizedBox(height: 14),
// Benefits List
_buildBenefit( _buildBenefit(
icon: '🚫', icon: '🚫',
title: 'No Surge Pricing'.tr, title: 'No Surge Pricing'.tr,
subtitle: 'Never pay extra during peak hours. Your price stays fixed regardless of demand.'.tr, subtitle:
gradient: [const Color(0xFF7C3AED), const Color(0xFF4F46E5)], 'Never pay extra during peak hours. Your price stays fixed regardless of demand.'
.tr,
gradient: const [Color(0xFF7C3AED), Color(0xFF4F46E5)],
surfaceColor: surfaceColor,
isDark: isDark,
), ),
_buildBenefit( _buildBenefit(
icon: '⚡', icon: '⚡',
title: 'Priority Matching'.tr, title: 'Priority Matching'.tr,
subtitle: 'Your ride request reaches drivers who have destinations near you first.'.tr, subtitle:
gradient: [const Color(0xFFDB2777), const Color(0xFF9333EA)], 'Your ride request reaches drivers who have destinations near you first.'
.tr,
gradient: const [Color(0xFFDB2777), Color(0xFF9333EA)],
surfaceColor: surfaceColor,
isDark: isDark,
), ),
_buildBenefit( _buildBenefit(
icon: '👑', icon: '👑',
title: 'Prime Badge'.tr, title: 'Prime Badge'.tr,
subtitle: 'Drivers can see your Prime status, making them more likely to accept your request quickly.'.tr, subtitle:
gradient: [const Color(0xFFD97706), const Color(0xFFEF4444)], 'Drivers can see your Prime status, making them more likely to accept your request quickly.'
.tr,
gradient: const [Color(0xFFD97706), Color(0xFFEF4444)],
surfaceColor: surfaceColor,
isDark: isDark,
), ),
_buildBenefit( _buildBenefit(
icon: '💰', icon: '💰',
title: 'Save Every Ride'.tr, title: 'Save Every Ride'.tr,
subtitle: 'During rush hours, surge pricing can add 50–200% to your fare. Prime protects you completely.'.tr, subtitle:
gradient: [const Color(0xFF059669), const Color(0xFF0891B2)], 'During rush hours, surge pricing can add 50–200% to your fare. Prime protects you completely.'
.tr,
gradient: const [Color(0xFF059669), Color(0xFF0891B2)],
surfaceColor: surfaceColor,
isDark: isDark,
), ),
const SizedBox(height: 32), const SizedBox(height: 28),
_buildPriceCard(surfaceColor, isDark),
// Price Card
_buildPriceCard(),
const SizedBox(height: 16), const SizedBox(height: 16),
// Subscribe Button
_buildSubscribeButton(), _buildSubscribeButton(),
const SizedBox(height: 20),
const SizedBox(height: 24), // Fine print
// Fine Print
Text( Text(
'• Subscription renews automatically every 30 days\n• Cancel anytime from your wallet page\n• Amount is deducted from your in-app wallet'.tr, '• Subscription renews automatically every 30 days\n• Cancel anytime from your wallet page\n• Amount is deducted from your in-app wallet'
.tr,
style: TextStyle( style: TextStyle(
color: Colors.white.withOpacity(0.4), color: AppColor.grayColor,
fontSize: 12, fontSize: 11,
height: 1.8, height: 1.8,
), ),
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
const SizedBox(height: 36),
const SizedBox(height: 40),
], ],
), ),
), ),
@@ -147,15 +169,17 @@ class _SiroPrimePageState extends State<SiroPrimePage>
); );
} }
// ─── Header ────────────────────────────────────────────────── // ─── Header ───────────────────────────────────────────────────────
Widget _buildHeader() { Widget _buildHeader(bool isDark) {
return AnimatedBuilder( return AnimatedBuilder(
animation: _shimmerController, animation: _shimmerController,
builder: (context, child) { builder: (context, child) {
return Container( return Container(
decoration: const BoxDecoration( decoration: BoxDecoration(
gradient: LinearGradient( gradient: LinearGradient(
colors: [Color(0xFF1A0A2E), Color(0xFF0D0D1A)], colors: isDark
? [const Color(0xFF1A0A2E), const Color(0xFF0D0D1A)]
: [const Color(0xFFEDE9FE), const Color(0xFFF0EFFA)],
begin: Alignment.topCenter, begin: Alignment.topCenter,
end: Alignment.bottomCenter, end: Alignment.bottomCenter,
), ),
@@ -163,10 +187,7 @@ class _SiroPrimePageState extends State<SiroPrimePage>
child: Stack( child: Stack(
alignment: Alignment.center, alignment: Alignment.center,
children: [ children: [
// Background particles ..._buildParticles(isDark),
..._buildParticles(),
// Crown + Title
Column( Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
@@ -174,47 +195,53 @@ class _SiroPrimePageState extends State<SiroPrimePage>
ScaleTransition( ScaleTransition(
scale: _pulseAnimation, scale: _pulseAnimation,
child: Container( child: Container(
width: 90, width: 88,
height: 90, height: 88,
decoration: BoxDecoration( decoration: BoxDecoration(
shape: BoxShape.circle, shape: BoxShape.circle,
gradient: const LinearGradient( gradient: const LinearGradient(
colors: [Color(0xFF7C3AED), Color(0xFFDB2777)], colors: _primeGradient,
), ),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: const Color(0xFF7C3AED).withOpacity(0.6), color: _primeGradientStart.withOpacity(0.5),
blurRadius: 30, blurRadius: 28,
spreadRadius: 5, spreadRadius: 4,
), ),
], ],
), ),
child: const Center( child: const Center(
child: Text('👑', style: TextStyle(fontSize: 44)), child: Text('👑', style: TextStyle(fontSize: 42)),
), ),
), ),
), ),
const SizedBox(height: 16), const SizedBox(height: 14),
ShaderMask( ShaderMask(
shaderCallback: (bounds) => const LinearGradient( shaderCallback: (bounds) => const LinearGradient(
colors: [Color(0xFFE879F9), Color(0xFF818CF8), Color(0xFFF59E0B)], colors: [
Color(0xFFE879F9),
Color(0xFF818CF8),
Color(0xFFF59E0B)
],
).createShader(bounds), ).createShader(bounds),
child: const Text( child: const Text(
'SIRO PRIME', 'SIRO PRIME',
style: TextStyle( style: TextStyle(
fontSize: 32, fontSize: 30,
fontWeight: FontWeight.w900, fontWeight: FontWeight.w900,
color: Colors.white, color: Colors.white,
letterSpacing: 4, letterSpacing: 4,
), ),
), ),
), ),
const SizedBox(height: 8), const SizedBox(height: 6),
Text( Text(
'The Premium Ride Experience'.tr, 'The Premium Ride Experience'.tr,
style: TextStyle( style: TextStyle(
color: Colors.white.withOpacity(0.6), color: isDark
fontSize: 14, ? Colors.white.withOpacity(0.55)
: AppColor.primaryColor.withOpacity(0.6),
fontSize: 13,
), ),
), ),
], ],
@@ -226,23 +253,23 @@ class _SiroPrimePageState extends State<SiroPrimePage>
); );
} }
List<Widget> _buildParticles() { List<Widget> _buildParticles(bool isDark) {
return List.generate(8, (i) { return List.generate(8, (i) {
final angle = (i / 8) * 2 * math.pi; final angle = (i / 8) * 2 * math.pi;
final radius = 120.0 + (i % 3) * 30; final radius = 110.0 + (i % 3) * 28;
final size = 3.0 + (i % 4).toDouble(); final size = 3.0 + (i % 4).toDouble();
final opacity = final opacity =
(0.1 + (_shimmerController.value + i / 8) % 1.0 * 0.5).clamp(0.0, 0.6); (0.08 + (_shimmerController.value + i / 8) % 1.0 * 0.4).clamp(0.0, 0.5);
return Positioned( return Positioned(
left: MediaQuery.of(context).size.width / 2 + math.cos(angle) * radius - 5, left: MediaQuery.of(context).size.width / 2 + math.cos(angle) * radius - 5,
top: 140 + math.sin(angle) * 80, top: 130 + math.sin(angle) * 75,
child: Opacity( child: Opacity(
opacity: opacity, opacity: opacity,
child: Container( child: Container(
width: size, width: size,
height: size, height: size,
decoration: const BoxDecoration( decoration: BoxDecoration(
color: Color(0xFFE879F9), color: isDark ? const Color(0xFFE879F9) : _primeGradientStart,
shape: BoxShape.circle, shape: BoxShape.circle,
), ),
), ),
@@ -251,8 +278,8 @@ class _SiroPrimePageState extends State<SiroPrimePage>
}); });
} }
// ─── Status Card ────────────────────────────────────────────── // ─── Status Card ──────────────────────────────────────────────────
Widget _buildStatusCard() { Widget _buildStatusCard(Color surfaceColor, bool isDark) {
return GetBuilder<PrimeController>( return GetBuilder<PrimeController>(
builder: (c) { builder: (c) {
if (!c.isPrime) return const SizedBox.shrink(); if (!c.isPrime) return const SizedBox.shrink();
@@ -260,27 +287,37 @@ class _SiroPrimePageState extends State<SiroPrimePage>
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
gradient: const LinearGradient( gradient: const LinearGradient(colors: _primeGradient),
colors: [Color(0xFF7C3AED), Color(0xFFDB2777)], boxShadow: [
), BoxShadow(
color: _primeGradientStart.withOpacity(0.3),
blurRadius: 16,
offset: const Offset(0, 6),
)
],
), ),
child: Row( child: Row(
children: [ children: [
const Icon(Icons.verified, color: Colors.white, size: 28), const Icon(Icons.verified, color: Colors.white, size: 26),
const SizedBox(width: 12), const SizedBox(width: 12),
Column( Expanded(
crossAxisAlignment: CrossAxisAlignment.start, child: Column(
children: [ crossAxisAlignment: CrossAxisAlignment.start,
Text('You are a Prime member!'.tr, children: [
style: const TextStyle( Text('You are a Prime member!'.tr,
color: Colors.white, fontWeight: FontWeight.bold)), style: const TextStyle(
if (c.expireAt != null) color: Colors.white,
Text( fontWeight: FontWeight.bold,
'${'Active until'.tr}: ${c.expireAt!.substring(0, 10)}', fontSize: 14)),
style: TextStyle( if (c.expireAt != null)
color: Colors.white.withOpacity(0.8), fontSize: 12), Text(
), '${'Active until'.tr}: ${c.expireAt!.substring(0, 10)}',
], style: TextStyle(
color: Colors.white.withOpacity(0.8),
fontSize: 12),
),
],
),
), ),
], ],
), ),
@@ -289,33 +326,42 @@ class _SiroPrimePageState extends State<SiroPrimePage>
); );
} }
// ─── Benefit Card ──────────────────────────────────────────── // ─── Benefit Card ─────────────────────────────────────────────────
Widget _buildBenefit({ Widget _buildBenefit({
required String icon, required String icon,
required String title, required String title,
required String subtitle, required String subtitle,
required List<Color> gradient, required List<Color> gradient,
required Color surfaceColor,
required bool isDark,
}) { }) {
return Container( return Container(
margin: const EdgeInsets.only(bottom: 12), margin: const EdgeInsets.only(bottom: 10),
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
color: Colors.white.withOpacity(0.05), color: surfaceColor,
border: Border.all(color: Colors.white.withOpacity(0.08)), border: Border.all(color: AppColor.borderColor),
boxShadow: [
if (!isDark)
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 8,
offset: const Offset(0, 3))
],
), ),
child: Row( child: Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Container( Container(
width: 48, width: 46,
height: 48, height: 46,
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
gradient: LinearGradient(colors: gradient), gradient: LinearGradient(colors: gradient),
), ),
child: Center( child: Center(
child: Text(icon, style: const TextStyle(fontSize: 22)), child: Text(icon, style: const TextStyle(fontSize: 21)),
), ),
), ),
const SizedBox(width: 14), const SizedBox(width: 14),
@@ -324,14 +370,16 @@ class _SiroPrimePageState extends State<SiroPrimePage>
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text(title, Text(title,
style: const TextStyle( style: AppStyle.title.copyWith(
color: Colors.white, color: AppColor.writeColor,
fontWeight: FontWeight.w600, fontSize: 14,
fontSize: 15)), fontWeight: FontWeight.w700)),
const SizedBox(height: 4), const SizedBox(height: 4),
Text(subtitle, Text(subtitle,
style: TextStyle( style: TextStyle(
color: Colors.white.withOpacity(0.55), fontSize: 13, height: 1.5)), color: AppColor.grayColor,
fontSize: 12,
height: 1.5)),
], ],
), ),
), ),
@@ -340,10 +388,10 @@ class _SiroPrimePageState extends State<SiroPrimePage>
); );
} }
// ─── Price Card ─────────────────────────────────────────────── // ─── Price Card ───────────────────────────────────────────────────
Widget _buildPriceCard() { Widget _buildPriceCard(Color surfaceColor, bool isDark) {
final country = box.read(BoxName.countryCode) ?? 'Jordan'; final country = box.read(BoxName.countryCode) ?? 'Jordan';
final pricing = { const pricing = {
'Jordan': {'price': '3', 'currency': 'JOD'}, 'Jordan': {'price': '3', 'currency': 'JOD'},
'Egypt': {'price': '200', 'currency': 'EGP'}, 'Egypt': {'price': '200', 'currency': 'EGP'},
'Syria': {'price': '500', 'currency': 'SYP'}, 'Syria': {'price': '500', 'currency': 'SYP'},
@@ -354,13 +402,22 @@ class _SiroPrimePageState extends State<SiroPrimePage>
padding: const EdgeInsets.symmetric(vertical: 24, horizontal: 20), padding: const EdgeInsets.symmetric(vertical: 24, horizontal: 20),
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20), borderRadius: BorderRadius.circular(20),
border: Border.all(color: const Color(0xFF7C3AED).withOpacity(0.4), width: 1.5), color: surfaceColor,
color: const Color(0xFF7C3AED).withOpacity(0.08), border: Border.all(
color: _primeGradientStart.withOpacity(isDark ? 0.4 : 0.25),
width: 1.5),
boxShadow: [
if (!isDark)
BoxShadow(
color: _primeGradientStart.withOpacity(0.08),
blurRadius: 16,
offset: const Offset(0, 6))
],
), ),
child: Column( child: Column(
children: [ children: [
Text('Monthly Subscription'.tr, Text('Monthly Subscription'.tr,
style: TextStyle(color: Colors.white.withOpacity(0.6), fontSize: 13)), style: TextStyle(color: AppColor.grayColor, fontSize: 12)),
const SizedBox(height: 8), const SizedBox(height: 8),
Row( Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
@@ -368,11 +425,10 @@ class _SiroPrimePageState extends State<SiroPrimePage>
children: [ children: [
Text( Text(
p['price']!, p['price']!,
style: const TextStyle( style: TextStyle(
color: Colors.white, color: AppColor.writeColor,
fontSize: 48, fontSize: 46,
fontWeight: FontWeight.w900, fontWeight: FontWeight.w900),
),
), ),
const SizedBox(width: 6), const SizedBox(width: 6),
Padding( Padding(
@@ -380,59 +436,63 @@ class _SiroPrimePageState extends State<SiroPrimePage>
child: Text( child: Text(
p['currency']!, p['currency']!,
style: const TextStyle( style: const TextStyle(
color: Color(0xFFE879F9), color: Color(0xFF7C3AED),
fontSize: 18, fontSize: 17,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold),
),
), ),
), ),
], ],
), ),
Text( Text('≈ \$4 USD / ${'month'.tr}',
'≈ \$4 USD / ${'month'.tr}', style: TextStyle(color: AppColor.grayColor, fontSize: 11)),
style: TextStyle(color: Colors.white.withOpacity(0.4), fontSize: 12),
),
], ],
), ),
); );
} }
// ─── Subscribe Button ───────────────────────────────────────── // ─── Subscribe Button ─────────────────────────────────────────────
Widget _buildSubscribeButton() { Widget _buildSubscribeButton() {
return GetBuilder<PrimeController>( return GetBuilder<PrimeController>(
builder: (c) { builder: (c) {
// Already subscribed state
if (c.isPrime) { if (c.isPrime) {
return Container( return Container(
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
color: Colors.green.withOpacity(0.15), color: AppColor.greenColor.withOpacity(0.1),
border: Border.all(color: Colors.green.withOpacity(0.4)), border: Border.all(color: AppColor.greenColor.withOpacity(0.4)),
), ),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
const Icon(Icons.check_circle, color: Colors.green), const Icon(Icons.check_circle, color: AppColor.greenColor),
const SizedBox(width: 8), const SizedBox(width: 8),
Text('Already subscribed'.tr, Text('Already subscribed'.tr,
style: const TextStyle( style: const TextStyle(
color: Colors.green, fontWeight: FontWeight.bold)), color: AppColor.greenColor,
fontWeight: FontWeight.bold)),
], ],
), ),
); );
} }
// Subscribe button with animated gradient
return GestureDetector( return GestureDetector(
onTap: c.isLoading ? null : () => c.subscribePrime(context), onTap: c.isLoading ? null : () => c.subscribePrime(context),
child: AnimatedBuilder( child: AnimatedBuilder(
animation: _shimmerController, animation: _shimmerController,
builder: (context, child) { builder: (context, child) {
return Container( return Container(
height: 56, height: 54,
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
gradient: LinearGradient( gradient: LinearGradient(
colors: const [Color(0xFF7C3AED), Color(0xFFDB2777), Color(0xFFD97706)], colors: const [
Color(0xFF7C3AED),
Color(0xFFDB2777),
Color(0xFFD97706),
],
stops: [ stops: [
0, 0,
(_shimmerController.value + 0.5) % 1.0, (_shimmerController.value + 0.5) % 1.0,
@@ -441,8 +501,8 @@ class _SiroPrimePageState extends State<SiroPrimePage>
), ),
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: const Color(0xFF7C3AED).withOpacity(0.5), color: _primeGradientStart.withOpacity(0.4),
blurRadius: 20, blurRadius: 18,
offset: const Offset(0, 8), offset: const Offset(0, 8),
), ),
], ],
@@ -450,24 +510,23 @@ class _SiroPrimePageState extends State<SiroPrimePage>
child: Center( child: Center(
child: c.isLoading child: c.isLoading
? const SizedBox( ? const SizedBox(
width: 24, width: 22,
height: 24, height: 22,
child: CircularProgressIndicator( child: CircularProgressIndicator(
color: Colors.white, strokeWidth: 2), color: Colors.white, strokeWidth: 2),
) )
: Row( : Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
const Text('👑', style: TextStyle(fontSize: 20)), const Text('👑', style: TextStyle(fontSize: 19)),
const SizedBox(width: 8), const SizedBox(width: 8),
Text( Text(
'Subscribe Now'.tr, 'Subscribe Now'.tr,
style: const TextStyle( style: const TextStyle(
color: Colors.white, color: Colors.white,
fontSize: 17, fontSize: 16,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
letterSpacing: 0.5, letterSpacing: 0.5),
),
), ),
], ],
), ),