added pucks and samples
This commit is contained in:
@ -1,19 +1,7 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import {
|
||||
Box,
|
||||
Typography,
|
||||
TextField,
|
||||
Button,
|
||||
Select,
|
||||
MenuItem,
|
||||
Snackbar
|
||||
} from '@mui/material';
|
||||
import { Box, Typography, TextField, Button, Select, MenuItem, Snackbar } from '@mui/material';
|
||||
import QRCode from 'react-qr-code';
|
||||
import {
|
||||
ContactPerson,
|
||||
Address,
|
||||
Dewar, ContactsService, AddressesService, ShipmentsService,
|
||||
} from '../../openapi';
|
||||
import { ContactPerson, Address, Dewar, ContactsService, AddressesService, ShipmentsService, Puck, Sample } from '../../openapi';
|
||||
import Unipuck from '../components/Unipuck';
|
||||
|
||||
interface DewarDetailsProps {
|
||||
@ -48,6 +36,7 @@ const DewarDetails: React.FC<DewarDetailsProps> = ({
|
||||
const [selectedReturnAddress, setSelectedReturnAddress] = useState<string>('');
|
||||
const [isCreatingContactPerson, setIsCreatingContactPerson] = useState(false);
|
||||
const [isCreatingReturnAddress, setIsCreatingReturnAddress] = useState(false);
|
||||
const [puckStatuses, setPuckStatuses] = useState<string[][]>(dewar.pucks.map(() => Array(16).fill('empty')));
|
||||
const [newContactPerson, setNewContactPerson] = useState({
|
||||
id: 0,
|
||||
firstName: '',
|
||||
@ -114,6 +103,28 @@ const DewarDetails: React.FC<DewarDetailsProps> = ({
|
||||
getReturnAddresses();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchSamples = async () => {
|
||||
if (dewar.id) {
|
||||
try {
|
||||
const samples: Sample[] = await ShipmentsService.getSamplesInDewarShipmentsShipmentIdDewarsDewarIdSamplesGet(shipmentId, dewar.id);
|
||||
const updatedPuckStatuses = dewar.pucks.map(puck => {
|
||||
return puck.positions.map(position => {
|
||||
const isOccupied = samples.some(sample => sample.id === position.id);
|
||||
return isOccupied ? 'filled' : 'empty';
|
||||
});
|
||||
});
|
||||
setPuckStatuses(updatedPuckStatuses);
|
||||
} catch {
|
||||
setFeedbackMessage('Failed to load samples. Please try again later.');
|
||||
setOpenSnackbar(true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
fetchSamples();
|
||||
}, [dewar, shipmentId]);
|
||||
|
||||
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);
|
||||
@ -123,7 +134,6 @@ const DewarDetails: React.FC<DewarDetailsProps> = ({
|
||||
}
|
||||
|
||||
const handleAddContact = async () => {
|
||||
console.log('handleAddContact called');
|
||||
if (!validateEmail(newContactPerson.email) || !validatePhoneNumber(newContactPerson.phone_number) ||
|
||||
!newContactPerson.firstName || !newContactPerson.lastName) {
|
||||
setFeedbackMessage('Please fill in all new contact person fields correctly.');
|
||||
@ -154,9 +164,7 @@ const DewarDetails: React.FC<DewarDetailsProps> = ({
|
||||
};
|
||||
|
||||
const handleAddAddress = async () => {
|
||||
console.log('handleAddAddress called');
|
||||
if (!validateZipCode(newReturnAddress.zipcode) || !newReturnAddress.street || !newReturnAddress.city ||
|
||||
!newReturnAddress.country) {
|
||||
if (!validateZipCode(newReturnAddress.zipcode) || !newReturnAddress.street || !newReturnAddress.city || !newReturnAddress.country) {
|
||||
setFeedbackMessage('Please fill in all new return address fields correctly.');
|
||||
setOpenSnackbar(true);
|
||||
return;
|
||||
@ -185,7 +193,6 @@ const DewarDetails: React.FC<DewarDetailsProps> = ({
|
||||
};
|
||||
|
||||
const getShipmentById = async (shipmentId: string) => {
|
||||
console.log(`Fetching shipment with ID: ${shipmentId}`);
|
||||
try {
|
||||
const response = await ShipmentsService.fetchShipmentsShipmentsGet(shipmentId);
|
||||
if (response && response.length > 0) {
|
||||
@ -193,14 +200,11 @@ const DewarDetails: React.FC<DewarDetailsProps> = ({
|
||||
}
|
||||
throw new Error('Shipment not found');
|
||||
} catch (error) {
|
||||
console.error('Error fetching shipment:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
const handleSaveChanges = async () => {
|
||||
console.log('handleSaveChanges called');
|
||||
|
||||
const formatDate = (dateString: string | undefined): string | null => {
|
||||
if (!dateString) return null;
|
||||
const date = new Date(dateString);
|
||||
@ -208,23 +212,15 @@ const DewarDetails: React.FC<DewarDetailsProps> = ({
|
||||
return date.toISOString().split('T')[0];
|
||||
};
|
||||
|
||||
console.log('Selected Contact Person:', selectedContactPerson);
|
||||
console.log('Selected Return Address:', selectedReturnAddress);
|
||||
|
||||
// Check if required fields are filled
|
||||
if (!selectedContactPerson || !selectedReturnAddress) {
|
||||
setFeedbackMessage('Please ensure all required fields are filled.');
|
||||
setOpenSnackbar(true);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Saving changes...');
|
||||
console.log('Current Dewar:', dewar);
|
||||
|
||||
let existingShipment;
|
||||
try {
|
||||
existingShipment = await getShipmentById(shipmentId);
|
||||
console.log('Existing Shipment:', existingShipment);
|
||||
} catch {
|
||||
setFeedbackMessage('Failed to fetch existing shipment data. Please try again later.');
|
||||
setOpenSnackbar(true);
|
||||
@ -234,7 +230,7 @@ const DewarDetails: React.FC<DewarDetailsProps> = ({
|
||||
const updatedDewar = {
|
||||
dewar_id: dewar.id,
|
||||
dewar_name: dewar.dewar_name,
|
||||
tracking_number: dewar.tracking_number,
|
||||
tracking_number: localTrackingNumber,
|
||||
number_of_pucks: dewar.number_of_pucks,
|
||||
number_of_samples: dewar.number_of_samples,
|
||||
status: dewar.status,
|
||||
@ -244,7 +240,7 @@ const DewarDetails: React.FC<DewarDetailsProps> = ({
|
||||
returning_date: dewar.returning_date,
|
||||
qrcode: dewar.qrcode,
|
||||
return_address_id: selectedReturnAddress,
|
||||
contact_person_id: selectedContactPerson, // Set dewar-specific contact person
|
||||
contact_person_id: selectedContactPerson,
|
||||
};
|
||||
|
||||
const payload = {
|
||||
@ -259,16 +255,12 @@ const DewarDetails: React.FC<DewarDetailsProps> = ({
|
||||
dewars: [updatedDewar],
|
||||
};
|
||||
|
||||
console.log('Payload for update:', JSON.stringify(payload, null, 2));
|
||||
|
||||
try {
|
||||
await ShipmentsService.updateShipmentShipmentsShipmentIdPut(shipmentId, payload);
|
||||
setFeedbackMessage('Changes saved successfully.');
|
||||
setChangesMade(false);
|
||||
refreshShipments();
|
||||
} catch (error: any) {
|
||||
console.error('Update Shipment Error:', error);
|
||||
|
||||
if (error.response && error.response.data) {
|
||||
setFeedbackMessage(`Failed to save shipment. Validation errors: ${JSON.stringify(error.response.data)}`);
|
||||
} else {
|
||||
@ -286,7 +278,7 @@ const DewarDetails: React.FC<DewarDetailsProps> = ({
|
||||
value={localTrackingNumber}
|
||||
onChange={(e) => {
|
||||
setLocalTrackingNumber(e.target.value);
|
||||
setTrackingNumber(e.target.value); // Ensure parent state is updated if applicable
|
||||
setTrackingNumber(e.target.value);
|
||||
setChangesMade(true);
|
||||
}}
|
||||
variant="outlined"
|
||||
@ -299,20 +291,29 @@ const DewarDetails: React.FC<DewarDetailsProps> = ({
|
||||
) : (
|
||||
<Typography>No QR code available</Typography>
|
||||
)}
|
||||
<Button variant="contained" sx={{ marginTop: 1 }} onClick={() => { /** Add logic to generate QR Code */ }}>
|
||||
<Button variant="contained" sx={{ marginTop: 1 }} onClick={() => { /* Add logic to generate QR Code */ }}>
|
||||
Generate QR Code
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
<Typography variant="body1">Number of Pucks: {dewar.number_of_pucks}</Typography>
|
||||
<Unipuck pucks={dewar.number_of_pucks ?? 0} />
|
||||
<Box sx={{ marginTop: 2 }}>
|
||||
{/* Other inputs and elements */}
|
||||
|
||||
<Typography variant="body1">Number of Pucks: {dewar.number_of_pucks}</Typography>
|
||||
|
||||
{/* Here we integrate the Unipuck component with puck data */}
|
||||
{puckStatuses && <Unipuck pucks={puckStatuses.length} samples={puckStatuses} />}
|
||||
|
||||
<Typography variant="body1">Number of Samples: {dewar.number_of_samples}</Typography>
|
||||
{/* Rest of DewarDetails component */}
|
||||
</Box>
|
||||
<Typography variant="body1">Number of Samples: {dewar.number_of_samples}</Typography>
|
||||
<Typography variant="body1">Current Contact Person:</Typography>
|
||||
<Select
|
||||
value={selectedContactPerson}
|
||||
onChange={(e) => {
|
||||
const value = e.target.value;
|
||||
console.log('Contact Person Selected:', value);
|
||||
setSelectedContactPerson(value);
|
||||
setIsCreatingContactPerson(value === 'add');
|
||||
setChangesMade(true);
|
||||
@ -377,7 +378,6 @@ const DewarDetails: React.FC<DewarDetailsProps> = ({
|
||||
value={selectedReturnAddress}
|
||||
onChange={(e) => {
|
||||
const value = e.target.value;
|
||||
console.log('Return Address Selected:', value);
|
||||
setSelectedReturnAddress(value);
|
||||
setIsCreatingReturnAddress(value === 'add');
|
||||
setChangesMade(true);
|
||||
|
@ -1,13 +1,13 @@
|
||||
// app/components/Unipuck.tsx
|
||||
import React from 'react';
|
||||
import { Box } from '@mui/material';
|
||||
|
||||
interface UnipuckProps {
|
||||
pucks: number; // Number of pucks, assuming each puck follows the same layout
|
||||
pucks: number; // Number of pucks
|
||||
samples?: string[][]; // Array of sample arrays for each puck
|
||||
}
|
||||
|
||||
const Unipuck: React.FC<UnipuckProps> = ({ pucks }) => {
|
||||
const renderPuck = () => {
|
||||
const Unipuck: React.FC<UnipuckProps> = ({ pucks, samples }) => {
|
||||
const renderPuck = (sampleStatus: string[]) => {
|
||||
const puckSVG = (
|
||||
<svg width="100" height="100" viewBox="0 0 100 100">
|
||||
<circle cx="50" cy="50" r="45" stroke="black" strokeWidth="2" fill="none" />
|
||||
@ -15,13 +15,13 @@ const Unipuck: React.FC<UnipuckProps> = ({ pucks }) => {
|
||||
const angle = (index * (360 / 11)) * (Math.PI / 180);
|
||||
const x = 50 + 35 * Math.cos(angle);
|
||||
const y = 50 + 35 * Math.sin(angle);
|
||||
return <circle key={index} cx={x} cy={y} r="5" fill="black" />;
|
||||
return <circle key={index} cx={x} cy={y} r="5" fill={sampleStatus[index] === 'filled' ? 'black' : 'none'} stroke="black" />;
|
||||
})}
|
||||
{[...Array(5)].map((_, index) => {
|
||||
const angle = (index * (360 / 5) + 36) * (Math.PI / 180);
|
||||
const x = 50 + 15 * Math.cos(angle);
|
||||
const y = 50 + 15 * Math.sin(angle);
|
||||
return <circle key={index} cx={x} cy={y} r="5" fill="black" />;
|
||||
return <circle key={index + 11} cx={x} cy={y} r="5" fill={sampleStatus[index + 11] === 'filled' ? 'black' : 'none'} stroke="black" />;
|
||||
})}
|
||||
</svg>
|
||||
);
|
||||
@ -32,7 +32,7 @@ const Unipuck: React.FC<UnipuckProps> = ({ pucks }) => {
|
||||
<Box sx={{ display: 'flex', flexWrap: 'wrap', justifyContent: 'center', gap: 2 }}>
|
||||
{[...Array(pucks)].map((_, index) => (
|
||||
<Box key={index} sx={{ margin: 1 }}>
|
||||
{renderPuck()}
|
||||
{renderPuck(samples ? samples[index] : Array(16).fill('empty'))}
|
||||
</Box>
|
||||
))}
|
||||
</Box>
|
||||
|
Reference in New Issue
Block a user