152 lines
5.1 KiB
Dart
152 lines
5.1 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
/// CompetitorPriceBadge
|
|
/// ─────────────────────
|
|
/// ويدجت يعرض مقارنة ذكية بين سعر سيرو وسعر المنافسين.
|
|
/// يُستخدم في شاشة عرض الأسعار (bottomSheet) ويظهر فقط إذا توفرت
|
|
/// بيانات المنافسين من API (has_competitor_data = true).
|
|
class CompetitorPriceBadge extends StatelessWidget {
|
|
/// نسبة التوفير للراكب (مثال: 8.5 تعني "أوفر بـ 8.5%")
|
|
final double? savingsPercent;
|
|
|
|
/// النص التوضيحي الجاهز من السيرفر (مثال: "أوفر بـ 8% من التطبيقات الأخرى ⚡")
|
|
final String? savingsLabel;
|
|
|
|
/// اسم أكبر منافس للمقارنة (مثال: "Careem")
|
|
final String? topCompetitor;
|
|
|
|
const CompetitorPriceBadge({
|
|
super.key,
|
|
this.savingsPercent,
|
|
this.savingsLabel,
|
|
this.topCompetitor,
|
|
});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
// لا تُظهر الويدجت إذا لم تتوفر بيانات
|
|
if (savingsLabel == null || savingsLabel!.isEmpty) {
|
|
return const SizedBox.shrink();
|
|
}
|
|
|
|
final double pct = savingsPercent ?? 0.0;
|
|
final bool isSignificant = pct >= 5.0;
|
|
final bool isModerate = pct >= 2.0 && pct < 5.0;
|
|
|
|
// اختيار ألوان حسب قوة التوفير
|
|
final Color bgColor = isSignificant
|
|
? const Color(0xFF1A3A2A)
|
|
: isModerate
|
|
? const Color(0xFF1A2A3A)
|
|
: const Color(0xFF1F1F2E);
|
|
final Color borderColor = isSignificant
|
|
? const Color(0xFF34D399)
|
|
: isModerate
|
|
? const Color(0xFF60A5FA)
|
|
: const Color(0xFF818CF8);
|
|
final Color textColor = isSignificant
|
|
? const Color(0xFF34D399)
|
|
: isModerate
|
|
? const Color(0xFF60A5FA)
|
|
: const Color(0xFFA5B4FC);
|
|
|
|
return AnimatedOpacity(
|
|
opacity: 1.0,
|
|
duration: const Duration(milliseconds: 400),
|
|
child: Container(
|
|
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
|
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 10),
|
|
decoration: BoxDecoration(
|
|
color: bgColor,
|
|
borderRadius: BorderRadius.circular(12),
|
|
border: Border.all(color: borderColor.withOpacity(0.5), width: 1),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: borderColor.withOpacity(0.12),
|
|
blurRadius: 8,
|
|
offset: const Offset(0, 2),
|
|
),
|
|
],
|
|
),
|
|
child: Row(
|
|
children: [
|
|
// أيقونة التوفير
|
|
Container(
|
|
width: 32,
|
|
height: 32,
|
|
decoration: BoxDecoration(
|
|
color: borderColor.withOpacity(0.15),
|
|
shape: BoxShape.circle,
|
|
),
|
|
child: Icon(
|
|
isSignificant ? Icons.trending_down_rounded : Icons.price_check_rounded,
|
|
color: textColor,
|
|
size: 18,
|
|
),
|
|
),
|
|
const SizedBox(width: 10),
|
|
// نص المقارنة
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
savingsLabel!,
|
|
style: TextStyle(
|
|
color: textColor,
|
|
fontSize: 12,
|
|
fontWeight: FontWeight.w700,
|
|
height: 1.3,
|
|
),
|
|
),
|
|
if (topCompetitor != null && topCompetitor!.isNotEmpty) ...[
|
|
const SizedBox(height: 2),
|
|
Text(
|
|
'مقارنةً بـ ${_formatCompetitorName(topCompetitor!)} والتطبيقات الأخرى',
|
|
style: TextStyle(
|
|
color: textColor.withOpacity(0.6),
|
|
fontSize: 10,
|
|
fontWeight: FontWeight.w400,
|
|
),
|
|
),
|
|
],
|
|
],
|
|
),
|
|
),
|
|
// شارة النسبة
|
|
if (pct >= 2.0)
|
|
Container(
|
|
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
|
decoration: BoxDecoration(
|
|
color: borderColor.withOpacity(0.18),
|
|
borderRadius: BorderRadius.circular(20),
|
|
),
|
|
child: Text(
|
|
'-${pct.toStringAsFixed(1)}%',
|
|
style: TextStyle(
|
|
color: textColor,
|
|
fontSize: 11,
|
|
fontWeight: FontWeight.w800,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
String _formatCompetitorName(String raw) {
|
|
final names = {
|
|
'careem': 'كريم',
|
|
'uber': 'أوبر',
|
|
'yallago': 'يلاكو',
|
|
'zaken': 'زاكن',
|
|
'tufaddal': 'تفضل',
|
|
'jeeny': 'جيني',
|
|
'taxif': 'تاكسيف',
|
|
};
|
|
return names[raw.toLowerCase()] ?? raw;
|
|
}
|
|
}
|