Files
Epicure/apps/web/lib/fractions.ts
T
Arnaud 9d9dfb46c6 feat: misc — cooking mode, OpenAPI docs, email, storage, upload, homepage
Cooking mode step-by-step view. OpenAPI 3.1 spec auto-generated from Zod schemas.
Email lib (resend). Redis client. S3 storage helper. Photo upload endpoint.
Landing page. Short recipe URL redirect /r/[id]. API docs page.
2026-07-01 08:11:31 +02:00

46 lines
1.1 KiB
TypeScript

const FRACTIONS: [number, string][] = [
[1 / 8, "⅛"],
[1 / 4, "¼"],
[1 / 3, "⅓"],
[3 / 8, "⅜"],
[1 / 2, "½"],
[5 / 8, "⅝"],
[2 / 3, "⅔"],
[3 / 4, "¾"],
[7 / 8, "⅞"],
];
export function formatQuantity(value: number): string {
if (value === 0) return "0";
const whole = Math.floor(value);
const decimal = value - whole;
if (decimal < 0.05) return whole === 0 ? "0" : String(whole);
if (decimal > 0.95) return String(whole + 1);
let bestFraction = "";
let bestDiff = Infinity;
for (const [frac, symbol] of FRACTIONS) {
const diff = Math.abs(decimal - frac);
if (diff < bestDiff) {
bestDiff = diff;
bestFraction = symbol;
}
}
if (bestDiff > 0.06) {
return value.toFixed(1);
}
return whole === 0 ? bestFraction : `${whole} ${bestFraction}`;
}
export function scaleQuantity(baseQuantity: string | null, base: number, desired: number): string {
if (!baseQuantity) return "";
const raw = parseFloat(baseQuantity);
if (isNaN(raw)) return baseQuantity;
const scale = base === 0 ? 1 : desired / base;
return formatQuantity(raw * scale);
}