75 lines
2.6 KiB
Markdown
75 lines
2.6 KiB
Markdown
# Code Quality Improvements (Round 2) Design
|
|
|
|
**Date:** 2026-04-03
|
|
**Scope:** Combined formatters hook, test helper schema generation, stale todo cleanup
|
|
|
|
## 1. useFormatters Combined Hook
|
|
|
|
**Problem:** 14 component files import the same 3-4 lines: `useWeightUnit`, `useCurrency`, `formatWeight`, `formatPrice`. This is repetitive boilerplate.
|
|
|
|
**Solution:** Create `src/client/hooks/useFormatters.ts` that returns pre-bound formatting functions:
|
|
|
|
```ts
|
|
export function useFormatters() {
|
|
const unit = useWeightUnit();
|
|
const currency = useCurrency();
|
|
return {
|
|
weight: (grams: number | null) => formatWeight(grams, unit),
|
|
price: (cents: number | null) => formatPrice(cents, currency),
|
|
unit,
|
|
currency,
|
|
};
|
|
}
|
|
```
|
|
|
|
**Consumer files to update (14):**
|
|
- CollectionView.tsx
|
|
- setups/$setupId.tsx
|
|
- routes/index.tsx
|
|
- WeightSummaryCard.tsx
|
|
- TotalsBar.tsx
|
|
- settings.tsx
|
|
- ThreadCard.tsx
|
|
- SetupCard.tsx
|
|
- ItemPicker.tsx
|
|
- ItemCard.tsx
|
|
- ComparisonTable.tsx
|
|
- CandidateCard.tsx
|
|
- CandidateListItem.tsx
|
|
- CategoryHeader.tsx
|
|
|
|
Each file replaces 3-4 imports + 2 hook calls with 1 import + 1 destructured hook call. Components that need raw `unit` or `currency` (e.g., WeightSummaryCard uses `unit` as a type, TotalsBar has a unit toggle) get them from the return object.
|
|
|
|
## 2. Test Helper Schema Generation
|
|
|
|
**Problem:** `tests/helpers/db.ts` has 120 lines of hand-written CREATE TABLE SQL that must manually mirror `src/db/schema.ts`. Any schema change requires updating both files — a known source of `SqliteError: no such column` failures.
|
|
|
|
**Solution:** Replace hand-written SQL with Drizzle's migration runner:
|
|
|
|
```ts
|
|
import { migrate } from "drizzle-orm/bun-sqlite/migrator";
|
|
|
|
export function createTestDb() {
|
|
const sqlite = new Database(":memory:");
|
|
sqlite.run("PRAGMA foreign_keys = ON");
|
|
const db = drizzle(sqlite, { schema });
|
|
migrate(db, { migrationsFolder: "./drizzle" });
|
|
db.insert(schema.categories).values({ name: "Uncategorized", icon: "package" }).run();
|
|
return db;
|
|
}
|
|
```
|
|
|
|
This reduces the file from ~128 lines to ~15 lines and eliminates all future manual sync.
|
|
|
|
## 3. Stale Todo Cleanup
|
|
|
|
**Problem:** Pending todo "Replace planning category filter select with icon-aware dropdown" from 2026-03-15 is already resolved — `PlanningView.tsx` uses `<CategoryFilterDropdown>` which renders Lucide icons.
|
|
|
|
**Solution:** Move the todo file from `pending/` to `done/`.
|
|
|
|
## Commit Strategy
|
|
|
|
1. **useFormatters hook** — create hook + update all 14 consumer files
|
|
2. **Test helper migration** — replace hand-written SQL with migrate()
|
|
3. **Todo cleanup** — move stale todo to done
|