Connected frontend shipments to backend
This commit is contained in:
@ -1,308 +0,0 @@
|
||||
import React from 'react';
|
||||
import { Box, Typography, Button, Stack, TextField } from '@mui/material';
|
||||
import ShipmentForm from './ShipmentForm.tsx';
|
||||
import DewarDetails from './DewarDetails.tsx';
|
||||
import { Shipment, Dewar, ContactPerson, Proposal, Address } from '../types.ts';
|
||||
import { SxProps } from '@mui/system';
|
||||
import QRCode from 'react-qr-code';
|
||||
import bottleGrey from '../assets/icons/bottle-svgrepo-com-grey.svg';
|
||||
import bottleYellow from '../assets/icons/bottle-svgrepo-com-yellow.svg';
|
||||
import bottleGreen from '../assets/icons/bottle-svgrepo-com-green.svg';
|
||||
import ArrowForwardIcon from "@mui/icons-material/ArrowForward";
|
||||
import AirplanemodeActiveIcon from "@mui/icons-material/AirplanemodeActive";
|
||||
import StoreIcon from "@mui/icons-material/Store";
|
||||
import DeleteIcon from "@mui/icons-material/Delete"; // Import delete icon
|
||||
|
||||
interface ShipmentDetailsProps {
|
||||
selectedShipment: Shipment | null;
|
||||
setSelectedDewar: React.Dispatch<React.SetStateAction<Dewar | null>>;
|
||||
isCreatingShipment: boolean;
|
||||
newShipment: Shipment;
|
||||
setNewShipment: React.Dispatch<React.SetStateAction<Shipment>>;
|
||||
handleSaveShipment: () => void;
|
||||
contactPersons: ContactPerson[];
|
||||
proposals: Proposal[];
|
||||
returnAddresses: Address[];
|
||||
sx?: SxProps;
|
||||
}
|
||||
|
||||
const ShipmentDetails: React.FC<ShipmentDetailsProps> = ({
|
||||
selectedShipment,
|
||||
setSelectedDewar,
|
||||
isCreatingShipment,
|
||||
newShipment,
|
||||
setNewShipment,
|
||||
handleSaveShipment,
|
||||
contactPersons,
|
||||
proposals,
|
||||
returnAddresses,
|
||||
sx = {},
|
||||
}) => {
|
||||
const [localSelectedDewar, setLocalSelectedDewar] = React.useState<Dewar | null>(null);
|
||||
const [trackingNumber, setTrackingNumber] = React.useState<string>('');
|
||||
const [isAddingDewar, setIsAddingDewar] = React.useState<boolean>(false);
|
||||
const [newDewar, setNewDewar] = React.useState<Partial<Dewar>>({
|
||||
dewar_name: '',
|
||||
tracking_number: '',
|
||||
});
|
||||
|
||||
const shippingStatusMap: { [key: string]: string } = {
|
||||
"not shipped": "grey",
|
||||
"shipped": "yellow",
|
||||
"arrived": "green",
|
||||
};
|
||||
|
||||
const arrivalStatusMap: { [key: string]: string } = {
|
||||
"not arrived": "grey",
|
||||
"arrived": "green",
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
if (localSelectedDewar) {
|
||||
setTrackingNumber(localSelectedDewar.tracking_number);
|
||||
}
|
||||
}, [localSelectedDewar]);
|
||||
|
||||
if (!selectedShipment) {
|
||||
return isCreatingShipment ? (
|
||||
<ShipmentForm
|
||||
newShipment={newShipment}
|
||||
setNewShipment={setNewShipment}
|
||||
handleSaveShipment={handleSaveShipment}
|
||||
contactPersons={contactPersons}
|
||||
proposals={proposals}
|
||||
returnAddresses={returnAddresses}
|
||||
/>
|
||||
) : (
|
||||
<Typography>No shipment selected.</Typography>
|
||||
);
|
||||
}
|
||||
|
||||
// Calculate total pucks and samples
|
||||
const totalPucks = selectedShipment.dewars.reduce((acc, dewar) => acc + (dewar.number_of_pucks || 0), 0);
|
||||
const totalSamples = selectedShipment.dewars.reduce((acc, dewar) => acc + (dewar.number_of_samples || 0), 0);
|
||||
|
||||
// Handle dewar selection
|
||||
const handleDewarSelection = (dewar: Dewar) => {
|
||||
setLocalSelectedDewar(prevDewar => (prevDewar?.tracking_number === dewar.tracking_number ? null : dewar));
|
||||
setSelectedDewar(prevDewar => (prevDewar?.tracking_number === dewar.tracking_number ? null : dewar));
|
||||
};
|
||||
|
||||
// Handle dewar deletion
|
||||
const handleDeleteDewar = () => {
|
||||
if (localSelectedDewar) {
|
||||
const confirmed = window.confirm('Are you sure you want to delete this dewar?');
|
||||
if (confirmed) {
|
||||
const updatedDewars = selectedShipment.dewars.filter(dewar => dewar.tracking_number !== localSelectedDewar.tracking_number);
|
||||
console.log('Updated Dewars:', updatedDewars); // Log or update state as needed
|
||||
setLocalSelectedDewar(null); // Reset selection after deletion
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Handle form input changes for the new dewar
|
||||
const handleNewDewarChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const { name, value } = e.target;
|
||||
setNewDewar((prev) => ({
|
||||
...prev,
|
||||
[name]: value,
|
||||
}));
|
||||
};
|
||||
|
||||
// Handle adding a new dewar
|
||||
const handleAddDewar = () => {
|
||||
if (selectedShipment && newDewar.dewar_name) {
|
||||
const updatedDewars = [
|
||||
...selectedShipment.dewars,
|
||||
{ ...newDewar, tracking_number: newDewar.tracking_number || `TN-${Date.now()}` } as Dewar,
|
||||
];
|
||||
setNewShipment({
|
||||
...selectedShipment,
|
||||
dewars: updatedDewars,
|
||||
});
|
||||
setIsAddingDewar(false);
|
||||
setNewDewar({ dewar_name: '', number_of_pucks: 0, number_of_samples: 0, tracking_number: '' });
|
||||
} else {
|
||||
alert('Please fill in the Dewar Name');
|
||||
}
|
||||
};
|
||||
|
||||
// Function to generate QR Code (Placeholder)
|
||||
const generateQRCode = () => {
|
||||
console.log('Generate QR Code');
|
||||
};
|
||||
|
||||
// Handle adding new contact person and return address
|
||||
const addNewContactPerson = (name: string) => {
|
||||
// Implementation to add a new contact person
|
||||
console.log('Add new contact person:', name);
|
||||
};
|
||||
|
||||
const addNewReturnAddress = (address: string) => {
|
||||
// Implementation to add a new return address
|
||||
console.log('Add new return address:', address);
|
||||
};
|
||||
|
||||
return (
|
||||
<Box sx={{ ...sx, padding: 2, textAlign: 'left' }}>
|
||||
{/* Add Dewar Button - only visible if no dewar is selected */}
|
||||
{!localSelectedDewar && !isAddingDewar && (
|
||||
<Button
|
||||
variant="contained"
|
||||
onClick={() => setIsAddingDewar(true)}
|
||||
sx={{ marginBottom: 2 }}
|
||||
>
|
||||
Add Dewar
|
||||
</Button>
|
||||
)}
|
||||
|
||||
{/* Add Dewar Form */}
|
||||
{isAddingDewar && (
|
||||
<Box sx={{ marginBottom: 2, width: '20%' }}>
|
||||
<Typography variant="h6">Add New Dewar</Typography>
|
||||
<TextField
|
||||
label="Dewar Name"
|
||||
name="dewar_name"
|
||||
value={newDewar.dewar_name}
|
||||
onChange={handleNewDewarChange}
|
||||
fullWidth
|
||||
sx={{ marginBottom: 2 }}
|
||||
/>
|
||||
<Button variant="contained" color="primary" onClick={handleAddDewar} sx={{ marginRight: 2 }}>
|
||||
Save Dewar
|
||||
</Button>
|
||||
<Button variant="outlined" color="secondary" onClick={() => setIsAddingDewar(false)}>
|
||||
Cancel
|
||||
</Button>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
|
||||
<Typography variant="h5">{selectedShipment.shipment_name}</Typography>
|
||||
<Typography variant="body1">Number of Pucks: {totalPucks}</Typography>
|
||||
<Typography variant="body1">Number of Samples: {totalSamples}</Typography>
|
||||
<Typography variant="body1">Shipment Date: {selectedShipment.shipment_date}</Typography>
|
||||
|
||||
<Stack spacing={1}>
|
||||
{/* Render the DewarDetails component only if a dewar is selected */}
|
||||
{localSelectedDewar && (
|
||||
<DewarDetails
|
||||
dewar={localSelectedDewar}
|
||||
trackingNumber={trackingNumber}
|
||||
setTrackingNumber={setTrackingNumber}
|
||||
onGenerateQRCode={generateQRCode}
|
||||
contactPersons={contactPersons} // Pass contact persons
|
||||
returnAddresses={returnAddresses} // Pass return addresses
|
||||
addNewContactPerson={addNewContactPerson} // Pass function to add a new contact person
|
||||
addNewReturnAddress={addNewReturnAddress} // Pass function to add a new return address
|
||||
shipping_date={localSelectedDewar?.shipping_date} // Ensure these are passed
|
||||
arrival_date={localSelectedDewar?.arrival_date}
|
||||
/>
|
||||
)}
|
||||
{selectedShipment.dewars.map((dewar: Dewar) => (
|
||||
<Button
|
||||
key={dewar.tracking_number}
|
||||
onClick={() => handleDewarSelection(dewar)}
|
||||
sx={{
|
||||
width: '100%',
|
||||
textAlign: 'left',
|
||||
backgroundColor: localSelectedDewar?.tracking_number === dewar.tracking_number ? '#d0f0c0' : '#f0f0f0', // Highlight if selected
|
||||
padding: 2,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
width: 80,
|
||||
height: 80,
|
||||
backgroundColor: '#e0e0e0',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
marginRight: 2,
|
||||
}}
|
||||
>
|
||||
{dewar.qrcode ? (
|
||||
<QRCode value={dewar.qrcode} size={70} />
|
||||
) : (
|
||||
<Typography variant="body2" color="textSecondary">No QR code available</Typography>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
<Box sx={{ flexGrow: 1, marginRight: 0 }}>
|
||||
<Typography variant="body1">{dewar.dewar_name}</Typography>
|
||||
<Typography variant="body2">Number of Pucks: {dewar.number_of_pucks || 0}</Typography>
|
||||
<Typography variant="body2">Number of Samples: {dewar.number_of_samples || 0}</Typography>
|
||||
<Typography variant="body2">Tracking Number: {dewar.tracking_number}</Typography>
|
||||
</Box>
|
||||
|
||||
<Box sx={{ flexGrow: 1, display: 'flex', alignItems: 'center', flexDirection: 'row', justifyContent: 'space-evenly' }}>
|
||||
{/* Status icons and date information */}
|
||||
<Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center' }}>
|
||||
<img
|
||||
src={dewar.status === "in preparation" ? bottleYellow : (dewar.status === "ready for shipping" ? bottleGreen : bottleGrey)}
|
||||
alt={`Status: ${dewar.status}`}
|
||||
style={{ width: '40px', height: '40px', marginBottom: '4px' }}
|
||||
/>
|
||||
<Typography variant="caption" sx={{ fontSize: '12px' }} color="textSecondary">
|
||||
{dewar.ready_date ? `Ready: ${new Date(dewar.ready_date).toLocaleDateString()}` : 'N/A'}
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
<ArrowForwardIcon sx={{ margin: '0 8px', fontSize: '40px', alignSelf: 'center' }} />
|
||||
|
||||
<Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center' }}>
|
||||
<AirplanemodeActiveIcon
|
||||
sx={{
|
||||
color: shippingStatusMap[dewar.shippingStatus || ""] || "grey",
|
||||
fontSize: '40px',
|
||||
marginBottom: '4px'
|
||||
}}
|
||||
/>
|
||||
<Typography variant="caption" sx={{ fontSize: '12px' }} color="textSecondary">
|
||||
{dewar.shipping_date ? `Shipped: ${new Date(dewar.shipping_date).toLocaleDateString()}` : 'N/A'}
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
<ArrowForwardIcon sx={{ margin: '0 8px', fontSize: '40px', alignSelf: 'center' }} />
|
||||
|
||||
<Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center' }}>
|
||||
<StoreIcon
|
||||
sx={{
|
||||
color: arrivalStatusMap[dewar.arrivalStatus || ""] || "grey",
|
||||
fontSize: '40px',
|
||||
marginBottom: '4px'
|
||||
}}
|
||||
/>
|
||||
<Typography variant="caption" sx={{ fontSize: '12px' }} color="textSecondary">
|
||||
{dewar.arrival_date ? `Arrived: ${new Date(dewar.arrival_date).toLocaleDateString()}` : 'N/A'}
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
{/* Delete button if the dewar is selected */}
|
||||
{localSelectedDewar?.tracking_number === dewar.tracking_number && (
|
||||
<Button
|
||||
onClick={handleDeleteDewar}
|
||||
color="error"
|
||||
sx={{
|
||||
minWidth: '40px',
|
||||
height: '40px',
|
||||
marginLeft: 2,
|
||||
padding: 0,
|
||||
alignSelf: 'center'
|
||||
}}
|
||||
title="Delete Dewar"
|
||||
>
|
||||
<DeleteIcon />
|
||||
</Button>
|
||||
)}
|
||||
</Box>
|
||||
</Button>
|
||||
))}
|
||||
</Stack>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default ShipmentDetails;
|
Reference in New Issue
Block a user