| Duration | ~60 min in the lesson + ~30 min homework |
| Prerequisites | Checkpoint lesson-5.3; the browser connection from 1.6. |
| Checkpoint | lesson-5.4 |
What you will have
The student has a board at /admin/pipeline with one column per stage. A lead's status can be changed by dragging its card, from the keyboard, or from the lead card, and every change is written to lead_status_history with its time. Marking a lead lost asks for a reason.
Video
The video for this lesson is not recorded yet.
Prompts used in this lesson
Part 5 — Building the board
Build the pipeline board at /admin/pipeline, replacing the placeholder, and add status changing to the lead card. Purpose: the owner sees the whole pipeline at once and moves leads between stages; every move is recorded so the dashboard can later measure response time and win rate. Context: docs/crm-spec.md, the lead_status_history table, the lead card and list from earlier lessons. One door for status changes: a single server-side function that every status change uses. It checks the new status is one of the five stages, updates leads.status and inserts a lead_status_history row (from status, to status, time, optional reason) as one transaction, so both are saved or neither. If the new status equals the current one, it does nothing and records nothing. A change to lost requires a non-empty reason. Board: - five columns in pipeline order: new, contacted, qualified, won, lost, each with its name and the number of cards; - a card shows the lead's name, how long ago it was created and the first words of the message, and links to the lead card; - cards within a column are ordered newest first; - dragging a card to another column changes its status. The card moves at once; if saving fails, it returns to where it was and an error is shown; - every card also has a "Move to" control usable with the keyboard alone and by screen readers, offering the other four stages; - dropping or moving to lost opens a dialog asking for the reason; Cancel leaves the lead where it was; - won and lost columns show only leads whose status changed in the last 30 days, with a link to the full list filtered by that status, so the board stays readable. Lead card: - the status badge becomes a control that changes status through the same function, with the same lost-reason dialog; - a new "History" section lists every status change for this lead, newest first: from, to, date and time in the business time zone, and the reason when there is one. Drag and drop library: choose one yourself, but first check the package registry and the library's own documentation, not memory. It must be currently maintained and not deprecated, work with the React and Next.js versions in this project, and support keyboard operation. Tell me which you chose, its latest version and release date, and why, before installing it. Constraints: all changes happen on the server for the signed-in owner only. The board must be usable on a phone: columns scroll sideways, and "Move to" works by touch. Before you report, verify in a real browser using the browser connection; when the login page appears, wait while I sign in myself. Check and report on each: drag one lead from new to contacted, then confirm its badge in /admin/leads, its History section on the lead card, and a new row in lead_status_history; move a second lead using only the keyboard; move a lead to lost, cancel the dialog and confirm nothing changed and no history row was written; move it to lost with a reason and confirm the reason is stored; drop a card back on its own column and confirm no history row; change a status from the lead card and confirm the board shows it; check the board at phone width. Run the build. Say plainly what you could not verify.
Do along
- Pause at the prompt in Part 5. Run the prompt. Before approving the library, ask Claude to show the evidence that it is maintained; note the name in
docs/crm-spec.md. - Adapt the lost reasons: ask Claude to offer your four or five most likely reasons as quick choices plus a free-text "other".
- After Part 6, take one sample lead through every stage from new to won, using a different method for each move: drag, keyboard, lead card.
- Mark one lead lost, cancelling once and confirming once.
- After each move, look at the list, the lead card and the
lead_status_historytable. - Do the "Check your work" steps, then run the commit and tag commands that end the lesson.
Check your work
- Open
/admin/pipeline. Expected: five columns in order, each with a count; the counts of new, contacted and qualified match the list filtered by that status. - Drag a lead from New to Contacted. Expected: the card stays in Contacted after a page reload.
- Open
/admin/leadsand find that lead. Expected: badge "contacted". - Open the lead's card. Expected: a History line "new → contacted" with the current time.
- Open
lead_status_historyin the Supabase table view. Expected: a new row for that change. - Without touching the mouse, move another lead with "Move to". Expected: it moves and a history line appears.
- Move a lead to Lost and press Cancel. Expected: the lead is where it was; no new history row.
- Move it to Lost with a reason. Expected: the reason is shown in History.
- Change a status from a lead card. Expected: the board shows the card in the new column.
Common problems
- The card jumps back after dropping. → Saving failed and the board undid the move, as designed. → Read the error shown, then: "Dropping a card fails with this message: <message>. Find the cause and verify the fix in the browser."
- The card moves but the list still shows the old status. → The screen changed but nothing was saved, or the list shows stored-earlier data. → "After a move, the list shows the old status even after reload. Check that the status function really runs and that the list is not serving a stale copy."
- Status changes but there is no history row. → Some path bypasses the one door. → "Find every place that changes leads.status and make each use the single status function. List the places you found."
- Dragging does not work on a phone. → Touch settings of the library. → Tell Claude what happens; in the meantime "Move to" works.
- Claude proposes react-beautiful-dnd. → Outdated knowledge. → "That package is marked deprecated on npm. Check the registry and choose a maintained alternative."
Homework
About 30 minutes, on your own, after the lesson. No later lesson depends on it.
- A pretend week, on your phone. Open the board on your phone. Pick eight sample leads, invent what happened to each this week, and move them accordingly; mark at least two as lost with a reason. Leave at least one lead in every column. Deliverable: eight leads with a believable story. Done when: the History section on each of the eight cards matches the story you invented, and every move worked on the phone.
- What each lost reason would change. For each lost reason in your list, write one line: "If this became my most common reason, I would change …". Deliverable: a section "Lost reasons" in
docs/crm-habits.md(your own notes; create it if missing). Done when: every reason has an action, or is marked "nothing to change". - Where will leads pile up? Look at the column counts and think about your real week. Write two or three sentences: which column would fill first in your business, and what you would do on the day it holds more than ten cards. Deliverable: the sentences, in the same file. Done when: they name one column and one action.
If a task changed files in the project, commit and push without a tag.
Save your work
git add -A
git commit -m "Lesson 5.4: pipeline board, status changes with history, lost reason"
git tag lesson-5.4
git push
git push --tags