From 750e25db8945a74412445198ae7746f538e1c28a Mon Sep 17 00:00:00 2001 From: "christian.vidal" Date: Fri, 27 Mar 2026 13:26:16 +0100 Subject: [PATCH] feat: show EOL not neccessary for OOC products with 0 stock --- api/dropbox-proxy.js | 23 ++++++++++++++++++++++ src/App.tsx | 7 +++++-- src/components/ProductDescriptions.tsx | 27 +++++++++++++++++++++----- src/types.ts | 4 +++- vercel.json | 9 ++++----- 5 files changed, 57 insertions(+), 13 deletions(-) create mode 100644 api/dropbox-proxy.js diff --git a/api/dropbox-proxy.js b/api/dropbox-proxy.js new file mode 100644 index 0000000..79e06dd --- /dev/null +++ b/api/dropbox-proxy.js @@ -0,0 +1,23 @@ +// Vercel serverless function — proxies the Dropbox file server-side (no CORS) +export default async function handler(req, res) { + const fileUrl = + 'https://dl.dropboxusercontent.com/scl/fi/nkyabkq2jdwfudof2ovrl/Data-Matrix.xlsx' + + '?rlkey=1cz5fuabwipqqivihii7sybw0&st=io0g4wvb&dl=1'; + + try { + const upstream = await fetch(fileUrl, { + headers: { 'User-Agent': 'Mozilla/5.0' }, + }); + + if (!upstream.ok) { + return res.status(upstream.status).send(`Dropbox error: ${upstream.status}`); + } + + const buffer = await upstream.arrayBuffer(); + res.setHeader('Content-Type', 'application/octet-stream'); + res.setHeader('Cache-Control', 'no-store'); + res.send(Buffer.from(buffer)); + } catch (err) { + res.status(500).send('Proxy error: ' + err.message); + } +} diff --git a/src/App.tsx b/src/App.tsx index f23bf24..f2e1957 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -24,8 +24,11 @@ export default function App() { useEffect(() => { const loadDefaultData = async () => { - // Use Vite's dev proxy to avoid CORS issues - const fileUrl = '/dropbox-file/scl/fi/nkyabkq2jdwfudof2ovrl/Data-Matrix.xlsx?rlkey=1cz5fuabwipqqivihii7sybw0&st=io0g4wvb&dl=1'; + // In dev: Vite proxy handles /dropbox-file (see vite.config.ts) + // In prod: Vercel serverless function at /api/dropbox-proxy handles it + const fileUrl = import.meta.env.DEV + ? '/dropbox-file/scl/fi/nkyabkq2jdwfudof2ovrl/Data-Matrix.xlsx?rlkey=1cz5fuabwipqqivihii7sybw0&st=io0g4wvb&dl=1' + : '/api/dropbox-proxy'; setIsLoadingDefault(true); setDefaultLoadError(null); diff --git a/src/components/ProductDescriptions.tsx b/src/components/ProductDescriptions.tsx index dc7a1ac..04a157a 100644 --- a/src/components/ProductDescriptions.tsx +++ b/src/components/ProductDescriptions.tsx @@ -76,6 +76,14 @@ export function ProductDescriptions({ data, onEdit }: ProductDescriptionsProps) }; const getRowColor = (row: ExcelRow) => { + // EOL Rule: OOC Classification and 0 stock (Item Available) + const classification = String(row[COLUMNS.CLASSIFICATION] || '').toUpperCase(); + const stock = Number(row[COLUMNS.ITEM_AVAILABLE] || 0); + + if (classification === 'OOC' && stock === 0) { + return 'bg-yellow-500/10 hover:bg-yellow-500/20'; // EOL Highlight + } + const fields = [row[COLUMNS.LONG_DE], row[COLUMNS.LONG_EN], row[COLUMNS.SHORT_DE], row[COLUMNS.SHORT_EN]]; const filled = fields.filter(Boolean).length; if (filled === 4) return 'bg-green-900/10 hover:bg-green-900/20'; @@ -83,8 +91,17 @@ export function ProductDescriptions({ data, onEdit }: ProductDescriptionsProps) return 'bg-yellow-900/10 hover:bg-yellow-900/20'; }; - const Badge = ({ content }: { content: any }) => { + const Badge = ({ content, row }: { content: any, row: ExcelRow }) => { if (content) return ; + + // EOL Exception + const classification = String(row[COLUMNS.CLASSIFICATION] || '').toUpperCase(); + const stock = Number(row[COLUMNS.ITEM_AVAILABLE] || 0); + + if (classification === 'OOC' && stock === 0) { + return EOL not neccessary; + } + return ✗ Missing; }; @@ -184,10 +201,10 @@ export function ProductDescriptions({ data, onEdit }: ProductDescriptionsProps) {row[COLUMNS.ARTICLE_NAME]} {row[COLUMNS.LINE]} {row[COLUMNS.LICENSE]} - - - - + + + +