design
Rider Support Agent — design notes (MVP)
Section titled “Rider Support Agent — design notes (MVP)”The tool a customer service rep uses to find a rider, raise an issue-management case, and stay on it until the rider confirms the fix. This is the MVP defined in the Rider Support Console MVP PRD v3.1 (atlas docs/rider-support-mvp-prd-v3.1.docx).
Persona: Sarah Igwoba · Rider Support Agent, all clusters, filed under revenue-assurance. Boots straight to Support home with no login gate. The shell is copied verbatim from starter-template: sidebar, topbar, dormant login, role switcher, account menu, notifications, settings and dark mode. Only the content views are specific to this flow.
What changed from the first version
Section titled “What changed from the first version”The first version of this flow was the full vision: a WhatsApp inbox, a call panel, its own ticket taxonomy and parent/child escalation. The MVP drops all of that:
- No third-party integrations. Calls and WhatsApp stay on the support handset. The agent logs what happened in Atlas, so there is no inbox, thread or composer.
- A ticket is an issue-management case. Cases use the production issue types (Swap, Field Support, Tricycle Hardware, plus a new Revenue Assurance “Rider enquiry” type). The team comes from the existing routing rules. The statuses are each team’s own workflow statuses (Requested, In transit, Arrived, Needs reupload, Escalated, Resolved, Closed, Done). Serials use the real
SC-YYYYMMDD-NNNNformat. The agent never picks the team. - The agent follows the case instead of owning a parent ticket. The case goes to the team. The agent tracks it as its raiser, calls the rider back, and confirms before it closes.
The full-vision version is still in git history and in PR #80.
Screens
Section titled “Screens”-
Support home (
v-dashboard)- Four KPI cards split every open case support raised, with each case in exactly one card: Needs callback, Past due, Unassigned, On track. They are assigned in that order of precedence, so the four always add up to the total in the On track sub-line. Each card opens Cases filtered to that bucket.
- A trend chart of cases raised per day, with the canonical
.chart-tiphover. - An Open cases by team breakdown, computed from the same open cases, so it sums to the KPI total.
- Two table cards grouped behind a page-level
.pseg(never stacked):- Find a rider searches plate, name and both phone numbers.
- Needs callback shows why each case needs a call.
-
Rider (
v-rider): the inner page an agent works from while the rider is on the line. It opens from Find a rider or from a case.- KPIs: wallet balance (overdraft in the sub-line), last swap, swap efficiency over 30 days, and open cases across every team.
- The Rider tab shows identity, keke and station fields as
.td-rows. - The Cases tab shows every case on the rider, raised by anyone, scoped Open / Closed · last 30 days / All cases.
- Raise case is the primary action.
-
Cases (
v-cases): every case support raised.- Search, plus two inline dropdown filters: view (All open, the four buckets, Raised by me, Closed) and team.
- The SLA column shows time left, turns amber in the last quarter of the target, and turns red when overdue.
- The pager is rendered from the filtered rows and is hidden when everything fits on one page.
-
Case detail (
v-case): an inner page with.pg-back, the serial as the title and the workflow status badge inline.- KPIs: SLA, Open for, Priority, and rider contacts (intake plus logged follow-ups).
- Overview has a case card (type, team, assignee, location, keke can move, channel and contact number, raised by), what the rider reported, a rider card, and the latest two events.
- Timeline lists every status change, assignment, follow-up and chase, newest first.
- Actions depend on state:
- Follow up shows while the case is open.
- Confirm with rider shows only once a team marks the case resolved.
Batch 1 (PRD v2.1)
Section titled “Batch 1 (PRD v2.1)”- Routing follows issue management strictly. The Raise case dialog uses the same primary-then-secondary picker as the station manager and RM apps, with the same labels. The secondary type is locked until a primary is chosen.
- The team comes from the routing rules: a rule for the secondary type beats a rule for the primary alone.
- Types and secondaries with no rule are not offered. Production has five today: Wallet dispute, Field Support - Electrical, REPT Battery Issues, Bay walk-in, and Other · Faulty keke parked at station.
- The SLA comes from the most specific SLA policy.
- Location is entered by the agent from what the rider says: location type and detail. Vehicle GPS is never shown to support (removed in PRD v2.7).
- Notifications go to roles. Case detail has a “Who is notified” card listing the receiving team’s lead role (with its current holders), its members, the assignee, the Rider Support team as follower, and the team mailbox used when a role is empty.
- The timeline records every email, with the case ID subject line.
- Escalation to the team lead role is automatic when a follow-up goes on a late case.
- Cases has a KPI row. It uses the same four-way split as Support home (each case in exactly one card) and follows the team filter, so the page’s filter applies to the whole page.
- Tables use a
<colgroup>, and cells stay on one line with an ellipsis (PATTERNS: Tables).
Batch 2 (PRD v2.4): when no issue type fits
Section titled “Batch 2 (PRD v2.4): when no issue type fits”- A raised case lands in the receiving team’s queue in their own app, through issue management. Email goes out as well. The timeline and the Where this goes card say “Created in Field Support queue (their app)”.
- Follow up with the team always emails the person assigned (worked out at send time), or the team lead role when nobody is assigned.
- Can’t find the issue type? Under the type pickers, a row switches the Raise case dialog to describing the problem.
- As the agent types, Closest issue types suggests up to three existing types, each with how many past cases looked like it and which team it goes to. Use this returns to the routed raise.
- Only after the suggestions does None of these fit unlock a case title.
- The line manager owns unclassified cases until they close. A no-type case is raised as Rider Support’s Unclassified type, and the routing rule puts it in Rider Support triage.
- It is owned by the South West Revenue Assurance Lead role, taken from issue management rather than Polaris. That role is emailed with the case ID and the agent’s details, and the agent is copied.
- The line manager emails the team responsible and the issue management admins.
- Add responsible team (agent role). A
.dlglists issue-management teams and their members only. A team with no members is shown disabled until the admins add them. Once saved, the person responsible gets every update. - Update the agent (Revenue Assurance Lead role, through the role switcher). A
.dlgsends an update to the agent and the person responsible, and can close the case. While the line manager owns the case, the agent’s follow-ups email the line manager. - Weekly review. Cases has a No matching type view, which is the issue management admins’ weekly list for adding types and routing rules. Notifications add an “Update from your line manager” item.
Batch 3 (PRD v2.6): the agent’s day
Section titled “Batch 3 (PRD v2.6): the agent’s day”- Support home shows only cases this agent raised: the KPIs, the team breakdown, the chase list and Needs callback. Cases raised by others appear only on the rider they belong to.
- Today’s chase list is the first
.psegpanel and opens by default. It has two parts:- A Today’s routine · set by your line manager card: working day 07:00 to 20:00, chase every open case you raised and close it within its SLA, and add a daily note on anything past its SLA.
- An Open cases you raised table, overdue first, with a Today column: Note required, Chased or Not chased. The table head shows chased-today progress and how many cases need a note.
- Follow up with the team (was Log follow-up; Chase team is merged into it). The To and CC rows show who it reaches, set by the case’s state: the assignee; the team lead role when nobody is assigned; the assignee with the lead role copied when the case is past its SLA. One required message to the assignee, or to the team lead role if nobody is assigned, which is the email; on someone else’s case the raiser is copied. An optional I spoke to the rider toggle adds the channel and what was said: it is saved on the case, not emailed, and is what counts as a rider contact for repeat callers. On a case past its SLA, sending the message counts as today’s note.
- Cases raised by others. The rider’s Cases tab lists every case on the rider and who raised it (“by Lawson Afeuni”). The case page shows the raiser with their role and the assignee’s work phone, so the agent can call while the rider holds.
- The agent can only log a follow-up on these. It emails the assignee and copies the raiser.
- Confirm with rider is hidden on them.
- Shift handover is built but off by default. The routine has one shift, so Write handover, the Handover panel and its notification are hidden. They switch on when the line manager’s workflow defines more than one shift (
ROUTINE.shifts); nothing is hard-coded. - My numbers (
v-stats). The agent’s own week: KPIs, a per-day chart, a by-issue-type breakdown and recent closures (every row opens its case). - Repeat callers (3 or more contacts in 7 days, on any case).
- A red badge and a contacts card on the rider view.
- A Contacts · 7 days column in Find a rider.
- Escalate instead in Raise case, and Escalate to line manager, which emails the South West Revenue Assurance Lead role.
Dialogs (centred .dlg, never a side drawer)
Section titled “Dialogs (centred .dlg, never a side drawer)”- Raise case
- Fields: rider, channel, contact number, issue type (grouped by business unit) and detail, location, priority, keke can move, and what the rider reported.
- A Where this goes card shows the routed team, its team leads and the SLA due time before the agent submits.
- The priority defaults from the type: Battery rescue is Critical with a 2-hour target, and Rider enquiry is Low.
- Already open on this rider appears when the rider has an open case of the same type and offers Add to that case, so one problem stays one case.
- Rider enquiry types also offer Resolve now, which raises and closes the case on first contact.
- “Other” needs at least 30 characters of description.
- Follow up with the team: a message emailed to the assignee, plus an optional record of what the rider was told; both are saved on the case.
- Confirm with rider: the agent records one of three outcomes.
- It is fixed: the case closes.
- It is not fixed: a new linked case is raised with the original description, which is how reopening works.
- Unreachable after two attempts: the case closes as unconfirmed and is reported separately.
Grounding
Section titled “Grounding”Teams, team leads, issue types and workflow statuses were taken from the production issue_management_* tables on 5 Oct 2026:
- Swap Support: Ridwan Egbeyemi, Jumai Abidoye, Omeiza Ahmed.
- Field Support: Gbenga Akilo, Miracle Edwin.
- Tricycle Maintenance Team: Musbau Azeez, Erioluwa Morenikeji, Folusho Dada.
Rider Support is the new team the PRD configures under the Revenue Assurance business unit. Riders are illustrative. “Now” in the prototype is Monday 5 October, 16:00.
Batch 5 (PRD v3.0): account answers
Section titled “Batch 5 (PRD v3.0): account answers”What riders call about besides faults, all on the rider page:
- Loans card (after the caller check). It shows the active loan, of either type:
- Tricycle parts loan: principal and total, daily amount, paid so far (n of N), left to pay, due date, and an Overdue badge.
- Tricycle purchase loan (live from 7 Oct): price, ₦4,000 a paying day, 4% a month, and the pending status. A hint explains that interest is charged on the first day of each loan month.
- Below it, a
.prof-sectCan they get a loan? section. The parts loan shows the Max Allowable Loan, or the reason it is zero: an active loan, 14 or fewer swap days, or efficiency at or below 0.80. The purchase loan shows its requirements and refers the rider to their RM.
- Payments tab. The wallet KPI opens a third
.psegpanel, Wallet activity, laid out as the Caesar ledger table.- Columns are date and time, entry and where (
.td-title/.td-sub), a status badge, the amount and the balance after. Money cells aretd.r.amt. - Each row is a funding, a swap fee (the sub-line shows any loan inside it), a reversed fee, or its refund. Free later swaps appear in the entry dialog, not as ₦0 rows.
.tbl-footcarries the month’s net charged, with the charged, returned and funded figures in its label.- The card head holds a month
.filt-selectand a Dispute guide button, which opens the eight dispute cases in a.dlg. - Every row opens a compact
.dlgwith the fee and loan split, the later free swaps, the balance after and a reference. - May 2026 shows an
.empty-wrapexplaining that history before June is incomplete. The whole tab is locked until the caller check is complete.
- Columns are date and time, entry and where (
- Funding accounts card. Active accounts with the primary first and a Copy action. A deactivated account is called out. Shown without the caller check, because these are pay-in accounts only.
- First swap date in Identity, with a blue New rider badge on the title for riders within 30 days of their first swap.
- Maintenance bay is v2. No bay is linked to swap stations in the data yet, so it is not shown.
- Rider enquiry gains two secondary types: Loan status or eligibility, and Funding account details.
Batch 4 (PRD v2.9): caller check, team replied, attachments, callbacks
Section titled “Batch 4 (PRD v2.9): caller check, team replied, attachments, callbacks”- Caller check (G1). The rider page opens with a Caller check card: plate number, registered name and calling from a number on file, as
.frrows with.tgltoggles.- Two of three verifies the caller. I called them on a number on file verifies outbound calls in one step.
- Until verified, the wallet KPI shows dots and “verify the caller to see”. Once verified, a green Caller verified badge sits beside the rider’s name.
- A case raised afterwards records which checks were confirmed, or “Caller not verified”, on its first timeline entry.
- Team replied (G2). A reply from the team on the agent’s case moves it into Needs callback with a blue Team replied badge in the chase list’s Today column, and adds a notification. The reply appears on the case timeline.
- The badge clears when the agent follows up having spoken to the rider, and the case drops back to its previous bucket. Support home recounts.
- Attachments (G3). Raise case and Follow up have a Photos or receipts field: the canonical
.att-zonedrop zone with.att-grid/.att-cardpreviews (Polaris), spacing kept on the 4px grid.- The case page has an Attachments card. Long file names cut off with an ellipsis and a
title.
- The case page has an Attachments card. Long file names cut off with an ellipsis and a
- Scheduled callbacks (G4). Raise case (Promised the rider a callback) and Follow up (Call the rider back) take a day and time.
- The chase list shows grey “Call back 17:00”, amber within 30 minutes, and red “Missed 15:30”. A missed callback puts the case in Needs callback.
- The case page has a Callback row. Speaking to the rider clears a missed callback.
Canon review (PRD v2.7)
Section titled “Canon review (PRD v2.7)”A full canon review (the repo’s design-reviewer method), plus a text-spill scan of every view, case and dialog, led to these changes:
- Long text no longer sits in
.fr-label, which cannot shrink. The case timeline, latest events and rider contacts use the canonical.tl-steptimeline. The rider’s report, the handover note and the routine are.body-textprose. - Dialogs no longer nest white
.cards. Captioned groups are.prof-sect, and key/value groups are.td-detailswith.frrows (Polaris). - Toggles in dialogs are
.frrows with the.tglin.fr-valand the explanation in a.fld-hint. The Settings-only.set-rowand.set-footare no longer used outside Settings. In-section actions use.sect-act, with no inline margins. - KPIs show direction: a
.trendchip in.pstat-valrow(vs yesterday on Support home, vs last week on My numbers), with good and bad set per metric. - Support home’s chart, KPIs and cards are scoped to “you raised”. Cases has a Raised by me / All support scope filter that drives both its KPIs and its rows, so a home card opens a list with the same count.
- The case page’s Priority moves from a
.pstatinto a.td-rowbadge, and a numeric Follow-ups sent KPI takes its place. The SLA icon tone follows the state. The rider page’s “Last swap” becomes Swaps · last 30 days. - Ellipsized table cells carry a
title. Headers name their pairing (“Case · raised by”) and their measure (“Time to callback”). - Gap fixed between a card and the table card below it in the same panel, and
--amber-textlifted for dark mode.
Canon notes
Section titled “Canon notes”- No custom CSS beyond the starter’s, except one rule:
.pg-view > .pseg{margin-bottom:16px}, whichweb-stacked-tables-not-tabbedprescribes. - Empty states are
.empty-wrapinside the table card whose table came back empty. - Filters inside a table card head are
.filt-selectdropdowns, never a.pseg. - KPI sub-lines never repeat the currency symbol, because the probe allows a unit to be printed only once per value.