Skip to content

Daily review 2026-06-21 - #56

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

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

Conversation

@NghaReformer

Copy link
Copy Markdown
Owner

Daily Review — 2026-06-21

Reviewer: automated (claude-sonnet-4-6)
Branch scanned: main (HEAD at review time)


1. Bugs & Issues

Issue 1 — Emoji icons in all playground manifests

Severity: high
Files:

  • src/lib/playgrounds/amortization/manifest.ts:7
  • src/lib/playgrounds/bank-reconciliation/manifest.ts:7
  • src/lib/playgrounds/cvp/manifest.ts:7
  • src/lib/playgrounds/interest/manifest.ts:7
  • src/lib/playgrounds/journal-entry/manifest.ts:7
  • src/lib/playgrounds/tvm/manifest.ts:7
  • src/lib/data/playgrounds.ts:18,27,36,44,53,61,69

CLAUDE.md rule: "No emoji icons." Every playground manifest sets icon to an emoji literal ('📊', '🏦', '📒', '🏧', '📈', '📐'). These render in PlaygroundCard.svelte:13, PlaygroundShell.svelte:110, and the playground detail header at src/routes/[lang]/playgrounds/[slug]/+page.svelte:80.

Suggested fix: Replace emoji strings with short SVG icon identifiers (e.g., a slug like "bar-chart") and render them through a shared <Icon name={pg.icon} /> component backed by inline SVG sprites. Update PlaygroundManifest.icon type to a union of allowed icon slugs instead of string.


Issue 2 — Hardcoded #fff in component CSS

Severity: medium
Files:

  • src/routes/[lang]/learn/+page.svelte:202
  • src/routes/[lang]/chart-of-accounts/+page.svelte:423,458
  • src/lib/playgrounds/journal-entry/components/EntryHistory.svelte:400

Each site sets color: #fff for button or chip text. This bypasses the theme token system and will be invisible if the design ever introduces a light-mode variant or increases button contrast.

Suggested fix: Add a --color-on-accent or --color-on-error token to src/lib/theme/tokens.ts and reference it via CSS custom property, e.g. color: var(--color-on-accent).


Issue 3 — Hardcoded hex fallbacks in bank-reconciliation SVG/CSS

Severity: medium
Files:

  • src/lib/playgrounds/bank-reconciliation/components/ReconciliationFlow.svelte:137,144,207-208,270,275,278,281
  • src/lib/playgrounds/bank-reconciliation/components/ScenarioWalkthrough.svelte:182-183,195,199,231,234,238-239,271,274

SVG stroke/fill attributes and CSS rules use the pattern var(--accent, #6ea8fe), var(--green, #22c55e), and var(--orange, #f59e0b) with hardcoded fallback values. The fallback hex values duplicate what the theme already defines and will silently diverge if tokens change.

Suggested fix: Remove the hex fallbacks. The root layout always injects theme CSS before these components mount, so the vars are always defined. If a fallback is truly needed for standalone rendering, define a <style> block at the top of each file with scoped --accent, --green, --orange that inherit from the theme.


Issue 4 — $effect used to initialize $state from a prop (GoalSeekPanel)

Severity: medium
File: src/lib/playgrounds/cvp/components/GoalSeekPanel.svelte:43–46

$effect(() => {
  if (targetProfitInput === '') {
    targetProfitInput = fmtNumber(targetProfit || 20000, 0, locale);
  }
});

This effect runs once (when targetProfitInput is empty string on mount), then never re-runs because the condition is never truthy again. If the parent changes targetProfit after mount (e.g., the user loads a new scenario), the input does not update. Additionally, using $effect for one-time initialization is an anti-pattern in Svelte 5.

Suggested fix: Initialize the state directly at declaration time using the prop:

let targetProfitInput = $state(fmtNumber(targetProfit || 20000, 0, locale));

If the input must reset when targetProfit changes from the parent, use $derived with a reset gate or expose a reset() function the parent can call.


Issue 5 — Three redundant $effect calls each syncing one tween (VarianceScale)

Severity: low
File: src/lib/playgrounds/bank-reconciliation/components/VarianceScale.svelte:54–62

Three separate $effect blocks each set a single tweened store, creating three reactive subscriptions that fire separately even when all inputs change in the same tick.

Suggested fix: Collapse into one $effect block.


Issue 6 — Deprecated buildGoogleFontsUrl still publicly exported

Severity: low
Files:

  • src/lib/theme/fonts.ts:66–73 (declaration, marked @deprecated)
  • src/lib/theme/index.ts:7 (re-exports it)

Marked deprecated but still exported from the theme barrel. No callers found in the source tree — dead code that exposes a Google Fonts CDN dependency through the public API.

Suggested fix: Delete buildGoogleFontsUrl from fonts.ts and remove it from the index.ts re-export.


Issue 7 — PlaygroundManifest.icon typed as string with no enforcement

Severity: low
File: src/lib/contracts/playground.ts:17

The icon: string field places no compile-time constraint on what gets stored, making CLAUDE.md's "No emoji icons" rule unenforceable at the type level.

Suggested fix: Replace with a union type of allowed SVG icon slugs once Issue 1 is resolved.


2. New Playground Ideas

Existing coverage: journal-entry, TVM (annuities + investments), CVP (break-even, sensitivity, goal-seek), simple/compound interest, loan amortization, bank reconciliation, depreciation (static HTML).


Idea 1 — Financial Statement Builder (Constructeur d'états financiers)

Title (EN/FR): Financial Statement Builder / Constructeur d'états financiers SYSCOHADA
Target learner: Licence 3 / Master 1
Pedagogical objective: Students can post journal entries and calculate account balances but struggle to assemble the SYSCOHADA Bilan and Compte de résultat from a trial balance. This playground bridges the gap between the chart of accounts and published statements.
Core interaction: The learner receives a pre-populated trial balance of 12–18 accounts and drags rows into the correct line item of either the Bilan or Compte de résultat. Wrong placements are highlighted with the SYSCOHADA classification number that should have been used.
Minimum viable inputs / outputs: Trial balance rows (account code, debit/credit balance) → completed Bilan + Compte de résultat, Assets = Liabilities + Equity check, score.
Why it complements existing playgrounds: Journal Entry teaches debits/credits; Amortization teaches periodic expense recognition; this closes the loop by teaching how those entries aggregate into SYSCOHADA statutory reports.


Idea 2 — VAT & Withholding Tax Simulator (Simulateur TVA / taxes)

Title (EN/FR): VAT & Withholding Tax Simulator / Simulateur TVA et retenues à la source
Target learner: Licence 2 / Licence 3
Pedagogical objective: Students routinely mis-post recoverable VAT (4451) vs. collected VAT (4452) and confuse the net/gross/tax triangle. OHADA-zone VAT rates vary by country (18–20%) and withholding regimes add further complexity.
Core interaction: Given a purchase or sale invoice (amount HT, VAT rate, optional withholding), the learner computes VAT and net amounts, selects the correct SYSCOHADA accounts for each journal line, and verifies the tax payable balance. A live "tax triangle" diagram updates as they type.
Minimum viable inputs / outputs: Invoice amount (HT), VAT rate selector, transaction type, withholding toggle → journal entry, tax payable/recoverable balances, score. Country-specific presets (Côte d'Ivoire, Sénégal, Cameroun, Congo).
Why it complements existing playgrounds: Fills the most important OHADA-specific tax gap not addressed by any current playground.


Idea 3 — Payroll & Social Charges Calculator (Calculateur de paie)

Title (EN/FR): Payroll & Social Charges Calculator / Calculateur de paie et charges sociales
Target learner: Licence 3 / practicing professional (HR/accounting staff)
Pedagogical objective: African payroll computation is a frequent source of errors: CNPS contributions, IRPP brackets, and the employer/employee split differ by country and are often misapplied.
Core interaction: The learner enters gross salary and selects a country (Cameroun, Côte d'Ivoire, Sénégal, Gabon). The playground computes gross → employee deductions (CNPS, IRPP) → net pay, plus employer CNPS share and training levy, then generates the full payroll journal entry with SYSCOHADA accounts (641x, 431x, 444x).
Minimum viable inputs / outputs: Gross salary, country selector, number of dependents → net pay, deduction breakdown, employer cost, journal entry.
Why it complements existing playgrounds: No existing playground touches HR accounting or tax administration. Payroll is a daily task for OHADA-zone accountants with direct legal exposure.


Idea 4 — Foreign Currency Transaction Trainer (Transactions en devises)

Title (EN/FR): Foreign Currency Transaction Trainer / Transactions en devises étrangères
Target learner: Master 1 / Master 2 / practicing professional
Pedagogical objective: SYSCOHADA requires revaluation of monetary items at closing rate and recognition of unrealized exchange differences in accounts 476/477. Students confuse the three separate events: transaction-date recording, payment-date settlement, and year-end revaluation.
Core interaction: A three-stage timeline steps the learner through: (1) invoice date — record at spot rate; (2) payment date — record settlement and realized FX gain/loss (776/676); (3) year-end — revalue open receivable/payable at closing rate and post unrealized difference to 476/477. A rate slider makes it easy to see how a weakening CFA franc changes each entry.
Minimum viable inputs / outputs: Invoice amount (foreign currency), invoice/payment/year-end exchange rates, transaction type → three journal entries, running balance, net FX impact. Optional IFRS IAS 21 comparison mode.
Why it complements existing playgrounds: The only multi-currency mechanics topic in the curriculum; not addressed by any current playground.


Idea 5 — Cash Flow Statement Builder (Tableau des flux de trésorerie)

Title (EN/FR): Cash Flow Statement Builder / Tableau des flux de trésorerie — méthode indirecte
Target learner: Master 1 / Master 2
Pedagogical objective: Most students can produce a P&L but cannot derive operating cash flow using the indirect method — adjusting net income for non-cash items and working capital changes. A standard DSCG and OHADA audit exam topic.
Core interaction: Given net income, depreciation charge, and balance sheet deltas (receivables, payables, inventory), the learner classifies each item (Add-back, Deduction, Working Capital Change) by dragging it to the correct TFT row. Running cash-from-operations updates live. A toggle switches between SYSCOHADA TFT format and IAS 7.
Minimum viable inputs / outputs: Net income, depreciation, Δ receivables/payables/inventory, capex → completed indirect-method TFT (Operating + Investing + Financing), net change in cash, score.
Why it complements existing playgrounds: Completes the trio of SYSCOHADA primary financial statements alongside the Financial Statement Builder (Idea 1). No current playground addresses cash flow mechanics.


Report generated by automated daily review on 2026-06-21.


Generated by Claude Code

@vercel

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

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