From 989baa9be749fabdc10e97e37e6a95501c718738 Mon Sep 17 00:00:00 2001 From: Timothy Cardoza Date: Fri, 13 Mar 2026 16:28:43 -0500 Subject: [PATCH] Tables Good --- src/ItemExtractor.tsx | 6 -- src/components/EstimateBuilder.tsx | 32 ++++++- .../estimate-builder/BuilderHeader.tsx | 86 +++++++++++------- .../estimate-builder/NewEstimateModal.tsx | 90 +++++++++++++++++++ src/store/appStore.ts | 19 +++- 5 files changed, 193 insertions(+), 40 deletions(-) create mode 100644 src/components/estimate-builder/NewEstimateModal.tsx diff --git a/src/ItemExtractor.tsx b/src/ItemExtractor.tsx index 72734f8..1d85f40 100644 --- a/src/ItemExtractor.tsx +++ b/src/ItemExtractor.tsx @@ -23,7 +23,6 @@ const ItemExtractor: Component = () => { const ignoredLines = appStore.ignoredLines; const setIgnoredLines = appStore.setIgnoredLines; const estimateItems = appStore.estimateItems; - const setEstimateName = appStore.setEstimateName; const [showToast] = createSignal(false); const [toastMessage] = createSignal(''); @@ -80,11 +79,6 @@ const ItemExtractor: Component = () => {
{ - setItems([]); - setIgnoredLines([]); - setEstimateName(''); - }} />
diff --git a/src/components/EstimateBuilder.tsx b/src/components/EstimateBuilder.tsx index 1f57754..f2f24c9 100644 --- a/src/components/EstimateBuilder.tsx +++ b/src/components/EstimateBuilder.tsx @@ -15,6 +15,7 @@ import CloudLoadModal from './CloudLoadModal'; import ExportTableModal from './ExportTableModal'; import ApplyTemplateModal from './ApplyTemplateModal'; import HistoryModal from './estimate-builder/HistoryModal'; +import { NewEstimateModal } from './estimate-builder/NewEstimateModal'; // Import extracted components & hooks import { useEstimateCalculations } from './estimate-builder/useEstimateCalculations'; @@ -33,7 +34,6 @@ import { ScopesList } from './estimate-builder/ScopesList'; interface EstimateBuilderProps { initialItems: ExtractedItem[]; - onReset: () => void; } const EstimateBuilder: Component = (props) => { @@ -48,6 +48,7 @@ const EstimateBuilder: Component = (props) => { const [showSaveModal, setShowSaveModal] = createSignal(false); const [showLoadModal, setShowLoadModal] = createSignal(false); const [showHistoryModal, setShowHistoryModal] = createSignal(false); + const [showNewEstimateModal, setShowNewEstimateModal] = createSignal(false); const [showExportTableModal, setShowExportTableModal] = createSignal(false); const [applyTemplateScopeId, setApplyTemplateScopeId] = createSignal(null); @@ -105,6 +106,7 @@ const EstimateBuilder: Component = (props) => { setScopes(prev => [...prev, newScope]); addSubScopeWithName(scopeId, 'Materials'); addSubScopeWithName(scopeId, 'Labor'); + return scopeId; }; const addSubScopeWithName = (scopeId: string, name: string) => { @@ -114,6 +116,7 @@ const EstimateBuilder: Component = (props) => { scopeId }; setSubScopes(prev => [...prev, newSubScope]); + return newSubScope.id; }; const addSubScope = (scopeId: string) => { @@ -195,14 +198,14 @@ const EstimateBuilder: Component = (props) => { isSidebarCollapsed={isSidebarCollapsed()} onToggleSidebar={() => setIsSidebarCollapsed(!isSidebarCollapsed())} onAddScope={addScope} - onReset={props.onReset} + onShowNewEstimateModal={() => setShowNewEstimateModal(true)} onImportEstimate={importEstimate} onShowExportTableModal={() => setShowExportTableModal(true)} onExportEstimate={exportEstimate} onShowLoadModal={() => setShowLoadModal(true)} onShowSaveModal={() => setShowSaveModal(true)} onShowHistoryModal={() => setShowHistoryModal(true)} - onSaveChanges={saveChangesToCloud} + onSaveChanges={() => appStore.isLatestVersion() ? saveChangesToCloud() : saveAsNewestToCloud()} />
@@ -358,6 +361,29 @@ const EstimateBuilder: Component = (props) => { setShowExportTableModal(false)} /> setApplyTemplateScopeId(null)} /> setShowHistoryModal(false)} onCheckout={checkoutVersion} /> + + setShowNewEstimateModal(false)} + onResetCSV={() => { + appStore.resetEstimate(); + setShowNewEstimateModal(false); + }} + onManualEstimate={() => { + appStore.resetEstimate(); + setItems([{ + id: crypto.randomUUID(), + description: 'Item', + quantity: 1, + unitPrice: 0, + markup: 0, + markupType: 'percent', + contingency: 0, + contingencyType: 'percent' + }]); + setShowNewEstimateModal(false); + }} + />
); }; diff --git a/src/components/estimate-builder/BuilderHeader.tsx b/src/components/estimate-builder/BuilderHeader.tsx index 617f1bf..02c5708 100644 --- a/src/components/estimate-builder/BuilderHeader.tsx +++ b/src/components/estimate-builder/BuilderHeader.tsx @@ -1,13 +1,13 @@ -import { Show } from 'solid-js'; +import { createSignal, onCleanup, Show } from 'solid-js'; import type { Component } from 'solid-js'; -import { PanelLeftOpen, PanelLeftClose, Calculator, Plus, FileUp, Upload, Table, Download, History, Save } from 'lucide-solid'; +import { PanelLeftOpen, PanelLeftClose, Calculator, Plus, Upload, Table, Download, History, Save, ChevronDown, MoreHorizontal } from 'lucide-solid'; import { appStore } from '../../store/appStore'; interface BuilderHeaderProps { isSidebarCollapsed: boolean; onToggleSidebar: () => void; onAddScope: () => void; - onReset: () => void; + onShowNewEstimateModal: () => void; onImportEstimate: (e: Event) => void; onShowExportTableModal: () => void; onExportEstimate: () => void; @@ -19,6 +19,17 @@ interface BuilderHeaderProps { export const BuilderHeader: Component = (props) => { const { scopes, estimateItems: items } = appStore; + const [showActions, setShowActions] = createSignal(false); + let dropdownRef: HTMLDivElement | undefined; + + const handleClickOutside = (e: MouseEvent) => { + if (dropdownRef && !dropdownRef.contains(e.target as Node)) { + setShowActions(false); + } + }; + + window.addEventListener('click', handleClickOutside); + onCleanup(() => window.removeEventListener('click', handleClickOutside)); return (
@@ -46,38 +57,53 @@ export const BuilderHeader: Component = (props) => {
- -
- -