fix(07): revise plans based on checker feedback
This commit is contained in:
@@ -15,7 +15,7 @@ requirements: [QADD-01, QADD-03]
|
|||||||
|
|
||||||
must_haves:
|
must_haves:
|
||||||
truths:
|
truths:
|
||||||
- "A quick_add_items table exists with user_id, name, icon, and sort_order columns"
|
- "The API accepts and returns quick-add items with name, icon, and sort_order in all CRUD responses"
|
||||||
- "API returns a list of quick-add items for the authenticated user"
|
- "API returns a list of quick-add items for the authenticated user"
|
||||||
- "API can create, update, and delete quick-add items"
|
- "API can create, update, and delete quick-add items"
|
||||||
- "Quick-add items are user-scoped — one user cannot see another's items"
|
- "Quick-add items are user-scoped — one user cannot see another's items"
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ Output: QuickAddPage, QuickAddPicker component, useQuickAdd hook, API client add
|
|||||||
@frontend/src/pages/TemplatePage.tsx
|
@frontend/src/pages/TemplatePage.tsx
|
||||||
@frontend/src/pages/DashboardPage.tsx
|
@frontend/src/pages/DashboardPage.tsx
|
||||||
@frontend/src/components/AppLayout.tsx
|
@frontend/src/components/AppLayout.tsx
|
||||||
|
@frontend/src/components/EmptyState.tsx
|
||||||
@frontend/src/App.tsx
|
@frontend/src/App.tsx
|
||||||
@frontend/src/i18n/en.json
|
@frontend/src/i18n/en.json
|
||||||
@frontend/src/i18n/de.json
|
@frontend/src/i18n/de.json
|
||||||
@@ -187,7 +188,7 @@ const navItems = [
|
|||||||
- Table with columns: Name, Icon, Actions (Edit pencil button, Delete trash button)
|
- Table with columns: Name, Icon, Actions (Edit pencil button, Delete trash button)
|
||||||
- Edit mode: clicking edit turns row into inline inputs, Save/Cancel buttons
|
- Edit mode: clicking edit turns row into inline inputs, Save/Cancel buttons
|
||||||
- Delete: immediate delete (no confirmation needed for library items — they are presets, not budget data)
|
- Delete: immediate delete (no confirmation needed for library items — they are presets, not budget data)
|
||||||
- Empty state: use EmptyState component with Zap icon, heading "No saved items", subtext "Save your frequently-used one-off categories here for quick access."
|
- Empty state: use the project's existing `EmptyState` component (`frontend/src/components/EmptyState.tsx`) with Zap icon, heading "No saved items", subtext "Save your frequently-used one-off categories here for quick access."
|
||||||
|
|
||||||
4. **Sidebar nav** (`frontend/src/components/AppLayout.tsx`):
|
4. **Sidebar nav** (`frontend/src/components/AppLayout.tsx`):
|
||||||
Add nav item after template: `{ path: '/quick-add', label: t('nav.quickAdd'), icon: Zap }`
|
Add nav item after template: `{ path: '/quick-add', label: t('nav.quickAdd'), icon: Zap }`
|
||||||
@@ -256,9 +257,11 @@ const navItems = [
|
|||||||
- On mount, fetch quick-add items via `quickAdd.list()` (direct API call, not hook — this is a lightweight picker, not a full CRUD page)
|
- On mount, fetch quick-add items via `quickAdd.list()` (direct API call, not hook — this is a lightweight picker, not a full CRUD page)
|
||||||
- Render a Popover (from shadcn/ui) with trigger button: icon `Zap` + text "Quick Add" (from i18n `quickAdd.addOneOff`)
|
- Render a Popover (from shadcn/ui) with trigger button: icon `Zap` + text "Quick Add" (from i18n `quickAdd.addOneOff`)
|
||||||
- Inside popover: list of quick-add items, each as a clickable row showing icon + name
|
- Inside popover: list of quick-add items, each as a clickable row showing icon + name
|
||||||
- On click: create a budget item via `budgetItems.create(budgetId, { category_id: null, item_tier: 'one_off', notes: item.name })` — Since quick-add items are independent presets (not linked to categories), the picker creates a one-off budget item. The backend CreateBudgetItem handler must accept this. **However**, looking at the existing BudgetItem model, category_id is required (UUID NOT NULL in DB). So instead:
|
- On click, resolve the category_id then create the budget item. Since category_id is NOT NULL in the DB, the picker must find or create a matching category:
|
||||||
- The picker should first check if a category with the same name exists for the user. If not, create one via `categories.create({ name: item.name, type: 'variable_expense', icon: item.icon })`, then create the budget item with that category_id and `item_tier: 'one_off'`.
|
1. Fetch the user's categories via `categories.list()`
|
||||||
- Alternatively (simpler): show the quick-add library items, and on click, find or create a matching category, then call `budgetItems.create(budgetId, { category_id, item_tier: 'one_off' })`.
|
2. Find a category whose name matches `item.name` (case-insensitive)
|
||||||
|
3. If no match, create one via `categories.create({ name: item.name, type: 'variable_expense', icon: item.icon })`
|
||||||
|
4. Call `budgetItems.create(budgetId, { category_id: resolvedCategoryId, item_tier: 'one_off' })` with the resolved category_id
|
||||||
- After creation: call `onItemAdded()` to refresh, close popover
|
- After creation: call `onItemAdded()` to refresh, close popover
|
||||||
- If quick-add library is empty: show a small message "No saved items" with a link to /quick-add
|
- If quick-add library is empty: show a small message "No saved items" with a link to /quick-add
|
||||||
- Add loading spinner on the clicked item while creating
|
- Add loading spinner on the clicked item while creating
|
||||||
|
|||||||
Reference in New Issue
Block a user