Skip to content

Daily review 2026-07-10 - #74

Draft
NghaReformer wants to merge 1 commit into
mainfrom
daily-review/2026-07-10
Draft

Daily review 2026-07-10#74
NghaReformer wants to merge 1 commit into
mainfrom
daily-review/2026-07-10

Conversation

@NghaReformer

Copy link
Copy Markdown
Owner

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/stores found)


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–116

nativeLoader is declared as a $derived that calls getPlayground(slug).then(...). Two problems compound:

  1. The {#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.
  2. Because nativeLoader is $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 nativeLoader to a $state initialized once in onMount (or use untrack inside the derived), and add {:catch err} with an error UI — e.g., an error card re-using the existing --error token.


HIGH

H-1 · Theme tokens --orange, --blue, --red referenced but never defined

Files: 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.ts outputs only --amber, --green, --error. Variables --orange, --blue, and --red are not emitted, so every var(--orange, #f59e0b), var(--blue, #3b82f6), and var(--red, #ef4444) always falls through to the hardcoded hex fallback. These colors cannot be restyled via the token system.

Fix: Add orange, blue, and red entries to ThemeTokens and emit them in css-generator.ts.

H-2 · i18n parity failures across 4 namespaces

Namespace Missing from FR
cvp cvp.ex.aftertax.desc, cvp.ex.bep.desc, cvp.learn.cAfterTaxD, cvp.learn.cMarginSafetyD, cvp.learn.cSalesMixD, cvp.learn.cTargetProfitD, pg.cvp.desc
feedback feedback.description.placeholder, feedback.screenshot.capture_unsupported, feedback.success.body
common coa.class.6, coa.class.7
interest int.exercise.eir-to-nominal.hint

These 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–47

The $effect guard if (targetProfitInput === '') prevents re-sync once the user has typed. When the parent loads a new scenario (changing targetProfit), 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:7

import type { FeedbackType, FeedbackSeverity } from '$lib/server/db/types';

Even as import type, SvelteKit's Vite plugin flags $lib/server/* references in non-server files. FeedbackType and FeedbackSeverity are 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–35

Both define JS Record<string, string> color maps with raw hex literals entirely outside the theme token pipeline.

M-2 · Bare color: #fff in 4 stylesheets

Files: EntryHistory.svelte:400, chart-of-accounts/+page.svelte:423,458, learn/+page.svelte:202

Fix: Add --text-on-accent and --text-on-error tokens.

M-3 · ARIA tab pattern incomplete — missing aria-controls / role="tabpanel"

Files: PlaygroundTabs.svelte, tvm/SolverPanel.svelte, tvm/AnnuityPanel.svelte, tvm/Playground.svelte

Tab buttons lack aria-controls; panel containers lack role="tabpanel", id, and aria-labelledby. WCAG 4.1.2 violation.

M-4 · Unkeyed {#each} on dynamic lists in Journal Entry playground

Files: TAccountView.svelte:65,74, EntryHistory.svelte:114, AccountingStagePanel.svelte:190,401,417,433

Without 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–26

All headings and body text are hardcoded English. French users visiting /fr/privacy see an untranslated page.

M-6 · Landing page <title>, meta description, hero badge hardcoded English

File: src/routes/[lang]/+page.svelte:21–22,28

The 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-icon is aria-hidden="true" and .tab-label has display: none at 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:216

outline: none on input[type='range'] with no :focus-visible replacement.

M-9 · MultiProductForm inputs have no accessible labels (WCAG 1.3.1)

File: src/lib/playgrounds/cvp/components/MultiProductForm.svelte:93–114

Four <input> elements in a custom role="row" grid have no aria-label or associated <label>.


LOW

  • L-1: Inline style= for dynamic progress/opacity values — use CSS custom property pattern (--pct: {pct}%)
  • L-2: Nav aria-label strings hardcoded English (Nav.svelte:16,28)
  • L-3: 12+ aria-label strings hardcoded English across playground components
  • L-4: Emoji used as UI icons in violation of CLAUDE.md "No emoji icons" rule
  • L-5: Dead exports: getRegisteredSlugs, getCurrencyDecimals, fmtUnitsCeil, initLocale, buildGoogleFontsUrl, buildPreconnectLinks

Full 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 AccountPicker and 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 KpiStrip pattern.

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.ts and ScheduleTable component. Addresses the practitioner-level gap not covered by any existing playground.


Generated by Claude Code

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W4z57pE66vR8Co9mrrmN5S
@vercel

vercel Bot commented Jul 10, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
ohadalearn Ready Ready Preview, Comment Jul 10, 2026 11:19pm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants