From d92fce497086abf85c42e64f5ee32d3796432599 Mon Sep 17 00:00:00 2001 From: GotthardG <51994228+GotthardG@users.noreply.github.com> Date: Mon, 4 Nov 2024 22:20:14 +0100 Subject: [PATCH] Add option to change the dewar status --- backend/test.db | Bin 77824 -> 77824 bytes frontend/src/components/DewarStepper.tsx | 137 ++++++++++++-------- frontend/src/components/ShipmentDetails.tsx | 2 +- frontend/src/components/statusUtils.ts | 24 ++++ 4 files changed, 110 insertions(+), 53 deletions(-) create mode 100644 frontend/src/components/statusUtils.ts diff --git a/backend/test.db b/backend/test.db index c14eef26300ded29c36fffc29ac5659779620af2..98fd0b75e9e74d70de719d8afc8fbc453294a699 100644 GIT binary patch delta 156 zcmZp8z|!!5Wr8$g>_i!7#@LMs3)c(s1v0Smb};ZS;Sb^c#J8NcW3!?{881f$E3d2~ zuc6}P$bHgMi7Ax|Y57G8!5Nta1(|v2Mg~SEx`u|j1}2lM_UW?6GV{tR%NkB*-mfeZ ml!`~O^?pefzCR3M6DI~uUcN7sg@J(~V&cS*%^~~O6aWB(^DzMc delta 134 zcmZp8z|!!5Wr8$g^h6nF#^{X+3)c%WFfg$41v2n2;Sb^a!?&C-aI>O = ({ fill }) => ( @@ -17,21 +15,15 @@ const BottleIcon: React.FC<{ fill: string }> = ({ fill }) => ( ); -// Define types for icons mapping. const ICONS: { [key: number]: React.ReactElement } = { 0: , - 1: , // 'Ready for Shipping' -> Active - 2: , // 'Not Arrived' - 3: , // 'Returned' - 4: , // 'Shipped' - Active - 5: , // 'Delayed' + 1: , + 2: , + 3: , + 4: , + 5: , }; -// Define StepIconContainer to accept correct props and handle typing better. -interface StepIconContainerProps extends React.HTMLAttributes { - color: string; -} - const StepIconContainer: React.FC = ({ color, children, ...rest }) => (
{children} @@ -41,26 +33,83 @@ const StepIconContainer: React.FC = ({ color, children, type StepIconComponentProps = { icon: number; dewar: Dewar; + isSelected: boolean; } & StepIconProps; -const StepIconComponent = ({ icon, dewar, ...props }: StepIconComponentProps) => { - const { iconIndex, color} = getIconProperties(icon, dewar); +const StepIconComponent = ({ icon, dewar, isSelected, ...props }: StepIconComponentProps) => { + const [anchorEl, setAnchorEl] = useState(null); + const handleIconEnter = (event: React.MouseEvent) => { + if (isSelected && icon === 0) { + setAnchorEl(event.currentTarget); + } + }; + const handleIconLeave = () => { + setAnchorEl(null); + }; - // Adjust icon color for the bottle especially since it's an SVG element + const handleStatusChange = async (status: DewarStatus) => { + try { + const today = new Date().toISOString().split('T')[0]; + const payload = { + dewar_id: dewar.id, + dewar_name: dewar.dewar_name, + tracking_number: dewar.tracking_number, + number_of_pucks: dewar.number_of_pucks, + number_of_samples: dewar.number_of_samples, + status: status, + ready_date: status === 'Ready for Shipping' ? today : dewar.ready_date, + shipping_date: dewar.shipping_date, + arrival_date: dewar.arrival_date, + returning_date: dewar.returning_date, + qrcode: dewar.qrcode, + return_address_id: dewar.return_address_id, + contact_person_id: dewar.contact_person_id, + }; + + await DewarsService.updateDewarDewarsDewarIdPut(dewar.id || '', payload); + setAnchorEl(null); + } catch (error) { + console.error('Failed to update dewar status:', error); + alert('Failed to update dewar status. Please try again.'); + } + }; + + const { iconIndex, color } = getIconProperties(icon, dewar); const IconComponent = ICONS[iconIndex]; const iconProps = iconIndex === 0 ? { fill: color } : {}; return ( - - {IconComponent - ? React.cloneElement(IconComponent, iconProps) - : Invalid icon - } - +
+ + {IconComponent + ? React.cloneElement(IconComponent, iconProps) + : Invalid icon + } + + + setAnchorEl(anchorEl), + onMouseLeave: handleIconLeave, + }} + > + {['Ready for Shipping'].map((status) => ( + handleStatusChange(status as DewarStatus)}> + {status} + + ))} + +
); }; -// Extracted function to determine icon properties const getIconProperties = (icon: number, dewar: Dewar) => { const status = dewar.status as DewarStatus; const iconIndex = status === 'Delayed' && icon === 1 ? 5 : icon; @@ -69,40 +118,24 @@ const getIconProperties = (icon: number, dewar: Dewar) => { return { iconIndex, color, fill }; }; -const STATUS_TO_STEP: Record = { - 'In Preparation': 0, - 'Ready for Shipping': 1, - 'Shipped': 1, - 'Delayed': 1, - 'Not Arrived': 2, - 'Arrived': 2, - 'Returned': 3 -}; - -const getStatusStepIndex = (status: DewarStatus): number => STATUS_TO_STEP[status]; - -const determineIconColor = (iconIndex: number, status: DewarStatus): string => { - const statusIndex = getStatusStepIndex(status); - if (status === 'Delayed' && iconIndex === 1) { - return 'orange'; - } - return iconIndex <= statusIndex ? (iconIndex === statusIndex ? (status === 'Shipped' ? 'green' : 'blue') : 'green') : 'grey'; -}; - -// Define your steps const steps = ['In-House', 'Transit', 'At SLS', 'Returned']; -const CustomStepper = ({ dewar }: { dewar: Dewar }) => { - // Determine the current active step +type CustomStepperProps = { + dewar: Dewar; + selectedDewarId: string | null; +} + +const CustomStepper = ({ dewar, selectedDewarId }: CustomStepperProps) => { const activeStep = getStatusStepIndex(dewar.status as DewarStatus); + const isSelected = dewar.id === selectedDewarId; return ( -
+
{steps.map((label, index) => ( } + StepIconComponent={(stepProps) => } > {label} diff --git a/frontend/src/components/ShipmentDetails.tsx b/frontend/src/components/ShipmentDetails.tsx index 7e56119..b68f0c5 100644 --- a/frontend/src/components/ShipmentDetails.tsx +++ b/frontend/src/components/ShipmentDetails.tsx @@ -311,7 +311,7 @@ const ShipmentDetails: React.FC = ({ flexDirection: 'row', justifyContent: 'space-between' }}> - + diff --git a/frontend/src/components/statusUtils.ts b/frontend/src/components/statusUtils.ts new file mode 100644 index 0000000..c62308f --- /dev/null +++ b/frontend/src/components/statusUtils.ts @@ -0,0 +1,24 @@ +// statusUtils.ts +// Utility functions to handle dewar statuses and icon colors + +export type DewarStatus = 'In Preparation' | 'Ready for Shipping' | 'Shipped' | 'Not Arrived' | 'Arrived' | 'Returned' | 'Delayed'; + +export const STATUS_TO_STEP: Record = { + 'In Preparation': 0, + 'Ready for Shipping': 1, + 'Shipped': 1, + 'Delayed': 1, + 'Not Arrived': 2, + 'Arrived': 2, + 'Returned': 3 +}; + +export const getStatusStepIndex = (status: DewarStatus): number => STATUS_TO_STEP[status]; + +export const determineIconColor = (iconIndex: number, status: DewarStatus): string => { + const statusIndex = getStatusStepIndex(status); + if (status === 'Delayed' && iconIndex === 1) { + return 'orange'; + } + return iconIndex <= statusIndex ? (iconIndex === statusIndex ? (status === 'Shipped' ? 'green' : 'blue') : 'green') : 'grey'; +}; \ No newline at end of file