basic module setup

This commit is contained in:
2026-03-16 13:38:22 -05:00
parent f4ad67e097
commit 865c4a954c
10 changed files with 373 additions and 14 deletions
+26 -3
View File
@@ -1,5 +1,4 @@
import type { Component } from 'solid-js';
import { For, createMemo, Show, createSignal } from 'solid-js';
import { For, Show, createMemo, createSignal, type Component } from 'solid-js';
import { Trash2, Plus, Settings2, Percent, DollarSign, ChevronDown, FileText, ClipboardList, FileBox } from 'lucide-solid';
import NumericInput from './ui/NumericInput';
import type { EstimateItem, Scope, SubScope, PricingType } from '../types';
@@ -8,6 +7,7 @@ import SubScopeCard from './SubScopeCard';
import NoteEditor from './NoteEditor';
import LazyItem from './LazyItem';
import ScopeScaleWrapper from './ui/ScopeScaleWrapper';
import { ModifierRegistry } from '../utils/modifier-registry';
interface ScopeCardProps {
scope: Scope;
@@ -68,14 +68,31 @@ const ScopeCard: Component<ScopeCardProps> = (props) => {
? subtotal * (props.scope.deliveryFee / 100)
: props.scope.deliveryFee;
let modifiersTotal = 0;
props.subScopes.forEach(ss => {
const ssItems = props.items.filter(i => i.subScopeId === ss.id);
const ssTotalWithMarkup = ssItems.reduce((sum, item) => {
const base = item.quantity * item.unitPrice;
const markup = item.markupType === 'percent' ? base * (item.markup / 100) : item.markup;
const contingency = item.contingencyType === 'percent' ? base * (item.contingency / 100) : item.contingency;
return sum + base + markup + contingency;
}, 0);
(ss.modifiers || []).forEach(m => {
if (!m.includeInTotal) return;
modifiersTotal += ModifierRegistry.calculate(m, ssTotalWithMarkup, ssItems);
});
});
return {
subtotal,
markup,
contingency,
mgmtTotal,
deliveryTotal,
modifiersTotal,
totalQuantity,
total: subtotal + markup + contingency + mgmtTotal + deliveryTotal
total: subtotal + markup + contingency + mgmtTotal + deliveryTotal + modifiersTotal
};
});
@@ -377,6 +394,12 @@ const ScopeCard: Component<ScopeCardProps> = (props) => {
<span>Scope Contingency:</span>
<span class="w-28 text-right">${formatNumber(totals().contingency)}</span>
</div>
<Show when={totals().modifiersTotal !== 0}>
<div class="flex justify-end gap-8 text-indigo-600">
<span>Scope Modifiers:</span>
<span class="w-28 text-right">${formatNumber(totals().modifiersTotal)}</span>
</div>
</Show>
<div class="flex justify-end gap-8 font-black text-foreground text-xl mt-4">
<span>Scope Grand Total:</span>
<span class="w-32 text-right border-t-2 border-foreground pt-1">