fix: 筛选面板改为确认后才搜索、隐藏公务车分类
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful

- 三个筛选面板(库存/区域/客户)改为draft状态模式:
  打开时复制当前筛选到draft,面板内操作draft,
  点确认才应用到实际筛选状态
- 移除点击外部关闭(只能通过确认按钮关闭)
- 业务负责人下拉隐藏"公务车"分组(部门Tab和客户Tab都已处理)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
kkfluous
2026-03-29 00:11:46 +08:00
parent 7b39d51fa3
commit 8f42676f7c

View File

@@ -161,11 +161,13 @@ export default function App() {
const [expandedRegionCities, setExpandedRegionCities] = useState<Set<string>>(new Set()); const [expandedRegionCities, setExpandedRegionCities] = useState<Set<string>>(new Set());
const [regionFilters, setRegionFilters] = useState({ region: '', city: '', customer: '' }); const [regionFilters, setRegionFilters] = useState({ region: '', city: '', customer: '' });
const [isRegionFilterOpen, setIsRegionFilterOpen] = useState(false); const [isRegionFilterOpen, setIsRegionFilterOpen] = useState(false);
const [draftRegionFilters, setDraftRegionFilters] = useState({ region: '', city: '', customer: '' });
// Customer section state // Customer section state
const [expandedCustomers, setExpandedCustomers] = useState<Set<string>>(new Set()); const [expandedCustomers, setExpandedCustomers] = useState<Set<string>>(new Set());
const [customerFilters, setCustomerFilters] = useState({ customer: '', brand: '', department: '', manager: '', region: '' }); const [customerFilters, setCustomerFilters] = useState({ customer: '', brand: '', department: '', manager: '', region: '' });
const [isCustomerFilterOpen, setIsCustomerFilterOpen] = useState(false); const [isCustomerFilterOpen, setIsCustomerFilterOpen] = useState(false);
const [draftCustomerFilters, setDraftCustomerFilters] = useState({ customer: '', brand: '', department: '', manager: '', region: '' });
// Inventory statistics section state // Inventory statistics section state
const [inventoryData, setInventoryData] = useState<RegionalInventoryStats[]>([]); const [inventoryData, setInventoryData] = useState<RegionalInventoryStats[]>([]);
@@ -174,6 +176,7 @@ export default function App() {
const [expandedInventoryTypes, setExpandedInventoryTypes] = useState<Set<string>>(new Set(['4.5T普货'])); const [expandedInventoryTypes, setExpandedInventoryTypes] = useState<Set<string>>(new Set(['4.5T普货']));
const [inventoryFilters, setInventoryFilters] = useState({ region: '', city: '', brand: '', type: '', model: '' }); const [inventoryFilters, setInventoryFilters] = useState({ region: '', city: '', brand: '', type: '', model: '' });
const [isInventoryFilterOpen, setIsInventoryFilterOpen] = useState(false); const [isInventoryFilterOpen, setIsInventoryFilterOpen] = useState(false);
const [draftInventoryFilters, setDraftInventoryFilters] = useState({ region: '', city: '', brand: '', type: '', model: '' });
// Chart view states // Chart view states
const [customerChartView, setCustomerChartView] = useState<'region' | 'city'>('region'); const [customerChartView, setCustomerChartView] = useState<'region' | 'city'>('region');
@@ -377,9 +380,10 @@ export default function App() {
return types.sort((a, b) => INVENTORY_TYPE_ORDER_LIST.indexOf(a) - INVENTORY_TYPE_ORDER_LIST.indexOf(b)); return types.sort((a, b) => INVENTORY_TYPE_ORDER_LIST.indexOf(a) - INVENTORY_TYPE_ORDER_LIST.indexOf(b));
}, [inventoryData]); }, [inventoryData]);
const uniqueInventoryModelsForType = useMemo(() => { const uniqueInventoryModelsForType = useMemo(() => {
const source = inventoryFilters.type ? inventoryData.filter((s) => s.type === inventoryFilters.type) : inventoryData; const typeFilter = isInventoryFilterOpen ? draftInventoryFilters.type : inventoryFilters.type;
const source = typeFilter ? inventoryData.filter((s) => s.type === typeFilter) : inventoryData;
return Array.from(new Set(source.map((s) => s.model).filter(Boolean))); return Array.from(new Set(source.map((s) => s.model).filter(Boolean)));
}, [inventoryData, inventoryFilters.type]); }, [inventoryData, inventoryFilters.type, draftInventoryFilters.type, isInventoryFilterOpen]);
const inventoryByRegion = useMemo(() => { const inventoryByRegion = useMemo(() => {
const result: Record<string, Record<string, RegionalInventoryStats[]>> = {}; const result: Record<string, Record<string, RegionalInventoryStats[]>> = {};
@@ -1023,7 +1027,7 @@ export default function App() {
<div className="relative"> <div className="relative">
<button <button
onClick={() => setIsInventoryFilterOpen(!isInventoryFilterOpen)} onClick={() => { if (!isInventoryFilterOpen) setDraftInventoryFilters({...inventoryFilters}); setIsInventoryFilterOpen(!isInventoryFilterOpen); }}
className={`flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-bold transition-all ${ className={`flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-bold transition-all ${
isInventoryFilterOpen || (inventoryFilters.region || inventoryFilters.city || inventoryFilters.brand || inventoryFilters.type || inventoryFilters.model) isInventoryFilterOpen || (inventoryFilters.region || inventoryFilters.city || inventoryFilters.brand || inventoryFilters.type || inventoryFilters.model)
? 'bg-blue-600 text-white shadow-md' ? 'bg-blue-600 text-white shadow-md'
@@ -1040,7 +1044,7 @@ export default function App() {
<AnimatePresence> <AnimatePresence>
{isInventoryFilterOpen && ( {isInventoryFilterOpen && (
<> <>
<div className="fixed inset-0 z-40" onClick={() => setIsInventoryFilterOpen(false)} /> <div className="fixed inset-0 z-40" />
<motion.div <motion.div
initial={{ opacity: 0, y: 10, scale: 0.95 }} initial={{ opacity: 0, y: 10, scale: 0.95 }}
animate={{ opacity: 1, y: 0, scale: 1 }} animate={{ opacity: 1, y: 0, scale: 1 }}
@@ -1049,52 +1053,47 @@ export default function App() {
> >
<div className="flex justify-between items-center mb-4"> <div className="flex justify-between items-center mb-4">
<h3 className="text-xs font-bold text-slate-800"> - </h3> <h3 className="text-xs font-bold text-slate-800"> - </h3>
<button <button onClick={() => setDraftInventoryFilters({ region: '', city: '', brand: '', type: '', model: '' })} className="text-[10px] text-blue-500 hover:underline"></button>
onClick={() => setInventoryFilters({ region: '', city: '', brand: '', type: '', model: '' })}
className="text-[10px] text-blue-500 hover:underline"
>
</button>
</div> </div>
<div className="space-y-3 text-left"> <div className="space-y-3 text-left">
<div> <div>
<label className="text-[10px] text-slate-400 block mb-1"></label> <label className="text-[10px] text-slate-400 block mb-1"></label>
<select value={inventoryFilters.region} onChange={(e) => setInventoryFilters({...inventoryFilters, region: e.target.value})} className="w-full text-xs bg-white border border-slate-200 rounded-lg px-2 py-1.5 focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 transition-all shadow-sm cursor-pointer"> <select value={draftInventoryFilters.region} onChange={(e) => setDraftInventoryFilters({...draftInventoryFilters, region: e.target.value})} className="w-full text-xs bg-white border border-slate-200 rounded-lg px-2 py-1.5 focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 transition-all shadow-sm cursor-pointer">
<option value=""></option> <option value=""></option>
{uniqueInventoryRegions.map(r => <option key={r} value={r}>{r}</option>)} {uniqueInventoryRegions.map(r => <option key={r} value={r}>{r}</option>)}
</select> </select>
</div> </div>
<div> <div>
<label className="text-[10px] text-slate-400 block mb-1"></label> <label className="text-[10px] text-slate-400 block mb-1"></label>
<select value={inventoryFilters.city} onChange={(e) => setInventoryFilters({...inventoryFilters, city: e.target.value})} className="w-full text-xs bg-white border border-slate-200 rounded-lg px-2 py-1.5 focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 transition-all shadow-sm cursor-pointer"> <select value={draftInventoryFilters.city} onChange={(e) => setDraftInventoryFilters({...draftInventoryFilters, city: e.target.value})} className="w-full text-xs bg-white border border-slate-200 rounded-lg px-2 py-1.5 focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 transition-all shadow-sm cursor-pointer">
<option value=""></option> <option value=""></option>
{uniqueInventoryCities.map(c => <option key={c} value={c}>{c}</option>)} {uniqueInventoryCities.map(c => <option key={c} value={c}>{c}</option>)}
</select> </select>
</div> </div>
<div> <div>
<label className="text-[10px] text-slate-400 block mb-1"></label> <label className="text-[10px] text-slate-400 block mb-1"></label>
<select value={inventoryFilters.brand} onChange={(e) => setInventoryFilters({...inventoryFilters, brand: e.target.value})} className="w-full text-xs bg-white border border-slate-200 rounded-lg px-2 py-1.5 focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 transition-all shadow-sm cursor-pointer"> <select value={draftInventoryFilters.brand} onChange={(e) => setDraftInventoryFilters({...draftInventoryFilters, brand: e.target.value})} className="w-full text-xs bg-white border border-slate-200 rounded-lg px-2 py-1.5 focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 transition-all shadow-sm cursor-pointer">
<option value=""></option> <option value=""></option>
{uniqueInventoryBrands.map(b => <option key={b} value={b}>{b}</option>)} {uniqueInventoryBrands.map(b => <option key={b} value={b}>{b}</option>)}
</select> </select>
</div> </div>
<div> <div>
<label className="text-[10px] text-slate-400 block mb-1"></label> <label className="text-[10px] text-slate-400 block mb-1"></label>
<select value={inventoryFilters.type} onChange={(e) => setInventoryFilters({...inventoryFilters, type: e.target.value, model: ''})} className="w-full text-xs bg-white border border-slate-200 rounded-lg px-2 py-1.5 focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 transition-all shadow-sm cursor-pointer"> <select value={draftInventoryFilters.type} onChange={(e) => setDraftInventoryFilters({...draftInventoryFilters, type: e.target.value, model: ''})} className="w-full text-xs bg-white border border-slate-200 rounded-lg px-2 py-1.5 focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 transition-all shadow-sm cursor-pointer">
<option value=""></option> <option value=""></option>
{uniqueInventoryTypes.map(t => <option key={t} value={t}>{t}</option>)} {uniqueInventoryTypes.map(t => <option key={t} value={t}>{t}</option>)}
</select> </select>
</div> </div>
<div> <div>
<label className="text-[10px] text-slate-400 block mb-1"></label> <label className="text-[10px] text-slate-400 block mb-1"></label>
<select value={inventoryFilters.model} onChange={(e) => setInventoryFilters({...inventoryFilters, model: e.target.value})} className="w-full text-xs bg-white border border-slate-200 rounded-lg px-2 py-1.5 focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 transition-all shadow-sm cursor-pointer"> <select value={draftInventoryFilters.model} onChange={(e) => setDraftInventoryFilters({...draftInventoryFilters, model: e.target.value})} className="w-full text-xs bg-white border border-slate-200 rounded-lg px-2 py-1.5 focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 transition-all shadow-sm cursor-pointer">
<option value=""></option> <option value=""></option>
{uniqueInventoryModelsForType.map(m => <option key={m} value={m}>{m}</option>)} {uniqueInventoryModelsForType.map(m => <option key={m} value={m}>{m}</option>)}
</select> </select>
</div> </div>
</div> </div>
<button onClick={() => setIsInventoryFilterOpen(false)} className="w-full mt-4 py-2 bg-blue-600 text-white rounded-lg text-xs font-bold hover:bg-blue-700 transition-colors"></button> <button onClick={() => { setInventoryFilters({...draftInventoryFilters}); setIsInventoryFilterOpen(false); }} className="w-full mt-4 py-2 bg-blue-600 text-white rounded-lg text-xs font-bold hover:bg-blue-700 transition-colors"></button>
</motion.div> </motion.div>
</> </>
)} )}
@@ -1447,7 +1446,7 @@ export default function App() {
className="w-full pl-9 pr-8 py-1.5 bg-white border border-gray-200 rounded-lg text-xs focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 transition-all shadow-sm appearance-none cursor-pointer font-bold text-gray-700" className="w-full pl-9 pr-8 py-1.5 bg-white border border-gray-200 rounded-lg text-xs focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 transition-all shadow-sm appearance-none cursor-pointer font-bold text-gray-700"
> >
<option value="All"></option> <option value="All"></option>
{managersGroupedByDept.map(g => ( {managersGroupedByDept.filter(g => g.department !== '公务车').map(g => (
<optgroup key={g.department} label={g.department}> <optgroup key={g.department} label={g.department}>
{g.managers.map(m => <option key={m} value={m}>{m}</option>)} {g.managers.map(m => <option key={m} value={m}>{m}</option>)}
</optgroup> </optgroup>
@@ -1954,7 +1953,7 @@ export default function App() {
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<button <button
onClick={() => setIsRegionFilterOpen(!isRegionFilterOpen)} onClick={() => { if (!isRegionFilterOpen) setDraftRegionFilters({...regionFilters}); setIsRegionFilterOpen(!isRegionFilterOpen); }}
className={`flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-medium transition-all ${ className={`flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-medium transition-all ${
isRegionFilterOpen || Object.values(regionFilters).some(v => v !== '') isRegionFilterOpen || Object.values(regionFilters).some(v => v !== '')
? 'bg-slate-200 text-slate-900 shadow-sm' ? 'bg-slate-200 text-slate-900 shadow-sm'
@@ -1971,7 +1970,7 @@ export default function App() {
<AnimatePresence> <AnimatePresence>
{isRegionFilterOpen && ( {isRegionFilterOpen && (
<> <>
<div className="fixed inset-0 z-40" onClick={() => setIsRegionFilterOpen(false)} /> <div className="fixed inset-0 z-40" />
<motion.div <motion.div
initial={{ opacity: 0, y: 10, scale: 0.95 }} initial={{ opacity: 0, y: 10, scale: 0.95 }}
animate={{ opacity: 1, y: 0, scale: 1 }} animate={{ opacity: 1, y: 0, scale: 1 }}
@@ -1980,38 +1979,33 @@ export default function App() {
> >
<div className="flex items-center justify-between mb-4"> <div className="flex items-center justify-between mb-4">
<h3 className="text-sm font-bold text-gray-900"></h3> <h3 className="text-sm font-bold text-gray-900"></h3>
<button <button onClick={() => setDraftRegionFilters({ region: '', city: '', customer: '' })} className="text-[10px] text-slate-600 hover:text-slate-700 font-medium"></button>
onClick={() => setRegionFilters({ region: '', city: '', customer: '' })}
className="text-[10px] text-slate-600 hover:text-slate-700 font-medium"
>
</button>
</div> </div>
<div className="space-y-4"> <div className="space-y-4">
<div className="space-y-1.5"> <div className="space-y-1.5">
<label className="text-[10px] font-bold text-gray-400 uppercase tracking-wider"></label> <label className="text-[10px] font-bold text-gray-400 uppercase tracking-wider"></label>
<SearchSelect value={regionFilters.customer} onChange={(v) => setRegionFilters(prev => ({ ...prev, customer: v }))} options={uniqueCustomerNames} placeholder="所有客户" className="text-xs py-2 px-2" /> <SearchSelect value={draftRegionFilters.customer} onChange={(v) => setDraftRegionFilters(prev => ({ ...prev, customer: v }))} options={uniqueCustomerNames} placeholder="所有客户" className="text-xs py-2 px-2" />
</div> </div>
<div className="grid grid-cols-2 gap-3"> <div className="grid grid-cols-2 gap-3">
<div className="space-y-1.5"> <div className="space-y-1.5">
<label className="text-[10px] font-bold text-gray-400 uppercase tracking-wider"></label> <label className="text-[10px] font-bold text-gray-400 uppercase tracking-wider"></label>
<select className="w-full bg-white border border-gray-200 rounded-lg py-2 px-2 text-xs focus:ring-2 focus:ring-slate-500/20 focus:border-slate-500 outline-none transition-all cursor-pointer shadow-sm" value={regionFilters.region} onChange={(e) => setRegionFilters(prev => ({ ...prev, region: e.target.value }))}> <select className="w-full bg-white border border-gray-200 rounded-lg py-2 px-2 text-xs focus:ring-2 focus:ring-slate-500/20 focus:border-slate-500 outline-none transition-all cursor-pointer shadow-sm" value={draftRegionFilters.region} onChange={(e) => setDraftRegionFilters(prev => ({ ...prev, region: e.target.value }))}>
<option value=""></option> <option value=""></option>
{uniqueRegions.map(r => <option key={r} value={r}>{r}</option>)} {uniqueRegions.map(r => <option key={r} value={r}>{r}</option>)}
</select> </select>
</div> </div>
<div className="space-y-1.5"> <div className="space-y-1.5">
<label className="text-[10px] font-bold text-gray-400 uppercase tracking-wider"></label> <label className="text-[10px] font-bold text-gray-400 uppercase tracking-wider"></label>
<select className="w-full bg-white border border-gray-200 rounded-lg py-2 px-2 text-xs focus:ring-2 focus:ring-slate-500/20 focus:border-slate-500 outline-none transition-all cursor-pointer shadow-sm" value={regionFilters.city} onChange={(e) => setRegionFilters(prev => ({ ...prev, city: e.target.value }))}> <select className="w-full bg-white border border-gray-200 rounded-lg py-2 px-2 text-xs focus:ring-2 focus:ring-slate-500/20 focus:border-slate-500 outline-none transition-all cursor-pointer shadow-sm" value={draftRegionFilters.city} onChange={(e) => setDraftRegionFilters(prev => ({ ...prev, city: e.target.value }))}>
<option value=""></option> <option value=""></option>
{uniqueCities.map(c => <option key={c} value={c}>{c}</option>)} {uniqueCities.map(c => <option key={c} value={c}>{c}</option>)}
</select> </select>
</div> </div>
</div> </div>
</div> </div>
<button onClick={() => setIsRegionFilterOpen(false)} className="w-full mt-4 py-2 bg-slate-800 text-white rounded-lg text-xs font-bold hover:bg-slate-900 transition-colors"></button> <button onClick={() => { setRegionFilters({...draftRegionFilters}); setIsRegionFilterOpen(false); }} className="w-full mt-4 py-2 bg-slate-800 text-white rounded-lg text-xs font-bold hover:bg-slate-900 transition-colors"></button>
</motion.div> </motion.div>
</> </>
)} )}
@@ -2248,7 +2242,7 @@ export default function App() {
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<button <button
onClick={() => setIsCustomerFilterOpen(!isCustomerFilterOpen)} onClick={() => { if (!isCustomerFilterOpen) setDraftCustomerFilters({...customerFilters}); setIsCustomerFilterOpen(!isCustomerFilterOpen); }}
className={`flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-medium transition-all ${ className={`flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-medium transition-all ${
isCustomerFilterOpen || Object.values(customerFilters).some(v => v !== '') isCustomerFilterOpen || Object.values(customerFilters).some(v => v !== '')
? 'bg-emerald-400 text-emerald-900 shadow-lg shadow-emerald-900/20' ? 'bg-emerald-400 text-emerald-900 shadow-lg shadow-emerald-900/20'
@@ -2266,7 +2260,7 @@ export default function App() {
{isCustomerFilterOpen && ( {isCustomerFilterOpen && (
<> <>
{/* Backdrop */} {/* Backdrop */}
<div className="fixed inset-0 z-40" onClick={() => setIsCustomerFilterOpen(false)} /> <div className="fixed inset-0 z-40" />
{/* Popover Content */} {/* Popover Content */}
<motion.div <motion.div
@@ -2278,26 +2272,21 @@ export default function App() {
<div className="flex items-center justify-between mb-4"> <div className="flex items-center justify-between mb-4">
<h3 className="text-sm font-bold text-gray-900"></h3> <h3 className="text-sm font-bold text-gray-900"></h3>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<button <button onClick={() => setDraftCustomerFilters({ customer: '', brand: '', department: '', manager: '', region: '' })} className="text-[10px] text-emerald-600 hover:text-emerald-700 font-medium"></button>
onClick={() => setCustomerFilters({ customer: '', brand: '', department: '', manager: '', region: '' })}
className="text-[10px] text-emerald-600 hover:text-emerald-700 font-medium"
>
</button>
</div> </div>
</div> </div>
<div className="space-y-4"> <div className="space-y-4">
<div className="space-y-1.5"> <div className="space-y-1.5">
<label className="text-[10px] font-bold text-gray-400 uppercase tracking-wider"></label> <label className="text-[10px] font-bold text-gray-400 uppercase tracking-wider"></label>
<SearchSelect value={customerFilters.customer} onChange={(v) => setCustomerFilters(prev => ({ ...prev, customer: v }))} options={uniqueCustomerNames} placeholder="所有客户" className="text-xs py-2 px-2" /> <SearchSelect value={draftCustomerFilters.customer} onChange={(v) => setDraftCustomerFilters(prev => ({ ...prev, customer: v }))} options={uniqueCustomerNames} placeholder="所有客户" className="text-xs py-2 px-2" />
</div> </div>
<div className="space-y-1.5"> <div className="space-y-1.5">
<label className="text-[10px] font-bold text-gray-400 uppercase tracking-wider"></label> <label className="text-[10px] font-bold text-gray-400 uppercase tracking-wider"></label>
<select className="w-full bg-white border border-gray-200 rounded-lg py-2 px-2 text-xs focus:ring-2 focus:ring-emerald-500/20 focus:border-emerald-500 outline-none transition-all cursor-pointer shadow-sm" value={customerFilters.manager} onChange={(e) => setCustomerFilters(prev => ({ ...prev, manager: e.target.value }))}> <select className="w-full bg-white border border-gray-200 rounded-lg py-2 px-2 text-xs focus:ring-2 focus:ring-emerald-500/20 focus:border-emerald-500 outline-none transition-all cursor-pointer shadow-sm" value={draftCustomerFilters.manager} onChange={(e) => setDraftCustomerFilters(prev => ({ ...prev, manager: e.target.value }))}>
<option value=""></option> <option value=""></option>
{customerManagersGroupedByDept.map(g => ( {customerManagersGroupedByDept.filter(g => g.department !== '公务车').map(g => (
<optgroup key={g.department} label={g.department}> <optgroup key={g.department} label={g.department}>
{g.managers.map(m => <option key={m} value={m}>{m}</option>)} {g.managers.map(m => <option key={m} value={m}>{m}</option>)}
</optgroup> </optgroup>
@@ -2308,28 +2297,28 @@ export default function App() {
<div className="grid grid-cols-2 gap-3"> <div className="grid grid-cols-2 gap-3">
<div className="space-y-1.5"> <div className="space-y-1.5">
<label className="text-[10px] font-bold text-gray-400 uppercase tracking-wider"></label> <label className="text-[10px] font-bold text-gray-400 uppercase tracking-wider"></label>
<select className="w-full bg-white border border-gray-200 rounded-lg py-2 px-2 text-xs focus:ring-2 focus:ring-emerald-500/20 focus:border-emerald-500 outline-none transition-all cursor-pointer shadow-sm" value={customerFilters.brand} onChange={(e) => setCustomerFilters(prev => ({ ...prev, brand: e.target.value }))}> <select className="w-full bg-white border border-gray-200 rounded-lg py-2 px-2 text-xs focus:ring-2 focus:ring-emerald-500/20 focus:border-emerald-500 outline-none transition-all cursor-pointer shadow-sm" value={draftCustomerFilters.brand} onChange={(e) => setDraftCustomerFilters(prev => ({ ...prev, brand: e.target.value }))}>
<option value=""></option> <option value=""></option>
{uniqueBrands.map(b => <option key={b} value={b}>{b}</option>)} {uniqueBrands.map(b => <option key={b} value={b}>{b}</option>)}
</select> </select>
</div> </div>
<div className="space-y-1.5"> <div className="space-y-1.5">
<label className="text-[10px] font-bold text-gray-400 uppercase tracking-wider"></label> <label className="text-[10px] font-bold text-gray-400 uppercase tracking-wider"></label>
<select className="w-full bg-white border border-gray-200 rounded-lg py-2 px-2 text-xs focus:ring-2 focus:ring-emerald-500/20 focus:border-emerald-500 outline-none transition-all cursor-pointer shadow-sm" value={customerFilters.department} onChange={(e) => setCustomerFilters(prev => ({ ...prev, department: e.target.value }))}> <select className="w-full bg-white border border-gray-200 rounded-lg py-2 px-2 text-xs focus:ring-2 focus:ring-emerald-500/20 focus:border-emerald-500 outline-none transition-all cursor-pointer shadow-sm" value={draftCustomerFilters.department} onChange={(e) => setDraftCustomerFilters(prev => ({ ...prev, department: e.target.value }))}>
<option value=""></option> <option value=""></option>
{uniqueDepts.map(d => <option key={d} value={d}>{d}</option>)} {uniqueDepts.map(d => <option key={d} value={d}>{d}</option>)}
</select> </select>
</div> </div>
<div className="space-y-1.5"> <div className="space-y-1.5">
<label className="text-[10px] font-bold text-gray-400 uppercase tracking-wider"></label> <label className="text-[10px] font-bold text-gray-400 uppercase tracking-wider"></label>
<select className="w-full bg-white border border-gray-200 rounded-lg py-2 px-2 text-xs focus:ring-2 focus:ring-emerald-500/20 focus:border-emerald-500 outline-none transition-all cursor-pointer shadow-sm" value={customerFilters.region} onChange={(e) => setCustomerFilters(prev => ({ ...prev, region: e.target.value }))}> <select className="w-full bg-white border border-gray-200 rounded-lg py-2 px-2 text-xs focus:ring-2 focus:ring-emerald-500/20 focus:border-emerald-500 outline-none transition-all cursor-pointer shadow-sm" value={draftCustomerFilters.region} onChange={(e) => setDraftCustomerFilters(prev => ({ ...prev, region: e.target.value }))}>
<option value=""></option> <option value=""></option>
{uniqueRegions.map(r => <option key={r} value={r}>{r}</option>)} {uniqueRegions.map(r => <option key={r} value={r}>{r}</option>)}
</select> </select>
</div> </div>
</div> </div>
</div> </div>
<button onClick={() => setIsCustomerFilterOpen(false)} className="w-full mt-4 py-2 bg-emerald-600 text-white rounded-lg text-xs font-bold hover:bg-emerald-700 transition-colors"></button> <button onClick={() => { setCustomerFilters({...draftCustomerFilters}); setIsCustomerFilterOpen(false); }} className="w-full mt-4 py-2 bg-emerald-600 text-white rounded-lg text-xs font-bold hover:bg-emerald-700 transition-colors"></button>
</motion.div> </motion.div>
</> </>
)} )}