Connected frontend new contact, new address and shipments to backend

This commit is contained in:
GotthardG
2024-10-29 23:49:33 +01:00
parent 7f46006435
commit c34c117a15
8 changed files with 329 additions and 219 deletions

View File

@ -1,96 +1,68 @@
import React from 'react';
import {Box, Typography, Button, Stack, TextField, Stepper, Step, StepLabel} from '@mui/material';
import DewarDetails from '../components/DewarDetails.tsx';
import { SxProps } from '@mui/system';
import {Box, Typography, Button, Stack, TextField} from '@mui/material';
import QRCode from 'react-qr-code';
import bottleIcon from '../assets/icons/bottle-svgrepo-com-grey.svg';
import AirplanemodeActiveIcon from "@mui/icons-material/AirplanemodeActive";
import StoreIcon from "@mui/icons-material/Store";
import DeleteIcon from "@mui/icons-material/Delete";
import {ContactPerson, Dewar, Proposal, Address, Shipment_Input, DefaultService} from "../../openapi"; // Import delete icon
import {Dewar, Shipment_Input, DefaultService} from "../../openapi";
import {SxProps} from "@mui/system";
import CustomStepper from "./DewarStepper";
import DewarDetails from './DewarDetails';
interface ShipmentDetailsProps {
selectedShipment: Shipment_Input | null;
setSelectedDewar: React.Dispatch<React.SetStateAction<Dewar | null>>;
isCreatingShipment: boolean;
newShipment: Shipment_Input;
setNewShipment: React.Dispatch<React.SetStateAction<Shipment_Input>>;
handleSaveShipment: () => void;
contactPersons: ContactPerson[];
proposals: Proposal[];
returnAddresses: Address[];
selectedShipment: Shipment_Input;
selectedDewar: Dewar | null;
setSelectedDewar: React.Dispatch<React.SetStateAction<Dewar | null>>;
sx?: SxProps;
}
const ShipmentDetails: React.FC<ShipmentDetailsProps> = ({
selectedShipment,
setSelectedDewar,
setNewShipment,
contactPersons,
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: '',
});
// Step titles based on your status
const steps = ['Ready for Shipping', 'Shipped', 'Arrived'];
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));
if (setSelectedDewar) {
const newSelection = localSelectedDewar?.id === dewar.id ? null : dewar;
setLocalSelectedDewar(newSelection);
setSelectedDewar(newSelection);
}
};
// 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
console.log('Updated Dewars:', updatedDewars);
setLocalSelectedDewar(null);
}
}
};
// Handle form input changes for the new dewar
const handleNewDewarChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const { name, value } = e.target;
const {name, value} = e.target;
setNewDewar((prev) => ({
...prev,
[name]: value,
}));
};
const createDewar = async (newDewar: Partial<Dewar>, shipmentId: string) => {
console.log("Payload being sent to the API:", newDewar);
try {
const response = await DefaultService.createDewarDewarsPost(shipmentId, newDewar);
console.log("Response from API:", response);
return response;
} catch (error) {
console.error("Error creating dewar:", error);
if (error.response) {
console.error("Validation error details:", error.response.data);
}
throw error;
}
};
// Handle adding a new dewar
const handleAddDewar = async () => {
if (selectedShipment && newDewar.dewar_name) {
try {
const newDewarToPost: Dewar = {
//id: `DEWAR${Date.now()}`,
dewar_name: newDewar.dewar_name.trim() || 'Unnamed Dewar',
number_of_pucks: newDewar.number_of_pucks ?? 0,
number_of_samples: newDewar.number_of_samples ?? 0,
@ -100,25 +72,11 @@ const ShipmentDetails: React.FC<ShipmentDetailsProps> = ({
shippingStatus: 'not shipped',
arrivalStatus: 'not arrived',
qrcode: newDewar.qrcode || 'N/A',
//tracking_number: newDewar.tracking_number?.trim() || `TN-${Date.now()}`,
//ready_date: newDewar.ready_date || 'N/A',
//shipping_date: newDewar.shipping_date || 'N/A',
//arrival_date: newDewar.arrival_date || 'N/A',
};
// Post to backend
const createdDewar = await createDewar(newDewarToPost, selectedShipment.id);
// Update state with the response from backend
setNewShipment(prev => ({
...prev,
dewars: [...prev.dewars, createdDewar],
}));
// Reset form fields
await DefaultService.createDewarDewarsPost(newDewarToPost);
setIsAddingDewar(false);
//setNewDewar({ dewar_name: '', number_of_pucks: 0, number_of_samples: 0, tracking_number: '' });
setNewDewar({dewar_name: '', tracking_number: ''});
} catch (error) {
alert("Failed to add dewar. Please try again.");
console.error("Error adding dewar:", error);
@ -128,49 +86,20 @@ const ShipmentDetails: React.FC<ShipmentDetailsProps> = ({
}
};
// 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);
};
// Function to determine the color of the step icon
const getStepIconColor = (dewar: Dewar) => {
const { status, shippingStatus, arrivalStatus } = dewar;
if (status === 'Ready for Shipping') return 'green'; // Bottle Icon
if (shippingStatus === 'shipped') return 'green'; // Plane Icon
if (shippingStatus === 'not shipped') return 'yellow'; // Plane Icon
if (arrivalStatus === 'arrived') return 'green'; // Store Icon
if (arrivalStatus === 'not arrived') return 'yellow'; // Store Icon
return 'grey'; // Default color
};
return (
<Box sx={{ ...sx, padding: 2, textAlign: 'left' }}>
{/* Add Dewar Button - only visible if no dewar is selected */}
<Box sx={{...sx, padding: 2, textAlign: 'left'}}>
{!localSelectedDewar && !isAddingDewar && (
<Button
variant="contained"
onClick={() => setIsAddingDewar(true)}
sx={{ marginBottom: 2 }}
sx={{marginBottom: 2}}
>
Add Dewar
</Button>
)}
{/* Add Dewar Form */}
{isAddingDewar && (
<Box sx={{ marginBottom: 2, width: '20%' }}>
<Box sx={{marginBottom: 2, width: '20%'}}>
<Typography variant="h6">Add New Dewar</Typography>
<TextField
label="Dewar Name"
@ -178,9 +107,9 @@ const ShipmentDetails: React.FC<ShipmentDetailsProps> = ({
value={newDewar.dewar_name}
onChange={handleNewDewarChange}
fullWidth
sx={{ marginBottom: 2 }}
sx={{marginBottom: 2}}
/>
<Button variant="contained" color="primary" onClick={handleAddDewar} sx={{ marginRight: 2 }}>
<Button variant="contained" color="primary" onClick={handleAddDewar} sx={{marginRight: 2}}>
Save Dewar
</Button>
<Button variant="outlined" color="secondary" onClick={() => setIsAddingDewar(false)}>
@ -190,40 +119,27 @@ const ShipmentDetails: React.FC<ShipmentDetailsProps> = ({
)}
<Typography variant="h5">{selectedShipment.shipment_name}</Typography>
{/* Iterate over contact persons if it's an array */}
{selectedShipment.contact_person && selectedShipment.contact_person.length > 0 ? (
selectedShipment.contact_person.map((person, index) => (
<Typography key={index} variant="body1">
Contact Person: {person.firstname} {person.lastname}
</Typography>
))
) : (
<Typography variant="body1">No contact person assigned.</Typography>
)}
<Typography variant="body1" color="textSecondary">Main contact person: {`${selectedShipment.contact_person[0].firstname} ${selectedShipment.contact_person[0].lastname}`}</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
/>
)}
{localSelectedDewar && !isAddingDewar && (
<DewarDetails
dewar={localSelectedDewar}
trackingNumber={localSelectedDewar.tracking_number || ''}
setTrackingNumber={(value) => {
setLocalSelectedDewar((prev) => prev ? {...prev, tracking_number: value} : prev);
}}
contactPersons={selectedShipment.contact_person}
returnAddresses={selectedShipment.return_address}
/>
)}
<Stack spacing={1}>
{selectedShipment.dewars.map((dewar) => (
<Button
key={dewar.tracking_number}
key={dewar.id}
onClick={() => handleDewarSelection(dewar)}
variant="outlined"
sx={{
@ -233,7 +149,7 @@ const ShipmentDetails: React.FC<ShipmentDetailsProps> = ({
padding: 1,
border: '1px solid #ccc',
borderRadius: 1,
backgroundColor: localSelectedDewar?.tracking_number === dewar.tracking_number ? '#f0f0f0' : '#fff', // Color when selected
backgroundColor: localSelectedDewar?.id === dewar.id ? '#f0f0f0' : '#fff',
}}
>
<Box
@ -245,7 +161,7 @@ const ShipmentDetails: React.FC<ShipmentDetailsProps> = ({
}}
>
{dewar.qrcode ? (
<QRCode value={dewar.qrcode} size={70} />
<QRCode value={dewar.qrcode} size={70}/>
) : (
<Box
sx={{
@ -254,7 +170,7 @@ const ShipmentDetails: React.FC<ShipmentDetailsProps> = ({
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
border: '1px dashed #ccc', // Dashed border for placeholder
border: '1px dashed #ccc',
borderRadius: 1,
color: 'text.secondary'
}}
@ -264,46 +180,21 @@ const ShipmentDetails: React.FC<ShipmentDetailsProps> = ({
)}
</Box>
<Box sx={{ flexGrow: 1, marginRight: 0 }}>
<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-between' }}>
{/* Horizontal Stepper for status */}
<Stepper alternativeLabel activeStep={steps.indexOf(dewar.status) !== -1 ? steps.indexOf(dewar.status) : 0}>
{steps.map((label, index) => (
<Step key={label}>
<StepLabel StepIconComponent={({ active, completed }) => {
const color = getStepIconColor(dewar); // Use status for color
return (
<span style={{ color }}>
{index === 0 ? (
<img src={bottleIcon} alt="Bottle Icon" style={{ width: 24, height: 24 }} />
) : index === 1 ? (
<AirplanemodeActiveIcon style={{ color }} />
) : index === 2 ? (
<StoreIcon style={{ color , width: 24, height: 24}} />
) : (
<StoreIcon style={{ color }} // Use store icon for arrival status
/>
)}
</span>
);
}}>{label}</StepLabel>
{/* Display associated date */}
<Typography variant="body2">
{index === 0 ? dewar.ready_date :
index === 1 ? dewar.shipping_date :
index === 2 ? dewar.arrival_date : ''}
</Typography>
</Step>
))}
</Stepper>
{/* Delete button if the dewar is selected */}
<Box sx={{
flexGrow: 1,
display: 'flex',
alignItems: 'center',
flexDirection: 'row',
justifyContent: 'space-between'
}}>
<CustomStepper dewar={dewar} />
{localSelectedDewar?.tracking_number === dewar.tracking_number && (
<Button
onClick={handleDeleteDewar}
@ -316,7 +207,7 @@ const ShipmentDetails: React.FC<ShipmentDetailsProps> = ({
alignSelf: 'center',
}}
>
<DeleteIcon />
<DeleteIcon/>
</Button>
)}
</Box>
@ -327,4 +218,4 @@ const ShipmentDetails: React.FC<ShipmentDetailsProps> = ({
);
};
export default ShipmentDetails;
export default ShipmentDetails;