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