veza/apps/web/src/components/views/GearView.tsx

99 lines
3.5 KiB
TypeScript

import React, { useState, useMemo } from 'react';
import { LayoutGrid, List } from 'lucide-react';
import { useToast } from '@/components/feedback/ToastProvider';
import {
GearViewHeader,
GearFilters,
GearInventoryGrid,
GearDetailModal,
mockGearInventory,
type GearViewMode,
type GearFilterValue,
} from '@/features/inventory/components/gear';
import { cn } from '@/lib/utils';
export const GearView: React.FC = () => {
const { addToast } = useToast();
const [selectedItem, setSelectedItem] = useState<(typeof mockGearInventory)[0] | null>(null);
const [filter, setFilter] = useState<GearFilterValue>('All');
const [search, setSearch] = useState('');
const [viewMode, setViewMode] = useState<GearViewMode>('grid');
const filteredInventory = useMemo(() => {
return mockGearInventory.filter((item) => {
const matchesFilter = filter === 'All' || item.category === filter || item.status === filter;
const matchesSearch =
item.name.toLowerCase().includes(search.toLowerCase()) ||
item.brand.toLowerCase().includes(search.toLowerCase());
return matchesFilter && matchesSearch;
});
}, [filter, search]);
const handleListOnMarketplace = (item: (typeof mockGearInventory)[0]) => {
addToast(`Draft listing created for ${item.brand} ${item.name}`, 'success');
setSelectedItem(null);
};
return (
<div className="space-y-8 animate-fadeIn relative max-w-layout-content mx-auto px-4 md:px-6">
<GearViewHeader
onExport={() => addToast('Exporting Inventory CSV...')}
onRegister={() => addToast('Opens Registration Form')}
/>
<GearFilters
search={search}
onSearchChange={setSearch}
filter={filter}
onFilterChange={setFilter}
/>
{/* View mode toggle — smooth grid/list transition (documented in GearInventoryGrid stories) */}
<div className="flex items-center justify-between">
<span className="text-sm text-muted-foreground font-mono">View</span>
<div className="flex gap-1 bg-muted p-1 rounded-lg border border-border">
<button
type="button"
onClick={() => setViewMode('grid')}
className={cn(
'p-1.5 rounded transition-colors',
viewMode === 'grid' ? 'bg-primary text-primary-foreground' : 'text-muted-foreground hover:text-foreground'
)}
aria-label="Grid view"
>
<LayoutGrid className="w-4 h-4" />
</button>
<button
type="button"
onClick={() => setViewMode('list')}
className={cn(
'p-1.5 rounded transition-colors',
viewMode === 'list' ? 'bg-primary text-primary-foreground' : 'text-muted-foreground hover:text-foreground'
)}
aria-label="List view"
>
<List className="w-4 h-4" />
</button>
</div>
</div>
<GearInventoryGrid
items={filteredInventory}
viewMode={viewMode}
onItemSelect={setSelectedItem}
onAddNew={() => addToast('Opens Registration Form')}
/>
{selectedItem && (
<GearDetailModal
item={selectedItem}
onClose={() => setSelectedItem(null)}
onSellOnMarketplace={handleListOnMarketplace}
onLogMaintenance={() => addToast('Maintenance Log Updated')}
onContactSupport={(item) => addToast(`Contacting ${item.supportContact}`)}
onUploadDocument={() => addToast('Upload document')}
/>
)}
</div>
);
};