/* ========================================================
غمبولة بيوتي — App Logic
⚠️ منطق الأعمال (الكتالوج / الأسعار / صيغة نص الأوردر / الأرقام الثابتة /
طريقة الحفظ في localStorage) منقول زي ما هو من النسخة السابقة بدون أي تغيير.
ممنوع تتغير القيم دي إلا لو طُلب صراحة.
======================================================== */
// =========================================================
// 1) الكتالوج (زي ما هو بالظبط — الأسماء والأحجام والأسعار)
// =========================================================
// ⚠️ سعر البخاخ هنا 365 ج (زي الكتالوج الرسمي). لو الرقم الصح فعليًا 356،
// غيّري الرقم في السطر اللي فيه "بخاخ علاج التساقط" تحت.
const CATALOG = [
{ cat: "روتين العناية بالشعر", items: [
{ name: "بخاخ علاج التساقط", sizes: [["125 مل", 365]] },
{ name: "تركيبة روبانزل", sizes: [["125 مل", 225]] },
{ name: "شامبو", sizes: [["125 مل", 110], ["200 مل", 190]] },
{ name: "بلسم", sizes: [["125 مل", 110], ["200 مل", 190]] },
{ name: "حمام كريم", sizes: [["200 مل", 175], ["350 مل", 275]] },
{ name: "سيرم", sizes: [["125 مل", 275]] },
{ name: "كريم تسريح", sizes: [["125 مل", 165], ["250 مل", 265]] },
{ name: "الروتين الكامل (باقة)", sizes: [["كل المنتجات", 1425]] },
]},
{ cat: "زيوت ومكملات فردية", items: [
{ name: "خلطة مساج", sizes: [["-", 265]] },
{ name: "جوز هند", sizes: [["125 مل", 205]] },
{ name: "نبتة شيا", sizes: [["50 مل", 140]] },
{ name: "أرجان بجوجوبا", sizes: [["-", 265]] },
{ name: "جوجوبا", sizes: [["125 مل", 185]] },
{ name: "هير سول (ماء ورد)", sizes: [["200 مل", 100]] },
]},
{ cat: "العناية بالبشرة والجسم", items: [
{ name: "كريم تفتيح الجسم", sizes: [["300 مل", 350]] },
{ name: "الشمعة المنورة", sizes: [["-", 285]] },
]},
{ cat: "الرموش والحواجب", items: [
{ name: "ماسكرا الرموش والحواجب", sizes: [["10 مل", 265]] },
]},
{ cat: "شامبو القشرة", items: [
{ name: "شامبو القشرة", sizes: [["-", 275]] },
]},
];
let customRows = [];
let customIdCounter = 0;
let orderLog = [];
// =========================================================
// 2) Navigation (Bottom Nav + Screens)
// =========================================================
const SCREEN_TITLES = {
home: 'إدارة الأوردرات',
products: 'اختيار المنتجات',
order: 'مراجعة الأوردر',
customer: 'بيانات العميل',
preview: 'إرسال الأوردر',
earnings: 'الأرباح',
};
function showScreen(name){
document.querySelectorAll('.screen').forEach(s => s.classList.toggle('active', s.dataset.screen === name));
document.querySelectorAll('.nav-btn[data-screen-btn]').forEach(b => {
b.classList.toggle('active', b.dataset.screenBtn === name);
});
document.getElementById('headerSubtitle').textContent = SCREEN_TITLES[name] || '';
document.getElementById('app').scrollTop = 0;
window.scrollTo(0,0);
updateStickyBar();
if(name === 'earnings') renderCounter();
// ملحوظة: render() بيتنادى من كل الـ inputs عند أي تغيير، وبيحدّث
// الداشبورد ونص المعاينة أوتوماتيك، فمش محتاجين ننادي حاجة تانية هنا
// (تجنّبًا لأي استدعاء متبادل بين الدوال).
render();
}
function initNav(){
document.querySelectorAll('[data-screen-btn]').forEach(btn => {
btn.addEventListener('click', () => showScreen(btn.dataset.screenBtn));
});
document.querySelectorAll('[data-goto]').forEach(btn => {
btn.addEventListener('click', () => showScreen(btn.dataset.goto));
});
}
// =========================================================
// 3) بناء قايمة المنتجات (Accordion + Cards)
// =========================================================
function buildCategories(){
const container = document.getElementById('categoriesContainer');
container.innerHTML = '';
CATALOG.forEach((catObj, ci) => {
const catDiv = document.createElement('div');
catDiv.className = 'cat' + (ci === 0 ? ' open' : '');
catDiv.innerHTML = `
`;
container.appendChild(catDiv);
const body = catDiv.querySelector(`#catBody${ci}`);
catObj.items.forEach((item, ii) => {
const row = document.createElement('div');
row.className = 'prod-card';
row.id = `prodCard_${ci}_${ii}`;
const sizeOptions = item.sizes.map((s, si) => ``).join('');
row.innerHTML = `
`;
body.appendChild(row);
});
});
container.querySelectorAll('[data-toggle-cat]').forEach(header => {
header.addEventListener('click', () => {
header.closest('.cat').classList.toggle('open');
});
});
container.querySelectorAll('[data-render-on-change]').forEach(sel => {
sel.addEventListener('change', render);
});
container.querySelectorAll('[data-qty-step]').forEach(btn => {
btn.addEventListener('click', () => {
const targetId = btn.dataset.qtyTarget;
const el = document.getElementById(targetId);
const step = Number(btn.dataset.qtyStep);
let current = Number(el.textContent) || 0;
current = Math.max(0, current + step);
el.textContent = current;
render();
});
});
}
function getQty(ci, ii){
const el = document.getElementById(`qty_${ci}_${ii}`);
return el ? (Number(el.textContent) || 0) : 0;
}
// =========================================================
// 4) منتج مخصص
// =========================================================
function addCustomRow(){
const id = customIdCounter++;
customRows.push({ id, name: '', size: '', price: 0, qty: 0 });
renderCustomRows();
}
function removeCustomRow(id){
customRows = customRows.filter(r => r.id !== id);
renderCustomRows();
render();
}
function renderCustomRows(){
const el = document.getElementById('customList');
if(customRows.length === 0){
el.innerHTML = 'مفيش منتجات مخصصة مضافة
';
return;
}
el.innerHTML = customRows.map(r => `
`).join('');
el.querySelectorAll('[data-rm-custom]').forEach(b => {
b.addEventListener('click', () => removeCustomRow(Number(b.dataset.rmCustom)));
});
el.querySelectorAll('[data-custom-field]').forEach(inp => {
inp.addEventListener('input', () => {
const id = Number(inp.dataset.customId);
const field = inp.dataset.customField;
updateCustom(id, field, inp.value);
});
});
el.querySelectorAll('[data-custom-qty-step]').forEach(b => {
b.addEventListener('click', () => {
const id = Number(b.dataset.customQtyId);
const row = customRows.find(r => r.id === id);
if(!row) return;
row.qty = Math.max(0, (row.qty || 0) + Number(b.dataset.customQtyStep));
const span = el.querySelector(`[data-custom-qty-value="${id}"]`);
if(span) span.textContent = row.qty;
render();
});
});
}
function updateCustom(id, field, value){
const row = customRows.find(r => r.id === id);
if(!row) return;
row[field] = (field === 'price') ? Number(value) : value;
render();
}
// =========================================================
// 5) localStorage — نفس المفاتيح القديمة بالظبط
// =========================================================
function saveManagerPhone(){ try { localStorage.setItem('gamboola_manager_phone', document.getElementById('managerPhone').value); } catch(e){} }
function loadManagerPhone(){ try { const v = localStorage.getItem('gamboola_manager_phone'); if(v) document.getElementById('managerPhone').value = v; } catch(e){} }
function saveAgentName(){ try { localStorage.setItem('gamboola_agent_name', document.getElementById('agentName').value); } catch(e){} }
function loadAgentName(){ try { const v = localStorage.getItem('gamboola_agent_name'); if(v) document.getElementById('agentName').value = v; } catch(e){} }
function saveRate(){ try { localStorage.setItem('gamboola_rate', document.getElementById('rate').value); } catch(e){} }
function loadRate(){ try { const v = localStorage.getItem('gamboola_rate'); if(v) document.getElementById('rate').value = v; } catch(e){} }
function saveNotifyPhone(){ try { localStorage.setItem('gamboola_notify_phone', document.getElementById('notifyPhone').value); } catch(e){} }
function loadNotifyPhone(){ try { const v = localStorage.getItem('gamboola_notify_phone'); if(v) document.getElementById('notifyPhone').value = v; } catch(e){} }
function loadOrderLog(){
try { const v = localStorage.getItem('gamboola_order_log'); orderLog = v ? JSON.parse(v) : []; }
catch(e){ orderLog = []; }
}
function saveOrderLog(){ try { localStorage.setItem('gamboola_order_log', JSON.stringify(orderLog)); } catch(e){} }
function todayStr(){
const d = new Date();
return `${d.getDate()}/${d.getMonth()+1}/${d.getFullYear()}`;
}
// =========================================================
// 6) الحساب الرئيسي + بناء نص الأوردر (منطق الأعمال الأصلي)
// =========================================================
function collectItems(){
let items = [];
let productsTotal = 0;
CATALOG.forEach((catObj, ci) => {
catObj.items.forEach((item, ii) => {
const sizeSel = document.getElementById(`size_${ci}_${ii}`);
const qty = getQty(ci, ii);
const sizeIdx = Number(sizeSel.value);
const [sizeLabel, price] = item.sizes[sizeIdx];
const lineTotal = qty * price;
const ltEl = document.getElementById(`lt_${ci}_${ii}`);
if(ltEl) ltEl.textContent = lineTotal + ' ج';
const card = document.getElementById(`prodCard_${ci}_${ii}`);
if(card) card.classList.toggle('selected', qty > 0);
if(qty > 0){
items.push({ name: item.name, size: sizeLabel, qty, price, lineTotal });
productsTotal += lineTotal;
}
});
});
customRows.forEach(r => {
const lineTotal = (r.qty || 0) * (r.price || 0);
if(r.qty > 0 && r.name){
items.push({ name: r.name, size: r.size || '', qty: r.qty, price: r.price, lineTotal });
productsTotal += lineTotal;
}
});
return { items, productsTotal };
}
function render(){
const { items, productsTotal } = collectItems();
const shipping = Number(document.getElementById('shipping').value) || 0;
const grandTotal = productsTotal + shipping;
document.getElementById('productsTotal').textContent = productsTotal + ' ج';
document.getElementById('grandTotal').textContent = grandTotal + ' ج';
// ملخص شاشة "الأوردر"
const summaryEl = document.getElementById('orderSummaryList');
if(items.length === 0){
summaryEl.innerHTML = '🛒مفيش منتجات متضافة للطلب لسه
';
} else {
summaryEl.innerHTML = items.map(it => `
${it.name}
${it.size ? it.size + ' • ' : ''}الكمية ${it.qty}
${it.lineTotal} ج
`).join('');
}
const totalQty = items.reduce((s,it)=>s+it.qty,0);
updateStickyBar(totalQty, grandTotal);
updateNavBadge(totalQty);
// بنحدّث الداشبورد ونص الأوردر النهائي دايمًا (حسابات رخيصة)،
// من غير أي استدعاء متبادل بين الدوال عشان نتجنب أي تكرار لا نهائي.
renderHome(items, productsTotal);
buildOutputText(items, shipping, grandTotal);
return { items, productsTotal, shipping, grandTotal };
}
// ⚠️ صيغة نص الأوردر — الأرقام الثابتة (1500 / 000000) والفواصل والترتيب
// منقولين حرفيًا زي ما اتأكد عليهم. ممنوع تتغير إلا بطلب صريح.
function buildOutputText(items, shipping, grandTotal){
let productsLine = '';
if(items.length === 0){
productsLine = '(لسه مفيش منتجات مختارة)';
} else {
const parts = items.map(it => {
const qtyPart = it.qty > 1 ? `×${it.qty}` : '';
const sizePart = it.size ? ` ${it.size}` : '';
return `${it.name}${sizePart}${qtyPart} ${it.lineTotal}`;
});
parts.push(`شحن ${shipping}`);
productsLine = parts.join('+');
}
const name = document.getElementById('custName').value || '';
const phone1 = document.getElementById('phone1').value || '';
const phone2 = document.getElementById('phone2').value || '';
const address = document.getElementById('address').value || '';
const agentName = document.getElementById('agentName').value || '';
const date = document.getElementById('orderDate').value || todayStr();
const text =
`الاوردر /${productsLine}
1500
000000
${grandTotal}
000000
${name}
${phone1}
${phone2}
العنوان بالتفصيل / ${address}
${agentName} ${date}`;
document.getElementById('outputText').value = text;
}
// =========================================================
// 7) نسخ + واتساب (نفس المنطق الأصلي، مع fallback للموبايل)
// =========================================================
function copyText(){
const ta = document.getElementById('outputText');
const btn = document.getElementById('copyBtn');
const orig = btn.innerHTML;
const done = () => {
btn.innerHTML = 'تم النسخ ✓';
btn.style.background = 'linear-gradient(135deg, #4CAF7D, #3d9469)';
showToast('تم نسخ النص ✓');
setTimeout(() => { btn.innerHTML = orig; btn.style.background = ''; }, 1500);
};
if(navigator.clipboard && navigator.clipboard.writeText){
navigator.clipboard.writeText(ta.value).then(done).catch(() => fallbackCopy(ta, done));
} else {
fallbackCopy(ta, done);
}
}
function fallbackCopy(ta, done){
ta.removeAttribute('readonly');
ta.focus();
ta.select();
try { document.execCommand('copy'); done(); } catch(e){ showToast('انسخي النص يدويًا بالضغط المطول عليه'); }
ta.setAttribute('readonly', true);
}
function sendWhatsapp(){
const text = encodeURIComponent(document.getElementById('outputText').value);
const phone = document.getElementById('managerPhone').value.replace(/[^0-9]/g, '');
const url = phone ? `https://wa.me/${phone}?text=${text}` : `https://wa.me/?text=${text}`;
window.open(url, '_blank');
}
// =========================================================
// 8) عداد الأوردرات والأرباح (نفس المنطق الأصلي)
// =========================================================
function registerOrder(){
const name = document.getElementById('custName').value || '(بدون اسم)';
const grand = document.getElementById('grandTotal').textContent;
const date = document.getElementById('orderDate').value || todayStr();
orderLog.push({ name, grand, date, ts: Date.now() });
saveOrderLog();
renderCounter();
renderHome();
showToast('تم تسجيل الأوردر ✅');
}
function undoLastOrder(){
if(orderLog.length === 0) return;
if(!confirm('متأكدة تمسحي آخر أوردر مسجل؟')) return;
orderLog.pop();
saveOrderLog();
renderCounter();
renderHome();
}
function clearLog(){
if(!confirm('متأكدة تمسحي كل السجل والعدّاد يرجع صفر؟')) return;
orderLog = [];
saveOrderLog();
renderCounter();
renderHome();
}
function renderCounter(){
const rate = Number(document.getElementById('rate').value) || 0;
const count = orderLog.length;
const earned = count * rate;
document.getElementById('earnCount').textContent = count;
document.getElementById('earnRateDisplay').textContent = rate + ' ج';
document.getElementById('earnTotal').textContent = earned + ' ج';
const logEl = document.getElementById('orderLog');
if(count === 0){
logEl.innerHTML = '🗒️مفيش أوردرات مسجلة لسه
';
} else {
const last15 = orderLog.slice(-15).reverse();
logEl.innerHTML = last15.map((o, i) => `
${o.grand}
#${count - i} — ${o.name}
${o.date}
`).join('');
}
}
function notifyWhatsapp(){
const rate = Number(document.getElementById('rate').value) || 0;
const count = orderLog.length;
const earned = count * rate;
const msg = `تحديث أوردرات غمبولة 📊\nعدد الأوردرات: ${count}\nالمستحق: ${earned} جنيه`;
const text = encodeURIComponent(msg);
const phone = document.getElementById('notifyPhone').value.replace(/[^0-9]/g, '');
const url = phone ? `https://wa.me/${phone}?text=${text}` : `https://wa.me/?text=${text}`;
window.open(url, '_blank');
}
// =========================================================
// 9) واجهة إضافية: Home dashboard / Sticky bar / Badge / Toast
// =========================================================
// items/productsTotal اختياريين — لو معدّياش، بتتحسب من تاني (بدون ما تنادي render()).
function renderHome(items, productsTotal){
if(items === undefined){
const collected = collectItems();
items = collected.items;
productsTotal = collected.productsTotal;
}
const rate = Number(document.getElementById('rate').value) || 0;
document.getElementById('homeOrderCount').textContent = orderLog.length;
document.getElementById('homeEarned').textContent = (orderLog.length * rate) + ' ج';
const shipping = Number(document.getElementById('shipping').value) || 0;
document.getElementById('homeCartItems').textContent = items.reduce((s,it)=>s+it.qty,0);
document.getElementById('homeCartTotal').textContent = (items.length ? productsTotal + shipping : 0) + ' ج';
}
// totalQty/grandTotal اختياريين — لو معدّياش، بيتحسبوا من تاني.
function updateStickyBar(totalQty, grandTotal){
const bar = document.getElementById('stickyOrderBar');
const productsScreenActive = document.querySelector('.screen[data-screen="products"]').classList.contains('active');
if(!productsScreenActive){ bar.classList.remove('show'); return; }
if(totalQty === undefined){
const collected = collectItems();
totalQty = collected.items.reduce((s,it)=>s+it.qty,0);
const shipping = Number(document.getElementById('shipping').value) || 0;
grandTotal = collected.productsTotal + shipping;
}
if(!totalQty){
bar.classList.remove('show');
return;
}
document.getElementById('stickyText').textContent = `${totalQty} منتجات — ${grandTotal} ج`;
bar.classList.add('show');
}
function updateNavBadge(count){
const badge = document.getElementById('productsBadge');
if(count > 0){
badge.textContent = count;
badge.classList.remove('hidden');
} else {
badge.classList.add('hidden');
}
}
let toastTimer = null;
function showToast(msg){
const toast = document.getElementById('toast');
toast.textContent = msg;
toast.classList.add('show');
clearTimeout(toastTimer);
toastTimer = setTimeout(() => toast.classList.remove('show'), 1800);
}
function resetCurrentOrder(){
CATALOG.forEach((catObj, ci) => {
catObj.items.forEach((item, ii) => {
const qtyEl = document.getElementById(`qty_${ci}_${ii}`);
if(qtyEl) qtyEl.textContent = '0';
const sizeEl = document.getElementById(`size_${ci}_${ii}`);
if(sizeEl) sizeEl.value = '0';
});
});
customRows = [];
renderCustomRows();
document.getElementById('custName').value = '';
document.getElementById('phone1').value = '';
document.getElementById('phone2').value = '';
document.getElementById('address').value = '';
document.getElementById('orderDate').value = todayStr();
render();
renderHome();
}
// =========================================================
// 10) PWA: تسجيل Service Worker + زرار التثبيت
// =========================================================
function registerServiceWorker(){
if('serviceWorker' in navigator){
window.addEventListener('load', () => {
navigator.serviceWorker.register('sw.js').catch(() => {});
});
}
}
let deferredInstallPrompt = null;
function initInstallPrompt(){
const installBtn = document.getElementById('installBtn');
window.addEventListener('beforeinstallprompt', (e) => {
e.preventDefault();
deferredInstallPrompt = e;
installBtn.classList.add('show');
});
installBtn.addEventListener('click', async () => {
if(!deferredInstallPrompt) return;
deferredInstallPrompt.prompt();
await deferredInstallPrompt.userChoice;
deferredInstallPrompt = null;
installBtn.classList.remove('show');
});
window.addEventListener('appinstalled', () => {
installBtn.classList.remove('show');
showToast('تم تثبيت التطبيق 🎉');
});
// iOS Safari: مفيش beforeinstallprompt، فبنعرض تلميح بسيط بدل ما نضايق المستخدم
const isIos = /iphone|ipad|ipod/i.test(navigator.userAgent);
const isStandalone = window.navigator.standalone === true || window.matchMedia('(display-mode: standalone)').matches;
const dismissed = localStorage.getItem('gamboola_ios_hint_dismissed') === '1';
if(isIos && !isStandalone && !dismissed){
document.getElementById('iosHint').classList.remove('hidden');
}
document.getElementById('closeIosHint').addEventListener('click', () => {
document.getElementById('iosHint').classList.add('hidden');
try { localStorage.setItem('gamboola_ios_hint_dismissed', '1'); } catch(e){}
});
}
// =========================================================
// 11) ربط الأحداث العامة + التشغيل الأول
// =========================================================
function initFieldListeners(){
['shipping'].forEach(id => document.getElementById(id).addEventListener('input', render));
['custName','phone1','phone2','address'].forEach(id => document.getElementById(id).addEventListener('input', render));
document.getElementById('agentName').addEventListener('input', () => { saveAgentName(); render(); });
document.getElementById('orderDate').addEventListener('input', render);
document.getElementById('managerPhone').addEventListener('input', saveManagerPhone);
document.getElementById('rate').addEventListener('input', () => { saveRate(); renderCounter(); renderHome(); });
document.getElementById('notifyPhone').addEventListener('input', saveNotifyPhone);
document.getElementById('addCustomBtn').addEventListener('click', addCustomRow);
document.getElementById('copyBtn').addEventListener('click', copyText);
document.getElementById('sendWaBtn').addEventListener('click', sendWhatsapp);
document.getElementById('registerOrderBtn').addEventListener('click', registerOrder);
document.getElementById('undoOrderBtn').addEventListener('click', undoLastOrder);
document.getElementById('clearLogBtn').addEventListener('click', clearLog);
document.getElementById('notifyWaBtn').addEventListener('click', notifyWhatsapp);
document.getElementById('startNewOrderBtn').addEventListener('click', () => {
resetCurrentOrder();
showScreen('products');
});
document.getElementById('goToCustomerBtn').addEventListener('click', () => showScreen('customer'));
document.getElementById('goToPreviewBtn').addEventListener('click', () => showScreen('preview'));
}
function init(){
document.getElementById('orderDate').value = todayStr();
buildCategories();
renderCustomRows();
loadManagerPhone();
loadAgentName();
loadRate();
loadNotifyPhone();
loadOrderLog();
initFieldListeners();
initNav();
registerServiceWorker();
initInstallPrompt();
render();
renderCounter();
renderHome();
showScreen('home');
}
document.addEventListener('DOMContentLoaded', init);