โ„๏ธ Soon Heng Air-Cond Service

Source Code — Scripted WhatsApp Agent Demo

HTML CSS JavaScript No Backend

About This Code Showcase

The entire demo lives in a single self-contained demo.html file. No backend, no API key, no build step. The 6-stage conversation is scripted in JavaScript, and the WhatsApp UI is built with plain CSS using the WhatsApp dark theme palette.

Below are the key excerpts: the message rendering helpers, the quote card, and the stage flow that drives the demo.

Core: Message Rendering Helpers

Each conversation turn calls agentReply() or customerMsg(). The agent reply shows a typing indicator before the message lands, just like a real WhatsApp conversation.

demo.html — Bubble & Typing Helpers
const sleep = ms => new Promise(r => setTimeout(r, ms)); function appendBubble(role, text, time, media) { const box = document.getElementById('msg-box'); const w = document.createElement('div'); w.className = `mw ${role === 'agent' ? 'sent' : 'received'}`; let mediaHtml = ''; if (media === 'photo') { mediaHtml = `<div class="media-card"> <div class="media-ico">๐Ÿ“ธ</div> <div> <div class="media-n">aircon-indoor.jpg</div> <div class="media-s">2.4 MB ยท Photo</div> </div> </div>`; } let quoteHtml = ''; if (media === 'quote') { quoteHtml = `<div class="quote-card"> <div class="qc-title">Quotation</div> <div class="qc-row"><span>Service</span><span>Chemical Wash ร— 2 units</span></div> <div class="qc-row"><span>Estimated Time</span><span>1.5 hours</span></div> <div class="qc-row"><span>Parts</span><span>Cleaning chemicals included</span></div> <div class="qc-row qc-total"><span>Total</span><span>RM 220</span></div> </div>`; } w.innerHTML = `<div class="bubble"> <div class="b-text">${text}</div> ${mediaHtml}${quoteHtml} <div class="b-meta"> <span class="b-time">${time}</span> ${role === 'agent' ? '<span class="tick">โœ“โœ“</span>' : ''} </div> </div>`; box.appendChild(w); box.scrollTop = box.scrollHeight; } async function agentReply(text, time, media) { showTyping(); await sleep(1800); hideTyping(); appendBubble('agent', text, time, media); } async function customerMsg(text, time, media) { await sleep(800); appendBubble('customer', text, time, media); }

Stage 1 — Customer Inquiry

The customer opens with a question; the AI confirms the service area and immediately starts scoping.

demo.html — Stage 1 Flow
async function startDemo() { document.getElementById('intro').style.display = 'none'; setStage(1, '๐Ÿ“ฉ Stage 1 โ€” Customer sends inquiry'); setBtn('Incoming message...', null, true); updateStats(1, 0, 0, 'โ€”'); await sleep(1000); await customerMsg( 'Hi, my bedroom aircon not cold liao. You all do service in Seremban?', '9:14 AM' ); await sleep(600); setStage(1, '๐Ÿค– Stage 1 โ€” AI agent responding to inquiry...'); await agentReply( 'Hi! Yes we cover Seremban and Nilai. Sorry to hear that. ' + 'A few quick questions: how many units are not cold? ' + 'Are they wall-mounted? When was the last service?', '9:14 AM' ); updateStats(1, 0, 0, '14s'); setStage(2, 'โœ… Stage 1 complete โ€” Moving to scoping'); setBtn('Customer replies with details...', stage2); }

Stage 3 — AI Generates the Quote

Once the AI has enough info (unit count, symptoms, last-service date, address), it drops a quote card into the chat with the chemical wash recommendation.

demo.html — Stage 3 Flow
async function stage3() { setBtn('Processing...', null, true); setStage(3, 'โ„๏ธ Stage 3 โ€” AI agent providing quote...'); await sleep(500); appendBanner('โ€” AI generating quote based on job details โ€”'); await agentReply( 'Here\'s your quote for the chemical wash:', '9:17 AM', 'quote' ); await sleep(300); await agentReply( 'RM 220 covers both units โ€” chemical wash, drainage clear, ' + 'gas pressure check, and we\'ll inspect the dripping issue. ' + 'Quote valid 7 days. Want to book a slot?', '9:17 AM' ); setStage(4, 'โœ… Stage 3 complete โ€” Quote sent. Waiting for customer...'); setBtn('Customer accepts quote...', stage4); }

Stage 5 — Confirm + Auto Reminder

After confirming the booking, the demo simulates a same-evening reminder using a banner + agent message.

demo.html — Stage 5 Flow (excerpt)
async function stage5() { setStage(5, 'โœ… Stage 5 โ€” AI agent confirming booking...'); appendBanner('โ€” Booking confirmed โ€”'); await agentReply( 'Booking confirmed! Here\'s your summary:\n\n' + 'โ„๏ธ Service: Chemical Wash ร— 2 units\n' + '๐Ÿ“… Date: Tomorrow, 2:00 PM\n' + '๐Ÿ“ Address: No. 18, Jln Rasah 5, Taman Rasah Jaya, Seremban\n' + '๐Ÿ’ฐ Price: RM 220 (chemicals included)', '9:20 AM' ); updateStats(1, 1, 220, '14s'); await sleep(1500); appendBanner('โ€” Tonight 7pm: AI sends automatic reminder โ€”'); await agentReply( 'Hi Auntie Wong! Just a reminder about your aircon chemical wash ' + 'tomorrow at 2:00 PM. Please make sure both bedroom aircons are ' + 'accessible and switch them off 30 minutes before we arrive.', '7:00 PM' ); }