Fix category edit stale UI and simplify categories state#12
Conversation
There was a problem hiding this comment.
Pull request overview
Refactors the PWA Categories screen state to eliminate stale UI during category edits by centralizing dialog workflows in hooks and updating the TanStack Query cache on successful saves, while also adding VS Code debug configuration to support PWA attach debugging against a .env-derived URL.
Changes:
- Extracted category edit + auto-match rule dialog state/logic into
useCategoryEditDialoganduseAutoMatchRulesDialog. - Updated the category update mutation to patch the
['categories']query cache immediately and invalidate without an immediate refetch. - Added/updated repo docs and VS Code debug task/launch configs for PWA Chrome attach debugging.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| apps/pwa/src/features/categories/hooks/useCategoryEditDialog.ts | New hook to manage edit-dialog state with ref-synced draft reads for save. |
| apps/pwa/src/features/categories/hooks/useCategoriesMutations.ts | Update mutation now patches ['categories'] cache and invalidates without refetch. |
| apps/pwa/src/features/categories/hooks/useAutoMatchRulesDialog.ts | New hook for auto-match rule dialog open/toggle state + error handling. |
| apps/pwa/src/features/categories/CategoriesScreen.tsx | Simplifies screen to composition layer using the two new dialog hooks. |
| README.md | Documents updated Categories edit behavior (cache update + stale invalidation). |
| AGENTS.md | Adds state-management guidance and documents Categories edit cache policy. |
| .vscode/tasks.json | Adds task to open Chrome with remote debugging against .env port. |
| .vscode/launch.json | Adds PWA Chrome attach debug configuration using the new task. |
| .agents/notes.md | Captures notes on avoiding stale writes/refetch overwrites and VS Code PWA debugging. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| { | ||
| "label": "Tithe PWA: Open Chrome (.env URL)", | ||
| "type": "shell", | ||
| "command": "PORT=$(node -e \"const fs=require('node:fs'); const env=fs.existsSync('.env')?fs.readFileSync('.env','utf8'):''; const read=(k)=>{const m=env.match(new RegExp('^'+k+'=(.*)$','m')); return m?m[1].trim().replace(/^['\\\"]|['\\\"]$/g,''):'';}; const p=read('PWA_PORT')||read('VITE_PWA_PORT')||'5173'; process.stdout.write(p);\") && URL=\"http://localhost:${PORT}\" && open -na \"Google Chrome\" --args --remote-debugging-port=9222 --user-data-dir=/tmp/chrome-debug-tithe \"$URL\"", |
There was a problem hiding this comment.
This task hard-codes macOS-only tooling (open -na "Google Chrome", /tmp/...) and relies on POSIX shell syntax, so it will fail on Windows/Linux or when VS Code uses a non-bash shell. Consider using VS Code task OS overrides (windows/linux/osx) with equivalent commands (or a cross-platform opener like npx open) and setting an explicit options.shell if needed.
| "command": "PORT=$(node -e \"const fs=require('node:fs'); const env=fs.existsSync('.env')?fs.readFileSync('.env','utf8'):''; const read=(k)=>{const m=env.match(new RegExp('^'+k+'=(.*)$','m')); return m?m[1].trim().replace(/^['\\\"]|['\\\"]$/g,''):'';}; const p=read('PWA_PORT')||read('VITE_PWA_PORT')||'5173'; process.stdout.write(p);\") && URL=\"http://localhost:${PORT}\" && open -na \"Google Chrome\" --args --remote-debugging-port=9222 --user-data-dir=/tmp/chrome-debug-tithe \"$URL\"", | |
| "command": "PORT=$(node -e \"const fs=require('node:fs'); const env=fs.existsSync('.env')?fs.readFileSync('.env','utf8'):''; const read=(k)=>{const m=env.match(new RegExp('^'+k+'=(.*)$','m')); return m?m[1].trim().replace(/^['\\\"]|['\\\"]$/g,''):'';}; const p=read('PWA_PORT')||read('VITE_PWA_PORT')||'5173'; process.stdout.write(p);\") && URL=\"http://localhost:${PORT}\" && google-chrome --remote-debugging-port=9222 --user-data-dir=/tmp/chrome-debug-tithe \"$URL\"", | |
| "options": { | |
| "shell": { | |
| "executable": "/bin/bash", | |
| "args": [ | |
| "-c" | |
| ] | |
| } | |
| }, | |
| "osx": { | |
| "command": "PORT=$(node -e \"const fs=require('node:fs'); const env=fs.existsSync('.env')?fs.readFileSync('.env','utf8'):''; const read=(k)=>{const m=env.match(new RegExp('^'+k+'=(.*)$','m')); return m?m[1].trim().replace(/^['\\\"]|['\\\"]$/g,''):'';}; const p=read('PWA_PORT')||read('VITE_PWA_PORT')||'5173'; process.stdout.write(p);\") && URL=\"http://localhost:${PORT}\" && open -na \"Google Chrome\" --args --remote-debugging-port=9222 --user-data-dir=/tmp/chrome-debug-tithe \"$URL\"" | |
| }, | |
| "windows": { | |
| "options": { | |
| "shell": { | |
| "executable": "C:\\\\Windows\\\\System32\\\\WindowsPowerShell\\\\v1.0\\\\powershell.exe", | |
| "args": [ | |
| "-NoProfile", | |
| "-ExecutionPolicy", | |
| "Bypass", | |
| "-Command" | |
| ] | |
| } | |
| }, | |
| "command": "$PORT = node -e \"const fs=require('node:fs'); const env=fs.existsSync('.env')?fs.readFileSync('.env','utf8'):''; const read=(k)=>{const m=env.match(new RegExp('^'+k+'=(.*)$','m')); return m?m[1].trim().replace(/^['\\\"']|['\\\"']$/g,''):'';}; const p=read('PWA_PORT')||read('VITE_PWA_PORT')||'5173'; process.stdout.write(p);\"; $Url = \"http://localhost:$PORT\"; Start-Process \"chrome\" \"--remote-debugging-port=9222 --user-data-dir=$env:TEMP\\chrome-debug-tithe $Url\"" | |
| }, |
| "name": "Tithe PWA: Launch (Chrome)", | ||
| "type": "pwa-chrome", | ||
| "request": "attach", | ||
| "port": 9222, | ||
| "preLaunchTask": "Tithe PWA: Open Chrome (.env URL)", |
There was a problem hiding this comment.
The configuration name says "Launch" but the debugger request is actually an "attach" to an existing Chrome instance. Rename the config to "Attach" (or switch to a true launch config) to avoid confusing users when selecting debug targets.
Summary
useCategoryEditDialog,useAutoMatchRulesDialog) to reduce component-level state complexity.env-derived URLValidation
pnpm lintvia hook)