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.
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
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);
|
||||
}
|
||||
Reference in New Issue
Block a user