Daily review 2026-07-10 - #74
Draft
NghaReformer wants to merge 1 commit into
Draft
Conversation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W4z57pE66vR8Co9mrrmN5S
|
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-10
Codebase: OhadaLearn (SvelteKit 2 + Svelte 5 runes)
Reviewer: Automated — senior UI + SYSCOHADA domain review
Svelte 5 runes compliance: ✅ Clean (no
export let,$:,on:*,<slot>,$app/storesfound)1. Bugs & Issues
CRITICAL
C-1 · Unhandled async rejection + Promise leak in playground loader
File:
src/routes/[lang]/playgrounds/[slug]/+page.svelte:12–16, 101–116nativeLoaderis declared as a$derivedthat callsgetPlayground(slug).then(...). Two problems compound:{#await nativeLoader}block at line 103 has no{:catch}clause. If the dynamic import fails (network error, missing chunk, wrong slug in registry), the spinner disappears and the user sees a completely blank pane with no error message — a silent production failure.nativeLoaderis$derived, any reactive dependency change (e.g., locale update) re-evaluates the derived expression, firing a new, abandoned Promise on each run. Each firing kicks off a parallel module load that may never be used.Fix: Promote
nativeLoaderto a$stateinitialized once inonMount(or useuntrackinside the derived), and add{:catch err}with an error UI — e.g., an error card re-using the existing--errortoken.HIGH
H-1 · Theme tokens
--orange,--blue,--redreferenced but never definedFiles:
KpiStrip.svelte:76,amortization/ChartPanel.svelte:436–533,amortization/ScheduleTable.svelte:240–265,amortization/InputsPanel.svelte:604–605, plus 20+ occurrences across bank-reconciliation components.css-generator.tsoutputs only--amber,--green,--error. Variables--orange,--blue, and--redare not emitted, so everyvar(--orange, #f59e0b),var(--blue, #3b82f6), andvar(--red, #ef4444)always falls through to the hardcoded hex fallback. These colors cannot be restyled via the token system.Fix: Add
orange,blue, andredentries toThemeTokensand emit them incss-generator.ts.H-2 · i18n parity failures across 4 namespaces
cvpcvp.ex.aftertax.desc,cvp.ex.bep.desc,cvp.learn.cAfterTaxD,cvp.learn.cMarginSafetyD,cvp.learn.cSalesMixD,cvp.learn.cTargetProfitD,pg.cvp.descfeedbackfeedback.description.placeholder,feedback.screenshot.capture_unsupported,feedback.success.bodycommoncoa.class.6,coa.class.7interestint.exercise.eir-to-nominal.hintThese render as raw key strings for French users at runtime.
H-3 · Stale goal-seek input after scenario change
File:
src/lib/playgrounds/cvp/components/GoalSeekPanel.svelte:43–47The
$effectguardif (targetProfitInput === '')prevents re-sync once the user has typed. When the parent loads a new scenario (changingtargetProfit), the stale user input remains, causing the solver to report an incorrect break-even figure.H-4 · Server-type import in client component (build risk)
File:
src/lib/components/feedback/FeedbackForm.svelte:7Even as
import type, SvelteKit's Vite plugin flags$lib/server/*references in non-server files.FeedbackTypeandFeedbackSeverityare pure string unions — move them to$lib/contracts/feedback.ts.MEDIUM
M-1 · Hardcoded hex color maps in visualization components
Files:
CategoryBreakdownDonut.svelte:30–40,MatchingPairsOverlay.svelte:30–35Both define JS
Record<string, string>color maps with raw hex literals entirely outside the theme token pipeline.M-2 · Bare
color: #fffin 4 stylesheetsFiles:
EntryHistory.svelte:400,chart-of-accounts/+page.svelte:423,458,learn/+page.svelte:202Fix: Add
--text-on-accentand--text-on-errortokens.M-3 · ARIA tab pattern incomplete — missing
aria-controls/role="tabpanel"Files:
PlaygroundTabs.svelte,tvm/SolverPanel.svelte,tvm/AnnuityPanel.svelte,tvm/Playground.svelteTab buttons lack
aria-controls; panel containers lackrole="tabpanel",id, andaria-labelledby. WCAG 4.1.2 violation.M-4 · Unkeyed
{#each}on dynamic lists in Journal Entry playgroundFiles:
TAccountView.svelte:65,74,EntryHistory.svelte:114,AccountingStagePanel.svelte:190,401,417,433Without keys, Svelte patches by index and can misrecycle DOM nodes when items are inserted or removed mid-list.
M-5 · Privacy page entirely untranslated
File:
src/routes/[lang]/privacy/+page.svelte:6–26All headings and body text are hardcoded English. French users visiting
/fr/privacysee an untranslated page.M-6 · Landing page
<title>, meta description, hero badge hardcoded EnglishFile:
src/routes/[lang]/+page.svelte:21–22,28The rest of the page uses
$t()but the SEO-critical elements do not.M-7 · Mobile tabs have no accessible name at ≤480 px (WCAG 4.1.2)
File:
src/lib/components/playground/PlaygroundTabs.svelte:19–31, CSS:82–90.tab-iconisaria-hidden="true"and.tab-labelhasdisplay: noneat mobile widths — the resulting<button>has no accessible name.M-8 · Range sliders remove focus outline with no replacement (WCAG 2.4.7)
Files:
cvp/WhatIfPanel.svelte:260,cvp/SensitivityTable.svelte:299,interest/WhatIfPanel.svelte:216outline: noneoninput[type='range']with no:focus-visiblereplacement.M-9 · MultiProductForm inputs have no accessible labels (WCAG 1.3.1)
File:
src/lib/playgrounds/cvp/components/MultiProductForm.svelte:93–114Four
<input>elements in a customrole="row"grid have noaria-labelor associated<label>.LOW
style=for dynamic progress/opacity values — use CSS custom property pattern (--pct: {pct}%)aria-labelstrings hardcoded English (Nav.svelte:16,28)aria-labelstrings hardcoded English across playground componentsgetRegisteredSlugs,getCurrencyDecimals,fmtUnitsCeil,initLocale,buildGoogleFontsUrl,buildPreconnectLinksFull details with line numbers for all findings are in
reports/daily/2026-07-10.md.2. New Playground Ideas
Existing: TVM, CVP, Journal Entry, Amortization, Depreciation, Bank Reconciliation, Interest
Idea 1 — Balance Sheet Classifier / Classeur du Bilan SYSCOHADA
Target: Licence 1/2 — drag-and-drop SYSCOHADA account codes into the correct balance sheet section (Actif Immobilisé / Actif Circulant / Trésorerie / Capitaux Propres / Dettes). Closes the gap between posting journal entries and understanding financial statement positions. Reuses existing
AccountPickerand chart-of-accounts data.Idea 2 — Inventory Valuation Methods / Valorisation des Stocks
Target: Licence 2/3 — live comparison of FIFO vs. CMUP (after-movement and end-of-period) on a user-entered receipt/issue table, with auto-generated journal entries (comptes 31x/60x). Corrects the misconception that method choice does not affect reported profit. Equivalent to Depreciation/Amortization for current assets.
Idea 3 — VAT Mechanics / Mécanisme de la TVA
Target: Licence 2/3, professionals — compute TVA collectée, TVA déductible, prorata coefficient for mixed-use entities, and net TVA payable. Auto-generate journal entries (comptes 4441/4452/4455). Unique topic in the platform; addresses the single most common practical error for OHADA-zone practitioners.
Idea 4 — Financial Ratios Dashboard / Tableau de Bord des Ratios
Target: Licence 3, Master, professionals — input a simplified balance sheet + P&L; auto-compute six ratios (liquidité générale, endettement, ROE, ROA, marge brute, levier opérationnel) with OHADA sector benchmarks and interpretation. Synthesises all other playgrounds. Extends the existing
KpiStrippattern.Idea 5 — Lease Accounting: SYSCOHADA vs IFRS 16 / Contrats de Location
Target: Master, professionals — input lease terms; engine classifies finance vs. operating; shows side-by-side SYSCOHADA and IFRS 16 journal entries and year-one balance sheet impact. Reuses amortization
engine.tsandScheduleTablecomponent. Addresses the practitioner-level gap not covered by any existing playground.Generated by Claude Code