Enhance Dewar handling and display in logistics system

Added new fields and enriched data representations in DewarStatusTab, backend schemas, and APIs to improve dewar tracking and management. Introduced new API endpoint `/dewar/table` for simplified data rendering. Applied logging and validations for missing relationships.
This commit is contained in:
GotthardG
2025-02-05 21:43:17 +01:00
parent 25673ae05c
commit 43d67b1044
3 changed files with 243 additions and 38 deletions

View File

@ -2,12 +2,18 @@ import React, { useEffect, useState } from "react";
import DataGrid from "react-data-grid";
import { Box, Typography, Snackbar, Alert, CircularProgress } from "@mui/material";
import { LogisticsService } from "../../../frontend/openapi";
import "react-data-grid/lib/styles.css";
import dayjs from 'dayjs'; // Import dayjs library
interface Dewar {
id: string;
dewar_name: string;
shipment_name: string; // Added new field
slot_id: string; // Added new field
status: string;
location: string;
beamline_location: string;
timestamp: string; // You can change this type based on your API response
}
@ -15,54 +21,149 @@ const DewarStatusTab: React.FC = () => {
const [dewars, setDewars] = useState<Dewar[]>([]);
const [loading, setLoading] = useState<boolean>(false);
const [error, setError] = useState<string | null>(null);
const columns = [
{ key: "dewar_name", name: "Dewar Name", resizable: true },
{
key: "status",
name: "Status",
editable: true,
resizable: true,
editor: (props: { row: any; column: any; onRowChange: any }) => {
return (
<input
type="text"
value={props.row[props.column.key]}
onChange={(e) => props.onRowChange({ ...props.row, [props.column.key]: e.target.value })}
style={{
border: "none",
outline: "none",
padding: "4px",
}}
/>
);
},
},
{ key: "location", name: "Location", resizable: true },
{ key: "timestamp", name: "Last Updated", resizable: true },
const slotQRCodes = [
"A1-X06SA",
"A2-X06SA",
"A3-X06SA",
"A4-X06SA",
"A5-X06SA",
"B1-X06SA",
"B2-X06SA",
"B3-X06SA",
"B4-X06SA",
"B5-X06SA",
"C1-X06SA",
"C2-X06SA",
"C3-X06SA",
"C4-X06SA",
"C5-X06SA",
"D1-X06SA",
"D2-X06SA",
"D3-X06SA",
"D4-X06SA",
"D5-X06SA",
"A1-X10SA",
"A2-X10SA",
"A3-X10SA",
"A4-X10SA",
"A5-X10SA",
"B1-X10SA",
"B2-X10SA",
"B3-X10SA",
"B4-X10SA",
"B5-X10SA",
"C1-X10SA",
"C2-X10SA",
"C3-X10SA",
"C4-X10SA",
"C5-X10SA",
"D1-X10SA",
"D2-X10SA",
"D3-X10SA",
"D4-X10SA",
"D5-X10SA",
"NB1",
"NB2",
"NB3",
"NB4",
"NB5",
"NB6",
"X10SA-Beamline",
"X06SA-Beamline",
"X06DA-Beamline",
"Outgoing X10SA",
"Outgoing X06SA",
];
// Fetch dewars when component mounts
useEffect(() => {
fetchDewarData();
}, []);
// Updated columns array
const columns = [
{ key: "shipment_name", name: "Shipment Name", resizable: true },
{ key: "dewar_name", name: "Dewar Name", resizable: true },
{ key: "slot_id", name: "Storage", resizable: true },
{ key: "status", name: "Status", editable: true, resizable: true },
{ key: "beamline_location", name: "Location", resizable: true },
{ key: "last_updated", name: "Last Updated", resizable: true },
{ key: "local_contact", name: "Local Contact", resizable: true }, // Now a string
{ key: "contact", name: "Contact", resizable: true }, // Now a string
{ key: "address", name: "Return Address", resizable: true }, // Now a string
];
const fetchDewarData = async () => {
setLoading(true);
try {
const dewarData = await LogisticsService.getAllDewarsLogisticsDewarsGet(); // Use your real API call
setDewars(dewarData);
// Fetch data from API
const dewarData = await LogisticsService.getAllDewarsTableLogisticsDewarTableGet();
// Log the raw data for debugging
console.log("Fetched dewarData:", dewarData);
// Flatten and enrich data
const enrichedData = dewarData.map((dewar: any) => {
// Format address into a single string
const returnAddress = dewar.address && dewar.address.length > 0
? `${dewar.address[0].house_number || ""} ${dewar.address[0].street || ""}, ${dewar.address[0].city || ""}, ${dewar.address[0].state || ""}, ${dewar.address[0].zipcode || ""}, ${dewar.address[0].country || ""}`.trim()
: "N/A";
// Format contact into a single string
const contact = dewar.contact && dewar.contact.length > 0
? `${dewar.contact[0].firstname || "N/A"} ${dewar.contact[0].lastname || "N/A"} (${dewar.contact[0].email || "N/A"})`
: "N/A";
// Format local_contact into a single string
const localContact = dewar.local_contact
? `${dewar.local_contact.firstname || "N/A"} ${dewar.local_contact.lastname || "N/A"} (${dewar.local_contact.phone_number || "N/A"})`
: "N/A";
const beamline_location = dewar.events.slot_id || "N/A";
console.log("Beamline location:", beamline_location);
// Log any fields that are missing or appear incorrect
if (!dewar.local_contact) console.warn("Missing local_contact for dewar:", dewar);
if (!dewar.contact) console.warn("Missing contact for dewar:", dewar);
if (!dewar.address) console.warn("Missing address for dewar:", dewar);
return {
...dewar,
local_contact: localContact,
contact: contact,
address: returnAddress, // Replace `address` object with single formatted string
beamline_location: dewar.events !== undefined && slotQRCodes[dewar.events]
? slotQRCodes[dewar.events -1]
: "",
slot_id: dewar.slot_id !== undefined && slotQRCodes[dewar.slot_id]
? slotQRCodes[dewar.slot_id -1]
: "", // Convert slot_id to descriptive label
last_updated: dewar.last_updated
? new Date(dewar.last_updated).toLocaleString('en-US', {
year: 'numeric',
month: 'short',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
hour12: true,
})
: ""
};
});
setDewars(enrichedData);
console.log("Final enrichedData:", enrichedData);
} catch (e) {
console.error("Failed to fetch or process dewar data:", e);
setError("Failed to fetch dewar data");
} finally {
setLoading(false);
}
};
const onRowsChange = async (updatedRow: Dewar[]) => {
setDewars(updatedRow);
useEffect(() => {
fetchDewarData();
}, []);
const onRowsChange = async (updatedRows: Dewar[]) => {
setDewars(updatedRows);
try {
const updatedDewar = updatedRow[updatedRow.length - 1]; // Get the last edited row
const updatedDewar = updatedRows[updatedRows.length - 1]; // Get the last edited row
await LogisticsService.updateDewarStatus({ ...updatedDewar }); // Mock API update
} catch (err) {
setError("Error updating dewar");
@ -87,7 +188,7 @@ const DewarStatusTab: React.FC = () => {
columns={columns}
rows={dewars}
onRowsChange={onRowsChange}
style={{ height: 600, width: "100%" }}
style={{ height: 600, width: "100%" }} // Make sure height and width are set
/>
)}
</Box>