import React, { useState, useEffect } from 'react'; import { Box, Typography, Button, Stack, TextField, IconButton, Grid } from '@mui/material'; import QRCode from 'react-qr-code'; import DeleteIcon from "@mui/icons-material/Delete"; import CheckIcon from '@mui/icons-material/Check'; import CloseIcon from '@mui/icons-material/Close'; import { Dewar, DewarsService, Shipment, ContactPerson, ApiError, ShipmentsService } from "../../openapi"; import { SxProps } from "@mui/system"; import CustomStepper from "./DewarStepper"; import DewarDetails from './DewarDetails'; const MAX_COMMENTS_LENGTH = 200; interface ShipmentDetailsProps { isCreatingShipment: boolean; sx?: SxProps; selectedShipment: Shipment | null; selectedDewar: Dewar | null; setSelectedDewar: React.Dispatch>; setSelectedShipment: React.Dispatch>; refreshShipments: () => void; defaultContactPerson?: ContactPerson; } const ShipmentDetails: React.FC = ({ sx, selectedShipment, setSelectedDewar, setSelectedShipment, refreshShipments, }) => { const [localSelectedDewar, setLocalSelectedDewar] = useState(null); const [isAddingDewar, setIsAddingDewar] = useState(false); const [comments, setComments] = useState(selectedShipment?.comments || ''); const [initialComments, setInitialComments] = useState(selectedShipment?.comments || ''); const initialNewDewarState: Partial = { dewar_name: '', tracking_number: '', number_of_pucks: 0, number_of_samples: 0, status: 'In preparation', ready_date: null, shipping_date: null, arrival_date: null, returning_date: null, contact_person_id: selectedShipment?.contact_person?.id, return_address_id: selectedShipment?.return_address?.id, }; const [newDewar, setNewDewar] = useState>(initialNewDewarState); useEffect(() => { setLocalSelectedDewar(null); // Ensure to update the default contact person and return address when the shipment changes setNewDewar((prev) => ({ ...prev, contact_person_id: selectedShipment?.contact_person?.id, return_address_id: selectedShipment?.return_address?.id })); }, [selectedShipment]); useEffect(() => { setComments(selectedShipment?.comments || ''); setInitialComments(selectedShipment?.comments || ''); }, [selectedShipment]); const totalPucks = selectedShipment?.dewars?.reduce((acc, dewar) => acc + (dewar.number_of_pucks || 0), 0) || 0; const totalSamples = selectedShipment?.dewars?.reduce((acc, dewar) => acc + (dewar.number_of_samples || 0), 0) || 0; const handleDewarSelection = (dewar: Dewar) => { const newSelection = localSelectedDewar?.id === dewar.id ? null : dewar; setLocalSelectedDewar(newSelection); setSelectedDewar(newSelection); }; const handleDeleteDewar = async (dewarId: number) => { const confirmed = window.confirm('Are you sure you want to delete this dewar?'); if (confirmed && selectedShipment) { try { const updatedShipment = await ShipmentsService.removeDewarFromShipmentShipmentsShipmentIdRemoveDewarDewarIdDelete(selectedShipment.id, dewarId); setSelectedShipment(updatedShipment); setLocalSelectedDewar(null); refreshShipments(); } catch (error) { console.error('Failed to delete dewar:', error); alert('Failed to delete dewar. Please try again.'); } } }; const handleNewDewarChange = (e: React.ChangeEvent) => { const { name, value } = e.target; setNewDewar((prev) => ({ ...prev, [name]: value, })); }; const handleAddDewar = async () => { if (newDewar.dewar_name?.trim()) { try { const newDewarToPost: Dewar = { ...initialNewDewarState, ...newDewar, dewar_name: newDewar.dewar_name.trim(), contact_person_id: selectedShipment?.contact_person?.id, return_address_id: selectedShipment?.return_address?.id } as Dewar; if (!newDewarToPost.dewar_name || !newDewarToPost.status) { throw new Error('Missing required fields'); } const createdDewar = await DewarsService.createDewarDewarsPost(newDewarToPost); if (createdDewar && selectedShipment) { const updatedShipment = await ShipmentsService.addDewarToShipmentShipmentsShipmentIdAddDewarPost(selectedShipment.id, createdDewar.id); setSelectedShipment(updatedShipment); setIsAddingDewar(false); setNewDewar(initialNewDewarState); refreshShipments(); } } catch (error) { console.error('Error adding dewar or updating shipment:', error); if (error instanceof ApiError && error.body) { console.error('Validation errors:', error.body.detail); } else { console.error('Unexpected error:', error); } alert('Failed to add dewar or update shipment. Please check the data and try again.'); } } else { alert('Please fill in the Dewar Name'); } }; const handleSaveComments = async () => { if (selectedShipment && selectedShipment.id) { try { const payload = { comments }; // Assuming `updateShipmentCommentsShipmentsShipmentIdCommentsPut` only needs the shipment ID const updatedShipment = await ShipmentsService.updateShipmentCommentsShipmentsShipmentIdCommentsPut(selectedShipment.id, payload); setSelectedShipment({ ...selectedShipment, comments: updatedShipment.comments }); setInitialComments(comments); refreshShipments(); alert('Comments updated successfully.'); } catch (error) { console.error('Failed to update comments:', error); alert('Failed to update comments. Please try again.'); } } else { console.error("Selected shipment or shipment ID is undefined"); } }; const handleCancelEdit = () => { setComments(initialComments); }; const isCommentsEdited = comments !== initialComments; const contactPerson = selectedShipment?.contact_person; return ( {!localSelectedDewar && !isAddingDewar && ( )} {isAddingDewar && ( Add New Dewar )} {selectedShipment ? ( {selectedShipment.shipment_name} Main contact person: {contactPerson ? `${contactPerson.firstname} ${contactPerson.lastname}` : 'N/A'} Number of Pucks: {totalPucks} Number of Samples: {totalSamples} Shipment Date: {selectedShipment.shipment_date} setComments(e.target.value)} sx={{ marginBottom: 2, '& .MuiInputBase-root': { color: isCommentsEdited ? 'inherit' : 'rgba(0, 0, 0, 0.6)', }, }} helperText={`${MAX_COMMENTS_LENGTH - comments.length} characters remaining`} error={comments.length > MAX_COMMENTS_LENGTH} /> MAX_COMMENTS_LENGTH} > ) : ( No shipment selected )} {selectedShipment?.dewars?.map((dewar) => ( {localSelectedDewar?.id === dewar.id && ( { setLocalSelectedDewar((prev) => (prev ? { ...prev, tracking_number: value as string } : prev)); }} initialContactPersons={localSelectedDewar?.contact_person ? [localSelectedDewar.contact_person] : []} initialReturnAddresses={localSelectedDewar?.return_address ? [localSelectedDewar.return_address] : []} defaultContactPerson={localSelectedDewar?.contact_person ?? undefined} defaultReturnAddress={localSelectedDewar?.return_address ?? undefined} shipmentId={selectedShipment?.id ?? null} refreshShipments={refreshShipments} /> )} ))} ); }; export default ShipmentDetails;