Update: 2026-08-02 17:52:28
This commit is contained in:
@@ -229,7 +229,7 @@ class InviteScreen extends StatelessWidget {
|
||||
final appName = 'Siro';
|
||||
final isDriver = controller.selectedTab == 0;
|
||||
final shareText = isDriver
|
||||
? 'Join $appName as a driver! Use my referral code: ${rc.referralCode}\nDownload: ${AppLink.inviteRedirectUrl}?code=${rc.referralCode}&app=driver\n\n💡 Note: If the link is not clickable, save this number or reply to activate links!'
|
||||
? 'Join $appName as a driver! Use my referral code: ${rc.referralCode}\n${AppLink.driverDownloadLinks}\n\n💡 Note: If the link is not clickable, save this number or reply to activate links!'
|
||||
: 'Get a ride with $appName! Use my referral code: ${rc.referralCode} for a discount.\nDownload: ${AppLink.inviteRedirectUrl}?code=${rc.referralCode}&app=rider\n\n💡 Note: If the link is not clickable, save this number or reply to activate links!';
|
||||
Share.share(shareText);
|
||||
},
|
||||
|
||||
@@ -0,0 +1,235 @@
|
||||
// food_delivery_home_page.dart — تبويب التوصيل: تفعيل وضع التوصيل، عروض واردة، مهام نشطة
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import '../../constant/colors.dart';
|
||||
import '../../constant/style.dart';
|
||||
import '../../controller/food_delivery/food_delivery_controller.dart';
|
||||
import '../../controller/food_delivery/food_delivery_models.dart';
|
||||
import '../widgets/elevated_btn.dart';
|
||||
import '../widgets/my_scafold.dart';
|
||||
|
||||
class FoodDeliveryHomePage extends StatelessWidget {
|
||||
const FoodDeliveryHomePage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Get.put(FoodDeliveryController());
|
||||
|
||||
return GetBuilder<FoodDeliveryController>(
|
||||
builder: (c) => MyScafolld(
|
||||
title: 'Delivery'.tr,
|
||||
isleading: true,
|
||||
body: [
|
||||
Column(
|
||||
children: [
|
||||
_modeToggleBar(c),
|
||||
if (c.pendingOffers.isNotEmpty) _offersSection(c),
|
||||
Expanded(
|
||||
child: RefreshIndicator(
|
||||
onRefresh: c.fetchActiveTasks,
|
||||
child: c.isLoadingTasks && c.activeTasks.isEmpty
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: c.activeTasks.isEmpty
|
||||
? _emptyState(c)
|
||||
: ListView.builder(
|
||||
padding: const EdgeInsets.all(16),
|
||||
itemCount: c.activeTasks.length,
|
||||
itemBuilder: (_, i) => _taskCard(c, c.activeTasks[i]),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _modeToggleBar(FoodDeliveryController c) {
|
||||
return Container(
|
||||
margin: const EdgeInsets.all(16),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColor.cardColor,
|
||||
borderRadius: BorderRadius.circular(14),
|
||||
border: Border.all(color: AppColor.borderColor),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(
|
||||
c.isDeliveryModeEnabled ? Icons.delivery_dining_rounded : Icons.moped_outlined,
|
||||
color: c.isDeliveryModeEnabled ? AppColor.greenColor : AppColor.grayColor,
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text('Delivery Mode'.tr, style: AppStyle.title.copyWith(fontWeight: FontWeight.bold)),
|
||||
Text(
|
||||
c.isDeliveryModeEnabled
|
||||
? 'You will receive delivery offers'.tr
|
||||
: 'Turn on to receive delivery offers'.tr,
|
||||
style: AppStyle.subtitle,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
c.isTogglingMode
|
||||
? const SizedBox(width: 24, height: 24, child: CircularProgressIndicator(strokeWidth: 2))
|
||||
: Switch(
|
||||
value: c.isDeliveryModeEnabled,
|
||||
activeColor: AppColor.greenColor,
|
||||
onChanged: (v) => c.toggleDeliveryMode(v),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _offersSection(FoodDeliveryController c) {
|
||||
return SizedBox(
|
||||
height: 150,
|
||||
child: ListView.builder(
|
||||
scrollDirection: Axis.horizontal,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
itemCount: c.pendingOffers.length,
|
||||
itemBuilder: (_, i) => _offerCard(c, c.pendingOffers[i]),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _offerCard(FoodDeliveryController c, FoodDeliveryOffer offer) {
|
||||
final isResponding = c.isRespondingToOffer(offer.orderId);
|
||||
return Container(
|
||||
width: 260,
|
||||
margin: const EdgeInsets.symmetric(horizontal: 4),
|
||||
padding: const EdgeInsets.all(14),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColor.primaryColor,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.15), blurRadius: 12, offset: const Offset(0, 4))],
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
const Icon(Icons.notifications_active_rounded, color: Colors.white, size: 18),
|
||||
const SizedBox(width: 6),
|
||||
Expanded(
|
||||
child: Text('New Delivery Offer'.tr,
|
||||
style: const TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: 13)),
|
||||
),
|
||||
Text('${offer.secondsRemaining}s', style: const TextStyle(color: Colors.amber, fontWeight: FontWeight.bold)),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
Text(offer.merchantNameAr,
|
||||
style: const TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: 15),
|
||||
maxLines: 1, overflow: TextOverflow.ellipsis),
|
||||
Text(foodFormatPrice(offer.deliveryFee),
|
||||
style: const TextStyle(color: Colors.white70, fontSize: 13)),
|
||||
const Spacer(),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: SizedBox(
|
||||
height: 36,
|
||||
child: isResponding
|
||||
? const Center(child: SizedBox(width: 18, height: 18, child: CircularProgressIndicator(strokeWidth: 2, color: Colors.white)))
|
||||
: OutlinedButton(
|
||||
style: OutlinedButton.styleFrom(side: const BorderSide(color: Colors.white54)),
|
||||
onPressed: () => c.respondToOffer(offer.orderId, false),
|
||||
child: Text('Reject'.tr, style: const TextStyle(color: Colors.white70, fontSize: 12)),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: SizedBox(
|
||||
height: 36,
|
||||
child: isResponding
|
||||
? const SizedBox.shrink()
|
||||
: MyElevatedButton(
|
||||
title: 'Accept'.tr,
|
||||
kolor: AppColor.greenColor,
|
||||
onPressed: () => c.respondToOffer(offer.orderId, true),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _emptyState(FoodDeliveryController c) {
|
||||
return ListView(
|
||||
children: [
|
||||
const SizedBox(height: 100),
|
||||
Icon(Icons.moped_outlined, size: 72, color: AppColor.grayColor),
|
||||
const SizedBox(height: 16),
|
||||
Center(child: Text('No delivery tasks right now'.tr, style: AppStyle.title)),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _taskCard(FoodDeliveryController c, FoodDeliveryTask task) {
|
||||
final isPickedUp = task.status == 'picked_up';
|
||||
final isBusy = c.isTaskBusy(task.id);
|
||||
|
||||
return Card(
|
||||
margin: const EdgeInsets.only(bottom: 14),
|
||||
color: AppColor.cardColor,
|
||||
elevation: 0,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(14),
|
||||
side: BorderSide(color: isPickedUp ? AppColor.greenColor : AppColor.borderColor, width: isPickedUp ? 1.5 : 1),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(14),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Icon(isPickedUp ? Icons.location_on_rounded : Icons.storefront_rounded,
|
||||
color: AppColor.accentColor),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Text(
|
||||
isPickedUp ? (task.deliveryAddress ?? '') : task.merchantNameAr,
|
||||
style: AppStyle.title.copyWith(fontWeight: FontWeight.bold),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
Text(foodFormatPrice(task.deliveryFee), style: AppStyle.subtitle),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
isPickedUp ? 'Deliver to customer'.tr : (task.merchantAddress ?? ''),
|
||||
style: AppStyle.subtitle,
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
height: 44,
|
||||
child: isBusy
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: MyElevatedButton(
|
||||
title: isPickedUp ? 'Mark Delivered'.tr : 'Picked Up from Restaurant'.tr,
|
||||
kolor: isPickedUp ? AppColor.greenColor : AppColor.accentColor,
|
||||
onPressed: () => isPickedUp ? c.markDelivered(task.id) : c.markPickedUp(task.id),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -33,6 +33,7 @@ import '../About Us/video_page.dart';
|
||||
import '../assurance_health_page.dart';
|
||||
import '../maintain_center_page.dart';
|
||||
import '../../../transit/transit_driver_home_page.dart';
|
||||
import '../../../food_delivery/food_delivery_home_page.dart';
|
||||
|
||||
// 1. إنشاء Class لتعريف بيانات كل عنصر في القائمة
|
||||
class DrawerItem {
|
||||
@@ -61,6 +62,11 @@ class AppDrawer extends StatelessWidget {
|
||||
// icon: Icons.directions_bus_filled_rounded,
|
||||
// color: Colors.teal,
|
||||
// onTap: () => Get.to(() => const TransitDriverHomePage())),
|
||||
DrawerItem(
|
||||
title: 'Delivery'.tr,
|
||||
icon: Icons.delivery_dining_rounded,
|
||||
color: Colors.deepOrange,
|
||||
onTap: () => Get.to(() => const FoodDeliveryHomePage())),
|
||||
DrawerItem(
|
||||
title: 'Balance'.tr,
|
||||
icon: Icons.account_balance_wallet,
|
||||
|
||||
Reference in New Issue
Block a user