Skip to content

Commit

Permalink
Add hazmat page (#9)
Browse files Browse the repository at this point in the history
  • Loading branch information
r00tat authored Jul 27, 2023
1 parent ebd7bde commit 006ee92
Show file tree
Hide file tree
Showing 19 changed files with 410 additions and 11 deletions.
1 change: 1 addition & 0 deletions config/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
service_account.json
service_account*.json
45 changes: 41 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
"dependencies": {
"@emotion/react": "^11.10.6",
"@emotion/styled": "^11.10.6",
"@mdi/js": "^7.2.96",
"@mdi/react": "^1.6.1",
"@mui/icons-material": "^5.11.16",
"@mui/material": "^5.12.0",
"@mui/x-data-grid": "^6.1.0",
Expand All @@ -33,10 +35,11 @@
"firebase-admin": "^11.6.0",
"firebaseui": "^6.0.0",
"geofire-common": "^6.0.0",
"googleapis": "^117.0.0",
"googleapis": "^122.0.0",
"leaflet": "^1.7.1",
"leaflet-rotatedmarker": "^0.2.0",
"leaflet.markercluster": "^1.5.3",
"lodash.debounce": "^4.0.8",
"moment": "^2.29.1",
"moment-timezone": "^0.5.34",
"next": "^13.3.0",
Expand All @@ -50,6 +53,7 @@
"devDependencies": {
"@types/circle-to-polygon": "^2.2.0",
"@types/leaflet": "^1.7.8",
"@types/lodash.debounce": "^4.0.7",
"@types/node": "^18.15.11",
"@types/react": "^18.0.35",
"eslint": "^8.38.0",
Expand Down
7 changes: 7 additions & 0 deletions src/common/hazmat.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export interface HazmatMaterial {
unNumber: string;
name: string;
resistanceTemperature: number;
resistanceTime?: string;
damage?: string;
}
128 changes: 128 additions & 0 deletions src/components/pages/Schadstoff.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import Box from '@mui/material/Box';
import Button from '@mui/material/Button';
import Card from '@mui/material/Card';
import CardActions from '@mui/material/CardActions';
import CardContent from '@mui/material/CardContent';
import TextField from '@mui/material/TextField';
import Typography from '@mui/material/Typography';
import { useCallback, useState } from 'react';
import useHazmatDb from '../../hooks/useHazmatDb';

export default function SchadstoffPage() {
const [unNumber, setUnNumber] = useState('');
const [materialName, setMaterialName] = useState('');
const hazmatRecords = useHazmatDb(unNumber, materialName);

const openEricards = useCallback((num: string, nam: string) => {
let form = document.createElement('form');
form.method = 'POST';
form.action = 'https://www.ericards.net/psp/ericards.psp_search_result';
form.target = '_blank';

const fields = {
unnumber: num,
substance: nam,
operators: 'OR',
};

Object.entries(fields).forEach(([key, value]) => {
const element = document.createElement('input');
element.name = key;
element.value = value;
form.appendChild(element);
});

document.body.appendChild(form);
form.submit();
form.parentNode?.removeChild(form);
}, []);

return (
<>
<Box sx={{ p: 2, m: 2 }}>
<Typography variant="h3" gutterBottom>
Schadstoff
</Typography>

<TextField
autoFocus
margin="dense"
id="unNumber"
label="Stoffnummer (UN Nummer)"
type="text"
fullWidth
variant="standard"
inputProps={{ tabIndex: 1 }}
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
setUnNumber(event.target.value);
}}
value={unNumber}
/>
<TextField
margin="dense"
id="materialName"
label="Stoff Name"
type="text"
fullWidth
variant="standard"
inputProps={{ tabIndex: 2 }}
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
setMaterialName(event.target.value);
}}
value={materialName}
/>
<Button
variant="contained"
color="primary"
onClick={() => {
openEricards(unNumber, materialName);
}}
>
Suche in den Ericards nach aktuellen Eingaben
</Button>
{unNumber === '' && materialName === '' && (
<Typography variant="body1">
Gib die Stoffnummer oder den Stoffnamen ein, um Informationen zu dem
Stoff zu erhalten.
</Typography>
)}
{(unNumber !== '' || materialName !== '') && (
<>
{/* <Typography variant="body1">
Stoffe gefunden:
{JSON.stringify(hazmatRecords)}
</Typography> */}
{hazmatRecords.map((r) => (
<Card key={r.unNumber} variant="outlined">
<CardContent>
<Typography color="text.secondary">{r.unNumber}</Typography>
<Typography>{r.name}</Typography>
<Typography variant="caption">
Schutzanzug Parameter
</Typography>
<Typography variant="body2">
Temperatur Resistenz: Klasse {r.resistanceTemperature}
<br />
Zeitliche Resistenz: {r.resistanceTime}
<br />
Beschädigung: {r.damage}
</Typography>
</CardContent>
<CardActions>
<Button
size="small"
onClick={() => {
openEricards(r.unNumber, '');
}}
>
Ericards
</Button>
</CardActions>
</Card>
))}
</>
)}
</Box>
</>
);
}
10 changes: 10 additions & 0 deletions src/components/site/AppDrawer.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { mdiBiohazard } from '@mdi/js';
import Icon from '@mdi/react';
import ApiIcon from '@mui/icons-material/Api';
import DirectionsCarIcon from '@mui/icons-material/DirectionsCar';
import InfoIcon from '@mui/icons-material/Info';
Expand Down Expand Up @@ -93,6 +95,14 @@ export default function AppDrawer({
<ListItemText primary="Einsätze" />
</ListItem>
</Link>
<Link href="/schadstoff" passHref>
<ListItem button key="schadstoff">
<ListItemIcon>
<Icon path={mdiBiohazard} size={1} />
</ListItemIcon>
<ListItemText primary="Schadstoff" />
</ListItem>
</Link>
<Link href="/print" passHref>
<ListItem button key="print">
<ListItemIcon>
Expand Down
22 changes: 22 additions & 0 deletions src/hooks/useDebounce.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import debounce from 'lodash.debounce';
import { useEffect, useMemo, useRef } from 'react';

const useDebounce = (callback: () => void, time = 500) => {
const ref = useRef<() => void>();

useEffect(() => {
ref.current = callback;
}, [callback]);

const debouncedCallback = useMemo(() => {
const func = () => {
ref.current?.();
};

return debounce(func, time);
}, [time]);

return debouncedCallback;
};

export default useDebounce;
46 changes: 46 additions & 0 deletions src/hooks/useHazmatDb.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { useCallback, useEffect, useState } from 'react';
import { HazmatMaterial } from '../common/hazmat';
import useFirebaseLogin from './useFirebaseLogin';
import useDebounce from './useDebounce';

export default function useHazmatDb(unNumber?: string, name?: string) {
const [hazmatRecords, setHazmatRecords] = useState<HazmatMaterial[]>([]);
const { user, isSignedIn } = useFirebaseLogin();

const fetchHazmat = useCallback(
async (unNumberArg?: string, unName?: string) => {
console.info(`searching for hazmat ${unNumberArg} ${unName}`);
if (!(isSignedIn && user && (unNumberArg || unName))) return;
const token = await user?.getIdToken();
const response: HazmatMaterial[] = await (
await fetch(
'/api/hazmat?' +
new URLSearchParams({
unnumber: '' + unNumberArg,
name: '' + unName,
}),
{
method: 'GET',
headers: {
Authorization: `Bearer ${token}`,
},
}
)
).json();
setHazmatRecords(response);
},
[isSignedIn, user]
);

const fetchDb = useCallback(() => {
fetchHazmat(unNumber, name);
}, [fetchHazmat, name, unNumber]);

const debouncedFetch = useDebounce(fetchDb);

useEffect(() => {
debouncedFetch();
}, [debouncedFetch, unNumber, name]);

return hazmatRecords;
}
2 changes: 1 addition & 1 deletion src/pages/api/geojson.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import exportGeoJson, {
GeoFilterProperties,
GeoJsonFeatureColleaction,
} from '../../server/geojson';
import tokenRequired from '../../server/tokenRequired';
import tokenRequired from '../../server/auth/tokenRequired';

export default async function handler(
req: NextApiRequest,
Expand Down
Loading

0 comments on commit 006ee92

Please sign in to comment.