docs: add Texan roster (real names + LUP employee ids), login person picker, optional profile identity fields; update plan + protocol order

This commit is contained in:
Satyam Rastogi
2026-05-29 02:53:51 +05:30
parent eb0f600ee0
commit 670b33c69b
3 changed files with 140 additions and 24 deletions
@@ -14,25 +14,34 @@
---
## Canonical ID reference (used throughout)
## Canonical roster (single source of truth — used throughout)
The canonical scheme is the `MOCK_USERS` one. Remap everything else to it:
Canonical id scheme = `MOCK_USERS`. Real Texan names. Unified `LUP-####` empIds. Shared password `password`.
| Entity | Canonical id | Name | Old ids to replace |
|--------|-------------|------|--------------------|
| Owner 1 | `own_001` | Justin Johnson | `owner_001` |
| Owner 2 | `own_002` | Diana Reeves | `owner_002`, and name "Maria Garcia" |
| Admin 1 | `a1` | Adam Admin | `ADM01`, name "Admin One" |
| Admin 2 | `a2` | Amanda Manager | `ADM02`, name "Admin Two" |
| Admin 3 | `a3` | Arthur Director | `ADM03`, name "Admin Three" |
| Field agent 1 | `e1` | Frank Agent | `FA001` |
| Field agent 2 | `e2` | Fiona Field | `FA002` |
| Field agent 3 | `e3` | Fred Flyer | `FA003` |
| Field agent 4 | `e4` | Felicity Fast | `FA004` |
| Field agent 5 | `e5` | Felix Fixer | `FA005` |
| Justin email | — | `justin@lynkeduppro.com` | `justin@johnsondev.com` (reconcile to one — use lynkeduppro.com everywhere) |
| 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`: OWNER/ADMIN/SALES_REP/CANVASSER/SUBCONTRACTOR) stays as-is; only the `userId` it points to changes.
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)**.
---
@@ -219,7 +228,7 @@ git commit -m "fix(data): seed leads list so the Leads page is populated on load
**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) record shape (`id`, `name`, `email`, `password: 'password'`, `role: 'SUBCONTRACTOR'`, type `subcontractor`). Use the names already in `MOCK_SUBCONTRACTORS` (Maya Patel, Dwayne …, Jennifer …, Greg Alston) so ids and names match across collections.
- [ ] **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.**
@@ -270,10 +279,89 @@ git commit -m "feat(data): add lead values, fix Complete-stage data, populate st
---
## 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.
@@ -47,6 +47,7 @@ Execution order is the task number. Each task's editable surface:
|---|------|---------------|--------------------|
| 1 | DEMO_TODAY anchor | `mockStore.jsx` (top-of-file constant) + `KanbanCard.jsx:~14` | — |
| 2 | `resolvePerson` selector | `mockStore.jsx` (provider body: people index + context `value` object) | — |
| **R** | **Canonical roster rename** (real Texan names + LUP empIds) | `mockStore.jsx` people source records (`MOCK_USERS`/personnel/owners/subcontractors) **+ repo-wide replacement of the old name strings** | ⚠ cross-cutting (touches many regions/files) — runs **after Task 2, before Task 3**, alone, then commits |
| 3 | Remap `orgMembers` | `mockStore.jsx` → the `orgMembers` useState array only | — |
| 4 | Remap sub-task actor ids | `mockStore.jsx``MOCK_SUBCONTRACTOR_TASKS` + `MOCK_NOTIFICATIONS` (actor/sender id + denormalized name fields only) | ⚠ shares `MOCK_SUBCONTRACTOR_TASKS` with Task 8 — must run before Task 8 |
| 5 | Financial reconciliation + breakdowns | `mockStore.jsx` → the `projects` array only | — |
@@ -54,10 +55,13 @@ Execution order is the task number. Each task's editable surface:
| 7 | Sub logins | `mockStore.jsx``MOCK_USERS` only | — |
| 8 | Task↔project + On Hold | `mockStore.jsx``MOCK_SUBCONTRACTOR_TASKS` (`projectId`/`location` only) + `SubcontractorTasksPage.jsx` + `TaskViewModal.jsx` | ⚠ shares array with Task 4 — runs after Task 4 |
| 9 | Kanban values + Complete fixes | `mockStore.jsx``KANBAN_LEADS_INITIAL` + `KANBAN_PROJECT_DATA` only | — |
| **L** | **Login per-role person picker** | `src/pages/Login.jsx` + `src/context/AuthContext.jsx` only | runs **last** |
**Canonical execution order:** 1 → 2 → **R** → 3 → 4 → 5 → 6 → 7 → 8 → 9 → **L**. (Task R establishes names before the id-remaps; Task L wires the picker after all people exist.)
**Lane rule:** if an implementer believes it must touch a surface outside its lane, it STOPS and reports `NEEDS_CONTEXT` to the controller — it does not edit out of lane.
**Invariant every task must preserve:** the canonical ID scheme from the plan (`own_001/own_002`, `e1e5`, `a1a3`, `con_001`, `sub_001005`). No task may reintroduce `owner_001`/`FA0*`/`ADM0*` ids or the names "Maria Garcia"/"Admin One/Two/Three".
**Invariant every task must preserve:** the canonical ID scheme (`own_001/own_002`, `e1e5`, `a1a3`, `con_001`, `sub_001005`) **and the canonical roster names/empIds** (see the plan's roster table — Wade Hollis, Cody Tatum, Carlos Mendoza, etc., with `LUP-####` empIds). After Task R, no task may reintroduce old ids (`owner_001`/`FA0*`/`ADM0*`) **or** old placeholder names ("Frank Agent", "Adam Admin", "Admin One/Two/Three", "Maria Garcia", "Sarah Sales", "Carlos Subcontractor", "Mike Contractor", etc.).
---
@@ -72,7 +76,7 @@ Execution order is the task number. Each task's editable surface:
7. **Code-quality review** (fresh read-only subagent) — only after spec ✅: review the diff for correctness/quality. Issues → implementer fixes → re-review until ✅.
8. **Mark task complete** in TodoWrite. Go to next task.
**Continuous execution:** the controller runs tasks 1→9 back-to-back without pausing to ask the human "should I continue?". Stop only on an unresolvable BLOCKED, genuine ambiguity, or all-tasks-complete.
**Continuous execution:** the controller runs the canonical order (1 → 2 → R → 3 → 4 → 5 → 6 → 7 → 8 → 9 → L) back-to-back without pausing to ask the human "should I continue?". Stop only on an unresolvable BLOCKED, genuine ambiguity, or all-tasks-complete.
---
@@ -100,9 +104,9 @@ Final gate after Task 9: run the plan's **self-review checklist**, then a whole-
- [ ] Only one implementer in flight at any time.
- [ ] Tree clean before each dispatch.
- [ ] Each task committed before the next starts.
- [ ] Task 4 ran before Task 8 (shared array).
- [ ] Task 4 ran before Task 8 (shared array); Task R ran after Task 2 and before Task 3.
- [ ] No agent edited outside its §3 lane.
- [ ] Canonical-ID invariant intact after every task.
- [ ] Canonical-ID **and roster-name** invariant intact after every task (no old ids/names reintroduced).
- [ ] Build green after every task.
---
@@ -14,8 +14,32 @@
**Problem (audit):** the same people exist under three incompatible ID schemes; cross-module lookups silently fail; Owner #2 has two names; admins have placeholder names; subcontractor tasks reference non-existent ids (`owner_001`, `ADM01`).
**Decision:** unify on the `MOCK_USERS` scheme (auth + `projects` already use it):
- Owners `own_001` (Justin Johnson), `own_002` (Diana Reeves); Admins `a1` (Adam Admin), `a2` (Amanda Manager), `a3` (Arthur Director); Field agents `e1``e5`; Sales/personnel `p1` (Jesus Gonzales), `p2` (Sarah Sales); Contractor `con_001`; Subcontractors `sub_001``sub_005`.
**Decision:** unify on the `MOCK_USERS` id scheme (auth + `projects` already use it), with **realistic Texan names**, a **unified `LUP-####` employee-ID scheme**, and a shared demo password (`password`). Canonical roster (single source of truth):
| id | Role | Name | empId | Login type | Login id | Password |
|----|------|------|-------|-----------|----------|----------|
| own_001 | OWNER | Justin Johnson | LUP-1001 | owner | justin | password |
| own_002 | OWNER | Diana Reeves | LUP-1002 | owner | diana | password |
| a1 | ADMIN | Wade Hollis | LUP-1010 | employee | LUP-1010 | password |
| a2 | ADMIN | Darlene Brooks | LUP-1011 | employee | LUP-1011 | password |
| a3 | ADMIN | Roy Schaefer | LUP-1012 | employee | LUP-1012 | password |
| p1 | SALES_REP | Jesus Gonzales | LUP-1030 | employee | LUP-1030 | password |
| p2 | SALES_REP | Sarah Calloway | LUP-1031 | employee | LUP-1031 | password |
| e1 | FIELD_AGENT | Cody Tatum | LUP-1040 | employee | LUP-1040 | password |
| e2 | FIELD_AGENT | Hannah Reyes | LUP-1041 | employee | LUP-1041 | password |
| e3 | FIELD_AGENT | Travis Boone | LUP-1042 | employee | LUP-1042 | password |
| e4 | FIELD_AGENT | Shelby Greer | LUP-1043 | employee | LUP-1043 | password |
| e5 | FIELD_AGENT | Dalton Pruitt | LUP-1044 | employee | LUP-1044 | password |
| con_001 | CONTRACTOR | Mike Brennan | LUP-3001 | contractor | mike | password |
| sub_001 | SUBCONTRACTOR | Carlos Mendoza | LUP-2001 | subcontractor | carlos | password |
| sub_002 | SUBCONTRACTOR | Maya Patel | LUP-2002 | subcontractor | maya | password |
| sub_003 | SUBCONTRACTOR | Dwayne Boudreaux | LUP-2003 | subcontractor | dwayne | password |
| sub_004 | SUBCONTRACTOR | Jennifer Castillo | LUP-2004 | subcontractor | jennifer | password |
| sub_005 | SUBCONTRACTOR | Greg Alston | LUP-2005 | subcontractor | greg | password |
Names are **denormalized** across the store (teamMembers, tasks, kanban activity, DISPATCH_REPS) and some components, so the rename is a **repo-wide string replace** of each old name → new (old names are distinctive), plus setting names/empIds on the source people records. `resolvePerson(id)` is the go-forward single source.
**Login page:** the "Quick Demo Access" row becomes a **per-role person picker** — clicking a role (Admin/Agent/Sub-Con) expands the list of people in that role; clicking a person auto-fills the correct login id + password (and can sign in). Single-person roles (Owner) stay one-click.
**Changes:** remap `orgMembers[].userId` and all subcontractor-task references (`assignedBy`/`actorId`/`senderId`) to canonical ids; reconcile names/emails (Owner #2 = Diana Reeves everywhere; real admin names; consistent Justin email); add a `resolvePerson(id)` selector returning `{ id, name, email, role }` from a single merged index.
@@ -126,7 +150,7 @@ Status set (replaces flat Assigned/In Progress/…), **each transition carries a
Every person (employee **and** subcontractor) gets a two-layer `profile`, surfaced through a self-service **User Details** page (all roles, including owners) and an owner-facing **Employee/Subcontractor Details** view.
**① Self section** (person edits; owner can view): preferred name, photo, phone, alt contact, address, emergency contact; short bio, years of experience/since-date, languages; self-declared specialties + **equipment carried** (e.g., tarp, ladder rack, drone); availability/service areas. Subcontractors also: company name, license #, insurance/COI + expiry, W-9 status.
**① Self section** (person edits; owner can view): preferred name, photo, phone, alt contact, address, emergency contact; **optional identity fields — nickname, pronouns, gender, sex (all optional)**; short bio, years of experience/since-date, languages; self-declared specialties + **equipment carried** (e.g., tarp, ladder rack, drone); availability/service areas. Subcontractors also: company name, license #, insurance/COI + expiry, W-9 status.
**② Company section** (owner/admin edits; **private to owner/admin — not shown to the person**): company bio / internal notes ("reliable in storms, keeps a tarp on the truck"); internal status/tags (preferred / probation / do-not-use); **skill scores** (see below); pay/commission terms; hire date; manager.