Update from CSV added

This commit is contained in:
2026-03-19 14:48:15 -05:00
parent f2dcff7b71
commit c2f384a105
8 changed files with 632 additions and 9 deletions
+48 -1
View File
@@ -1,7 +1,7 @@
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';
import type { EstimateItem, Scope, SubScope, PricingType, ScopeTextTemplateType } from '../types';
import ItemRow from './ItemRow';
import SubScopeCard from './SubScopeCard';
import NoteEditor from './NoteEditor';
@@ -10,6 +10,7 @@ import ScopeScaleWrapper from './ui/ScopeScaleWrapper';
import { ModifierRegistry } from '../utils/modifier-registry';
import { appStore } from '../store/appStore';
import { SupplierDropdown } from './ui/SupplierDropdown';
import ScopeTextTemplateModal from './ScopeTextTemplateModal';
interface ScopeCardProps {
scope: Scope;
@@ -44,6 +45,8 @@ const ScopeCard: Component<ScopeCardProps> = (props) => {
const [bulkMarkup, setBulkMarkup] = createSignal(0);
const [bulkContingency, setBulkContingency] = createSignal(0);
const [isOver, setIsOver] = createSignal(false);
const [activeTemplateType, setActiveTemplateType] = createSignal<ScopeTextTemplateType>('estimatorNotes');
const [isTemplateModalOpen, setIsTemplateModalOpen] = createSignal(false);
const scopeItems = createMemo(() => props.items.filter(i => !i.subScopeId));
@@ -116,6 +119,26 @@ const ScopeCard: Component<ScopeCardProps> = (props) => {
setIsOver(false);
};
const openTemplateModal = (type: ScopeTextTemplateType) => {
setActiveTemplateType(type);
setIsTemplateModalOpen(true);
};
const templateModalCurrentValue = createMemo(() =>
activeTemplateType() === 'estimatorNotes'
? props.scope.estimatorNotes || ''
: props.scope.bidDescription || ''
);
const applyTemplateValue = (value: string) => {
if (activeTemplateType() === 'estimatorNotes') {
props.onUpdateScope(props.scope.id, { estimatorNotes: value });
return;
}
props.onUpdateScope(props.scope.id, { bidDescription: value });
};
return (
<div
onDragOver={handleDragOver}
@@ -460,6 +483,14 @@ const ScopeCard: Component<ScopeCardProps> = (props) => {
onUpdate={(val) => props.onUpdateScope(props.scope.id, { estimatorNotes: val })}
icon={ClipboardList}
highlight={props.scope.estimatorNotes?.includes('#')}
headerActions={
<button
onClick={() => openTemplateModal('estimatorNotes')}
class="px-3 py-1 rounded-lg text-[10px] font-bold transition-all border text-muted-foreground hover:bg-muted border-border/40"
>
Template
</button>
}
/>
<NoteEditor
label="Scope Description (Appears on Finale Estimate)"
@@ -467,6 +498,14 @@ const ScopeCard: Component<ScopeCardProps> = (props) => {
onUpdate={(val) => props.onUpdateScope(props.scope.id, { bidDescription: val })}
icon={FileText}
highlight={props.scope.bidDescription?.includes('#')}
headerActions={
<button
onClick={() => openTemplateModal('bidDescription')}
class="px-3 py-1 rounded-lg text-[10px] font-bold transition-all border text-muted-foreground hover:bg-muted border-border/40"
>
Template
</button>
}
/>
</div>
@@ -504,6 +543,14 @@ const ScopeCard: Component<ScopeCardProps> = (props) => {
</div>
</div>
</Show>
<ScopeTextTemplateModal
show={isTemplateModalOpen()}
templateType={activeTemplateType()}
currentValue={templateModalCurrentValue()}
onApply={applyTemplateValue}
onClose={() => setIsTemplateModalOpen(false)}
/>
</div>
);
};