Skip to content

Daily review 2026-07-01 - #66

Draft
NghaReformer wants to merge 2 commits into
mainfrom
daily-review/2026-07-01
Draft

Daily review 2026-07-01#66
NghaReformer wants to merge 2 commits into
mainfrom
daily-review/2026-07-01

Conversation

@NghaReformer

@NghaReformer NghaReformer commented Jul 1, 2026

Copy link
Copy Markdown
Owner

Daily Review — 2026-07-01

1. Bugs & Issues

CRITICAL

None found.


HIGH

H-1 — Undefined CSS custom properties --orange, --blue, --red used across 9+ files

Severity: High
Files (sample):

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

Explanation: css-generator.ts emits --green, --amber, --error, and --accent among others — but never --orange, --blue, or --red. These variables are undefined at runtime, so the hex fallback in every var(--orange, #f59e0b) / var(--blue, #3b82f6) / var(--red, #ef4444) is always used. The fallbacks are Tailwind palette values, not the design-system tokens (e.g. --amber is #f5a623, not #f59e0b; --error is #f06070, not #ef4444). Theme changes will never reach these components.

Suggested fix: Replace with the nearest defined token — --orange--amber, --blue--accent, --red--error. Update css-generator.ts if explicit semantic aliases are preferred.


MEDIUM

M-1 — Client component imports from $lib/server/db/types

Severity: Medium
Files:

  • src/lib/components/feedback/FeedbackForm.svelte:7
  • src/routes/api/feedback/validation.ts:1-5

Explanation: FeedbackForm.svelte uses import type { FeedbackType, FeedbackSeverity } from '$lib/server/db/types'. Although TypeScript erases import type at compile time, SvelteKit's Vite plugin enforces $lib/server boundaries by static import analysis and may fail the build. Even if it passes today, it violates the architectural contract. validation.ts (a route co-location file) also imports from $lib/server/db/types, making it subtly server-coupled despite not being a *.server.ts file.

Suggested fix: Move the shared type-only definitions (FeedbackType, FeedbackSeverity) out of $lib/server/db/types.ts into a new $lib/types/feedback.ts. Server-only runtime code (Supabase calls, DB schemas) stays under $lib/server/.


M-2 — Hardcoded hex colors in JS color maps (not CSS custom properties)

Severity: Medium
Files:

  • src/lib/playgrounds/bank-reconciliation/components/CategoryBreakdownDonut.svelte:30-40
  • src/lib/playgrounds/bank-reconciliation/components/MatchingPairsOverlay.svelte:31-34

Explanation: CATEGORY_COLORS and the match-type color map are JS objects with raw hex values ('#6ea8fe', '#22c55e', etc.) used as SVG fill/stroke attributes. These cannot reference CSS custom properties and will not follow the theme.

Suggested fix: Define a canonical chart color set in tokens.ts and export a JS map from the theme module (e.g. getChartColors(theme)). At minimum, align values with the existing token palette so a future theme swap is a single-file change.


M-3 — Hardcoded color: #fff in 4 Svelte files

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

Explanation: Active-state and confirm-action buttons set color: #fff without a CSS variable. The pattern color: var(--bg) (page background) is already used elsewhere for this purpose and is more robust.

Suggested fix: Replace color: #fff with color: var(--bg) on accent/error-background buttons, consistent with WaitlistForm.svelte:199.


LOW

L-1 — Hardcoded "items" string not routed through i18n

Severity: Low
File: src/lib/playgrounds/bank-reconciliation/components/VarianceScale.svelte:178,197

Explanation: The scale SVG displays {bankItemCount} items / {booksItemCount} items with "items" hardcoded in English. All surrounding labels are properly passed as translated props, but this one string was missed.

Suggested fix: Add an itemsLabel prop to VarianceScale and pass $t('bank-reconciliation.items') from the parent, alongside a FR translation entry.


L-2 — Hardcoded hex colors in SVG background-image data URIs

Severity: Low
Files:

  • src/lib/components/WaitlistForm.svelte:179 (%23555c74 = --text-muted)
  • src/lib/components/feedback/FeedbackForm.svelte:322 (%23555c74)
  • src/lib/components/playground/PlaygroundSettings.svelte:94 (%237c7fff = --accent)

Explanation: SVG data URIs in background-image cannot reference CSS custom properties — browser limitation. Values match current tokens but diverge silently on theme changes.

Suggested fix: Accept as a known limitation and add a comment, or generate the data URI at runtime from getComputedStyle.


L-3 — API error messages are English-only user-facing strings

Severity: Low
Files:

  • src/routes/api/waitlist/+server.ts:33,39,50,63,66
  • src/routes/api/feedback/+server.ts:40,47,75,78,85,99

Explanation: Server error strings ({ error: "Too many requests…" }) are surfaced directly to the user via WaitlistForm.svelte:31 and displayed in the UI, bypassing the i18n system entirely.

Suggested fix: Return machine-readable error codes ({ code: 'rate_limit' }) and map them to translated strings in the Svelte component.


L-4 — Tab buttons and share button lose accessible name on mobile (WCAG 4.1.2)

Severity: Low
Files:

  • src/lib/components/playground/PlaygroundTabs.svelte.tab-label { display: none } at ≤480 px; no aria-label on buttons; icon SVG is aria-hidden
  • src/lib/components/playground/ShareButton.svelte — same pattern; .label { display: none } at ≤480 px; title attribute is unreliable as primary name source

Explanation: At mobile widths both components hide their visible label via display: none (removes element from accessibility tree) while also marking the icon SVG as aria-hidden="true". Net result: zero accessible name on those buttons for screen reader users on mobile.

Suggested fix: Add aria-label={$t(tab.labelKey)} directly on each <button> in PlaygroundTabs, and aria-label={$t('shell.share')} on the share button.


L-5 — Multi-product CVP form inputs have no programmatic label (WCAG 1.3.1)

Severity: Low
File: src/lib/playgrounds/cvp/components/MultiProductForm.svelte:93,99,106,114

Explanation: The grid renders visual header <span> elements that are not associated with the corresponding <input> elements — no for/id linkage, no aria-label, no aria-labelledby. Screen readers announce these inputs without any context ("edit text" instead of "Product name, row 1").

Suggested fix: Add aria-label to each input, e.g. aria-label="{translate('cvp.product.name')} {i + 1}".


L-6 — --green CSS fallback value mismatches the actual token

Severity: Low
Files: Multiple (e.g. VarianceScale.svelte:223, ReconciliationStatement.svelte:275)

Explanation: Many var(--green, #22c55e) calls use #22c55e (Tailwind green-500) as the fallback. The actual theme token is #34d399. Since --green IS defined by the generator, the fallback is never used at runtime — but the misleading value creates confusion in authoring and static analysis tools.

Suggested fix: Remove the fallback from var(--green) calls, or update fallbacks to match the token value.


2. New Playground Ideas

Existing coverage: amortization, bank reconciliation, CVP/break-even, simple/compound interest, journal entry, TVM (FV/PV, IRR/NPV, annuities). Static HTML playgrounds also cover depreciation and basic journal entries.


Idea 1 — Inventory Valuation Methods

Title (EN): Inventory Costing Methods | Title (FR): Méthodes d'évaluation des stocks
Target learner: Licence 2, practicing accountant
Pedagogical objective: SYSCOHADA mandates weighted-average cost (CMP); students regularly confuse it with FIFO and sometimes erroneously apply LIFO (not permitted under SYSCOHADA). Side-by-side comparison fixes this misconception.
Core interaction: Enter a sequence of inventory movements (purchases + sales). Engine computes COGS and ending inventory under FIFO, CMP, and a greyed-out LIFO column. A live banner shows XAF impact on net income between methods.
Minimum viable inputs: Initial stock (qty + unit cost), up to 10 purchase/sale transactions.
Outputs: Inventory ledger per method, COGS total, ending inventory value, income difference, SYSCOHADA compliance flag.
Complement: Fills the gap between the amortization playground (asset cost allocation) and the journal-entry playground (recording movements). Reuses format/currency.ts and AccountPicker.


Idea 2 — VAT / TVA Computation and Return

Title (EN): VAT Calculation & Return | Title (FR): Calcul de TVA et déclaration
Target learner: Licence 3, Master, practicing accountant
Pedagogical objective: Students struggle to compute net TVA payable (output minus deductible input TVA) and to apply country-specific OHADA-zone rates (18 % Cameroon, 19.25 % Côte d'Ivoire, etc.).
Core interaction: Enter sales and purchase invoices for a period, select country/rate, classify each line. Engine builds the TVA return form and computes net balance due or refundable.
Minimum viable inputs: Country (drives rate), up to 15 invoices per direction with HT amount and taxability class.
Outputs: TVA return summary, SYSCOHADA journal entries (4441/4455 accounts), common error highlights.
Complement: Bridges journal-entry mechanics to real-world tax compliance. Uses format/currency.ts with FCFA-zone currencies.


Idea 3 — Payroll / Bulletin de Paie

Title (EN): Payroll Calculator | Title (FR): Simulateur de Bulletin de Paie
Target learner: Licence 3, Master, HR/finance practitioner
Pedagogical objective: Students cannot map gross salary to employer cost or produce SYSCOHADA journal entries (641, 431, 447) for payroll. CNPS contributions and IRPP withholding are taught abstractly.
Core interaction: Enter gross salary, employee category, family charges, and OHADA country. Sliders experiment with gross salary to see IRPP brackets apply progressively. Output shows the payslip breakdown and the four journal entries an employer must post.
Minimum viable inputs: Country, gross salary, employee category (cadre/non-cadre), number of dependants.
Outputs: Net-to-gross bridge, CNPS employer/employee split, IRPP by bracket, CAC/RAV where applicable, payslip layout, SYSCOHADA journal entries.
Complement: The most-requested real-world topic not yet covered. Reuses journal entry display components and fmtCurrency for FCFA amounts.


Idea 4 — Financial Ratio Dashboard

Title (EN): Financial Ratio Dashboard | Title (FR): Tableau de Bord des Ratios Financiers
Target learner: Licence 3, Master
Pedagogical objective: Students compute individual ratios in isolation but miss how ratio families interact and what thresholds signal distress under SYSCOHADA's TAFIRE framework.
Core interaction: Fill in a simplified SYSCOHADA balance sheet and income statement. Dashboard instantly computes and colour-codes 12 ratios across four families (liquidity, solvency, profitability, activity) with OHADA-zone SME benchmarks.
Minimum viable inputs: 8–10 key balance-sheet line items (BFR, trésorerie, fonds propres, total bilan, CA, résultat net).
Outputs: Ratio tiles with traffic-light status, radar chart, one-sentence interpretation per ratio, TAFIRE indicators.
Complement: Synthesis playground drawing on all existing modules. Reuses KpiStrip and cvp/chart-utils.ts.


Idea 5 — Depreciation Method Comparison (SYSCOHADA vs IFRS)

Title (EN): Depreciation Method Comparison | Title (FR): Comparaison des Méthodes d'Amortissement
Target learner: Licence 2/3, Master
Pedagogical objective: The existing static HTML depreciation playground shows one method in isolation. Students confuse straight-line, declining-balance, and units-of-production and don't understand how SYSCOHADA differs from IFRS on component depreciation.
Core interaction: Side-by-side schedule tables for three methods with a SYSCOHADA/IFRS toggle. Chart overlay shows NBV divergence between methods.
Minimum viable inputs: Asset cost, residual value, useful life, declining-balance rate, annual production/hours.
Outputs: Three parallel amortization tables, carrying-value comparison chart, income difference per year.
Complement: Directly supersedes the static depreciation-playground.html as a native Svelte module, integrating with the amortization playground's existing engine.ts and ScheduleTable components.

@vercel

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

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