42 lines
1.6 KiB
Markdown
42 lines
1.6 KiB
Markdown
# SPEC — Money privacy (eye button)
|
|
|
|
**Produto:** Rently / RentCharge
|
|
**Data:** 2026-09-19
|
|
**Status:** implemented (prod + test)
|
|
**Versão:** 007.2026
|
|
**Operador:** Roger
|
|
|
|
**Relacionados:** `SPEC-SYSTEM-DASHBOARD.md` · `SPEC-SESSION-2026-09-19.md`
|
|
|
|
---
|
|
|
|
## Purpose
|
|
|
|
Operators often work in open offices. Euro amounts start **hidden** (`€ ••••`). One control (header + page toolbars) reveals or hides **all** sensitive amounts together. After **30 seconds** idle, amounts hide again.
|
|
|
|
## UI
|
|
|
|
| Control | Location |
|
|
|---------|----------|
|
|
| Show € / Hide € | AppShell header (all authenticated pages) |
|
|
| Same button | Page toolbars (Dashboard, Residents, Mapa, Receivables, …) |
|
|
|
|
## Technical contract
|
|
|
|
1. Module flag: `frontend/src/lib/moneyFormat.ts` — `euro()`, `privacyMoneyLabel()`, `setMoneyHiddenFlag()`.
|
|
2. Flag changes **notify** subscribers (`subscribeMoneyHidden`).
|
|
3. React: `useMoneyPrivacyRender()` / `useMoneyPrivacy()` use `useSyncExternalStore` so components re-render when the eye toggles.
|
|
4. **Why not only AppShell?** Next.js App Router does not re-render the page slot when a Client layout updates state. Every page that displays euros must subscribe (or use a child that does).
|
|
|
|
## Rules
|
|
|
|
- Print / statement handouts use `euroVisible()` (never masked).
|
|
- Counts and percentages are not masked.
|
|
- Default on load: **hidden**.
|
|
|
|
## Acceptance
|
|
|
|
1. Dashboard: eye toggles amounts.
|
|
2. `/residents`, `/mapa`, `/receivables`, resident detail: same toggle updates amounts without navigation.
|
|
3. Idle ~30s → amounts hide again.
|
|
4. Prod (`:3000`) and test (`:3010`) behave the same.
|