---
phase: 04-tags
plan: 02
type: execute
wave: 1
depends_on: []
files_modified:
  - src/routes/+page.server.ts
  - src/routes/+page.svelte
  - src/lib/components/EntryCard.svelte
  - src/lib/components/EntryList.svelte
autonomous: true

must_haves:
  truths:
    - "User can click a pin button to toggle pinned state"
    - "User can set a due date on any entry"
    - "Pinned entries appear in a dedicated section at top of list"
    - "Due date shows on entry card when set"
  artifacts:
    - path: "src/routes/+page.server.ts"
      provides: "togglePin and updateDueDate form actions"
      contains: "togglePin"
    - path: "src/lib/components/EntryCard.svelte"
      provides: "Pin button and due date picker in expanded view"
      contains: "togglePin"
    - path: "src/lib/components/EntryList.svelte"
      provides: "Pinned section above regular entries"
      contains: "pinned"
  key_links:
    - from: "EntryCard pin button"
      to: "?/togglePin action"
      via: "form submit or fetch"
      pattern: "togglePin"
    - from: "EntryCard due date input"
      to: "?/updateDueDate action"
      via: "form submit or fetch"
      pattern: "updateDueDate"
---

<objective>
Add pin/favorite and due date features using existing schema columns (pinned, dueDate already in entries table).

Purpose: Enables ORG-01, ORG-02, ORG-03 requirements - quick access to important entries and task scheduling
Output: Toggle pin button, due date picker, pinned entries section at top of list
</objective>

<execution_context>
@/home/tho/.claude/get-shit-done/workflows/execute-plan.md
@/home/tho/.claude/get-shit-done/templates/summary.md
</execution_context>

<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md

@src/routes/+page.server.ts
@src/routes/+page.svelte
@src/lib/components/EntryCard.svelte
@src/lib/components/EntryList.svelte
@src/lib/server/db/schema.ts
</context>

<tasks>

<task type="auto">
  <name>Task 1: Add togglePin and updateDueDate form actions</name>
  <files>src/routes/+page.server.ts</files>
  <action>
Add two new form actions to the existing actions object:

1. `togglePin` action:
```typescript
togglePin: async ({ request }) => {
  const formData = await request.formData();
  const id = formData.get('id')?.toString();

  if (!id) {
    return fail(400, { error: 'Entry ID is required' });
  }

  const existing = entryRepository.getById(id);
  if (!existing) {
    return fail(404, { error: 'Entry not found' });
  }

  // Toggle pinned state
  entryRepository.update(id, { pinned: !existing.pinned });

  return { success: true };
}
```

2. `updateDueDate` action:
```typescript
updateDueDate: async ({ request }) => {
  const formData = await request.formData();
  const id = formData.get('id')?.toString();
  const dueDate = formData.get('dueDate')?.toString() || null;

  if (!id) {
    return fail(400, { error: 'Entry ID is required' });
  }

  const existing = entryRepository.getById(id);
  if (!existing) {
    return fail(404, { error: 'Entry not found' });
  }

  // Update due date (empty string becomes null)
  entryRepository.update(id, { dueDate: dueDate || null });

  return { success: true };
}
```

Note: The dueDate is stored as ISO date string (YYYY-MM-DD format from HTML5 date input).
  </action>
  <verify>Run `npm run check` - TypeScript compiles. Start dev server and test actions via form submission.</verify>
  <done>togglePin and updateDueDate form actions work correctly, entries.pinned toggles and entries.dueDate updates</done>
</task>

<task type="auto">
  <name>Task 2: Add pin button, due date picker, and pinned section UI</name>
  <files>src/lib/components/EntryCard.svelte, src/lib/components/EntryList.svelte</files>
  <action>
**EntryCard.svelte changes:**

1. Add state for due date editing:
```typescript
let editDueDate = $state(entry.dueDate || '');
```

2. Sync dueDate with entry on collapse (add to existing $effect):
```typescript
$effect(() => {
  if (!expanded) {
    // ... existing syncs
    editDueDate = entry.dueDate || '';
  }
});
```

3. Add async function for pin toggle (similar to debouncedSave pattern):
```typescript
async function handleTogglePin() {
  const formData = new FormData();
  formData.append('id', entry.id);

  await fetch('?/togglePin', {
    method: 'POST',
    body: formData
  });

  await invalidateAll();
}
```

4. Add async function for due date change:
```typescript
async function handleDueDateChange(e: Event) {
  const input = e.target as HTMLInputElement;
  editDueDate = input.value;

  const formData = new FormData();
  formData.append('id', entry.id);
  formData.append('dueDate', input.value);

  await fetch('?/updateDueDate', {
    method: 'POST',
    body: formData
  });

  await invalidateAll();
}
```

5. In collapsed view header (after the expand arrow), add pin indicator:
```svelte
{#if entry.pinned}
  <svg class="w-4 h-4 text-yellow-500" fill="currentColor" viewBox="0 0 20 20">
    <path d="M5 4a2 2 0 012-2h6a2 2 0 012 2v3.586l1.707 1.707A1 1 0 0117 10v1a1 1 0 01-1 1h-4v5a1 1 0 11-2 0v-5H6a1 1 0 01-1-1v-1a1 1 0 01.293-.707L7 7.586V4z" />
  </svg>
{/if}
```

6. In collapsed view, show due date if set (near type badge):
```svelte
{#if entry.dueDate}
  <span class="text-xs text-gray-500">{entry.dueDate}</span>
{/if}
```

7. In expanded view, add pin button and due date picker (in the flex row with type and delete):
```svelte
<div class="flex items-center gap-3">
  <button
    type="button"
    onclick={handleTogglePin}
    class="p-2 rounded-lg hover:bg-gray-100 {entry.pinned ? 'text-yellow-500' : 'text-gray-400'}"
    aria-label={entry.pinned ? 'Unpin entry' : 'Pin entry'}
  >
    <svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
      <path d="M5 4a2 2 0 012-2h6a2 2 0 012 2v3.586l1.707 1.707A1 1 0 0117 10v1a1 1 0 01-1 1h-4v5a1 1 0 11-2 0v-5H6a1 1 0 01-1-1v-1a1 1 0 01.293-.707L7 7.586V4z" />
    </svg>
  </button>

  <div>
    <label for="due-date-{entry.id}" class="block text-sm font-medium text-gray-700 mb-1">Due Date</label>
    <input
      id="due-date-{entry.id}"
      type="date"
      value={editDueDate}
      onchange={handleDueDateChange}
      class="px-3 py-2 border border-gray-200 rounded-lg text-base focus:outline-none focus:ring-2 focus:ring-blue-500"
    />
  </div>
</div>
```

**EntryList.svelte changes:**

1. Separate entries into pinned and unpinned:
```typescript
let pinnedEntries = $derived(entries.filter(e => e.pinned));
let unpinnedEntries = $derived(entries.filter(e => !e.pinned));
```

2. Render pinned section first if there are any:
```svelte
{#if pinnedEntries.length > 0}
  <div class="mb-4">
    <h2 class="text-sm font-medium text-gray-500 uppercase tracking-wide mb-2 px-4 md:px-0">Pinned</h2>
    <div class="space-y-0 md:space-y-3">
      {#each pinnedEntries as entry (entry.id)}
        <EntryCard {entry} />
      {/each}
    </div>
  </div>
{/if}

{#if unpinnedEntries.length > 0}
  <div class="space-y-0 md:space-y-3">
    {#each unpinnedEntries as entry (entry.id)}
      <EntryCard {entry} />
    {/each}
  </div>
{/if}

{#if entries.length === 0}
  <!-- existing empty state -->
{/if}
```
  </action>
  <verify>Run `npm run dev`, test:
1. Click pin button in expanded view - entry moves to pinned section
2. Click again - entry moves back to regular list
3. Set due date - shows on collapsed card
4. Clear due date - disappears from card</verify>
  <done>Pin toggle works, due date picker works, pinned entries appear in dedicated section at top</done>
</task>

</tasks>

<verification>
1. `npm run check` passes
2. Pin button toggles entry.pinned state
3. Due date picker updates entry.dueDate
4. Pinned section appears at top of list with pinned entries
5. Pin icon visible on collapsed pinned entries
6. Due date visible on collapsed entries when set
</verification>

<success_criteria>
- User can toggle pin status with visual feedback (ORG-01)
- User can set/clear due date using native date picker (ORG-02)
- Pinned entries appear in labeled section at top of list (ORG-03)
- Due date displays on entry card in collapsed view
</success_criteria>

<output>
After completion, create `.planning/phases/04-tags/04-02-SUMMARY.md`
</output>
