- Install @alpinejs/collapse plugin for smooth expand/collapse animation
- Fix controller ordering: notes now explicitly ordered newest first via latest('created_at')
- Note count badge is now clickable button to toggle history panel
- Add expansion panel row with loading state, search filter, empty state
- Search filters notes by content or author name (client-side)
- Panel collapses cleanly, search query resets on close
- Cache sync: new notes from inline form appear in history immediately
- Display format: author name and formatted datetime (YYYY年MM月DD日 HH:mm)
- Empty state shows '尚無備註', no-results shows '找不到符合的備忘錄'
- Alpine.js inline note forms in member list with per-row badge counters
- AJAX submission, validation error display, and full dark mode support
- 5 feature tests pass, no regressions in 7 Phase 1 tests
- Duration: 2 min 17 sec
- Tasks: 2 (feat + test)
- Files: 2 (1 created, 1 modified)
- Self-check: PASSED
- Test note count badge renders with correct count from withCount
- Test Alpine.js directives present in HTML (noteFormOpen, submitNote, x-model, :disabled)
- Test 備忘錄 column header renders
- Test zero-note members show 0 count
- Test correct note store route URL embedded for each member
All 5 tests pass. No regressions in 7 Phase 1 tests.
- Add Alpine.js x-data scope to each member row with noteFormOpen, noteContent, isSubmitting, errors, noteCount
- Add submitNote() async method calling axios.post to admin.members.notes.store route
- Add note count badge with reactive x-text binding to noteCount (initialized from withCount)
- Add toggle button to expand/collapse inline note form
- Add inline form with textarea, cancel button, and submit button
- Submit button disabled when isSubmitting or noteContent is empty
- Loading state toggles between 儲存 and 儲存中...
- Validation errors display in Traditional Chinese via x-show and x-text
- Cancel button clears content, closes form, and resets errors
- Add 備忘錄 column header between 狀態 and 操作
- Update empty state colspan from 7 to 8
- Add x-cloak CSS to prevent flash of unstyled content
- All elements include dark mode classes (dark:*)
- AdminMemberController index() now includes withCount('notes')
- Created MemberNoteTest with 7 feature tests
- Tests cover: creation, retrieval, validation, audit logging, authorization, N+1 prevention, ordering
- All new tests passing (7/7)
- No regressions in existing test suite
- MemberNoteController with index() and store() methods
- StoreNoteRequest with Traditional Chinese validation messages
- Routes registered at admin.members.notes.index/store
- JSON responses for AJAX consumption in Phase 2
- DB::transaction wrapper with AuditLogger::log
- Add SUMMARY.md documenting all tasks and deviations
- Update STATE.md: plan 1 of 2 complete in phase 01
- Update performance metrics: 3 min execution time
- Document morph map decision in STATE.md
- Changed from enforceMorphMap to morphMap in AppServiceProvider
- enforceMorphMap was causing errors with Spatie Laravel Permission package
- morphMap still provides namespace protection for our custom models
- Adds comment explaining why we don't enforce strict mapping
- Add notes() morphMany relationship to Member model (ordered by created_at desc)
- Register morph map in AppServiceProvider ('member' => Member::class)
- Create NoteFactory with forMember() and byAuthor() state methods
- Add notes migration with polymorphic columns (notable_type, notable_id)
- Add foreign key to users table for author tracking
- Add indexes on composite (notable_type, notable_id) and created_at
- Create Note model with morphTo and belongsTo relationships
The related articles query was missing ->with(['categories']),
causing the frontend ArticleCard to crash on undefined categories.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Changed getFeaturedImageUrlAttribute to return relative paths
(e.g., /images/blog/photo.jpg) instead of full Laravel storage URLs.
Migrated image paths updated from migrated-images/ to images/ prefix.
Images are now served from Next.js public/ directory via Vercel CDN.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add identity_type field (patient/parent) to distinguish 病友/家長
- Add guardian_member_id for parent-child relationships
- Add guardian() and dependents() relationships
- Add isPatient(), isParent() helper methods
- Add identity_type_label accessor
Data updated:
- 47 members set as patient, 4 as parent
- 25 members with approved disability, 26 without
- 張序 linked to guardian 張誠駿
- Payment amounts corrected based on 2024 accounting records
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>