The page where an agent or a vendor checks what they have on: the jobs they've booked, the applications still waiting on an answer, and the work they've finished. It was three stat tiles that counted finished jobs as confirmed, a two-way toggle, and an undated pile of cards led by generated placeholder pictures. It is now a diary grouped by day with a summary rail beside it, a booked-job dialog rebuilt in the board's language, and loading, empty and error states that were designed rather than left over. Same data layer, same tokens, nothing renamed.
Most of it was not a layout problem. The page was telling people things that were not true, and the layout made that hard to notice.
window.location, which dropped the demo's URL prefix and put a demo visitor on the login page.A day sheet. Showing agents work off a printed sheet per day, and this is the screen version of it. Each day gets a calendar rail: its name over a large date numeral, the way a wall calendar marks a day, so a column of days scans by the numerals alone. Each job is a card whose left edge is the property itself, the agent's photo bleeding to the edge with no frame, so the card reads as a house first. The text answers the questions in the order they are asked: when, as a real range; what; where; and on the far edge, how much and who is paying, in tabular figures so a column of them adds up by eye.
A row opens the right dialog for what it is. A booked or finished job opens the appointment dialog, rebuilt here in the same order the board's dialog reads. A pending application opens the board's dialog in a new applied state.
flex-1 with no min-w-0, so it could never shrink below the header's natural width. One class in App.tsx and DemoApp.tsx fixed the whole app.formatClock turns "13:00" or "13:00:00" into "1:00 pm" and hands anything that isn't a clock back untouched; formatClockRange adds the duration to make "10:00 – 11:00 am", collapsing the meridiem when both ends share it. The board's cards and dialog, the calendar rows and the dashboard widget all pick it up through the same functions.tsc --noEmit clean, eslint with no errors on every changed file, production build passing./demo at 390, 768, 1024, 1280 and 1440px, light and dark. At every width the document's scroll width equals the viewport, which is the check that caught the shell overflow./demo.| Self-critique | Score | Why |
|---|---|---|
| Philosophy | 4 | Every part answers one of the three questions a person brings to the page. |
| Hierarchy | 5 | Date numeral, house, time, title, pay. The eye has one path across each card and one path down the days. |
| Execution | 4 | Full state coverage, tokens only, one radius scale. Long titles wrap at 1280px with the rail beside. |
| Specificity | 5 | A day sheet with the house as the card's edge and a real time range is this product's, not a template's. |
| Restraint | 5 | No accent on the page, no decorative motion, no icons beyond the map pin and the service mark. |
| Variety | 4 | A diary with a rail, where the board is a list beside a map and My listings is tabs of cards. |
main as 439016b through 94475cd, pushed to the GitHub backup, and deployed to tour-dash.pages.dev on 2026-09-04.| File | What changed |
|---|---|
| src/pages/MyOpportunities.tsx | Rewritten: tabs, day-grouped agenda, summary rail, states, both dialogs. |
| src/components/AgendaList.tsx | New. The day sheet: a calendar rail with a date numeral beside per-job cards whose left edge is the property photo; the whole card is the button. |
| src/components/AppointmentDetailsDialog.tsx | Rebuilt in the board dialog's language; invented notes and placeholder image removed. |
| src/components/OpportunityPreviewDialog.tsx | Applied state (no apply button), "Your price" label, shared Fact. |
| src/components/FactStrip.tsx | New. The shared "value over label" fact. |
| src/lib/schedule.ts | New. Local-day arithmetic, day labels, "3 days ago", grouping by day. |
| src/lib/opportunity-adapter.ts | formatClock, formatPrice, exported parseLocalDate, pictures and service type on the appointment card. |
| src/App.tsx, src/demo/DemoApp.tsx | min-w-0 on the sidebar's main pane. |