Phase 02: Core CRUD - 4 plans in 4 waves - 3 parallel-ready (Wave 1-3 sequential), 1 checkpoint - Ready for execution
219 lines
6.8 KiB
Markdown
219 lines
6.8 KiB
Markdown
---
|
|
phase: 02-core-crud
|
|
plan: 01
|
|
type: execute
|
|
wave: 1
|
|
depends_on: []
|
|
files_modified:
|
|
- src/routes/+page.server.ts
|
|
- src/lib/server/db/repository.ts
|
|
- src/app.css
|
|
autonomous: true
|
|
|
|
must_haves:
|
|
truths:
|
|
- "Form actions accept POST requests for create, update, delete, toggleComplete"
|
|
- "Repository has getOrdered method returning tasks-first, newest-within-type"
|
|
- "Base font size is 16px (1rem) respecting browser settings"
|
|
artifacts:
|
|
- path: "src/routes/+page.server.ts"
|
|
provides: "SvelteKit form actions for CRUD operations"
|
|
exports: ["actions", "load"]
|
|
- path: "src/lib/server/db/repository.ts"
|
|
provides: "Extended repository with getOrdered method"
|
|
contains: "getOrdered"
|
|
- path: "src/app.css"
|
|
provides: "Base styling for accessibility"
|
|
contains: "font-size: 100%"
|
|
key_links:
|
|
- from: "src/routes/+page.server.ts"
|
|
to: "src/lib/server/db/repository.ts"
|
|
via: "entryRepository import"
|
|
pattern: "import.*entryRepository.*from.*repository"
|
|
---
|
|
|
|
<objective>
|
|
Create SvelteKit form actions for all CRUD operations and establish base styling for accessibility.
|
|
|
|
Purpose: Provides the server-side API that all UI components will use, ensuring progressive enhancement (forms work without JavaScript) and establishing accessible typography.
|
|
|
|
Output: Form actions (create, update, delete, toggleComplete), extended repository with ordering, base CSS with 16px minimum font.
|
|
</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
|
|
@.planning/phases/02-core-crud/02-CONTEXT.md
|
|
@.planning/phases/02-core-crud/02-RESEARCH.md
|
|
@src/lib/server/db/repository.ts
|
|
@src/lib/server/db/schema.ts
|
|
@src/routes/+page.server.ts
|
|
</context>
|
|
|
|
<tasks>
|
|
|
|
<task type="auto">
|
|
<name>Task 1: Extend repository with getOrdered method</name>
|
|
<files>src/lib/server/db/repository.ts</files>
|
|
<action>
|
|
Add a `getOrdered` method to EntryRepository interface and SQLiteEntryRepository implementation:
|
|
|
|
```typescript
|
|
getOrdered(options?: { showCompleted?: boolean }): Entry[]
|
|
```
|
|
|
|
Behavior:
|
|
- If showCompleted is false (default), exclude entries where status='done'
|
|
- Order by: type ASC (task before thought alphabetically), then createdAt DESC (newest first)
|
|
- Use drizzle-orm operators: `asc`, `ne` (import from drizzle-orm)
|
|
|
|
Implementation pattern from research:
|
|
```typescript
|
|
import { eq, desc, asc, ne } from 'drizzle-orm';
|
|
|
|
getOrdered(options: { showCompleted?: boolean } = {}): Entry[] {
|
|
const { showCompleted = false } = options;
|
|
|
|
let query = db.select().from(entries);
|
|
|
|
if (!showCompleted) {
|
|
query = query.where(ne(entries.status, 'done'));
|
|
}
|
|
|
|
return query
|
|
.orderBy(asc(entries.type), desc(entries.createdAt))
|
|
.all();
|
|
}
|
|
```
|
|
</action>
|
|
<verify>
|
|
Run TypeScript check: `npm run check` passes without errors.
|
|
Test manually: Start dev server, database should still work with existing getAll method.
|
|
</verify>
|
|
<done>Repository has getOrdered method that filters completed entries and orders tasks-first, newest-within-type</done>
|
|
</task>
|
|
|
|
<task type="auto">
|
|
<name>Task 2: Create form actions for CRUD operations</name>
|
|
<files>src/routes/+page.server.ts</files>
|
|
<action>
|
|
Replace current page.server.ts with full CRUD form actions. Keep the existing load function but modify to use getOrdered.
|
|
|
|
Actions to implement:
|
|
|
|
1. **create**: Accept title (optional), content (required), type (task|thought, default thought)
|
|
- Validate content not empty
|
|
- Return { success: true, entryId } on success
|
|
- Return fail(400, { error, title, content, type }) on validation failure
|
|
|
|
2. **update**: Accept id (required), plus any of: title, content, type, status
|
|
- Return fail(400) if no id
|
|
- Return fail(404) if entry not found
|
|
- Return { success: true } on success
|
|
|
|
3. **delete**: Accept id (required)
|
|
- Return fail(400) if no id
|
|
- Return fail(404) if entry not found
|
|
- Return { success: true } on success
|
|
|
|
4. **toggleComplete**: Accept id (required)
|
|
- Toggle status between 'open' and 'done'
|
|
- Return fail(400) if no id
|
|
- Return { success: true } on success
|
|
|
|
Import `fail` from '@sveltejs/kit'.
|
|
Import `entryRepository` from '$lib/server/db/repository'.
|
|
|
|
Update load function:
|
|
- Use getOrdered() instead of getAll()
|
|
- Pass showCompleted: false for now (will be dynamic later)
|
|
</action>
|
|
<verify>
|
|
Run `npm run check` - TypeScript passes.
|
|
Test with curl:
|
|
```bash
|
|
# Create
|
|
curl -X POST http://localhost:5173/?/create -d "content=Test entry&type=task"
|
|
# Should return redirect (SvelteKit form action behavior)
|
|
```
|
|
</verify>
|
|
<done>All four form actions (create, update, delete, toggleComplete) exist and handle validation/errors correctly</done>
|
|
</task>
|
|
|
|
<task type="auto">
|
|
<name>Task 3: Establish accessible base styling</name>
|
|
<files>src/app.css</files>
|
|
<action>
|
|
Update app.css to establish accessible base typography:
|
|
|
|
```css
|
|
@import 'tailwindcss';
|
|
|
|
/* Ensure minimum 16px base for accessibility (UX-02) */
|
|
html {
|
|
font-size: 100%; /* 16px default, respects user browser settings */
|
|
}
|
|
|
|
body {
|
|
font-size: 1rem; /* 16px minimum */
|
|
line-height: 1.5;
|
|
-webkit-font-smoothing: antialiased;
|
|
-moz-osx-font-smoothing: grayscale;
|
|
}
|
|
|
|
/* Safe area padding for mobile devices with notches */
|
|
.safe-bottom {
|
|
padding-bottom: env(safe-area-inset-bottom, 0px);
|
|
}
|
|
|
|
/* Utility for adequate touch targets (44x44px minimum per WCAG) */
|
|
.touch-target {
|
|
min-height: 44px;
|
|
min-width: 44px;
|
|
}
|
|
```
|
|
|
|
This ensures:
|
|
- Base font respects user's browser zoom settings (100% = 16px default)
|
|
- All text uses rem, so user scaling works
|
|
- Mobile safe areas handled for bottom capture bar
|
|
- Touch target utility class available
|
|
</action>
|
|
<verify>
|
|
Start dev server: `npm run dev`
|
|
Open in browser, inspect html element - font-size should be 100%.
|
|
Inspect body - font-size should be 1rem (16px computed).
|
|
</verify>
|
|
<done>Base CSS establishes 16px minimum font, safe area insets, and touch target utility</done>
|
|
</task>
|
|
|
|
</tasks>
|
|
|
|
<verification>
|
|
After all tasks complete:
|
|
|
|
1. **TypeScript**: `npm run check` passes
|
|
2. **Dev server**: `npm run dev` starts without errors
|
|
3. **Repository**: getOrdered method exists and returns entries in correct order
|
|
4. **Form actions**: All four actions exist in +page.server.ts
|
|
5. **CSS**: Base font is 16px (1rem), safe-bottom and touch-target classes defined
|
|
</verification>
|
|
|
|
<success_criteria>
|
|
- Repository has getOrdered(options?) method with showCompleted filter and tasks-first ordering
|
|
- Form actions handle create (with validation), update, delete, and toggleComplete
|
|
- Base CSS ensures 16px minimum font and provides mobile-friendly utilities
|
|
- TypeScript compilation passes
|
|
- All requirements groundwork laid: CORE-01 through CORE-06, UX-02
|
|
</success_criteria>
|
|
|
|
<output>
|
|
After completion, create `.planning/phases/02-core-crud/02-01-SUMMARY.md`
|
|
</output>
|