-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathWISMO-Rider.html
More file actions
298 lines (288 loc) · 22 KB
/
Copy pathWISMO-Rider.html
File metadata and controls
298 lines (288 loc) · 22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>WISMO Rider</title>
<style>
:root{
--bg:#0A1A2F; --panel:#0E1B2E; --panel-2:#0F2236; --panel-3:#11283f;
--teal:#0E7490; --teal-dk:#0B5563; --teal-lt:#19A0BF;
--amber:#E8B85D; --amber-dk:#C99A3B;
--ink:#EAF1F7; --muted:#8FA3B8; --muted-2:#6B7E93;
--line:#1C2E44; --line-2:#27425E;
--green:#28C840; --green-dk:#15803D; --green-lt:rgba(40,200,64,.16);
--red:#FF5F57; --red-lt:rgba(255,95,87,.16); --orange:#F59E0B; --orange-lt:rgba(245,158,11,.16);
--mono:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
--sans:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
--r:10px; --r-lg:14px; --r-xl:22px;
}
*{box-sizing:border-box;margin:0;padding:0}
body{font-family:var(--sans);background:var(--bg);color:var(--ink);-webkit-font-smoothing:antialiased;min-height:100vh}
.bg{position:fixed;inset:0;z-index:0;pointer-events:none;opacity:.5;
background:radial-gradient(700px 500px at 90% -10%,rgba(14,116,144,.3) 0%,rgba(10,26,47,0) 60%);}
.wrap{position:relative;z-index:1;max-width:1080px;margin:0 auto;padding:28px 22px 70px}
.top{display:flex;align-items:center;gap:13px;margin-bottom:8px}
.logo{width:38px;height:38px}
.tt{font-size:19px;font-weight:700}.tt b{color:var(--teal-lt)}
.ekn{font-family:var(--mono);font-size:10.5px;letter-spacing:.08em;color:var(--teal-lt);
background:rgba(14,116,144,.16);border:1px solid var(--line-2);padding:4px 10px;border-radius:20px}
.spacer{flex:1}
.live{display:inline-flex;align-items:center;gap:8px;font-family:var(--mono);font-size:12px;color:var(--green);
background:var(--green-lt);border:1px solid rgba(40,200,64,.3);padding:6px 12px;border-radius:20px}
.live .d{width:8px;height:8px;border-radius:50%;background:var(--green);animation:p 1.8s infinite}
@keyframes p{0%{box-shadow:0 0 0 0 rgba(40,200,64,.5)}70%{box-shadow:0 0 0 8px rgba(40,200,64,0)}100%{box-shadow:0 0 0 0 rgba(40,200,64,0)}}
.lede{color:var(--muted);font-size:14.5px;margin:6px 0 26px}
.grid{display:grid;grid-template-columns:340px 1fr;gap:22px;align-items:start}
@media(max-width:820px){.grid{grid-template-columns:1fr}}
/* phone */
.phone{width:100%;background:var(--bg);border:1px solid var(--line-2);border-radius:34px;overflow:hidden;
box-shadow:0 26px 60px rgba(0,0,0,.5);position:sticky;top:20px}
.pnotch{height:22px;background:var(--panel-2);position:relative}
.pnotch::after{content:"";position:absolute;top:7px;left:50%;transform:translateX(-50%);width:90px;height:7px;border-radius:5px;background:#13283f}
.pbar{display:flex;justify-content:space-between;align-items:center;padding:10px 18px;background:var(--panel-2);
border-bottom:1px solid var(--line-2);font-size:10.5px;font-family:var(--mono)}
.online{display:flex;align-items:center;gap:6px;color:var(--green);font-weight:700}
.online .d{width:7px;height:7px;border-radius:50%;background:var(--green);animation:p 1.8s infinite}
.phdr{background:linear-gradient(135deg,var(--navy-2,#0B2E4F),var(--teal-dk));color:#fff;padding:16px 18px;display:flex;justify-content:space-between;align-items:center}
.phdr .nm{font-size:15px;font-weight:700}
.phdr .st{font-size:11px;opacity:.8}
.map{height:170px;position:relative;overflow:hidden;background:
radial-gradient(140px 90px at 28% 32%,rgba(14,116,144,.28),transparent),
linear-gradient(135deg,#0c2030,#0a1a28)}
.road{position:absolute;background:rgba(120,150,180,.18);border-radius:2px}
.rpin{position:absolute;filter:drop-shadow(0 3px 7px rgba(0,0,0,.5))}
.route{position:absolute;height:3px;background:linear-gradient(90deg,var(--teal),var(--amber));border-radius:2px;opacity:.8}
.maplbl{position:absolute;bottom:9px;right:11px;font-size:9.5px;font-weight:600;background:rgba(10,26,47,.85);padding:3px 8px;border-radius:5px;color:var(--muted)}
.stats{display:grid;grid-template-columns:1fr 1fr;gap:1px;background:var(--line-2)}
.stat{background:var(--panel-2);padding:13px 16px}
.stat .l{font-family:var(--mono);font-size:9.5px;letter-spacing:.1em;text-transform:uppercase;color:var(--muted-2)}
.stat .v{font-size:18px;font-weight:800;margin-top:4px}
.stat .v.am{color:var(--amber)}
.ocard{border:1px solid var(--line-2);border-radius:var(--r);margin:14px;padding:14px;background:var(--panel-2)}
.orr{display:flex;justify-content:space-between;align-items:center;margin-bottom:8px}
.oid{font-family:var(--mono);font-size:11.5px;color:var(--teal-lt);font-weight:700}
.addr{font-size:12px;color:var(--muted);margin-bottom:4px}
.addr b{color:var(--ink)}
.btnrow{display:grid;grid-template-columns:1fr 1fr;gap:9px;margin-top:12px}
.bp{background:linear-gradient(135deg,var(--teal),var(--teal-dk));color:#fff;border:0;border-radius:var(--r);padding:11px;font-size:12px;font-weight:700;cursor:pointer;text-align:center;transition:.15s}
.bp:hover{filter:brightness(1.08)} .bp:active{transform:scale(.98)}
.bo{background:var(--panel-3);border:1px solid var(--line-2);color:var(--ink);border-radius:var(--r);padding:11px;font-size:12px;font-weight:600;cursor:pointer;text-align:center;transition:.15s}
.bo:hover{border-color:var(--amber);color:var(--amber)}
.qp{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.07em;color:var(--muted-2);padding:8px 14px 4px}
.qi{display:flex;justify-content:space-between;align-items:center;padding:9px 14px;border-top:1px solid var(--line);font-size:12px}
.qi .qid{font-family:var(--mono);font-size:10px;color:var(--muted-2)}
.qi .qv{font-weight:700;color:var(--teal-lt)}
.bnav{display:flex;border-top:1px solid var(--line-2);background:var(--panel-2)}
.ntab{flex:1;text-align:center;padding:12px 4px;font-size:10.5px;font-weight:600;color:var(--muted-2);cursor:pointer;transition:.15s}
.ntab.active{color:var(--teal-lt);border-top:2px solid var(--teal);background:var(--panel-3)}
/* features */
.panel{background:var(--panel);border:1px solid var(--line-2);border-radius:var(--r-xl);padding:24px;box-shadow:0 24px 60px rgba(0,0,0,.4)}
.eyebrow{font-family:var(--mono);font-size:11.5px;letter-spacing:.22em;text-transform:uppercase;color:var(--amber);display:inline-flex;align-items:center;gap:9px;margin-bottom:12px}
.eyebrow::before{content:"";width:24px;height:1px;background:var(--amber);display:inline-block}
.ph{font-size:clamp(22px,3vw,30px);margin:0 0 8px;font-weight:700;letter-spacing:-.01em}
.ps{color:var(--muted);font-size:14.5px;margin:0 0 22px;max-width:520px}
.feat{display:grid;grid-template-columns:1fr;gap:12px}
.f{display:grid;grid-template-columns:46px 1fr;gap:15px;align-items:start;background:linear-gradient(180deg,var(--panel-2),var(--panel-3));
border:1px solid var(--line-2);border-radius:var(--r-lg);padding:16px;transition:.18s}
.f:hover{border-color:var(--teal);transform:translateY(-2px)}
.f .ic{width:46px;height:46px;border-radius:13px;background:rgba(14,116,144,.15);border:1px solid var(--line-2);
display:grid;place-items:center;color:var(--teal-lt)}
.f h4{margin:0 0 5px;font-size:15.5px;letter-spacing:-.01em}
.f p{margin:0;color:var(--muted);font-size:13.5px}
.f .tag{display:inline-block;font-family:var(--mono);font-size:9.5px;letter-spacing:.1em;text-transform:uppercase;
color:var(--amber);border:1px solid rgba(232,184,93,.35);padding:2px 7px;border-radius:6px;margin-top:9px}
.cta-row{display:flex;gap:12px;flex-wrap:wrap;margin-top:22px}
.btn{background:linear-gradient(135deg,var(--teal),var(--teal-dk));color:#fff;border:0;border-radius:var(--r);padding:12px 18px;font-size:14px;font-weight:700;cursor:pointer;transition:.15s;text-decoration:none;display:inline-flex;align-items:center;gap:8px}
.btn:hover{filter:brightness(1.08);transform:translateY(-1px)}
.btn.ghost{background:var(--panel-3);border:1px solid var(--line-2);color:var(--ink);font-weight:600}
.btn.ghost:hover{border-color:var(--teal);color:var(--teal-lt)}
.toast{position:fixed;bottom:22px;right:22px;background:var(--panel-2);color:#fff;padding:11px 16px;border-radius:var(--r);font-size:12.5px;box-shadow:0 12px 30px rgba(0,0,0,.5);z-index:80;border:1px solid var(--line-2)}
@media(prefers-reduced-motion:reduce){*{animation:none!important}}
.login-overlay{position:fixed;inset:0;z-index:100;background:rgba(10,26,47,.92);backdrop-filter:blur(10px);display:flex;align-items:center;justify-content:center}
.login-card{background:linear-gradient(180deg,var(--panel),var(--panel-2));border:1px solid var(--line-2);border-radius:var(--r-xl);padding:22px;width:100%;max-width:380px;box-shadow:0 30px 70px rgba(0,0,0,.45)}
.login-overlay.hidden{display:none}
</style>
</head>
<body><div class="bg"></div>
<div class="wrap">
<div class="login-overlay" id="loginOverlay">
<div class="login-card">
<div class="brand" style="margin-bottom:18px">
<svg class="logo" viewBox="0 0 120 120" aria-label="WISMO" style="width:36px;height:36px"><defs><linearGradient id="lgR" x1="18" y1="18" x2="102" y2="102" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#0B5563"/><stop offset="1" stop-color="#0E7490"/></linearGradient></defs>
<path d="M20 96 C40 60 56 100 74 56 S96 26 100 24" stroke="#0E7490" stroke-width="3" stroke-opacity=".35" stroke-linecap="round" fill="none"/>
<path d="M100 24 C112 24 112 8 100 8 C88 8 88 24 100 24 Z" fill="url(#lgR)"/>
<circle cx="100" cy="18" r="4" fill="#E8B85D"/><circle cx="20" cy="96" r="9" fill="url(#lgR)"/><circle cx="20" cy="96" r="3.5" fill="#E8B85D"/>
<circle cx="47" cy="78" r="2.5" fill="#0E7490" fill-opacity=".5"/><circle cx="74" cy="56" r="2.5" fill="#0E7490" fill-opacity=".5"/></svg>
<span class="tt" style="font-size:18px;font-weight:700;letter-spacing:.01em">WI<b>S</b>MO Rider</span>
</div>
<div style="font-size:13px;color:var(--muted);margin-bottom:14px">Sign in for demo access. Use one of the demo accounts below.</div>
<div class="row" style="gap:10px">
<div class="field"><label>Username</label><input id="loginUser" placeholder="demo@wismo.ke"></div>
<div class="field"><label>Password</label><input id="loginPass" type="password" placeholder="password"></div>
</div>
<div class="row" style="gap:10px;margin-top:10px">
<button class="btn" id="loginBtn" style="flex:1">Sign in</button>
<button class="btn ghost" id="loginDemo" style="flex:1">Use demo account</button>
</div>
<div id="loginError" style="color:var(--red);font-size:12px;margin-top:10px;min-height:16px"></div>
<div style="margin-top:14px;font-size:11px;color:var(--muted-2);line-height:1.55">
Demo credentials:<br>
• rider@wismo.ke / rider123 — Rider console and queue<br>
• admin@wismo.ke / admin123 — Full demo access
</div>
</div>
</div>
<div class="top">
<svg class="logo" viewBox="0 0 120 120" aria-label="WISMO"><defs><linearGradient id="lg2" x1="18" y1="18" x2="102" y2="102" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#0B5563"/><stop offset="1" stop-color="#0E7490"/></linearGradient></defs>
<path d="M20 96 C40 60 56 100 74 56 S96 26 100 24" stroke="#0E7490" stroke-width="3" stroke-opacity=".35" stroke-linecap="round" fill="none"/>
<path d="M100 24 C112 24 112 8 100 8 C88 8 88 24 100 24 Z" fill="url(#lg2)"/>
<circle cx="100" cy="18" r="4" fill="#E8B85D"/><circle cx="20" cy="96" r="9" fill="url(#lg2)"/><circle cx="20" cy="96" r="3.5" fill="#E8B85D"/>
<circle cx="47" cy="78" r="2.5" fill="#0E7490" fill-opacity=".5"/><circle cx="74" cy="56" r="2.5" fill="#0E7490" fill-opacity=".5"/></svg>
<span class="tt">WI<b>S</b>MO Rider</span>
<span class="ekn">EKN Consulting International Ltd</span>
<div class="spacer"></div>
<span class="live"><span class="d"></span> rider online</span>
</div>
<p class="lede">The field side of WISMO — turn-by-turn delivery, scan-to-confirm, and live reroute pushes straight from the Geo / Route service.</p>
<div class="grid">
<!-- PHONE -->
<div class="phone">
<div class="pnotch"></div>
<div class="pbar"><span class="online"><span class="d"></span> Online</span><span id="activeOrdersLabel">3 active orders</span><span id="earningsLabel" style="color:var(--amber);font-weight:700">KES 10,440 today</span></div>
<div class="phdr"><div><div class="nm">John Kimani</div><div class="st">Rider · Westlands depot</div></div><span class="live" style="font-size:10px;padding:4px 9px"><span class="d"></span> on shift</span></div>
<div class="map">
<div class="road" style="left:0;right:0;top:64px;height:7px;opacity:.5"></div>
<div class="road" style="left:0;right:0;top:118px;height:5px;opacity:.3"></div>
<div class="road" style="left:96px;top:0;bottom:0;width:6px;opacity:.4"></div>
<div class="road" style="left:182px;top:0;bottom:0;width:5px;opacity:.3"></div>
<div class="route" style="left:96px;top:64px;width:86px;transform:rotate(18deg);transform-origin:left"></div>
<div class="rpin" style="top:48px;left:80px"><svg width="24" height="30" viewBox="0 0 22 28"><path d="M11 0C5 0 0 5 0 11c0 8 11 17 11 17s11-9 11-17C22 5 17 0 11 0z" fill="#0E7490"/><circle cx="11" cy="11" r="5" fill="#E8B85D"/></svg></div>
<div class="rpin" style="top:78px;right:58px"><svg width="22" height="28" viewBox="0 0 20 26"><path d="M10 0C4.5 0 0 4.5 0 10c0 7 10 16 10 16s10-9 10-16C20 4.5 15.5 0 10 0z" fill="#FF5F57"/><circle cx="10" cy="10" r="4" fill="#fff"/></svg></div>
<span class="maplbl">Delphi route · 3 stops optimized</span>
</div>
<div class="stats">
<div class="stat"><div class="l">Today</div><div class="v" id="sDeliv">12</div></div>
<div class="stat"><div class="l">Earnings</div><div class="v am" id="sEarn">KES 10,440</div></div>
<div class="stat"><div class="l">Avg rating</div><div class="v">4.8★</div></div>
<div class="stat"><div class="l">Active</div><div class="v" id="sActive">3</div></div>
</div>
<div class="ocard">
<div class="orr"><span class="oid" id="riderOrderId">WISMO-260725-001</span><span class="live" style="font-size:9.5px;padding:3px 8px;color:var(--teal-lt);background:rgba(14,116,144,.18);border:1px solid var(--line-2)"><span class="d" style="background:var(--teal-lt)"></span> pickup next</span></div>
<div class="addr"><span style="color:var(--teal-lt)">●</span> <b id="riderPickup">Amara Okeke</b> · Westlands</div>
<div class="addr">→ <b id="riderDrop">Kileleshwa</b> · KES <b id="riderValue">2,400</b> · ETA <b id="riderEta">24m</b></div>
<div class="btnrow"><div class="bp" id="btnPickedUp">✓ Picked up</div><div class="bp" id="btnDelivered" style="background:linear-gradient(135deg,var(--green-dk),var(--green));color:#06210d">✓ Delivered</div></div>
<div class="btnrow"><div class="bo" id="btnCall">Call customer</div><div class="bo" id="btnReport">Report issue</div></div>
</div>
<div class="qp">Queue · next stops</div>
<div id="queueList"></div>
<div class="bnav"><div class="ntab active">Home</div><div class="ntab" id="tabRoute">Route</div><div class="ntab" id="tabReport">Report</div></div>
</div>
<!-- FEATURES -->
<div class="panel">
<span class="eyebrow">What riders get</span>
<h2 class="ph">Built for the last mile</h2>
<p class="ps">Every control a rider needs is one tap away — live route, customer context, and instant status that syncs to the customer's WhatsApp thread.</p>
<div class="feat">
<div class="f"><div class="ic"><svg width="22" height="22" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M9 3 3 9l6 12 6-12-6-6z"/><path d="M3 9h18"/></svg></div><div><h4>Live route & turn-by-turn</h4><p>Geo / Route computes the optimized multi-stop plan; riders see the next pin and ETA without leaving the app.</p><span class="tag">Geo · Route 3002</span></div></div>
<div class="f"><div class="ic"><svg width="22" height="22" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg></div><div><h4>Scan-to-confirm delivery</h4><p>One tap marks Picked up or Delivered; the status pushes to the order service and fires the customer's WhatsApp update.</p><span class="tag">Order 3001 · Notify 3003</span></div></div>
<div class="f"><div class="ic"><svg width="22" height="22" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 13l2-5h6l3 5M14 13h4a2 2 0 002 2 2 2 0 01-2 2M5 17a2 2 0 104 0 2 2 0 00-4 0zM17 17a2 2 0 104 0 2 2 0 00-4 0z"/></svg></div><div><h4>Live reroute pushes</h4><p>Dispatchers reroute from the console; the rider's queue and map update instantly — no phone calls, no confusion.</p><span class="tag">Delphi · console</span></div></div>
<div class="f"><div class="ic"><svg width="22" height="22" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg></div><div><h4>Customer context & chat</h4><p>Pickup name, drop address, value, and a direct call/Report line — everything needed for a clean handoff.</p><span class="tag">Customer Portal</span></div></div>
<div class="f"><div class="ic"><svg width="22" height="22" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2v20M2 12h20"/><circle cx="12" cy="12" r="9"/></svg></div><div><h4>Earnings & shift view</h4><p>Live count of deliveries, earnings, and ratings — so riders see their day add up in real time.</p><span class="tag">Telemetry</span></div></div>
</div>
<div class="cta-row">
<a class="btn" href="https://ekn1.github.io/wismo/">Open platform console →</a>
<a class="btn ghost" href="/DEMO/WISMO-Landing.html">View landing page</a>
</div>
</div>
</div>
</div>
<script>
const $ = s => document.querySelector(s);
const toast = m => { const t=document.createElement('div'); t.className='toast'; t.textContent=m; document.body.appendChild(t); setTimeout(()=>t.remove(),1800); };
const fmt = n => 'KES ' + Number(n||0).toLocaleString();
const state = {
deliveries: 12, earnings: 10440,
current: {id:'WISMO-260725-001', pickup:'Amara Okeke', zone:'Westlands', drop:'Kileleshwa', value:2400, eta:'24m'},
queue: [
{id:'WISMO-260725-002', zone:'Kileleshwa', status:'Assigned'},
{id:'WISMO-260725-004', zone:'Karen', status:'Picked up'},
{id:'WISMO-260725-005', zone:'Lavington', status:'Assigned'}
]
};
function renderRider(){
$('#riderOrderId').textContent=state.current.id;
$('#riderPickup').textContent=state.current.pickup+' · '+state.current.zone;
$('#riderDrop').textContent=state.current.drop;
$('#riderValue').textContent=state.current.value.toLocaleString();
$('#riderEta').textContent=state.current.eta;
$('#earningsLabel').textContent=fmt(state.earnings)+' today';
$('#sEarn').textContent=fmt(state.earnings);
$('#sDeliv').textContent=state.deliveries;
$('#activeOrdersLabel').textContent=(state.queue.length+1)+' active orders';
$('#sActive').textContent=state.queue.length+1;
$('#queueList').innerHTML=state.queue.map(x=>`<div class="qi"><span class="qid">${x.id}</span><span>${x.zone}</span><span class="qv">${x.status}</span></div>`).join('')||'<div class="qi"><span>Queue empty</span></div>';
}
$('#btnPickedUp').addEventListener('click',()=>{ toast('Picked up — customer notified'); });
$('#btnDelivered').addEventListener('click',()=>{
state.deliveries++; state.earnings+=state.current.value;
toast('Delivered ✓ — earnings updated');
if(state.queue.length){ state.current=state.queue.shift(); } else { state.current=null; }
renderRider();
});
$('#btnCall').addEventListener('click',()=>toast('Calling '+ (state.current?state.current.pickup:'customer') +'…'));
$('#btnReport').addEventListener('click',()=>toast('Issue reported — dispatcher notified'));
$('#tabRoute').addEventListener('click',()=>toast('Route view — 3 stops optimized'));
$('#tabReport').addEventListener('click',()=>toast('Report view'));
renderRider();
const DEMO_USERS = {
'rider@wismo.ke': { password:'rider123', role:'rider', name:'John Kimani' },
'admin@wismo.ke': { password:'admin123', role:'admin', name:'Demo Admin' },
};
const ROLE_VIEWS = {
rider: ['rider','tracking'],
admin: ['rider','tracking'],
};
function applyRole(role){
window.__wismoRole = role;
const allowed = ROLE_VIEWS[role] || [];
$$('.side .nav').forEach(n=>{
const view = n.dataset.view;
n.style.display = allowed.includes(view) ? '' : 'none';
if(!allowed.includes(view)) n.classList.remove('active');
});
const accountName = DEMO_USERS[Object.keys(DEMO_USERS).find(k=>DEMO_USERS[k].role===role)]?.name || 'Demo';
$('.side .hd').textContent = accountName;
if(!allowed.includes('rider')) showView(allowed[0] || 'rider');
}
function loginSuccess(user){
$('#loginOverlay').classList.add('hidden');
$('#loginError').textContent = '';
applyRole(user.role);
}
$('#loginBtn').addEventListener('click',()=>{
const u = $('#loginUser').value.trim();
const p = $('#loginPass').value;
const rec = DEMO_USERS[u];
if(!rec || rec.password !== p){ $('#loginError').textContent = 'Invalid demo credentials.'; return; }
loginSuccess({ role: rec.role });
});
$('#loginDemo').addEventListener('click',()=>{
const rec = DEMO_USERS['rider@wismo.ke'];
$('#loginUser').value = 'rider@wismo.ke';
$('#loginPass').value = rec.password;
loginSuccess({ role: rec.role });
});
$$('.side .nav').forEach(n=>n.addEventListener('click',()=>{
const view = n.dataset.view;
const allowed = ROLE_VIEWS[window.__wismoRole || 'rider'] || [];
if(!allowed.includes(view)){ toast('Not available for this demo role'); return; }
showView(view);
}));
(function init(){
if(!window.__wismoRole){ $('#loginOverlay').classList.remove('hidden'); return; }
renderRider();
})();
</script>
</body>
</html>