207 lines
7.8 KiB
Dart
207 lines
7.8 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter/services.dart';
|
|
import 'package:get/get.dart';
|
|
import 'package:Intaleq/controller/home/profile/promos_controller.dart';
|
|
import 'package:Intaleq/views/widgets/my_scafold.dart';
|
|
import 'dart:ui'; // لاستخدامه في الفاصل
|
|
|
|
import '../../../constant/colors.dart';
|
|
import '../../../constant/style.dart';
|
|
import '../../widgets/mycircular.dart';
|
|
import 'package:dotted_line/dotted_line.dart'; // ستحتاج لإضافة هذا الباكج
|
|
|
|
// ملاحظة: ستحتاج لإضافة هذا الباكج إلى ملف pubspec.yaml الخاص بك
|
|
// flutter pub add dotted_line
|
|
|
|
// --- الويدجت الرئيسية بالتصميم الجديد ---
|
|
class PromosPassengerPage extends StatelessWidget {
|
|
const PromosPassengerPage({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
Get.put(PromosController()); // نفس منطقك القديم
|
|
return MyScafolld(
|
|
title: "Today's Promos".tr, // عنوان أكثر جاذبية
|
|
isleading: true,
|
|
body: [
|
|
GetBuilder<PromosController>(
|
|
builder: (controller) {
|
|
if (controller.isLoading) {
|
|
return const MyCircularProgressIndicator();
|
|
}
|
|
if (controller.promoList.isEmpty) {
|
|
return Center(
|
|
child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
const Icon(Icons.local_offer_outlined,
|
|
size: 80, color: Colors.grey),
|
|
const SizedBox(height: 16),
|
|
Text("No promos available right now.".tr,
|
|
style: AppStyle.headTitle2),
|
|
Text("Check back later for new offers!".tr,
|
|
style: AppStyle.subtitle),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
return ListView.builder(
|
|
padding: const EdgeInsets.all(16.0),
|
|
itemCount: controller.promoList.length,
|
|
itemBuilder: (BuildContext context, int index) {
|
|
final promo = controller.promoList[index];
|
|
// --- استدعاء ويدجت الكوبون الجديدة ---
|
|
return _buildPromoTicket(context, promo);
|
|
},
|
|
);
|
|
},
|
|
)
|
|
],
|
|
);
|
|
}
|
|
|
|
// --- ويدجت بناء كوبون الخصم ---
|
|
Widget _buildPromoTicket(BuildContext context, Map<String, dynamic> promo) {
|
|
return Padding(
|
|
padding: const EdgeInsets.only(bottom: 20.0),
|
|
child: Container(
|
|
height: 140, // ارتفاع ثابت للكوبون
|
|
decoration: BoxDecoration(
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.black.withOpacity(0.15),
|
|
blurRadius: 12,
|
|
offset: const Offset(0, 6),
|
|
),
|
|
],
|
|
),
|
|
child: ClipPath(
|
|
clipper: TicketClipper(), // Clipper مخصص لرسم شكل التذكرة
|
|
child: Container(
|
|
color: AppColor.secondaryColor,
|
|
child: Row(
|
|
children: [
|
|
// --- الجزء الأيسر: تفاصيل العرض ---
|
|
Expanded(
|
|
flex: 3,
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(16.0),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
Text(
|
|
promo['description'],
|
|
style: AppStyle.headTitle.copyWith(fontSize: 18),
|
|
maxLines: 2,
|
|
overflow: TextOverflow.ellipsis,
|
|
),
|
|
const Spacer(),
|
|
Row(
|
|
children: [
|
|
const Icon(Icons.calendar_today_outlined,
|
|
size: 14, color: Colors.grey),
|
|
const SizedBox(width: 6),
|
|
Text(
|
|
'${'Valid Until:'.tr} ${promo['validity_end_date']}',
|
|
style: AppStyle.subtitle
|
|
.copyWith(fontSize: 12, color: Colors.grey),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
// --- الفاصل المنقط ---
|
|
SizedBox(
|
|
height: 110,
|
|
child: DottedLine(
|
|
direction: Axis.vertical,
|
|
lineThickness: 2.0,
|
|
dashLength: 8.0,
|
|
dashColor: AppColor.writeColor.withOpacity(0.2),
|
|
dashGapLength: 4.0,
|
|
),
|
|
),
|
|
// --- الجزء الأيمن: كود الخصم وزر النسخ ---
|
|
Expanded(
|
|
flex: 2,
|
|
child: GestureDetector(
|
|
onTap: () {
|
|
// --- نفس منطقك القديم للنسخ ---
|
|
Clipboard.setData(
|
|
ClipboardData(text: promo['promo_code']));
|
|
Get.snackbar(
|
|
'Promo Copied!'.tr,
|
|
'${'Code'.tr} ${promo['promo_code']} ${'copied to clipboard'.tr}',
|
|
snackPosition: SnackPosition.BOTTOM,
|
|
backgroundColor: AppColor.greenColor,
|
|
colorText: Colors.white,
|
|
);
|
|
},
|
|
child: Container(
|
|
color: AppColor.primaryColor.withOpacity(0.1),
|
|
child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
Text(
|
|
'CODE'.tr,
|
|
style: AppStyle.subtitle.copyWith(
|
|
color: AppColor.primaryColor, letterSpacing: 2),
|
|
),
|
|
const SizedBox(height: 8),
|
|
Text(
|
|
promo['promo_code'],
|
|
style: AppStyle.headTitle.copyWith(
|
|
fontSize: 24, color: AppColor.primaryColor),
|
|
),
|
|
const SizedBox(height: 12),
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
const Icon(Icons.copy,
|
|
size: 14, color: AppColor.primaryColor),
|
|
const SizedBox(width: 4),
|
|
Text('Copy'.tr,
|
|
style: AppStyle.subtitle
|
|
.copyWith(color: AppColor.primaryColor)),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
// --- كلاس مخصص لرسم شكل التذكرة ---
|
|
class TicketClipper extends CustomClipper<Path> {
|
|
@override
|
|
Path getClip(Size size) {
|
|
Path path = Path();
|
|
|
|
path.lineTo(0.0, size.height);
|
|
path.lineTo(size.width, size.height);
|
|
path.lineTo(size.width, 0.0);
|
|
|
|
double radius = 10;
|
|
path.addOval(
|
|
Rect.fromCircle(center: Offset(0, size.height / 2), radius: radius));
|
|
path.addOval(Rect.fromCircle(
|
|
center: Offset(size.width, size.height / 2), radius: radius));
|
|
|
|
return path;
|
|
}
|
|
|
|
@override
|
|
bool shouldReclip(CustomClipper<Path> oldClipper) => false;
|
|
}
|