Daily review 2026-07-01 - #66
Draft
NghaReformer wants to merge 2 commits into
Draft
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Daily Review — 2026-07-01
1. Bugs & Issues
CRITICAL
None found.
HIGH
H-1 — Undefined CSS custom properties
--orange,--blue,--redused across 9+ filesSeverity: High
Files (sample):
src/lib/components/playground/KpiStrip.svelte:76src/lib/playgrounds/amortization/components/ChartPanel.svelte:436,444,493,501,515,529,533src/lib/playgrounds/amortization/components/ScheduleTable.svelte:240,246,259src/lib/playgrounds/amortization/components/InputsPanel.svelte:604,605src/lib/playgrounds/bank-reconciliation/components/VarianceScale.svelte:230,260,261,331,335,370,416src/lib/playgrounds/bank-reconciliation/components/ScenarioWalkthrough.svelte:234,274src/lib/playgrounds/bank-reconciliation/components/TransactionJournal.svelte:382,383src/lib/playgrounds/bank-reconciliation/components/ReconciliationFlow.svelte:278src/lib/playgrounds/bank-reconciliation/components/LedgerPanel.svelte:175src/lib/playgrounds/bank-reconciliation/components/BankStatementPanel.svelte:175Explanation:
css-generator.tsemits--green,--amber,--error, and--accentamong others — but never--orange,--blue, or--red. These variables are undefined at runtime, so the hex fallback in everyvar(--orange, #f59e0b)/var(--blue, #3b82f6)/var(--red, #ef4444)is always used. The fallbacks are Tailwind palette values, not the design-system tokens (e.g.--amberis#f5a623, not#f59e0b;--erroris#f06070, not#ef4444). Theme changes will never reach these components.Suggested fix: Replace with the nearest defined token —
--orange→--amber,--blue→--accent,--red→--error. Updatecss-generator.tsif explicit semantic aliases are preferred.MEDIUM
M-1 — Client component imports from
$lib/server/db/typesSeverity: Medium
Files:
src/lib/components/feedback/FeedbackForm.svelte:7src/routes/api/feedback/validation.ts:1-5Explanation:
FeedbackForm.svelteusesimport type { FeedbackType, FeedbackSeverity } from '$lib/server/db/types'. Although TypeScript erasesimport typeat compile time, SvelteKit's Vite plugin enforces$lib/serverboundaries by static import analysis and may fail the build. Even if it passes today, it violates the architectural contract.validation.ts(a route co-location file) also imports from$lib/server/db/types, making it subtly server-coupled despite not being a*.server.tsfile.Suggested fix: Move the shared type-only definitions (
FeedbackType,FeedbackSeverity) out of$lib/server/db/types.tsinto a new$lib/types/feedback.ts. Server-only runtime code (Supabase calls, DB schemas) stays under$lib/server/.M-2 — Hardcoded hex colors in JS color maps (not CSS custom properties)
Severity: Medium
Files:
src/lib/playgrounds/bank-reconciliation/components/CategoryBreakdownDonut.svelte:30-40src/lib/playgrounds/bank-reconciliation/components/MatchingPairsOverlay.svelte:31-34Explanation:
CATEGORY_COLORSand the match-type color map are JS objects with raw hex values ('#6ea8fe','#22c55e', etc.) used as SVGfill/strokeattributes. These cannot reference CSS custom properties and will not follow the theme.Suggested fix: Define a canonical chart color set in
tokens.tsand export a JS map from the theme module (e.g.getChartColors(theme)). At minimum, align values with the existing token palette so a future theme swap is a single-file change.M-3 — Hardcoded
color: #fffin 4 Svelte filesSeverity: Medium
Files:
src/routes/[lang]/learn/+page.svelte:202src/routes/[lang]/chart-of-accounts/+page.svelte:423,458src/lib/playgrounds/journal-entry/components/EntryHistory.svelte:400Explanation: Active-state and confirm-action buttons set
color: #fffwithout a CSS variable. The patterncolor: var(--bg)(page background) is already used elsewhere for this purpose and is more robust.Suggested fix: Replace
color: #fffwithcolor: var(--bg)on accent/error-background buttons, consistent withWaitlistForm.svelte:199.LOW
L-1 — Hardcoded "items" string not routed through i18n
Severity: Low
File:
src/lib/playgrounds/bank-reconciliation/components/VarianceScale.svelte:178,197Explanation: The scale SVG displays
{bankItemCount} items/{booksItemCount} itemswith "items" hardcoded in English. All surrounding labels are properly passed as translated props, but this one string was missed.Suggested fix: Add an
itemsLabelprop toVarianceScaleand pass$t('bank-reconciliation.items')from the parent, alongside a FR translation entry.L-2 — Hardcoded hex colors in SVG
background-imagedata URIsSeverity: Low
Files:
src/lib/components/WaitlistForm.svelte:179(%23555c74=--text-muted)src/lib/components/feedback/FeedbackForm.svelte:322(%23555c74)src/lib/components/playground/PlaygroundSettings.svelte:94(%237c7fff=--accent)Explanation: SVG data URIs in
background-imagecannot reference CSS custom properties — browser limitation. Values match current tokens but diverge silently on theme changes.Suggested fix: Accept as a known limitation and add a comment, or generate the data URI at runtime from
getComputedStyle.L-3 — API error messages are English-only user-facing strings
Severity: Low
Files:
src/routes/api/waitlist/+server.ts:33,39,50,63,66src/routes/api/feedback/+server.ts:40,47,75,78,85,99Explanation: Server error strings (
{ error: "Too many requests…" }) are surfaced directly to the user viaWaitlistForm.svelte:31and displayed in the UI, bypassing the i18n system entirely.Suggested fix: Return machine-readable error codes (
{ code: 'rate_limit' }) and map them to translated strings in the Svelte component.L-4 — Tab buttons and share button lose accessible name on mobile (WCAG 4.1.2)
Severity: Low
Files:
src/lib/components/playground/PlaygroundTabs.svelte—.tab-label { display: none }at ≤480 px; noaria-labelon buttons; icon SVG isaria-hiddensrc/lib/components/playground/ShareButton.svelte— same pattern;.label { display: none }at ≤480 px;titleattribute is unreliable as primary name sourceExplanation: At mobile widths both components hide their visible label via
display: none(removes element from accessibility tree) while also marking the icon SVG asaria-hidden="true". Net result: zero accessible name on those buttons for screen reader users on mobile.Suggested fix: Add
aria-label={$t(tab.labelKey)}directly on each<button>inPlaygroundTabs, andaria-label={$t('shell.share')}on the share button.L-5 — Multi-product CVP form inputs have no programmatic label (WCAG 1.3.1)
Severity: Low
File:
src/lib/playgrounds/cvp/components/MultiProductForm.svelte:93,99,106,114Explanation: The grid renders visual header
<span>elements that are not associated with the corresponding<input>elements — nofor/idlinkage, noaria-label, noaria-labelledby. Screen readers announce these inputs without any context ("edit text" instead of "Product name, row 1").Suggested fix: Add
aria-labelto each input, e.g.aria-label="{translate('cvp.product.name')} {i + 1}".L-6 —
--greenCSS fallback value mismatches the actual tokenSeverity: Low
Files: Multiple (e.g.
VarianceScale.svelte:223,ReconciliationStatement.svelte:275)Explanation: Many
var(--green, #22c55e)calls use#22c55e(Tailwind green-500) as the fallback. The actual theme token is#34d399. Since--greenIS defined by the generator, the fallback is never used at runtime — but the misleading value creates confusion in authoring and static analysis tools.Suggested fix: Remove the fallback from
var(--green)calls, or update fallbacks to match the token value.2. New Playground Ideas
Existing coverage: amortization, bank reconciliation, CVP/break-even, simple/compound interest, journal entry, TVM (FV/PV, IRR/NPV, annuities). Static HTML playgrounds also cover depreciation and basic journal entries.
Idea 1 — Inventory Valuation Methods
Title (EN): Inventory Costing Methods | Title (FR): Méthodes d'évaluation des stocks
Target learner: Licence 2, practicing accountant
Pedagogical objective: SYSCOHADA mandates weighted-average cost (CMP); students regularly confuse it with FIFO and sometimes erroneously apply LIFO (not permitted under SYSCOHADA). Side-by-side comparison fixes this misconception.
Core interaction: Enter a sequence of inventory movements (purchases + sales). Engine computes COGS and ending inventory under FIFO, CMP, and a greyed-out LIFO column. A live banner shows XAF impact on net income between methods.
Minimum viable inputs: Initial stock (qty + unit cost), up to 10 purchase/sale transactions.
Outputs: Inventory ledger per method, COGS total, ending inventory value, income difference, SYSCOHADA compliance flag.
Complement: Fills the gap between the amortization playground (asset cost allocation) and the journal-entry playground (recording movements). Reuses
format/currency.tsandAccountPicker.Idea 2 — VAT / TVA Computation and Return
Title (EN): VAT Calculation & Return | Title (FR): Calcul de TVA et déclaration
Target learner: Licence 3, Master, practicing accountant
Pedagogical objective: Students struggle to compute net TVA payable (output minus deductible input TVA) and to apply country-specific OHADA-zone rates (18 % Cameroon, 19.25 % Côte d'Ivoire, etc.).
Core interaction: Enter sales and purchase invoices for a period, select country/rate, classify each line. Engine builds the TVA return form and computes net balance due or refundable.
Minimum viable inputs: Country (drives rate), up to 15 invoices per direction with HT amount and taxability class.
Outputs: TVA return summary, SYSCOHADA journal entries (4441/4455 accounts), common error highlights.
Complement: Bridges journal-entry mechanics to real-world tax compliance. Uses
format/currency.tswith FCFA-zone currencies.Idea 3 — Payroll / Bulletin de Paie
Title (EN): Payroll Calculator | Title (FR): Simulateur de Bulletin de Paie
Target learner: Licence 3, Master, HR/finance practitioner
Pedagogical objective: Students cannot map gross salary to employer cost or produce SYSCOHADA journal entries (641, 431, 447) for payroll. CNPS contributions and IRPP withholding are taught abstractly.
Core interaction: Enter gross salary, employee category, family charges, and OHADA country. Sliders experiment with gross salary to see IRPP brackets apply progressively. Output shows the payslip breakdown and the four journal entries an employer must post.
Minimum viable inputs: Country, gross salary, employee category (cadre/non-cadre), number of dependants.
Outputs: Net-to-gross bridge, CNPS employer/employee split, IRPP by bracket, CAC/RAV where applicable, payslip layout, SYSCOHADA journal entries.
Complement: The most-requested real-world topic not yet covered. Reuses journal entry display components and
fmtCurrencyfor FCFA amounts.Idea 4 — Financial Ratio Dashboard
Title (EN): Financial Ratio Dashboard | Title (FR): Tableau de Bord des Ratios Financiers
Target learner: Licence 3, Master
Pedagogical objective: Students compute individual ratios in isolation but miss how ratio families interact and what thresholds signal distress under SYSCOHADA's TAFIRE framework.
Core interaction: Fill in a simplified SYSCOHADA balance sheet and income statement. Dashboard instantly computes and colour-codes 12 ratios across four families (liquidity, solvency, profitability, activity) with OHADA-zone SME benchmarks.
Minimum viable inputs: 8–10 key balance-sheet line items (BFR, trésorerie, fonds propres, total bilan, CA, résultat net).
Outputs: Ratio tiles with traffic-light status, radar chart, one-sentence interpretation per ratio, TAFIRE indicators.
Complement: Synthesis playground drawing on all existing modules. Reuses
KpiStripandcvp/chart-utils.ts.Idea 5 — Depreciation Method Comparison (SYSCOHADA vs IFRS)
Title (EN): Depreciation Method Comparison | Title (FR): Comparaison des Méthodes d'Amortissement
Target learner: Licence 2/3, Master
Pedagogical objective: The existing static HTML depreciation playground shows one method in isolation. Students confuse straight-line, declining-balance, and units-of-production and don't understand how SYSCOHADA differs from IFRS on component depreciation.
Core interaction: Side-by-side schedule tables for three methods with a SYSCOHADA/IFRS toggle. Chart overlay shows NBV divergence between methods.
Minimum viable inputs: Asset cost, residual value, useful life, declining-balance rate, annual production/hours.
Outputs: Three parallel amortization tables, carrying-value comparison chart, income difference per year.
Complement: Directly supersedes the static
depreciation-playground.htmlas a native Svelte module, integrating with the amortization playground's existingengine.tsandScheduleTablecomponents.