diff --git a/package.json b/package.json index b33d28a..1bc1fe6 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "idb": "^8.0.3", "lucide-svelte": "^0.577.0", "markdown-it": "^14.1.1", + "svelte-dnd-action": "^0.9.69", "tiptap-markdown": "^0.9.0", "uuid": "^11.1.0" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4416b3c..80cb3d4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -61,6 +61,9 @@ importers: markdown-it: specifier: ^14.1.1 version: 14.1.1 + svelte-dnd-action: + specifier: ^0.9.69 + version: 0.9.69(svelte@5.53.7) tiptap-markdown: specifier: ^0.9.0 version: 0.9.0(@tiptap/core@3.20.1(@tiptap/pm@3.20.1)) @@ -2900,6 +2903,11 @@ packages: svelte: ^4.0.0 || ^5.0.0-next.0 typescript: '>=5.0.0' + svelte-dnd-action@0.9.69: + resolution: {integrity: sha512-NAmSOH7htJoYraTQvr+q5whlIuVoq88vEuHr4NcFgscDRUxfWPPxgie2OoxepBCQCikrXZV4pqV86aun60wVyw==} + peerDependencies: + svelte: '>=3.23.0 || ^5.0.0-next.0' + svelte@5.53.7: resolution: {integrity: sha512-uxck1KI7JWtlfP3H6HOWi/94soAl23jsGJkBzN2BAWcQng0+lTrRNhxActFqORgnO9BHVd1hKJhG+ljRuIUWfQ==} engines: {node: '>=18'} @@ -6037,6 +6045,10 @@ snapshots: transitivePeerDependencies: - picomatch + svelte-dnd-action@0.9.69(svelte@5.53.7): + dependencies: + svelte: 5.53.7 + svelte@5.53.7: dependencies: '@jridgewell/remapping': 2.3.5 diff --git a/src/lib/components/Checklist.svelte b/src/lib/components/Checklist.svelte index 88a2657..9eae59d 100644 --- a/src/lib/components/Checklist.svelte +++ b/src/lib/components/Checklist.svelte @@ -1,8 +1,13 @@
- {#each items as item, index} -
- toggleItem(index)} - class="h-4 w-4 rounded border-[var(--border-subtle)] text-[var(--primary)] focus:ring-[var(--primary)]" - data-testid="checklist-checkbox" - /> - updateText(index, (e.target as HTMLInputElement).value)} - onkeydown={(e) => handleKeydown(e, index)} - class="flex-1 bg-transparent text-sm outline-none {item.checked ? 'text-[var(--text-muted)] line-through' : 'text-[var(--text)]'}" - placeholder="List item" - data-testid="checklist-input" - /> - -
- {/each} +
+ {#each activeItems as item (item.id)} +
+
+ +
+ toggleItem(item.id)} + class="h-4 w-4 rounded border-[var(--border-subtle)] text-[var(--primary)] focus:ring-[var(--primary)]" + data-testid="checklist-checkbox" + /> + updateText(item.id, (e.target as HTMLInputElement).value)} + onkeydown={(e) => handleKeydown(e, item.id)} + class="flex-1 bg-transparent text-sm outline-none {item.checked ? 'text-[var(--text-muted)] line-through' : 'text-[var(--text)]'}" + placeholder="List item" + data-testid="checklist-input" + /> + +
+ {/each} +
+ + + {#if doneCount > 0} +
+ + + {#if !hideCompleted} + + {:else if showDoneSection} +
+ {#each doneItems as item (item.id)} +
+ toggleItem(item.id)} + class="h-4 w-4 rounded border-[var(--border-subtle)] text-[var(--primary)] focus:ring-[var(--primary)]" + data-testid="checklist-done-checkbox" + /> + {item.text} +
+ {/each} +
+ {/if} +
+ {/if}
diff --git a/tests/e2e/checklist.spec.ts b/tests/e2e/checklist.spec.ts index e9889b0..2a933a6 100644 --- a/tests/e2e/checklist.spec.ts +++ b/tests/e2e/checklist.spec.ts @@ -80,6 +80,35 @@ test.describe('Checklist', () => { await expect(page.getByTestId('checklist-input')).toHaveCount(1); }); + test('Scenario: Completed checklist items can be hidden and shown', async ({ authenticatedPage: page }) => { + // Given a checklist note with a completed item and an uncompleted item + await page.getByTestId('new-note-btn').click(); + await page.getByTestId('note-title-input').fill('Hide Done Test'); + await page.getByTestId('checklist-toggle').click(); + await page.getByTestId('checklist-input').first().fill('Done task'); + await page.getByTestId('checklist-input').first().press('Enter'); + await page.getByTestId('checklist-input').nth(1).fill('Pending task'); + await page.getByTestId('checklist-checkbox').first().check(); + + // Then the "done" toggle is visible + await expect(page.getByTestId('checklist-toggle-done')).toBeVisible(); + await expect(page.getByTestId('checklist-toggle-done')).toContainText('1 done'); + + // When the user clicks the "done" toggle to hide completed items + await page.getByTestId('checklist-toggle-done').click(); + + // Then the completed item is hidden from the main list + await expect(page.getByTestId('checklist-input')).toHaveCount(1); + await expect(page.getByTestId('checklist-input').first()).toHaveValue('Pending task'); + + // When the user expands the done section + await page.getByTestId('checklist-toggle-done').click(); + + // Then the completed items are shown in the done section + await expect(page.getByTestId('checklist-done-section')).toBeVisible(); + await expect(page.getByTestId('checklist-done-section')).toContainText('Done task'); + }); + test('Scenario: Switching back from checklist mode restores the text area', async ({ authenticatedPage: page }) => { // Given the user has checklist mode enabled await page.getByTestId('new-note-btn').click();