Add At Risk to products views
This commit is contained in:
@@ -49,11 +49,12 @@ const FILTER_OPTIONS: FilterOption[] = [
|
||||
label: 'Stock Status',
|
||||
type: 'select',
|
||||
options: [
|
||||
{ label: 'Critical', value: 'Critical' },
|
||||
{ label: 'Reorder', value: 'Reorder' },
|
||||
{ label: 'Healthy', value: 'Healthy' },
|
||||
{ label: 'Overstocked', value: 'Overstocked' },
|
||||
{ label: 'New', value: 'New' }
|
||||
{ label: 'Critical', value: 'critical' },
|
||||
{ label: 'At Risk', value: 'at-risk' },
|
||||
{ label: 'Reorder', value: 'reorder' },
|
||||
{ label: 'Healthy', value: 'healthy' },
|
||||
{ label: 'Overstocked', value: 'overstocked' },
|
||||
{ label: 'New', value: 'new' }
|
||||
],
|
||||
group: 'Inventory'
|
||||
},
|
||||
|
||||
@@ -85,7 +85,8 @@ function SortableHeader({ column, columnDef, onSort, sortColumn, sortDirection }
|
||||
style={style}
|
||||
className={cn(
|
||||
"cursor-pointer select-none",
|
||||
columnDef?.width
|
||||
columnDef?.width,
|
||||
sortColumn === column && "bg-accent/50"
|
||||
)}
|
||||
{...attributes}
|
||||
{...listeners}
|
||||
@@ -95,8 +96,8 @@ function SortableHeader({ column, columnDef, onSort, sortColumn, sortDirection }
|
||||
{columnDef?.label ?? column}
|
||||
{sortColumn === column && (
|
||||
sortDirection === 'desc'
|
||||
? <SortDesc className="h-4 w-4" />
|
||||
: <SortAsc className="h-4 w-4" />
|
||||
? <SortDesc className="h-4 w-4 min-w-4" />
|
||||
: <SortAsc className="h-4 w-4 min-w-4" />
|
||||
)}
|
||||
</div>
|
||||
</TableHead>
|
||||
@@ -154,21 +155,22 @@ export function ProductTable({
|
||||
|
||||
const getStockStatus = (status: string | undefined) => {
|
||||
if (!status) return null;
|
||||
switch (status.toLowerCase()) {
|
||||
const normalizedStatus = status.toLowerCase().replace(/-/g, ' ');
|
||||
switch (normalizedStatus) {
|
||||
case 'critical':
|
||||
return <Badge variant="destructive">Critical</Badge>;
|
||||
case 'reorder':
|
||||
return <Badge variant="warning">Reorder</Badge>;
|
||||
return <Badge variant="secondary">Reorder</Badge>;
|
||||
case 'healthy':
|
||||
return <Badge variant="success">Healthy</Badge>;
|
||||
return <Badge variant="default">Healthy</Badge>;
|
||||
case 'overstocked':
|
||||
return <Badge variant="secondary">Overstocked</Badge>;
|
||||
case 'new':
|
||||
return <Badge variant="default">New</Badge>;
|
||||
case 'out of stock':
|
||||
return <Badge variant="destructive">Out of Stock</Badge>;
|
||||
case 'at-risk':
|
||||
return <Badge variant="warning">At Risk</Badge>;
|
||||
case 'at risk':
|
||||
return <Badge variant="secondary">At Risk</Badge>;
|
||||
default:
|
||||
return <Badge variant="outline">{status}</Badge>;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs"
|
||||
import { Product } from "@/types/products"
|
||||
import { AlertCircle, AlertTriangle, CheckCircle2, PackageSearch, Sparkles } from "lucide-react"
|
||||
import {
|
||||
AlertTriangle,
|
||||
AlertCircle,
|
||||
CheckCircle2,
|
||||
PackageSearch,
|
||||
Sparkles,
|
||||
Timer,
|
||||
PackagePlus,
|
||||
PackageX
|
||||
} from "lucide-react"
|
||||
|
||||
export type ProductView = {
|
||||
id: string
|
||||
@@ -19,35 +28,42 @@ export const PRODUCT_VIEWS: ProductView[] = [
|
||||
columns: ["image", "title", "SKU", "stock_quantity", "price", "stock_status"]
|
||||
},
|
||||
{
|
||||
id: "Critical",
|
||||
id: "critical",
|
||||
label: "Critical Stock",
|
||||
icon: AlertTriangle,
|
||||
iconClassName: "",
|
||||
columns: ["image", "title", "SKU", "stock_quantity", "daily_sales_avg", "reorder_qty", "replenishable", "last_purchase_date", "lead_time_status"]
|
||||
columns: ["image", "title", "SKU", "stock_quantity", "daily_sales_avg", "reorder_qty", "last_purchase_date", "lead_time_status"]
|
||||
},
|
||||
{
|
||||
id: "Reorder",
|
||||
id: "reorder",
|
||||
label: "Reorder Soon",
|
||||
icon: AlertCircle,
|
||||
icon: PackagePlus,
|
||||
iconClassName: "",
|
||||
columns: ["image", "title", "SKU", "stock_quantity", "daily_sales_avg", "reorder_qty", "replenishable", "last_purchase_date", "lead_time_status"]
|
||||
columns: ["image", "title", "SKU", "stock_quantity", "daily_sales_avg", "reorder_qty", "last_purchase_date", "lead_time_status"]
|
||||
},
|
||||
{
|
||||
id: "Healthy",
|
||||
id: "healthy",
|
||||
label: "Healthy Stock",
|
||||
icon: CheckCircle2,
|
||||
iconClassName: "",
|
||||
columns: ["image", "title", "stock_quantity", "daily_sales_avg", "stock_status", "abc_class"]
|
||||
},
|
||||
{
|
||||
id: "Overstocked",
|
||||
label: "Overstock",
|
||||
icon: PackageSearch,
|
||||
id: "at-risk",
|
||||
label: "At Risk",
|
||||
icon: Timer,
|
||||
iconClassName: "",
|
||||
columns: ["image", "title", "stock_quantity", "daily_sales_avg", "overstocked_amt", "replenishable", "last_sale_date", "abc_class"]
|
||||
columns: ["image", "title", "stock_quantity", "daily_sales_avg", "weekly_sales_avg", "days_of_inventory", "last_sale_date"]
|
||||
},
|
||||
{
|
||||
id: "New",
|
||||
id: "overstocked",
|
||||
label: "Overstock",
|
||||
icon: PackageX,
|
||||
iconClassName: "",
|
||||
columns: ["image", "title", "stock_quantity", "daily_sales_avg", "overstocked_amt", "days_of_inventory", "last_sale_date"]
|
||||
},
|
||||
{
|
||||
id: "new",
|
||||
label: "New Products",
|
||||
icon: Sparkles,
|
||||
iconClassName: "",
|
||||
|
||||
@@ -127,8 +127,8 @@ const VIEW_COLUMNS: Record<string, ColumnKey[]> = {
|
||||
'stock_quantity',
|
||||
'daily_sales_avg',
|
||||
'weekly_sales_avg',
|
||||
'monthly_sales_avg',
|
||||
'days_of_inventory',
|
||||
'last_sale_date',
|
||||
],
|
||||
new: [
|
||||
'image',
|
||||
@@ -241,7 +241,7 @@ export function Products() {
|
||||
|
||||
// Add view filter
|
||||
if (activeView !== 'all') {
|
||||
params.append('stockStatus', activeView);
|
||||
params.append('stockStatus', activeView === 'at-risk' ? 'At Risk' : activeView);
|
||||
}
|
||||
|
||||
// Add showNonReplenishable param
|
||||
|
||||
Reference in New Issue
Block a user