Skip to content

Daily review 2026-07-08 - #72

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

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

Conversation

@NghaReformer

Copy link
Copy Markdown
Owner

Daily Review — 2026-07-08

Automated codebase review for OhadaLearn (SvelteKit 2 + Svelte 5 runes).
Reviewer scope: Svelte 5 rules, theme-token compliance, i18n, server boundary, accessibility, dead code, performance.


1. Bugs & Issues

Summary

# Severity Area File(s)
1 high Design tokens KpiStrip.svelte, ChartPanel.svelte, +18 more
2 high Hardcoded colors CategoryBreakdownDonut.svelte, MatchingPairsOverlay.svelte
3 medium Server boundary FeedbackForm.svelte
4 medium Unhandled async error [slug]/+page.svelte
5 medium Inline style CategoryBreakdownDonut.svelte
6 medium Hardcoded color PlaygroundCard.svelte, EntryHistory.svelte
7 medium Generic gradient (CLAUDE.md) [lang]/+page.svelte
8 low Emoji icons (CLAUDE.md) playgrounds.ts, PlaygroundTabs.svelte
9 low i18n — hardcoded EN string PlaygroundTabs.svelte

1.1 --orange token does not exist — 20 call-sites silently fall back to #f59e0b (high)

src/lib/theme/tokens.ts defines no --orange property; the theme uses --amber / --amber-glow instead. Every use of var(--orange, #f59e0b) silently renders the hardcoded hex colour, breaking the theme contract.

Affected files (non-exhaustive):

  • src/lib/components/playground/KpiStrip.svelte:76
  • src/lib/playgrounds/amortization/components/ScheduleTable.svelte:240
  • src/lib/playgrounds/amortization/components/ChartPanel.svelte:436, 493, 515, 529
  • src/lib/playgrounds/bank-reconciliation/components/LedgerPanel.svelte:175
  • src/lib/playgrounds/bank-reconciliation/components/VarianceScale.svelte:230, 260, 261

Suggested fix: Either add orange to ThemeTokens.colors in tokens.ts (mapping to #f59e0b), or replace every var(--orange, …) with var(--amber). The amber token (#f5a623) is already defined and semantically equivalent. Prefer --amber since the token already exists.


1.2 Hardcoded hex colour maps in chart components (high)

Two components define private colour tables that bypass the design-token system entirely and cannot be recoloured by theme changes:

src/lib/playgrounds/bank-reconciliation/components/CategoryBreakdownDonut.svelte:30–40

const CATEGORY_COLORS: Record<ItemCategory, string> = {
  'outstanding-check': '#6ea8fe',
  'deposit-in-transit': '#22c55e',
  'bank-charge': '#f59e0b',
  ...
};

Nine hardcoded hex values for donut chart segments.

src/lib/playgrounds/bank-reconciliation/components/MatchingPairsOverlay.svelte:30–35

const COLOR: Record<MatchType, string> = {
  'exact-amount-ref': '#22c55e',
  'exact-amount-date': '#10b981',
  fuzzy: '#f59e0b',
  manual: '#6ea8fe',
};

Four hardcoded hex values for SVG match-line strokes.

Suggested fix: Map each semantic category to an existing CSS custom property (var(--accent), var(--green), var(--amber), var(--error), etc.). For categories without a direct token mapping, add purpose-specific tokens to tokens.ts so all colour decisions remain in one file.


1.3 $lib/server/ type imported into client component (medium)

src/lib/components/feedback/FeedbackForm.svelte:7

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

FeedbackType and FeedbackSeverity are simple string-union types. Although import type is erased at runtime, SvelteKit's Vite plugin enforces the $lib/server/ boundary at the module graph level and may emit a build warning or error in certain modes. Shared types used in client components should not live behind the server boundary.

Suggested fix: Move FeedbackType and FeedbackSeverity to src/lib/types/feedback.ts. Update $lib/server/db/types.ts to re-import from there if needed.


1.4 {#await nativeLoader} block missing {:catch} (medium)

src/routes/[lang]/playgrounds/[slug]/+page.svelte:103–116

No {:catch} block. If the dynamic import throws (network failure, malformed module, missing export), Svelte propagates the rejection to the page-level error boundary, replacing the entire layout instead of showing an in-context message.

Suggested fix: Add a {:catch err} block with a role="alert" error panel and a new i18n key playgrounds.load_error in both locale files.


1.5 Inline style attribute for dynamic chart colour (medium)

src/lib/playgrounds/bank-reconciliation/components/CategoryBreakdownDonut.svelte:120

<span class="legend-swatch" style="background: {seg.color}"></span>

CLAUDE.md prohibits inline styles. This is a symptom of finding 1.2. Resolves once seg.color is replaced with a data-cat attribute and CSS-variable-based colour rules.


1.6 Hardcoded raw colour values in component CSS (medium)

  • src/lib/components/PlaygroundCard.svelte:45rgba(0, 0, 0, 0.3) in box-shadow; replace with var(--shadow-md).
  • src/lib/playgrounds/journal-entry/components/EntryHistory.svelte:400color: #fff on .btn-confirm; add a --text-on-error token to tokens.ts and use it here.

1.7 Generic text gradient on hero title (medium)

src/routes/[lang]/+page.svelte:128

background: linear-gradient(135deg, var(--text-primary) 0%, var(--accent) 100%);
-webkit-background-clip: text;

CLAUDE.md: "No generic gradients." Move the definition into a named token (--hero-title-gradient) in tokens.ts, or replace the gradient with a solid colour + accented <em> element.


1.8 Emoji used as rendered icons (low)

CLAUDE.md: "No emoji icons."

  • src/lib/data/playgrounds.ts:18–70icon field uses 📐, 📊, 📒, 🏦, 📉, 🏧, 📈
  • src/lib/components/playground/PlaygroundTabs.svelte:11–14 — tab icons 📖, 🧮, 📋

Both render directly in UI. Replace with inline SVGs consistent with Nav.svelte / FeedbackLauncher.svelte.


1.9 Hardcoded English string in aria-label (low)

src/lib/components/playground/PlaygroundTabs.svelte:18

<div class="tab-bar" role="tablist" aria-label="Playground sections">

French-language users receive an English accessibility label. Replace with aria-label={$t('shell.tabs.aria')} and add the key to both locale files.


2. New Playground Ideas

Existing coverage: TVM, CVP, Journal Entry, Amortization (loan), Depreciation (fixed assets), Bank Reconciliation, Interest (simple/compound).


2.1 Financial Ratio Analysis — Analyse des ratios financiers

Target learner: Licence 3 / Master 1

Pedagogical objective: Students compute ratios mechanically without interpreting what they signal. This playground shows a SYSCOHADA-formatted balance sheet + income statement, computes 15+ ratios live, and shows colour-coded traffic-light feedback against OHADA-sector benchmarks.

Core interaction: Learner enters or adjusts balance-sheet / income-statement line items; ratios update live; out-of-range ratios are flagged with an interpretation of the implication.

MVPs:

  • Inputs: fixed assets, current assets, equity, long-term debt, current liabilities, revenue, COGS, EBIT, net income
  • Outputs: liquidity (current, quick, cash), solvency (D/E, interest cover), profitability (ROE, ROA, net margin), activity (asset turnover, DSO, DIO)

Why it complements existing playgrounds: Journal Entry produces raw accounting data; this playground teaches what to do with it analytically. Pairs naturally with TVM for capital-structure decisions.


2.2 VAT / TVA Returns — Calculateur de déclaration TVA OHADA

Target learner: Licence 2 / practicing professional

Pedagogical objective: OHADA-zone VAT varies by member state. Students confuse TVA collectée with TVA déductible and make sign errors on net balances.

Core interaction: Learner enters a list of purchase/sale invoices with TVA rates (0%, 8.5%, 18%, exempt) and selects a country (Cameroon, CI, Sénégal). Playground computes TVA collectée, TVA déductible, net balance (payable or credit), and generates the SYSCOHADA journal entry (accounts 443/445).

MVPs:

  • Inputs: transaction list (type, amount HT, TVA rate, exempt flag) + country selector
  • Outputs: TVA collectée, TVA déductible, net TVA, draft return table, SYSCOHADA journal entry

Why it complements existing playgrounds: Bank Reconciliation and Journal Entry handle recording; TVA adds the tax-compliance dimension mandatory for any OHADA-zone accountant.


2.3 Inventory Valuation Methods — Méthodes de valorisation des stocks

Target learner: Licence 2

Pedagogical objective: SYSCOHADA permits FIFO and two variants of CMP (at each entry / end-of-period). Students confuse the variants and under-appreciate how the choice affects COGS and closing inventory, impacting profit.

Core interaction: Learner enters stock movements (date, in/out, qty, unit cost). Three side-by-side schedules update live — FIFO, CUMP à chaque entrée, CUMP de fin de période — with a delta strip showing the impact on closing stock value and COGS.

MVPs:

  • Inputs: opening stock (qty, unit cost) + movement list
  • Outputs: valuation schedule per method, closing stock value, COGS, comparative delta

Why it complements existing playgrounds: The missing "Class 3 stocks" module to complement the Class 2 (Amortization, Depreciation) and Class 5 (Bank Reconciliation) playgrounds.


2.4 OHADA Payroll — Calcul de la fiche de paie (CNPS + IRPP)

Target learner: Licence 3 / Master / Practicing professional

Pedagogical objective: OHADA-zone payroll requires country-specific CNPS rates and progressive IRPP brackets. Most students cannot derive net salary from gross, leading to errors in payroll journal entries and social-charge declarations.

Core interaction: Learner inputs gross salary, country (Cameroon / CI / Sénégal), contract type, and allowances. Playground itemises deductions (CNPS employee/employer, IRPP, CAFAL), shows net salary, and generates the SYSCOHADA payroll journal entry (accounts 661, 4211, 4311, 4321, 4341…).

MVPs:

  • Inputs: gross salary, country, contract type, non-taxable allowances
  • Outputs: itemised payslip, employer total cost, SYSCOHADA journal entry (charge + settlement)

Why it complements existing playgrounds: Payroll is the highest-frequency periodic journal entry in practice; adds country-by-country compliance data not covered elsewhere.


2.5 Lease Accounting Comparison — Contrats de location : SYSCOHADA vs IFRS 16

Target learner: Master / Practicing professional

Pedagogical objective: SYSCOHADA's operating-vs-finance lease classification diverges from IFRS 16's right-of-use model. Professionals in dual-reporting environments must reconcile the two; this is a frequent source of errors in first-time IFRS adoption projects.

Core interaction: Learner inputs lease terms (payment, frequency, duration, implicit rate, asset fair value and economic life). Playground classifies under SYSCOHADA, generates the IFRS 16 ROU/liability schedule, and shows side-by-side P&L and balance-sheet impact plus reconciliation delta.

MVPs:

  • Inputs: lease payment, frequency, total duration, implicit rate, asset fair value, economic life
  • Outputs: SYSCOHADA classification + journal entry, IFRS 16 ROU schedule, lease liability schedule, annual delta reconciliation

Why it complements existing playgrounds: Amortization handles asset depreciation; this adds the lease-liability side and a comparative IFRS angle absent from all current modules.


Report generated by automated daily review routine. No code was modified.


Generated by Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 8, 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 8, 2026 11:16pm

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