Files
EstiMaker/src/utils/modifier-registry.ts
T
2026-03-16 14:22:01 -05:00

76 lines
2.5 KiB
TypeScript

import type { Modifier, EstimateItem } from '../types';
export interface ModifierModule {
id: string;
name: string;
description: string;
defaultLabel: string;
defaultValue: number;
defaultValueType: 'percent' | 'amount' | 'unit';
defaultUnitLabel?: string;
calculate: (modifier: Modifier, subScopeTotalWithMarkup: number, subScopeItems: EstimateItem[]) => number;
calculateDisplay?: (modifier: Modifier, subScopeTotalWithMarkup: number, subScopeItems: EstimateItem[]) => number;
}
const TaxModule: ModifierModule = {
id: 'tax',
name: 'Tax',
description: 'Calculates percentage tax on the sub-scope total.',
defaultLabel: 'Sales Tax',
defaultValue: 0,
defaultValueType: 'percent',
calculate: (m, base) => {
if (m.valueType === 'percent') return base * (m.value / 100);
return m.value;
}
};
const ManHoursModule: ModifierModule = {
id: 'man-hours',
name: 'Man-Hours',
description: 'Calculates labor hours by dividing the sub-scope subtotal by a production factor.',
defaultLabel: 'Estimated Hours',
defaultValue: 30,
defaultValueType: 'unit',
defaultUnitLabel: 'factor',
calculate: () => 0,
calculateDisplay: (m, base) => {
const factor = m.value || 1;
return base / factor;
}
};
const SimpleAdjustmentModule: ModifierModule = {
id: 'adjustment',
name: 'Fixed adjustment',
description: 'Adds or subtracts a fixed amount or percentage.',
defaultLabel: 'Adjustment',
defaultValue: 0,
defaultValueType: 'amount',
calculate: (m, base) => {
if (m.valueType === 'percent') return base * (m.value / 100);
return m.value;
}
};
export const MODIFIER_MODULES: ModifierModule[] = [
TaxModule,
ManHoursModule,
SimpleAdjustmentModule
];
export const ModifierRegistry = {
getModule: (id: string) => MODIFIER_MODULES.find(m => m.id === id) || SimpleAdjustmentModule,
calculate: (modifier: Modifier, baseTotal: number, items: EstimateItem[]) => {
const module = ModifierRegistry.getModule(modifier.moduleId);
return module.calculate(modifier, baseTotal, items);
},
calculateDisplay: (modifier: Modifier, baseTotal: number, items: EstimateItem[]) => {
const module = ModifierRegistry.getModule(modifier.moduleId);
if (module.calculateDisplay) return module.calculateDisplay(modifier, baseTotal, items);
return module.calculate(modifier, baseTotal, items);
}
};