87 lines
4.6 KiB
TypeScript
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>
|
|
);
|
|
};
|