added pucks and samples

This commit is contained in:
GotthardG
2024-11-04 11:34:14 +01:00
parent a9b8925be8
commit 23e7ebb819
17 changed files with 378 additions and 112 deletions

View File

@ -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);

View File

@ -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>