// import React from "react";
// import { useGetInventoryStatsQuery } from "../../features/report/inventoryAPI";
// const StockBadge = ({ stock }) => {
// if (stock === 0) return Out of Stock;
// if (stock <= 5) return Low Stock;
// return {stock};
// };
// const ProductCard = ({ product }) => (
//
//
//
{product.name}
//
//
//
{product.category?.name || "Unknown Category"}
//
// );
// const InventorySection = ({ title, products }) => (
//
//
{title}
// {products.length === 0 ? (
//
No products found
// ) : (
//
// {products.map((p) => (
//
// ))}
//
// )}
//
// );
// const InventoryReport = () => {
// const { data, isLoading, isError } = useGetInventoryStatsQuery();
// if (isLoading) return Loading inventory...
;
// if (isError) return Failed to load inventory
;
// const { lowStock, outOfStock, fastMoving } = data.data;
// return (
//
//
//
//
//
// );
// };
// export default InventoryReport;
// InventoryReport v2 - Editorial warm theme
import React, { useState } from "react";
import { useGetInventoryStatsQuery } from "../../features/report/inventoryAPI";
const styles = `
@import url('https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,400;9..144,600;9..144,700&family=Instrument+Sans:wght@400;500;600&display=swap');
:root {
--bg: #f7f5f2;
--surface: #ffffff;
--border: #e8e4de;
--border2: #f0ece6;
--text: #1a1714;
--muted: #9c9489;
--red: #e8442a;
--red-bg: #fdf1ef;
--red-bdr: #f4c4bc;
--amber: #d97706;
--amber-bg: #fffbeb;
--amber-bdr: #fde68a;
--teal: #0d7a6b;
--teal-bg: #f0faf8;
--teal-bdr: #a7f3e4;
--ink: #2d2a26;
--shadow: 0 1px 3px rgba(0,0,0,0.06), 0 4px 12px rgba(0,0,0,0.04);
--shadow-lg: 0 2px 8px rgba(0,0,0,0.08), 0 12px 32px rgba(0,0,0,0.06);
}
* { box-sizing: border-box; margin: 0; padding: 0; }
.inv-root {
font-family: 'Instrument Sans', sans-serif;
background: var(--bg);
min-height: 100vh;
color: var(--text);
padding: 40px 36px;
}
.inv-header {
display: flex;
align-items: flex-start;
justify-content: space-between;
margin-bottom: 36px;
flex-wrap: wrap;
gap: 20px;
}
.inv-eyebrow {
font-size: 0.68rem;
font-weight: 600;
letter-spacing: 0.14em;
text-transform: uppercase;
color: var(--muted);
margin-bottom: 6px;
}
.inv-title {
font-family: 'Fraunces', serif;
font-size: 2.2rem;
font-weight: 700;
color: var(--ink);
line-height: 1;
letter-spacing: -0.02em;
}
.inv-summary {
display: flex;
gap: 10px;
flex-wrap: wrap;
}
.inv-pill {
display: flex;
align-items: center;
gap: 10px;
padding: 10px 16px;
border-radius: 12px;
border: 1px solid var(--border);
background: var(--surface);
box-shadow: var(--shadow);
}
.inv-pill-icon {
width: 32px;
height: 32px;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
font-size: 0.9rem;
flex-shrink: 0;
}
.inv-pill-val {
font-family: 'Fraunces', serif;
font-size: 1.3rem;
font-weight: 700;
line-height: 1;
color: var(--ink);
}
.inv-pill-label {
font-size: 0.65rem;
font-weight: 500;
color: var(--muted);
letter-spacing: 0.06em;
text-transform: uppercase;
margin-top: 2px;
}
.pill-total .inv-pill-icon { background: #f0ece6; }
.pill-ok .inv-pill-icon { background: var(--teal-bg); }
.pill-low .inv-pill-icon { background: var(--amber-bg); }
.pill-out .inv-pill-icon { background: var(--red-bg); }
.inv-tabs {
display: flex;
gap: 2px;
border-bottom: 1.5px solid var(--border);
margin-bottom: 28px;
}
.inv-tab {
padding: 10px 18px;
border: none;
background: transparent;
color: var(--muted);
font-family: 'Instrument Sans', sans-serif;
font-size: 0.82rem;
font-weight: 600;
cursor: pointer;
display: flex;
align-items: center;
gap: 7px;
transition: color 0.18s;
letter-spacing: 0.01em;
border-bottom: 2px solid transparent;
margin-bottom: -1.5px;
}
.inv-tab:hover { color: var(--ink); }
.inv-tab.active { color: var(--ink); border-bottom-color: var(--ink); }
.inv-tab-chip {
font-size: 0.6rem;
font-weight: 600;
padding: 2px 6px;
border-radius: 99px;
letter-spacing: 0.04em;
}
.chip-out { background: var(--red-bg); color: var(--red); }
.chip-low { background: var(--amber-bg); color: var(--amber); }
.chip-fast { background: var(--teal-bg); color: var(--teal); }
.inv-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(270px, 1fr));
gap: 14px;
}
.inv-card {
background: var(--surface);
border: 1px solid var(--border);
border-radius: 16px;
padding: 20px;
box-shadow: var(--shadow);
transition: box-shadow 0.2s, transform 0.2s, border-color 0.2s;
position: relative;
overflow: hidden;
animation: riseIn 0.3s both;
}
.inv-card:hover {
box-shadow: var(--shadow-lg);
transform: translateY(-2px);
border-color: #d8d2ca;
}
@keyframes riseIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
.inv-card-stripe {
position: absolute;
left: 0; top: 16px; bottom: 16px;
width: 3px;
border-radius: 0 3px 3px 0;
}
.stripe-red { background: var(--red); }
.stripe-amber { background: var(--amber); }
.stripe-teal { background: var(--teal); }
.inv-card-inner { padding-left: 14px; }
.inv-card-top {
display: flex;
justify-content: space-between;
align-items: flex-start;
gap: 8px;
margin-bottom: 4px;
}
.inv-card-name {
font-family: 'Fraunces', serif;
font-size: 0.97rem;
font-weight: 600;
color: var(--ink);
line-height: 1.3;
}
.inv-badge {
font-size: 0.62rem;
font-weight: 600;
padding: 3px 8px;
border-radius: 20px;
white-space: nowrap;
flex-shrink: 0;
letter-spacing: 0.05em;
text-transform: uppercase;
}
.badge-out { background: var(--red-bg); color: var(--red); border: 1px solid var(--red-bdr); }
.badge-low { background: var(--amber-bg); color: var(--amber); border: 1px solid var(--amber-bdr); }
.badge-ok { background: var(--teal-bg); color: var(--teal); border: 1px solid var(--teal-bdr); }
.inv-card-meta {
font-size: 0.68rem;
font-weight: 500;
color: var(--muted);
margin-bottom: 14px;
letter-spacing: 0.03em;
}
.inv-bar-row {
display: flex;
align-items: center;
gap: 10px;
}
.inv-bar-bg {
flex: 1;
height: 4px;
background: var(--border2);
border-radius: 99px;
overflow: hidden;
}
.inv-bar-fill {
height: 100%;
border-radius: 99px;
transition: width 0.55s cubic-bezier(0.34,1.4,0.64,1);
}
.inv-bar-label {
font-size: 0.7rem;
font-weight: 600;
color: var(--muted);
min-width: 24px;
text-align: right;
}
.inv-rank-row {
display: flex;
align-items: flex-start;
gap: 12px;
margin-bottom: 4px;
}
.inv-rank-num {
font-family: 'Fraunces', serif;
font-size: 2rem;
font-weight: 700;
color: var(--border);
line-height: 1;
min-width: 44px;
flex-shrink: 0;
}
.inv-purchase-tag {
display: inline-flex;
align-items: center;
gap: 4px;
font-size: 0.65rem;
font-weight: 600;
color: var(--teal);
background: var(--teal-bg);
border: 1px solid var(--teal-bdr);
padding: 2px 7px;
border-radius: 99px;
margin-top: 3px;
letter-spacing: 0.04em;
text-transform: uppercase;
}
.inv-empty {
grid-column: 1/-1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 72px 20px;
gap: 10px;
}
.inv-empty-icon { font-size: 2.5rem; opacity: 0.25; }
.inv-empty-text {
font-size: 0.75rem;
font-weight: 600;
color: var(--muted);
letter-spacing: 0.08em;
text-transform: uppercase;
}
.inv-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 60vh;
gap: 14px;
}
.inv-spinner {
width: 32px; height: 32px;
border: 2px solid var(--border);
border-top-color: var(--ink);
border-radius: 50%;
animation: spin 0.75s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
.inv-state-text {
font-size: 0.72rem;
font-weight: 600;
color: var(--muted);
letter-spacing: 0.1em;
text-transform: uppercase;
}
.inv-state-text.err { color: var(--red); }
`;
const shortId = (id = "") =>
typeof id === "string" && id.length > 8
? id.slice(-6).toUpperCase()
: String(id).toUpperCase();
const getStockPct = (stock, max = 50) =>
stock === 0 ? 0 : Math.min(100, Math.round((stock / max) * 100));
const StockBadge = ({ stock }) => {
if (stock === 0) return No stock;
if (stock <= 5)
return {stock} left;
return In stock;
};
const StockBar = ({ stock, fillColor }) => (
);
const OutCard = ({ product, idx }) => (
{product.name}
Category · {shortId(product.category)}
);
const LowCard = ({ product, idx }) => (
{product.name}
Category · {shortId(product.category)}
);
const FastCard = ({ product, idx }) => (
{String(idx + 1).padStart(2, "0")}
{product.name}
↑ {product.purchaseCount ?? 0} sold
Category · {shortId(product.category)}
);
const EmptyState = ({ label }) => (
);
const TABS = [
{ key: "out", label: "Out of Stock", chipClass: "chip-out" },
{ key: "low", label: "Low Stock", chipClass: "chip-low" },
{ key: "fast", label: "Fast Moving", chipClass: "chip-fast" },
];
const InventoryReport = () => {
const [activeTab, setActiveTab] = useState("out");
const { data, isLoading, isError } = useGetInventoryStatsQuery();
if (isLoading)
return (
);
if (isError)
return (
);
const {
summary,
lowStock = [],
outOfStock = [],
fastMoving = [],
} = data.data;
const tabContent = {
out: { products: outOfStock, Card: OutCard, emptyLabel: "out-of-stock" },
low: { products: lowStock, Card: LowCard, emptyLabel: "low-stock" },
fast: { products: fastMoving, Card: FastCard, emptyLabel: "fast-moving" },
};
const { products, Card, emptyLabel } = tabContent[activeTab];
return (
Admin · Reports
Inventory
{summary && (
📦
{summary.totalProducts}
Total
✅
{summary.healthyStockCount}
Healthy
⚠️
{summary.lowStockCount}
Low Stock
🚫
{summary.outOfStockCount}
Out of Stock
)}
{TABS.map((tab) => (
))}
{products.length === 0 ? (
) : (
products.map((p, i) => )
)}
);
};
export default InventoryReport;