# Project Materials Drawer - Scratchpad

## Initial Discovery (2026-02-04)

### Related Work
- **Ticket Materials PR #1701** (merged 2026-01-29): `328eff8b0` - "feat: implement ticket materials with multi-currency"
- **Tag Filter Fix**: `6057c5bd0` - "Fix tag filter to preserve colors and clean orphans"

### Architecture Decision: Component Location

**Pattern Discovered:** `TicketMaterialsCard` lives in `@alga-psa/tickets`, NOT in `@alga-psa/billing`.

**Decision:** Keep `ProjectMaterialsDrawer` in `@alga-psa/projects` and add `@alga-psa/billing` as a dependency.

**Rationale:**
- Follows established pattern (TicketMaterialsCard in tickets, imports from billing)
- Feature modules keep their UI components
- Import actions from the domain owner (billing)

### Required Package Change

`packages/projects/package.json` needs:
```json
"dependencies": {
  "@alga-psa/billing": "*",
  // ... existing
}
```

### Existing Infrastructure

#### Server Actions (Already Exist!)
Located in `packages/billing/src/actions/materialActions.ts`:
- `listProjectMaterials(projectId)` - Returns `IProjectMaterial[]` with service_name and sku joined
- `addProjectMaterial(input)` - Creates new material (rate in cents, quantity floored to min 1)
- `deleteProjectMaterial(projectMaterialId)` - Deletes if not billed

All actions are already exported from `@alga-psa/billing/actions`.

#### Data Model
`IProjectMaterial` interface (`packages/types/src/interfaces/material.interfaces.ts`):
- `project_material_id: string` - Primary key
- `project_id: string` - Foreign key to project
- `client_id: string` - Foreign key to client (for billing)
- `service_id: string` - Foreign key to service_catalog (product)
- `service_name?: string` - Denormalized from service_catalog
- `sku?: string | null` - Product SKU
- `quantity: number`
- `rate: number` - Price in cents
- `currency_code: string` - ISO 4217 currency code
- `description?: string | null`
- `is_billed: boolean`

### Key Files

| File | Purpose |
|------|---------|
| `packages/projects/package.json` | Add billing dependency |
| `packages/projects/src/components/ProjectMaterialsDrawer.tsx` | Implement drawer |
| `packages/tickets/src/components/ticket/TicketMaterialsCard.tsx` | Reference impl |
| `packages/billing/src/actions/materialActions.ts` | Actions (complete) |

---

## Decisions Log

| Date | Decision | Rationale |
|------|----------|-----------|
| 2026-02-04 | Keep component in projects package | Follows TicketMaterialsCard pattern |
| 2026-02-04 | Add @alga-psa/billing dependency | Required for material actions |
| 2026-02-04 | 12 features, 18 tests | Streamlined from initial 41/78 |

---

## Updates

- 2026-02-04: Added `@alga-psa/billing` dependency to `packages/projects/package.json` for project materials drawer actions.
- 2026-02-04: Added drawer header scaffold and set project materials drawer width to 560px via `openDrawer`.
- 2026-02-04: Wired `ProjectMaterialsDrawer` to `listProjectMaterials` with loading and empty states.
- 2026-02-04: Added materials table layout with product, SKU, qty, rate, total, and status badge columns.
- 2026-02-04: Added per-currency unbilled totals summary to support multi-currency projects.
- 2026-02-04: Implemented add-form product picker with searchable catalog lookup.
- 2026-02-04: Added price/currency selector with auto-selected first price and multi-price dropdown.
- 2026-02-04: Added quantity/description inputs and live total display to the add form.
- 2026-02-04: Implemented add-material submission with validation, toast feedback, and list refresh.
- 2026-02-04: Added delete action for unbilled materials with toast feedback and reload.
- 2026-02-04: Allowed materials drawer to open without a client and display a no-client warning while hiding the Add button.
- 2026-02-04: Wrapped drawer content in `ReflectionContainer` and added automation IDs for key elements.
- 2026-02-04: Added T001 test to assert billing dependency in projects package.json.
- 2026-02-04: Added T002 test to assert ProjectInfo opens materials drawer with 560px width.
- 2026-02-04: Added T003 test to verify loading state while materials fetch is pending.
- 2026-02-04: Added T004 test to verify empty state when no materials are returned.
- 2026-02-04: Added T005 test to verify table columns and material row content.
- 2026-02-04: Added T006 test to verify Pending/Billed badge rendering.
- 2026-02-04: Added T007 test to verify currency formatting from minor units.
- 2026-02-04: Added T008 test to verify per-currency unbilled totals summary.
- 2026-02-04: Added T009 test to ensure product picker loads catalog items.
- 2026-02-04: Added T010 test to ensure price selector options appear after product selection.
- 2026-02-04: Added T011 test for quantity default/min validation.
- 2026-02-04: Added T012 test for total recalculation on quantity/currency changes.
- 2026-02-04: Added T013 test to verify add-material submission and list refresh.
- 2026-02-04: Added T014 test to verify validation toasts for missing product/price.
- 2026-02-04: Added T015 test to ensure delete controls only show for unbilled items.
- 2026-02-04: Added T016 test to verify delete action triggers list refresh.
- 2026-02-04: Added T017 test to verify no-client warning and Add button suppression.
- 2026-02-04: Added T018 test to verify automation IDs on key elements.
- 2026-02-04: Adjusted add button to allow validation toasts without disabling, and aligned vitest aliases for @alga-psa/projects.
- 2026-02-04: Added vitest alias for @alga-psa/tags and ensured RTL cleanup between drawer tests.
- 2026-02-04: Added explicit data-automation-id wrappers for quantity/description fields and mocked TagManager in tests.
- 2026-02-04: Test run: `npx vitest --run packages/projects/tests/packageDependencies.test.ts packages/projects/tests/projectInfoDrawer.test.tsx packages/projects/tests/projectMaterialsDrawer.test.tsx` (passes; warnings about act()).
