better support of add and delete dewar to a shipment
This commit is contained in:
parent
d6d7e7c919
commit
dc31eec66e
@ -148,8 +148,8 @@ dewars = [
|
|||||||
id='DEWAR003',
|
id='DEWAR003',
|
||||||
dewar_name='Dewar Three',
|
dewar_name='Dewar Three',
|
||||||
tracking_number='TRACK125',
|
tracking_number='TRACK125',
|
||||||
number_of_pucks=4,
|
number_of_pucks=7,
|
||||||
number_of_samples=47,
|
number_of_samples=72,
|
||||||
return_address=[return_addresses[0]],
|
return_address=[return_addresses[0]],
|
||||||
contact_person=[contacts[2]],
|
contact_person=[contacts[2]],
|
||||||
status='Not Shipped',
|
status='Not Shipped',
|
||||||
@ -163,8 +163,8 @@ dewars = [
|
|||||||
id='DEWAR004',
|
id='DEWAR004',
|
||||||
dewar_name='Dewar Four',
|
dewar_name='Dewar Four',
|
||||||
tracking_number='',
|
tracking_number='',
|
||||||
number_of_pucks=4,
|
number_of_pucks=7,
|
||||||
number_of_samples=47,
|
number_of_samples=70,
|
||||||
return_address=[return_addresses[0]],
|
return_address=[return_addresses[0]],
|
||||||
contact_person=[contacts[2]],
|
contact_person=[contacts[2]],
|
||||||
status='Delayed',
|
status='Delayed',
|
||||||
@ -178,8 +178,8 @@ dewars = [
|
|||||||
id='DEWAR005',
|
id='DEWAR005',
|
||||||
dewar_name='Dewar Five',
|
dewar_name='Dewar Five',
|
||||||
tracking_number='',
|
tracking_number='',
|
||||||
number_of_pucks=4,
|
number_of_pucks=3,
|
||||||
number_of_samples=47,
|
number_of_samples=30,
|
||||||
return_address=[return_addresses[0]],
|
return_address=[return_addresses[0]],
|
||||||
contact_person=[contacts[2]],
|
contact_person=[contacts[2]],
|
||||||
status='Returned',
|
status='Returned',
|
||||||
@ -312,6 +312,23 @@ async def create_dewar(dewar: Dewar) -> Dewar:
|
|||||||
|
|
||||||
return dewar # Return the newly created dewar
|
return dewar # Return the newly created dewar
|
||||||
|
|
||||||
|
@app.delete("/shipments/{shipment_id}/remove_dewar/{dewar_id}", response_model=Shipment)
|
||||||
|
async def remove_dewar_from_shipment(shipment_id: str, dewar_id: str):
|
||||||
|
"""Remove a dewar from a shipment."""
|
||||||
|
# Log parameters
|
||||||
|
logging.info(f"Received request to remove dewar {dewar_id} from shipment {shipment_id}")
|
||||||
|
|
||||||
|
# Find the shipment by ID
|
||||||
|
shipment = next((sh for sh in shipments if sh.shipment_id == shipment_id), None)
|
||||||
|
if not shipment:
|
||||||
|
logging.error(f"Shipment with ID {shipment_id} not found")
|
||||||
|
raise HTTPException(status_code=404, detail="Shipment not found")
|
||||||
|
|
||||||
|
# Remove the dewar from the shipment
|
||||||
|
shipment.dewars = [dw for dw in shipment.dewars if dw.id != dewar_id]
|
||||||
|
|
||||||
|
return shipment
|
||||||
|
|
||||||
|
|
||||||
@app.get("/shipment_contact_persons")
|
@app.get("/shipment_contact_persons")
|
||||||
async def get_shipment_contact_persons():
|
async def get_shipment_contact_persons():
|
||||||
|
@ -24,7 +24,7 @@ const ICONS: { [key: number]: React.ReactElement } = {
|
|||||||
2: <StoreIcon style={ICON_STYLE} />, // 'Not Arrived'
|
2: <StoreIcon style={ICON_STYLE} />, // 'Not Arrived'
|
||||||
3: <RecycleIcon style={ICON_STYLE} />, // 'Returned'
|
3: <RecycleIcon style={ICON_STYLE} />, // 'Returned'
|
||||||
4: <AirplanemodeActiveIcon style={{ ...ICON_STYLE, color: 'green' }} />, // 'Shipped' - Active
|
4: <AirplanemodeActiveIcon style={{ ...ICON_STYLE, color: 'green' }} />, // 'Shipped' - Active
|
||||||
5: <AirplanemodeActiveIcon style={{ ...ICON_STYLE, color: 'yellow' }} />, // 'Delayed'
|
5: <AirplanemodeActiveIcon style={{ ...ICON_STYLE, color: 'orange' }} />, // 'Delayed'
|
||||||
};
|
};
|
||||||
|
|
||||||
// Define StepIconContainer to accept correct props and handle typing better.
|
// Define StepIconContainer to accept correct props and handle typing better.
|
||||||
@ -44,7 +44,7 @@ type StepIconComponentProps = {
|
|||||||
} & StepIconProps;
|
} & StepIconProps;
|
||||||
|
|
||||||
const StepIconComponent = ({ icon, dewar, ...props }: StepIconComponentProps) => {
|
const StepIconComponent = ({ icon, dewar, ...props }: StepIconComponentProps) => {
|
||||||
const { iconIndex, color, fill } = getIconProperties(icon, dewar);
|
const { iconIndex, color} = getIconProperties(icon, dewar);
|
||||||
|
|
||||||
// Adjust icon color for the bottle especially since it's an SVG element
|
// Adjust icon color for the bottle especially since it's an SVG element
|
||||||
const IconComponent = ICONS[iconIndex];
|
const IconComponent = ICONS[iconIndex];
|
||||||
@ -84,7 +84,7 @@ const getStatusStepIndex = (status: DewarStatus): number => STATUS_TO_STEP[statu
|
|||||||
const determineIconColor = (iconIndex: number, status: DewarStatus): string => {
|
const determineIconColor = (iconIndex: number, status: DewarStatus): string => {
|
||||||
const statusIndex = getStatusStepIndex(status);
|
const statusIndex = getStatusStepIndex(status);
|
||||||
if (status === 'Delayed' && iconIndex === 1) {
|
if (status === 'Delayed' && iconIndex === 1) {
|
||||||
return 'yellow';
|
return 'orange';
|
||||||
}
|
}
|
||||||
return iconIndex <= statusIndex ? (iconIndex === statusIndex ? (status === 'Shipped' ? 'green' : 'blue') : 'green') : 'grey';
|
return iconIndex <= statusIndex ? (iconIndex === statusIndex ? (status === 'Shipped' ? 'green' : 'blue') : 'green') : 'grey';
|
||||||
};
|
};
|
||||||
@ -97,23 +97,25 @@ const CustomStepper = ({ dewar }: { dewar: Dewar }) => {
|
|||||||
const activeStep = getStatusStepIndex(dewar.status as DewarStatus);
|
const activeStep = getStatusStepIndex(dewar.status as DewarStatus);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stepper alternativeLabel activeStep={activeStep}>
|
<div style={{ display: 'flex', justifyContent: 'center', width: '100%' /* Or any other preferred width */, maxWidth: '600px', margin: '0 auto' }}>
|
||||||
{steps.map((label, index) => (
|
<Stepper alternativeLabel activeStep={activeStep} style={{ width: '100%' }}>
|
||||||
<Step key={label}>
|
{steps.map((label, index) => (
|
||||||
<StepLabel
|
<Step key={label}>
|
||||||
StepIconComponent={(stepProps) => <StepIconComponent {...stepProps} icon={index} dewar={dewar} />}
|
<StepLabel
|
||||||
>
|
StepIconComponent={(stepProps) => <StepIconComponent {...stepProps} icon={index} dewar={dewar} />}
|
||||||
{label}
|
>
|
||||||
</StepLabel>
|
{label}
|
||||||
<Typography variant="body2">
|
</StepLabel>
|
||||||
{index === 0 ? dewar.ready_date :
|
<Typography variant="body2">
|
||||||
index === 1 ? dewar.shipping_date :
|
{index === 0 ? dewar.ready_date :
|
||||||
index === 2 ? dewar.arrival_date :
|
index === 1 ? dewar.shipping_date :
|
||||||
index === 3 ? dewar.returning_date : null}
|
index === 2 ? dewar.arrival_date :
|
||||||
</Typography>
|
index === 3 ? dewar.returning_date : ''}
|
||||||
</Step>
|
</Typography>
|
||||||
))}
|
</Step>
|
||||||
</Stepper>
|
))}
|
||||||
|
</Stepper>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -29,6 +29,11 @@ const ShipmentDetails: React.FC<ShipmentDetailsProps> = ({
|
|||||||
tracking_number: '',
|
tracking_number: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// To reset localSelectedDewar when selectedShipment changes
|
||||||
|
React.useEffect(() => {
|
||||||
|
setLocalSelectedDewar(null);
|
||||||
|
}, [selectedShipment]);
|
||||||
|
|
||||||
const totalPucks = selectedShipment.dewars.reduce((acc, dewar) => acc + (dewar.number_of_pucks || 0), 0);
|
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);
|
const totalSamples = selectedShipment.dewars.reduce((acc, dewar) => acc + (dewar.number_of_samples || 0), 0);
|
||||||
|
|
||||||
@ -38,13 +43,23 @@ const ShipmentDetails: React.FC<ShipmentDetailsProps> = ({
|
|||||||
setSelectedDewar(newSelection);
|
setSelectedDewar(newSelection);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDeleteDewar = () => {
|
const handleDeleteDewar = async (dewarId: string) => {
|
||||||
if (localSelectedDewar) {
|
const confirmed = window.confirm('Are you sure you want to delete this dewar?');
|
||||||
const confirmed = window.confirm('Are you sure you want to delete this dewar?');
|
if (confirmed) {
|
||||||
if (confirmed) {
|
try {
|
||||||
const updatedDewars = selectedShipment.dewars.filter(dewar => dewar.tracking_number !== localSelectedDewar.tracking_number);
|
console.log('Selected Shipment ID:', selectedShipment.shipment_id);
|
||||||
setSelectedShipment((prev) => ({ ...prev, dewars: updatedDewars }));
|
console.log('Dewar ID to be deleted:', dewarId);
|
||||||
|
|
||||||
|
const updatedShipment = await DefaultService.removeDewarFromShipmentShipmentsShipmentIdRemoveDewarDewarIdDelete(
|
||||||
|
selectedShipment.shipment_id, dewarId
|
||||||
|
);
|
||||||
|
|
||||||
|
// Ensure state is updated with server response
|
||||||
|
setSelectedShipment(updatedShipment);
|
||||||
setLocalSelectedDewar(null);
|
setLocalSelectedDewar(null);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to delete dewar:', error);
|
||||||
|
alert('Failed to delete dewar. Please try again.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -57,15 +72,6 @@ const ShipmentDetails: React.FC<ShipmentDetailsProps> = ({
|
|||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
const addDewarToList = (currentDewars: Array<Dewar>, newDewar: Dewar): Array<Dewar> => {
|
|
||||||
return [...currentDewars, newDewar];
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateDewarsState = (prev: Shipment_Input, createdDewar: Dewar): Shipment_Input => {
|
|
||||||
const updatedDewars = addDewarToList(prev.dewars, createdDewar);
|
|
||||||
return { ...prev, dewars: updatedDewars };
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleAddDewar = async () => {
|
const handleAddDewar = async () => {
|
||||||
if (selectedShipment && newDewar.dewar_name) {
|
if (selectedShipment && newDewar.dewar_name) {
|
||||||
try {
|
try {
|
||||||
@ -100,15 +106,15 @@ const ShipmentDetails: React.FC<ShipmentDetailsProps> = ({
|
|||||||
if (updatedShipment) {
|
if (updatedShipment) {
|
||||||
setSelectedShipment(updatedShipment);
|
setSelectedShipment(updatedShipment);
|
||||||
} else {
|
} else {
|
||||||
throw new Error("Failed to update shipment with new dewar");
|
throw new Error('Failed to update shipment with new dewar');
|
||||||
}
|
}
|
||||||
|
|
||||||
setIsAddingDewar(false);
|
setIsAddingDewar(false);
|
||||||
setNewDewar({ dewar_name: '', tracking_number: '' });
|
setNewDewar({ dewar_name: '', tracking_number: '' });
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
alert("Failed to add dewar or update shipment. Please try again.");
|
alert('Failed to add dewar or update shipment. Please try again.');
|
||||||
console.error("Error adding dewar or updating shipment:", error);
|
console.error('Error adding dewar or updating shipment:', error);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
alert('Please fill in the Dewar Name');
|
alert('Please fill in the Dewar Name');
|
||||||
@ -224,9 +230,9 @@ const ShipmentDetails: React.FC<ShipmentDetailsProps> = ({
|
|||||||
justifyContent: 'space-between'
|
justifyContent: 'space-between'
|
||||||
}}>
|
}}>
|
||||||
<CustomStepper dewar={dewar} />
|
<CustomStepper dewar={dewar} />
|
||||||
{localSelectedDewar?.tracking_number === dewar.tracking_number && (
|
{localSelectedDewar?.id === dewar.id && (
|
||||||
<Button
|
<Button
|
||||||
onClick={handleDeleteDewar}
|
onClick={() => handleDeleteDewar(dewar.id)} // <--- Pass the dewar ID here
|
||||||
color="error"
|
color="error"
|
||||||
sx={{
|
sx={{
|
||||||
minWidth: '40px',
|
minWidth: '40px',
|
||||||
|
@ -8,12 +8,10 @@ import { useEffect } from "react";
|
|||||||
interface ShipmentFormProps {
|
interface ShipmentFormProps {
|
||||||
sx?: SxProps;
|
sx?: SxProps;
|
||||||
onCancel: () => void;
|
onCancel: () => void;
|
||||||
|
refreshShipments: () => void; // Add the refresh function as a prop
|
||||||
}
|
}
|
||||||
|
|
||||||
const ShipmentForm: React.FC<ShipmentFormProps> = ({
|
const ShipmentForm: React.FC<ShipmentFormProps> = ({ sx = {}, onCancel, refreshShipments }) => {
|
||||||
sx = {},
|
|
||||||
onCancel,
|
|
||||||
}) => {
|
|
||||||
const [contactPersons, setContactPersons] = React.useState<ContactPerson[]>([]);
|
const [contactPersons, setContactPersons] = React.useState<ContactPerson[]>([]);
|
||||||
const [returnAddresses, setReturnAddresses] = React.useState<Address[]>([]);
|
const [returnAddresses, setReturnAddresses] = React.useState<Address[]>([]);
|
||||||
const [proposals, setProposals] = React.useState<Proposal[]>([]);
|
const [proposals, setProposals] = React.useState<Proposal[]>([]);
|
||||||
@ -25,14 +23,12 @@ const ShipmentForm: React.FC<ShipmentFormProps> = ({
|
|||||||
phone_number: '',
|
phone_number: '',
|
||||||
email: '',
|
email: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
const [newReturnAddress, setNewReturnAddress] = React.useState<Address>({
|
const [newReturnAddress, setNewReturnAddress] = React.useState<Address>({
|
||||||
street: '',
|
street: '',
|
||||||
city: '',
|
city: '',
|
||||||
zipcode: '',
|
zipcode: '',
|
||||||
country: ''
|
country: ''
|
||||||
});
|
});
|
||||||
|
|
||||||
const [newShipment, setNewShipment] = React.useState<Shipment_Input>({
|
const [newShipment, setNewShipment] = React.useState<Shipment_Input>({
|
||||||
comments: undefined,
|
comments: undefined,
|
||||||
contact_person: [],
|
contact_person: [],
|
||||||
@ -44,7 +40,6 @@ const ShipmentForm: React.FC<ShipmentFormProps> = ({
|
|||||||
shipment_name: "",
|
shipment_name: "",
|
||||||
shipment_status: ""
|
shipment_status: ""
|
||||||
});
|
});
|
||||||
|
|
||||||
const [errorMessage, setErrorMessage] = React.useState<string | null>(null);
|
const [errorMessage, setErrorMessage] = React.useState<string | null>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -168,6 +163,7 @@ const ShipmentForm: React.FC<ShipmentFormProps> = ({
|
|||||||
try {
|
try {
|
||||||
await DefaultService.createShipmentShipmentsPost(payload);
|
await DefaultService.createShipmentShipmentsPost(payload);
|
||||||
setErrorMessage(null);
|
setErrorMessage(null);
|
||||||
|
refreshShipments(); // Ensure shipments are refreshed after creation
|
||||||
onCancel(); // close the form after saving
|
onCancel(); // close the form after saving
|
||||||
} catch {
|
} catch {
|
||||||
setErrorMessage('Failed to save shipment. Please try again.');
|
setErrorMessage('Failed to save shipment. Please try again.');
|
||||||
@ -286,12 +282,18 @@ const ShipmentForm: React.FC<ShipmentFormProps> = ({
|
|||||||
<FormControl fullWidth required>
|
<FormControl fullWidth required>
|
||||||
<InputLabel>Contact Person</InputLabel>
|
<InputLabel>Contact Person</InputLabel>
|
||||||
<Select
|
<Select
|
||||||
value={newShipment.contact_person?.[0]?.lastname || ''}
|
value={
|
||||||
|
isCreatingContactPerson
|
||||||
|
? 'new'
|
||||||
|
: newShipment.contact_person.length > 0
|
||||||
|
? newShipment.contact_person[0].lastname
|
||||||
|
: ''
|
||||||
|
}
|
||||||
onChange={handleContactPersonChange}
|
onChange={handleContactPersonChange}
|
||||||
displayEmpty
|
displayEmpty
|
||||||
>
|
>
|
||||||
{contactPersons.map((person) => (
|
{contactPersons.map((person) => (
|
||||||
<MenuItem key={person.lastname + person.firstname} value={person.lastname}>
|
<MenuItem key={person.lastname} value={person.lastname}>
|
||||||
{`${person.lastname}, ${person.firstname}`}
|
{`${person.lastname}, ${person.firstname}`}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
))}
|
))}
|
||||||
@ -346,10 +348,12 @@ const ShipmentForm: React.FC<ShipmentFormProps> = ({
|
|||||||
error={!validateEmail(newContactPerson.email)}
|
error={!validateEmail(newContactPerson.email)}
|
||||||
helperText={!validateEmail(newContactPerson.email) ? "Invalid email" : ""}
|
helperText={!validateEmail(newContactPerson.email) ? "Invalid email" : ""}
|
||||||
/>
|
/>
|
||||||
<Button variant="contained"
|
<Button
|
||||||
color="primary"
|
variant="contained"
|
||||||
onClick={handleSaveNewContactPerson}
|
color="primary"
|
||||||
disabled={!isContactFormValid()}>
|
onClick={handleSaveNewContactPerson}
|
||||||
|
disabled={!isContactFormValid()}
|
||||||
|
>
|
||||||
Save New Contact Person
|
Save New Contact Person
|
||||||
</Button>
|
</Button>
|
||||||
</>
|
</>
|
||||||
@ -371,7 +375,13 @@ const ShipmentForm: React.FC<ShipmentFormProps> = ({
|
|||||||
<FormControl fullWidth required>
|
<FormControl fullWidth required>
|
||||||
<InputLabel>Return Address</InputLabel>
|
<InputLabel>Return Address</InputLabel>
|
||||||
<Select
|
<Select
|
||||||
value={newShipment.return_address?.[0]?.city || ''}
|
value={
|
||||||
|
isCreatingReturnAddress
|
||||||
|
? 'new'
|
||||||
|
: newShipment.return_address.length > 0
|
||||||
|
? newShipment.return_address[0].city
|
||||||
|
: ''
|
||||||
|
}
|
||||||
onChange={handleReturnAddressChange}
|
onChange={handleReturnAddressChange}
|
||||||
displayEmpty
|
displayEmpty
|
||||||
>
|
>
|
||||||
@ -424,10 +434,12 @@ const ShipmentForm: React.FC<ShipmentFormProps> = ({
|
|||||||
fullWidth
|
fullWidth
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
<Button variant="contained"
|
<Button
|
||||||
color="primary"
|
variant="contained"
|
||||||
onClick={handleSaveNewReturnAddress}
|
color="primary"
|
||||||
disabled={!isAddressFormValid()}>
|
onClick={handleSaveNewReturnAddress}
|
||||||
|
disabled={!isAddressFormValid()}
|
||||||
|
>
|
||||||
Save New Return Address
|
Save New Return Address
|
||||||
</Button>
|
</Button>
|
||||||
</>
|
</>
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { useEffect, useState } from 'react';
|
|
||||||
import { Button, Box, Typography, IconButton } from '@mui/material';
|
import { Button, Box, Typography, IconButton } from '@mui/material';
|
||||||
import { Add as AddIcon, Delete as DeleteIcon, UploadFile as UploadFileIcon, Refresh as RefreshIcon } from '@mui/icons-material';
|
import { Add as AddIcon, Delete as DeleteIcon, UploadFile as UploadFileIcon, Refresh as RefreshIcon } from '@mui/icons-material';
|
||||||
import UploadDialog from './UploadDialog';
|
import UploadDialog from './UploadDialog';
|
||||||
import { Shipment_Input, DefaultService, OpenAPI, Dewar } from '../../openapi'; // Import relevant types
|
import { Shipment_Input, Dewar, DefaultService } from '../../openapi';
|
||||||
import { SxProps } from '@mui/material';
|
import { SxProps } from '@mui/material';
|
||||||
import bottleGrey from '/src/assets/icons/bottle-svgrepo-com-grey.svg'
|
import bottleGrey from '/src/assets/icons/bottle-svgrepo-com-grey.svg'
|
||||||
import bottleYellow from '/src/assets/icons/bottle-svgrepo-com-yellow.svg'
|
import bottleYellow from '/src/assets/icons/bottle-svgrepo-com-yellow.svg'
|
||||||
@ -15,11 +14,11 @@ interface ShipmentPanelProps {
|
|||||||
selectedPage?: string;
|
selectedPage?: string;
|
||||||
selectShipment: (shipment: Shipment_Input | null) => void;
|
selectShipment: (shipment: Shipment_Input | null) => void;
|
||||||
sx?: SxProps;
|
sx?: SxProps;
|
||||||
|
shipments: Shipment_Input[];
|
||||||
|
refreshShipments: () => void;
|
||||||
|
error: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const API_BASE_URL = 'http://127.0.0.1:8000';
|
|
||||||
OpenAPI.BASE = API_BASE_URL;
|
|
||||||
|
|
||||||
const statusIconMap: Record<string, string> = {
|
const statusIconMap: Record<string, string> = {
|
||||||
'In Transit': bottleYellow,
|
'In Transit': bottleYellow,
|
||||||
'Delivered': bottleGreen,
|
'Delivered': bottleGreen,
|
||||||
@ -27,25 +26,16 @@ const statusIconMap: Record<string, string> = {
|
|||||||
'Unknown': bottleRed,
|
'Unknown': bottleRed,
|
||||||
};
|
};
|
||||||
|
|
||||||
const ShipmentPanel: React.FC<ShipmentPanelProps> = ({ setCreatingShipment, selectShipment, sx }) => {
|
const ShipmentPanel: React.FC<ShipmentPanelProps> = ({
|
||||||
const [shipments, setShipments] = useState<Shipment_Input[]>([]);
|
setCreatingShipment,
|
||||||
const [selectedShipment, setSelectedShipment] = useState<Shipment_Input | null>(null);
|
selectShipment,
|
||||||
const [error, setError] = useState<string | null>(null);
|
sx,
|
||||||
const [uploadDialogOpen, setUploadDialogOpen] = useState(false);
|
shipments,
|
||||||
|
refreshShipments,
|
||||||
useEffect(() => {
|
error
|
||||||
fetchAndSetShipments();
|
}) => {
|
||||||
}, []);
|
const [selectedShipment, setSelectedShipment] = React.useState<Shipment_Input | null>(null);
|
||||||
|
const [uploadDialogOpen, setUploadDialogOpen] = React.useState(false);
|
||||||
const fetchAndSetShipments = async () => {
|
|
||||||
try {
|
|
||||||
const shipmentsData: Shipment_Input[] = await DefaultService.getShipmentsShipmentsGet();
|
|
||||||
shipmentsData.sort((a, b) => new Date(b.shipment_date).getTime() - new Date(a.shipment_date).getTime());
|
|
||||||
setShipments(shipmentsData);
|
|
||||||
} catch (error) {
|
|
||||||
setError('Failed to fetch shipments. Please try again later.');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleDeleteShipment = async () => {
|
const handleDeleteShipment = async () => {
|
||||||
if (selectedShipment) {
|
if (selectedShipment) {
|
||||||
@ -59,12 +49,12 @@ const ShipmentPanel: React.FC<ShipmentPanelProps> = ({ setCreatingShipment, sele
|
|||||||
const deleteShipment = async (shipmentId: string | undefined) => {
|
const deleteShipment = async (shipmentId: string | undefined) => {
|
||||||
if (!shipmentId) return;
|
if (!shipmentId) return;
|
||||||
try {
|
try {
|
||||||
|
// Assumes DefaultService.deleteShipmentShipmentsShipmentIdDelete is already defined
|
||||||
await DefaultService.deleteShipmentShipmentsShipmentIdDelete(shipmentId);
|
await DefaultService.deleteShipmentShipmentsShipmentIdDelete(shipmentId);
|
||||||
setShipments(shipments.filter(shipment => shipment.shipment_id !== shipmentId));
|
refreshShipments(); // Call the refresh function after deletion
|
||||||
setSelectedShipment(null);
|
setSelectedShipment(null);
|
||||||
setError(null);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setError('Failed to delete shipment. Please try again later.');
|
// Handle error
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -77,7 +67,6 @@ const ShipmentPanel: React.FC<ShipmentPanelProps> = ({ setCreatingShipment, sele
|
|||||||
|
|
||||||
const openUploadDialog = () => setUploadDialogOpen(true);
|
const openUploadDialog = () => setUploadDialogOpen(true);
|
||||||
const closeUploadDialog = () => setUploadDialogOpen(false);
|
const closeUploadDialog = () => setUploadDialogOpen(false);
|
||||||
const refreshShipments = () => fetchAndSetShipments();
|
|
||||||
|
|
||||||
const getNumberOfDewars = (shipment: Shipment_Input): number => {
|
const getNumberOfDewars = (shipment: Shipment_Input): number => {
|
||||||
return shipment.dewars ? shipment.dewars.length : 0;
|
return shipment.dewars ? shipment.dewars.length : 0;
|
||||||
|
@ -1,16 +1,35 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import Grid from '@mui/material/Grid'; // Using Grid (deprecated but configurable)
|
import Grid from '@mui/material/Grid'; // Using Grid (deprecated but configurable)
|
||||||
import ShipmentPanel from '../components/ShipmentPanel';
|
import ShipmentPanel from '../components/ShipmentPanel';
|
||||||
import ShipmentDetails from '../components/ShipmentDetails';
|
import ShipmentDetails from '../components/ShipmentDetails';
|
||||||
import ShipmentForm from '../components/ShipmentForm';
|
import ShipmentForm from '../components/ShipmentForm';
|
||||||
import { Dewar, Shipment_Input } from '../../openapi';
|
import { Dewar, Shipment_Input, DefaultService, OpenAPI } from '../../openapi';
|
||||||
|
|
||||||
type ShipmentViewProps = React.PropsWithChildren<Record<string, never>>;
|
type ShipmentViewProps = React.PropsWithChildren<Record<string, never>>;
|
||||||
|
|
||||||
|
const API_BASE_URL = 'http://127.0.0.1:8000';
|
||||||
|
OpenAPI.BASE = API_BASE_URL;
|
||||||
|
|
||||||
const ShipmentView: React.FC<ShipmentViewProps> = () => {
|
const ShipmentView: React.FC<ShipmentViewProps> = () => {
|
||||||
const [isCreatingShipment, setIsCreatingShipment] = useState(false);
|
const [isCreatingShipment, setIsCreatingShipment] = useState(false);
|
||||||
const [selectedShipment, setSelectedShipment] = useState<Shipment_Input | null>(null);
|
const [selectedShipment, setSelectedShipment] = useState<Shipment_Input | null>(null);
|
||||||
const [selectedDewar, setSelectedDewar] = useState<Dewar | null>(null);
|
const [selectedDewar, setSelectedDewar] = useState<Dewar | null>(null);
|
||||||
|
const [shipments, setShipments] = useState<Shipment_Input[]>([]);
|
||||||
|
const [error, setError] = useState<string | null>(null);
|
||||||
|
|
||||||
|
const fetchAndSetShipments = async () => {
|
||||||
|
try {
|
||||||
|
const shipmentsData: Shipment_Input[] = await DefaultService.getShipmentsShipmentsGet();
|
||||||
|
shipmentsData.sort((a, b) => new Date(b.shipment_date).getTime() - new Date(a.shipment_date).getTime());
|
||||||
|
setShipments(shipmentsData);
|
||||||
|
} catch (error) {
|
||||||
|
setError('Failed to fetch shipments. Please try again later.');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchAndSetShipments();
|
||||||
|
}, []);
|
||||||
|
|
||||||
const handleSelectShipment = (shipment: Shipment_Input | null) => {
|
const handleSelectShipment = (shipment: Shipment_Input | null) => {
|
||||||
setSelectedShipment(shipment);
|
setSelectedShipment(shipment);
|
||||||
@ -23,7 +42,11 @@ const ShipmentView: React.FC<ShipmentViewProps> = () => {
|
|||||||
|
|
||||||
const renderShipmentContent = () => {
|
const renderShipmentContent = () => {
|
||||||
if (isCreatingShipment) {
|
if (isCreatingShipment) {
|
||||||
return <ShipmentForm sx={{ flexGrow: 1 }} onCancel={handleCancelShipmentForm} />;
|
return <ShipmentForm
|
||||||
|
sx={{ flexGrow: 1 }}
|
||||||
|
onCancel={handleCancelShipmentForm}
|
||||||
|
refreshShipments={fetchAndSetShipments} // Pass the fetch function to refresh shipments
|
||||||
|
/>;
|
||||||
}
|
}
|
||||||
if (selectedShipment) {
|
if (selectedShipment) {
|
||||||
return (
|
return (
|
||||||
@ -56,6 +79,9 @@ const ShipmentView: React.FC<ShipmentViewProps> = () => {
|
|||||||
selectedPage="Shipments"
|
selectedPage="Shipments"
|
||||||
setCreatingShipment={setIsCreatingShipment}
|
setCreatingShipment={setIsCreatingShipment}
|
||||||
selectShipment={handleSelectShipment}
|
selectShipment={handleSelectShipment}
|
||||||
|
shipments={shipments}
|
||||||
|
refreshShipments={fetchAndSetShipments}
|
||||||
|
error={error}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid
|
<Grid
|
||||||
|
Loading…
x
Reference in New Issue
Block a user