724 lines
29 KiB
TypeScript
724 lines
29 KiB
TypeScript
import React, { useRef, useState, useEffect } from 'react';
|
|
import {
|
|
Box,
|
|
Typography,
|
|
TextField,
|
|
Button,
|
|
Select,
|
|
MenuItem,
|
|
Snackbar,
|
|
FormControl,
|
|
InputLabel,
|
|
IconButton,
|
|
Tooltip,
|
|
Alert,
|
|
} from '@mui/material';
|
|
|
|
import QRCode from 'react-qr-code';
|
|
import {
|
|
Dewar,
|
|
DewarType,
|
|
DewarSerialNumber,
|
|
ContactPerson,
|
|
Address,
|
|
ContactsService,
|
|
AddressesService,
|
|
DewarsService,
|
|
ShipmentsService,
|
|
} from '../../openapi';
|
|
import Unipuck from '../components/Unipuck';
|
|
import { saveAs } from 'file-saver';
|
|
import DownloadIcon from '@mui/icons-material/Download';
|
|
|
|
interface DewarDetailsProps {
|
|
dewar: Dewar;
|
|
trackingNumber: string;
|
|
setTrackingNumber: (trackingNumber: string) => void;
|
|
initialContactPersons?: ContactPerson[];
|
|
initialReturnAddresses?: Address[];
|
|
defaultContactPerson?: ContactPerson;
|
|
defaultReturnAddress?: Address;
|
|
shipmentId: number;
|
|
}
|
|
|
|
interface NewContactPerson {
|
|
id: number;
|
|
firstName: string;
|
|
lastName: string;
|
|
phone_number: string;
|
|
email: string;
|
|
}
|
|
|
|
interface NewReturnAddress {
|
|
id: number;
|
|
street: string;
|
|
city: string;
|
|
zipcode: string;
|
|
country: string;
|
|
}
|
|
|
|
const DewarDetails: React.FC<DewarDetailsProps> = ({
|
|
dewar,
|
|
trackingNumber,
|
|
setTrackingNumber,
|
|
initialContactPersons = [],
|
|
initialReturnAddresses = [],
|
|
defaultContactPerson,
|
|
defaultReturnAddress,
|
|
shipmentId,
|
|
}) => {
|
|
const [localTrackingNumber, setLocalTrackingNumber] = useState(trackingNumber);
|
|
const [contactPersons, setContactPersons] = useState(initialContactPersons);
|
|
const [returnAddresses, setReturnAddresses] = useState(initialReturnAddresses);
|
|
const [selectedContactPerson, setSelectedContactPerson] = useState<string>('');
|
|
const [selectedReturnAddress, setSelectedReturnAddress] = useState<string>('');
|
|
const [isCreatingContactPerson, setIsCreatingContactPerson] = useState(false);
|
|
const [isCreatingReturnAddress, setIsCreatingReturnAddress] = useState(false);
|
|
const [puckStatuses, setPuckStatuses] = useState<string[][]>([]);
|
|
const [newContactPerson, setNewContactPerson] = useState<NewContactPerson>({
|
|
id: 0,
|
|
firstName: '',
|
|
lastName: '',
|
|
phone_number: '',
|
|
email: '',
|
|
});
|
|
const [newReturnAddress, setNewReturnAddress] = useState<NewReturnAddress>({
|
|
id: 0,
|
|
street: '',
|
|
city: '',
|
|
zipcode: '',
|
|
country: '',
|
|
});
|
|
const [changesMade, setChangesMade] = useState(false);
|
|
const [feedbackMessage, setFeedbackMessage] = useState<string>('');
|
|
const [openSnackbar, setOpenSnackbar] = useState<boolean>(false);
|
|
const [newDewarType, setNewDewarType] = useState<string>('');
|
|
const [newDewarSerialNumber, setNewDewarSerialNumber] = useState<string>('');
|
|
const [selectedDewarType, setSelectedDewarType] = useState<string>(dewar.dewar_type_id?.toString() || '');
|
|
const [knownDewarTypes, setKnownDewarTypes] = useState<DewarType[]>([]);
|
|
const [knownSerialNumbers, setKnownSerialNumbers] = useState<DewarSerialNumber[]>([]);
|
|
const [selectedSerialNumber, setSelectedSerialNumber] = useState<string>('');
|
|
const [isQRCodeGenerated, setIsQRCodeGenerated] = useState(false);
|
|
const [qrCodeValue, setQrCodeValue] = useState(dewar.qrcode || '');
|
|
const qrCodeRef = useRef<HTMLCanvasElement>(null); //
|
|
|
|
useEffect(() => {
|
|
const fetchDewarTypes = async () => {
|
|
try {
|
|
const response = await DewarsService.getDewarTypesDewarsDewarTypesGet();
|
|
setKnownDewarTypes(response ?? []);
|
|
} catch (error) {
|
|
setFeedbackMessage('Failed to fetch dewar types.');
|
|
setOpenSnackbar(true);
|
|
console.error('Error fetching dewar types:', error);
|
|
}
|
|
};
|
|
fetchDewarTypes();
|
|
}, []);
|
|
|
|
// Fetch known serial numbers
|
|
useEffect(() => {
|
|
const fetchSerialNumbers = async () => {
|
|
try {
|
|
const response = await DewarsService.getAllSerialNumbersDewarsDewarSerialNumbersGet();
|
|
setKnownSerialNumbers(response ?? []);
|
|
} catch (error) {
|
|
setFeedbackMessage('Failed to fetch serial numbers.');
|
|
setOpenSnackbar(true);
|
|
console.error('Error fetching serial numbers:', error);
|
|
}
|
|
};
|
|
fetchSerialNumbers();
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
setLocalTrackingNumber(dewar.tracking_number || '');
|
|
|
|
const setInitialContactPerson = () => {
|
|
setSelectedContactPerson(
|
|
dewar.contact_person?.id?.toString() || defaultContactPerson?.id?.toString() || ''
|
|
);
|
|
};
|
|
|
|
const setInitialReturnAddress = () => {
|
|
setSelectedReturnAddress(
|
|
dewar.return_address?.id?.toString() || defaultReturnAddress?.id?.toString() || ''
|
|
);
|
|
};
|
|
|
|
setInitialContactPerson();
|
|
setInitialReturnAddress();
|
|
|
|
if (dewar.dewar_type_id) {
|
|
setSelectedDewarType(dewar.dewar_type_id.toString());
|
|
}
|
|
if (dewar.dewar_serial_number_id) {
|
|
setSelectedSerialNumber(dewar.dewar_serial_number_id.toString());
|
|
}
|
|
}, [dewar, defaultContactPerson, defaultReturnAddress]);
|
|
|
|
useEffect(() => {
|
|
const getContacts = async () => {
|
|
try {
|
|
const c = await ContactsService.getContactsContactsGet();
|
|
setContactPersons(c);
|
|
} catch {
|
|
setFeedbackMessage('Failed to load contact persons. Please try again later.');
|
|
setOpenSnackbar(true);
|
|
}
|
|
};
|
|
|
|
const getReturnAddresses = async () => {
|
|
try {
|
|
const a = await AddressesService.getReturnAddressesAddressesGet();
|
|
setReturnAddresses(a);
|
|
} catch {
|
|
setFeedbackMessage('Failed to load return addresses. Please try again later.');
|
|
setOpenSnackbar(true);
|
|
}
|
|
};
|
|
|
|
getContacts();
|
|
getReturnAddresses();
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
const fetchSamples = async () => {
|
|
if (dewar.id) {
|
|
try {
|
|
const fetchedSamples = await ShipmentsService.getSamplesInDewarShipmentsShipmentsShipmentIdDewarsDewarIdSamplesGet(
|
|
shipmentId,
|
|
dewar.id
|
|
);
|
|
|
|
const updatedPuckStatuses = (dewar.pucks ?? []).map((puck) => {
|
|
const puckSamples = fetchedSamples.filter((sample) => sample.puck_id === puck.id);
|
|
|
|
const statusArray = Array(16).fill('empty');
|
|
|
|
puckSamples.forEach((sample) => {
|
|
if (sample.position >= 1 && sample.position <= 16) {
|
|
statusArray[sample.position - 1] = 'filled';
|
|
}
|
|
});
|
|
|
|
return statusArray;
|
|
});
|
|
|
|
setPuckStatuses(updatedPuckStatuses);
|
|
} catch (error) {
|
|
console.error('Error fetching samples:', error);
|
|
}
|
|
}
|
|
};
|
|
|
|
fetchSamples();
|
|
}, [dewar, shipmentId]);
|
|
|
|
useEffect(() => {
|
|
setSelectedDewarType(
|
|
knownDewarTypes.find((type) => type.id === dewar.dewar_type_id)?.id.toString() || ''
|
|
);
|
|
}, [knownDewarTypes, dewar.dewar_type_id]);
|
|
|
|
useEffect(() => {
|
|
setSelectedSerialNumber(
|
|
knownSerialNumbers.find((sn) => sn.id === dewar.dewar_serial_number_id)?.id.toString() || ''
|
|
);
|
|
}, [knownSerialNumbers, dewar.dewar_serial_number_id]);
|
|
|
|
const validateEmail = (email: string) => /\S+@\S+\.\S+/.test(email);
|
|
const validatePhoneNumber = (phone: string) => /^\+?[1-9]\d{1,14}$/.test(phone);
|
|
const validateZipCode = (zipcode: string) => /^\d{5}(?:[-\s]\d{4})?$/.test(zipcode);
|
|
|
|
if (!dewar) return <Typography>No dewar selected.</Typography>;
|
|
|
|
const handleSaveNewDewarTypeAndSerialNumber = async () => {
|
|
if (newDewarType) {
|
|
try {
|
|
const typeResponse = await DewarsService.createDewarTypeDewarsDewarTypesPost({ dewar_type: newDewarType });
|
|
const serialResponse = await DewarsService.createDewarSerialNumberDewarsDewarSerialNumbersPost({
|
|
serial_number: newDewarSerialNumber,
|
|
dewar_type_id: typeResponse.id,
|
|
});
|
|
setKnownDewarTypes([...knownDewarTypes, typeResponse]);
|
|
setKnownSerialNumbers([...knownSerialNumbers, serialResponse]);
|
|
setSelectedDewarType(typeResponse.id.toString());
|
|
setSelectedSerialNumber(serialResponse.serial_number);
|
|
setNewDewarType('');
|
|
setNewDewarSerialNumber('');
|
|
setChangesMade(true);
|
|
} catch (error) {
|
|
setFeedbackMessage('Failed to save new dewar type and serial number.');
|
|
setOpenSnackbar(true);
|
|
}
|
|
} else if (newDewarSerialNumber && selectedDewarType) {
|
|
try {
|
|
const response = await DewarsService.createDewarSerialNumberDewarsDewarSerialNumbersPost({
|
|
serial_number: newDewarSerialNumber,
|
|
dewar_type_id: parseInt(selectedDewarType, 10),
|
|
});
|
|
setKnownSerialNumbers([...knownSerialNumbers, response]);
|
|
setSelectedSerialNumber(response.serial_number);
|
|
setNewDewarSerialNumber('');
|
|
setChangesMade(true);
|
|
} catch (error) {
|
|
setFeedbackMessage('Failed to save new serial number.');
|
|
setOpenSnackbar(true);
|
|
}
|
|
}
|
|
};
|
|
|
|
const handleAddContact = async () => {
|
|
if (!validateEmail(newContactPerson.email) || !validatePhoneNumber(newContactPerson.phone_number) || !newContactPerson.firstName || !newContactPerson.lastName) {
|
|
setFeedbackMessage('Please fill in all new contact person fields correctly.');
|
|
setOpenSnackbar(true);
|
|
return;
|
|
}
|
|
|
|
const payload = {
|
|
firstname: newContactPerson.firstName,
|
|
lastname: newContactPerson.lastName,
|
|
phone_number: newContactPerson.phone_number,
|
|
email: newContactPerson.email,
|
|
};
|
|
|
|
try {
|
|
const c = await ContactsService.createContactContactsPost(payload);
|
|
setContactPersons([...contactPersons, c]);
|
|
setFeedbackMessage('Contact person added successfully.');
|
|
setNewContactPerson({ id: 0, firstName: '', lastName: '', phone_number: '', email: '' });
|
|
setSelectedContactPerson(c.id?.toString() || '');
|
|
} catch {
|
|
setFeedbackMessage('Failed to create a new contact person. Please try again later.');
|
|
}
|
|
|
|
setOpenSnackbar(true);
|
|
setIsCreatingContactPerson(false);
|
|
setChangesMade(true);
|
|
};
|
|
|
|
const handleAddAddress = async () => {
|
|
if (!validateZipCode(newReturnAddress.zipcode) || !newReturnAddress.street || !newReturnAddress.city || !newReturnAddress.country) {
|
|
setFeedbackMessage('Please fill in all new return address fields correctly.');
|
|
setOpenSnackbar(true);
|
|
return;
|
|
}
|
|
|
|
const payload = {
|
|
street: newReturnAddress.street.trim(),
|
|
city: newReturnAddress.city.trim(),
|
|
zipcode: newReturnAddress.zipcode.trim(),
|
|
country: newReturnAddress.country.trim(),
|
|
};
|
|
|
|
try {
|
|
const a = await AddressesService.createReturnAddressAddressesPost(payload);
|
|
setReturnAddresses([...returnAddresses, a]);
|
|
setFeedbackMessage('Return address added successfully.');
|
|
setNewReturnAddress({
|
|
id: 0,
|
|
street: '',
|
|
city: '',
|
|
zipcode: '',
|
|
country: '',
|
|
});
|
|
setSelectedReturnAddress(a.id?.toString() || '');
|
|
} catch {
|
|
setFeedbackMessage('Failed to create a new return address. Please try again later.');
|
|
}
|
|
|
|
setOpenSnackbar(true);
|
|
setIsCreatingReturnAddress(false);
|
|
setChangesMade(true);
|
|
};
|
|
|
|
const handleSaveChanges = async () => {
|
|
const formatDate = (dateString: string | null) => {
|
|
if (!dateString) return null;
|
|
const date = new Date(dateString);
|
|
if (isNaN(date.getTime())) return null;
|
|
return date.toISOString().split('T')[0];
|
|
};
|
|
|
|
if (!selectedContactPerson || !selectedReturnAddress) {
|
|
setFeedbackMessage('Please ensure all required fields are filled.');
|
|
setOpenSnackbar(true);
|
|
return;
|
|
}
|
|
|
|
const dewarId = dewar.id;
|
|
|
|
if (!dewarId) {
|
|
setFeedbackMessage('Invalid Dewar ID. Please ensure Dewar ID is provided.');
|
|
setOpenSnackbar(true);
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const payload = {
|
|
dewar_name: dewar.dewar_name,
|
|
dewar_type_id: parseInt(selectedDewarType, 10),
|
|
dewar_serial_number_id: parseInt(selectedSerialNumber, 10),
|
|
tracking_number: localTrackingNumber,
|
|
number_of_pucks: dewar.number_of_pucks,
|
|
number_of_samples: dewar.number_of_samples,
|
|
status: dewar.status,
|
|
ready_date: formatDate(dewar.ready_date),
|
|
shipping_date: formatDate(dewar.shipping_date),
|
|
arrival_date: dewar.arrival_date,
|
|
returning_date: dewar.returning_date,
|
|
qrcode: dewar.qrcode,
|
|
return_address_id: parseInt(selectedReturnAddress ?? '', 10),
|
|
contact_person_id: parseInt(selectedContactPerson ?? '', 10),
|
|
};
|
|
|
|
await DewarsService.updateDewarDewarsDewarIdPut(dewarId, payload);
|
|
setFeedbackMessage('Changes saved successfully.');
|
|
setChangesMade(false);
|
|
} catch (error) {
|
|
setFeedbackMessage('Failed to save changes. Please try again later.');
|
|
setOpenSnackbar(true);
|
|
}
|
|
};
|
|
|
|
const handleSerialNumberChange = (value: string) => {
|
|
setSelectedSerialNumber(value);
|
|
const serialNumber = knownSerialNumbers.find((sn) => sn.id.toString() === value);
|
|
if (serialNumber) {
|
|
setSelectedDewarType(serialNumber.dewar_type_id.toString());
|
|
}
|
|
setChangesMade(true);
|
|
};
|
|
|
|
const handleGenerateQRCode = async () => {
|
|
if (!dewar) return;
|
|
|
|
try {
|
|
const response = await DewarsService.generateDewarQrcodeDewarsDewarIdGenerateQrcodePost(dewar.id);
|
|
setQrCodeValue(response.qrcode); // assuming the backend returns the QR code value
|
|
setIsQRCodeGenerated(true); // to track the state if the QR code is generated
|
|
setFeedbackMessage("QR Code generated successfully");
|
|
setOpenSnackbar(true);
|
|
} catch (error) {
|
|
console.error("Failed to generate QR code:", error);
|
|
setFeedbackMessage("QR Code generation failed");
|
|
setOpenSnackbar(true);
|
|
}
|
|
};
|
|
|
|
const handleDownloadLabel = async () => {
|
|
if (!dewar) return;
|
|
|
|
try {
|
|
const response = await DewarsService.downloadDewarLabelDewarsDewarIdDownloadLabelGet(dewar.id);
|
|
|
|
// The response object might need parsing
|
|
const blob = new Blob([response as any], { type: 'application/pdf' });
|
|
const url = window.URL.createObjectURL(blob);
|
|
const link = document.createElement('a');
|
|
link.href = url;
|
|
link.setAttribute('download', `dewar_label_${dewar.id}.pdf`);
|
|
document.body.appendChild(link);
|
|
link.click();
|
|
document.body.removeChild(link);
|
|
|
|
setFeedbackMessage("Label downloaded successfully");
|
|
setOpenSnackbar(true);
|
|
} catch (error) {
|
|
console.error("Failed to download label:", error);
|
|
setFeedbackMessage("Label download failed");
|
|
setOpenSnackbar(true);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<Box sx={{ marginTop: 2 }}>
|
|
<Typography variant="h6">Selected Dewar: {dewar.dewar_name}</Typography>
|
|
<TextField
|
|
label="Tracking Number"
|
|
value={localTrackingNumber}
|
|
onChange={(e) => {
|
|
setLocalTrackingNumber(e.target.value);
|
|
setTrackingNumber(e.target.value);
|
|
setChangesMade(true);
|
|
}}
|
|
variant="outlined"
|
|
sx={{ width: '300px', marginBottom: 2 }}
|
|
/>
|
|
<FormControl variant="outlined" sx={{ width: '300px', marginBottom: 2 }}>
|
|
<InputLabel id="dewar-serial-number-label">Dewar Serial Number</InputLabel>
|
|
<Select
|
|
labelId="dewar-serial-number-label"
|
|
label="Dewar Serial Number"
|
|
value={selectedSerialNumber}
|
|
onChange={(e) => handleSerialNumberChange(e.target.value as string)}
|
|
displayEmpty
|
|
>
|
|
{knownSerialNumbers.map((sn) => (
|
|
<MenuItem key={sn.id} value={sn.id.toString()}>
|
|
{sn.serial_number}
|
|
</MenuItem>
|
|
))}
|
|
<MenuItem value="add">Add New Serial Number</MenuItem>
|
|
</Select>
|
|
{selectedSerialNumber === 'add' && (
|
|
<Box>
|
|
<FormControl variant="outlined" sx={{ width: '300px', marginBottom: 2 }}>
|
|
<InputLabel id="dewar-type-label">Dewar Type</InputLabel>
|
|
<Select
|
|
labelId="dewar-type-label"
|
|
label="Dewar Type"
|
|
value={selectedDewarType}
|
|
onChange={(e) => {
|
|
const value = e.target.value as string;
|
|
setSelectedDewarType(value);
|
|
setChangesMade(true);
|
|
}}
|
|
displayEmpty
|
|
>
|
|
{knownDewarTypes.map((type) => (
|
|
<MenuItem key={type.id} value={type.id.toString()}>
|
|
{type.dewar_type}
|
|
</MenuItem>
|
|
))}
|
|
<MenuItem value="add">Add New Dewar Type</MenuItem>
|
|
</Select>
|
|
{selectedDewarType === 'add' && (
|
|
<Box>
|
|
<TextField
|
|
label="Add New Dewar Type"
|
|
value={newDewarType}
|
|
onChange={(e) => setNewDewarType(e.target.value)}
|
|
variant="outlined"
|
|
sx={{ width: '300px', marginBottom: 2 }}
|
|
/>
|
|
</Box>
|
|
)}
|
|
</FormControl>
|
|
<TextField
|
|
label="Add New Serial Number"
|
|
value={newDewarSerialNumber}
|
|
onChange={(e) => setNewDewarSerialNumber(e.target.value)}
|
|
variant="outlined"
|
|
sx={{ width: '300px', marginBottom: 2 }}
|
|
/>
|
|
<Button onClick={handleSaveNewDewarTypeAndSerialNumber} variant="contained">
|
|
Save Dewar Type and Serial Number
|
|
</Button>
|
|
</Box>
|
|
)}
|
|
</FormControl>
|
|
|
|
<Box sx={{ marginTop: 2 }}>
|
|
<Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center', marginBottom: 2 }}>
|
|
{qrCodeValue ? (
|
|
<Box sx={{ textAlign: 'center', marginBottom: 2 }}>
|
|
<QRCode id="qrCodeCanvas" value={qrCodeValue} size={150} />
|
|
<Box sx={{ display: 'flex', alignItems: 'center', marginTop: 1 }}>
|
|
<Tooltip title="Download Label">
|
|
<IconButton onClick={handleDownloadLabel} sx={{ transform: 'scale(1.5)', margin: 1 }}>
|
|
<DownloadIcon />
|
|
</IconButton>
|
|
</Tooltip>
|
|
<Typography variant="body2">Label is ready for download</Typography>
|
|
</Box>
|
|
</Box>
|
|
) : (
|
|
<Typography>No QR code available</Typography>
|
|
)}
|
|
<Button
|
|
variant="contained"
|
|
sx={{ marginTop: 1 }}
|
|
onClick={handleGenerateQRCode}
|
|
>
|
|
Generate QR Code
|
|
</Button>
|
|
</Box>
|
|
</Box>
|
|
|
|
<Box sx={{ marginTop: 2 }}>
|
|
<Typography variant="body1">Number of Pucks: {dewar.number_of_pucks}</Typography>
|
|
{(dewar.pucks ?? []).length > 0 ? (
|
|
<Unipuck pucks={(dewar.pucks ?? []).length} samples={puckStatuses} />
|
|
) : (
|
|
<Typography>No pucks attached to the dewar.</Typography>
|
|
)}
|
|
<Typography variant="body1">Number of Samples: {dewar.number_of_samples}</Typography>
|
|
</Box>
|
|
|
|
<Typography variant="body1">Current Contact Person:</Typography>
|
|
<Select
|
|
value={selectedContactPerson}
|
|
onChange={(e) => {
|
|
const value = e.target.value;
|
|
setSelectedContactPerson(value);
|
|
setIsCreatingContactPerson(value === 'add');
|
|
setChangesMade(true);
|
|
}}
|
|
displayEmpty
|
|
sx={{ width: '300px', marginBottom: 2 }}
|
|
>
|
|
{contactPersons.map((person) => (
|
|
<MenuItem key={person.id} value={person.id?.toString()}>
|
|
{person.firstname} {person.lastname}
|
|
</MenuItem>
|
|
))}
|
|
<MenuItem value="add">Add New Contact Person</MenuItem>
|
|
</Select>
|
|
{isCreatingContactPerson && (
|
|
<Box sx={{ marginBottom: 2 }}>
|
|
<TextField
|
|
label="First Name"
|
|
value={newContactPerson.firstName}
|
|
onChange={(e) =>
|
|
setNewContactPerson((prev) => ({
|
|
...prev,
|
|
firstName: e.target.value,
|
|
}))
|
|
}
|
|
variant="outlined"
|
|
sx={{ width: '300px', marginBottom: 2 }}
|
|
/>
|
|
<TextField
|
|
label="Last Name"
|
|
value={newContactPerson.lastName}
|
|
onChange={(e) =>
|
|
setNewContactPerson((prev) => ({
|
|
...prev,
|
|
lastName: e.target.value,
|
|
}))
|
|
}
|
|
variant="outlined"
|
|
sx={{ width: '300px', marginBottom: 2 }}
|
|
/>
|
|
<TextField
|
|
label="Phone Number"
|
|
value={newContactPerson.phone_number}
|
|
onChange={(e) =>
|
|
setNewContactPerson((prev) => ({
|
|
...prev,
|
|
phone_number: e.target.value,
|
|
}))
|
|
}
|
|
variant="outlined"
|
|
sx={{ width: '300px', marginBottom: 2 }}
|
|
/>
|
|
<TextField
|
|
label="Email"
|
|
value={newContactPerson.email}
|
|
onChange={(e) =>
|
|
setNewContactPerson((prev) => ({
|
|
...prev,
|
|
email: e.target.value,
|
|
}))
|
|
}
|
|
variant="outlined"
|
|
sx={{ width: '300px', marginBottom: 2 }}
|
|
/>
|
|
<Button onClick={handleAddContact} variant="contained">
|
|
Save New Contact Person
|
|
</Button>
|
|
</Box>
|
|
)}
|
|
|
|
<Typography variant="body1">Current Return Address:</Typography>
|
|
<Select
|
|
value={selectedReturnAddress}
|
|
onChange={(e) => {
|
|
const value = e.target.value;
|
|
setSelectedReturnAddress(value);
|
|
setIsCreatingReturnAddress(value === 'add');
|
|
setChangesMade(true);
|
|
}}
|
|
displayEmpty
|
|
sx={{ width: '300px', marginBottom: 2 }}
|
|
>
|
|
{returnAddresses.map((address) => (
|
|
<MenuItem key={address.id} value={address.id?.toString()}>
|
|
{address.street}, {address.city}, {address.zipcode}, {address.country}
|
|
</MenuItem>
|
|
))}
|
|
<MenuItem value="add">Add New Return Address</MenuItem>
|
|
</Select>
|
|
{isCreatingReturnAddress && (
|
|
<Box sx={{ marginBottom: 2 }}>
|
|
<TextField
|
|
label="Street"
|
|
value={newReturnAddress.street}
|
|
onChange={(e) =>
|
|
setNewReturnAddress((prev) => ({
|
|
...prev,
|
|
street: e.target.value,
|
|
}))
|
|
}
|
|
variant="outlined"
|
|
sx={{ width: '300px', marginBottom: 2 }}
|
|
/>
|
|
<TextField
|
|
label="City"
|
|
value={newReturnAddress.city}
|
|
onChange={(e) =>
|
|
setNewReturnAddress((prev) => ({
|
|
...prev,
|
|
city: e.target.value,
|
|
}))
|
|
}
|
|
variant="outlined"
|
|
sx={{ width: '300px', marginBottom: 2 }}
|
|
/>
|
|
<TextField
|
|
label="Zip Code"
|
|
value={newReturnAddress.zipcode}
|
|
onChange={(e) =>
|
|
setNewReturnAddress((prev) => ({
|
|
...prev,
|
|
zipcode: e.target.value,
|
|
}))
|
|
}
|
|
variant="outlined"
|
|
sx={{ width: '300px', marginBottom: 2 }}
|
|
/>
|
|
<TextField
|
|
label="Country"
|
|
value={newReturnAddress.country}
|
|
onChange={(e) =>
|
|
setNewReturnAddress((prev) => ({
|
|
...prev,
|
|
country: e.target.value,
|
|
}))
|
|
}
|
|
variant="outlined"
|
|
sx={{ width: '300px', marginBottom: 2 }}
|
|
/>
|
|
<Button onClick={handleAddAddress} variant="contained">
|
|
Save New Return Address
|
|
</Button>
|
|
</Box>
|
|
)}
|
|
|
|
<Box sx={{ marginTop: 2 }}>
|
|
<Button
|
|
variant="contained"
|
|
color="primary"
|
|
onClick={handleSaveChanges}
|
|
disabled={!changesMade}
|
|
>
|
|
Save Changes
|
|
</Button>
|
|
</Box>
|
|
|
|
<Snackbar
|
|
open={openSnackbar}
|
|
autoHideDuration={6000}
|
|
onClose={() => setOpenSnackbar(false)}
|
|
>
|
|
<Alert onClose={() => setOpenSnackbar(false)} severity="info" sx={{ width: '100%' }}>
|
|
{feedbackMessage}
|
|
</Alert>
|
|
</Snackbar>
|
|
</Box>
|
|
);
|
|
};
|
|
|
|
export default DewarDetails; |