fix(03): replace template x-data with tbody x-data for table rendering

<template x-data> inside <tbody> is inert — browsers don't render its
children. Replace with per-member <tbody x-data> (multiple tbody is
valid HTML). Also replace x-collapse on <tr> with x-transition since
table rows don't support max-height/overflow-hidden.

UAT: all 7 tests passed via Playwright automation.

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:02:16 +08:00
parent 596e43bed3
commit 3e9bf153dc
3 changed files with 65 additions and 6 deletions

View File

@@ -0,0 +1,53 @@
---
status: complete
phase: 03-note-history-display
source: 03-01-SUMMARY.md
started: 2026-02-13T14:58:00Z
updated: 2026-02-13T15:02:00Z
---
## Current Test
[testing complete]
## Tests
### 1. Expand note history panel
expected: Click a member's note count badge (the blue number). An inline panel should expand below that member's row with a smooth animation, showing a loading spinner briefly, then displaying notes.
result: pass
### 2. Notes display order and formatting
expected: Notes in the expanded panel appear newest first. Each note shows: content text, author name, and a formatted datetime like "2026年02月13日 14:30". A blue left border accent separates each note.
result: pass
### 3. Empty state for member with no notes
expected: Click the badge of a member who has zero notes. Panel expands and shows "尚無備註" text. No search input should appear.
result: pass
### 4. Search filtering by content or author
expected: With the history panel open (for a member with multiple notes), type text in the search input ("搜尋備忘錄內容或作者..."). Notes filter in real-time as you type — matching by note content or author name (case-insensitive).
result: pass
### 5. Search no results state
expected: Type a search query that matches no notes. The notes list is replaced with "找不到符合的備忘錄" text.
result: pass
### 6. Collapse panel and reset search
expected: With search text entered, click the badge again. Panel collapses smoothly. Re-open the panel — the search input should be empty (reset).
result: pass
### 7. Cache sync after adding note
expected: Open a member's history panel to see existing notes. Then use the pencil icon to add a new note via the inline form. After submitting, the new note should appear at the top of the history panel immediately — no page refresh or re-clicking the badge needed.
result: pass
## Summary
total: 7
passed: 7
issues: 0
pending: 0
skipped: 0
## Gaps
[none]

View File

@@ -191,9 +191,8 @@
</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200 dark:divide-gray-700 bg-white dark:bg-gray-800">
@forelse ($members as $member)
<template x-data="{
<tbody class="divide-y divide-gray-200 dark:divide-gray-700 bg-white dark:bg-gray-800" x-data="{
noteFormOpen: false,
noteContent: '',
isSubmitting: false,
@@ -364,7 +363,13 @@
</td>
</tr>
<!-- Expansion panel row -->
<tr x-show="historyOpen" x-collapse
<tr x-show="historyOpen"
x-transition:enter="transition ease-out duration-200"
x-transition:enter-start="opacity-0"
x-transition:enter-end="opacity-100"
x-transition:leave="transition ease-in duration-150"
x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0"
:id="'notes-panel-{{ $member->id }}'"
class="bg-gray-50 dark:bg-gray-900">
<td colspan="8" class="px-6 py-4">
@@ -417,15 +422,16 @@
</div>
</td>
</tr>
</template>
</tbody>
@empty
<tbody class="bg-white dark:bg-gray-800">
<tr>
<td colspan="8" class="px-4 py-4 text-sm text-gray-500 dark:text-gray-400">
找不到會員。
</td>
</tr>
</tbody>
@endforelse
</tbody>
</table>
</div>

View File

@@ -256,7 +256,7 @@ class MemberNoteTest extends TestCase
$response->assertStatus(200);
$response->assertSee('toggleHistory', false);
$response->assertSee('historyOpen', false);
$response->assertSee('x-collapse', false);
$response->assertSee('x-transition:enter', false);
$response->assertSee('searchQuery', false);
$response->assertSee('filteredNotes', false);
$response->assertSee('尚無備註', false);