/** * Unit conversion service wrapper for convert-units library * Provides type-safe conversion utilities and metadata */ import convert from 'convert-units'; export type Measure = | 'angle' | 'apparentPower' | 'area' | 'current' | 'digital' | 'each' | 'energy' | 'frequency' | 'illuminance' | 'length' | 'mass' | 'pace' | 'partsPer' | 'power' | 'pressure' | 'reactiveEnergy' | 'reactivePower' | 'speed' | 'temperature' | 'time' | 'voltage' | 'volume' | 'volumeFlowRate'; export interface UnitInfo { abbr: string; measure: Measure; system: 'metric' | 'imperial' | 'bits' | 'bytes' | string; singular: string; plural: string; } export interface ConversionResult { value: number; unit: string; unitInfo: UnitInfo; } /** * Get all available measures/categories */ export function getAllMeasures(): Measure[] { return convert().measures() as Measure[]; } /** * Get all units for a specific measure */ export function getUnitsForMeasure(measure: Measure): string[] { return convert().possibilities(measure); } /** * Get detailed information about a unit */ export function getUnitInfo(unit: string): UnitInfo | null { try { const description = convert().describe(unit); return description as UnitInfo; } catch { return null; } } /** * Convert a value from one unit to another */ export function convertUnit( value: number, fromUnit: string, toUnit: string ): number { try { return convert(value).from(fromUnit).to(toUnit); } catch (error) { console.error('Conversion error:', error); return value; } } /** * Convert a value to all compatible units in the same measure */ export function convertToAll( value: number, fromUnit: string ): ConversionResult[] { try { const unitInfo = getUnitInfo(fromUnit); if (!unitInfo) return []; const compatibleUnits = getUnitsForMeasure(unitInfo.measure); return compatibleUnits.map(toUnit => { const convertedValue = convertUnit(value, fromUnit, toUnit); const toUnitInfo = getUnitInfo(toUnit); return { value: convertedValue, unit: toUnit, unitInfo: toUnitInfo!, }; }); } catch (error) { console.error('Conversion error:', error); return []; } } /** * Get category color for a measure (Tailwind class name) */ export function getCategoryColor(measure: Measure): string { const colorMap: Record = { angle: 'category-angle', apparentPower: 'category-apparent-power', area: 'category-area', current: 'category-current', digital: 'category-digital', each: 'category-each', energy: 'category-energy', frequency: 'category-frequency', illuminance: 'category-illuminance', length: 'category-length', mass: 'category-mass', pace: 'category-pace', partsPer: 'category-parts-per', power: 'category-power', pressure: 'category-pressure', reactiveEnergy: 'category-reactive-energy', reactivePower: 'category-reactive-power', speed: 'category-speed', temperature: 'category-temperature', time: 'category-time', voltage: 'category-voltage', volume: 'category-volume', volumeFlowRate: 'category-volume-flow-rate', }; return colorMap[measure]; } /** * Get category color hex value for a measure */ export function getCategoryColorHex(measure: Measure): string { const colorMap: Record = { angle: '#0EA5E9', apparentPower: '#8B5CF6', area: '#F59E0B', current: '#F59E0B', digital: '#06B6D4', each: '#64748B', energy: '#EAB308', frequency: '#A855F7', illuminance: '#84CC16', length: '#3B82F6', mass: '#10B981', pace: '#14B8A6', partsPer: '#EC4899', power: '#F43F5E', pressure: '#6366F1', reactiveEnergy: '#D946EF', reactivePower: '#E879F9', speed: '#10B981', temperature: '#EF4444', time: '#7C3AED', voltage: '#FB923C', volume: '#8B5CF6', volumeFlowRate: '#22D3EE', }; return colorMap[measure]; } /** * Format measure name for display */ export function formatMeasureName(measure: Measure): string { const nameMap: Record = { angle: 'Angle', apparentPower: 'Apparent Power', area: 'Area', current: 'Current', digital: 'Digital Storage', each: 'Each', energy: 'Energy', frequency: 'Frequency', illuminance: 'Illuminance', length: 'Length', mass: 'Mass', pace: 'Pace', partsPer: 'Parts Per', power: 'Power', pressure: 'Pressure', reactiveEnergy: 'Reactive Energy', reactivePower: 'Reactive Power', speed: 'Speed', temperature: 'Temperature', time: 'Time', voltage: 'Voltage', volume: 'Volume', volumeFlowRate: 'Volume Flow Rate', }; return nameMap[measure]; } /** * Search units by query string (fuzzy search) */ export function searchUnits(query: string): UnitInfo[] { if (!query) return []; const allMeasures = getAllMeasures(); const results: UnitInfo[] = []; const lowerQuery = query.toLowerCase(); for (const measure of allMeasures) { const units = getUnitsForMeasure(measure); for (const unit of units) { const info = getUnitInfo(unit); if (!info) continue; const searchableText = [ info.abbr, info.singular, info.plural, measure, formatMeasureName(measure), ] .join(' ') .toLowerCase(); if (searchableText.includes(lowerQuery)) { results.push(info); } } } return results; }