371 lines
21 KiB
Markdown
371 lines
21 KiB
Markdown
# Demo Data Foundation Implementation Plan
|
||
|
||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||
|
||
**Goal:** Make the mock data internally coherent — one canonical identity scheme, reconciling financials, and no empty/broken views — as the foundation for the larger demo build.
|
||
|
||
**Architecture:** All edits are to `src/data/mockStore.jsx` (a ~6,950-line mock store) plus a few consuming components. Changes are surgical and additive. A new `resolvePerson(id)` selector gives every module one consistent way to look up people. Verification is by `npm run build` + `grep` reconciliation + dev-run, since the project has no unit-test harness.
|
||
|
||
**Tech Stack:** React 18, Vite 7, mock React-context store (`useMockStore`), pnpm.
|
||
|
||
**Spec:** `docs/superpowers/specs/2026-05-29-demo-data-coherence-design.md` (Phases 1–3).
|
||
|
||
**Scope of this plan:** Phase 1 (canonical identity), Phase 2 (financial coherence), Phase 3 (feature-breaking fixes). Phases 4–10 are separate plans.
|
||
|
||
---
|
||
|
||
## Canonical roster (single source of truth — used throughout)
|
||
|
||
Canonical id scheme = `MOCK_USERS`. Real Texan names. Unified `LUP-####` empIds. Shared password `password`.
|
||
|
||
| id | Role | Name | empId | Login type | Login id | Old id(s) | Old name |
|
||
|----|------|------|-------|-----------|----------|-----------|----------|
|
||
| own_001 | OWNER | Justin Johnson | LUP-1001 | owner | justin | `owner_001` | — (email → `justin@lynkeduppro.com`) |
|
||
| own_002 | OWNER | Diana Reeves | LUP-1002 | owner | diana | `owner_002` | "Maria Garcia" |
|
||
| a1 | ADMIN | Wade Hollis | LUP-1010 | employee | LUP-1010 | `ADM01` | "Adam Admin" / "Admin One" |
|
||
| a2 | ADMIN | Darlene Brooks | LUP-1011 | employee | LUP-1011 | `ADM02` | "Amanda Manager" / "Admin Two" |
|
||
| a3 | ADMIN | Roy Schaefer | LUP-1012 | employee | LUP-1012 | `ADM03` | "Arthur Director" / "Admin Three" |
|
||
| p1 | SALES_REP | Jesus Gonzales | LUP-1030 | employee | LUP-1030 | — | — (keep) |
|
||
| p2 | SALES_REP | Sarah Calloway | LUP-1031 | employee | LUP-1031 | — | "Sarah Sales" |
|
||
| e1 | FIELD_AGENT | Cody Tatum | LUP-1040 | employee | LUP-1040 | `FA001` | "Frank Agent" |
|
||
| e2 | FIELD_AGENT | Hannah Reyes | LUP-1041 | employee | LUP-1041 | `FA002` | "Fiona Field" |
|
||
| e3 | FIELD_AGENT | Travis Boone | LUP-1042 | employee | LUP-1042 | `FA003` | "Fred Flyer" |
|
||
| e4 | FIELD_AGENT | Shelby Greer | LUP-1043 | employee | LUP-1043 | `FA004` | "Felicity Fast" |
|
||
| e5 | FIELD_AGENT | Dalton Pruitt | LUP-1044 | employee | LUP-1044 | `FA005` | "Felix Fixer" |
|
||
| con_001 | CONTRACTOR | Mike Brennan | LUP-3001 | contractor | mike | — | "Mike Contractor" |
|
||
| sub_001 | SUBCONTRACTOR | Carlos Mendoza | LUP-2001 | subcontractor | carlos | — | "Carlos Subcontractor" |
|
||
| sub_002 | SUBCONTRACTOR | Maya Patel | LUP-2002 | subcontractor | maya | — | (keep) |
|
||
| sub_003 | SUBCONTRACTOR | Dwayne Boudreaux | LUP-2003 | subcontractor | dwayne | — | (current sub_003 name) |
|
||
| sub_004 | SUBCONTRACTOR | Jennifer Castillo | LUP-2004 | subcontractor | jennifer | — | (current sub_004 name) |
|
||
| sub_005 | SUBCONTRACTOR | Greg Alston | LUP-2005 | subcontractor | greg | — | (keep) |
|
||
|
||
Org role taxonomy (`orgMembers[].roleKey`) stays; only the `userId` it points to changes. Email rule: use `@lynkeduppro.com` consistently.
|
||
|
||
**Execution order** (overrides plain numeric order; see execution protocol): 1 → 2 → **R (roster rename, below)** → 3 → 4 → 5 → 6 → 7 → 8 → 9 → **L (login picker, below)**.
|
||
|
||
---
|
||
|
||
## File structure
|
||
|
||
- **Modify:** `src/data/mockStore.jsx` — identity remap, `resolvePerson`, financial fixes, breakdowns, `leads` seed, sub logins, task↔project fixes, kanban lead values, `DEMO_TODAY`.
|
||
- **Modify:** `src/pages/owner/SubcontractorTasksPage.jsx`, `src/components/subcontractor/TaskViewModal.jsx` — add `On Hold` styling.
|
||
- **Create:** none in this plan.
|
||
|
||
---
|
||
|
||
## Task 1: Add `DEMO_TODAY` constant
|
||
|
||
**Files:**
|
||
- Modify: `src/data/mockStore.jsx` (near top, after imports)
|
||
- Modify: `src/components/kanban/KanbanCard.jsx:14` (replace hardcoded date)
|
||
|
||
- [ ] **Step 1: Add the constant** near the top of `mockStore.jsx` (after the import lines):
|
||
|
||
```jsx
|
||
// Fixed "today" for the demo so seeded dates never go stale or land in the future.
|
||
export const DEMO_TODAY = new Date('2026-05-29T12:00:00');
|
||
```
|
||
|
||
- [ ] **Step 2: Use it in KanbanCard.** In `src/components/kanban/KanbanCard.jsx` replace the hardcoded `new Date('2026-04-07')` (line ~14) with an import + use:
|
||
|
||
```jsx
|
||
import { DEMO_TODAY } from '../../data/mockStore';
|
||
// ...
|
||
const NOW = DEMO_TODAY; // was: new Date('2026-04-07')
|
||
```
|
||
|
||
- [ ] **Step 3: Verify build.** Run: `npm run build` — Expected: `✓ built` with no errors.
|
||
- [ ] **Step 4: Commit.**
|
||
|
||
```bash
|
||
git add src/data/mockStore.jsx src/components/kanban/KanbanCard.jsx
|
||
git commit -m "chore(data): add DEMO_TODAY anchor and use it for kanban day-counter"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 2: Add `resolvePerson` selector
|
||
|
||
**Files:**
|
||
- Modify: `src/data/mockStore.jsx` — add a memoized people index + `resolvePerson` exposed on the store context value.
|
||
|
||
- [ ] **Step 1: Build a merged people index** inside the provider (after the people collections are defined, before the `value={{...}}`):
|
||
|
||
```jsx
|
||
// One lookup for any person across users/personnel/owners/subcontractors.
|
||
const peopleIndex = useMemo(() => {
|
||
const idx = {};
|
||
const add = (p) => { if (p?.id && !idx[p.id]) idx[p.id] = p; };
|
||
[...(users || []), ...(personnel || []), ...(owners || []),
|
||
...(subcontractors || [])].forEach(add);
|
||
return idx;
|
||
}, [users, personnel, owners, subcontractors]);
|
||
|
||
const resolvePerson = (id) => {
|
||
const p = peopleIndex[id];
|
||
if (!p) return { id, name: 'Unknown', email: '', role: '' };
|
||
return { id: p.id, name: p.name || p.fullName || 'Unknown', email: p.email || p.emailAddress || '', role: p.role || '' };
|
||
};
|
||
```
|
||
|
||
- [ ] **Step 2: Expose it** on the context value object (add `resolvePerson,` to the `value={{ ... }}`).
|
||
- [ ] **Step 3: Verify build.** Run: `npm run build` — Expected: `✓ built`.
|
||
- [ ] **Step 4: Commit.**
|
||
|
||
```bash
|
||
git add src/data/mockStore.jsx
|
||
git commit -m "feat(data): add resolvePerson selector over a merged people index"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 3: Remap `orgMembers` to canonical ids + fix names
|
||
|
||
**Files:**
|
||
- Modify: `src/data/mockStore.jsx` — the `orgMembers` useState array.
|
||
|
||
- [ ] **Step 1: Apply the ID + name remap** in `orgMembers` using the Canonical ID reference table:
|
||
- `userId: 'owner_001'` → `'own_001'` (name "Justin Johnson", email `justin@lynkeduppro.com`)
|
||
- `userId: 'owner_002'` → `'own_002'`, **name "Maria Garcia" → "Diana Reeves"**, email → Diana's canonical email from `MOCK_USERS`
|
||
- `userId: 'ADM01'/'ADM02'/'ADM03'` → `'a1'/'a2'/'a3'`, **names "Admin One/Two/Three" → "Adam Admin"/"Amanda Manager"/"Arthur Director"**
|
||
- `userId: 'FA001'..'FA005'` → `'e1'..'e5'` (names already match)
|
||
- [ ] **Step 2: Verify no stale ids remain.** Run:
|
||
|
||
```bash
|
||
git grep -nE "owner_00[12]|ADM0[123]|FA00[12345]" -- src/data/mockStore.jsx
|
||
```
|
||
|
||
Expected: **no matches in `orgMembers`** (matches may still exist in subcontractor tasks — fixed in Task 4). Confirm none are in the `orgMembers` block.
|
||
|
||
- [ ] **Step 3: Verify build.** Run: `npm run build` — Expected: `✓ built`.
|
||
- [ ] **Step 4: Commit.**
|
||
|
||
```bash
|
||
git add src/data/mockStore.jsx
|
||
git commit -m "fix(data): remap orgMembers to canonical ids; reconcile Owner #2 + admin names"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 4: Remap subcontractor-task person references
|
||
|
||
**Files:**
|
||
- Modify: `src/data/mockStore.jsx` — `MOCK_SUBCONTRACTOR_TASKS` (and `MOCK_NOTIFICATIONS` actor ids).
|
||
|
||
- [ ] **Step 1: Replace ids** in every task's `assignedBy`, `actorId`, `senderId`, and status/thread rows:
|
||
- `'owner_001'` → `'own_001'`
|
||
- `'ADM01'` → `'a1'`
|
||
- Update the denormalized `assignedByName`/`actorName`/`senderName` so "Admin One" → "Adam Admin" and any owner name → "Justin Johnson".
|
||
- [ ] **Step 2: Verify no stale ids remain anywhere.** Run:
|
||
|
||
```bash
|
||
git grep -nE "owner_00[12]|\bADM0[123]\b|FA00[12345]" -- src/data/mockStore.jsx
|
||
```
|
||
|
||
Expected: **no matches** (all remapped).
|
||
|
||
- [ ] **Step 3: Verify build.** Run: `npm run build` — Expected: `✓ built`.
|
||
- [ ] **Step 4: Commit.**
|
||
|
||
```bash
|
||
git add src/data/mockStore.jsx
|
||
git commit -m "fix(data): remap subcontractor task/notification actor ids to canonical scheme"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 5: Financial coherence — fix the flagged projects
|
||
|
||
**Files:**
|
||
- Modify: `src/data/mockStore.jsx` — the `projects` array.
|
||
|
||
Reference (from audit): rules = breakdown `allocated`→budget, `committed`→committedCost, `actual`→actualCost; `committed ≥ actual`; `variancePercent = (actualCost − budget)/budget × 100`.
|
||
|
||
- [ ] **Step 1: proj_005** — set top-level `committedCost: 28850` (matches the breakdown's committed sum). Leave actualCost 14200 (breakdown actual sum). Recompute `variancePercent = (14200−28000)/28000×100 = -49.3`.
|
||
- [ ] **Step 2: proj_008** — reduce paid invoices so the paid total ≤ `actualCost` (44500). Adjust the invoice `amount`s / `status` so `Σ paid ≤ 44500` and `Σ paid ≤ committedCost (52000)`.
|
||
- [ ] **Step 3: proj_002 & proj_010** (completed) — reduce paid invoices so `Σ paid ≤ actualCost` (6200 and 23800 respectively).
|
||
- [ ] **Step 4: proj_004** — in `budgetBreakdown`, fix the Contingency line so `committed ≥ actual` (raise committed to ≥ 11500, keeping the over-budget total intact).
|
||
- [ ] **Step 5: Add `budgetBreakdown`** to proj_006, 008, 009, 010, 011, 012. Each: 4–7 line items where `allocated` sums to the project `budget`, `committed` sums to `committedCost`, `actual` sums to `actualCost`, and `committed ≥ actual` per line. Use realistic vendor/category names matching the project type (e.g. for a roof job: "ABC Supply Co. — Materials", "Texas Roofing Crew A — Labor", "City of Plano — Permits").
|
||
- [ ] **Step 6: Verify variance signs** render correctly — over-budget shows `+`, under shows `−`. (Display logic already does this; just confirm the stored `variancePercent` sign matches `(actualCost−budget)`.)
|
||
- [ ] **Step 7: Verify build.** Run: `npm run build` — Expected: `✓ built`.
|
||
- [ ] **Step 8: Reconciliation spot-check.** For each project with a `budgetBreakdown`, confirm the three column sums equal `committedCost`/`actualCost` and `allocated`→`budget`. (Manual read or a scratch node script; do not commit the script.)
|
||
- [ ] **Step 9: Commit.**
|
||
|
||
```bash
|
||
git add src/data/mockStore.jsx
|
||
git commit -m "fix(data): reconcile project financials and add missing budget breakdowns"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 6: Seed the Leads List page
|
||
|
||
**Files:**
|
||
- Modify: `src/data/mockStore.jsx` — the `leads` useState (currently `useState([])`).
|
||
|
||
- [ ] **Step 1: Inspect the shape** the page reads. Open `src/pages/LeadsListPage.jsx` and note the fields used (`firstName`/`lastName`, `phones[]`, `urgency`, `status`, `leadSource`, `canvasserName`, `createdByName`, `createdAt`, `stormSource`, `address`, etc.).
|
||
- [ ] **Step 2: Seed ~28–35 records** by initializing `leads` from the existing storm-attribution leads (`MOCK_STORM_ATTRIBUTION_LEADS`), mapped into the LeadsListPage shape. Use canonical `canvasserName`/`createdByName` (Frank Agent, Fiona Field, … — names that exist in `MOCK_USERS`). Spread `createdAt` across recent dates relative to `DEMO_TODAY`; set `stormSource: true` on storm-sourced ones; vary `urgency`/`status`.
|
||
|
||
```jsx
|
||
const [leads, setLeads] = useState(() => seedLeadsFromAttribution());
|
||
```
|
||
|
||
(Define `seedLeadsFromAttribution()` above the provider; map each SAL-* record to the page shape.)
|
||
|
||
- [ ] **Step 3: Verify in dev.** Run dev server, open `/emp/fa/leads` (or owner equivalent). Expected: the list is populated (no "No Leads Yet" empty state).
|
||
- [ ] **Step 4: Verify build.** Run: `npm run build` — Expected: `✓ built`.
|
||
- [ ] **Step 5: Commit.**
|
||
|
||
```bash
|
||
git add src/data/mockStore.jsx
|
||
git commit -m "fix(data): seed leads list so the Leads page is populated on load"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 7: Add subcontractor logins (sub_002–005)
|
||
|
||
**Files:**
|
||
- Modify: `src/data/mockStore.jsx` — `MOCK_USERS`.
|
||
|
||
- [ ] **Step 1: Add four login user records** to `MOCK_USERS` for `sub_002`–`sub_005`, mirroring the `sub_001` (Carlos Mendoza) record shape (`id`, `name`, `email`, `empId`, `password: 'password'`, `role: 'SUBCONTRACTOR'`, type `subcontractor`). Use the **canonical roster** names + empIds (Maya Patel/LUP-2002, Dwayne Boudreaux/LUP-2003, Jennifer Castillo/LUP-2004, Greg Alston/LUP-2005) and usernames (maya/dwayne/jennifer/greg) so ids/names match across collections and the login picker works.
|
||
- [ ] **Step 2: Verify in dev.** Log in as `sub_002`'s email / `password`. Expected: the subcontractor dashboard loads and shows that sub's tasks/notifications (Maya's rich set is now reachable).
|
||
- [ ] **Step 3: Verify build.** Run: `npm run build` — Expected: `✓ built`.
|
||
- [ ] **Step 4: Commit.**
|
||
|
||
```bash
|
||
git add src/data/mockStore.jsx
|
||
git commit -m "feat(data): add login records for sub_002-005 so each subcontractor inbox is reachable"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 8: Fix task↔project associations + On Hold styling
|
||
|
||
**Files:**
|
||
- Modify: `src/data/mockStore.jsx` — `MOCK_SUBCONTRACTOR_TASKS` (projectId/location).
|
||
- Modify: `src/pages/owner/SubcontractorTasksPage.jsx` — `STATUS_CONFIG`.
|
||
- Modify: `src/components/subcontractor/TaskViewModal.jsx` — `STATUS_STYLES`.
|
||
|
||
- [ ] **Step 1: Re-point tasks** so each task's `projectId` references a project whose `address` matches the task `location` (residential roofing/electrical tasks → residential projects, not the commercial `proj_011`/`proj_012`). Fix the 6 mismatches the audit flagged (sct_004, _005, _006, _007, _008, _010).
|
||
- [ ] **Step 2: Add `On Hold`** to `STATUS_CONFIG` in `SubcontractorTasksPage.jsx` (give it an icon + amber/grey styling, consistent with siblings) and to `STATUS_STYLES` in `TaskViewModal.jsx`.
|
||
- [ ] **Step 3: Verify in dev.** Open `/owner/subcontractor-tasks`: On-Hold tasks (sct_005, sct_009) show distinct On-Hold styling (not "Assigned"); the project column shows a sensible, matching project.
|
||
- [ ] **Step 4: Verify build.** Run: `npm run build` — Expected: `✓ built`.
|
||
- [ ] **Step 5: Commit.**
|
||
|
||
```bash
|
||
git add src/data/mockStore.jsx src/pages/owner/SubcontractorTasksPage.jsx src/components/subcontractor/TaskViewModal.jsx
|
||
git commit -m "fix(data): match subcontractor tasks to real projects; style On Hold status"
|
||
```
|
||
|
||
---
|
||
|
||
## Task 9: Add structured `value` to kanban leads + fix Complete-stage data
|
||
|
||
**Files:**
|
||
- Modify: `src/data/mockStore.jsx` — `KANBAN_LEADS_INITIAL` and `KANBAN_PROJECT_DATA`.
|
||
|
||
- [ ] **Step 1: Add a numeric `value`** (estimate $) to **every** `kl_*` lead. For signed+ leads reuse the existing `estimatedAmount` from `KANBAN_PROJECT_DATA`; for earlier-stage leads assign realistic varied amounts ($6k–$42k).
|
||
- [ ] **Step 2: Fix Complete-stage leads** (kl_034–038): set their project `completionPct: 100` and a real `actualCost` (≈ their estimate), since they're in the Complete column.
|
||
- [ ] **Step 3: Populate `stormSource: true`** on storm-canvassed kanban leads (those whose notes mention storm/hail).
|
||
- [ ] **Step 4: Verify in dev.** Open the Kanban board: cards render; storm badges appear on storm leads; Complete column leads show 100%.
|
||
- [ ] **Step 5: Verify build.** Run: `npm run build` — Expected: `✓ built`.
|
||
- [ ] **Step 6: Commit.**
|
||
|
||
```bash
|
||
git add src/data/mockStore.jsx
|
||
git commit -m "feat(data): add lead values, fix Complete-stage data, populate stormSource on kanban leads"
|
||
```
|
||
|
||
---
|
||
|
||
## Task R: Canonical roster rename (real Texan names + LUP empIds)
|
||
|
||
**Runs after Task 2, before Task 3.** **Files:** `src/data/mockStore.jsx` (people source records) + repo-wide name-string replacement.
|
||
|
||
- [ ] **Step 1: Set names + empIds on source records.** In `MOCK_USERS`, `MOCK_PERSONNEL`/`personnel`, `MOCK_OWNERS`, and `MOCK_SUBCONTRACTORS`, for each person in the Canonical Roster set the `name` to the roster name and set `empId` to the roster `LUP-####`. Reconcile Justin's email to `justin@lynkeduppro.com`. Keep password `password`.
|
||
- [ ] **Step 2: Repo-wide name replace.** Replace every occurrence of each old name string with its new name across the whole repo (covers denormalized copies in teamMembers, subcontractor tasks, kanban activity, `DISPATCH_REPS`, and any component). Pairs:
|
||
- "Frank Agent"→"Cody Tatum", "Fiona Field"→"Hannah Reyes", "Fred Flyer"→"Travis Boone", "Felicity Fast"→"Shelby Greer", "Felix Fixer"→"Dalton Pruitt"
|
||
- "Adam Admin"→"Wade Hollis", "Amanda Manager"→"Darlene Brooks", "Arthur Director"→"Roy Schaefer"
|
||
- "Admin One"→"Wade Hollis", "Admin Two"→"Darlene Brooks", "Admin Three"→"Roy Schaefer"
|
||
- "Maria Garcia"→"Diana Reeves", "Sarah Sales"→"Sarah Calloway"
|
||
- "Carlos Subcontractor"→"Carlos Mendoza", "Mike Contractor"→"Mike Brennan"
|
||
- sub_003 current name → "Dwayne Boudreaux", sub_004 current name → "Jennifer Castillo" (look up the current strings first via `git grep`).
|
||
- [ ] **Step 3: Verify old names gone.** Run:
|
||
|
||
```bash
|
||
git grep -nE "Frank Agent|Fiona Field|Fred Flyer|Felicity Fast|Felix Fixer|Adam Admin|Amanda Manager|Arthur Director|Admin (One|Two|Three)|Maria Garcia|Sarah Sales|Carlos Subcontractor|Mike Contractor" -- src
|
||
```
|
||
|
||
Expected: **no matches**.
|
||
|
||
- [ ] **Step 4: Verify build.** Run: `npm run build` — Expected: `✓ built`.
|
||
- [ ] **Step 5: Commit.**
|
||
|
||
```bash
|
||
git add -A
|
||
git commit -m "feat(data): canonical roster — real Texan names + unified LUP-#### employee ids"
|
||
```
|
||
|
||
---
|
||
|
||
## Task L: Login per-role person picker
|
||
|
||
**Runs last.** **Files:** `src/pages/Login.jsx`; `src/context/AuthContext.jsx` (only if id matching needs updating).
|
||
|
||
- [ ] **Step 1: Inline demo-account list** in `Login.jsx` (keeps this task's lane to Login.jsx). Define from the roster:
|
||
|
||
```jsx
|
||
const DEMO_ACCOUNTS = {
|
||
customer: [{ name: 'Alice Carter', loginType: 'customer', id: 'alice', pw: 'password' }],
|
||
employee: [
|
||
{ name: 'Wade Hollis (Admin)', loginType: 'employee', id: 'LUP-1010', pw: 'password' },
|
||
{ name: 'Darlene Brooks (Admin)',loginType: 'employee', id: 'LUP-1011', pw: 'password' },
|
||
{ name: 'Roy Schaefer (Admin)', loginType: 'employee', id: 'LUP-1012', pw: 'password' },
|
||
{ name: 'Cody Tatum (Agent)', loginType: 'employee', id: 'LUP-1040', pw: 'password' },
|
||
{ name: 'Hannah Reyes (Agent)', loginType: 'employee', id: 'LUP-1041', pw: 'password' },
|
||
{ name: 'Travis Boone (Agent)', loginType: 'employee', id: 'LUP-1042', pw: 'password' },
|
||
{ name: 'Shelby Greer (Agent)', loginType: 'employee', id: 'LUP-1043', pw: 'password' },
|
||
{ name: 'Dalton Pruitt (Agent)', loginType: 'employee', id: 'LUP-1044', pw: 'password' },
|
||
],
|
||
owner: [
|
||
{ name: 'Justin Johnson', loginType: 'owner', id: 'justin', pw: 'password' },
|
||
{ name: 'Diana Reeves', loginType: 'owner', id: 'diana', pw: 'password' },
|
||
],
|
||
contractor: [{ name: 'Mike Brennan', loginType: 'contractor', id: 'mike', pw: 'password' }],
|
||
subcontractor: [
|
||
{ name: 'Carlos Mendoza', loginType: 'subcontractor', id: 'carlos', pw: 'password' },
|
||
{ name: 'Maya Patel', loginType: 'subcontractor', id: 'maya', pw: 'password' },
|
||
{ name: 'Dwayne Boudreaux', loginType: 'subcontractor', id: 'dwayne', pw: 'password' },
|
||
{ name: 'Jennifer Castillo',loginType: 'subcontractor', id: 'jennifer', pw: 'password' },
|
||
{ name: 'Greg Alston', loginType: 'subcontractor', id: 'greg', pw: 'password' },
|
||
],
|
||
};
|
||
```
|
||
|
||
- [ ] **Step 2: Replace the quick-access row** so each role chip, when clicked, expands the list of people for that role; clicking a person calls a `pickDemo(acct)` that sets `loginType`, `identifier`, `password` (and may submit). Single-person roles act as one-click.
|
||
- [ ] **Step 3: Ensure AuthContext accepts the ids.** Confirm `login(identifier, password, loginType)` matches employees by `empId` (`LUP-####`) and owner/contractor/sub by username. If `MOCK_USERS` records carry the LUP `empId` (set in Task R / Task 7), update the match in `AuthContext.jsx` only if needed.
|
||
- [ ] **Step 4: Verify in dev.** Log in via the picker as an Admin (LUP-1010), an Agent (LUP-1041), the second Owner (Diana), and a Subcontractor (Maya). Each lands on the right dashboard.
|
||
- [ ] **Step 5: Verify build.** Run: `npm run build` — Expected: `✓ built`.
|
||
- [ ] **Step 6: Commit.**
|
||
|
||
```bash
|
||
git add src/pages/Login.jsx src/context/AuthContext.jsx
|
||
git commit -m "feat(login): per-role person picker for quick demo access"
|
||
```
|
||
|
||
---
|
||
|
||
## Self-review checklist (run after all tasks)
|
||
|
||
- [ ] `git grep -nE "owner_00[12]|\bADM0[123]\b|FA00[12345]"` returns **no matches** in `src/data/mockStore.jsx`.
|
||
- [ ] All old placeholder names gone (the Task R Step 3 grep → no matches); roster names appear in projects/tables/schedule/dispatch/leaderboard.
|
||
- [ ] `own_002` is "Diana Reeves" everywhere (`git grep -n "Maria Garcia"` → no matches).
|
||
- [ ] Login picker: signing in as an Admin (LUP-1010), Agent (LUP-1041), Owner #2 (Diana), and a Sub (Maya) each lands on the correct dashboard.
|
||
- [ ] Every project with a `budgetBreakdown` reconciles (column sums == totals).
|
||
- [ ] `npm run build` is clean.
|
||
- [ ] Dev run: Leads page non-empty; each `sub_00N` login sees its own tasks; On-Hold styled; no "Unknown" person labels on subcontractor tasks.
|
||
|
||
## Spec coverage note
|
||
This plan covers spec Phases 1–3. Phases 4–6 (threaded scenarios, pipeline breadth, computed analytics) and 7–10 (lifecycle/inspections, sub-task stage machine, profiles) are separate plans authored after this one lands.
|