// pdp.jsx — product detail, cart, checkout, confirmation, quick-view modal
function PDP({ product, lang, addToCart, setRoute, openPDP }) {
const t = (ar, en) => lang === 'ar' ? ar : en;
const fam = SCENT_FAMILIES.find(f => f.id === product.family);
const [size, setSize] = React.useState(product.sizes[1]);
const [tab, setTab] = React.useState('notes');
const btnRef = React.useRef();
// Scent profile (synthetic, but consistent per product)
const profile = React.useMemo(() => {
const seed = product.id.charCodeAt(2);
const fams = ['oud', 'rose', 'amber', 'musk', 'spice', 'flora', 'woody'];
return fams.map((f, i) => {
let v = 20 + (((seed * (i + 3)) % 60));
if (f === product.family) v = 88 + ((seed % 10));
return { family: f, val: v };
});
}, [product.id]);
const related = PRODUCTS.filter(p => p.family === product.family && p.id !== product.id).slice(0, 4);
return (
<>
{t('استبرق', 'ISTABRAQ')}
N°{product.id.slice(1)}
{product.origin}
{product.year}
ISTABRAQ
{product.name_en}
{product.concentration} · {size.ml}ML
setRoute('shop')}>
{t('عودة للكولكشن', 'Back to collection')}
{lang === 'ar' ? fam.ar : fam.en} · {product.concentration}
{lang === 'ar' ? product.name_ar : product.name_en}
{lang === 'ar' ? product.name_en : product.name_ar}
AED {size.price}
{[...Array(5)].map((_, i) => )}
{product.rating} · 124 {t('تقييم', 'reviews')}
{lang === 'ar'
? `عطر يحكي ${fam.ar} من ${product.origin}. تفتح القصة بـ${product.top_ar}، تنبض بـ${product.heart_ar}، وتنغلق بنفس ${product.base_ar} يبقى على الجلد ساعات طويلة.`
: `A fragrance that tells the story of ${fam.en} from ${product.origin}. Opens with ${product.top_ar}, beats with ${product.heart_ar}, settles with ${product.base_ar} that lingers for hours.`}
{t('النوتة العليا', 'Top notes')}
{product.top_ar}
{t('قلب العطر', 'Heart')}
{product.heart_ar}
{t('القاعدة', 'Base')}
{product.base_ar}
{t('الحجم', 'Size')}
{product.sizes.map(s => (
setSize(s)}>
{s.ml}ml
AED {s.price}
))}
addToCart(product, btnRef.current, size)}>
{t('أضف للسلة', 'Add to bag')} · AED {size.price}
{/* Scent profile radar */}
{t('ملف الرائحة', 'Scent Profile')}
{profile.map(r => {
const f = SCENT_FAMILIES.find(x => x.id === r.family);
return (
{lang === 'ar' ? f.ar : f.en}
{r.val}
);
})}
✓ {t('شحن مجاني', 'Free shipping')}
{t('للطلبات فوق 350 AED', 'orders over AED 350')}
✓ {t('عينة مجانية', 'Free sample')}
{t('مع كل طلب', 'with every order')}
✓ {t('استرداد 14 يوم', '14-day returns')}
{t('غير مفتوح', 'unopened')}
{/* Related */}
{t('قد يعجبك أيضاً', 'You may also love')}
>
);
}
// ── Quick view modal ────────────────────────────────────────
function QuickView({ product, onClose, lang, addToCart, openFull }) {
const t = (ar, en) => lang === 'ar' ? ar : en;
const fam = SCENT_FAMILIES.find(f => f.id === product.family);
const [size, setSize] = React.useState(product.sizes[1]);
const btnRef = React.useRef();
return (
e.stopPropagation()}>
ISTABRAQ{product.name_en}
{lang === 'ar' ? fam.ar : fam.en} · {product.concentration}
{lang === 'ar' ? product.name_ar : product.name_en}
{lang === 'ar' ? product.name_en : product.name_ar}
AED {size.price}
{lang === 'ar' ? `${product.top_ar} · ${product.heart_ar} · ${product.base_ar}` : `${product.top_ar} · ${product.heart_ar} · ${product.base_ar}`}
{product.sizes.map(s => (
setSize(s)}>
{s.ml}ml
AED {s.price}
))}
{ addToCart(product, btnRef.current, size); onClose(); }}>
{t('أضف للسلة', 'Add to bag')}
{ openFull(product); onClose(); }}>
{t('التفاصيل', 'Details')}
);
}
// ── Cart ────────────────────────────────────────────────────
function Cart({ items, setItems, lang, setRoute }) {
const t = (ar, en) => lang === 'ar' ? ar : en;
const subtotal = items.reduce((s, i) => s + i.price * i.qty, 0);
const shipping = subtotal > 350 ? 0 : 25;
const tax = Math.round(subtotal * 0.05);
const total = subtotal + shipping + tax;
const updateQty = (idx, d) => {
const next = [...items];
next[idx] = { ...next[idx], qty: Math.max(1, next[idx].qty + d) };
setItems(next);
};
const remove = (idx) => setItems(items.filter((_, i) => i !== idx));
if (items.length === 0) {
return (
{t('السلة', 'Bag')}
{t('سلتك فارغة', 'Your bag is empty.')}
{t('استكشف عطور استبرق وابدأ رحلتك.', 'Browse our fragrances and begin your journey.')}
setRoute('shop')}>{t('تسوّق العطور', 'Shop fragrances')}
);
}
return (
{t('سلة التسوّق · 01', 'Shopping bag · 01')}
{t('السلة', 'Your bag')}
{items.reduce((s, i) => s + i.qty, 0)} {t('قطعة', 'items')}
{items.map((it, idx) => (
{lang === 'ar' ? it.name_ar : it.name_en}
{lang === 'ar' ? it.name_en : it.name_ar}
{it.size}ml · {it.concentration}
remove(idx)}>{t('إزالة', 'Remove')}
updateQty(idx, -1)}>
{it.qty}
updateQty(idx, 1)}>
{(it.price * it.qty).toLocaleString()} AED
))}
{t('الملخّص', 'Summary')}
{t('قبل الدفع', 'Before checkout')}
{t('المجموع الفرعي', 'Subtotal')}
{subtotal.toLocaleString()} AED
{t('الشحن', 'Shipping')}
{shipping === 0 ? t('مجاناً', 'Free') : `${shipping} AED`}
{t('الضريبة (٥٪)', 'VAT (5%)')}
{tax.toLocaleString()} AED
{t('الإجمالي', 'Total')}
{total.toLocaleString()} AED
setRoute('checkout')}>
{t('متابعة للدفع', 'Continue to checkout')}
setRoute('shop')}>
{t('استمر بالتسوّق', 'Continue shopping')}
✓
{t('عينة مجانية مع كل طلب', 'Free sample with every order')}
✓
{t('شحن مجاني فوق 350 AED', 'Free shipping over AED 350')}
);
}
// ── Checkout ────────────────────────────────────────────────
function Checkout({ items, lang, setRoute, setLastOrder }) {
const t = (ar, en) => lang === 'ar' ? ar : en;
const [pay, setPay] = React.useState('card');
const [form, setForm] = React.useState({
email: '', firstName: '', lastName: '', phone: '+971 50 ',
address: '', city: 'دبي', emirate: 'Dubai',
cardName: '', cardNumber: '4521 ', cardExp: '', cardCvc: '',
});
const upd = (k, v) => setForm({ ...form, [k]: v });
const subtotal = items.reduce((s, i) => s + i.price * i.qty, 0);
const shipping = subtotal > 350 ? 0 : 25;
const tax = Math.round(subtotal * 0.05);
const total = subtotal + shipping + tax;
const submit = () => {
const order = {
id: 'IST-' + (2826 + Math.floor(Math.random() * 100)),
items, total, customer: `${form.firstName} ${form.lastName}`,
email: form.email, phone: form.phone,
address: `${form.address}, ${form.city}, ${form.emirate}`,
pay, date: new Date().toISOString().slice(0, 10),
};
setLastOrder(order);
setRoute('confirm');
};
return (
{t('إتمام الشراء', 'Checkout')}
1
{t('الشحن', 'Shipping')}
2
{t('الدفع', 'Payment')}
3
{t('المراجعة', 'Review')}
{t('معلومات التوصيل', 'Delivery details')}
{t('البريد الإلكتروني', 'Email')} upd('email', e.target.value)} placeholder="you@example.ae" />
{t('الاسم الأول', 'First name')} upd('firstName', e.target.value)} />
{t('الاسم الأخير', 'Last name')} upd('lastName', e.target.value)} />
{t('الجوّال', 'Phone')} upd('phone', e.target.value)} />
{t('الإمارة', 'Emirate')}
upd('emirate', e.target.value)}>
Dubai Abu Dhabi Sharjah Ajman Ras Al Khaimah Fujairah Umm Al Quwain
{t('العنوان', 'Address')} upd('address', e.target.value)} placeholder={t('شارع، مبنى، شقة', 'Street, building, flat')} />
{t('طريقة الدفع', 'Payment method')}
setPay('card')}>
{t('بطاقة', 'Card')}
Visa · Master · Mada
setPay('apple')}>
Apple Pay
{t('سريع وآمن', 'Fast & secure')}
{pay === 'card' && (
{(form.cardNumber || '•••• •••• •••• ••••').padEnd(19, '•')}
{form.cardName || t('اسم حامل البطاقة', 'CARDHOLDER NAME')}
{form.cardExp || 'MM/YY'}
)}
{pay === 'apple' && (
{t('استخدم Touch ID أو Face ID للدفع', 'Use Touch ID or Face ID to pay')}
AED {total.toLocaleString()}
)}
{t(`أكّد الطلب · AED ${total.toLocaleString()}`, `Place order · AED ${total.toLocaleString()}`)}
);
}
// ── Confirmation ────────────────────────────────────────────
function Confirmation({ order, lang, setRoute }) {
const t = (ar, en) => lang === 'ar' ? ar : en;
if (!order) return null;
return (
✓
{t('تأكيد الطلب', 'Order confirmed')}
{t('شكراً لك', 'Thank you.')}
{t(`أرسلنا تأكيد الطلب إلى ${order.email}. سيصلك خلال 48 ساعة.`,
`We sent a confirmation to ${order.email}. Your bottles arrive within 48 hours.`)}
{t('رقم الطلب', 'Order number')}
{order.id}
{t('الإجمالي', 'Total')}
AED {order.total.toLocaleString()}
{t('التوصيل إلى', 'Delivering to')}
{order.customer}
{order.address}
{t('الموعد المتوقّع', 'Estimated arrival')}
{t('خلال يومين عمل', '2 business days')}
{t('قائمة العطور', 'Your fragrances')}
{order.items.map((it, idx) => (
{lang === 'ar' ? it.name_ar : it.name_en}
{it.size}ml × {it.qty}
{(it.price * it.qty).toLocaleString()}
))}
setRoute('home')}>{t('العودة للرئيسية', 'Back home')}
setRoute('shop')}>{t('متابعة التسوّق', 'Continue shopping')}
);
}
window.PDP = PDP;
window.QuickView = QuickView;
window.Cart = Cart;
window.Checkout = Checkout;
window.Confirmation = Confirmation;