Skip to content

ALAZAB #3294

Description

@tarekmsre5-design

<!doctype html>

<title>Barber Queue</title> <script src="https://cdn.tailwindcss.com/3.4.17"></script> <script src="https://cdn.jsdelivr.net/npm/lucide@0.263.0/dist/umd/lucide.min.js"></script> <script src="/_sdk/element_sdk.js"></script> <script src="/_sdk/data_sdk.js"></script> <style> * { font-family: 'Tajawal', sans-serif; } .queue-item { animation: slideIn 0.3s ease-out; } @Keyframes slideIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } @Keyframes pulse-dot { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.4); } } .pulse-dot { animation: pulse-dot 1.5s infinite; } </style> <style>body { box-sizing: border-box; }</style>

ALAZABBARE

مرحباً بكم - احجز دورك الآن

عدد المنتظرين

0

الوقت التقريبي

0 د

احجز دورك

الاسم
رقم الجوال
احجز الآن

قائمة الانتظار

لا يوجد أحد في الانتظار

<script> const defaultConfig = { shop_name: "ALAZABBARE" welcome_text: 'مرحباً بكم - احجز دورك الآن', background_color: '#0f1923', surface_color: '#1a2a3a', text_color: '#ffffff', primary_color: '#f59e0b', secondary_color: '#8ba4b8', font_family: 'Tajawal', font_size: 16 };

let allData = [];
let currentConfig = { ...defaultConfig };

// Element SDK
window.elementSdk.init({
defaultConfig,
onConfigChange: async (config) => {
currentConfig = { ...defaultConfig, ...config };
document.getElementById('shop-name').textContent = currentConfig.shop_name;
document.getElementById('welcome-text').textContent = currentConfig.welcome_text;
document.getElementById('app').style.backgroundColor = currentConfig.background_color;
document.getElementById('shop-name').style.color = currentConfig.primary_color;
document.querySelectorAll('.queue-pos').forEach(el => el.style.backgroundColor = currentConfig.primary_color);
},
mapToCapabilities: (config) => ({
recolorables: [
{ get: () => config.background_color || defaultConfig.background_color, set: (v) => { config.background_color = v; window.elementSdk.setConfig({ background_color: v }); } },
{ get: () => config.surface_color || defaultConfig.surface_color, set: (v) => { config.surface_color = v; window.elementSdk.setConfig({ surface_color: v }); } },
{ get: () => config.text_color || defaultConfig.text_color, set: (v) => { config.text_color = v; window.elementSdk.setConfig({ text_color: v }); } },
{ get: () => config.primary_color || defaultConfig.primary_color, set: (v) => { config.primary_color = v; window.elementSdk.setConfig({ primary_color: v }); } },
{ get: () => config.secondary_color || defaultConfig.secondary_color, set: (v) => { config.secondary_color = v; window.elementSdk.setConfig({ secondary_color: v }); } }
],
borderables: [],
fontEditable: { get: () => config.font_family || defaultConfig.font_family, set: (v) => { config.font_family = v; window.elementSdk.setConfig({ font_family: v }); } },
fontSizeable: { get: () => config.font_size || defaultConfig.font_size, set: (v) => { config.font_size = v; window.elementSdk.setConfig({ font_size: v }); } }
}),
mapToEditPanelValues: (config) => new Map([
['shop_name', config.shop_name || defaultConfig.shop_name],
['welcome_text', config.welcome_text || defaultConfig.welcome_text]
])
});

// Data SDK
const dataHandler = {
onDataChanged(data) {
allData = data.filter(d => d.status === 'waiting').sort((a, b) => a.position - b.position);
renderQueue();
}
};

function renderQueue() {
const list = document.getElementById('queue-list');
const empty = document.getElementById('empty-msg');
const countEl = document.getElementById('queue-count');
const waitEl = document.getElementById('wait-time');

countEl.textContent = allData.length;
waitEl.textContent = (allData.length * 15) + ' د';

if (allData.length === 0) {
  list.innerHTML = '';
  list.appendChild(empty);
  empty.classList.remove('hidden');
  return;
}

const existingMap = new Map([...list.children].map(el => [el.dataset.id, el]));
const fragment = document.createDocumentFragment();

allData.forEach((item, i) => {
  let el = existingMap.get(item.__backendId);
  if (el) {
    el.querySelector('.queue-name').textContent = item.name;
    el.querySelector('.queue-pos-num').textContent = i + 1;
    existingMap.delete(item.__backendId);
  } else {
    el = document.createElement('div');
    el.dataset.id = item.__backendId;
    el.className = 'queue-item bg-[#1a2a3a] border border-[#2a4a5a] rounded-xl p-3 flex items-center justify-between';
    el.innerHTML = `
      <div class="flex items-center gap-3">
        <span class="queue-pos w-8 h-8 rounded-full bg-[#f59e0b] text-[#0f1923] flex items-center justify-center font-700 text-sm"><span class="queue-pos-num">${i + 1}</span></span>
        <div>
          <p class="queue-name font-500">${item.name}</p>
          <p class="text-xs text-[#8ba4b8]">${item.phone || ''}</p>
        </div>
      </div>
      <button class="done-btn text-xs bg-green-600 hover:bg-green-700 text-white px-3 py-1.5 rounded-lg transition-colors">تم ✓</button>
    `;
    el.querySelector('.done-btn').addEventListener('click', () => markDone(item));
  }
  fragment.appendChild(el);
});

existingMap.forEach(el => el.remove());
list.innerHTML = '';
list.appendChild(fragment);

}

async function markDone(item) {
const updated = { ...item, status: 'done' };
const result = await window.dataSdk.update(updated);
if (!result.isOk) showError('حدث خطأ');
}

function showError(msg) {
const el = document.getElementById('form-error');
el.textContent = msg; el.classList.remove('hidden');
setTimeout(() => el.classList.add('hidden'), 3000);
}

function showSuccess(msg) {
const el = document.getElementById('form-success');
el.textContent = msg; el.classList.remove('hidden');
setTimeout(() => el.classList.add('hidden'), 3000);
}

document.getElementById('booking-form').addEventListener('submit', async (e) => {
e.preventDefault();
const name = document.getElementById('name-input').value.trim();
const phone = document.getElementById('phone-input').value.trim();
if (!name) { showError('الرجاء إدخال الاسم'); return; }
if (allData.length >= 999) { showError('القائمة ممتلئة'); return; }

const btn = document.getElementById('submit-btn');
btn.disabled = true; btn.textContent = 'جاري الحجز...';

const position = allData.length + 1;
const result = await window.dataSdk.create({ name, phone, position, status: 'waiting', created_at: new Date().toISOString() });

btn.disabled = false; btn.textContent = 'احجز الآن';
if (result.isOk) {
  showSuccess(`تم الحجز! دورك رقم ${position}`);
  document.getElementById('name-input').value = '';
  document.getElementById('phone-input').value = '';
} else {
  showError('حدث خطأ، حاول مرة أخرى');
}

});

window.dataSdk.init(dataHandler);
lucide.createIcons();
</script>

<script>(function(){function c(){var b=a.contentDocument||a.contentWindow.document;if(b){var d=b.createElement('script');d.innerHTML="window.__CF$cv$params={r:'a03f25a97803d233',t:'MTc4MDE1ODg3NQ=='};var a=document.createElement('script');a.src='/cdn-cgi/challenge-platform/scripts/jsd/main.js';document.getElementsByTagName('head')[0].appendChild(a);";b.getElementsByTagName('head')[0].appendChild(d)}}if(document.body){var a=document.createElement('iframe');a.height=1;a.width=1;a.style.position='absolute';a.style.top=0;a.style.left=0;a.style.border='none';a.style.visibility='hidden';document.body.appendChild(a);if('loading'!==document.readyState)c();else if(window.addEventListener)document.addEventListener('DOMContentLoaded',c);else{var e=document.onreadystatechange||function(){};document.onreadystatechange=function(b){e(b);'loading'!==document.readyState&&(document.onreadystatechange=e,c())}}}})();</script>

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions