77 lines
3.0 KiB
TypeScript
77 lines
3.0 KiB
TypeScript
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 };
|
|
}
|