--- plan: 5-PLAN-01 feature: Quick Quantity Adjustment status: ready estimated_tasks: 5 total_lines: ~450 --- # Phase 5 Plan 01: Quick Quantity Adjustment ## Overview Implement hybrid quantity adjustment UI combining persistent +/- buttons with tap-to-edit on number display. Eliminates modal friction for check-in/check-out workflows by allowing both button-based increment/decrement AND direct number input via tap-to-edit inline. ## Tasks ### Task 1: Refactor QuantityDisplay Component (UI Layer) - **File:** frontend/components/inventory/QuantityDisplay.tsx - **Component:** `QuantityDisplay(itemId: string, currentQuantity: number, onQuantityChange: (newQty: number) => Promise) → JSX.Element` - **Lines:** ~120 - **Description:** Create editable quantity display with tap-to-edit mode. Render number as pressable text that toggles edit mode; show inline input field with +/- buttons flanking the number. - **Acceptance Criteria:** - [ ] Normal state: displays quantity as tappable text - [ ] Tap triggers edit mode: input field + +/- buttons visible - [ ] +/- buttons increment/decrement in-field value without API call (optimistic UI) - [ ] Blur or Enter key commits change to backend via `onQuantityChange` - [ ] Escape key cancels edit without changes - [ ] Input only accepts positive integers - [ ] Accessibility: proper ARIA labels on buttons, input has focus indicators - [ ] Unit tests pass (Vitest) ### Task 2: Create useQuantityAdjustment Hook - **File:** frontend/hooks/useQuantityAdjustment.ts - **Hook:** `useQuantityAdjustment(itemId: string, initialQuantity: number) → { quantity: number; isLoading: boolean; error: string | null; adjustQuantity: (delta: number | absolute: number) => Promise; resetError: () => void }` - **Lines:** ~80 - **Description:** Custom hook managing quantity state, API calls, optimistic updates, and error handling. Supports both delta (increment/decrement) and absolute (direct input) adjustments. - **Acceptance Criteria:** - [ ] Optimistic UI: state updates immediately; reverts on API failure - [ ] API call to PATCH /items/{itemId} with new quantity - [ ] Handles network errors gracefully with user-facing message - [ ] Validates quantity >= 0 - [ ] Debounces rapid successive calls (100ms) - [ ] Unit tests cover success, failure, validation scenarios ### Task 3: Update Inventory Page Main UI (Integration) - **File:** frontend/app/inventory/page.tsx - **Component:** Update inventory item list rendering section - **Lines:** ~60 - **Description:** Integrate new QuantityDisplay component into main inventory grid/list. Replace or augment existing quantity display with hybrid tap-to-edit UI. - **Acceptance Criteria:** - [ ] Each item row displays new QuantityDisplay component - [ ] Quantity changes persist immediately (no modal needed) - [ ] Layout remains responsive on mobile/desktop - [ ] Spinner shows during API call - [ ] Error toast appears on failure - [ ] No modal opens for quantity adjustment - [ ] Integration tests confirm full workflow ### Task 4: Backend Endpoint Enhancement (PATCH /items/{itemId}) - **File:** backend/routers/items.py - **Endpoint:** `PATCH /items/{itemId}` with body `{ quantity: int }` - **Function:** `update_item_quantity(itemId: str, body: UpdateQuantityRequest, auth: User) → ItemResponse` - **Lines:** ~40 - **Description:** Ensure endpoint handles direct quantity updates (no modal validation needed). Create audit log entry for quantity change. - **Acceptance Criteria:** - [ ] Accepts POST/PATCH with `{ quantity: int }` - [ ] Validates quantity >= 0 - [ ] Creates AuditLog entry with old_qty → new_qty delta - [ ] Returns updated Item with new quantity - [ ] Authorization: users can adjust inventory they have access to - [ ] Unit tests confirm audit logging ### Task 5: Integration & E2E Tests - **File:** frontend/tests/inventory/quick-adjust.test.ts - **Test:** Full workflow: tap number → edit → +/- button → commit - **Lines:** ~150 - **Description:** End-to-end test of quantity adjustment workflow without modal. Verify UI state transitions, API calls, error handling. - **Acceptance Criteria:** - [ ] Test case: tap number displays edit mode UI - [ ] Test case: +/- buttons change input value (no API yet) - [ ] Test case: Enter key commits, calls API, updates UI - [ ] Test case: Error from API shows toast, reverts quantity - [ ] Test case: Escape cancels without API call - [ ] All assertions pass (Vitest) - [ ] Backend integration test: PATCH /items/{itemId} creates audit log ## Dependencies - Task 1 (UI) must complete before Task 3 (integration) - Task 2 (hook) must complete before Task 1 (UI needs the hook) - Task 4 (backend endpoint) can run in parallel with Tasks 1-2 - Task 5 (tests) depends on Tasks 1-4 ## Testing Strategy - **Unit tests:** QuantityDisplay component (Vitest), useQuantityAdjustment hook (Vitest) - **Integration tests:** Inventory page with QuantityDisplay (Vitest) - **Backend tests:** PATCH endpoint audit logging (Pytest) - **E2E:** Manual verification on mobile device (tap number, edit, +/-, commit) ## Blockers & Workarounds - **Mobile tap detection:** Ensure click/tap handlers work consistently on iOS/Android. Use `onClick` + `onTouchEnd` for maximum compatibility. - **Input validation:** Client-side validation prevents invalid input; backend validation is final authority. - **Concurrent edits:** If user edits quantity twice rapidly, second edit overwrites first. Acceptable per Phase 5 scope (single-user offline scenario).