feat: update inventory columns to match legacy portal and grant admins all companies
Some checks failed
Build and Deploy / build (push) Successful in 4m57s
Build and Deploy / deploy (push) Failing after 13s

Inventory summary table now shows Plant, Cust Part#, Vorteq Part#,
Vorteq Desc, Warehouse, Qty LB, Rows with a blue View button for
drill-down. Admins see all active companies in the company selector.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Lorentz 2026-02-16 17:02:20 +00:00
parent cf9af94f7d
commit 87c1cdf8da
3 changed files with 45 additions and 24 deletions

View file

@ -12,7 +12,7 @@ import {
} from '@/components/ui/table';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Search, Download } from 'lucide-react';
import { Search, Download, Eye } from 'lucide-react';
import { InventorySummaryRow } from '@/services/inventory';
type InventorySummaryTableProps = {
@ -30,31 +30,34 @@ export function InventorySummaryTable({
(row) =>
row.part_num.toLowerCase().includes(searchTerm.toLowerCase()) ||
row.description?.toLowerCase().includes(searchTerm.toLowerCase()) ||
row.plant?.toLowerCase().includes(searchTerm.toLowerCase())
row.plant?.toLowerCase().includes(searchTerm.toLowerCase()) ||
row.cust_part_num?.toLowerCase().includes(searchTerm.toLowerCase())
);
const handleExportCSV = () => {
// Create CSV content
const headers = [
'Part Number',
'Description',
'Plant',
'Cust Part#',
'Vorteq Part#',
'Vorteq Desc',
'Warehouse',
'On Hand Qty',
'Qty LB',
'Rows',
];
const rows = filteredData.map((row) => [
row.plant,
row.cust_part_num || '',
row.part_num,
row.description || '',
row.plant,
row.warehouse,
row.on_hand_qty,
row.rows,
]);
const csvContent = [headers, ...rows]
.map((row) => row.join(','))
.map((row) => row.map((cell) => `"${cell}"`).join(','))
.join('\n');
// Download CSV
const blob = new Blob([csvContent], { type: 'text/csv' });
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
@ -95,32 +98,39 @@ export function InventorySummaryTable({
<Table>
<TableHeader>
<TableRow>
<TableHead>Part Number</TableHead>
<TableHead>Description</TableHead>
<TableHead>Plant</TableHead>
<TableHead>Cust Part#</TableHead>
<TableHead>Vorteq Part#</TableHead>
<TableHead>Vorteq Desc</TableHead>
<TableHead>Warehouse</TableHead>
<TableHead className="text-right">On Hand Qty</TableHead>
<TableHead className="text-right">Qty LB</TableHead>
<TableHead className="text-right">Rows</TableHead>
<TableHead className="w-[70px]"></TableHead>
</TableRow>
</TableHeader>
<TableBody>
{filteredData.map((row, idx) => (
<TableRow key={idx}>
<TableCell>
<Link
href={`/inventory/${category}/detail?part=${encodeURIComponent(row.part_num)}&plant=${encodeURIComponent(row.plant_key || row.plant)}&warehouse=${encodeURIComponent(row.warehouse)}`}
className="font-medium hover:underline"
>
{row.part_num}
</Link>
</TableCell>
<TableCell className="max-w-xs truncate">
{row.description || 'N/A'}
</TableCell>
<TableCell>{row.plant}</TableCell>
<TableCell>{row.cust_part_num || '-'}</TableCell>
<TableCell className="font-medium">{row.part_num}</TableCell>
<TableCell className="max-w-xs truncate">
{row.description || '-'}
</TableCell>
<TableCell>{row.warehouse}</TableCell>
<TableCell className="text-right">
{Number(row.on_hand_qty).toLocaleString()}
</TableCell>
<TableCell className="text-right">{row.rows}</TableCell>
<TableCell>
<Link
href={`/inventory/${category}/detail?part=${encodeURIComponent(row.part_num)}&plant=${encodeURIComponent(row.plant_key || row.plant)}&warehouse=${encodeURIComponent(row.warehouse)}`}
>
<Button variant="ghost" size="icon" className="h-8 w-8 text-blue-600 hover:text-blue-800">
<Eye className="h-4 w-4" />
</Button>
</Link>
</TableCell>
</TableRow>
))}
</TableBody>

View file

@ -247,7 +247,8 @@ export async function getActiveCompany() {
}
/**
* Get all companies accessible by the current user
* Get all companies accessible by the current user.
* Admins and Super Admins can access all active companies.
*/
export async function getUserCompanies() {
const session = await getQuestSession();
@ -256,6 +257,14 @@ export async function getUserCompanies() {
return [];
}
// Admins see all active companies
if (session.userType === 'Admin' || session.userType === 'Super Admin') {
return await db.quest_company.findMany({
where: { is_active: true },
orderBy: { display_name: 'asc' },
});
}
const questUser = await db.quest_user.findUnique({
where: { id: session.questUserId },
include: {

View file

@ -14,6 +14,7 @@ export type InventorySummaryRow = {
plant_key: string;
warehouse: string;
on_hand_qty: number;
rows: number;
paint_code?: string;
cust_part_num?: string;
};
@ -50,6 +51,7 @@ function mapSummaryRow(raw: Record<string, unknown>): InventorySummaryRow {
plant_key: String(raw.PlantKey ?? ''),
warehouse: String(raw.Warehouse ?? ''),
on_hand_qty: Number(raw.OnHandQty ?? 0),
rows: Number(raw.Rows ?? 0),
paint_code: raw.PaintCode ? String(raw.PaintCode) : undefined,
cust_part_num: raw.CustPartNum ? String(raw.CustPartNum) : undefined,
};