Table UI fix and XLSX library fix
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import { useState, useRef, useEffect } from "react";
|
import { useState, useRef, useEffect } from "react";
|
||||||
import * as XLSX from "xlsx";
|
import ExcelJS from "exceljs";
|
||||||
import { chemicalsApi } from "../lib/api";
|
import { chemicalsApi } from "../lib/api";
|
||||||
import type { ChemicalInventory } from "../shared/types";
|
import type { ChemicalInventory } from "../shared/types";
|
||||||
import { Card } from "./ui/card";
|
import { Card } from "./ui/card";
|
||||||
@@ -282,15 +282,19 @@ export function Inventory() {
|
|||||||
URL.revokeObjectURL(url);
|
URL.revokeObjectURL(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleDownloadExcel() {
|
async function handleDownloadExcel() {
|
||||||
const wsData = [
|
const wb = new ExcelJS.Workbook();
|
||||||
TABLE_COLUMNS.map(c => c.label),
|
const ws = wb.addWorksheet("Chemical Inventory");
|
||||||
...filtered.map(item => TABLE_COLUMNS.map(c => item[c.key] ?? "")),
|
ws.addRow(TABLE_COLUMNS.map(c => c.label));
|
||||||
];
|
filtered.forEach(item => ws.addRow(TABLE_COLUMNS.map(c => item[c.key] ?? "")));
|
||||||
const ws = XLSX.utils.aoa_to_sheet(wsData);
|
const buffer = await wb.xlsx.writeBuffer();
|
||||||
const wb = XLSX.utils.book_new();
|
const blob = new Blob([buffer], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" });
|
||||||
XLSX.utils.book_append_sheet(wb, ws, "Chemical Inventory");
|
const url = URL.createObjectURL(blob);
|
||||||
XLSX.writeFile(wb, "chemical_inventory.xlsx");
|
const a = document.createElement("a");
|
||||||
|
a.href = url;
|
||||||
|
a.download = "chemical_inventory.xlsx";
|
||||||
|
a.click();
|
||||||
|
URL.revokeObjectURL(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── derived ─────────────────────────────────────────────────────────────
|
// ── derived ─────────────────────────────────────────────────────────────
|
||||||
@@ -622,7 +626,7 @@ export function Inventory() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<div className="overflow-auto flex-1">
|
<div className="table-scroll flex-1">
|
||||||
<table className="text-xs border-collapse min-w-max">
|
<table className="text-xs border-collapse min-w-max">
|
||||||
<thead className="sticky top-0 z-10 bg-muted">
|
<thead className="sticky top-0 z-10 bg-muted">
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
@@ -42,6 +42,7 @@
|
|||||||
"cmdk": "^1.1.1",
|
"cmdk": "^1.1.1",
|
||||||
"dotenv": "^17.3.1",
|
"dotenv": "^17.3.1",
|
||||||
"embla-carousel-react": "^8.6.0",
|
"embla-carousel-react": "^8.6.0",
|
||||||
|
"exceljs": "^4.4.0",
|
||||||
"input-otp": "^1.4.2",
|
"input-otp": "^1.4.2",
|
||||||
"lucide-react": "^0.487.0",
|
"lucide-react": "^0.487.0",
|
||||||
"next-themes": "^0.4.6",
|
"next-themes": "^0.4.6",
|
||||||
@@ -53,8 +54,7 @@
|
|||||||
"recharts": "^2.15.2",
|
"recharts": "^2.15.2",
|
||||||
"sonner": "^2.0.3",
|
"sonner": "^2.0.3",
|
||||||
"tailwind-merge": "^2.6.0",
|
"tailwind-merge": "^2.6.0",
|
||||||
"vaul": "^1.1.2",
|
"vaul": "^1.1.2"
|
||||||
"xlsx": "^0.18.5"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tailwindcss/vite": "^4.0.0",
|
"@tailwindcss/vite": "^4.0.0",
|
||||||
|
|||||||
@@ -198,3 +198,91 @@
|
|||||||
html {
|
html {
|
||||||
font-size: var(--font-size);
|
font-size: var(--font-size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.table-scroll {
|
||||||
|
overflow: scroll;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-scroll::-webkit-scrollbar {
|
||||||
|
width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-scroll::-webkit-scrollbar-track {
|
||||||
|
background: var(--muted);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-scroll::-webkit-scrollbar-thumb {
|
||||||
|
background: var(--muted-foreground);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 999px;
|
||||||
|
min-width: 30px;
|
||||||
|
min-height: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-scroll::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: var(--foreground);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hide all buttons by default, then selectively show the correct one per end */
|
||||||
|
.table-scroll::-webkit-scrollbar-button {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Up arrow — top of vertical bar */
|
||||||
|
.table-scroll::-webkit-scrollbar-button:vertical:decrement:start {
|
||||||
|
display: block;
|
||||||
|
background: var(--muted);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 999px 999px 0 0;
|
||||||
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath d='M4 2 L7 6 L1 6 Z' fill='%23666'/%3E%3C/svg%3E");
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: center;
|
||||||
|
background-size: 8px 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Down arrow — bottom of vertical bar */
|
||||||
|
.table-scroll::-webkit-scrollbar-button:vertical:increment:end {
|
||||||
|
display: block;
|
||||||
|
background: var(--muted);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 0 0 999px 999px;
|
||||||
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath d='M4 6 L7 2 L1 2 Z' fill='%23666'/%3E%3C/svg%3E");
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: center;
|
||||||
|
background-size: 8px 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Left arrow — left end of horizontal bar */
|
||||||
|
.table-scroll::-webkit-scrollbar-button:horizontal:decrement:start {
|
||||||
|
display: block;
|
||||||
|
background: var(--muted);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 999px 0 0 999px;
|
||||||
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath d='M2 4 L6 1 L6 7 Z' fill='%23666'/%3E%3C/svg%3E");
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: center;
|
||||||
|
background-size: 8px 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Right arrow — right end of horizontal bar */
|
||||||
|
.table-scroll::-webkit-scrollbar-button:horizontal:increment:end {
|
||||||
|
display: block;
|
||||||
|
background: var(--muted);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 0 999px 999px 0;
|
||||||
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath d='M6 4 L2 1 L2 7 Z' fill='%23666'/%3E%3C/svg%3E");
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: center;
|
||||||
|
background-size: 8px 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-scroll::-webkit-scrollbar-button:hover {
|
||||||
|
background: var(--border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-scroll::-webkit-scrollbar-corner {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user