Fix and restyle overstockmetrics and topoverstockedproducts, link products to backend

This commit is contained in:
2025-01-18 00:43:57 -05:00
parent 9759bac94f
commit 1b4447f886
4 changed files with 47 additions and 21 deletions

View File

@@ -357,7 +357,7 @@ router.get('/overstock/metrics', async (req, res) => {
SUM(total_excess_units) as total_excess_units,
SUM(total_excess_cost) as total_excess_cost,
SUM(total_excess_retail) as total_excess_retail,
CAST(JSON_ARRAYAGG(
CONCAT('[', GROUP_CONCAT(
JSON_OBJECT(
'category', category_name,
'products', overstocked_products,
@@ -365,7 +365,7 @@ router.get('/overstock/metrics', async (req, res) => {
'cost', total_excess_cost,
'retail', total_excess_retail
)
) AS JSON) as category_data
), ']') as category_data
FROM (
SELECT *
FROM category_overstock
@@ -378,10 +378,17 @@ router.get('/overstock/metrics', async (req, res) => {
// Format response with explicit type conversion
const response = {
overstockedProducts: parseInt(rows[0].total_overstocked) || 0,
excessUnits: parseInt(rows[0].total_excess_units) || 0,
excessCost: parseFloat(rows[0].total_excess_cost) || 0,
excessRetail: parseFloat(rows[0].total_excess_retail) || 0,
categoryData: rows[0].category_data ? JSON.parse(rows[0].category_data) : []
total_excess_units: parseInt(rows[0].total_excess_units) || 0,
total_excess_cost: parseFloat(rows[0].total_excess_cost) || 0,
total_excess_retail: parseFloat(rows[0].total_excess_retail) || 0,
category_data: rows[0].category_data ?
JSON.parse(rows[0].category_data).map(obj => ({
category: obj.category,
products: parseInt(obj.products) || 0,
units: parseInt(obj.units) || 0,
cost: parseFloat(obj.cost) || 0,
retail: parseFloat(obj.retail) || 0
})) : []
};
res.json(response);

View File

@@ -6,14 +6,15 @@ import { Package, Layers, DollarSign, ShoppingCart } from "lucide-react"
interface OverstockMetricsData {
overstockedProducts: number
overstockedUnits: number
overstockedCost: number
overstockedRetail: number
overstockByCategory: {
total_excess_units: number
total_excess_cost: number
total_excess_retail: number
category_data: {
category: string
products: number
units: number
cost: number
retail: number
}[]
}
@@ -41,28 +42,28 @@ export function OverstockMetrics() {
<Package className="h-4 w-4 text-muted-foreground" />
<p className="text-sm font-medium text-muted-foreground">Overstocked Products</p>
</div>
<p className="text-2xl font-bold">{data?.overstockedProducts.toLocaleString() || 0}</p>
<p className="text-lg font-bold">{data?.overstockedProducts.toLocaleString() || 0}</p>
</div>
<div className="flex items-baseline justify-between">
<div className="flex items-center gap-2">
<Layers className="h-4 w-4 text-muted-foreground" />
<p className="text-sm font-medium text-muted-foreground">Overstocked Units</p>
</div>
<p className="text-2xl font-bold">{data?.overstockedUnits.toLocaleString() || 0}</p>
<p className="text-lg font-bold">{data?.total_excess_units.toLocaleString() || 0}</p>
</div>
<div className="flex items-baseline justify-between">
<div className="flex items-center gap-2">
<DollarSign className="h-4 w-4 text-muted-foreground" />
<p className="text-sm font-medium text-muted-foreground">Overstocked Cost</p>
</div>
<p className="text-2xl font-bold">{formatCurrency(data?.overstockedCost || 0)}</p>
<p className="text-lg font-bold">{formatCurrency(data?.total_excess_cost || 0)}</p>
</div>
<div className="flex items-baseline justify-between">
<div className="flex items-center gap-2">
<ShoppingCart className="h-4 w-4 text-muted-foreground" />
<p className="text-sm font-medium text-muted-foreground">Overstocked Retail</p>
</div>
<p className="text-2xl font-bold">{formatCurrency(data?.overstockedRetail || 0)}</p>
<p className="text-lg font-bold">{formatCurrency(data?.total_excess_retail || 0)}</p>
</div>
</div>
</CardContent>

View File

@@ -9,10 +9,10 @@ interface OverstockedProduct {
product_id: number
SKU: string
title: string
stock_quantity: number
overstocked_amt: number
excess_cost: number
excess_retail: number
days_of_inventory: number
}
export function TopOverstockedProducts() {
@@ -38,9 +38,10 @@ export function TopOverstockedProducts() {
<TableHeader>
<TableRow>
<TableHead>Product</TableHead>
<TableHead className="text-right">Units</TableHead>
<TableHead className="text-right">Cost</TableHead>
<TableHead className="text-right">Days</TableHead>
<TableHead className="text-right">Current Stock</TableHead>
<TableHead className="text-right">Overstock Amt</TableHead>
<TableHead className="text-right">Overstock Cost</TableHead>
<TableHead className="text-right">Overstock Retail</TableHead>
</TableRow>
</TableHeader>
<TableBody>
@@ -48,10 +49,20 @@ export function TopOverstockedProducts() {
<TableRow key={product.product_id}>
<TableCell>
<div>
<p className="font-medium">{product.title}</p>
<a
href={`https://backend.acherryontop.com/product/${product.product_id}`}
target="_blank"
rel="noopener noreferrer"
className="font-medium hover:underline"
>
{product.title}
</a>
<p className="text-sm text-muted-foreground">{product.SKU}</p>
</div>
</TableCell>
<TableCell className="text-right">
{product.stock_quantity.toLocaleString()}
</TableCell>
<TableCell className="text-right">
{product.overstocked_amt.toLocaleString()}
</TableCell>
@@ -59,7 +70,7 @@ export function TopOverstockedProducts() {
{formatCurrency(product.excess_cost)}
</TableCell>
<TableCell className="text-right">
{product.days_of_inventory}
{formatCurrency(product.excess_retail)}
</TableCell>
</TableRow>
))}

View File

@@ -49,7 +49,14 @@ export function TopReplenishProducts() {
<TableRow key={product.product_id}>
<TableCell>
<div>
<p className="font-medium">{product.title}</p>
<a
href={`https://backend.acherryontop.com/product/${product.product_id}`}
target="_blank"
rel="noopener noreferrer"
className="font-medium hover:underline"
>
{product.title}
</a>
<p className="text-sm text-muted-foreground">{product.SKU}</p>
</div>
</TableCell>