// Duyuf marketing + browse website (desktop / responsive) // Headless web entry to the marketplace — hero search, featured // packages, top providers, how-it-works, become-a-provider CTA, footer. function WebNav({ theme, lang, onLanguageChange, dark, onThemeChange }) { const T = theme; const rtl = isRTL(lang); const ctx = useWeb(); const [menuOpen, setMenuOpen] = React.useState(false); const isProvider = Boolean(localStorage.getItem('duyuf_provider_session')); const visitorItems = [ { id: 'home', ar: 'الرئيسية', en: 'Home' }, { id: 'browse', ar: 'العمرة', en: 'Umrah' }, { id: 'browse', ar: 'الفنادق', en: 'Hotels' }, { id: 'browse', ar: 'الطيران', en: 'Flights' }, { id: 'browse', ar: 'المواصلات', en: 'Transport' }, { id: 'contact', ar: 'تواصل', en: 'Contact' }, ]; const providerItems = [ { id: 'provider-dashboard', ar: 'لوحة التحكم', en: 'Dashboard' }, { id: 'provider-dashboard', ar: 'إدارة الباقات', en: 'Manage packages' }, { id: 'provider-add-package', ar: 'إضافة باقة', en: 'Add package' }, { id: 'provider-dashboard', ar: 'الملف التجاري', en: 'Business profile' }, ]; const items = isProvider ? providerItems : visitorItems; const navigate = (page) => { ctx?.setPage(page); setMenuOpen(false); }; const logout = async () => { try { await firebase.auth().signOut(); } catch (_) {} localStorage.removeItem('duyuf_provider_session'); localStorage.removeItem('duyuf_provider'); setMenuOpen(false); ctx?.setPage('home'); }; return ( <>
navigate(isProvider ? 'provider-dashboard' : 'home')} style={{ cursor: 'pointer' }}>
{lang === 'ar' ? 'العربية' : lang === 'ur' ? 'اردو' : 'EN'}
{!isProvider && }
{menuOpen &&
{rtl ? 'اللغة' : 'Language'}
{rtl ? 'المظهر' : 'Appearance'}
); } function WebHero({ theme, lang }) { const T = theme; const rtl = isRTL(lang); const ctx = useWeb(); return (
{rtl ? 'مزوّدون معتمدون · حماية كاملة' : 'Verified providers · Protected booking'}

{rtl ? 'رحلتك إلى بيت الله، في خطوات ميسّرة.' : 'Your journey to the holy sites, made simple.'}

{rtl ? 'باقات عمرة كاملة، فنادق قرب الحرم، طيران ومواصلات — من أكثر من 68 مزوّداً موثوقاً.' : 'Complete Umrah packages, stays near the Haram, flights and transport — from 68+ verified providers.'}

{/* Unified search bar (no service-tab strip — icons live in the homepage already) */}
{[ { l: rtl ? 'من' : 'From', v: rtl ? 'جدة' : 'Jeddah', sub: 'JED', i: 'plane' }, { l: rtl ? 'إلى' : 'To', v: rtl ? 'مكة المكرمة' : 'Makkah', sub: rtl ? 'العزيزية' : 'Al Aziziyah', i: 'kaaba' }, { l: rtl ? 'الموعد' : 'Departure', v: '16 Ramadan', sub: rtl ? '10 أيام' : '10 days', i: 'calendar' }, { l: rtl ? 'مسافرون' : 'Travelers', v: rtl ? '3 بالغين' : '3 adults', sub: '', i: 'user' }, ].map((f, i, a) => (
{f.l}
{f.v}
{f.sub &&
{f.sub}
}
))}
{/* Trust stats */}
{[ { v: '68+', l: rtl ? 'مزوّد معتمد' : 'Verified providers' }, { v: '12K+', l: rtl ? 'رحلة ميسّرة' : 'Trips arranged' }, { v: '4.8★', l: rtl ? 'تقييم المعتمرين' : 'Customer rating' }, { v: rtl ? '3 لغات' : '3 langs', l: rtl ? 'العربية · English · اردو' : 'Arabic · English · Urdu' }, ].map((s, i) => (
{s.v}
{s.l}
))}
); } function WebPackages({ theme, lang }) { const T = theme; const rtl = isRTL(lang); const ctx = useWeb(); const packages = [ { hotel: rtl ? 'فيرمونت ساعة مكة' : 'Fairmont Makkah', dates: rtl ? '16–25 رمضان' : '16–25 Ramadan', nights: 7, transport: 'flight', price: 4899, seats: 4, tag: rtl ? 'الأكثر طلباً' : 'Most booked', tone: 'dark', provider: rtl ? 'الإيلاف الفاخرة' : 'Elaf Premium' }, { hotel: rtl ? 'سويس أوتيل الزمزم' : 'Swissôtel Al Maqam', dates: rtl ? '1–8 شوال' : '1–8 Shawwal', nights: 7, transport: 'flight', price: 3450, seats: 12, tone: 'brown', provider: rtl ? 'الرحمة للحج' : 'Al-Rahma' }, { hotel: rtl ? 'فندق ميلينيوم' : 'Millennium Makkah', dates: rtl ? '20 رمضان' : '20 Ramadan', nights: 14, transport: 'bus', price: 1899, seats: 3, tag: rtl ? 'حصري' : 'Exclusive', tone: 'camel', provider: rtl ? 'دار البركة' : 'Dar Albaraka' }, { hotel: rtl ? 'هيلتون مكة' : 'Hilton Makkah', dates: rtl ? '12 شوال' : '12 Shawwal', nights: 5, transport: 'flight', price: 2799, seats: 8, tone: 'cream', provider: rtl ? 'إيلاف ضيوف' : 'Elaf Guests' }, ]; return (
{rtl ? 'باقات مختارة' : 'Featured packages'}

{rtl ? 'أحدث باقات العمرة من مزوّدين موثوقين' : 'Latest Umrah packages from verified providers'}

ctx?.setPage('browse')} style={{ fontFamily: 'Alexandria', fontSize: 13, color: T.primary, fontWeight: 600, cursor: 'pointer' }}> {rtl ? 'كل الباقات →' : 'Browse all →'}
{packages.map((p, i) => (
{ ctx?.setPkg(p); ctx?.setPage('detail'); }} style={{ background: T.surface, borderRadius: 18, border: `1px solid ${T.hairline}`, overflow: 'hidden', boxShadow: T.cardShadow, cursor: 'pointer', }}>
{p.tag && (
{p.tag}
)}
{p.hotel}
4.7
{p.dates}
{p.nights} {rtl ? 'ليالٍ' : 'nights'}
{rtl ? 'يبدأ من' : 'from'}
{p.price.toLocaleString()} SAR
))}
); } function WebHowItWorks({ theme, lang }) { const T = theme; const rtl = isRTL(lang); const steps = [ { n: '01', i: 'search', t: rtl ? 'اختر باقتك' : 'Pick your package', d: rtl ? 'تصفّح آلاف الباقات من مزوّدين موثوقين' : 'Browse packages from verified providers' }, { n: '02', i: 'card', t: rtl ? 'احجز وادفع بأمان' : 'Book securely', d: rtl ? 'دفع آمن بـ Apple Pay، مدى، فيزا، STC Pay وغيرها' : 'Apple Pay, mada, Visa, STC Pay & more' }, { n: '03', i: 'qr', t: rtl ? 'استلم رمز الحجز' : 'Get your QR', d: rtl ? 'تأكيد فوري ورمز QR للسفر' : 'Instant confirmation with travel QR' }, { n: '04', i: 'kaaba', t: rtl ? 'سافر بسلام' : 'Travel with ease', d: rtl ? 'تنبيهات وإرشادات أثناء الرحلة' : 'In-trip alerts and on-site guides' }, ]; return (
{rtl ? 'كيف يعمل' : 'How it works'}

{rtl ? 'من البحث إلى الحرم في 4 خطوات' : 'From search to the Haram in 4 steps'}

{steps.map((s, i) => (
{s.n}
{s.t}
{s.d}
))}
); } function WebProviders({ theme, lang }) { const T = theme; const rtl = isRTL(lang); const providers = [ rtl ? 'الإيلاف الفاخرة' : 'Elaf Premium', rtl ? 'الرحمة للحج' : 'Al-Rahma Hajj', rtl ? 'إيلاف ضيوف' : 'Elaf Guests', rtl ? 'دار الراحة' : 'Dar Al-Raha', rtl ? 'بوابة الكعبة' : 'Kaaba Gate', rtl ? 'حجاج الجزيرة' : 'Hujjaj Aljazeera', rtl ? 'نسائم الرحمن' : 'Nasaim Al-Rahman', rtl ? 'دار البركة' : 'Dar Albaraka', ]; return (
{rtl ? 'موثوق من قبل أكثر من 68 مزوّداً' : 'Trusted by 68+ verified providers'}
{providers.map((p, i) => (
))}
); } function WebBecomeProvider({ theme, lang }) { const T = theme; const rtl = isRTL(lang); const ctx = useWeb(); return (
{rtl ? 'انضم إلى السوق' : 'Join the marketplace'}

{rtl ? 'وفّر باقاتك لآلاف المعتمرين عبر منصة ضيوف' : 'Offer your packages to thousands of pilgrims via Duyuf'}

{rtl ? 'لوحة إدارة كاملة لتكوين الباقات، إدارة الحجوزات، وتطبيق تشغيل لمتابعة العملاء أثناء الرحلة.' : 'A full dashboard to create packages, manage bookings, plus an operations app to track travelers during their trip.'}

{[ { i: 'trend-up', t: rtl ? 'وصول لـ 12K+ معتمر شهرياً' : '12K+ pilgrims/month' }, { i: 'percent', t: rtl ? 'عمولة شفافة من لوحة الإدارة' : 'Transparent commission' }, { i: 'shield', t: rtl ? 'دفعات آمنة ومجدولة' : 'Secure scheduled payouts' }, { i: 'bell', t: rtl ? 'تطبيق تشغيل وتنبيهات للعملاء' : 'Ops app + traveler alerts' }, ].map((f, i) => (
{f.t}
))}
); } function WebAppDownload({ theme, lang }) { const T = theme; const rtl = isRTL(lang); return (
{rtl ? 'حمّل التطبيق' : 'Get the app'}

{rtl ? 'كل رحلتك في تطبيق واحد' : 'Your whole journey in one app'}

{rtl ? 'احجز، ادفع، تتبّع رحلتك، واستلم تنبيهات أثناء السفر — بالعربية، الإنجليزية، أو الأردية.' : 'Book, pay, track your trip, and receive on-trip alerts — in Arabic, English, or Urdu.'}

{[ { t: rtl ? 'تنزيل من' : 'Download on', store: 'App Store', icon: '' }, { t: rtl ? 'احصل عليه من' : 'Get it on', store: 'Google Play', icon: '▶' }, ].map((s, i) => (
{s.icon}
{s.t}
{s.store}
))}
4.8 · 4,200+ {rtl ? 'تقييم' : 'ratings'}
{/* Phone mockup */}
); } function WebFAQ({ theme, lang }) { const T = theme; const rtl = isRTL(lang); const faqs = rtl ? [ { q: 'هل يمكنني الحجز كزائر دون تسجيل؟', a: 'يمكنك تصفّح كل الباقات بدون تسجيل، لكن إتمام الحجز يتطلب التحقق برقم الهاتف عبر رمز SMS.' }, { q: 'كيف تختار المزوّدين الموجودين على المنصة؟', a: 'كل المزوّدين يمرّون بعملية توثيق KYC قبل ظهور باقاتهم. تظهر شارة "موثّق" على الباقات.', open: true }, { q: 'ما هي سياسة الإلغاء والاسترداد؟', a: 'استرداد كامل قبل 7 أيام من السفر، وخصم 50% خلال 7 أيام. الاسترداد يصل لمحفظتك خلال 3 أيام عمل.' }, { q: 'هل أحتاج لاختيار مقعد للعمرة بالطائرة؟', a: 'لا، باقات العمرة (بالطائرة أو الحافلة) مجدولة مسبقاً ولا تتطلب اختيار مقعد. اختيار المقاعد متاح فقط في حجوزات الطيران المستقلة من أيقونة الطيران.' }, { q: 'بأي وسائل دفع يمكنني الدفع؟', a: 'Apple Pay، مدى، فيزا/ماستركارد، STC Pay، تابي وتمارا للأقساط، أو رصيد محفظة ضيوف.' }, { q: 'كيف أصبح مزوّداً على المنصة؟', a: 'سجّل عبر "انضم كمزوّد"، أرسل وثائقك (سجل تجاري + ترخيص هيئة السياحة)، وبعد الموافقة ستحصل على لوحة إدارة وتطبيق التشغيل.' }, ] : [ { q: 'Can I book as a guest without an account?', a: 'You can browse all packages without signing up, but completing a booking requires phone verification via SMS code.' }, { q: 'How are providers verified on Duyuf?', a: 'All providers go through KYC verification before their packages appear. Look for the "Verified" badge on package listings.', open: true }, { q: 'What is the cancellation policy?', a: 'Full refund up to 7 days before travel, 50% within 7 days. Refunds land in your Duyuf wallet within 3 business days.' }, { q: 'Do I select a seat for Umrah by Flight?', a: 'No. Umrah packages (flight or bus) are pre-arranged and do not require seat selection. Seat selection is only available for standalone flight bookings from the Flights icon.' }, { q: 'Which payment methods are supported?', a: 'Apple Pay, mada, Visa/Mastercard, STC Pay, Tabby and Tamara installments, or your Duyuf wallet balance.' }, { q: 'How do I become a provider?', a: 'Apply via "Become a provider", submit your documents (commercial registration + tourism license), and once approved you get a dashboard and operations app.' }, ]; return (
{rtl ? 'الأسئلة الشائعة' : 'Frequently asked'}

{rtl ? 'كل ما تحتاج معرفته قبل حجز رحلتك' : 'Everything you need to know before booking'}

{rtl ? 'لم تجد إجابتك؟ تواصل مع فريق الدعم على واتساب وسنردّ خلال دقائق.' : "Didn't find your answer? Reach our support team on WhatsApp and we'll reply in minutes."}

{faqs.map((f, i) => (
{f.q}
{f.open && (
{f.a}
)}
))}
); } function WebFooter({ theme, lang }) { const T = theme; const rtl = isRTL(lang); const cols = [ { h: rtl ? 'الخدمات' : 'Services', items: rtl ? ['عمرة بالطائرة','عمرة بالحافلة','فنادق','طيران','مواصلات'] : ['Umrah by flight','Umrah by bus','Hotels','Flights','Transport'] }, { h: rtl ? 'الشركة' : 'Company', items: rtl ? ['عن ضيوف','قصتنا','مدونة','وظائف','الصحافة'] : ['About','Story','Blog','Careers','Press'] }, { h: rtl ? 'المزوّدون' : 'For providers', items: rtl ? ['انضم كمزوّد','لوحة الإدارة','تطبيق التشغيل','الأسعار والعمولات','الموارد'] : ['Become a provider','Provider dashboard','Ops app','Pricing & commission','Resources'] }, { h: rtl ? 'الدعم' : 'Support', items: rtl ? ['مركز المساعدة','اتصل بنا','الشروط','الخصوصية','إعادة الجدولة'] : ['Help center','Contact','Terms','Privacy','Reschedules'] }, ]; return (

{rtl ? 'منصة سعودية تجمع ضيوف الرحمن مع أفضل مزوّدي خدمات العمرة.' : 'A Saudi marketplace connecting pilgrims with the best Umrah service providers.'}

{['phone','mail','globe'].map(i => (
))}
{cols.map(c => (
{c.h}
{c.items.map(it => ( {it} ))}
))}
© 2026 Duyuf · {rtl ? 'كل الحقوق محفوظة' : 'All rights reserved'}
{[ { t: rtl ? 'حمّل من' : 'Download', store: 'App Store', icon: '' }, { t: rtl ? 'متوفر على' : 'Get on', store: 'Google Play', icon: '▶' }, ].map((s, i) => (
{s.icon}
{s.t}
{s.store}
))}
{rtl ? 'المملكة العربية السعودية · SA' : 'Saudi Arabia · SA'}
); } // ─── Home page (the original landing) ───────────────────────────────── function WebHomePage({ theme, lang }) { const T = theme; return ( <> ); } // ─── Web App — page router ──────────────────────────────────────────── function WebApp({ theme, lang, onLanguageChange, dark = false, onThemeChange }) { const [page, setPage] = React.useState(() => { const requested = new URLSearchParams(window.location.search).get('page'); if (requested === 'provider-dashboard' && localStorage.getItem('duyuf_provider_session')) return 'provider-dashboard'; if (requested === 'payment-result') return 'payment-result'; return 'home'; }); const [pkg, setPkg] = React.useState(null); const ctx = React.useMemo(() => ({ page, setPage, pkg, setPkg }), [page, pkg]); const T = theme; const rtl = isRTL(lang); // Scroll to top on page change const scrollRef = React.useRef(null); React.useEffect(() => { if (scrollRef.current) scrollRef.current.scrollTop = 0; }, [page]); const Page = ({ home: WebHomePage, browse: WebBrowsePage, detail: WebDetailPage, checkout: WebCheckoutPage, 'payment-result': WebPaymentResultPage, 'become-provider': WebProviderSignupPage, contact: WebContactPage, signin: WebSignInPage, 'provider-dashboard': WebProviderDashboardPage, 'provider-add-package': WebProviderAddPackagePage, })[page] || WebHomePage; return (
); } // ─── Wrapped in a browser window for the canvas ────────────────────── function WebsiteArtboard({ theme, lang }) { return ( ); } Object.assign(window, { WebNav, WebHero, WebPackages, WebHowItWorks, WebProviders, WebBecomeProvider, WebAppDownload, WebFAQ, WebFooter, WebHomePage, WebApp, WebsiteArtboard, });