Files
EstiMaker/src/components/estimate-builder/UnassignedItemsSection.tsx
T
2026-03-11 15:03:59 -05:00

87 lines
4.6 KiB
TypeScript

import type { Component, Accessor } from 'solid-js';
import { Show, For } from 'solid-js';
import { ListTree } from 'lucide-solid';
import ItemRow from '../ItemRow';
import LazyItem from '../LazyItem';
import type { EstimateItem } from '../../types';
interface UnassignedItemsSectionProps {
unassignedItems: EstimateItem[];
isSidebarCollapsed: Accessor<boolean>;
anyDescriptionIsLong: Accessor<boolean>;
selectedIds: string[];
onDrop: (e: DragEvent, scopeId?: string, subScopeId?: string) => void;
clearSelection: (e: MouseEvent) => void;
updateItem: (id: string, updates: Partial<EstimateItem>) => void;
deleteItem: (id: string) => void;
handleDragStart: (e: DragEvent, id: string) => void;
duplicateItem: (id: string) => void;
toggleSelection: (id: string, isMulti: boolean, isShift: boolean) => void;
}
export const UnassignedItemsSection: Component<UnassignedItemsSectionProps> = (props) => {
return (
<Show when={props.unassignedItems.length > 0}>
<div
id="unassigned-section"
onDragOver={(e) => e.preventDefault()}
onDrop={(e) => props.onDrop(e, undefined, undefined)}
onClick={props.clearSelection}
class="bg-muted/10 border-2 border-dashed border-border rounded-3xl p-6 transition-all hover:bg-muted/20"
>
<div class="flex items-center justify-between mb-6">
<div class="flex items-center gap-3 text-foreground">
<div class="p-2 bg-primary/10 rounded-xl text-primary shadow-sm">
<ListTree class="w-5 h-5" />
</div>
<div>
<h3 class="font-black text-lg tracking-tight">Unassigned Takeoff Items</h3>
<p class="text-muted-foreground text-sm">Drag these items into scopes to begin your estimate.</p>
</div>
</div>
<span class="px-4 py-1.5 bg-card border border-border text-primary rounded-full text-[10px] font-black uppercase tracking-widest shadow-sm">
{props.unassignedItems.length} Items Pending
</span>
</div>
<div class="relative pb-4">
{/* Sticky Column Headers for Unassigned */}
<div class="sticky top-header z-10 bg-background/95 backdrop-blur-sm border-b border-border py-3 mb-4 hidden md:flex items-center gap-4 text-[10px] font-black text-muted-foreground/60 uppercase tracking-[0.2em] px-3">
<div class="w-4 shrink-0"></div>
<div class="flex-1 min-w-[200px]">Description</div>
<div class="w-20 shrink-0 text-right">Qty</div>
<div class="w-24 shrink-0 text-right">Unit Price</div>
<div class="w-24 shrink-0 text-right">Subtotal</div>
<Show when={props.isSidebarCollapsed() || !props.anyDescriptionIsLong()}>
<div class="w-32 shrink-0 text-center">Markup</div>
<div class="w-32 shrink-0 text-center">Contingency</div>
</Show>
<div class="w-28 shrink-0 text-right">Total</div>
<div class="w-16 shrink-0"></div>
</div>
<div class="grid gap-2">
<For each={props.unassignedItems}>
{(item) => (
<LazyItem estimatedHeight={60}>
<ItemRow
item={item}
onUpdate={props.updateItem}
onDelete={props.deleteItem}
onDragStart={props.handleDragStart}
onDuplicateItem={props.duplicateItem}
isSidebarCollapsed={props.isSidebarCollapsed}
isSelected={props.selectedIds.includes(item.id)}
anySelected={props.selectedIds.length > 0}
onToggleSelection={(id, isMulti, isShift) => props.toggleSelection(id, isMulti, isShift)}
hideColumns={props.anyDescriptionIsLong()}
/>
</LazyItem>
)}
</For>
</div>
</div>
</div>
</Show>
);
};