| Duration | ~60 min in the lesson + ~20 min homework |
| Prerequisites | Checkpoint lesson-5.1; the browser connection from 1.6. |
| Checkpoint | lesson-5.2 |
What you will have
The student has an admin layout with navigation and sign-out, and a lead list at /admin/leads with search, filters by status and date, sorting and pagination. The database holds about forty realistic sample leads to practise on.
Video
The video for this lesson is not recorded yet.
Prompts used in this lesson
Part 2 — Sample data first
I need realistic sample data so I can build and test the CRM screens. Context: read docs/crm-spec.md and the migrations. The business is described in docs/brief.md. Write a seed script that inserts 40 sample leads directly into the database (not through /api/leads, so no notifications are sent): - varied, fictional names; every email ends in @example.com; phone numbers are obviously fake, and about a quarter of leads have no phone; - messages that sound like real enquiries for this business, from one line to a short paragraph; - created dates spread over the last 60 days, more in recent weeks, at different times of day; - statuses: roughly 12 new, 10 contacted, 8 qualified, 5 won, 5 lost; - created_via is form for all of them; - for every lead that is not new, matching rows in lead_status_history that tell a believable story: each change with its from status, to status and a time after the lead was created. Lost leads have a short reason. Also write a second script that removes all sample data: every lead whose email ends in @example.com, together with its notes, tasks and history. Constraints: the seed script must refuse to run twice (if sample leads already exist, it says so and stops). Do not touch leads that are not samples. Do not print any keys. Done means: you ran the seed, then counted leads per status and history rows per lead in the database, and reported the counts to me.
Part 4 — Building the list
Build the admin layout and the lead list, as described in docs/crm-spec.md. Purpose: the owner must be able to see every lead and find any one of them in a few seconds. Admin layout, shared by every page under /admin except the login: - sidebar with links: Dashboard (/admin), Leads (/admin/leads), Pipeline (/admin/pipeline), Today (/admin/today); the current page is highlighted; - a page header with the page title, and a sign-out button that uses the existing sign-out from lesson 4.6; - on narrow screens the sidebar becomes a menu button; - Pipeline, Today and Dashboard are placeholder pages for now. Follow docs/design.md for colours and type, but keep the admin plain and dense: it is a work tool, not a marketing page. Lead list at /admin/leads: - a table with columns: name, email, phone, status, created date. Status is a coloured badge with the status written as text, never colour alone; - each row links to /admin/leads/<id> (a placeholder page for now); - search box: matches part of the name, email or phone, ignoring case; - filter by status (any one of the five, or all) and by created date (from and to), in the business time zone from the spec; - sorting by created date (newest first by default) and by name; - pagination, 25 per page, with the total count of matching leads shown; - search, filters, sort and page are kept in the page address, so a reload or a shared link shows the same view; - empty states: one message when there are no leads at all, a different one when the filters match nothing, with a "clear filters" button; - a loading state while data is fetched. Constraints: all data is read on the server for the signed-in owner only, consistent with the protection from 4.6 and 4.7; nothing under /admin may work when signed out. No new libraries unless you explain why first. Before you report, verify in a real browser using the browser connection. Open /admin/leads; when the login page appears, wait — I will sign in myself in that window; never ask me for the password. Then check and report on each: the 40 sample leads show a total of 40; searching for one sample name finds that lead; filtering by status "won" shows 5; a date range of the last 7 days shows only leads from those days; page 2 works; a search for "zzzz" shows the no-results state; the layout at phone width; signing out and opening /admin/leads redirects to the login. Also run the build. If you cannot verify something, say so plainly instead of assuming it works.
Do along
- Pause after Part 2. Run the seed prompt from Part 2. In the first lines, nothing needs changing: Claude takes the business from your own
docs/brief.md. Check the table view afterwards. - Pause at the prompt in Part 4. Run the list prompt. Sign in yourself when the browser shows the login page.
- After Part 5, adapt the columns to your business: remove a column you will not use, or ask for one you will (for example, the first words of the message).
- Pick three sample leads and find each one a different way: by part of the name, by email, by status plus date range.
- Do the "Check your work" steps, then run the commit and tag commands that end the lesson.
Check your work
- Open
/admin/leadssigned in. Expected: a table of leads, total count 40 plus any earlier test leads, newest first. - Choose a sample lead's name from the Supabase table view. Type part of it in the search box. Expected: that lead appears within a few seconds, without scrolling.
- Set the status filter to "won". Expected: 5 rows, each with a "won" badge.
- Set a date range covering the last 7 days. Expected: every row's created date is inside that range.
- Go to page 2, then reload the browser. Expected: still page 2, same filters.
- Search for "zzzz". Expected: a "no leads match" message and a button to clear filters.
- Sign out, then open
/admin/leadsdirectly. Expected: you land on the login page.
Common problems
- You received dozens of emails or Telegram messages. → The seed went through the form endpoint. → Tell Claude: "The seed must insert directly into the database, not call /api/leads. Fix it, and remove the duplicates it created."
- The list is empty although the table has rows. → The page is reading without the owner's session, so Row Level Security returns nothing. → "The list shows no rows but the table has 40. Check that the query runs on the server with the signed-in owner's session, as in 4.6 and 4.7."
- Counts are off by a few. → Your earlier test leads from section 4 are included. → That is correct behaviour; subtract them or filter by date.
- Leads near midnight appear on the wrong day. → Dates are shown in a different time zone from the one in the spec. → "Use the business time zone from docs/crm-spec.md for every displayed date and for the date filter."
- Filters reset on reload. → State is kept in the page, not in the address. → "Keep search, filters, sort and page in the URL."
- Claude asks for your password. → Refuse. → "Never ask for the password. Open the login page and wait; I will sign in in the browser."
Homework
About 20 minutes, on your own, after the lesson. No later lesson depends on it.
- Morning views. Decide the two or three filtered views you would open every morning, for example all new leads, or contacted leads from the last 14 days. Set each one in the list and bookmark it in your browser. Deliverable: the bookmarks. Done when: after closing and reopening the browser, each bookmark opens the same filtered list.
- The list on your phone. Open the list on your phone through your local network or on your deployed site, and check that a row is readable and tappable. If something is hard to use, tell Claude exactly what and have it fixed. Deliverable: a list that works on your phone. Done when: on the phone you find one sample lead by name and open its row with one tap.
- Your own words. Rewrite the two empty-state messages in the words you would use with a colleague, and ask Claude to change that text only. Leave the status names as they are. Deliverable: the new wording on screen. Done when: a search for "zzzz" shows your message and the "clear filters" button still works.
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.2: admin layout, lead list with search and filters, sample data"
git tag lesson-5.2
git push
git push --tags