Cleaning of the logistics frontend
This commit is contained in:
616
logistics/package-lock.json
generated
616
logistics/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -39,6 +39,6 @@
|
|||||||
"globals": "^15.11.0",
|
"globals": "^15.11.0",
|
||||||
"typescript": "~5.6.2",
|
"typescript": "~5.6.2",
|
||||||
"typescript-eslint": "^8.11.0",
|
"typescript-eslint": "^8.11.0",
|
||||||
"vite": "^5.4.11"
|
"vite": "^6.2.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,12 +75,12 @@ const BlurOverlay = styled.div`
|
|||||||
interface ScannerModalProps {
|
interface ScannerModalProps {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
onScan: (data: { text: string } | null) => void;
|
onScan: (data: string | null) => void;
|
||||||
slotQRCodes: string[]; // Required prop
|
slotQRCodes: string[]; // Required prop
|
||||||
}
|
}
|
||||||
|
|
||||||
const ScannerModal: React.FC<ScannerModalProps> = ({ open, onClose, onScan }) => {
|
const ScannerModal: React.FC<ScannerModalProps> = ({ open, onClose, onScan }) => {
|
||||||
const handleScan = (data: { text: string } | null) => {
|
const handleScan = (data: string | null) => {
|
||||||
if (data) {
|
if (data) {
|
||||||
onScan(data);
|
onScan(data);
|
||||||
}
|
}
|
||||||
@ -91,9 +91,10 @@ const ScannerModal: React.FC<ScannerModalProps> = ({ open, onClose, onScan }) =>
|
|||||||
};
|
};
|
||||||
|
|
||||||
const constraints = {
|
const constraints = {
|
||||||
video: { facingMode: { exact: "environment" } },
|
video: { facingMode: "environment" }, // Switch to "environment" for the rear-facing camera
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal open={open} onClose={onClose} title="Scan QR Code">
|
<Modal open={open} onClose={onClose} title="Scan QR Code">
|
||||||
<ScannerContainer>
|
<ScannerContainer>
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Box, Typography, Button, Alert } from '@mui/material';
|
import { Box, Typography, Alert } from '@mui/material';
|
||||||
import styled, { keyframes, css } from 'styled-components';
|
import styled, { keyframes, css } from 'styled-components';
|
||||||
import LocationOnIcon from '@mui/icons-material/LocationOn';
|
import LocationOnIcon from '@mui/icons-material/LocationOn';
|
||||||
import CountdownTimer from './CountdownTimer';
|
import CountdownTimer from './CountdownTimer';
|
||||||
|
|
||||||
export interface SlotData {
|
export interface SlotData {
|
||||||
id: string;
|
id: number;
|
||||||
qr_code: string;
|
qr_code: string;
|
||||||
label: string;
|
label: string;
|
||||||
qr_base: string;
|
qr_base: string;
|
||||||
@ -21,8 +21,6 @@ interface SlotProps {
|
|||||||
data: SlotData;
|
data: SlotData;
|
||||||
isSelected: boolean;
|
isSelected: boolean;
|
||||||
onSelect: (data: SlotData) => void;
|
onSelect: (data: SlotData) => void;
|
||||||
onRefillDewar: (dewar_unique_id?: string) => Promise<void>;
|
|
||||||
reloadSlots: () => Promise<void>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const pulse = keyframes`
|
const pulse = keyframes`
|
||||||
@ -110,8 +108,8 @@ const BottleIcon: React.FC<{ fillHeight: number }> = ({ fillHeight }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const Slot: React.FC<SlotProps> = ({ data, isSelected, onSelect, onRefillDewar, reloadSlots }) => {
|
const Slot: React.FC<SlotProps> = ({ data, isSelected, onSelect }) => {
|
||||||
const { id, qr_code, label, occupied, needs_refill, time_until_refill, dewar_unique_id, dewar_name, beamlineLocation } = data;
|
const { label, occupied, time_until_refill, dewar_unique_id, dewar_name, beamlineLocation } = data;
|
||||||
|
|
||||||
// Calculate fill height for the LN2 bottle level (only visual, no percentage displayed)
|
// Calculate fill height for the LN2 bottle level (only visual, no percentage displayed)
|
||||||
const calculateFillHeight = (timeUntilRefill?: number) => {
|
const calculateFillHeight = (timeUntilRefill?: number) => {
|
||||||
@ -128,13 +126,6 @@ const Slot: React.FC<SlotProps> = ({ data, isSelected, onSelect, onRefillDewar,
|
|||||||
const isSpecificBeamline = beamlineLocation === 'X10SA' || beamlineLocation === 'X06SA' || beamlineLocation === 'X06DA';
|
const isSpecificBeamline = beamlineLocation === 'X10SA' || beamlineLocation === 'X06SA' || beamlineLocation === 'X06DA';
|
||||||
const needsRefillSoon = occupied && (time_until_refill !== undefined && time_until_refill <= 10800);
|
const needsRefillSoon = occupied && (time_until_refill !== undefined && time_until_refill <= 10800);
|
||||||
|
|
||||||
// Refill handler
|
|
||||||
const handleRefill = async () => {
|
|
||||||
if (dewar_unique_id) {
|
|
||||||
await onRefillDewar(dewar_unique_id);
|
|
||||||
reloadSlots();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledSlot
|
<StyledSlot
|
||||||
@ -177,12 +168,6 @@ const Slot: React.FC<SlotProps> = ({ data, isSelected, onSelect, onRefillDewar,
|
|||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
{/* Refill Button Section */}
|
|
||||||
{needs_refill && (
|
|
||||||
<Button onClick={handleRefill} sx={{ mt: 1, color: 'white' }}>
|
|
||||||
Refill
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Countdown Timer */}
|
{/* Countdown Timer */}
|
||||||
{dewar_unique_id && time_until_refill !== undefined && time_until_refill !== -1 && (
|
{dewar_unique_id && time_until_refill !== undefined && time_until_refill !== -1 && (
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Box, Typography, Button } from '@mui/material';
|
import { Box, Typography } from '@mui/material';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import Slot, { SlotData } from '../components/Slots';
|
import Slot, { SlotData } from '../components/Slots';
|
||||||
|
|
||||||
@ -37,7 +37,7 @@ interface StorageProps {
|
|||||||
onRefillDewar: (slot: SlotData) => void;
|
onRefillDewar: (slot: SlotData) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Storage: React.FC<StorageProps> = ({ name, selectedSlot, slotsData, onSelectSlot, onRefillDewar }) => {
|
const Storage: React.FC<StorageProps> = ({ name, selectedSlot, slotsData, onSelectSlot }) => {
|
||||||
const handleSlotSelect = (slot: SlotData) => {
|
const handleSlotSelect = (slot: SlotData) => {
|
||||||
onSelectSlot(slot);
|
onSelectSlot(slot);
|
||||||
console.log('Selected slot:', slot);
|
console.log('Selected slot:', slot);
|
||||||
@ -53,7 +53,6 @@ const Storage: React.FC<StorageProps> = ({ name, selectedSlot, slotsData, onSele
|
|||||||
data={slot}
|
data={slot}
|
||||||
onSelect={handleSlotSelect}
|
onSelect={handleSlotSelect}
|
||||||
isSelected={selectedSlot === slot.qr_code}
|
isSelected={selectedSlot === slot.qr_code}
|
||||||
onRefillDewar={onRefillDewar}
|
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</StorageWrapper>
|
</StorageWrapper>
|
||||||
|
@ -3,7 +3,6 @@ import DataGrid from "react-data-grid";
|
|||||||
import { Box, Typography, Snackbar, Alert, CircularProgress } from "@mui/material";
|
import { Box, Typography, Snackbar, Alert, CircularProgress } from "@mui/material";
|
||||||
import { LogisticsService } from "../../../frontend/openapi";
|
import { LogisticsService } from "../../../frontend/openapi";
|
||||||
import "react-data-grid/lib/styles.css";
|
import "react-data-grid/lib/styles.css";
|
||||||
import dayjs from 'dayjs'; // Import dayjs library
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState } from "react";
|
||||||
import { Box, Tabs, Tab, Typography } from "@mui/material";
|
import { Box, Tabs, Tab, Typography } from "@mui/material";
|
||||||
import LogisticsTrackingTab from "./LogisticsTrackingTab";
|
import LogisticsTrackingTab from "./LogisticsTrackingTab";
|
||||||
import DewarStatusTab from "./DewarStatusTab"; // Adjust paths as necessary
|
import DewarStatusTab from "./DewarStatusTab"; // Adjust paths as necessary
|
||||||
@ -7,10 +7,11 @@ const LogisticsView: React.FC = () => {
|
|||||||
const [currentTab, setCurrentTab] = useState(0);
|
const [currentTab, setCurrentTab] = useState(0);
|
||||||
|
|
||||||
|
|
||||||
const handleTabChange = (event: React.SyntheticEvent, newValue: number) => {
|
const handleTabChange = (_: React.SyntheticEvent, newValue: number) => {
|
||||||
setCurrentTab(newValue);
|
setCurrentTab(newValue);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<Typography variant="h4" gutterBottom>
|
<Typography variant="h4" gutterBottom>
|
||||||
|
13
logistics/src/react-qr-reader.d.ts
vendored
13
logistics/src/react-qr-reader.d.ts
vendored
@ -1,13 +0,0 @@
|
|||||||
declare module 'react-qr-reader' {
|
|
||||||
import { Component } from 'react';
|
|
||||||
|
|
||||||
interface QrReaderProps {
|
|
||||||
delay?: number;
|
|
||||||
onError?: (error: any) => void;
|
|
||||||
onScan?: (data: string | null) => void;
|
|
||||||
style?: React.CSSProperties;
|
|
||||||
facingMode?: 'user' | 'environment';
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class QrReader extends Component<QrReaderProps> {}
|
|
||||||
}
|
|
28
logistics/src/types/react-qr-scanner.d.ts
vendored
Normal file
28
logistics/src/types/react-qr-scanner.d.ts
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
declare module 'react-qr-scanner' {
|
||||||
|
import { Component } from 'react';
|
||||||
|
|
||||||
|
interface QRScannerProps {
|
||||||
|
/** Delay between scans in milliseconds, or disable with `false` */
|
||||||
|
delay?: number | false;
|
||||||
|
/** Callback function triggered on scanning success */
|
||||||
|
onScan?: (data: string | null) => void;
|
||||||
|
/** Callback function triggered on scanning error */
|
||||||
|
onError?: (error: Error) => void;
|
||||||
|
/** Camera-facing mode ('user' for front, 'environment' for rear) */
|
||||||
|
facingMode?: 'user' | 'environment';
|
||||||
|
/** Enables legacy mode for scanning from files */
|
||||||
|
legacyMode?: boolean;
|
||||||
|
/** Toggles the visibility of the viewfinder UI */
|
||||||
|
showViewFinder?: boolean;
|
||||||
|
/** Custom styles for the scanner's container */
|
||||||
|
style?: React.CSSProperties;
|
||||||
|
/** Optional additional CSS class for the container */
|
||||||
|
className?: string;
|
||||||
|
/** Media constraints to customize video streams */
|
||||||
|
constraints?: MediaTrackConstraints | { video: MediaTrackConstraints }; // Allow nested video object
|
||||||
|
/** Optionally, invoke a specific camera device */
|
||||||
|
videoConstraints?: Record<string, unknown>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class QRScanner extends Component<QRScannerProps> {}
|
||||||
|
}
|
@ -4,8 +4,7 @@
|
|||||||
{ "path": "./tsconfig.app.json" },
|
{ "path": "./tsconfig.app.json" },
|
||||||
{ "path": "./tsconfig.node.json" }
|
{ "path": "./tsconfig.node.json" }
|
||||||
],
|
],
|
||||||
"include": [
|
"compilerOptions": {
|
||||||
"src",
|
"typeRoots": ["./node_modules/@types", "./src/@types"]
|
||||||
"react-qr-reader.d.ts"
|
}
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user