ali-ahnaf / ali-ahnaf/pocket_pixel
Settings: "Disable AI prompt" toggle to default transaction logging to manual entry
- Dominant language
- TypeScript
- Stars
- 14
- Forks
- 91
- PR merge metrics
- No merged PRs in 30d
Description
## Summary
Add a user setting called **"Disable AI prompt"** as a toggle on the Settings/Profile page.
When this setting is **ON**, opening the "log a transaction" modal should skip the AI prompt screen and go **straight to the manual entry form** every time. When it is **OFF** (the default), the modal keeps its current behaviour and shows the AI prompt screen first.
The setting must be **saved per user in the database** so it persists across logins and devices.
---
## Why we are building this
Some users prefer to type in their transactions by hand and do not want to use (or pay tokens for) the AI prompt. Today the modal always opens on the AI prompt screen and the user has to flip the manual toggle every single time. This setting lets them make manual entry the permanent default.
---
## Where things live today (read this first)
The transaction logging modal already supports both modes. Look at [`packages/ui/src/components/LogResourceModal.tsx`](packages/ui/src/components/LogResourceModal.tsx):
- Line ~19: `const [manualEntry, setManualEntry] = useState(false);` — this `false` is why it always starts on the AI prompt screen.
- Line ~211: the toggle button that flips `manualEntry`.
- The AI prompt UI renders when `!manualEntry`; the manual form renders when `manualEntry`.
**The whole feature is essentially: make that initial `false` come from a saved user setting instead of being hard-coded.**
---
## Acceptance criteria
- [ ] A new toggle **"Disable AI prompt"** appears on the Settings/Profile page (`packages/ui/src/app/profile/`).
- [ ] Toggling it immediately saves the value to the backend (via the existing update-user endpoint) and shows the saved state on reload.
- [ ] When the setting is **ON**, `LogResourceModal` opens directly in manual-entry mode every time it is opened.
- [ ] When the setting is **OFF**, behaviour is unchanged (opens on the AI prompt screen).
- [ ] The user can still manually flip between AI/manual inside the modal regardless of the setting — the setting only controls the **default** the modal opens with.
- [ ] The value is stored in the database on the `User` entity and survives logout/login.
---
## Implementation steps
### 1. Database / Entity
In [`packages/api/src/entities/User.entity.ts`](packages/api/src/entities/User.entity.ts) add a new column:
```ts
@Column({ type: 'boolean', default: false })
disableAiPrompt: boolean;
```
Then create and run a migration (from the repo root, per CLAUDE.md):
```bash
npm run migration:run
```
> Reminder: a new migration file is required for the new column — do not edit the DB by hand.
### 2. Shared contract (DTO)
DTOs that cross API↔UI live in `packages/shared/src/contracts/`. Add `disableAiPrompt?: boolean` to the relevant user DTO (request + response), re-export it, then rebuild shared:
```bash
npm run build:shared
```
### 3. API service + route
- In [`packages/api/src/services/users.service.ts`](packages/api/src/services/users.service.ts), add `disableAiPrompt?: boolean` to the `UpdateUserInput` interface and copy it across in `update()` the same way `name`/`email`/`avatar` are handled (`if (input.disableAiPrompt !== undefined) user.disableAiPrompt = input.disableAiPrompt;`).
- In [`packages/api/src/routes/users/put-user.route.ts`](packages/api/src/routes/users/put-user.route.ts), add `disableAiPrompt: Joi.boolean()` to the `updateUserSchema`.
- The GET user route ([`get-user.route.ts`](packages/api/src/routes/users/get-user.route.ts)) returns the full user, so the new field will be included automatically — just confirm it is not stripped out.
> Per project rules: **only save the specific allowed fields** — never persist the raw request body. No try/catch in routes; let the global error handler deal with errors.
### 4. UI – API client
In [`packages/ui/src/lib/api/ProfileApi.ts`](packages/ui/src/lib/api/ProfileApi.ts):
- Add `disableAiPrompt: boolean;` to the `ApiUser` interface.
- Add `disableAiPrompt?: boolean` to the `updateUser(...)` payload type.
### 5. UI – Settings toggle
On the profile/settings page (`packages/ui/src/app/profile/`), add a labelled toggle **"Disable AI prompt"** that reads the current `disableAiPrompt` value and calls `updateUser(userId, { disableAiPrompt: newValue })` when changed. Reuse the existing toggle styling used inside `LogResourceModal` (line ~218) so it matches the pixel design.
### 6. UI – Apply the setting in the modal
In [`packages/ui/src/components/LogResourceModal.tsx`](packages/ui/src/components/LogResourceModal.tsx):
- Get the current user's `disableAiPrompt` value (from the auth/user state already available on the page).
- Initialise `manualEntry` from it, e.g. `useState(disableAiPrompt)`, and make sure the modal resets to that value each time it is **opened** (the modal already resets state when it opens around line ~49 — set `manualEntry` to `disableAiPrompt` there instead of `false`).
---
## Testing / Definition of Done
- [ ] Toggle OFF → open log modal → AI prompt screen shows first (unchanged).
- [ ] Toggle ON → open log modal → manual form shows immediately.
- [ ] Reload the app / log out and back in → the toggle keeps its saved value.
- [ ] Inside the modal you can still switch to the other mode manually.
- [ ] Run Prettier on every changed file (`npx prettier --write `).
## Out of scope
- No changes to how the AI prompt itself works or to token usage tracking.
- No bulk/global admin setting — this is per individual user only.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with packages/ui/src/components/LogResourceModal.tsx and packages/ui/src/app/profile/, then follow the user update flow through packages/ui/src/lib/api/ProfileApi.ts, packages/api/src/routes/users/put-user.route.ts, packages/api/src/services/users.service.ts, and packages/api/src/entities/User.entity.ts. Add the shared DTO field under packages/shared/src/contracts/ and a migration for the User column. Done means the setting persists per user, controls the modal's default mode on each open, and the listed manual checks pass.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- nextjs, node.js, react, typescript
- Domain
- database, full-stack
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 58/100