Add custom icons to stock and coverage filters for better visibility

This commit is contained in:
Christian Vidal Wolf
2026-01-29 08:51:36 +01:00
parent d19f0cddac
commit 12ca24b9f6
5 changed files with 72 additions and 15 deletions
+4
View File
@@ -6,6 +6,7 @@ import { StockBadge } from './StockBadge';
import { Top50Badge } from './Top50Badge';
import { VendorStockBadge } from './VendorStockBadge';
import { InColumnStockFilter } from './InColumnStockFilter';
import { WarehouseIcon, AmazonSmileIcon, CoverageIcon } from './Icons';
interface AdsPerformanceProps {
data: CombinedKPIs[];
@@ -427,11 +428,13 @@ const AdsPerformance: React.FC<AdsPerformanceProps> = ({
currentFilters={stockFilter}
onFilterChange={onStockFilterChange}
title="Warehouse Stock"
icon={<WarehouseIcon className="w-3.5 h-3.5 text-fuchsia-400" />}
/>
<InColumnStockFilter
currentFilters={vendorStockFilter}
onFilterChange={onVendorStockFilterChange}
title="Vendor Stock"
icon={<AmazonSmileIcon className="w-5 h-5 text-amber-500" />}
options={[
'Out of Stock (0)',
'In Stock (>0)',
@@ -443,6 +446,7 @@ const AdsPerformance: React.FC<AdsPerformanceProps> = ({
currentFilters={wocFilter}
onFilterChange={onWocFilterChange}
title="Week Coverage"
icon={<CoverageIcon className="w-3.5 h-3.5 text-emerald-400" />}
options={[
'< 4 Weeks',
'> 4 Weeks',
+20
View File
@@ -3,6 +3,7 @@ import * as XLSX from 'xlsx';
import { ProductForecastData, FilterState, CombinedKPIs } from '../types';
import { DownloadIcon, FunnelIcon, TrendingIcon, ChartIcon } from './Icons';
import { StockBadge } from './StockBadge';
import { WarehouseIcon, AmazonSmileIcon, CoverageIcon } from './Icons';
import { Top50Badge } from './Top50Badge';
import { VendorStockBadge } from './VendorStockBadge';
import { InColumnStockFilter } from './InColumnStockFilter';
@@ -436,10 +437,29 @@ const ForecastView: React.FC<ForecastViewProps> = ({
className="bg-slate-950 border border-white/10 rounded-xl px-4 py-2 text-sm text-white focus:outline-none w-64"
/>
<button onClick={handleExportExcel} className="p-2 bg-slate-800 hover:bg-slate-700 text-white rounded-xl border border-white/5 transition-all"><DownloadIcon /></button>
<InColumnStockFilter
currentFilters={stockFilter}
onFilterChange={onStockFilterChange}
title="Warehouse Stock"
icon={<WarehouseIcon className="w-3.5 h-3.5 text-fuchsia-400" />}
/>
<InColumnStockFilter
currentFilters={vendorStockFilter}
onFilterChange={onVendorStockFilterChange}
title="Vendor Stock"
icon={<AmazonSmileIcon className="w-5 h-5 text-amber-500" />}
options={[
'Out of Stock (0)',
'In Stock (>0)',
'In Stock (>20)',
'Low Stock (<10)',
]}
/>
<InColumnStockFilter
currentFilters={wocFilter}
onFilterChange={onWocFilterChange}
title="Week Coverage"
icon={<CoverageIcon className="w-3.5 h-3.5 text-emerald-400" />}
options={[
'< 4 Weeks',
'> 4 Weeks',
+21
View File
@@ -67,3 +67,24 @@ export const MegaphoneIcon = () => (
<path strokeLinecap="round" strokeLinejoin="round" d="M10.34 15.84c-.688-.06-1.386-.09-2.09-.09H7.5a4.5 4.5 0 1 1 0-9h.75c.704 0 1.402-.03 2.09-.09m0 9.18c.253.962.584 1.892.985 2.783.247.55.06 1.21-.463 1.511l-.657.38c-.551.318-1.26.117-1.527-.461a20.845 20.845 0 0 1-1.44-4.282m3.102.069a18.03 18.03 0 0 1-.59-4.59c0-1.586.205-3.124.59-4.59m0 9.18a23.848 23.848 0 0 1 8.835 2.535M10.34 6.66a23.847 23.847 0 0 0 8.835-2.535m0 0A23.74 23.74 0 0 0 18.795 3m.38 1.125a23.91 23.91 0 0 1 1.014 5.795 23.91 23.91 0 0 1-1.014 5.795m0-11.589a23.917 23.917 0 0 1 6.391 5.34" />
</svg>
);
export const WarehouseIcon = ({ className = "w-4 h-4" }) => (
<svg className={className} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="M21 8L12 3L3 8V16L12 21L21 16V8Z" />
<path d="M3 8L12 13L21 8" />
<path d="M12 13V21" />
</svg>
);
export const AmazonSmileIcon = ({ className = "w-4 h-4" }) => (
<svg className={className} viewBox="0 0 24 24" fill="currentColor">
<path d="M18.66 15.65c-2.31 1.76-6.22 2.45-9.14 1.35-1-.38-2.22-1.05-2.02-2.12.15-.81 1.12-.72 1.83-.58 2.57.51 6.27.32 8.35-.67.4-.19 1-.53 1.33-.14.33.39-.12 1.25-.35 2.16zM19.78 12.78c-.32-.43-2.31-.15-3.32-.01-.36.05-.76.12-.86-.24-.13-.49.71-.9 1.12-1.06 1.11-.42 2.66-.78 3.3.01.53.64.08 1.8-.24 1.3z" />
</svg>
);
export const CoverageIcon = ({ className = "w-4 h-4" }) => (
<svg className={className} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<circle cx="12" cy="12" r="10" />
<polyline points="12 6 12 12 16 14" />
</svg>
);
+11 -3
View File
@@ -5,6 +5,7 @@ interface InColumnStockFilterProps {
onFilterChange: (newFilters: string[]) => void;
title?: string;
options?: string[];
icon?: React.ReactNode;
}
const DEFAULT_STOCK_OPTIONS = [
@@ -17,7 +18,8 @@ export const InColumnStockFilter: React.FC<InColumnStockFilterProps> = ({
currentFilters,
onFilterChange,
title = "Stock Filter",
options = DEFAULT_STOCK_OPTIONS
options = DEFAULT_STOCK_OPTIONS,
icon
}) => {
const [isOpen, setIsOpen] = useState(false);
const containerRef = useRef<HTMLDivElement>(null);
@@ -55,12 +57,18 @@ export const InColumnStockFilter: React.FC<InColumnStockFilterProps> = ({
e.stopPropagation();
setIsOpen(!isOpen);
}}
className={`p-1 rounded hover:bg-white/10 transition-colors ${currentFilters.length > 0 ? 'text-indigo-400 bg-indigo-500/10' : 'text-slate-500'}`}
title="Filter by Stock"
className={`flex flex-col items-center gap-0.5 p-1 rounded hover:bg-white/10 transition-all ${currentFilters.length > 0 ? 'text-indigo-400 bg-indigo-500/10' : 'text-slate-500'}`}
title={`Filter by ${title}`}
>
{icon ? (
<div className="transition-transform group-hover:scale-110">
{icon}
</div>
) : (
<svg className="w-3 h-3" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={3} d="M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z" />
</svg>
)}
</button>
{isOpen && (
+4
View File
@@ -6,6 +6,7 @@ import { StockBadge } from './StockBadge';
import { InColumnStockFilter } from './InColumnStockFilter';
import { Top50Badge } from './Top50Badge';
import { VendorStockBadge } from './VendorStockBadge';
import { WarehouseIcon, AmazonSmileIcon, CoverageIcon } from './Icons';
interface WeeklyGridProps {
data: CombinedKPIs[];
@@ -518,11 +519,13 @@ const WeeklyGrid: React.FC<WeeklyGridProps & { top50Mode: 'eu' | 'uk' }> = ({
currentFilters={stockFilter}
onFilterChange={onStockFilterChange}
title="Warehouse Stock"
icon={<WarehouseIcon className="w-3.5 h-3.5 text-fuchsia-400" />}
/>
<InColumnStockFilter
currentFilters={vendorStockFilter}
onFilterChange={onVendorStockFilterChange}
title="Vendor Stock"
icon={<AmazonSmileIcon className="w-5 h-5 text-amber-500" />}
options={[
'Out of Stock (0)',
'In Stock (>0)',
@@ -534,6 +537,7 @@ const WeeklyGrid: React.FC<WeeklyGridProps & { top50Mode: 'eu' | 'uk' }> = ({
currentFilters={wocFilter}
onFilterChange={onWocFilterChange}
title="Week Coverage"
icon={<CoverageIcon className="w-3.5 h-3.5 text-emerald-400" />}
options={[
'< 4 Weeks',
'> 4 Weeks',