chore: complete v1.0 Member Notes System milestone

Archive roadmap and requirements to milestones/v1.0-*.
Evolve PROJECT.md with validated requirements and decisions.
Reorganize ROADMAP.md with milestone grouping.
Delete REQUIREMENTS.md (fresh for next milestone).

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
This commit is contained in:
2026-02-13 15:07:30 +08:00
parent 3e9bf153dc
commit 25779933cc
7 changed files with 237 additions and 239 deletions

20
.planning/MILESTONES.md Normal file
View File

@@ -0,0 +1,20 @@
# Milestones
## v1.0 Member Notes System (Shipped: 2026-02-13)
**Phases completed:** 3 phases, 4 plans
**Files modified:** 29 | **Lines:** +3,989 / -36
**Timeline:** 2026-02-13 (single day)
**Key accomplishments:**
- Polymorphic notes table with Member relationship and author tracking
- JSON API endpoints for note creation/retrieval with validation and audit logging
- Inline quick-add note UI on member list with AJAX submission and dark mode
- Expandable note history panel with search filtering and cache sync
- 11 feature tests with 86 assertions
**Bug found during UAT:**
- `<template x-data>` inside `<tbody>` doesn't render children — fixed with per-member `<tbody x-data>`
---

View File

@@ -2,7 +2,7 @@
## What This Is ## What This Is
An enhancement to the existing admin member list that adds per-member note-taking capability. Any admin user can quickly add timestamped text notes to any member, and see a note count badge on the member list. Designed primarily for the chairman (理事長) to track observations and follow-ups, but shared across all admin roles. An enhancement to the existing admin member list that adds per-member note-taking capability with inline quick-add and expandable history panel. Any admin user can add timestamped text notes to any member, view full note history with search, and see note count badges — all without leaving the member list page. Designed primarily for the chairman (理事長) but shared across all admin roles.
## Core Value ## Core Value
@@ -12,26 +12,20 @@ The chairman can annotate any member with timestamped notes directly from the me
### Validated ### Validated
<!-- Existing capabilities inferred from codebase --> - ✓ Per-member notes with text + timestamp, stored in DB — v1.0
- ✓ Inline quick-add note UI on the admin member list (no page navigation) — v1.0
- ✓ Member lifecycle management (pending → active → expired/suspended) — existing - ✓ Note count badge displayed on each member row in the list — v1.0
- ✓ Admin member list with search, filter, CRUD — existing - ✓ Click badge to expand/view full note history for that member — v1.0
- ✓ Role-based access control via Spatie permissions — existing - ✓ All admin roles can view and write notes (shared visibility) — v1.0
- ✓ Multi-tier financial approval workflows — existing - ✓ Notes display author name and creation datetime — v1.0
- ✓ CMS (articles, pages, documents) with headless API — existing - ✓ Notes management (view history, search, chronological order) — v1.0
- ✓ Issue tracking systemexisting - ✓ Dark mode fully supportedv1.0
- ✓ Audit logging on business-critical actions — existing - ✓ All UI text in Traditional Chinese — v1.0
- ✓ Member profile with LINE ID — existing - ✓ Works across paginated member list pages — v1.0
### Active ### Active
- [ ] Per-member notes with text + timestamp, stored in DB (None — v1.0 complete, awaiting next milestone definition)
- [ ] Inline quick-add note UI on the admin member list (no page navigation)
- [ ] Note count badge displayed on each member row in the list
- [ ] Click badge to expand/view full note history for that member
- [ ] All admin roles can view and write notes (shared visibility)
- [ ] Notes display author name and creation datetime
- [ ] Notes management (view history, chronological order)
### Out of Scope ### Out of Scope
@@ -41,15 +35,20 @@ The chairman can annotate any member with timestamped notes directly from the me
- Note editing or deletion — append-only for audit integrity - Note editing or deletion — append-only for audit integrity
- Dashboard/summary statistics — just the annotated member list - Dashboard/summary statistics — just the annotated member list
- API endpoint for notes — admin-only, no public/headless API needed - API endpoint for notes — admin-only, no public/headless API needed
- Real-time updates (WebSocket) — single-user note-taking doesn't need sync
## Context ## Context
- The existing admin member list is at `/admin/members` with full CRUD, search, and filtering Shipped v1.0 with 3,989 lines added across 29 files.
- The chairman (理事長) role maps to `finance_chair` in the RBAC system Tech stack: Laravel 10, Blade, Tailwind CSS, Alpine.js 3.4 + @alpinejs/collapse.
- The `admin` middleware allows access to anyone with the `admin` role or any permissions 11 feature tests with 86 assertions covering API, UI rendering, and data contracts.
- UI is Blade + Tailwind CSS + Alpine.js — inline interactions fit naturally with Alpine.js
- All UI text is hardcoded Traditional Chinese Key files:
- The member list uses standard Laravel pagination - `app/Models/Note.php` — Polymorphic note model with author relationship
- `app/Http/Controllers/Admin/MemberNoteController.php` — CRUD endpoints
- `resources/views/admin/members/index.blade.php` — Inline UI with per-member `<tbody x-data>`
- `database/migrations/*_create_notes_table.php` — Schema with indexes
- `tests/Feature/Admin/MemberNoteTest.php` — 11 tests
## Constraints ## Constraints
@@ -63,10 +62,16 @@ The chairman can annotate any member with timestamped notes directly from the me
| Decision | Rationale | Outcome | | Decision | Rationale | Outcome |
|----------|-----------|---------| |----------|-----------|---------|
| Enhance existing member list vs new page | User wants notes integrated into existing workflow, not a separate tool | — Pending | | Enhance existing member list vs new page | User wants notes integrated into existing workflow | ✓ Good |
| Shared notes (all admin roles) | Chairman wants transparency; secretary and others should see same notes | — Pending | | Shared notes (all admin roles) | Chairman wants transparency; secretary and others should see same notes | ✓ Good |
| Append-only notes (no edit/delete) | Maintains audit integrity for member observations | — Pending | | Append-only notes (no edit/delete) | Maintains audit integrity for member observations | ✓ Good |
| Alpine.js inline UI | Matches existing stack; avoids full page reloads for quick note-taking | — Pending | | Alpine.js inline UI | Matches existing stack; avoids full page reloads for quick note-taking | ✓ Good |
| Polymorphic relationship (morphMap) | Future extensibility to other entities (issues, payments) | ✓ Good |
| morphMap instead of enforceMorphMap | Avoids breaking Spatie Laravel Permission's morph usage | ✓ Good |
| Per-member `<tbody x-data>` wrapper | Allows sibling `<tr>` elements to share Alpine state (template x-data is inert) | ✓ Good |
| Client-side search via computed property | Notes dataset is small (<20/member), no server-side filtering needed | ✓ Good |
| Explicit `latest('created_at')` ordering | Prevents bugs from implicit DB insertion order | ✓ Good |
| JSON responses for admin endpoints | Phase 2+ consumes via AJAX from Alpine.js | ✓ Good |
--- ---
*Last updated: 2026-02-13 after initialization* *Last updated: 2026-02-13 after v1.0 milestone*

View File

@@ -1,100 +0,0 @@
# Requirements: Member Notes System (會員備註系統)
**Defined:** 2026-02-13
**Core Value:** The chairman can annotate any member with timestamped notes directly from the member list, without navigating away from the page.
## v1 Requirements
### Note Creation
- [ ] **NOTE-01**: Admin can add a text note to any member inline from the member list (no page navigation)
- [ ] **NOTE-02**: Each note stores text content, author (current user), and creation datetime
- [ ] **NOTE-03**: Note submission uses AJAX (Axios) with CSRF protection — no page reload
### Note Display
- [ ] **DISP-01**: Each member row shows a note count badge indicating number of notes
- [ ] **DISP-02**: Clicking the badge expands an inline panel showing full note history (newest first)
- [ ] **DISP-03**: Each note displays author name and formatted datetime
- [ ] **DISP-04**: Notes can be filtered/searched by text content within a member's note history
### Data Layer
- [ ] **DATA-01**: Notes use polymorphic relationship (`notable_type`/`notable_id`) for future extensibility
- [ ] **DATA-02**: Migration includes proper indexes for member lookups and chronological ordering
- [ ] **DATA-03**: Member list uses eager loading (`withCount('notes')`) to prevent N+1 queries
### Access & Audit
- [ ] **ACCS-01**: All admin roles can view and write notes (reuses existing `admin` middleware)
- [ ] **ACCS-02**: Note creation is logged via `AuditLogger::log()`
- [ ] **ACCS-03**: Dark mode fully supported on all note UI elements
### UI/UX
- [ ] **UI-01**: All UI text in Traditional Chinese
- [ ] **UI-02**: Note quick-add works correctly across paginated member list pages
- [ ] **UI-03**: Alpine.js manages inline state (expand/collapse, form submission, loading states)
## v2 Requirements
### Enhanced Notes
- **NOTE-04**: Note editing with revision history
- **NOTE-05**: Note deletion with soft delete and audit trail
- **NOTE-06**: Rich text / markdown support in note content
### Advanced Display
- **DISP-05**: Export member notes to PDF
- **DISP-06**: Full-text search across all members' notes (global search)
### Extended Data
- **DATA-04**: Attach notes to other entities (Issues, Payments) using polymorphic relationship
- **DATA-05**: Note categories or tags for organization
### Permissions
- **ACCS-04**: Granular `manage_member_notes` permission via Spatie
## Out of Scope
| Feature | Reason |
|---------|--------|
| Private/role-scoped notes | All notes shared across admin roles per user decision |
| Note reminders/follow-ups | Over-engineering for v1; revisit based on usage |
| Note attachments (files/images) | Keep notes lightweight — text only |
| API endpoint for notes | Admin-only feature, no public/headless API needed |
| Dedicated notes management page | Notes integrated into existing member list |
| Real-time updates (WebSocket) | Single-user note-taking doesn't need real-time sync |
## Traceability
| Requirement | Phase | Status |
|-------------|-------|--------|
| NOTE-01 | Phase 2 | Pending |
| NOTE-02 | Phase 2 | Pending |
| NOTE-03 | Phase 2 | Pending |
| DISP-01 | Phase 2 | Pending |
| DISP-02 | Phase 3 | Pending |
| DISP-03 | Phase 3 | Pending |
| DISP-04 | Phase 3 | Pending |
| DATA-01 | Phase 1 | Pending |
| DATA-02 | Phase 1 | Pending |
| DATA-03 | Phase 1 | Pending |
| ACCS-01 | Phase 1 | Pending |
| ACCS-02 | Phase 1 | Pending |
| ACCS-03 | Phase 2 | Pending |
| UI-01 | Phase 2 | Pending |
| UI-02 | Phase 2 | Pending |
| UI-03 | Phase 2 | Pending |
**Coverage:**
- v1 requirements: 16 total
- Mapped to phases: 16 ✓
- Unmapped: 0 ✓
---
*Requirements defined: 2026-02-13*
*Last updated: 2026-02-13 after roadmap creation*

View File

@@ -1,94 +1,30 @@
# Roadmap: Member Notes System (會員備註系統) # Roadmap: Member Notes System (會員備註系統)
## Overview ## Milestones
This roadmap delivers inline note-taking capabilities for the Taiwan NPO admin member list, enabling quick annotation without page navigation. The implementation follows a foundation-first approach: database schema and backend API (Phase 1), followed by inline quick-add UI delivering core value (Phase 2), and concluding with full note history and display features (Phase 3). All work leverages the existing Laravel 10 + Alpine.js + Tailwind stack (Phase 3 adds @alpinejs/collapse, the official Alpine.js collapse plugin). - ✅ **v1.0 Member Notes System**Phases 1-3 (shipped 2026-02-13)
## Phases ## Phases
**Phase Numbering:** <details>
- Integer phases (1, 2, 3): Planned milestone work <summary>✅ v1.0 Member Notes System (Phases 1-3) — SHIPPED 2026-02-13</summary>
- Decimal phases (2.1, 2.2): Urgent insertions (marked with INSERTED)
Decimal phases appear between their surrounding integers in numeric order. - [x] Phase 1: Database Schema & Backend API (2/2 plans) — completed 2026-02-13
- [x] Phase 2: Inline Quick-Add UI (1/1 plan) — completed 2026-02-13
- [x] Phase 3: Note History & Display (1/1 plan) — completed 2026-02-13
- [x] **Phase 1: Database Schema & Backend API** - Foundation layer with polymorphic relationships Full details: `.planning/milestones/v1.0-ROADMAP.md`
- [x] **Phase 2: Inline Quick-Add UI** - Core value: quick annotation from member list
- [x] **Phase 3: Note History & Display** - Full note viewing and search capabilities
## Phase Details </details>
### Phase 1: Database Schema & Backend API
**Goal**: Establish database foundation and backend endpoints for note storage and retrieval
**Depends on**: Nothing (first phase)
**Requirements**: DATA-01, DATA-02, DATA-03, ACCS-01, ACCS-02
**Success Criteria** (what must be TRUE):
1. Notes table exists with polymorphic columns (`notable_type`, `notable_id`) and proper indexes
2. Admin can create a note via POST endpoint with text, member ID, and author auto-captured
3. Admin can retrieve all notes for a member via GET endpoint with author name and timestamps
4. Member list shows accurate note count for each member without N+1 queries
5. Note creation events are logged in audit trail with action and metadata
**Plans:** 2 plans
Plans:
- [x] 01-01-PLAN.md — Database schema, Note model, Member relationship, morph map, factory
- [x] 01-02-PLAN.md — MemberNoteController, routes, member list withCount, feature tests
### Phase 2: Inline Quick-Add UI
**Goal**: Deliver core value — admins can annotate members inline without page navigation
**Depends on**: Phase 1
**Requirements**: NOTE-01, NOTE-02, NOTE-03, DISP-01, UI-01, UI-02, UI-03, ACCS-03
**Success Criteria** (what must be TRUE):
1. Each member row displays a note count badge showing number of notes
2. Admin can click an inline form to add a note without leaving the member list page
3. After submitting a note, the badge updates immediately and the form clears
4. Note submission shows loading state during AJAX request (disabled button)
5. Validation errors display in Traditional Chinese below the form field
6. All note UI elements work correctly in both light and dark mode
7. Quick-add functionality works across paginated member list pages (pages 1, 2, 3+)
**Plans:** 1 plan
Plans:
- [x] 02-01-PLAN.md — Inline note form with Alpine.js, note count badge, AJAX submission, dark mode, and feature tests
### Phase 3: Note History & Display
**Goal**: Complete the note feature with full history viewing and search
**Depends on**: Phase 2
**Requirements**: DISP-02, DISP-03, DISP-04
**Success Criteria** (what must be TRUE):
1. Admin can click the note count badge to expand an inline panel showing all notes for that member
2. Notes display in chronological order (newest first) with author name and formatted datetime
3. Panel shows empty state message ("尚無備註") when member has no notes
4. Admin can filter/search notes by text content within a member's note history
5. Expanded panel collapses cleanly without affecting other member rows
**Plans:** 1 plan
Plans:
- [x] 03-01-PLAN.md — Expandable note history panel with search, collapse plugin, controller ordering fix, and feature tests
## Progress ## Progress
**Execution Order:** | Phase | Milestone | Plans Complete | Status | Completed |
Phases execute in numeric order: 1 → 2 → 3 |-------|-----------|----------------|--------|-----------|
| 1. Database Schema & Backend API | v1.0 | 2/2 | ✓ Complete | 2026-02-13 |
| Phase | Plans Complete | Status | Completed | | 2. Inline Quick-Add UI | v1.0 | 1/1 | ✓ Complete | 2026-02-13 |
|-------|----------------|--------|-----------| | 3. Note History & Display | v1.0 | 1/1 | ✓ Complete | 2026-02-13 |
| 1. Database Schema & Backend API | 2/2 | ✓ Complete | 2026-02-13 |
| 2. Inline Quick-Add UI | 1/1 | ✓ Complete | 2026-02-13 |
| 3. Note History & Display | 1/1 | ✓ Complete | 2026-02-13 |
--- ---
*Roadmap created: 2026-02-13* *Roadmap created: 2026-02-13*
*Last updated: 2026-02-13 (Phase 3 complete — all phases done)* *Last updated: 2026-02-13 (v1.0 milestone shipped)*

View File

@@ -6,14 +6,13 @@ See: .planning/PROJECT.md (updated 2026-02-13)
**Core value:** The chairman can annotate any member with timestamped notes directly from the member list, without navigating away from the page. **Core value:** The chairman can annotate any member with timestamped notes directly from the member list, without navigating away from the page.
**Current focus:** Phase 3 - Note History Display **Current focus:** v1.0 shipped — planning next milestone
## Current Position ## Current Position
Phase: 3 of 3 (Note History Display) Milestone: v1.0 Member Notes System — SHIPPED
Plan: 1 of 1 in current phase Status: Complete
Status: Phase Complete Last activity: 2026-02-13 — Milestone archived
Last activity: 2026-02-13 — Completed 03-01-PLAN.md (Expandable note history panel with search)
Progress: [██████████] 100% Progress: [██████████] 100%
@@ -32,45 +31,24 @@ Progress: [██████████] 100%
| 02 | 1 | 2.3 min | 2.3 min | | 02 | 1 | 2.3 min | 2.3 min |
| 03 | 1 | 2.2 min | 2.2 min | | 03 | 1 | 2.2 min | 2.2 min |
**Recent Trend:**
- Last 5 plans: 3 min, 2 min, 2.3 min, 2.2 min
- Trend: Consistently fast (sub-3 min average)
*Updated after each plan completion*
## Accumulated Context ## Accumulated Context
### Decisions ### Decisions
Decisions are logged in PROJECT.md Key Decisions table. All decisions logged in PROJECT.md Key Decisions table.
Recent decisions affecting current work:
- Use Alpine.js collapse plugin for panel animation: Provides smooth, accessible expand/collapse with minimal code (completed in 03-01)
- Wrap main row + expansion row in template x-data: Allows sibling tr elements to share Alpine.js state while maintaining table structure (completed in 03-01)
- Client-side search via computed property: Notes dataset is small, no need for server-side filtering (completed in 03-01)
- Fix controller ordering from implicit to explicit latest(): Prevents future bugs if database changes affect insertion order (completed in 03-01)
- Eager load only author id+name: Reduces payload size, only needed fields for display (completed in 03-01)
- Per-row Alpine.js scope for independent inline forms: Each row renders fresh x-data, pagination works correctly (completed in 02-01)
- Submit button disabled when isSubmitting OR noteContent empty: Prevents blank note submissions (completed in 02-01)
- Error display via optional chaining (errors.content?.[0]): Handles missing error keys gracefully (completed in 02-01)
- Cancel button resets all state (content, form open, errors): Clean slate on re-open (completed in 02-01)
- JSON responses for admin endpoints: Phase 2 consumes via AJAX from Alpine.js (completed in 01-02)
- Authorization via admin middleware: StoreNoteRequest returns true, route middleware handles auth (completed in 01-02)
- withCount in member list: Prevents N+1 queries for note count badges (completed in 01-02)
- Use morphMap instead of enforceMorphMap: Avoids breaking Spatie Laravel Permission while providing namespace protection (completed in 01-01)
### Pending Todos ### Pending Todos
None yet. None.
### Blockers/Concerns ### Blockers/Concerns
None yet. None.
## Session Continuity ## Session Continuity
Last session: 2026-02-13 Last session: 2026-02-13
Stopped at: Completed Phase 3 (03-01-PLAN.md) - Expandable note history panel with search Stopped at: v1.0 milestone complete and archived
Resume file: None Resume file: None
**Phase 3 Complete** - Note history display feature complete. Admins can now view all member notes inline with search filtering. The member notes feature is fully functional: inline quick-add (Phase 2) + expandable history panel (Phase 3). All 3 phases complete. **Milestone v1.0 shipped.** Next: `/gsd:new-milestone` when ready for new work.

View File

@@ -0,0 +1,65 @@
# Requirements Archive: v1.0 Member Notes System
**Archived:** 2026-02-13
**Status:** SHIPPED
---
## v1 Requirements — All Shipped
### Note Creation
- [x] **NOTE-01**: Admin can add a text note to any member inline from the member list — Phase 2
- [x] **NOTE-02**: Each note stores text content, author (current user), and creation datetime — Phase 1
- [x] **NOTE-03**: Note submission uses AJAX (Axios) with CSRF protection — no page reload — Phase 2
### Note Display
- [x] **DISP-01**: Each member row shows a note count badge indicating number of notes — Phase 2
- [x] **DISP-02**: Clicking the badge expands an inline panel showing full note history (newest first) — Phase 3
- [x] **DISP-03**: Each note displays author name and formatted datetime — Phase 3
- [x] **DISP-04**: Notes can be filtered/searched by text content within a member's note history — Phase 3
### Data Layer
- [x] **DATA-01**: Notes use polymorphic relationship (`notable_type`/`notable_id`) — Phase 1
- [x] **DATA-02**: Migration includes proper indexes for member lookups and chronological ordering — Phase 1
- [x] **DATA-03**: Member list uses eager loading (`withCount('notes')`) to prevent N+1 queries — Phase 1
### Access & Audit
- [x] **ACCS-01**: All admin roles can view and write notes (reuses existing `admin` middleware) — Phase 1
- [x] **ACCS-02**: Note creation is logged via `AuditLogger::log()` — Phase 1
- [x] **ACCS-03**: Dark mode fully supported on all note UI elements — Phase 2
### UI/UX
- [x] **UI-01**: All UI text in Traditional Chinese — Phase 2
- [x] **UI-02**: Note quick-add works correctly across paginated member list pages — Phase 2
- [x] **UI-03**: Alpine.js manages inline state (expand/collapse, form submission, loading states) — Phase 3
## Traceability
| Requirement | Phase | Status |
|-------------|-------|--------|
| NOTE-01 | Phase 2 | ✓ Shipped |
| NOTE-02 | Phase 1 | ✓ Shipped |
| NOTE-03 | Phase 2 | ✓ Shipped |
| DISP-01 | Phase 2 | ✓ Shipped |
| DISP-02 | Phase 3 | ✓ Shipped |
| DISP-03 | Phase 3 | ✓ Shipped |
| DISP-04 | Phase 3 | ✓ Shipped |
| DATA-01 | Phase 1 | ✓ Shipped |
| DATA-02 | Phase 1 | ✓ Shipped |
| DATA-03 | Phase 1 | ✓ Shipped |
| ACCS-01 | Phase 1 | ✓ Shipped |
| ACCS-02 | Phase 1 | ✓ Shipped |
| ACCS-03 | Phase 2 | ✓ Shipped |
| UI-01 | Phase 2 | ✓ Shipped |
| UI-02 | Phase 2 | ✓ Shipped |
| UI-03 | Phase 3 | ✓ Shipped |
**Coverage:** 16/16 requirements shipped (100%)
---
*Archived: 2026-02-13*

View File

@@ -0,0 +1,94 @@
# Roadmap: Member Notes System (會員備註系統)
## Overview
This roadmap delivers inline note-taking capabilities for the Taiwan NPO admin member list, enabling quick annotation without page navigation. The implementation follows a foundation-first approach: database schema and backend API (Phase 1), followed by inline quick-add UI delivering core value (Phase 2), and concluding with full note history and display features (Phase 3). All work leverages the existing Laravel 10 + Alpine.js + Tailwind stack (Phase 3 adds @alpinejs/collapse, the official Alpine.js collapse plugin).
## Phases
**Phase Numbering:**
- Integer phases (1, 2, 3): Planned milestone work
- Decimal phases (2.1, 2.2): Urgent insertions (marked with INSERTED)
Decimal phases appear between their surrounding integers in numeric order.
- [x] **Phase 1: Database Schema & Backend API** - Foundation layer with polymorphic relationships
- [x] **Phase 2: Inline Quick-Add UI** - Core value: quick annotation from member list
- [x] **Phase 3: Note History & Display** - Full note viewing and search capabilities
## Phase Details
### Phase 1: Database Schema & Backend API
**Goal**: Establish database foundation and backend endpoints for note storage and retrieval
**Depends on**: Nothing (first phase)
**Requirements**: DATA-01, DATA-02, DATA-03, ACCS-01, ACCS-02
**Success Criteria** (what must be TRUE):
1. Notes table exists with polymorphic columns (`notable_type`, `notable_id`) and proper indexes
2. Admin can create a note via POST endpoint with text, member ID, and author auto-captured
3. Admin can retrieve all notes for a member via GET endpoint with author name and timestamps
4. Member list shows accurate note count for each member without N+1 queries
5. Note creation events are logged in audit trail with action and metadata
**Plans:** 2 plans
Plans:
- [x] 01-01-PLAN.md — Database schema, Note model, Member relationship, morph map, factory
- [x] 01-02-PLAN.md — MemberNoteController, routes, member list withCount, feature tests
### Phase 2: Inline Quick-Add UI
**Goal**: Deliver core value — admins can annotate members inline without page navigation
**Depends on**: Phase 1
**Requirements**: NOTE-01, NOTE-02, NOTE-03, DISP-01, UI-01, UI-02, UI-03, ACCS-03
**Success Criteria** (what must be TRUE):
1. Each member row displays a note count badge showing number of notes
2. Admin can click an inline form to add a note without leaving the member list page
3. After submitting a note, the badge updates immediately and the form clears
4. Note submission shows loading state during AJAX request (disabled button)
5. Validation errors display in Traditional Chinese below the form field
6. All note UI elements work correctly in both light and dark mode
7. Quick-add functionality works across paginated member list pages (pages 1, 2, 3+)
**Plans:** 1 plan
Plans:
- [x] 02-01-PLAN.md — Inline note form with Alpine.js, note count badge, AJAX submission, dark mode, and feature tests
### Phase 3: Note History & Display
**Goal**: Complete the note feature with full history viewing and search
**Depends on**: Phase 2
**Requirements**: DISP-02, DISP-03, DISP-04
**Success Criteria** (what must be TRUE):
1. Admin can click the note count badge to expand an inline panel showing all notes for that member
2. Notes display in chronological order (newest first) with author name and formatted datetime
3. Panel shows empty state message ("尚無備註") when member has no notes
4. Admin can filter/search notes by text content within a member's note history
5. Expanded panel collapses cleanly without affecting other member rows
**Plans:** 1 plan
Plans:
- [x] 03-01-PLAN.md — Expandable note history panel with search, collapse plugin, controller ordering fix, and feature tests
## Progress
**Execution Order:**
Phases execute in numeric order: 1 → 2 → 3
| Phase | Plans Complete | Status | Completed |
|-------|----------------|--------|-----------|
| 1. Database Schema & Backend API | 2/2 | ✓ Complete | 2026-02-13 |
| 2. Inline Quick-Add UI | 1/1 | ✓ Complete | 2026-02-13 |
| 3. Note History & Display | 1/1 | ✓ Complete | 2026-02-13 |
---
*Roadmap created: 2026-02-13*
*Last updated: 2026-02-13 (Phase 3 complete — all phases done)*