Dashboard Active
0
Services
0
Bundles
0
Projects
0
Receipts
24/7
Status
Services & Pricing
Bundles
Projects
Special Offer Settings
Edit Special Offer
Receipts
Receipt Preview
Admin Access
Invalid credentials.
SYS_ONLINE // 2026 NBO // KE TECHGPT_v2.0
Tech + AI Specialist

TECHGPT

Nairobi's Tech Engine

Where tech meets intelligence. Full-spectrum tech support, AI solutions and digital services — morphed into one ruthless entity. Based in Nairobi, built for the world.

Scroll
Tech Support AI Solutions POS Systems Web Development SEO Ad Campaigns M-Pesa Integration School Systems Tech Support AI Solutions POS Systems Web Development SEO Ad Campaigns M-Pesa Integration School Systems
01 — About

The Entity

TechGPT is a Nairobi-based tech powerhouse built at the intersection of tech support and artificial intelligence.

Not just fixing problems. Building systems. Automating business. Engineering futures. One client at a time — with startup-friendly prices that don't compromise quality.

From hardware diagnosis to AI-powered campaigns, custom POS systems to school management platforms — TechGPT handles it all. Cold. Calculated. Delivered.

AI
Powered Dev
12K
Sites from KES
NBO
Nairobi, Kenya
24/7
Support Mode
Tech & IT SupportFrom KES 1,200
AI Integration & ChatbotsFrom KES 32,000
POS & Business SystemsFrom KES 55,000
Web & App DevelopmentFrom KES 12,000
School/SME SystemsFrom KES 140,000
SEOKES 9,000/mo
Ad Campaign ManagementKES 8,000/mo
Hosting & BackendFREE 3 months
Payment IntegrationM-Pesa · Stripe
Data Privacy CleanupKES 7,000
🔥 LIMITED TIME OFFER
WEBSITE
FROM
KES 5K
— KES 10,000 depending on type & platform

Price varies depending on the platform and type of website. Every package includes full professional design, free hosting for 365 days, and free dedicated support for 6 months.

Limited slots available · First come first served
🎨
Full Professional Design
Custom-built website tailored to your brand — responsive on all devices, modern and clean.
☁️
Free Hosting — 365 Days
One full year of fast, secure Firebase hosting completely free. No hidden fees. No contracts.
🛡
Free Support — 6 Months
Dedicated support for 6 months after launch. Updates, fixes, guidance — all covered.
AI-Powered Fast Delivery
Built with Claude AI assistance — faster delivery without compromising on quality.
02 — Work

Selected
Projects

05 — FAQ

Frequently
Asked

TechGPT provides full-scale tech solutions including website development, AI integration, POS systems, business automation, SEO, hosting, and IT support — all under one roof.

Our websites start from KES 5,000, with FREE hosting for 1 year included. Final pricing depends on the features, complexity, and platform required.

We follow a simple, transparent process: Consultation → Planning → Design → Development → Testing → Launch. You're kept informed at every stage with no surprises.

Yes. All projects are handled with clear, upfront pricing to ensure transparency and commitment on both sides. A 40–50% deposit is required to begin, with the balance due on delivery.

Most websites are delivered within a few days depending on requirements. Simple landing pages can be ready in 2–3 days, while more complex builds take 1–3 weeks.

Yes. We provide ongoing support, maintenance, and upgrades. The special website offer includes 6 months of free support after launch.

We combine AI, automation, and real business understanding to build systems — not just websites. AI-assisted development means faster delivery, smarter solutions, and better value for your budget.

We work with startups, SMEs, schools, and growing businesses across Kenya. Whether you're a small duka, a restaurant, a school, or a tech company — TechGPT has a solution for you.

03 — Quote Builder

Build Your
Quote

Quick & Easy
Marketing & Recurring
Development & Systems
Extras
High-Value Bundles — Big Savings
App Type
Frontend Framework
Backend
Database
Features & Integrations
Platform / Deployment
Your Quote
No services selected
Subtotal
Est. TotalKES 0

Estimates only. 40-50% deposit via M-Pesa. Final quote via WhatsApp.

Your offer (KES) — we'll check if it works
Est. Timeline
Add services to see timeline
Pay via M-Pesa Paybill
Paybill
247 247
Account
109481
40–50% deposit to confirm · balance on delivery
💬 Send to WhatsApp
04 — Contact

Let's
Connect

Got a
vision?
Let's Build.

Whether it's tech support, an AI project, a POS system or a full web build — TechGPT handles it. Reach out and let's get it moving.

Websites from KES 5,000 · POS from KES 55,000 · Hosting FREE
Send a Message

Or message directly → WhatsApp +254 112 260 758

💬
`); w.document.close();setTimeout(()=>w.print(),400); } // ─── ADMIN AUTH (Firebase) ────────────────────────────── function openAdminMod(){ document.getElementById('adminMod').classList.add('open'); document.getElementById('pwEmail').value=''; document.getElementById('pwPass').value=''; document.getElementById('pwErr').classList.remove('show'); } function closeAdminMod(){document.getElementById('adminMod').classList.remove('open');} async function checkPw(){ const email = document.getElementById('pwEmail').value.trim(); const pass = document.getElementById('pwPass').value; const btn = document.getElementById('loginBtn'); const err = document.getElementById('pwErr'); if(!email||!pass){err.textContent='Please enter email and password.';err.classList.add('show');return;} btn.textContent='Signing in...';btn.disabled=true; err.classList.remove('show'); try { await window._fbSignIn(email, pass); // onAuthStateChanged will fire and call _onAuthSignedIn } catch(e) { const msg = e.code === 'auth/invalid-credential' || e.code === 'auth/wrong-password' || e.code === 'auth/user-not-found' ? 'Invalid email or password.' : 'Login failed. Try again.'; err.textContent = msg; err.classList.add('show'); document.getElementById('pwPass').value=''; } finally { btn.textContent='Login →';btn.disabled=false; } } function openDashboard(){ document.getElementById('adminDash').classList.add('open'); document.body.style.overflow='hidden'; refreshDashboard(); } async function logoutAdmin(){ try { await window._fbSignOut(); } catch(e){} document.getElementById('adminDash').classList.remove('open'); document.body.style.overflow=''; } // ─── AUTH STATE CALLBACKS ──────────────────────────────── window._onAuthSignedIn = function(user) { closeAdminMod(); openDashboard(); }; window._onAuthSignedOut = function() { document.getElementById('adminDash').classList.remove('open'); document.body.style.overflow=''; }; function swAdmTab(tab,btn){ document.querySelectorAll('.adm-tab').forEach(t=>t.classList.remove('active')); document.querySelectorAll('.adm-panel').forEach(p=>p.classList.remove('active')); btn.classList.add('active'); document.getElementById('adm-'+tab).classList.add('active'); } function toast(msg){ const t=document.getElementById('admToast'); t.textContent=msg;t.classList.add('show'); setTimeout(()=>t.classList.remove('show'),2500); } function refreshDashboard(){ // Stats document.getElementById('statSvcs').textContent=Object.keys(prices).length; document.getElementById('statBundles').textContent=bundles.length; document.getElementById('statProjs').textContent=projects.length; document.getElementById('statReceipts').textContent=receipts.length; renderAdmServices(); renderAdmBundles(); renderAdmProjects(); renderAdmReceipts(); // Load offer fields document.getElementById('offerBadge').value=offerCfg.badge; document.getElementById('offerTitle').value=offerCfg.hl1+' '+offerCfg.hl2; document.getElementById('offerHL1').value=offerCfg.hl1; document.getElementById('offerHL2').value=offerCfg.hl2; document.getElementById('offerFrom').value=offerCfg.priceFrom; document.getElementById('offerTo').value=offerCfg.priceTo; document.getElementById('offerNote').value=offerCfg.note; document.getElementById('offerVisible').value=String(offerCfg.visible); } // ─── ADMIN: SERVICES ──────────────────────────────────── function renderAdmServices(){ const g=document.getElementById('svcGrid');g.innerHTML=''; for(const name in prices){ const p=prices[name]; const d=document.createElement('div');d.className='adm-card'; d.innerHTML=`
${p.ico||'⚙️'} ${name}
Ksh ${p.kes.toLocaleString()} floor: ${p.floor.toLocaleString()}
${p.type} · ${p.days} days · ${p.cat}
`; g.appendChild(d); } } function showSvcForm(editing){ editSvcKey=editing||null; document.getElementById('svcFormTitle').textContent=editing?'Edit Service':'Add New Service'; if(editing){ const p=prices[editing]; document.getElementById('svcName').value=editing; document.getElementById('svcIcon').value=p.ico||''; document.getElementById('svcPrice').value=p.kes; document.getElementById('svcFloor').value=p.floor; document.getElementById('svcType').value=p.type; document.getElementById('svcDays').value=p.days; document.getElementById('svcCat').value=p.cat; } else { ['svcName','svcIcon','svcPrice','svcFloor','svcDays'].forEach(id=>document.getElementById(id).value=''); } document.getElementById('svcForm').style.display='block'; } function hideSvcForm(){document.getElementById('svcForm').style.display='none';editSvcKey=null;} function editSvc(name){showSvcForm(name);} function delSvc(name){ if(!confirm(`Delete "${name}"?`))return; delete prices[name];save('prices',prices); renderAdmServices();renderGrids(); document.getElementById('statSvcs').textContent=Object.keys(prices).length; toast('Service deleted'); } function saveSvc(){ const name=document.getElementById('svcName').value.trim(); const ico=document.getElementById('svcIcon').value.trim()||'⚙️'; const kes=parseInt(document.getElementById('svcPrice').value)||0; const floor=parseInt(document.getElementById('svcFloor').value)||0; const type=document.getElementById('svcType').value; const days=parseInt(document.getElementById('svcDays').value)||0; const cat=document.getElementById('svcCat').value; if(!name||!kes){alert('Name and price are required.');return;} if(editSvcKey&&editSvcKey!==name) delete prices[editSvcKey]; prices[name]={kes,floor,type,days,cat,ico}; save('prices',prices); hideSvcForm();renderAdmServices();renderGrids(); document.getElementById('statSvcs').textContent=Object.keys(prices).length; toast('Service saved ✓'); } // ─── ADMIN: BUNDLES ────────────────────────────────────── function renderAdmBundles(){ const g=document.getElementById('bundleGrid');g.innerHTML=''; bundles.forEach((b,i)=>{ const d=document.createElement('div');d.className='adm-card'; d.innerHTML=`
📦 ${b.name}
Ksh ${b.kes.toLocaleString()} floor: ${b.floor.toLocaleString()}
${b.desc} · ${b.days} days
`; g.appendChild(d); }); } function showBundleForm(idx){ editBundleIdx=idx!=null?idx:null; document.getElementById('bundleFormTitle').textContent=idx!=null?'Edit Bundle':'Add New Bundle'; if(idx!=null){const b=bundles[idx];document.getElementById('bName').value=b.name;document.getElementById('bPrice').value=b.kes;document.getElementById('bFloor').value=b.floor;document.getElementById('bDays').value=b.days;document.getElementById('bDesc').value=b.desc;} else{['bName','bPrice','bFloor','bDays','bDesc'].forEach(id=>document.getElementById(id).value='');} document.getElementById('bundleForm').style.display='block'; } function hideBundleForm(){document.getElementById('bundleForm').style.display='none';editBundleIdx=null;} function editBundle(i){showBundleForm(i);} function delBundle(i){if(!confirm('Delete bundle?'))return;bundles.splice(i,1);save('bundles',bundles);renderAdmBundles();renderGrids();document.getElementById('statBundles').textContent=bundles.length;toast('Bundle deleted');} function saveBundle(){ const name=document.getElementById('bName').value.trim(); const kes=parseInt(document.getElementById('bPrice').value)||0; const floor=parseInt(document.getElementById('bFloor').value)||0; const days=parseInt(document.getElementById('bDays').value)||0; const desc=document.getElementById('bDesc').value.trim(); if(!name||!kes){alert('Name and price required.');return;} const obj={name,kes,floor,days,desc}; if(editBundleIdx!=null)bundles[editBundleIdx]=obj;else bundles.push(obj); save('bundles',bundles);hideBundleForm();renderAdmBundles();renderGrids(); document.getElementById('statBundles').textContent=bundles.length; toast('Bundle saved ✓'); } // ─── ADMIN: PROJECTS ──────────────────────────────────── function renderAdmProjects(){ const g=document.getElementById('projGrid');g.innerHTML=''; projects.forEach((p,i)=>{ const d=document.createElement('div');d.className='adm-card'; d.innerHTML=`
${p.name}
${p.tag} · ${p.status}${p.url?` · ${p.url}`:''}
${p.desc}
`; g.appendChild(d); }); } function showProjForm(idx){ editProjIdx=idx!=null?idx:null; document.getElementById('projFormTitle').textContent=idx!=null?'Edit Project':'Add New Project'; if(idx!=null){const p=projects[idx];document.getElementById('pName').value=p.name;document.getElementById('pTag').value=p.tag;document.getElementById('pUrl').value=p.url||'';document.getElementById('pStatus').value=p.status;document.getElementById('pDesc').value=p.desc;} else{['pName','pTag','pUrl','pDesc'].forEach(id=>document.getElementById(id).value='');document.getElementById('pStatus').value='live';} document.getElementById('projForm').style.display='block'; } function hideProjForm(){document.getElementById('projForm').style.display='none';editProjIdx=null;} function editProj(i){showProjForm(i);} function delProj(i){if(!confirm('Delete project?'))return;projects.splice(i,1);save('projects',projects);renderAdmProjects();renderProjects();document.getElementById('statProjs').textContent=projects.length;toast('Project deleted');} function saveProj(){ const name=document.getElementById('pName').value.trim(); const tag=document.getElementById('pTag').value.trim()||'Project'; const url=document.getElementById('pUrl').value.trim(); const status=document.getElementById('pStatus').value; const desc=document.getElementById('pDesc').value.trim(); if(!name){alert('Project name required.');return;} const obj={name,tag,url,status,desc}; if(editProjIdx!=null)projects[editProjIdx]=obj;else projects.push(obj); save('projects',projects);hideProjForm();renderAdmProjects();renderProjects(); document.getElementById('statProjs').textContent=projects.length; toast('Project saved ✓'); } // ─── ADMIN: OFFER ──────────────────────────────────────── function saveOffer(){ offerCfg={ badge:document.getElementById('offerBadge').value||'🔥 LIMITED TIME OFFER', hl1:document.getElementById('offerHL1').value||'WEBSITE', hl2:document.getElementById('offerHL2').value||'FROM', priceFrom:parseInt(document.getElementById('offerFrom').value)||5000, priceTo:parseInt(document.getElementById('offerTo').value)||10000, note:document.getElementById('offerNote').value||'', visible:document.getElementById('offerVisible').value==='true', }; save('offer',offerCfg); renderOffer(); toast('Offer updated & live on site ✓'); } // ─── EMAILJS ───────────────────────────────────────────── const EJS_SVC='YOUR_SERVICE_ID', EJS_TPL='YOUR_TEMPLATE_ID', EJS_KEY='YOUR_PUBLIC_KEY'; function sendEmail(){ const name=document.getElementById('cf-name').value.trim(); const phone=document.getElementById('cf-phone').value.trim(); const email=document.getElementById('cf-email').value.trim(); const service=document.getElementById('cf-service').value; const message=document.getElementById('cf-message').value.trim(); const budget=document.getElementById('cf-budget').value; const btn=document.getElementById('cf-btn'),status=document.getElementById('cf-status'); if(!name||!phone||!service||!message){status.className='cf-status err';status.textContent='✗ Please fill in all required fields.';return;} if(EJS_SVC==='YOUR_SERVICE_ID'){ const txt=`New enquiry from TechGPT site:\n\nName: ${name}\nPhone: ${phone}\nEmail: ${email||'N/A'}\nService: ${service}\nBudget: ${budget||'Not specified'}\n\nMessage: ${message}`; window.open('https://wa.me/254112260758?text='+encodeURIComponent(txt),'_blank'); status.className='cf-status ok';status.textContent='✓ Redirected to WhatsApp. Add EmailJS credentials to enable email delivery.';return; } btn.disabled=true;btn.textContent='Sending...';status.className='cf-status'; emailjs.send(EJS_SVC,EJS_TPL,{from_name:name,phone,email:email||'Not provided',service,budget:budget||'TBD',message,reply_to:email||'noreply'}) .then(()=>{ status.className='cf-status ok';status.textContent='✓ Message sent! TechGPT will respond within 24 hours.'; btn.textContent='Sent ✓'; ['cf-name','cf-phone','cf-email','cf-message'].forEach(id=>document.getElementById(id).value=''); document.getElementById('cf-service').value='';document.getElementById('cf-budget').value=''; setTimeout(()=>{const ping=`New enquiry on TechGPT site!\nFrom: ${name} (${phone})\nService: ${service}`;window.open('https://wa.me/254112260758?text='+encodeURIComponent(ping),'_blank');},1200); }).catch(()=>{status.className='cf-status err';status.textContent='✗ Failed. Please message on WhatsApp directly.';btn.disabled=false;btn.textContent='Send Message →';}); } // ─── CURSOR ────────────────────────────────────────────── const cur=document.getElementById('cur'),curR=document.getElementById('cur-r'); let mx=window.innerWidth/2,my=window.innerHeight/2,rx=mx,ry=my; document.addEventListener('mousemove',e=>{mx=e.clientX;my=e.clientY;cur.style.left=mx+'px';cur.style.top=my+'px';}); (function anim(){rx+=(mx-rx)*.12;ry+=(my-ry)*.12;curR.style.left=rx+'px';curR.style.top=ry+'px';requestAnimationFrame(anim);})(); document.querySelectorAll('a,button,.sc-card,.pill,.svc-row,.p-card,.st-box,.ct-lnk,.offer-feature').forEach(el=>{ el.addEventListener('mouseenter',()=>{cur.style.transform='translate(-50%,-50%) scale(2.2)';curR.style.opacity='.4';}); el.addEventListener('mouseleave',()=>{cur.style.transform='translate(-50%,-50%) scale(1)';curR.style.opacity='1';}); }); // ─── NAVBAR ────────────────────────────────────────────── window.addEventListener('scroll',()=>document.getElementById('nb').classList.toggle('sc',scrollY>60)); // ─── REVEAL ────────────────────────────────────────────── const rvObs=new IntersectionObserver(entries=>{entries.forEach((e,i)=>{if(e.isIntersecting){setTimeout(()=>e.target.classList.add('vis'),i*70);rvObs.unobserve(e.target);}});},{threshold:.1}); document.querySelectorAll('.rv').forEach(r=>rvObs.observe(r)); // ─── CLOSE ADMIN ON OUTSIDE CLICK ─────────────────────── document.getElementById('adminMod').addEventListener('click',function(e){if(e.target===this)closeAdminMod();}); // ─── PWA ───────────────────────────────────────────────── let deferredPrompt; window.addEventListener('beforeinstallprompt',e=>{e.preventDefault();deferredPrompt=e;document.getElementById('pwa-banner').style.display='flex';}); function installPWA(){if(!deferredPrompt)return;deferredPrompt.prompt();deferredPrompt.userChoice.then(()=>{deferredPrompt=null;document.getElementById('pwa-banner').style.display='none';});} function dismissPWA(){document.getElementById('pwa-banner').style.display='none';} if('serviceWorker'in navigator){window.addEventListener('load',()=>{navigator.serviceWorker.register('sw.js').catch(()=>{});});} // ─── RECEIPTS ──────────────────────────────────────────── let currentReceiptData = null; function getNextReceiptNum() { const year = new Date().getFullYear(); const existing = receipts.filter(r => r.num && r.num.includes(String(year))); const next = existing.length + 1; return `TGPT-${year}-${String(next).padStart(3,'0')}`; } function showReceiptForm() { document.getElementById('receiptForm').style.display = 'block'; document.getElementById('receiptFormTitle').textContent = 'Generate New Receipt'; ['rcName','rcPhone','rcEmail','rcProject','rcTotal','rcPaid','rcMpesa','rcServices'].forEach(id => { const el = document.getElementById(id); if(el) el.value = ''; }); document.getElementById('rcPayType').value = 'deposit'; } function hideReceiptForm() { document.getElementById('receiptForm').style.display = 'none'; } function calcReceiptAmount() { const total = parseFloat(document.getElementById('rcTotal').value) || 0; const type = document.getElementById('rcPayType').value; const paidEl = document.getElementById('rcPaid'); if(type === 'deposit') paidEl.value = Math.round(total * 0.4); else if(type === 'full') paidEl.value = total; // custom: leave it editable } document.addEventListener('change', function(e) { if(e.target && e.target.id === 'rcPayType') calcReceiptAmount(); }); function previewReceipt() { const name = document.getElementById('rcName').value.trim(); const phone = document.getElementById('rcPhone').value.trim(); const email = document.getElementById('rcEmail').value.trim(); const project = document.getElementById('rcProject').value.trim(); const total = parseFloat(document.getElementById('rcTotal').value) || 0; const paid = parseFloat(document.getElementById('rcPaid').value) || 0; const mpesa = document.getElementById('rcMpesa').value.trim().toUpperCase(); const services= document.getElementById('rcServices').value.trim(); const payType = document.getElementById('rcPayType').value; if(!name || !phone || !project || !total || !services) { alert('Please fill in all required fields (Name, Phone, Project, Total, Services).'); return; } const balance = total - paid; const num = getNextReceiptNum(); const date = new Date().toLocaleDateString('en-KE', {year:'numeric', month:'long', day:'numeric'}); const isFullyPaid = balance <= 0; const stampLabel = isFullyPaid ? 'PAID IN FULL' : 'DEPOSIT RECEIVED'; const stampClass = isFullyPaid ? 'rc-stamp full' : 'rc-stamp'; currentReceiptData = { num, name, phone, email, project, total, paid, balance, mpesa, services, payType, date, isFullyPaid }; const serviceLines = services.split('\n').map(s => s.trim()).filter(Boolean) .map(s => `
▸ ${s}
`).join(''); document.getElementById('receiptDoc').innerHTML = `
TECHGPT
Tech & AI Solutions · Nairobi, KE
+254 112 260 758 · techgpt-com.web.app
${num}
Date: ${date}
${stampLabel}
Bill To
Client Name${name}
Phone / WhatsApp${phone}
${email ? `
Email${email}
` : ''}
Project${project}
Services
${serviceLines}
Project Total
Full project value
Ksh ${Math.round(total).toLocaleString()}
Amount Paid
${payType==='deposit'?'40% Deposit':payType==='full'?'Full Payment':'Custom Payment'}
Ksh ${Math.round(paid).toLocaleString()}
${!isFullyPaid ? `
Balance Remaining
Due on delivery / demo
Ksh ${Math.round(balance).toLocaleString()}
` : ''} ${mpesa ? `
M-Pesa Transaction Code
${mpesa}
` : ''}
Payment Via M-Pesa Paybill
Paybill Number
247 247
Account Number
109481
`; document.getElementById('receiptPreviewMod').classList.add('open'); } function closeReceiptPreview() { document.getElementById('receiptPreviewMod').classList.remove('open'); } async function saveAndCloseReceipt() { if(!currentReceiptData) { closeReceiptPreview(); return; } const btn = document.querySelector('#receiptPreviewMod button[onclick="saveAndCloseReceipt()"]'); if(btn){ btn.textContent = '⏳ Saving...'; btn.disabled = true; } try { // Validate data integrity before saving if(!currentReceiptData.num || !currentReceiptData.name || !currentReceiptData.total) { throw new Error('Incomplete receipt data'); } // Deep clone to avoid reference issues on mobile const rcCopy = JSON.parse(JSON.stringify(currentReceiptData)); rcCopy.savedAt = new Date().toISOString(); receipts.push(rcCopy); // Persist — try Firestore first, fallback to localStorage let saved = false; if(window._fbDb && window._fbDoc && window._fbSet) { try { await window._fbSet(window._fbDoc('receipts'), { value: receipts }); saved = true; } catch(fsErr) { console.warn('Firestore save failed, using localStorage', fsErr); } } if(!saved) { try { localStorage.setItem('tgpt_receipts_backup', JSON.stringify(receipts)); } catch(e){} } renderAdmReceipts(); document.getElementById('statReceipts').textContent = receipts.length; hideReceiptForm(); closeReceiptPreview(); currentReceiptData = null; toast('✓ Receipt saved successfully!'); } catch(err) { console.error('Receipt save error:', err); toast('⚠ Save failed — try again'); if(btn){ btn.textContent = '💾 Save'; btn.disabled = false; } } } function renderAdmReceipts() { const g = document.getElementById('receiptGrid'); g.innerHTML = ''; if(!receipts.length) { g.innerHTML = '
No receipts yet. Generate one above.
'; return; } [...receipts].reverse().forEach((r, ri) => { const i = receipts.length - 1 - ri; const d = document.createElement('div'); d.className = 'adm-card'; d.innerHTML = `
🧾 ${r.num}
Ksh ${Math.round(r.paid).toLocaleString()} paid of ${Math.round(r.total).toLocaleString()}
${r.name} · ${r.project} · ${r.date}
${r.isFullyPaid ? '✓ Fully Paid' : `Balance: Ksh ${Math.round(r.balance).toLocaleString()}`}
`; g.appendChild(d); }); } function rePreviewReceipt(i) { currentReceiptData = receipts[i]; // Re-populate form fields so previewReceipt() can rebuild the doc document.getElementById('rcName').value = receipts[i].name; document.getElementById('rcPhone').value = receipts[i].phone; document.getElementById('rcEmail').value = receipts[i].email || ''; document.getElementById('rcProject').value = receipts[i].project; document.getElementById('rcTotal').value = receipts[i].total; document.getElementById('rcPaid').value = receipts[i].paid; document.getElementById('rcMpesa').value = receipts[i].mpesa || ''; document.getElementById('rcServices').value= receipts[i].services; document.getElementById('rcPayType').value = receipts[i].payType; previewReceipt(); } function delReceipt(i) { if(!confirm('Delete this receipt?')) return; receipts.splice(i, 1); save('receipts', receipts); renderAdmReceipts(); document.getElementById('statReceipts').textContent = receipts.length; toast('Receipt deleted'); } function getReceiptHTML() { return `Receipt ${currentReceiptData.num} — TechGPT ` + document.getElementById('receiptDoc').innerHTML + ``; } function printReceipt() { const w = window.open('', '_blank'); w.document.write(getReceiptHTML()); w.document.close(); setTimeout(() => w.print(), 500); } function downloadReceiptPDF() { const w = window.open('', '_blank'); w.document.write(getReceiptHTML()); w.document.close(); setTimeout(() => { w.print(); }, 500); toast('Use "Save as PDF" in the print dialog'); } function whatsappReceipt() { if(!currentReceiptData) return; const r = currentReceiptData; const bal = r.isFullyPaid ? 'FULLY PAID \u2713' : 'Balance: Ksh ' + Math.round(r.balance).toLocaleString() + ' (due on delivery)'; const mpesaLine = r.mpesa ? '\nM-Pesa Code: ' + r.mpesa : ''; const paybillLine = r.isFullyPaid ? '' : '\n\nPayment: Paybill 247247 \u00b7 Account 109481'; const msg = '*TECHGPT RECEIPT \u2014 ' + r.num + '*\n\n' + 'Client: ' + r.name + '\nProject: ' + r.project + '\nDate: ' + r.date + '\n\n' + '*Services:*\n' + r.services + '\n\n' + '*Project Total:* Ksh ' + Math.round(r.total).toLocaleString() + '\n' + '*Amount Paid:* Ksh ' + Math.round(r.paid).toLocaleString() + '\n' + bal + mpesaLine + paybillLine + '\n\nThank you for choosing TechGPT \ud83d\ude4f\ntechgpt-com.web.app'; window.open('https://wa.me/' + r.phone.replace(/[^0-9]/g,'').replace(/^0/,'254') + '?text=' + encodeURIComponent(msg), '_blank'); } document.getElementById('receiptPreviewMod').addEventListener('click', function(e) { if(e.target === this) closeReceiptPreview(); }); // ─── FAQ ACCORDION ─────────────────────────────────────── function toggleFaq(btn) { const item = btn.closest('.faq-item'); const isOpen = item.classList.contains('open'); // Close all others document.querySelectorAll('.faq-item.open').forEach(el => { if(el !== item) { el.classList.remove('open'); el.querySelector('.faq-q').setAttribute('aria-expanded','false'); } }); // Toggle current item.classList.toggle('open', !isOpen); btn.setAttribute('aria-expanded', String(!isOpen)); } // ─── INIT ──────────────────────────────────────────────── renderProjects(); renderOffer(); renderGrids(); renderApp(); updateQ();