RENT A CAR

Private Monitoring System

Dashboard

Quick view ng negosyo mo.

MONTHLY RENTAL
₱0
Total booking value
COLLECTED
₱0
Reservation + payments
EXPENSES
₱0
For selected month
OUTSTANDING
₱0
Unpaid balances
ONGOING RENTALS
0
Units currently out
AVAILABLE TODAY
0
Active and not booked
FUTURE BOOKINGS
0
Upcoming reservations
NET CASH FLOW
₱0
Collected less expenses

6-Month Performance

Alerts

Bookings

Reservations, rentals, payments, at balances.

Availability Finder

Pili ng dates para makita agad ang available units.

Vehicles

Units, rates, ownership, at expiry alerts.

Customers

Customer and license records.

Expenses

Date, category, description, at amount lang.

Maintenance

PMS, repairs, registration, at insurance reminders.

Owner Payouts

Automatic company at owner share para sa partner-owned units.

Settings & Backup

Business name, categories, at data protection.

Business Settings

Comma-separated. Example: Sedan, MPV, SUV, Van
Comma-separated.

Backup & Restore

Naka-save ang data sa browser na ito. Mag-download ng backup regularly.


`); win.document.close(); } function findAvailability(){ const start=document.getElementById('avStart').value,end=document.getElementById('avEnd').value,cat=document.getElementById('avCategory').value; if(!start||!end)return toast('Piliin ang pickup at return date.'); if(endv.status==='ACTIVE'&&(cat==='ALL'||v.category===cat)&&isUnitAvailable(v.id,start,end)); const days=daysBetween(start,end); document.getElementById('availabilitySummary').innerHTML=`
Dates${dateDisplay(start)}–${dateDisplay(end)}
Rental Days${days}
Available Units${units.length}
Category${esc(cat==='ALL'?'All':cat)}
`; document.getElementById('availabilityResults').innerHTML=units.length?units.map(v=>`
${v.photo?``:`
🚙
`}
${esc(v.name)}
${esc(v.category)} • ${v.seats||'—'} seats
${money(v.dailyRate)}/day
`).join(''):`
Walang available unit sa selected dates.
`; } function bookAvailableUnit(unitId,start,end){ nav('bookings');openBookingModal(); document.getElementById('bPickup').value=start;document.getElementById('bReturn').value=end;refreshBookingUnits('',unitId); } function renderVehicles(){ const q=(document.getElementById('vehicleSearch')?.value||'').toLowerCase(); const rows=db.vehicles.filter(v=>`${v.name} ${v.plate} ${v.category}`.toLowerCase().includes(q)); const el=document.getElementById('vehiclesList'); if(!rows.length){el.innerHTML='
Wala pang vehicle. Tap “Add Unit.”
';return} el.innerHTML=rows.map(v=>`
${v.photo?``:`
🚙
`}
${esc(v.name)} ${statusBadge(v.status)}
${esc(v.plate||'No plate')} • ${esc(v.category)} • ${v.seats||'—'} seats
${money(v.dailyRate)}/day • ${v.ownershipType==='PARTNER'?'Partner: '+esc(v.ownerName||'—'):'Company-owned'}
`).join(''); } function openVehicleModal(id=''){ const v=id?byId(db.vehicles,id):null; const d={name:'',plate:'',category:db.settings.categories[0]||'SUV',seats:5,year:new Date().getFullYear(),dailyRate:0,status:'ACTIVE',ownershipType:'COMPANY',ownerName:'',commissionRate:20,odometer:0,nextPmsDate:'',registrationExpiry:'',insuranceExpiry:'',notes:'',photo:'',...v}; setModal(id?'Edit Vehicle':'Add Vehicle',`
Compressed automatically para hindi mabigat.
`, `${id?``:''}`); toggleOwnerFields(); } function toggleOwnerFields(){ const partner=document.getElementById('vOwnership')?.value==='PARTNER'; if(document.getElementById('ownerNameBox'))document.getElementById('ownerNameBox').style.display=partner?'block':'none'; if(document.getElementById('commissionBox'))document.getElementById('commissionBox').style.display=partner?'block':'none'; } async function imageToDataURL(file){ return new Promise((resolve,reject)=>{ const img=new Image(),reader=new FileReader(); reader.onload=e=>img.src=e.target.result;reader.onerror=reject; img.onload=()=>{ const max=700,scale=Math.min(1,max/Math.max(img.width,img.height)),c=document.createElement('canvas'); c.width=Math.round(img.width*scale);c.height=Math.round(img.height*scale);c.getContext('2d').drawImage(img,0,0,c.width,c.height); resolve(c.toDataURL('image/jpeg',.72)); };reader.readAsDataURL(file); }); } async function saveVehicleForm(id=''){ const name=document.getElementById('vName').value.trim();if(!name)return toast('Ilagay ang unit name.'); const old=id?byId(db.vehicles,id):null,file=document.getElementById('vPhoto').files[0]; let photo=old?.photo||'';if(file)photo=await imageToDataURL(file); const rec={id:id||uid('VHC'),name,plate:document.getElementById('vPlate').value.trim(),category:document.getElementById('vCategory').value, seats:num(document.getElementById('vSeats').value),year:document.getElementById('vYear').value,dailyRate:num(document.getElementById('vRate').value), status:document.getElementById('vStatus').value,ownershipType:document.getElementById('vOwnership').value, ownerName:document.getElementById('vOwner')?.value||'',commissionRate:num(document.getElementById('vCommission')?.value), odometer:num(document.getElementById('vOdometer').value),nextPmsDate:document.getElementById('vPms').value, registrationExpiry:document.getElementById('vReg').value,insuranceExpiry:document.getElementById('vInsurance').value, notes:document.getElementById('vNotes').value,photo,createdAt:old?.createdAt||new Date().toISOString()}; if(old)Object.assign(old,rec);else db.vehicles.push(rec);saveDB();closeModal();toast('Vehicle saved.'); } function deleteVehicle(id){ if(db.bookings.some(b=>b.unitId===id))return toast('May booking record ang unit; set it to INACTIVE instead.'); if(!confirm('Delete this vehicle?'))return;db.vehicles=db.vehicles.filter(x=>x.id!==id);saveDB();closeModal(); } function renderCustomers(){ const q=(document.getElementById('customerSearch')?.value||'').toLowerCase(); const rows=db.customers.filter(c=>`${c.name} ${c.contact}`.toLowerCase().includes(q)); const el=document.getElementById('customersTable'); if(!rows.length){el.innerHTML='
Wala pang customer record.
';return} el.innerHTML=`
${rows.map(c=>``).join('')}
NameContactLicenseAddressAction
${esc(c.name)}${esc(c.contact||'—')}${esc(c.licenseType||'—')}
${esc(c.licenseNo||'')}
${esc(c.address||'—')}
`; } function openCustomerModal(id=''){ const c=id?byId(db.customers,id):null,d={name:'',contact:'',address:'',licenseType:'Philippine License',licenseNo:'',notes:'',...c}; setModal(id?'Edit Customer':'Add Customer',`
`, `${id?``:''}`); } function saveCustomerForm(id=''){ const name=document.getElementById('cName').value.trim();if(!name)return toast('Ilagay ang customer name.'); const old=id?byId(db.customers,id):null,rec={id:id||uid('CUS'),name,contact:document.getElementById('cContact').value.trim(), address:document.getElementById('cAddress').value.trim(),licenseType:document.getElementById('cLicenseType').value, licenseNo:document.getElementById('cLicenseNo').value.trim(),notes:document.getElementById('cNotes').value,createdAt:old?.createdAt||new Date().toISOString()}; if(old)Object.assign(old,rec);else db.customers.push(rec);saveDB();closeModal();toast('Customer saved.'); } function deleteCustomer(id){ if(db.bookings.some(b=>b.customerId===id))return toast('May booking record ang customer kaya hindi puwedeng i-delete.'); if(!confirm('Delete this customer?'))return;db.customers=db.customers.filter(x=>x.id!==id);saveDB();closeModal(); } function renderExpenses(){ const monthEl=document.getElementById('expenseMonthFilter');if(!monthEl.value)monthEl.value=monthNow(); const cat=document.getElementById('expenseCategoryFilter')?.value||'ALL'; const rows=[...db.expenses].filter(e=>e.date.slice(0,7)===monthEl.value&&(cat==='ALL'||e.category===cat)).sort((a,b)=>b.date.localeCompare(a.date)); const total=rows.reduce((s,e)=>s+num(e.amount),0); document.getElementById('expenseSummary').innerHTML=`
Selected Month${esc(monthEl.value)}
Records${rows.length}
Total Expenses${money(total)}
Category${esc(cat)}
`; const el=document.getElementById('expensesTable'); el.innerHTML=rows.length?`
${rows.map(e=>``).join('')}
DateCategoryDescriptionAmountAction
${dateDisplay(e.date)}${esc(e.category)}${esc(e.description)}${money(e.amount)}
`:'
Walang expenses sa selected month.
'; } function openExpenseModal(id=''){ const e=id?byId(db.expenses,id):null,d={date:today(),category:db.settings.expenseCategories[0],description:'',amount:0,...e}; setModal(id?'Edit Expense':'Add Expense',`
`, `${id?``:''}`); } function saveExpenseForm(id=''){ const desc=document.getElementById('eDescription').value.trim(),amount=num(document.getElementById('eAmount').value); if(!desc||amount<=0)return toast('Ilagay ang description at amount.'); const old=id?byId(db.expenses,id):null,rec={id:id||uid('EXP'),date:document.getElementById('eDate').value,category:document.getElementById('eCategory').value,description:desc,amount,createdAt:old?.createdAt||new Date().toISOString()}; if(old)Object.assign(old,rec);else db.expenses.push(rec);saveDB();closeModal();toast('Expense saved.'); } function deleteExpense(id){if(!confirm('Delete this expense?'))return;db.expenses=db.expenses.filter(x=>x.id!==id);saveDB();closeModal()} function renderMaintenance(){ const rows=[...db.maintenance].sort((a,b)=>(a.dueDate||'9999').localeCompare(b.dueDate||'9999')); const el=document.getElementById('maintenanceTable'); if(!rows.length){el.innerHTML='
Wala pang maintenance record.
';return} el.innerHTML=`
${rows.map(m=>``).join('')}
UnitTypeDue DateOdometer DueCostStatusAction
${esc(m.unitName)}${esc(m.type)}${dateDisplay(m.dueDate)}${m.odometerDue?num(m.odometerDue).toLocaleString():'—'}${money(m.cost)}${statusBadge(m.status)}
`; } function openMaintenanceModal(id=''){ if(!db.vehicles.length)return toast('Mag-add muna ng vehicle.'); const m=id?byId(db.maintenance,id):null,d={unitId:db.vehicles[0].id,type:'PMS',dueDate:'',odometerDue:0,status:'SCHEDULED',cost:0,notes:'',...m}; setModal(id?'Edit Maintenance':'Add Maintenance',`
`, `${id?``:''}`); } function saveMaintenanceForm(id=''){ const unit=byId(db.vehicles,document.getElementById('mtUnit').value),old=id?byId(db.maintenance,id):null; const rec={id:id||uid('MNT'),unitId:unit.id,unitName:unit.name,type:document.getElementById('mtType').value,status:document.getElementById('mtStatus').value, dueDate:document.getElementById('mtDue').value,odometerDue:num(document.getElementById('mtOdo').value),cost:num(document.getElementById('mtCost').value), notes:document.getElementById('mtNotes').value,createdAt:old?.createdAt||new Date().toISOString()}; if(old)Object.assign(old,rec);else db.maintenance.push(rec);saveDB();closeModal();toast('Maintenance saved.'); } function deleteMaintenance(id){if(!confirm('Delete this record?'))return;db.maintenance=db.maintenance.filter(x=>x.id!==id);saveDB();closeModal()} function renderPayouts(){ const rows=[...db.payouts].sort((a,b)=>(b.dueDate||'').localeCompare(a.dueDate||'')); const el=document.getElementById('payoutsTable'); if(!rows.length){el.innerHTML='
Wala pang partner-owned booking payout.
';return} el.innerHTML=`
${rows.map(p=>``).join('')}
BookingOwner / UnitGrossCommissionCompany ShareOwner ShareDueStatusAction
${esc(p.bookingId)}${esc(p.ownerName)}
${esc(p.unitName)}
${money(p.gross)}${p.commission}%${money(p.companyShare)}${money(p.ownerShare)}${dateDisplay(p.dueDate)}${statusBadge(p.status)}
`; } function togglePayout(id){const p=byId(db.payouts,id);p.status=p.status==='PAID'?'PENDING':'PAID';p.paidDate=p.status==='PAID'?today():'';saveDB();toast('Payout status updated.')} function renderSettings(){ document.getElementById('setBusinessName').value=db.settings.businessName||''; document.getElementById('setContact').value=db.settings.contactNumber||''; document.getElementById('setCategories').value=db.settings.categories.join(', '); document.getElementById('setExpenseCategories').value=db.settings.expenseCategories.join(', '); } function saveSettings(){ const categories=document.getElementById('setCategories').value.split(',').map(x=>x.trim()).filter(Boolean); const exps=document.getElementById('setExpenseCategories').value.split(',').map(x=>x.trim()).filter(Boolean); db.settings.businessName=document.getElementById('setBusinessName').value.trim()||'RENT A CAR'; db.settings.contactNumber=document.getElementById('setContact').value.trim(); if(categories.length)db.settings.categories=categories;if(exps.length)db.settings.expenseCategories=exps; saveDB();toast('Settings saved.'); } function openBackupModal(){nav('settings')} function exportBackup(){ const blob=new Blob([JSON.stringify(db,null,2)],{type:'application/json'}),a=document.createElement('a'); a.href=URL.createObjectURL(blob);a.download=`Rent_A_Car_Backup_${today()}.json`;a.click();URL.revokeObjectURL(a.href);toast('Backup downloaded.'); } function restoreBackup(e){ const file=e.target.files[0];if(!file)return; const r=new FileReader();r.onload=()=>{ try{const data=JSON.parse(r.result);if(!data.settings||!Array.isArray(data.bookings))throw new Error();if(confirm('Replace current data with this backup?')){db=Object.assign(defaultDB(),data);saveDB();toast('Backup restored.')}}catch(err){toast('Invalid backup file.')} e.target.value=''; };r.readAsText(file); } function resetAllData(){ if(!confirm('This will delete ALL records in this browser. Continue?'))return; if(!confirm('Final confirmation: delete everything?'))return; db=defaultDB();saveDB();toast('All data reset.'); } function loadDemoData(){ if(db.vehicles.length||db.customers.length||db.bookings.length){if(!confirm('Demo data will be added to existing records. Continue?'))return} const v1={id:uid('VHC'),name:'Toyota Fortuner 2026',plate:'',category:'SUV',seats:7,year:2026,dailyRate:3500,status:'ACTIVE',ownershipType:'COMPANY',ownerName:'',commissionRate:0,odometer:0,nextPmsDate:'',registrationExpiry:'',insuranceExpiry:'',notes:'',photo:'',createdAt:new Date().toISOString()}; const v2={id:uid('VHC'),name:'Mitsubishi Mirage G4 2026',plate:'',category:'Sedan',seats:5,year:2026,dailyRate:1800,status:'ACTIVE',ownershipType:'COMPANY',ownerName:'',commissionRate:0,odometer:0,nextPmsDate:'',registrationExpiry:'',insuranceExpiry:'',notes:'',photo:'',createdAt:new Date().toISOString()}; const c={id:uid('CUS'),name:'Sample Customer',contact:'09123456789',address:'',licenseType:'Philippine License',licenseNo:'',notes:'',createdAt:new Date().toISOString()}; db.vehicles.push(v1,v2);db.customers.push(c);saveDB();toast('Demo data loaded.'); } function exportBookingsCSV(){ const headers=['Booking ID','Pickup Date','Return Date','Customer','Contact','Unit','Booking Daily Rate','Rental Days','Total Rental Price','Paid','Balance','Status','Source']; const rows=db.bookings.map(b=>[b.id,b.pickupDate,b.returnDate,b.customerName,b.contact,b.unitName,b.dailyRate,b.rentalDays,b.total,b.amountPaid,b.balance,liveBookingStatus(b),b.source]); const csv=[headers,...rows].map(r=>r.map(v=>`"${String(v??'').replaceAll('"','""')}"`).join(',')).join('\n'); const blob=new Blob([csv],{type:'text/csv;charset=utf-8'}),a=document.createElement('a');a.href=URL.createObjectURL(blob);a.download=`Bookings_${today()}.csv`;a.click();URL.revokeObjectURL(a.href); } function setModal(title,body,foot){ document.getElementById('modalTitle').textContent=title;document.getElementById('modalBody').innerHTML=body;document.getElementById('modalFoot').innerHTML=foot;document.getElementById('modal').classList.add('show'); } function closeModal(){document.getElementById('modal').classList.remove('show')} function toast(msg){const el=document.getElementById('toast');el.textContent=msg;el.classList.add('show');clearTimeout(window._toast);window._toast=setTimeout(()=>el.classList.remove('show'),2800)} document.addEventListener('keydown',e=>{if(e.key==='Escape')closeModal()}); (function init(){ document.getElementById('dashboardMonth').value=monthNow(); document.getElementById('bookingMonthFilter').value=''; document.getElementById('expenseMonthFilter').value=monthNow(); document.getElementById('avStart').value=today(); const tomorrow=new Date(Date.now()+86400000).toISOString().slice(0,10); document.getElementById('avEnd').value=tomorrow; renderAll(); })();