Breakup of EstimateBuilder.tsx
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
import { createSignal } from 'solid-js';
|
||||
import { appStore } from '../../store/appStore';
|
||||
import type { EstimateItem } from '../../types';
|
||||
|
||||
export function useSelectionManager() {
|
||||
const [selectedIds, setSelectedIds] = createSignal<string[]>([]);
|
||||
const [lastSelectedId, setLastSelectedId] = createSignal<string | null>(null);
|
||||
|
||||
const getVisualOrderedItems = () => {
|
||||
const { estimateItems: items, scopes, subScopes } = appStore;
|
||||
const ordered: EstimateItem[] = [];
|
||||
|
||||
ordered.push(...items.filter(i => !i.scopeId));
|
||||
|
||||
scopes.forEach(scope => {
|
||||
ordered.push(...items.filter(i => i.scopeId === scope.id && !i.subScopeId));
|
||||
subScopes.filter(ss => ss.scopeId === scope.id).forEach(ss => {
|
||||
ordered.push(...items.filter(i => i.subScopeId === ss.id));
|
||||
});
|
||||
});
|
||||
|
||||
return ordered;
|
||||
};
|
||||
|
||||
const toggleSelection = (id: string, isMulti: boolean, isShift: boolean = false) => {
|
||||
if (isShift && lastSelectedId()) {
|
||||
const orderedItems = getVisualOrderedItems();
|
||||
const lastIdx = orderedItems.findIndex(i => i.id === lastSelectedId());
|
||||
const currentIdx = orderedItems.findIndex(i => i.id === id);
|
||||
|
||||
if (lastIdx !== -1 && currentIdx !== -1) {
|
||||
const start = Math.min(lastIdx, currentIdx);
|
||||
const end = Math.max(lastIdx, currentIdx);
|
||||
const rangeIds = orderedItems.slice(start, end + 1).map(i => i.id);
|
||||
|
||||
setSelectedIds(prev => {
|
||||
const newSet = new Set(prev);
|
||||
rangeIds.forEach(rid => newSet.add(rid));
|
||||
return Array.from(newSet);
|
||||
});
|
||||
}
|
||||
} else if (isMulti) {
|
||||
setSelectedIds(prev => prev.includes(id)
|
||||
? prev.filter(i => i !== id)
|
||||
: [...prev, id]
|
||||
);
|
||||
} else {
|
||||
if (selectedIds().includes(id) && selectedIds().length === 1) {
|
||||
setSelectedIds([]);
|
||||
} else {
|
||||
setSelectedIds([id]);
|
||||
}
|
||||
}
|
||||
setLastSelectedId(id);
|
||||
};
|
||||
|
||||
const clearSelection = (e?: MouseEvent) => {
|
||||
if (!e || e.target === e.currentTarget) {
|
||||
setSelectedIds([]);
|
||||
setLastSelectedId(null);
|
||||
}
|
||||
};
|
||||
|
||||
const copyColumnSum = (column: 'quantity'|'unitPrice'|'subtotal'|'markup'|'contingency'|'total', val: number, setCopyToast: (msg: string | null) => void) => {
|
||||
navigator.clipboard.writeText(String(val)).then(() => {
|
||||
const labels: Record<string, string> = {
|
||||
quantity: 'Qty', unitPrice: 'Price', subtotal: 'Subtotal',
|
||||
markup: 'Markup', contingency: 'Contingency', total: 'Total'
|
||||
};
|
||||
setCopyToast(`Copied ${labels[column]}: ${val}`);
|
||||
setTimeout(() => setCopyToast(null), 2500);
|
||||
});
|
||||
};
|
||||
|
||||
return { selectedIds, setSelectedIds, lastSelectedId, setLastSelectedId, toggleSelection, clearSelection, copyColumnSum };
|
||||
}
|
||||
Reference in New Issue
Block a user