import type { UnitPrice } from '../types'; const METRIC_UNITS = ['g', 'kg', 'ml', 'l']; const IMPERIAL_UNITS = ['oz', 'lb', 'fl oz']; const CONVERSIONS: Record = { // metric to imperial g: { to: 'oz', factor: 0.035274 }, kg: { to: 'lb', factor: 2.20462 }, ml: { to: 'fl oz', factor: 0.033814 }, l: { to: 'fl oz', factor: 33.814 }, // imperial to metric oz: { to: 'g', factor: 28.3495 }, lb: { to: 'kg', factor: 0.453592 }, 'fl oz': { to: 'ml', factor: 29.5735 }, }; interface FormattedPrice { price: string; unit: string | null; } /** * Converts a unit price to the target system and formats it for display. * @param unitPrice The structured unit price object from the database. * @param system The target system ('metric' or 'imperial'). * @returns An object with formatted price and unit strings. */ export const formatUnitPrice = (unitPrice: UnitPrice | null | undefined, system: 'metric' | 'imperial'): FormattedPrice => { if (!unitPrice || typeof unitPrice.value !== 'number' || !unitPrice.unit) { return { price: '—', unit: null }; } const { value, unit } = unitPrice; const isMetric = METRIC_UNITS.includes(unit); const isImperial = IMPERIAL_UNITS.includes(unit); let displayValue = value; let displayUnit = unit; if (system === 'imperial' && isMetric) { const conversion = CONVERSIONS[unit]; if (conversion) { displayValue = value * conversion.factor; displayUnit = conversion.to; } } else if (system === 'metric' && isImperial) { const conversion = CONVERSIONS[unit]; if (conversion) { displayValue = value * conversion.factor; displayUnit = conversion.to; } } // Smart formatting for price const formattedPrice = displayValue < 0.10 ? displayValue.toLocaleString('en-US', { style: 'currency', currency: 'USD', minimumFractionDigits: 3, maximumFractionDigits: 3 }) : displayValue.toLocaleString('en-US', { style: 'currency', currency: 'USD', minimumFractionDigits: 2, maximumFractionDigits: 2 }); // Always show a unit if one exists for clarity if (displayUnit === 'each') { return { price: formattedPrice, unit: '/each' }; } return { price: formattedPrice, unit: `/${displayUnit}` }; }; /** * Converts an imperial unit price to its metric equivalent for database storage. * @param unitPrice The structured unit price object, potentially in imperial units. * @returns A unit price object with metric units, or the original if already metric or not applicable. */ export const convertToMetric = (unitPrice: UnitPrice | null | undefined): UnitPrice | null | undefined => { if (!unitPrice || typeof unitPrice.value !== 'number' || !unitPrice.unit) { return unitPrice; } const { value, unit } = unitPrice; const isImperial = IMPERIAL_UNITS.includes(unit); if (isImperial) { const conversion = CONVERSIONS[unit]; if (conversion) { return { value: value * conversion.factor, unit: conversion.to, }; } } // Return original if it's already metric or not a weight/volume unit (like 'each') return unitPrice; };