Booking360 - Master Booking Engine

Booking360

Smart Booking. Simple Operation.

Sign in to your account

Demo Credentials (password: password)

Create your customer account

Reset your password

SIFUROBOT SOLUTIONS (003222179-X)

Dashboard

`); } /* ============================================================ REPORTS VIEW ============================================================ */ let reportFilter = { start: '', end: '' }; function renderReports() { if (!reportFilter.start) { const d = new Date(); d.setDate(d.getDate()-30); reportFilter.start = d.toISOString().split('T')[0]; reportFilter.end = todayStr(); } const bkgs = ReportService.bookingsByDateRange(reportFilter.start, reportFilter.end); const revenue = ReportService.revenueByDateRange(reportFilter.start, reportFilter.end); const topServices = ReportService.topServices().slice(0,5); const providerPerf = ReportService.providerPerformance(); const cancelled = bkgs.filter(b => b.status === 'cancelled'); $('contentArea').innerHTML = `
${statCard('Bookings', bkgs.length, 'calendar', 'blue')} ${statCard('Revenue', formatMoney(revenue), 'dollar-sign', 'green')} ${statCard('Cancelled', cancelled.length, 'x-circle', 'red')} ${statCard('Completed', bkgs.filter(b=>b.status==='completed').length, 'check-circle', 'purple')}

Top Services

Bookings by Day

${getIndustryPreset().providerLabel} Performance

${providerPerf.map(p => ``).join('')}
${getIndustryPreset().providerLabel}TotalCompletedCancelledRevenue
${escapeHtml(p.provider?.name||'-')} ${p.total} ${p.completed} ${p.cancelled} ${formatMoney(p.revenue)}
`; setTimeout(() => { State.charts.topServices = new Chart($('topServicesChart'), { type:'bar', data:{ labels: topServices.map(t => t.service?.name||'?'), datasets:[{ label:'Bookings', data: topServices.map(t => t.count), backgroundColor:'#2563eb', borderRadius:6 }] }, options:{ responsive:true, maintainAspectRatio:false, plugins:{legend:{display:false}}, scales:{y:{beginAtZero:true}} } }); // daily chart const days = {}; bkgs.forEach(b => { days[b.date] = (days[b.date]||0)+1; }); const sortedDays = Object.keys(days).sort(); State.charts.daily = new Chart($('dailyChart'), { type:'line', data:{ labels: sortedDays.map(d => formatDate(d)), datasets:[{ label:'Bookings', data: sortedDays.map(d => days[d]), borderColor:'#10b981', backgroundColor:'rgba(16,185,129,.1)', fill:true, tension:.3 }] }, options:{ responsive:true, maintainAspectRatio:false, plugins:{legend:{display:false}}, scales:{y:{beginAtZero:true}} } }); }, 50); safeIcons(); } function exportReportsCSV() { const bkgs = ReportService.bookingsByDateRange(reportFilter.start, reportFilter.end); const rows = bkgs.map(b => { const c = Api.customers.get(b.customer_id); const s = Api.services.get(b.service_id); const p = Api.providers.get(b.provider_id); return { id:b.id, date:b.date, time:b.start_time, customer:c?.name, service:s?.name, provider:p?.name, status:b.status, amount:b.amount, payment:b.payment_status }; }); exportCSV('report-bookings.csv', rows); } /* ============================================================ USERS VIEW ============================================================ */ let userFilters = { search:'', role:'', status:'' }; function renderUsers() { let users = Api.users.list(); if (State.user.role === 'business_admin') users = users.filter(u => u.business_id === getCurrentBusinessId()); if (userFilters.search) { const q = userFilters.search.toLowerCase(); users = users.filter(u => u.name.toLowerCase().includes(q) || u.email.toLowerCase().includes(q)); } if (userFilters.role) users = users.filter(u => u.role === userFilters.role); if (userFilters.status) users = users.filter(u => u.status === userFilters.status); $('contentArea').innerHTML = `
${users.map(u => ``).join('')}
NameEmailPhoneRoleStatusActions
${escapeHtml(u.name)} ${escapeHtml(u.email)} ${escapeHtml(u.phone||'-')} ${roleLabel(u.role)} ${statusActiveBadge(u.status)}
`; safeIcons(); } function openUserForm(id=null) { const u = id ? Api.users.get(id) : null; openModal(`

${u?'Edit':'Add'} User

`); } function submitUserForm(id) { const f = $('userForm'); if (!f.name.value || !f.email.value || !/\S+@\S+\.\S+/.test(f.email.value)) { toast('Valid name & email required','error'); return; } const data = { name:f.name.value, email:f.email.value, phone:f.phone.value, role:f.role.value, status:f.status.value, business_id: getCurrentBusinessId() }; if (f.password.value) data.password = f.password.value; if (id) Api.users.update(id, data); else Api.users.create({...data, password: data.password||'password'}); toast(id?'Updated':'Added','success'); closeModal(); renderPage(); } function toggleUserStatus(id) { const u = Api.users.get(id); Api.users.update(id, { status: u.status === 'active' ? 'inactive' : 'active' }); toast('Status updated','success'); renderPage(); } /* ============================================================ AUDIT LOG ============================================================ */ function renderAuditLog() { const logs = Store.get('app_audit_logs').slice(0,100); $('contentArea').innerHTML = `
${logs.map(l => { const u = Api.users.get(l.user_id); return ``; }).join('')}
TimeActionModuleDescriptionUser
${formatDateTime(l.created_at)} ${l.action} ${escapeHtml(l.module)} ${escapeHtml(l.description)} ${escapeHtml(u?.name||'System')}
`; } /* ============================================================ SETTINGS VIEW ============================================================ */ function renderSettings() { const biz = getCurrentBusiness(); $('contentArea').innerHTML = `

Business Information

Operating Hours

${['Sun','Mon','Tue','Wed','Thu','Fri','Sat'].map((d,i) => ``).join('')}

Notifications

TODO: integrate real Email/WhatsApp API endpoints

System

${APP.name} ${APP.version}

${APP.company}

${APP.tagline}

Resets all data to factory seed.

`; safeIcons(); } function saveBizInfo() { const f = $('bizForm'); Api.businesses.update(getCurrentBusinessId(), { name: f.name.value, industry: f.industry.value, phone: f.phone.value, email: f.email.value, address: f.address.value, logo: f.logo.value, theme_color: f.theme_color.value }); toast('Business info saved','success'); renderSidebar(); renderPage(); } function saveHours() { const f = $('hoursForm'); const off_days = []; for (let i=0; i<7; i++) if (f[`off${i}`].checked) off_days.push(i); Api.businesses.update(getCurrentBusinessId(), { opening_hours: { start: f.open.value, end: f.close.value }, break_time: f.break_start.value ? { start: f.break_start.value, end: f.break_end.value } : null, slot_interval: parseInt(f.interval.value), off_days, cancellation_hours: parseInt(f.cancel_hours.value) }); toast('Hours saved','success'); } function saveNotif() { const f = $('notifForm'); Api.businesses.update(getCurrentBusinessId(), { reminder_enabled: f.reminder.checked, email_notify: f.email_notify.checked, whatsapp_api: f.whatsapp.value }); toast('Notification settings saved','success'); } function resetDemoData() { confirmModal('Reset Demo Data', 'This will erase ALL current data and reload factory seed. Continue?', () => { Auth.logout(); Store.reset(); toast('Demo data reset. Logging in again...','success'); setTimeout(() => location.reload(), 800); }); } /* ============================================================ PROFILE VIEW (Customer) ============================================================ */ function renderProfile() { const u = State.user; const c = Api.customers.list().find(c => c.user_id === u.id); $('contentArea').innerHTML = `

My Profile

${c ? `
` : ''}
`; } function saveProfile() { const f = $('profileForm'); const data = { name: f.name.value, phone: f.phone.value }; if (f.password.value) data.password = f.password.value; Api.users.update(State.user.id, data); const c = Api.customers.list().find(c => c.user_id === State.user.id); if (c) Api.customers.update(c.id, { name: f.name.value, phone: f.phone.value, dob: f.dob?.value || c.dob, address: f.address?.value || c.address }); State.user = Api.users.get(State.user.id); toast('Profile updated','success'); renderSidebar(); } /* ============================================================ NOTIFICATIONS DROPDOWN ============================================================ */ function openNotifications() { const notifs = Api.notifications.list(State.user.id).slice(0,10); openModal(`

Notifications

${notifs.length === 0 ? emptyState('No notifications','bell') : notifs.map(n => `

${escapeHtml(n.title)}

${escapeHtml(n.message)}

${formatDateTime(n.created_at)}

`).join('')}
`); } /* ============================================================ AUTH HANDLERS ============================================================ */ function switchAuth(view) { ['loginForm','registerForm','forgotForm'].forEach(f => $(f).classList.add('hide')); $(view+'Form').classList.remove('hide'); } function fillLogin(email) { $('loginEmail').value = email; $('loginPassword').value = 'password'; } function handleLogin() { const email = $('loginEmail').value.trim(); const password = $('loginPassword').value; if (!email || !password) { toast('Email and password required','error'); return; } const user = Auth.login(email, password); if (!user) { toast('Invalid credentials','error'); return; } State.user = user; toast(`Welcome, ${user.name}!`,'success'); enterApp(); } function handleRegister() { const name = $('regName').value.trim(); const email = $('regEmail').value.trim(); const phone = $('regPhone').value.trim(); const password = $('regPassword').value; if (!name || !email || !phone || !password) { toast('All fields required','error'); return; } if (!/\S+@\S+\.\S+/.test(email)) { toast('Invalid email','error'); return; } const result = Auth.register({ name, email, phone, password }); if (result.error) { toast(result.error,'error'); return; } toast('Registered! Please login.','success'); $('loginEmail').value = email; $('loginPassword').value = password; switchAuth('login'); } function handleForgot() { toast('Reset link sent (placeholder). Use password "password" to login.','info'); switchAuth('login'); } function handleLogout() { confirmModal('Sign Out', 'Are you sure you want to sign out?', () => { Auth.logout(); $('appView').classList.add('hide'); $('authView').classList.remove('hide'); State.currentView = 'dashboard'; }); } function enterApp() { $('authView').classList.add('hide'); $('appView').classList.remove('hide'); State.currentView = 'dashboard'; renderSidebar(); renderPage(); } /* ============================================================ INIT APP ============================================================ */ function init() { seedData(); const user = Auth.current(); if (user) { State.user = user; enterApp(); } else { $('authView').classList.remove('hide'); $('appView').classList.add('hide'); } safeIcons(); } window.addEventListener('load', init);

Master Booking Engine

Master Booking Engine

| |
© 2026 SIFUROBOT SOLUTIONS
202103002712 (003222179-X)