import React, { useState, useEffect } from 'react'; import {Box, Typography, Button, Stack, TextField, IconButton, Grid, Chip} 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, Contact, ApiError, ShipmentsService } from "../../openapi"; import { SxProps } from "@mui/system"; import CustomStepper from "./DewarStepper"; import DewarDetails from './DewarDetails'; import { PuckDetailsVisual } from '../assets/icons/SimplePuckIcon'; import CrystalFacetedIcon from "../assets/icons/CrystalIcon.tsx"; const MAX_COMMENTS_LENGTH = 200; interface ShipmentDetailsProps { activePgroup: string; pgroups: string; isCreatingShipment: boolean; sx?: SxProps; selectedShipment: Shipment | null; selectedDewar: Dewar | null; setSelectedDewar: React.Dispatch>; setSelectedShipment: React.Dispatch>; refreshShipments: () => void; defaultContact?: Contact; } const ShipmentDetails: React.FC = ({ pgroups, activePgroup, 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 || ''); console.log('Active Pgroup:', activePgroup); // Debugging or use it where required const initialNewDewarState: Partial = { dewar_name: '', tracking_number: '', number_of_pucks: 0, number_of_samples: 0, contact_id: selectedShipment?.contact?.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_id: selectedShipment?.contact?.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.removeDewarFromShipmentProtectedShipmentsShipmentIdRemoveDewarDewarIdDelete( selectedShipment.id, dewarId ); setSelectedShipment(updatedShipment); setLocalSelectedDewar(null); refreshShipments(); alert('Dewar deleted successfully!'); } catch (error: any) { console.error('Full error object:', error); let errorMessage = 'Failed to delete dewar. Please try again.'; if (error instanceof ApiError && error.body) { console.error('API error body:', error.body); errorMessage = error.body.detail || errorMessage; } else if (error.message) { errorMessage = error.message; } alert(`Failed to delete dewar: ${errorMessage}`); } } }; 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, pgroups:activePgroup, dewar_name: newDewar.dewar_name.trim(), contact_id: selectedShipment?.contact?.id, return_address_id: selectedShipment?.return_address?.id, status: 'active', } as Dewar; if (!newDewarToPost.dewar_name || !newDewarToPost.status) { throw new Error('Missing required fields'); } const createdDewar = await DewarsService.createOrUpdateDewarProtectedDewarsPost(selectedShipment.id, newDewarToPost); if (createdDewar && selectedShipment) { const updatedShipment = await ShipmentsService.addDewarToShipmentProtectedShipmentsShipmentIdAddDewarPost(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.updateShipmentCommentsProtectedShipmentsShipmentIdCommentsPut(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 contact = selectedShipment?.contact; const renderPgroupChips = () => { // Safely handle pgroups as an array const pgroupsArray = Array.isArray(selectedShipment?.pgroups) ? selectedShipment.pgroups : selectedShipment?.pgroups?.split(",").map((pgroup: string) => pgroup.trim()) || []; if (!pgroupsArray.length) { return No associated pgroups; } return pgroupsArray.map((pgroup: string) => ( )); }; return ( {!localSelectedDewar && !isAddingDewar && ( )} {isAddingDewar && ( Add New Dewar )} {selectedShipment ? ( {selectedShipment.shipment_name} {renderPgroupChips()} Main contact person: {contact ? `${contact.firstname} ${contact.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)); }} initialContacts={localSelectedDewar?.contact ? [localSelectedDewar.contact] : []} initialReturnAddresses={localSelectedDewar?.return_address ? [localSelectedDewar.return_address] : []} defaultContact={localSelectedDewar?.contact ?? undefined} defaultReturnAddress={localSelectedDewar?.return_address ?? undefined} shipmentId={selectedShipment?.id ?? null} refreshShipments={refreshShipments} /> )} ))} ); }; export default ShipmentDetails;