```
- [ ] **Step 3: Create a minimal SCSS file**
Per house rule, do NOT put `display` rules here. Create `expense-snapshots-page.component.scss`:
```scss
.page {
padding: 0.5rem 0;
}
```
- [ ] **Step 4: Verify the build compiles**
Run from `APP/`: `npx ng build --configuration development`
Expected: build completes with no errors referencing `expense-snapshots-page`.
- [ ] **Step 5: Commit**
```bash
git add APP/src/app/features/expense/pages/expense-snapshots-page/
git commit -m "feat(expense-snapshot): snapshot management page (rename/delete)"
```
---
## Task 9: Route + sidebar nav
**Files:**
- Modify: `APP/src/app/app.routes.ts` (finance routes block, near line 192)
- Modify: `APP/src/app/portals/user-portal/user-portal.component.ts:139` (Expenses nav group)
- [ ] **Step 1: Import the page component in the routes file**
In `APP/src/app/app.routes.ts`, add an import alongside the other expense page imports (e.g. near the `ExpensesPageComponent` import):
```typescript
import { ExpenseSnapshotsPageComponent } from './features/expense/pages/expense-snapshots-page/expense-snapshots-page.component';
```
(Confirm the exact relative path matches the other expense page imports in that file; they live under `./features/expense/pages/...`.)
- [ ] **Step 2: Add the route**
In `app.routes.ts`, immediately after the `finance/expenses` route object (closes at line 164), add:
```typescript
{
path: 'finance/expense-snapshots',
component: ExpenseSnapshotsPageComponent,
canActivate: [PermissionGuard],
data: {
permission: { module: PermissionModules.Expenses, action: 'read' },
title: 'Expense Snapshots', titleZh: '費用範本', section: 'Finance',
},
},
```
- [ ] **Step 3: Add the sidebar nav item**
In `APP/src/app/portals/user-portal/user-portal.component.ts`, inside the `Expenses` finance group's `items` array, after the `Expense Categories` item (line 133-134), add:
```typescript
{ text: 'Expense Snapshots', icon: categorizeIcon, path: '/user-portal/finance/expense-snapshots',
permission: { module: PermissionModules.Expenses, action: 'read' } },
```
(`categorizeIcon` is already imported and used in this file.)
- [ ] **Step 4: Verify the build compiles**
Run from `APP/`: `npx ng build --configuration development`
Expected: build completes, 0 errors.
- [ ] **Step 5: Commit**
```bash
git add APP/src/app/app.routes.ts APP/src/app/portals/user-portal/user-portal.component.ts
git commit -m "feat(expense-snapshot): route + sidebar nav for snapshot management"
```
---
## Task 10: End-to-end verification
**Files:** none (manual + automated verification)
- [ ] **Step 1: Backend — full build + targeted tests green**
Run: `dotnet build API/ROLAC.API/ROLAC.API.csproj -c Release` → Build succeeded.
Run: `dotnet test API/ROLAC.API.Tests/ROLAC.API.Tests.csproj -c Release --filter FullyQualifiedName~ExpenseSnapshotServiceTests` → 7 passed.
- [ ] **Step 2: Frontend — service tests + build green**
Run from `APP/`:
```powershell
$env:CHROME_BIN = "C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe"
npx ng test --include="**/expense-snapshot-api.service.spec.ts" --watch=false --browsers=ChromeHeadless
npx ng build --configuration development
```
Expected: 3 specs pass; build succeeds.
- [ ] **Step 3: Manual smoke test**
Start the API and the frontend (see the Build/Run env memory). As a finance user:
1. Finance → Expenses → **+ Vendor Payment**. Fill ministry, description, vendor, one line with an amount. Click **存為範本 / Save as snapshot**, name it "Smoke Rent", Save. Confirm no error.
2. Close the dialog, reopen **+ Vendor Payment**. In **Load from snapshot**, pick "Smoke Rent". Confirm ministry/description/vendor/line all prefill and **Expense Date stays today** (not blank/altered).
3. Finance → **Expense Snapshots**. Confirm "Smoke Rent" appears with vendor, amount, and your name as creator. **Rename** it → confirm the new name shows. **Delete** it → confirm it disappears.
4. Resize the browser to mobile width on the Expense Snapshots page → confirm the card list shows (not the grid) and actions work.
- [ ] **Step 4: Final commit (if any manual-fix tweaks were needed)**
```bash
git add -A
git commit -m "test(expense-snapshot): verification fixes"
```
(Skip if nothing changed.)
---
## Self-Review Notes
- **Spec coverage:** capture fields (Task 1/3), shared + creator tag resolved at read (Task 4 `ResolveUserNamesAsync` + `GetByIdName` test), exclude ExpenseDate/receipt/MemberId (entities omit them; Task 7 `applySnapshot` keeps today's date), save-from-form (Task 7), quick picker + management page both present (Tasks 7 & 8 — spec Q4=C), rename + delete (Task 8), `Expenses:Write` gating (Task 5), mobile-friendly management page (Task 8). All covered.
- **CheckNumber:** captured and editable per spec; no special handling needed.
- **Type consistency:** `CreateExpenseSnapshotRequest`/`UpdateExpenseSnapshotRequest`, `ExpenseSnapshotDto`, `ExpenseSnapshotLineDto`, `ExpenseLineInput` names match across backend DTOs (Task 3), service (Task 4), frontend model (Task 6), and consumers (Tasks 7-8). Service method names (`getAll/getById/create/update/delete`) are identical across interface, service, and Angular service.