feat: Add eFiling Summary modal with LHDN-exact field mapping#4
feat: Add eFiling Summary modal with LHDN-exact field mapping#4vicksk13 wants to merge 20 commits into
Conversation
Adds a brandbook-derived dark theme alongside the existing light theme. Dark canvas stacked from brandbook --black (#1D1B2D) upward through --charcoal (#353140) for surface elevation. Text runs from brandbook --off-white (#FAF7F5) down to --mid-gray (#9A9498) for hierarchy. Brand red lifted from #B63B2C to #EB6E5E for WCAG AA contrast on dark backgrounds. Gold nudged to #C9993D for the same reason. Restores the Light/Dark toggle in Settings > Appearance. Theme preference persisted to localStorage. No logic, routing, or data changes — styling only.
Reorders navigation tabs across both mobile and desktop to prioritise Income as the primary entry point. Relief moves to second, Receipts third, Settings last. Default landing tab updated from Relief to Income. More tab renamed to Settings in both English and Bahasa Malaysia (Tetapan). Internal tab key unchanged — display label only. No logic, routing, state, or data handling was modified.
Reorders navigation tabs across both mobile and desktop to prioritise Income as the primary entry point. Relief moves to second, Receipts third, Settings last. Default landing tab updated from Relief to Income. More tab renamed to Settings in both English and Bahasa Malaysia (Tetapan). Internal tab key unchanged — display label only. No logic, routing, state, or data handling was modified.
… drawer Adds a two-part user guide system to help new users understand the MakeCents workflow without support intervention. Option B (first-launch modal): appears automatically on first login, tracked via localStorage["makecentstax-guide-seen"] so it shows exactly once. Covers all 4 steps — income, scan, manage, export. Dismissed via CTA or clicking outside. Both EN and BM strings included. Option C (persistent drawer): "How it works" entry in the desktop sidebar nav and a button in the mobile Income header. Opens a slide-in panel (right on desktop, bottom sheet on mobile) with the same 4 steps shown as a numbered flow with connecting lines. Always accessible after the modal is dismissed. No logic, data, or routing changes. Styling follows brandbook tokens throughout — DM Serif Display for headings, DM Sans for body, brand red accent, off-white backgrounds.
✅ Brandbook colours, DM Sans + DM Serif Display ✅ Light + dark mode with toggle in Settings ✅ Green removed, gold retained ✅ Nav order — Income → Relief → Receipts → Settings ✅ "More" renamed to Settings (EN + BM) ✅ First-launch guide modal + persistent How it works drawer
The How it works button was conditionally rendered only on the Income tab header on mobile, making it invisible on Receipts and Settings. Removed the tab === "income" guard so the button now appears in the header across all non-relief mobile tabs. Relief is unaffected — it uses its own full-screen header component. No logic or data changes. Styling unchanged.
✅ DM Sans + DM Serif Display (italic on numerals) ✅ Full brandbook colour tokens — light + dark ✅ Dark mode toggle in Settings ✅ Green removed everywhere, gold kept ✅ Nav order — Income → Relief → Receipts → Settings ✅ "More" → "Settings" (EN + BM) ✅ App opens on Income by default ✅ First-launch guide modal (once only, localStorage flagged) ✅ "How it works" drawer — desktop sidebar + mobile header ✅ Mobile "How it works" shows on all tabs, not just Income
Fixes three issues found during brandbook compliance audit of Dev.jsx:
1. BROKEN TRANSLATION KEY — L('your refund') called with a key that
didn't exist in TRANS (EN or BM), causing the hero card label to
display the raw string "your refund" in lowercase. Added:
EN: your_refund = "YOUR REFUND"
BM: your_refund = "BAYARAN BALIK ANDA"
Fixed both call sites (mobile Header + desktop ReliefTab KPI card)
to use L('your_refund').
2. MOBILE HOW IT WORKS MISSING ON RELIEF TAB — The Relief tab uses the
full <Header> stats component. Unlike the other 3 tabs, it had no
"How it works" button, contradicting the "shows on all tabs" spec.
Added onHowItWorks prop to Header, wired it to setGuideDrawer(true),
and placed the button in the top-right alongside the YA selector.
3. HARDCODED STALE OFF-WHITE — Desktop sidebar Scan Receipt button used
color: "#FBF7EE" (old brand value). Corrected to "#FAF7F5" (brandbook
off-white token) for both text color and icon color.
Font audit — all clear:
- DM Sans: Google Fonts import ✓, FONT constant ✓, html/body ✓
- DM Serif Display: 20 usages — 14 italic (all RM numerals) ✓,
6 upright (display headings, wordmark, empty states) ✓
- Zero Poppins/Fraunces remaining ✓
#ChangeStatus1your_refund key — EN: "YOUR REFUND", BM: "BAYARAN BALIK ANDA"✅ lines 597, 8392Both L('your refund') broken call sites fixed✅ lines 2863, 32143"How it works" on mobile Relief tab (onHowItWorks prop)✅ lines 2514, 2806, 28244#FBF7EE fully removed✅ zero hits5Replaced with brandbook #FAF7F5✅ lines 2482, 24876DM Sans + DM Serif Display constants✅ lines 412–4137Google Fonts import updated✅ line 48108html/body font-family = DM Sans✅ line 48169Nav order Income → Relief → Receipts → Settings (both layouts)✅ lines 2443–2446, 3129–313210App opens on Income tab✅ line 151211"More" → "Settings" EN + BM✅ lines 453, 69912First-launch guide modal + localStorage flag✅ lines 338, 1622, 291413Dark mode theme object✅ line 38714Dark mode toggle in Settings✅ lines 1487–1491, 2336, 433915No green tokens anywhere✅ zero hits16Gold retained (light + dark)✅ lines 378, 40117FONT_DISPLAY non-italic: only wordmark (22px) + welcome headline (42px)✅ exactly 218Poppins / Fraunces fully gone✅ zero hits
Adds a full-screen eFiling Guide modal accessible from Settings → Data & Export. The modal maps all user inputs to the corresponding LHDN BE form sections: - Section B: Employment income (B1a/b/c, D1, E1, E2) per employer - Section C: Rental income with deductible expenses - Aggregate income total - Section F: All relief claims with LHDN codes (C1–C24) and caps applied - Chargeable income computation - Tax payable using YA2025 progressive brackets with bracket highlighted - RM400 individual rebate applied where eligible (chargeable ≤ RM35,000) - MTD/PCB offset with final balance due or refund card Download PDF opens a print-ready HTML page in a new tab with auto print trigger. All labels are bilingual (EN/BM) following the app language selection. Calculations mirror existing app logic — same groupCapped, itemTotalRaw, BK brackets. Files changed: src/App.jsx
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2d19fbcf9d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const rm = (n) => `RM ${fmt(n)}`; | ||
|
|
||
| // ── Totals ─────────────────────────────────────────────── | ||
| const totalEmpIncome = incomes.reduce((s, i) => s + (i.amount || 0) + (i.bonus || 0) + (i.otherAllowances || 0), 0); |
There was a problem hiding this comment.
Avoid double-counting bonuses in filing totals
When an employment record has a bonus, this summary overstates income because IncomeTab.handleSave stores amount as the total of gross salary + bonus + other allowances, but this line adds i.bonus on top of i.amount again. That makes the eFiling summary's statutory income, chargeable income, tax computation, and final balance higher than the app's existing tax summary for any taxpayer who entered or scanned a bonus.
Useful? React with 👍 / 👎.
|
|
||
| const incomeRowsHTML = incomes.map((inc, idx) => { | ||
| return ` | ||
| ${(incomes.length > 1 || inc.employer) ? `<tr class="sec-hdr"><td colspan="2">${isBM ? "Majikan" : "Employer"}${incomes.length > 1 ? ` ${idx + 1}` : ""}: <strong>${inc.employer || "—"}</strong></td></tr>` : ""} |
There was a problem hiding this comment.
Escape user fields before writing the print window
If an employer name comes from an imported backup or the EA parser with HTML such as an event handler, clicking Download PDF writes it directly into a same-origin window.open document and executes it instead of displaying text. Please HTML-escape dynamic values before interpolating them into document.write; React's normal escaping does not apply in this generated HTML path.
Useful? React with 👍 / 👎.
…ef-rules Add YA2026/2027 relief updates: prompts, caps, UI logic and tests
…ef-rules-k65d89 Add YA2026 relief rules, adjust caps/UI and update scan prompt
Adds eFiling Guide modal (Settings → Export eFiling Summary) that mirrors the actual LHDN BE form pages exactly:
Includes Download PDF with print-ready layout. EN/BM bilingual.