aaredb/frontend/src/components/ShipmentPanel.tsx

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;