|
|
|
@ -129,35 +129,709 @@ const MOCK_ORDERS: CustomTripOrderItem[] = [ |
|
|
|
|
|
|
|
// Mock Origins organized by core countries
|
|
|
|
const MOCK_ORIGINS: CustomTripOriginItem[] = [ |
|
|
|
// عمان (Oman)
|
|
|
|
{ id: 'muscat', name: 'مسقط', nameEn: 'Muscat', country: 'عُمان', countryCode: 'OM', flag: '🇴🇲', isInternational: true, isActive: true }, |
|
|
|
{ id: 'salalah', name: 'صلاله', nameEn: 'Salalah', country: 'عُمان', countryCode: 'OM', flag: '🇴🇲', isInternational: true, isActive: true }, |
|
|
|
|
|
|
|
// بحرین (Bahrain)
|
|
|
|
{ id: 'manama', name: 'منامه', nameEn: 'Manama', country: 'بحرین', countryCode: 'BH', flag: '🇧🇭', isInternational: true, isActive: true }, |
|
|
|
{ id: 'muharraq', name: 'المحرق', nameEn: 'Muharraq', country: 'بحرین', countryCode: 'BH', flag: '🇧🇭', isInternational: true, isActive: true }, |
|
|
|
|
|
|
|
// کویت (Kuwait)
|
|
|
|
{ id: 'kuwait_city', name: 'کویت', nameEn: 'Kuwait City', country: 'کویت', countryCode: 'KW', flag: '🇰🇼', isInternational: true, isActive: true }, |
|
|
|
{ id: 'al_ahmadi', name: 'الاحمدی', nameEn: 'Al Ahmadi', country: 'کویت', countryCode: 'KW', flag: '🇰🇼', isInternational: true, isActive: true }, |
|
|
|
|
|
|
|
// عربستان سعودی (Saudi Arabia)
|
|
|
|
{ id: 'riyadh', name: 'ریاض', nameEn: 'Riyadh', country: 'عربستان سعودی', countryCode: 'SA', flag: '🇸🇦', isInternational: true, isActive: true }, |
|
|
|
{ id: 'jeddah', name: 'جده', nameEn: 'Jeddah', country: 'عربستان سعودی', countryCode: 'SA', flag: '🇸🇦', isInternational: true, isActive: true }, |
|
|
|
{ id: 'dammam', name: 'دمام', nameEn: 'Dammam', country: 'عربستان سعودی', countryCode: 'SA', flag: '🇸🇦', isInternational: true, isActive: true }, |
|
|
|
{ id: 'qatif', name: 'قطیف', nameEn: 'Qatif', country: 'عربستان سعودی', countryCode: 'SA', flag: '🇸🇦', isInternational: true, isActive: true }, |
|
|
|
|
|
|
|
// ایران (Iran)
|
|
|
|
{ id: 'tehran', name: 'تهران', nameEn: 'Tehran', country: 'ایران', countryCode: 'IR', flag: '🇮🇷', isInternational: false, isActive: true }, |
|
|
|
{ id: 'mashhad', name: 'مشهد', nameEn: 'Mashhad', country: 'ایران', countryCode: 'IR', flag: '🇮🇷', isInternational: false, isActive: true }, |
|
|
|
{ id: 'qom', name: 'قم', nameEn: 'Qom', country: 'ایران', countryCode: 'IR', flag: '🇮🇷', isInternational: false, isActive: true }, |
|
|
|
{ id: 'isfahan', name: 'اصفهان', nameEn: 'Isfahan', country: 'ایران', countryCode: 'IR', flag: '🇮🇷', isInternational: false, isActive: true }, |
|
|
|
{ id: 'shiraz', name: 'شیراز', nameEn: 'Shiraz', country: 'ایران', countryCode: 'IR', flag: '🇮🇷', isInternational: false, isActive: true }, |
|
|
|
{ id: 'ahvaz', name: 'اهواز', nameEn: 'Ahvaz', country: 'ایران', countryCode: 'IR', flag: '🇮🇷', isInternational: false, isActive: true }, |
|
|
|
|
|
|
|
// عراق (Iraq)
|
|
|
|
{ id: 'baghdad', name: 'بغداد', nameEn: 'Baghdad', country: 'عراق', countryCode: 'IQ', flag: '🇮🇶', isInternational: true, isActive: true }, |
|
|
|
{ id: 'basra', name: 'بصره', nameEn: 'Basra', country: 'عراق', countryCode: 'IQ', flag: '🇮🇶', isInternational: true, isActive: true }, |
|
|
|
// ۱. عربستان سعودی (Saudi Arabia)
|
|
|
|
{ |
|
|
|
id: 'riyadh', |
|
|
|
name: 'الرياض', |
|
|
|
nameEn: 'Riyadh', |
|
|
|
country: 'عربستان سعودی', |
|
|
|
countryCode: 'SA', |
|
|
|
flag: '🇸🇦', |
|
|
|
isInternational: true, |
|
|
|
isActive: true, |
|
|
|
translations: { |
|
|
|
ar: { name: 'الرياض' }, |
|
|
|
fa: { name: 'ریاض' }, |
|
|
|
en: { name: 'Riyadh' }, |
|
|
|
ru: { name: 'Эр-Рияд' }, |
|
|
|
id: { name: 'Riyadh' }, |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
id: 'qatif', |
|
|
|
name: 'القطيف', |
|
|
|
nameEn: 'Qatif', |
|
|
|
country: 'عربستان سعودی', |
|
|
|
countryCode: 'SA', |
|
|
|
flag: '🇸🇦', |
|
|
|
isInternational: true, |
|
|
|
isActive: true, |
|
|
|
translations: { |
|
|
|
ar: { name: 'القطيف' }, |
|
|
|
fa: { name: 'قطیف' }, |
|
|
|
en: { name: 'Qatif' }, |
|
|
|
ru: { name: 'Катиф' }, |
|
|
|
id: { name: 'Qatif' }, |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
id: 'dammam', |
|
|
|
name: 'الدمام', |
|
|
|
nameEn: 'Dammam', |
|
|
|
country: 'عربستان سعودی', |
|
|
|
countryCode: 'SA', |
|
|
|
flag: '🇸🇦', |
|
|
|
isInternational: true, |
|
|
|
isActive: true, |
|
|
|
translations: { |
|
|
|
ar: { name: 'الدمام' }, |
|
|
|
fa: { name: 'دمام' }, |
|
|
|
en: { name: 'Dammam' }, |
|
|
|
ru: { name: 'Даммам' }, |
|
|
|
id: { name: 'Dammam' }, |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
id: 'al_ahsa', |
|
|
|
name: 'الأحساء', |
|
|
|
nameEn: 'Al-Ahsa', |
|
|
|
country: 'عربستان سعودی', |
|
|
|
countryCode: 'SA', |
|
|
|
flag: '🇸🇦', |
|
|
|
isInternational: true, |
|
|
|
isActive: true, |
|
|
|
translations: { |
|
|
|
ar: { name: 'الأحساء' }, |
|
|
|
fa: { name: 'احساء' }, |
|
|
|
en: { name: 'Al-Ahsa' }, |
|
|
|
ru: { name: 'Эль-Ахса' }, |
|
|
|
id: { name: 'Al-Ahsa' }, |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
id: 'jeddah', |
|
|
|
name: 'جدة', |
|
|
|
nameEn: 'Jeddah', |
|
|
|
country: 'عربستان سعودی', |
|
|
|
countryCode: 'SA', |
|
|
|
flag: '🇸🇦', |
|
|
|
isInternational: true, |
|
|
|
isActive: true, |
|
|
|
translations: { |
|
|
|
ar: { name: 'جدة' }, |
|
|
|
fa: { name: 'جده' }, |
|
|
|
en: { name: 'Jeddah' }, |
|
|
|
ru: { name: 'Джидда' }, |
|
|
|
id: { name: 'Jeddah' }, |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
id: 'medina', |
|
|
|
name: 'المدينة المنورة', |
|
|
|
nameEn: 'Medina', |
|
|
|
country: 'عربستان سعودی', |
|
|
|
countryCode: 'SA', |
|
|
|
flag: '🇸🇦', |
|
|
|
isInternational: true, |
|
|
|
isActive: true, |
|
|
|
translations: { |
|
|
|
ar: { name: 'المدينة المنورة' }, |
|
|
|
fa: { name: 'مدینه منوره' }, |
|
|
|
en: { name: 'Medina' }, |
|
|
|
ru: { name: 'Медина' }, |
|
|
|
id: { name: 'Madinah' }, |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
id: 'mecca', |
|
|
|
name: 'مكة المكرمة', |
|
|
|
nameEn: 'Mecca', |
|
|
|
country: 'عربستان سعودی', |
|
|
|
countryCode: 'SA', |
|
|
|
flag: '🇸🇦', |
|
|
|
isInternational: true, |
|
|
|
isActive: true, |
|
|
|
translations: { |
|
|
|
ar: { name: 'مكة المكرمة' }, |
|
|
|
fa: { name: 'مکه مکرمه' }, |
|
|
|
en: { name: 'Mecca' }, |
|
|
|
ru: { name: 'Мекка' }, |
|
|
|
id: { name: 'Makkah' }, |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
// ۲. امارات متحده عربی (United Arab Emirates)
|
|
|
|
{ |
|
|
|
id: 'dubai', |
|
|
|
name: 'دبي', |
|
|
|
nameEn: 'Dubai', |
|
|
|
country: 'امارات متحده عربی', |
|
|
|
countryCode: 'AE', |
|
|
|
flag: '🇦🇪', |
|
|
|
isInternational: true, |
|
|
|
isActive: true, |
|
|
|
translations: { |
|
|
|
ar: { name: 'دبي' }, |
|
|
|
fa: { name: 'دبی' }, |
|
|
|
en: { name: 'Dubai' }, |
|
|
|
ru: { name: 'Дубай' }, |
|
|
|
id: { name: 'Dubai' }, |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
id: 'abu_dhabi', |
|
|
|
name: 'أبوظبي', |
|
|
|
nameEn: 'Abu Dhabi', |
|
|
|
country: 'امارات متحده عربی', |
|
|
|
countryCode: 'AE', |
|
|
|
flag: '🇦🇪', |
|
|
|
isInternational: true, |
|
|
|
isActive: true, |
|
|
|
translations: { |
|
|
|
ar: { name: 'أبوظبي' }, |
|
|
|
fa: { name: 'ابوظبی' }, |
|
|
|
en: { name: 'Abu Dhabi' }, |
|
|
|
ru: { name: 'Абу-Даби' }, |
|
|
|
id: { name: 'Abu Dhabi' }, |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
id: 'sharjah', |
|
|
|
name: 'الشارقة', |
|
|
|
nameEn: 'Sharjah', |
|
|
|
country: 'امارات متحده عربی', |
|
|
|
countryCode: 'AE', |
|
|
|
flag: '🇦🇪', |
|
|
|
isInternational: true, |
|
|
|
isActive: true, |
|
|
|
translations: { |
|
|
|
ar: { name: 'الشارقة' }, |
|
|
|
fa: { name: 'شارجه' }, |
|
|
|
en: { name: 'Sharjah' }, |
|
|
|
ru: { name: 'Шарджа' }, |
|
|
|
id: { name: 'Sharjah' }, |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
// ۳. قطر (Qatar)
|
|
|
|
{ |
|
|
|
id: 'doha', |
|
|
|
name: 'الدوحة', |
|
|
|
nameEn: 'Doha', |
|
|
|
country: 'قطر', |
|
|
|
countryCode: 'QA', |
|
|
|
flag: '🇶🇦', |
|
|
|
isInternational: true, |
|
|
|
isActive: true, |
|
|
|
translations: { |
|
|
|
ar: { name: 'الدوحة' }, |
|
|
|
fa: { name: 'دوحه' }, |
|
|
|
en: { name: 'Doha' }, |
|
|
|
ru: { name: 'Доха' }, |
|
|
|
id: { name: 'Doha' }, |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
id: 'al_rayyan', |
|
|
|
name: 'الريان', |
|
|
|
nameEn: 'Al Rayyan', |
|
|
|
country: 'قطر', |
|
|
|
countryCode: 'QA', |
|
|
|
flag: '🇶🇦', |
|
|
|
isInternational: true, |
|
|
|
isActive: true, |
|
|
|
translations: { |
|
|
|
ar: { name: 'الريان' }, |
|
|
|
fa: { name: 'الریان' }, |
|
|
|
en: { name: 'Al Rayyan' }, |
|
|
|
ru: { name: 'Эр-Райян' }, |
|
|
|
id: { name: 'Al Rayyan' }, |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
// ۴. کویت (Kuwait)
|
|
|
|
{ |
|
|
|
id: 'kuwait_city', |
|
|
|
name: 'مدينة الكويت', |
|
|
|
nameEn: 'Kuwait City', |
|
|
|
country: 'کویت', |
|
|
|
countryCode: 'KW', |
|
|
|
flag: '🇰🇼', |
|
|
|
isInternational: true, |
|
|
|
isActive: true, |
|
|
|
translations: { |
|
|
|
ar: { name: 'مدينة الكويت' }, |
|
|
|
fa: { name: 'شهر کویت' }, |
|
|
|
en: { name: 'Kuwait City' }, |
|
|
|
ru: { name: 'Эль-Кувейт' }, |
|
|
|
id: { name: 'Kota Kuwait' }, |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
id: 'al_ahmadi', |
|
|
|
name: 'الأحمدي', |
|
|
|
nameEn: 'Al Ahmadi', |
|
|
|
country: 'کویت', |
|
|
|
countryCode: 'KW', |
|
|
|
flag: '🇰🇼', |
|
|
|
isInternational: true, |
|
|
|
isActive: true, |
|
|
|
translations: { |
|
|
|
ar: { name: 'الأحمدي' }, |
|
|
|
fa: { name: 'الاحمدی' }, |
|
|
|
en: { name: 'Al Ahmadi' }, |
|
|
|
ru: { name: 'Аль-Ахмади' }, |
|
|
|
id: { name: 'Al Ahmadi' }, |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
id: 'hawally', |
|
|
|
name: 'حولي', |
|
|
|
nameEn: 'Hawally', |
|
|
|
country: 'کویت', |
|
|
|
countryCode: 'KW', |
|
|
|
flag: '🇰🇼', |
|
|
|
isInternational: true, |
|
|
|
isActive: true, |
|
|
|
translations: { |
|
|
|
ar: { name: 'حولي' }, |
|
|
|
fa: { name: 'حولی' }, |
|
|
|
en: { name: 'Hawally' }, |
|
|
|
ru: { name: 'Хавалли' }, |
|
|
|
id: { name: 'Hawally' }, |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
// ۵. بحرین (Bahrain)
|
|
|
|
{ |
|
|
|
id: 'manama', |
|
|
|
name: 'المنامة', |
|
|
|
nameEn: 'Manama', |
|
|
|
country: 'بحرین', |
|
|
|
countryCode: 'BH', |
|
|
|
flag: '🇧🇭', |
|
|
|
isInternational: true, |
|
|
|
isActive: true, |
|
|
|
translations: { |
|
|
|
ar: { name: 'المنامة' }, |
|
|
|
fa: { name: 'منامه' }, |
|
|
|
en: { name: 'Manama' }, |
|
|
|
ru: { name: 'Манама' }, |
|
|
|
id: { name: 'Manama' }, |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
id: 'muharraq', |
|
|
|
name: 'المحرق', |
|
|
|
nameEn: 'Muharraq', |
|
|
|
country: 'بحرین', |
|
|
|
countryCode: 'BH', |
|
|
|
flag: '🇧🇭', |
|
|
|
isInternational: true, |
|
|
|
isActive: true, |
|
|
|
translations: { |
|
|
|
ar: { name: 'المحرق' }, |
|
|
|
fa: { name: 'المحرق' }, |
|
|
|
en: { name: 'Muharraq' }, |
|
|
|
ru: { name: 'Мухаррак' }, |
|
|
|
id: { name: 'Muharraq' }, |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
id: 'sitra', |
|
|
|
name: 'سترة', |
|
|
|
nameEn: 'Sitra', |
|
|
|
country: 'بحرین', |
|
|
|
countryCode: 'BH', |
|
|
|
flag: '🇧🇭', |
|
|
|
isInternational: true, |
|
|
|
isActive: true, |
|
|
|
translations: { |
|
|
|
ar: { name: 'سترة' }, |
|
|
|
fa: { name: 'ستره' }, |
|
|
|
en: { name: 'Sitra' }, |
|
|
|
ru: { name: 'Ситра' }, |
|
|
|
id: { name: 'Sitra' }, |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
id: 'riffa', |
|
|
|
name: 'الرفاع', |
|
|
|
nameEn: 'Riffa', |
|
|
|
country: 'بحرین', |
|
|
|
countryCode: 'BH', |
|
|
|
flag: '🇧🇭', |
|
|
|
isInternational: true, |
|
|
|
isActive: true, |
|
|
|
translations: { |
|
|
|
ar: { name: 'الرفاع' }, |
|
|
|
fa: { name: 'الرفاع' }, |
|
|
|
en: { name: 'Riffa' }, |
|
|
|
ru: { name: 'Эр-Рифа' }, |
|
|
|
id: { name: 'Riffa' }, |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
// ۶. عُمان (Oman)
|
|
|
|
{ |
|
|
|
id: 'muscat', |
|
|
|
name: 'مسقط', |
|
|
|
nameEn: 'Muscat', |
|
|
|
country: 'عُمان', |
|
|
|
countryCode: 'OM', |
|
|
|
flag: '🇴🇲', |
|
|
|
isInternational: true, |
|
|
|
isActive: true, |
|
|
|
translations: { |
|
|
|
ar: { name: 'مسقط' }, |
|
|
|
fa: { name: 'مسقط' }, |
|
|
|
en: { name: 'Muscat' }, |
|
|
|
ru: { name: 'Маскат' }, |
|
|
|
id: { name: 'Muskat' }, |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
id: 'salalah', |
|
|
|
name: 'صلالة', |
|
|
|
nameEn: 'Salalah', |
|
|
|
country: 'عُمان', |
|
|
|
countryCode: 'OM', |
|
|
|
flag: '🇴🇲', |
|
|
|
isInternational: true, |
|
|
|
isActive: true, |
|
|
|
translations: { |
|
|
|
ar: { name: 'صلالة' }, |
|
|
|
fa: { name: 'صلاله' }, |
|
|
|
en: { name: 'Salalah' }, |
|
|
|
ru: { name: 'Салала' }, |
|
|
|
id: { name: 'Salalah' }, |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
id: 'sohar', |
|
|
|
name: 'صحار', |
|
|
|
nameEn: 'Sohar', |
|
|
|
country: 'عُمان', |
|
|
|
countryCode: 'OM', |
|
|
|
flag: '🇴🇲', |
|
|
|
isInternational: true, |
|
|
|
isActive: true, |
|
|
|
translations: { |
|
|
|
ar: { name: 'صحار' }, |
|
|
|
fa: { name: 'صحار' }, |
|
|
|
en: { name: 'Sohar' }, |
|
|
|
ru: { name: 'Сохар' }, |
|
|
|
id: { name: 'Sohar' }, |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
id: 'nizwa', |
|
|
|
name: 'نزوى', |
|
|
|
nameEn: 'Nizwa', |
|
|
|
country: 'عُمان', |
|
|
|
countryCode: 'OM', |
|
|
|
flag: '🇴🇲', |
|
|
|
isInternational: true, |
|
|
|
isActive: true, |
|
|
|
translations: { |
|
|
|
ar: { name: 'نزوى' }, |
|
|
|
fa: { name: 'نزوی' }, |
|
|
|
en: { name: 'Nizwa' }, |
|
|
|
ru: { name: 'Низва' }, |
|
|
|
id: { name: 'Nizwa' }, |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
// ۷. عراق (Iraq)
|
|
|
|
{ |
|
|
|
id: 'baghdad', |
|
|
|
name: 'بغداد', |
|
|
|
nameEn: 'Baghdad', |
|
|
|
country: 'عراق', |
|
|
|
countryCode: 'IQ', |
|
|
|
flag: '🇮🇶', |
|
|
|
isInternational: true, |
|
|
|
isActive: true, |
|
|
|
translations: { |
|
|
|
ar: { name: 'بغداد' }, |
|
|
|
fa: { name: 'بغداد' }, |
|
|
|
en: { name: 'Baghdad' }, |
|
|
|
ru: { name: 'Багдад' }, |
|
|
|
id: { name: 'Bagdad' }, |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
id: 'basra', |
|
|
|
name: 'البصرة', |
|
|
|
nameEn: 'Basra', |
|
|
|
country: 'عراق', |
|
|
|
countryCode: 'IQ', |
|
|
|
flag: '🇮🇶', |
|
|
|
isInternational: true, |
|
|
|
isActive: true, |
|
|
|
translations: { |
|
|
|
ar: { name: 'البصرة' }, |
|
|
|
fa: { name: 'بصره' }, |
|
|
|
en: { name: 'Basra' }, |
|
|
|
ru: { name: 'Басра' }, |
|
|
|
id: { name: 'Basra' }, |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
id: 'erbil', |
|
|
|
name: 'أربيل', |
|
|
|
nameEn: 'Erbil', |
|
|
|
country: 'عراق', |
|
|
|
countryCode: 'IQ', |
|
|
|
flag: '🇮🇶', |
|
|
|
isInternational: true, |
|
|
|
isActive: true, |
|
|
|
translations: { |
|
|
|
ar: { name: 'أربيل' }, |
|
|
|
fa: { name: 'اربیل' }, |
|
|
|
en: { name: 'Erbil' }, |
|
|
|
ru: { name: 'Эрбиль' }, |
|
|
|
id: { name: 'Erbil' }, |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
id: 'najaf', |
|
|
|
name: 'النجف الأشرف', |
|
|
|
nameEn: 'Najaf', |
|
|
|
country: 'عراق', |
|
|
|
countryCode: 'IQ', |
|
|
|
flag: '🇮🇶', |
|
|
|
isInternational: true, |
|
|
|
isActive: true, |
|
|
|
translations: { |
|
|
|
ar: { name: 'النجف الأشرف' }, |
|
|
|
fa: { name: 'نجف اشرف' }, |
|
|
|
en: { name: 'Najaf' }, |
|
|
|
ru: { name: 'Эн-Наджаф' }, |
|
|
|
id: { name: 'Najaf' }, |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
id: 'karbala', |
|
|
|
name: 'كربلاء المقدسة', |
|
|
|
nameEn: 'Karbala', |
|
|
|
country: 'عراق', |
|
|
|
countryCode: 'IQ', |
|
|
|
flag: '🇮🇶', |
|
|
|
isInternational: true, |
|
|
|
isActive: true, |
|
|
|
translations: { |
|
|
|
ar: { name: 'كربلاء المقدسة' }, |
|
|
|
fa: { name: 'کربلای معلی' }, |
|
|
|
en: { name: 'Karbala' }, |
|
|
|
ru: { name: 'Кербела' }, |
|
|
|
id: { name: 'Karbala' }, |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
// ۸. لبنان (Lebanon)
|
|
|
|
{ |
|
|
|
id: 'beirut', |
|
|
|
name: 'بيروت', |
|
|
|
nameEn: 'Beirut', |
|
|
|
country: 'لبنان', |
|
|
|
countryCode: 'LB', |
|
|
|
flag: '🇱🇧', |
|
|
|
isInternational: true, |
|
|
|
isActive: true, |
|
|
|
translations: { |
|
|
|
ar: { name: 'بيروت' }, |
|
|
|
fa: { name: 'بیروت' }, |
|
|
|
en: { name: 'Beirut' }, |
|
|
|
ru: { name: 'Бейрут' }, |
|
|
|
id: { name: 'Beirut' }, |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
id: 'sidon', |
|
|
|
name: 'صيدا', |
|
|
|
nameEn: 'Sidon', |
|
|
|
country: 'لبنان', |
|
|
|
countryCode: 'LB', |
|
|
|
flag: '🇱🇧', |
|
|
|
isInternational: true, |
|
|
|
isActive: true, |
|
|
|
translations: { |
|
|
|
ar: { name: 'صيدا' }, |
|
|
|
fa: { name: 'صیدا' }, |
|
|
|
en: { name: 'Sidon' }, |
|
|
|
ru: { name: 'Сайда' }, |
|
|
|
id: { name: 'Sidon' }, |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
// ۹. سوریه (Syria)
|
|
|
|
{ |
|
|
|
id: 'damascus', |
|
|
|
name: 'دمشق', |
|
|
|
nameEn: 'Damascus', |
|
|
|
country: 'سوریه', |
|
|
|
countryCode: 'SY', |
|
|
|
flag: '🇸🇾', |
|
|
|
isInternational: true, |
|
|
|
isActive: true, |
|
|
|
translations: { |
|
|
|
ar: { name: 'دمشق' }, |
|
|
|
fa: { name: 'دمشق' }, |
|
|
|
en: { name: 'Damascus' }, |
|
|
|
ru: { name: 'Дамаск' }, |
|
|
|
id: { name: 'Damaskus' }, |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
// ۱۰. اردن (Jordan)
|
|
|
|
{ |
|
|
|
id: 'amman', |
|
|
|
name: 'عمّان', |
|
|
|
nameEn: 'Amman', |
|
|
|
country: 'اردن', |
|
|
|
countryCode: 'JO', |
|
|
|
flag: '🇯🇴', |
|
|
|
isInternational: true, |
|
|
|
isActive: true, |
|
|
|
translations: { |
|
|
|
ar: { name: 'عمّان' }, |
|
|
|
fa: { name: 'امان' }, |
|
|
|
en: { name: 'Amman' }, |
|
|
|
ru: { name: 'Амман' }, |
|
|
|
id: { name: 'Amman' }, |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
// ۱۱. مصر (Egypt)
|
|
|
|
{ |
|
|
|
id: 'cairo', |
|
|
|
name: 'القاهرة', |
|
|
|
nameEn: 'Cairo', |
|
|
|
country: 'مصر', |
|
|
|
countryCode: 'EG', |
|
|
|
flag: '🇪🇬', |
|
|
|
isInternational: true, |
|
|
|
isActive: true, |
|
|
|
translations: { |
|
|
|
ar: { name: 'القاهرة' }, |
|
|
|
fa: { name: 'قاهره' }, |
|
|
|
en: { name: 'Cairo' }, |
|
|
|
ru: { name: 'Каир' }, |
|
|
|
id: { name: 'Kairo' }, |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
id: 'alexandria', |
|
|
|
name: 'الإسكندرية', |
|
|
|
nameEn: 'Alexandria', |
|
|
|
country: 'مصر', |
|
|
|
countryCode: 'EG', |
|
|
|
flag: '🇪🇬', |
|
|
|
isInternational: true, |
|
|
|
isActive: true, |
|
|
|
translations: { |
|
|
|
ar: { name: 'الإسكندرية' }, |
|
|
|
fa: { name: 'اسکندریه' }, |
|
|
|
en: { name: 'Alexandria' }, |
|
|
|
ru: { name: 'Александрия' }, |
|
|
|
id: { name: 'Aleksandria' }, |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
// ۱۲. ایران (Iran)
|
|
|
|
{ |
|
|
|
id: 'tehran', |
|
|
|
name: 'تهران', |
|
|
|
nameEn: 'Tehran', |
|
|
|
country: 'ایران', |
|
|
|
countryCode: 'IR', |
|
|
|
flag: '🇮🇷', |
|
|
|
isInternational: false, |
|
|
|
isActive: true, |
|
|
|
translations: { |
|
|
|
ar: { name: 'طهران' }, |
|
|
|
fa: { name: 'تهران' }, |
|
|
|
en: { name: 'Tehran' }, |
|
|
|
ru: { name: 'Тегеран' }, |
|
|
|
id: { name: 'Teheran' }, |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
id: 'mashhad', |
|
|
|
name: 'مشهد', |
|
|
|
nameEn: 'Mashhad', |
|
|
|
country: 'ایران', |
|
|
|
countryCode: 'IR', |
|
|
|
flag: '🇮🇷', |
|
|
|
isInternational: false, |
|
|
|
isActive: true, |
|
|
|
translations: { |
|
|
|
ar: { name: 'مشهد' }, |
|
|
|
fa: { name: 'مشهد' }, |
|
|
|
en: { name: 'Mashhad' }, |
|
|
|
ru: { name: 'Мешхед' }, |
|
|
|
id: { name: 'Masyhad' }, |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
id: 'qom', |
|
|
|
name: 'قم', |
|
|
|
nameEn: 'Qom', |
|
|
|
country: 'ایران', |
|
|
|
countryCode: 'IR', |
|
|
|
flag: '🇮🇷', |
|
|
|
isInternational: false, |
|
|
|
isActive: true, |
|
|
|
translations: { |
|
|
|
ar: { name: 'قم' }, |
|
|
|
fa: { name: 'قم' }, |
|
|
|
en: { name: 'Qom' }, |
|
|
|
ru: { name: 'Кум' }, |
|
|
|
id: { name: 'Qom' }, |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
id: 'isfahan', |
|
|
|
name: 'اصفهان', |
|
|
|
nameEn: 'Isfahan', |
|
|
|
country: 'ایران', |
|
|
|
countryCode: 'IR', |
|
|
|
flag: '🇮🇷', |
|
|
|
isInternational: false, |
|
|
|
isActive: true, |
|
|
|
translations: { |
|
|
|
ar: { name: 'أصفهان' }, |
|
|
|
fa: { name: 'اصفهان' }, |
|
|
|
en: { name: 'Isfahan' }, |
|
|
|
ru: { name: 'Исфахан' }, |
|
|
|
id: { name: 'Isfahan' }, |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
id: 'shiraz', |
|
|
|
name: 'شیراز', |
|
|
|
nameEn: 'Shiraz', |
|
|
|
country: 'ایران', |
|
|
|
countryCode: 'IR', |
|
|
|
flag: '🇮🇷', |
|
|
|
isInternational: false, |
|
|
|
isActive: true, |
|
|
|
translations: { |
|
|
|
ar: { name: 'شيراز' }, |
|
|
|
fa: { name: 'شیراز' }, |
|
|
|
en: { name: 'Shiraz' }, |
|
|
|
ru: { name: 'Шираз' }, |
|
|
|
id: { name: 'Syiraz' }, |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
id: 'ahvaz', |
|
|
|
name: 'اهواز', |
|
|
|
nameEn: 'Ahvaz', |
|
|
|
country: 'ایران', |
|
|
|
countryCode: 'IR', |
|
|
|
flag: '🇮🇷', |
|
|
|
isInternational: false, |
|
|
|
isActive: true, |
|
|
|
translations: { |
|
|
|
ar: { name: 'الأهواز' }, |
|
|
|
fa: { name: 'اهواز' }, |
|
|
|
en: { name: 'Ahvaz' }, |
|
|
|
ru: { name: 'Ахваз' }, |
|
|
|
id: { name: 'Ahvaz' }, |
|
|
|
}, |
|
|
|
}, |
|
|
|
] |
|
|
|
|
|
|
|
// Mock Destinations
|
|
|
|
@ -847,7 +1521,7 @@ const STORAGE_KEYS = { |
|
|
|
DESTINATIONS: 'aqila_custom_destinations_v2', |
|
|
|
HOTELS: 'aqila_custom_hotels_v2', |
|
|
|
RELATIONS: 'aqila_custom_relations_v2', |
|
|
|
ORIGINS: 'aqila_custom_origins_v2', |
|
|
|
ORIGINS: 'aqila_custom_origins_v3', |
|
|
|
} |
|
|
|
|
|
|
|
function getStored<T>(key: string, fallback: T): T { |
|
|
|
@ -869,7 +1543,12 @@ function setStored<T>(key: string, value: T): void { |
|
|
|
} |
|
|
|
|
|
|
|
export async function fetchCustomTripOrigins(): Promise<CustomTripOriginItem[]> { |
|
|
|
return getStored(STORAGE_KEYS.ORIGINS, MOCK_ORIGINS) |
|
|
|
const stored = getStored<CustomTripOriginItem[] | null>(STORAGE_KEYS.ORIGINS, null) |
|
|
|
if (!stored || !Array.isArray(stored) || stored.length < 25) { |
|
|
|
setStored(STORAGE_KEYS.ORIGINS, MOCK_ORIGINS) |
|
|
|
return MOCK_ORIGINS |
|
|
|
} |
|
|
|
return stored |
|
|
|
} |
|
|
|
|
|
|
|
export async function saveCustomTripOrigin(item: CustomTripOriginItem): Promise<CustomTripOriginItem> { |
|
|
|
@ -886,6 +1565,30 @@ export async function deleteCustomTripOrigin(id: string | number): Promise<void> |
|
|
|
} |
|
|
|
|
|
|
|
export async function fetchCustomTripDestinations(): Promise<CustomTripDestinationItem[]> { |
|
|
|
try { |
|
|
|
const remote = await apiFetch<CustomTripDestinationItem[]>('trip/custom/v2/catalog/destinations/?include_inactive=true') |
|
|
|
if (remote && Array.isArray(remote) && remote.length > 0) { |
|
|
|
// If local storage has user-modified values (such as added 1s or custom test names), sync them
|
|
|
|
const stored = getStored<CustomTripDestinationItem[] | null>(STORAGE_KEYS.DESTINATIONS, null) |
|
|
|
if (stored && Array.isArray(stored)) { |
|
|
|
for (const localItem of stored) { |
|
|
|
const match = remote.find((r) => String(r.id) === String(localItem.id) || r.name === localItem.name) |
|
|
|
if (match && localItem.name && localItem.name !== match.name) { |
|
|
|
match.name = localItem.name |
|
|
|
apiFetch(`trip/custom/v2/catalog/destinations/${match.id}/`, { |
|
|
|
method: 'PATCH', |
|
|
|
body: JSON.stringify({ name: localItem.name }), |
|
|
|
}).catch(() => {}) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
setStored(STORAGE_KEYS.DESTINATIONS, remote) |
|
|
|
return remote |
|
|
|
} |
|
|
|
} catch (err) { |
|
|
|
console.warn('[CustomTrip API] Could not fetch destinations from backend, falling back to cache:', err) |
|
|
|
} |
|
|
|
|
|
|
|
const stored = getStored<CustomTripDestinationItem[] | null>(STORAGE_KEYS.DESTINATIONS, null) |
|
|
|
if ( |
|
|
|
!stored || |
|
|
|
@ -912,16 +1615,60 @@ export async function fetchCustomTripDestinationById(id: string | number): Promi |
|
|
|
} |
|
|
|
|
|
|
|
export async function saveCustomTripDestination(item: CustomTripDestinationItem): Promise<CustomTripDestinationItem> { |
|
|
|
const list = await fetchCustomTripDestinations() |
|
|
|
const exists = list.some((d) => d.id === item.id) |
|
|
|
const updated = exists ? list.map((d) => (d.id === item.id ? item : d)) : [item, ...list] |
|
|
|
let savedItem = item |
|
|
|
try { |
|
|
|
const payload = { |
|
|
|
id: String(item.id), |
|
|
|
city_key: String(item.id), |
|
|
|
name: item.name, |
|
|
|
nameEn: item.nameEn, |
|
|
|
name_en: item.nameEn, |
|
|
|
country: item.country, |
|
|
|
flag: item.flag, |
|
|
|
description: item.description, |
|
|
|
holyPlaces: item.holyPlaces, |
|
|
|
holy_places: item.holyPlaces, |
|
|
|
hotelsCount: item.hotelsCount, |
|
|
|
hotels_count: item.hotelsCount, |
|
|
|
transportsCount: item.transportsCount, |
|
|
|
transports_count: item.transportsCount, |
|
|
|
isActive: item.isActive, |
|
|
|
is_active: item.isActive, |
|
|
|
translations: item.translations, |
|
|
|
} |
|
|
|
const res = await apiFetch<CustomTripDestinationItem>(`trip/custom/v2/catalog/destinations/${item.id}/`, { |
|
|
|
method: 'PUT', |
|
|
|
body: JSON.stringify(payload), |
|
|
|
}).catch(async () => { |
|
|
|
return await apiFetch<CustomTripDestinationItem>('trip/custom/v2/catalog/destinations/', { |
|
|
|
method: 'POST', |
|
|
|
body: JSON.stringify(payload), |
|
|
|
}) |
|
|
|
}) |
|
|
|
if (res && res.id) { |
|
|
|
savedItem = { ...item, ...res } |
|
|
|
} |
|
|
|
} catch (err) { |
|
|
|
console.warn('[CustomTrip API] Could not save destination to backend, cached locally:', err) |
|
|
|
} |
|
|
|
|
|
|
|
const list = getStored<CustomTripDestinationItem[]>(STORAGE_KEYS.DESTINATIONS, MOCK_DESTINATIONS) |
|
|
|
const exists = list.some((d) => String(d.id) === String(savedItem.id)) |
|
|
|
const updated = exists ? list.map((d) => (String(d.id) === String(savedItem.id) ? savedItem : d)) : [savedItem, ...list] |
|
|
|
setStored(STORAGE_KEYS.DESTINATIONS, updated) |
|
|
|
return item |
|
|
|
return savedItem |
|
|
|
} |
|
|
|
|
|
|
|
export async function deleteCustomTripDestination(id: string | number): Promise<void> { |
|
|
|
const list = await fetchCustomTripDestinations() |
|
|
|
setStored(STORAGE_KEYS.DESTINATIONS, list.filter((d) => d.id !== id)) |
|
|
|
try { |
|
|
|
await apiFetch(`trip/custom/v2/catalog/destinations/${id}/`, { |
|
|
|
method: 'DELETE', |
|
|
|
}) |
|
|
|
} catch (err) { |
|
|
|
console.warn('[CustomTrip API] Could not delete destination on backend:', err) |
|
|
|
} |
|
|
|
const list = getStored<CustomTripDestinationItem[]>(STORAGE_KEYS.DESTINATIONS, MOCK_DESTINATIONS) |
|
|
|
setStored(STORAGE_KEYS.DESTINATIONS, list.filter((d) => String(d.id) !== String(id))) |
|
|
|
} |
|
|
|
|
|
|
|
export async function fetchCustomTripTransportRelations(): Promise<CustomTripTransportRelationItem[]> { |
|
|
|
|