Skip to content

Daily review 2026-06-27 - #62

Draft
NghaReformer wants to merge 1 commit into
mainfrom
daily-review/2026-06-27
Draft

Daily review 2026-06-27#62
NghaReformer wants to merge 1 commit into
mainfrom
daily-review/2026-06-27

Conversation

@NghaReformer

Copy link
Copy Markdown
Owner

OhadaLearn Daily Review — 2026-06-27

Automated review of main snapshot. Codebase: SvelteKit 2.57 / Svelte 5.55 / TypeScript 6.0.


1. Bugs & Issues

MEDIUM-1 — Undefined CSS variables used across 10+ files (effective hardcoded colors)

Severity: High
Files: src/lib/components/playground/KpiStrip.svelte:76, src/lib/playgrounds/amortization/components/ScheduleTable.svelte:240,246,259, src/lib/playgrounds/amortization/components/InputsPanel.svelte:604–605, src/lib/playgrounds/amortization/components/ChartPanel.svelte:436,444,448,493,501,505,515,529,533, src/lib/playgrounds/bank-reconciliation/components/LedgerPanel.svelte:175, src/lib/playgrounds/bank-reconciliation/components/VarianceScale.svelte:230,260–261,331,335,370,416, src/lib/playgrounds/bank-reconciliation/components/TransactionJournal.svelte:382–383, src/lib/playgrounds/bank-reconciliation/components/BankStatementPanel.svelte:175, src/lib/playgrounds/bank-reconciliation/components/ScenarioWalkthrough.svelte:234,274, src/lib/playgrounds/bank-reconciliation/components/ReconciliationFlow.svelte:278

Explanation: --orange, --blue, and --red are used as CSS custom properties throughout these components (e.g., var(--orange, #f59e0b)) but are never defined in src/lib/theme/tokens.ts or src/lib/theme/css-generator.ts. The fallback hex values therefore activate on every render, making these effectively hardcoded colors that bypass the theme system entirely. A future palette change (e.g., dark mode variant) will silently skip all these surfaces.

Fix: Add orange, blue, and red (or semantically named equivalents — chartOrange, chartBlue, chartRed) to the ThemeTokens interface in tokens.ts, assign values in defaultTheme, and emit the corresponding --orange / --blue / --red vars in css-generator.ts. Replace all var(--red, ...) usages with the appropriate semantic token — --red and --error currently coexist with inconsistent fallbacks (#ef4444 vs #f06070), so consolidate error-state references to var(--error).


HIGH-2 — Bare hex strings in TypeScript color maps bypass theme entirely

Severity: High
Files: src/lib/playgrounds/bank-reconciliation/components/CategoryBreakdownDonut.svelte:31–39, src/lib/playgrounds/bank-reconciliation/components/MatchingPairsOverlay.svelte:31–34

Explanation: Both files define TypeScript Record<..., string> objects mapping category/match types to hex strings (e.g., 'outstanding-check': '#6ea8fe', fuzzy: '#f59e0b'). Unlike the var() pattern above, these values are used directly in SVG stroke/fill attributes — completely outside the CSS cascade and unable to be overridden by theme tokens. The colours also partially overlap with existing tokens (#6ea8fe ≈ accent, #f59e0b ≈ amber) but are not the exact same values, creating visual inconsistency.

Fix: Replace each hex with the corresponding CSS token value read from a computed style lookup (e.g., getComputedStyle(document.documentElement).getPropertyValue('--accent').trim()) or expose the color maps as CSS custom properties and reference them via var() in the SVG attributes.


MEDIUM-3 — Shared ExercisePanel hardcodes French difficulty labels instead of using i18n

Severity: Medium
File: src/lib/components/playground/ExercisePanel.svelte:11–13

Explanation:

fondamental: { label: 'Fondamental', color: 'var(--green)', glow: 'var(--green-glow)' },
intermediaire: { label: 'Intermédiaire', color: 'var(--amber)', glow: 'var(--amber-glow)' },
avance: { label: 'Avancé', color: 'var(--error)', glow: 'var(--amber-glow)' },

Each individual playground already defines bilingual i18n keys for these labels (e.g., am.exercise.difficulty.fondamental'Foundational' / 'Fondamental'). The shared component ignores all of them. An English-locale visitor sees raw French.

Fix: Either accept a difficultyLabels: Record<ExerciseDifficulty, string> prop and have each playground pass its own translated values, or standardize on a shared namespace key (e.g., shell.difficulty.fondamental) and call $t() inside ExercisePanel.


MEDIUM-4 — SSR renders <html lang="en"> for all locales

Severity: Medium
File: src/app.html:2

Explanation: The static HTML shell hardcodes <html lang="en">. The root layout fixes this client-side via $effect, but during SSR French pages (/fr/...) arrive with lang="en". Screen readers and search engine crawlers may apply incorrect linguistic processing to French content.

Fix: In src/hooks.server.ts, add a handle transformer:

const lang = url.pathname.startsWith('/fr') ? 'fr' : 'en';
return new Response(body.replace('<html lang="en">', `<html lang="${lang}">`), response);

MEDIUM-5 — Inline style on SvelteKit body wrapper violates project conventions

Severity: Medium
File: src/app.html:19

Explanation: <div style="display: contents">%sveltekit.body%</div> uses an inline style attribute, which CLAUDE.md explicitly bans. This is a SvelteKit scaffolding default that was never removed.

Fix: Since .app-shell in +layout.svelte already owns the flex layout, the display:contents wrapper is redundant. Remove the style attribute entirely, or move the rule to app.css with a class.


LOW-6 — Hardcoded theme-color meta duplicates the accent token

Severity: Low
File: src/app.html:9

<meta name="theme-color" content="#7c7fff"> hard-copies tokens.ts:53 (accent: '#7c7fff'). A designer updating the accent token will not know to update app.html. Add cross-reference comments in both files; long-term, generate it at build time via a Vite plugin.


LOW-7 — Hardcoded "items" string in SVG centre label

Severity: Low
File: src/lib/playgrounds/bank-reconciliation/components/CategoryBreakdownDonut.svelte:105

<text>items</text> is an untranslated English literal inside SVG. Fix: call $t('br.donut.items') after adding the key to both locale files (FR: 'éléments').


LOW-8 — Accounting standard labels not translated in PlaygroundSettings

Severity: Low
File: src/lib/components/playground/PlaygroundSettings.svelte:9–12

label: 'French PCG' is English-only; French users should see 'PCG français'. Fix: add shell.standard.* i18n keys and use $t() for all four options.


Passing checks

  • Svelte 5 runes: 100% compliant — zero export let, $:, on:click, <slot>, or $app/stores violations across 194 source files.
  • Accessibility: Comprehensive role, aria-label, aria-expanded, aria-selected, aria-checked usage throughout Nav, PlaygroundTabs, LanguageToggle, WaitlistForm, FeedbackLauncher, and SVG charts.
  • Server boundary: All Supabase and DB code confined to src/lib/server/; no leakage detected.
  • i18n parity: 1,335+ keys across 20 namespace files with auto-generated TranslationKey union; no gaps outside issues 3/7/8 above.
  • Async error handling: API routes wrap Supabase calls in try/catch with appropriate HTTP status codes.

2. New Playground Ideas

Existing playgrounds excluded: Loan Amortization, CVP/Breakeven, Bank Reconciliation, Journal Entry, Compound/Simple Interest, TVM. Static HTML legacy: Depreciation, CVP, Amortization, Journal Entry.


IDEA-1 — Depreciation Methods (Native Svelte Module)

Title: Depreciation Methods / Méthodes d'Amortissement Comptable
Target: Licence 2
Pedagogical objective: Students conflate loan amortization with asset depreciation, and misapply prorata temporis in year 1. A static HTML version exists but has no exercises or learn-mode content.
Core interaction: Input asset cost, useful life, residual value, acquisition date; select SYSCOHADA method (linéaire / dégressif / unités de production); see live schedule + year-end journal entries. Toggle between methods to compare.
MVP I/O: Cost, life, date, residual, method → full depreciation schedule, journal entry per year, net book value chart.
Complement: Amortization playground covers loan schedules; this covers asset depreciation — distinct concepts students routinely conflate.


IDEA-2 — Working Capital Analysis (FRNG / BFRE / TN)

Title: Working Capital Dashboard / Analyse du Fonds de Roulement
Target: Licence 3
Pedagogical objective: Students memorize TN = FRNG − BFRE without understanding that positive FRNG does not guarantee solvency. No existing playground covers SYSCOHADA working capital structure.
Core interaction: Populate a simplified SYSCOHADA balance sheet; three KPI cards (FRNG, BFRE, TN) update live with colour-coded status. Scenario mode stress-tests by adjusting supplier credit days or stock turnover.
MVP I/O: 8–10 balance sheet line items → FRNG / BFRE / TN cards, waterfall decomposition chart, localized one-sentence interpretation.
Complement: Bank Reconciliation teaches cash-book accuracy; this teaches structural cash position — a higher-level analytical skill.


IDEA-3 — SYSCOHADA Balance Sheet Builder

Title: Balance Sheet Constructor / Constructeur de Bilan SYSCOHADA
Target: Licence 2–3
Pedagogical objective: Students can post entries but cannot map accounts to the Bilan (classes 1–5) and Compte de Résultat (classes 6–7). This gap surfaces before internship.
Core interaction: Given a randomized trial balance (15–20 accounts from src/lib/shared/chart-of-accounts/), drag-and-drop into the correct Bilan/CdR cell. On submit, highlights misclassified items and shows reconciled totals.
MVP I/O: Seeded trial balance → two-column Bilan + CdR, totals, balance check, animated net-income reconciliation.
Complement: Journal Entry teaches how to record; this teaches where records land in financial statements — closing the accounting cycle loop.


IDEA-4 — Payroll & Social Contributions Calculator (OHADA Zone)

Title: Payroll & Social Charges / Bulletin de Paie et Charges Sociales
Target: Licence 3, practicing professionals
Pedagogical objective: OHADA-zone payroll is jurisdiction-specific (CNPS rates, IRPP brackets, family quotient differ by country). Junior accountants routinely under-provision for the part patronale, causing payroll charge errors.
Core interaction: Select country (Cameroon, Côte d'Ivoire, Sénégal), enter gross salary + dependent count. Output splits into take-home pay, salarié deductions, and patronale charges, with a live SYSCOHADA journal entry (Charges de Personnel / Rémunérations dues / Organismes sociaux).
MVP I/O: Gross salary (FCFA), country, dependents → net pay, deduction waterfall, employer cost total, journal entry.
Complement: No existing playground covers labor cost accounting — a daily task for every OHADA-zone accountant.


IDEA-5 — Financial Ratio Dashboard (Diagnostic Financier)

Title: Financial Ratio Analyzer / Tableau de Bord des Ratios Financiers
Target: Licence 3, Master, practicing professionals
Pedagogical objective: Students conflate liquidity (liquidité générale/immédiate), solvency (autonomie financière, capacité de remboursement), and profitability (ROE, ROA, marge nette) ratios. SYSCOHADA-specific metrics like CAF (capacité d'autofinancement) are rarely taught interactively.
Core interaction: Input simplified balance sheet + P&L (or load "PME saine" / "entreprise en difficulté" scenario). Dashboard shows 10 ratios across four families with colour-coded thresholds and one-sentence interpretation per ratio. Adjust line items and watch ratios recompute live.
MVP I/O: 12–15 aggregated statement lines → ratio table, spider/radar chart, rule-based one-paragraph diagnosis (no LLM).
Complement: CVP covers internal cost-volume decisions; this covers external financial diagnosis — the lens used by banks, auditors, and investors in the OHADA zone.


Report generated by automated daily review. Total source files audited: 194.


Generated by Claude Code

@vercel

vercel Bot commented Jun 27, 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 Jun 27, 2026 11:09pm

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