186 lines
8.2 KiB
TypeScript
186 lines
8.2 KiB
TypeScript
import * as React from 'react';
|
|
import { Button, Box, Typography, IconButton } from '@mui/material';
|
|
import { Add as AddIcon, Delete as DeleteIcon, UploadFile as UploadFileIcon, Refresh as RefreshIcon } from '@mui/icons-material';
|
|
import UploadDialog from './UploadDialog';
|
|
import { Shipment_Input, Dewar, DefaultService } from '../../openapi';
|
|
import { SxProps } from '@mui/material';
|
|
import bottleGrey from '/src/assets/icons/bottle-svgrepo-com-grey.svg'
|
|
import bottleYellow from '/src/assets/icons/bottle-svgrepo-com-yellow.svg'
|
|
import bottleGreen from '/src/assets/icons/bottle-svgrepo-com-green.svg'
|
|
import bottleRed from '/src/assets/icons/bottle-svgrepo-com-red.svg'
|
|
|
|
interface ShipmentPanelProps {
|
|
setCreatingShipment: (value: boolean) => void;
|
|
selectedPage?: string;
|
|
selectShipment: (shipment: Shipment_Input | null) => void;
|
|
sx?: SxProps;
|
|
shipments: Shipment_Input[];
|
|
refreshShipments: () => void;
|
|
error: string | null;
|
|
}
|
|
|
|
const statusIconMap: Record<string, string> = {
|
|
'In Transit': bottleYellow,
|
|
'Delivered': bottleGreen,
|
|
'Pending': bottleGrey,
|
|
'Unknown': bottleRed,
|
|
};
|
|
|
|
const ShipmentPanel: React.FC<ShipmentPanelProps> = ({
|
|
setCreatingShipment,
|
|
selectShipment,
|
|
sx,
|
|
shipments,
|
|
refreshShipments,
|
|
error
|
|
}) => {
|
|
const [selectedShipment, setSelectedShipment] = React.useState<Shipment_Input | null>(null);
|
|
const [uploadDialogOpen, setUploadDialogOpen] = React.useState(false);
|
|
|
|
const handleDeleteShipment = async () => {
|
|
if (selectedShipment) {
|
|
const confirmed = window.confirm(`Are you sure you want to delete the shipment: ${selectedShipment.shipment_name}?`);
|
|
if (confirmed) {
|
|
await deleteShipment(selectedShipment.shipment_id);
|
|
}
|
|
}
|
|
};
|
|
|
|
const deleteShipment = async (shipmentId: string | undefined) => {
|
|
if (!shipmentId) return;
|
|
try {
|
|
// Assumes DefaultService.deleteShipmentShipmentsShipmentIdDelete is already defined
|
|
await DefaultService.deleteShipmentShipmentsShipmentIdDelete(shipmentId);
|
|
refreshShipments(); // Call the refresh function after deletion
|
|
setSelectedShipment(null);
|
|
} catch (error) {
|
|
// Handle error
|
|
}
|
|
};
|
|
|
|
const handleShipmentSelection = (shipment: Shipment_Input) => {
|
|
const isSelected = selectedShipment?.shipment_id === shipment.shipment_id;
|
|
const updatedShipment = isSelected ? null : shipment;
|
|
setSelectedShipment(updatedShipment);
|
|
selectShipment(updatedShipment);
|
|
};
|
|
|
|
const openUploadDialog = () => setUploadDialogOpen(true);
|
|
const closeUploadDialog = () => setUploadDialogOpen(false);
|
|
|
|
const getNumberOfDewars = (shipment: Shipment_Input): number => {
|
|
return shipment.dewars ? shipment.dewars.length : 0;
|
|
};
|
|
|
|
return (
|
|
<Box sx={{ width: '90%', borderRight: '1px solid #ccc', padding: 2, ...sx }}>
|
|
{error && <Typography color="error">{error}</Typography>}
|
|
<Typography variant="h6" sx={{ marginBottom: 2, fontWeight: 'bold' }}>
|
|
Shipments
|
|
</Typography>
|
|
<Box sx={{ display: 'flex', alignItems: 'center', marginBottom: 2 }}>
|
|
<Button
|
|
variant="contained"
|
|
color="primary"
|
|
startIcon={<AddIcon />}
|
|
onClick={() => setCreatingShipment(true)}
|
|
sx={{ padding: '10px 16px' }}
|
|
>
|
|
Create Shipment
|
|
</Button>
|
|
<IconButton
|
|
onClick={refreshShipments}
|
|
color="primary"
|
|
title="Refresh Shipments"
|
|
sx={{ marginLeft: 1 }}
|
|
>
|
|
<RefreshIcon />
|
|
</IconButton>
|
|
</Box>
|
|
{shipments.map((shipment) => (
|
|
<Button
|
|
key={shipment.shipment_id}
|
|
onClick={() => handleShipmentSelection(shipment)}
|
|
sx={{
|
|
width: '100%',
|
|
textAlign: 'left',
|
|
marginBottom: 1,
|
|
color: 'white',
|
|
whiteSpace: 'nowrap',
|
|
overflow: 'hidden',
|
|
textOverflow: 'ellipsis',
|
|
padding: '10px 16px',
|
|
fontSize: '0.7rem',
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
justifyContent: 'space-between',
|
|
backgroundColor: selectedShipment?.shipment_id === shipment.shipment_id ? '#52893e' : '#424242',
|
|
'&:hover': {
|
|
backgroundColor: selectedShipment?.shipment_id === shipment.shipment_id ? '#9aca8c' : '#616161',
|
|
},
|
|
'&:active': {
|
|
backgroundColor: selectedShipment?.shipment_id === shipment.shipment_id ? '#915151' : '#212121',
|
|
},
|
|
}}
|
|
>
|
|
<div style={{ display: 'flex', alignItems: 'center' }}>
|
|
<div style={{ position: 'relative', marginRight: '8px' }}>
|
|
<img
|
|
src={statusIconMap[shipment.shipment_status] || bottleGrey}
|
|
alt={`Status: ${shipment.shipment_status}`}
|
|
width="24"
|
|
/>
|
|
<span style={{
|
|
position: 'absolute',
|
|
top: '0%',
|
|
right: '0%',
|
|
transform: 'translate(50%, -50%)',
|
|
color: 'white',
|
|
fontWeight: 'bold',
|
|
fontSize: '0.6rem',
|
|
backgroundColor: 'transparent',
|
|
borderRadius: '50%',
|
|
padding: '0 2px',
|
|
}}>
|
|
{getNumberOfDewars(shipment)} {/* Calculate number of dewars */}
|
|
</span>
|
|
</div>
|
|
<div>
|
|
<div>{shipment.shipment_name}</div>
|
|
<div style={{ fontSize: '0.6rem', color: '#ccc' }}>{shipment.shipment_date}</div>
|
|
<div style={{ fontSize: '0.6rem', color: '#ccc' }}>
|
|
Total Pucks: {shipment.dewars.reduce((total, dewar: Dewar) => total + dewar.number_of_pucks, 0)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div style={{ display: 'flex', alignItems: 'center' }}>
|
|
<IconButton
|
|
onClick={openUploadDialog}
|
|
color="primary"
|
|
title="Upload Sample Data Sheet"
|
|
sx={{ marginLeft: 1 }}
|
|
>
|
|
<UploadFileIcon />
|
|
</IconButton>
|
|
{selectedShipment?.shipment_id === shipment.shipment_id && (
|
|
<IconButton
|
|
onClick={handleDeleteShipment}
|
|
color="error"
|
|
title="Delete Shipment"
|
|
sx={{ marginLeft: 1 }}
|
|
>
|
|
<DeleteIcon />
|
|
</IconButton>
|
|
)}
|
|
</div>
|
|
</Button>
|
|
))}
|
|
<UploadDialog
|
|
open={uploadDialogOpen}
|
|
onClose={closeUploadDialog}
|
|
/>
|
|
</Box>
|
|
);
|
|
};
|
|
|
|
export default ShipmentPanel; |