// ============================================================= // FIELD FORCE FEATURE GRAPHICS (9) // ============================================================= const useTickFF = (interval = 1800) => { const [t, setT] = React.useState(0); React.useEffect(() => { const id = setInterval(() => setT(x => x + 1), interval); return () => clearInterval(id); }, [interval]); return t; }; const FBar = ({ url }) => (
{url}
); // 1. TRACK ROUTES — animated GPS breadcrumb trail const RoutesMock = () => (
today's trail · rahul s.
74.2 km · 8 stops
Live
{/* roads */} {/* breadcrumb path */} {/* stops */} {[[50,80,'9:14'],[200,90,'10:22'],[280,150,'11:48'],[360,130,'13:05'],[430,200,'14:30'],[510,180,'15:42'],[560,250,'16:55']].map(([x,y,t],i) => ( {t} ))} {/* live courier */}
{[['Distance','74.2 km'],['Stops','8'],['Idle','22 min'],['Speed avg','38 km/h']].map(([k,v]) => (
{k}
{v}
))}
); // 2. FFA REIMBURSEMENT const FFAReimburseMock = () => (
field claims · this week
₹ 24,860 from 18 reps
{[ { i: '⛽', l: 'Fuel', amt: 14200, n: 32 }, { i: '🍱', l: 'Meals', amt: 6400, n: 18 }, { i: '🅿️', l: 'Toll/Park', amt: 4260, n: 24 }, ].map(c => (
{c.i}
₹ {c.amt.toLocaleString('en-IN')}
{c.l} · {c.n} claims
))}
{[ { who: 'Rahul', what: 'Fuel · Vijay Nagar → Super Corridor', amt: 480, gps: '✓ GPS', photo: '✓ Bill' }, { who: 'Meera', what: 'Lunch · Client visit', amt: 320, gps: '✓ GPS', photo: '✓ Bill' }, { who: 'Karthik', what: 'Toll · Pithampur trip', amt: 280, gps: '✓ GPS', photo: '—' }, ].map((r,i) => (
{r.who[0]} {r.who} · {r.what} ₹ {r.amt} {r.gps} {r.photo}
))}
); // 3. FFA ATTENDANCE — geo-tagged start day const FFAAttendanceMock = () => { const t = useTickFF(2200); return (
field attendance · live
62 of 68 started day
91% on time
{[ { who: 'Rahul S.', loc: 'Vijay Nagar · 22.7533,75.8937', t: '8:42 am', status: 'started', selfie: true }, { who: 'Meera K.', loc: 'Bhawarkua · 22.6953,75.8653', t: '8:51 am', status: 'started', selfie: true }, { who: 'Karthik V.', loc: 'Pithampur SEZ', t: '8:58 am', status: 'started', selfie: true }, { who: 'Anish M.', loc: '— not started', t: '—', status: 'pending' }, ].map((r,i) => (
📷
{r.who} 📍 {r.loc} {r.t} {r.status === 'started' ? '✓ In' : 'Pending'}
))}
); }; // 4. VISITS const VisitsMock = () => (
today's visits · 24 logged
18 successful · 4 follow-ups · 2 missed
{[ { c: 'Surya Pharma', who: 'Rahul', out: 'Order placed · ₹ 84k', at: '10:22 am', tag: 'success', icon: '✓' }, { c: 'BlueWave Retail', who: 'Meera', out: 'Demo done · follow-up Tue', at: '11:48 am', tag: 'follow', icon: '↻' }, { c: 'Patel Stores', who: 'Karthik', out: 'Collection ₹ 12,400 · cheque', at: '13:05 pm', tag: 'success', icon: '✓' }, { c: 'Nimbus Foods', who: 'Anish', out: 'Owner not available', at: '14:30 pm', tag: 'missed', icon: '✗' }, ].map((v,i) => { const colors = { success: 'var(--accent-500)', follow: 'var(--warn-500)', missed: 'var(--rose-500)' }; return (
{v.c[0]}
{v.c}
by {v.who} · 📍 GPS · 📷 photo
{v.out} {v.at} {v.icon} {v.tag}
); })}
); // 5. COLLECTION const CollectionMock = () => { const t = useTickFF(1500); return (
cash collection · today
Synced to ledger
{[ { l: 'Cash', a: 84600, c: '#10b981' }, { l: 'Cheque', a: 142000, c: '#4f46e5' }, { l: 'UPI', a: 58000, c: '#f59e0b' }, ].map((m,i) => (
{m.l}
₹ {m.a.toLocaleString('en-IN')}
))}
{[ { c: 'Surya Pharma', amt: 124000, mode: 'Cheque #482301', by: 'Rahul', dep: 'HDFC' }, { c: 'Patel Stores', amt: 12400, mode: 'Cash', by: 'Karthik', dep: 'Pending deposit' }, { c: 'Anand Mart', amt: 38000, mode: 'UPI', by: 'Meera', dep: 'Auto · ICICI' }, ].map((r,i) => (
{r.c} ₹ {r.amt.toLocaleString('en-IN')} {r.mode} by {r.by} 📦 {r.dep}
))}
); }; // 6. PARTY MASTER const PartyMasterMock = () => (
party master · 1,284 records
Customers, vendors, distributors
PartyTypeGSTINCityCr daysOutstanding
{[ { n: 'Surya Pharma Pvt Ltd', t: 'Customer', g: '27AABCS1234A1Z5', c: 'Indore', cd: 30, os: 248000 }, { n: 'BlueWave Retail', t: 'Customer', g: '27AAACBL890K1ZP', c: 'Indore', cd: 45, os: 0 }, { n: 'Patel & Sons (Distrib)', t: 'Distrib', g: '24AABCP4521K1ZQ', c: 'Ujjain', cd: 21, os: 84500 }, { n: 'Nimbus Foods', t: 'Customer', g: '29AAFCN9012L1ZA', c: 'Bhopal', cd: 30, os: 0 }, { n: 'Krishna Logistics', t: 'Vendor', g: '07AAACK4567P1ZX', c: 'Gwalior', cd: 15, os: 124000 }, ].map((p,i) => { const colors = { Customer: 'var(--brand-500)', Distrib: 'var(--accent-500)', Vendor: 'var(--warn-500)' }; return (
{p.n} {p.t} {p.g} {p.c} {p.cd}d 0 ? 'var(--rose-500)' : 'var(--ink-500)' }}>{p.os > 0 ? `₹ ${p.os.toLocaleString('en-IN')}` : '—'}
); })}
); // 7. ROUTE PLAN const RoutePlanMock = () => (
beat plan · monday
Indore North — 12 stops
AI optimized · saved 38 km
{/* Route list */}
{[ { t: '9:30', c: 'Surya Pharma', loc: 'Vijay Nagar' }, { t: '10:15', c: 'BlueWave Retail', loc: 'AB Road' }, { t: '11:00', c: 'Patel Stores', loc: 'Geeta Bhawan' }, { t: '12:30', c: 'Anand Mart', loc: 'Bhawarkua' }, { t: '14:00', c: 'Nimbus Foods', loc: 'Rajwada' }, { t: '15:30', c: 'Kavya Pharma', loc: 'Scheme 54' }, { t: '17:00', c: 'Coastal Build', loc: 'Annapurna' }, ].map((s,i) => (
{s.t}
{i+1}. {s.c}
📍 {s.loc}
))}
{/* Mini map */}
{[[60,40],[100,70],[80,130],[150,170],[200,140],[230,220],[180,280]].map(([x,y],i) => ( {i+1} ))}
); // 8. MIS REPORT const MISMock = () => (
mis report · week 17
Sales · West region
{[ { l: 'Visits', v: 384, d: '+12%', c: 'var(--accent-600)' }, { l: 'Orders', v: 184, d: '+8%', c: 'var(--accent-600)' }, { l: 'Revenue', v: '₹ 24.8L', d: '+18%', c: 'var(--accent-600)' }, { l: 'Collection', v: '₹ 19.2L', d: '−4%', c: 'var(--rose-500)' }, ].map((k,i) => (
{k.l}
{k.v}
{k.d} vs prev wk
))}
{/* Bar chart by rep */}
Top reps · revenue
{[ { n: 'Rahul S.', v: 92, amt: '4.8L' }, { n: 'Meera K.', v: 78, amt: '4.1L' }, { n: 'Karthik V.', v: 65, amt: '3.4L' }, { n: 'Anish M.', v: 52, amt: '2.7L' }, { n: 'Priya M.', v: 38, amt: '2.0L' }, ].map((r,i) => (
{r.n}
₹ {r.amt}
))}
); // 9. COMPLAINT const ComplaintMock = () => { const t = useTickFF(2400); const cols = [ { name: 'Open', c: '#94a3b8', cards: [{ t: 'AC repair · Bhawarkua', urgent: true, sla: '2h', sla_color: '#f43f5e' }, { t: 'Demo · Surya Pharma', sla: '4h' }, { t: 'Order delivery · Super Corridor', sla: '6h' }] }, { name: 'In progress', c: '#4f46e5', cards: [{ t: 'Site survey · Palasia', urgent: true, sla: '1h', sla_color: '#f43f5e' }, { t: 'Collection · Vijay Nagar', sla: '3h' }] }, { name: 'Resolved', c: '#10b981', cards: [{ t: 'Service · Rau', sla: '✓' }, { t: 'Inspection · Pithampur', sla: '✓' }, { t: 'Demo · HQ', sla: '✓' }] }, ]; return (
complaint board · today
SLA-routed to nearest tech
94% resolved in SLA
{cols.map((col,ci) => (
{col.name} {col.cards.length}
{col.cards.map((c,ji) => (
{c.t} {c.sla}
))}
))}
); }; Object.assign(window, { RoutesMock, FFAReimburseMock, FFAAttendanceMock, VisitsMock, CollectionMock, PartyMasterMock, RoutePlanMock, MISMock, ComplaintMock });