Merge branch 'main' of https://github.com/VAR-Virtual-Air-Rescue/var-monorepo
This commit is contained in:
@@ -42,6 +42,16 @@ export const FMS_STATUS_COLORS: { [key: string]: string } = {
|
|||||||
"7": "rgb(140,10,10)",
|
"7": "rgb(140,10,10)",
|
||||||
"8": "rgb(186,105,0)",
|
"8": "rgb(186,105,0)",
|
||||||
"9": "rgb(10,134,25)",
|
"9": "rgb(10,134,25)",
|
||||||
|
E: "rgb(186,105,0)",
|
||||||
|
C: "rgb(186,105,0)",
|
||||||
|
F: "rgb(186,105,0)",
|
||||||
|
J: "rgb(186,105,0)",
|
||||||
|
L: "rgb(186,105,0)",
|
||||||
|
c: "rgb(186,105,0)",
|
||||||
|
d: "rgb(186,105,0)",
|
||||||
|
h: "rgb(186,105,0)",
|
||||||
|
o: "rgb(186,105,0)",
|
||||||
|
u: "rgb(186,105,0)",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const FMS_STATUS_TEXT_COLORS: { [key: string]: string } = {
|
export const FMS_STATUS_TEXT_COLORS: { [key: string]: string } = {
|
||||||
@@ -55,7 +65,17 @@ export const FMS_STATUS_TEXT_COLORS: { [key: string]: string } = {
|
|||||||
"7": "rgb(243,27,25)",
|
"7": "rgb(243,27,25)",
|
||||||
"8": "rgb(255,143,0)",
|
"8": "rgb(255,143,0)",
|
||||||
"9": "rgb(9,212,33)",
|
"9": "rgb(9,212,33)",
|
||||||
N: "rgb(153,153,153)",
|
N: "rgb(9,212,33)",
|
||||||
|
E: "rgb(255,143,0)",
|
||||||
|
C: "rgb(255,143,0)",
|
||||||
|
F: "rgb(255,143,0)",
|
||||||
|
J: "rgb(255,143,0)",
|
||||||
|
L: "rgb(255,143,0)",
|
||||||
|
c: "rgb(255,143,0)",
|
||||||
|
d: "rgb(255,143,0)",
|
||||||
|
h: "rgb(255,143,0)",
|
||||||
|
o: "rgb(255,143,0)",
|
||||||
|
u: "rgb(255,143,0)",
|
||||||
};
|
};
|
||||||
|
|
||||||
const AircraftPopupContent = ({
|
const AircraftPopupContent = ({
|
||||||
|
|||||||
@@ -2,8 +2,16 @@
|
|||||||
import { OSMWay } from "@repo/db";
|
import { OSMWay } from "@repo/db";
|
||||||
import { useMapStore } from "_store/mapStore";
|
import { useMapStore } from "_store/mapStore";
|
||||||
import { usePannelStore } from "_store/pannelStore";
|
import { usePannelStore } from "_store/pannelStore";
|
||||||
import { MapPinned, Search } from "lucide-react";
|
import {
|
||||||
import { useEffect } from "react";
|
MapPin,
|
||||||
|
MapPinned,
|
||||||
|
Radius,
|
||||||
|
Ruler,
|
||||||
|
Search,
|
||||||
|
RulerDimensionLine,
|
||||||
|
Scan,
|
||||||
|
} from "lucide-react";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
import { Popup, useMap } from "react-leaflet";
|
import { Popup, useMap } from "react-leaflet";
|
||||||
|
|
||||||
export const ContextMenu = () => {
|
export const ContextMenu = () => {
|
||||||
@@ -11,11 +19,19 @@ export const ContextMenu = () => {
|
|||||||
const { contextMenu, setContextMenu, setSearchElements, setSearchPopup } =
|
const { contextMenu, setContextMenu, setSearchElements, setSearchPopup } =
|
||||||
useMapStore();
|
useMapStore();
|
||||||
const { setMissionFormValues, setOpen } = usePannelStore((state) => state);
|
const { setMissionFormValues, setOpen } = usePannelStore((state) => state);
|
||||||
|
const [showRulerOptions, setShowRulerOptions] = useState(false);
|
||||||
|
const [rulerHover, setRulerHover] = useState(false);
|
||||||
|
const [rulerOptionsHover, setRulerOptionsHover] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setShowRulerOptions(rulerHover || rulerOptionsHover);
|
||||||
|
}, [rulerHover, rulerOptionsHover]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleContextMenu = (e: any) => {
|
const handleContextMenu = (e: any) => {
|
||||||
setContextMenu({ lat: e.latlng.lat, lng: e.latlng.lng });
|
setContextMenu({ lat: e.latlng.lat, lng: e.latlng.lng });
|
||||||
};
|
};
|
||||||
const handleClick = (e: any) => {
|
const handleClick = () => {
|
||||||
setContextMenu(null);
|
setContextMenu(null);
|
||||||
setSearchPopup(null);
|
setSearchPopup(null);
|
||||||
};
|
};
|
||||||
@@ -27,7 +43,7 @@ export const ContextMenu = () => {
|
|||||||
map.off("contextmenu", handleContextMenu);
|
map.off("contextmenu", handleContextMenu);
|
||||||
map.off("click", handleClick);
|
map.off("click", handleClick);
|
||||||
};
|
};
|
||||||
}, [contextMenu]);
|
}, [map, contextMenu, setContextMenu, setSearchPopup]);
|
||||||
|
|
||||||
if (!contextMenu) return null;
|
if (!contextMenu) return null;
|
||||||
|
|
||||||
@@ -76,86 +92,242 @@ export const ContextMenu = () => {
|
|||||||
autoPan={false}
|
autoPan={false}
|
||||||
>
|
>
|
||||||
{/* // TODO: maske: */}
|
{/* // TODO: maske: */}
|
||||||
<div className="absolute transform -translate-y-1/2 z-1000 opacity-100 pointer-events-auto p-3">
|
<div
|
||||||
<button
|
className="absolute opacity-100 pointer-events-none p-3 flex items-center justify-center"
|
||||||
className="btn btn-sm rounded-full bg-rescuetrack aspect-square"
|
style={{ left: "-13px", top: "-13px" }}
|
||||||
onClick={async () => {
|
>
|
||||||
const address = await fetch(
|
<div className="relative w-38 h-38 flex items-center justify-center -translate-x-1/2 -translate-y-1/2 pointer-events-none">
|
||||||
`https://nominatim.openstreetmap.org/reverse?lat=${contextMenu.lat}&lon=${contextMenu.lng}&format=json`,
|
{/* Top Button */}
|
||||||
);
|
<button
|
||||||
const data = (await address.json()) as {
|
className="btn btn-circle bg-rescuetrack w-10 h-10 absolute left-1/2 top-0 pointer-events-auto opacity-80 tooltip tooltip-top tooltip-accent"
|
||||||
address: {
|
data-tip="Nächstes Element übernehmen"
|
||||||
ISO3166_2_lvl4: string;
|
style={{ transform: "translateX(-50%)" }}
|
||||||
country: string;
|
onClick={async () => {
|
||||||
country_code: string;
|
const address = await fetch(
|
||||||
county: string;
|
`https://nominatim.openstreetmap.org/reverse?lat=${contextMenu.lat}&lon=${contextMenu.lng}&format=json`,
|
||||||
house_number: string;
|
);
|
||||||
municipality: string;
|
const data = (await address.json()) as {
|
||||||
postcode: string;
|
address: {
|
||||||
road: string;
|
ISO3166_2_lvl4: string;
|
||||||
state: string;
|
country: string;
|
||||||
city: string;
|
country_code: string;
|
||||||
town: string;
|
county: string;
|
||||||
|
house_number: string;
|
||||||
|
municipality: string;
|
||||||
|
postcode: string;
|
||||||
|
road: string;
|
||||||
|
state: string;
|
||||||
|
city: string;
|
||||||
|
town: string;
|
||||||
|
};
|
||||||
|
display_name: string;
|
||||||
|
importance: number;
|
||||||
|
lat: string;
|
||||||
|
licence: string;
|
||||||
|
lon: string;
|
||||||
|
name: string;
|
||||||
|
osm_id: number;
|
||||||
|
osm_type: string;
|
||||||
|
place_id: number;
|
||||||
|
place_rank: number;
|
||||||
|
type: string;
|
||||||
};
|
};
|
||||||
display_name: string;
|
const objects = await addOSMobjects();
|
||||||
importance: number;
|
const exactAddress = objects.find((object) => {
|
||||||
lat: string;
|
return (
|
||||||
licence: string;
|
object.tags["addr:street"] == data.address.road &&
|
||||||
lon: string;
|
object.tags["addr:housenumber"]?.includes(
|
||||||
name: string;
|
data.address.house_number,
|
||||||
osm_id: number;
|
)
|
||||||
osm_type: string;
|
);
|
||||||
place_id: number;
|
});
|
||||||
place_rank: number;
|
const closestToContext = objects.reduce((prev, curr) => {
|
||||||
type: string;
|
const prevLat = prev.nodes?.[0]?.lat ?? 0;
|
||||||
};
|
const prevLon = prev.nodes?.[0]?.lon ?? 0;
|
||||||
const objects = await addOSMobjects();
|
const currLat = curr.nodes?.[0]?.lat ?? 0;
|
||||||
const exactAddress = objects.find((object) => {
|
const currLon = curr.nodes?.[0]?.lon ?? 0;
|
||||||
return (
|
const prevDistance = Math.sqrt(
|
||||||
object.tags["addr:street"] == data.address.road &&
|
Math.pow(prevLat - contextMenu.lat, 2) +
|
||||||
object.tags["addr:housenumber"]?.includes(
|
Math.pow(prevLon - contextMenu.lng, 2),
|
||||||
data.address.house_number,
|
);
|
||||||
)
|
const currDistance = Math.sqrt(
|
||||||
);
|
Math.pow(currLat - contextMenu.lat, 2) +
|
||||||
});
|
Math.pow(currLon - contextMenu.lng, 2),
|
||||||
const closestToContext = objects.reduce((prev, curr) => {
|
);
|
||||||
const prevLat = prev.nodes?.[0]?.lat ?? 0;
|
return prevDistance < currDistance ? prev : curr;
|
||||||
const prevLon = prev.nodes?.[0]?.lon ?? 0;
|
});
|
||||||
const currLat = curr.nodes?.[0]?.lat ?? 0;
|
|
||||||
const currLon = curr.nodes?.[0]?.lon ?? 0;
|
|
||||||
const prevDistance = Math.sqrt(
|
|
||||||
Math.pow(prevLat - contextMenu.lat, 2) +
|
|
||||||
Math.pow(prevLon - contextMenu.lng, 2),
|
|
||||||
);
|
|
||||||
const currDistance = Math.sqrt(
|
|
||||||
Math.pow(currLat - contextMenu.lat, 2) +
|
|
||||||
Math.pow(currLon - contextMenu.lng, 2),
|
|
||||||
);
|
|
||||||
return prevDistance < currDistance ? prev : curr;
|
|
||||||
});
|
|
||||||
|
|
||||||
setOpen(true);
|
setOpen(true);
|
||||||
setMissionFormValues({
|
setMissionFormValues({
|
||||||
addressLat: contextMenu.lat,
|
addressLat: contextMenu.lat,
|
||||||
addressLng: contextMenu.lng,
|
addressLng: contextMenu.lng,
|
||||||
addressCity: data.address.city || data.address.town,
|
addressCity: data.address.city || data.address.town,
|
||||||
addressStreet: `${data.address.road}, ${data.address.house_number || "keine HN"}`,
|
addressStreet: `${data.address.road}, ${data.address.house_number || "keine HN"}`,
|
||||||
addressZip: data.address.postcode,
|
addressZip: data.address.postcode,
|
||||||
state: "draft",
|
state: "draft",
|
||||||
addressOSMways: [(exactAddress || closestToContext) as any],
|
addressOSMways: [(exactAddress || closestToContext) as any],
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<MapPinned size={20} />
|
<MapPinned size={20} />
|
||||||
</button>
|
</button>
|
||||||
<button
|
{/* Left Button */}
|
||||||
className="btn btn-sm rounded-full bg-rescuetrack aspect-square"
|
<button
|
||||||
onClick={async () => {
|
className="btn btn-circle bg-rescuetrack w-10 h-10 absolute top-1/2 left-0 pointer-events-auto opacity-80"
|
||||||
addOSMobjects();
|
style={{ transform: "translateY(-50%)" }}
|
||||||
}}
|
onMouseEnter={() => setRulerHover(true)}
|
||||||
>
|
onMouseLeave={() => setRulerHover(false)}
|
||||||
<Search size={20} />
|
>
|
||||||
</button>
|
<Ruler size={20} />
|
||||||
|
</button>
|
||||||
|
{/* Bottom Button */}
|
||||||
|
<button
|
||||||
|
className="btn btn-circle bg-rescuetrack w-10 h-10 absolute left-1/2 bottom-0 pointer-events-auto opacity-80 tooltip tooltip-bottom tooltip-accent"
|
||||||
|
data-tip="Koordinaten kopieren"
|
||||||
|
style={{ transform: "translateX(-50%)" }}
|
||||||
|
onClick={async () => {
|
||||||
|
const address = await fetch(
|
||||||
|
`https://nominatim.openstreetmap.org/reverse?lat=${contextMenu.lat}&lon=${contextMenu.lng}&format=json`,
|
||||||
|
);
|
||||||
|
const data = (await address.json()) as {
|
||||||
|
address: {
|
||||||
|
ISO3166_2_lvl4: string;
|
||||||
|
country: string;
|
||||||
|
country_code: string;
|
||||||
|
county: string;
|
||||||
|
house_number: string;
|
||||||
|
municipality: string;
|
||||||
|
postcode: string;
|
||||||
|
road: string;
|
||||||
|
state: string;
|
||||||
|
city: string;
|
||||||
|
town: string;
|
||||||
|
};
|
||||||
|
display_name: string;
|
||||||
|
importance: number;
|
||||||
|
lat: string;
|
||||||
|
licence: string;
|
||||||
|
lon: string;
|
||||||
|
name: string;
|
||||||
|
osm_id: number;
|
||||||
|
osm_type: string;
|
||||||
|
place_id: number;
|
||||||
|
place_rank: number;
|
||||||
|
type: string;
|
||||||
|
};
|
||||||
|
const objects = await addOSMobjects();
|
||||||
|
const exactAddress = objects.find((object) => {
|
||||||
|
return (
|
||||||
|
object.tags["addr:street"] == data.address.road &&
|
||||||
|
object.tags["addr:housenumber"]?.includes(
|
||||||
|
data.address.house_number,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
const closestToContext = objects.reduce((prev, curr) => {
|
||||||
|
const prevLat = prev.nodes?.[0]?.lat ?? 0;
|
||||||
|
const prevLon = prev.nodes?.[0]?.lon ?? 0;
|
||||||
|
const currLat = curr.nodes?.[0]?.lat ?? 0;
|
||||||
|
const currLon = curr.nodes?.[0]?.lon ?? 0;
|
||||||
|
const prevDistance = Math.sqrt(
|
||||||
|
Math.pow(prevLat - contextMenu.lat, 2) +
|
||||||
|
Math.pow(prevLon - contextMenu.lng, 2),
|
||||||
|
);
|
||||||
|
const currDistance = Math.sqrt(
|
||||||
|
Math.pow(currLat - contextMenu.lat, 2) +
|
||||||
|
Math.pow(currLon - contextMenu.lng, 2),
|
||||||
|
);
|
||||||
|
return prevDistance < currDistance ? prev : curr;
|
||||||
|
});
|
||||||
|
|
||||||
|
setOpen(true);
|
||||||
|
setMissionFormValues({
|
||||||
|
addressLat: contextMenu.lat,
|
||||||
|
addressLng: contextMenu.lng,
|
||||||
|
addressCity: data.address.city || data.address.town,
|
||||||
|
addressStreet: `${data.address.road}, ${data.address.house_number || "keine HN"}`,
|
||||||
|
addressZip: data.address.postcode,
|
||||||
|
state: "draft",
|
||||||
|
addressOSMways: [(exactAddress || closestToContext) as any],
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<MapPin size={20} />
|
||||||
|
</button>
|
||||||
|
{/* Right Button (original Search button) */}
|
||||||
|
<button
|
||||||
|
className="btn btn-circle bg-rescuetrack w-10 h-10 absolute top-1/2 right-0 pointer-events-auto opacity-80 tooltip tooltip-right tooltip-accent"
|
||||||
|
data-tip="Gebäude suchen"
|
||||||
|
style={{ transform: "translateY(-50%)" }}
|
||||||
|
onClick={async () => {
|
||||||
|
addOSMobjects();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Search size={20} />
|
||||||
|
</button>
|
||||||
|
{/* Ruler Options - shown when Ruler button is hovered or options are hovered */}
|
||||||
|
{showRulerOptions && (
|
||||||
|
<div
|
||||||
|
className="absolute flex flex-col items-center pointer-events-auto"
|
||||||
|
style={{
|
||||||
|
left: "-100px", // position to the right of the left button
|
||||||
|
top: "50%",
|
||||||
|
transform: "translateY(-50%)",
|
||||||
|
zIndex: 10,
|
||||||
|
width: "120px", // Make the hover area wider
|
||||||
|
height: "200px", // Make the hover area taller
|
||||||
|
padding: "20px 0", // Add vertical padding
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "center",
|
||||||
|
pointerEvents: "auto",
|
||||||
|
}}
|
||||||
|
onMouseEnter={() => setRulerOptionsHover(true)}
|
||||||
|
onMouseLeave={() => setRulerOptionsHover(false)}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
width: "100%",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
className="btn btn-circle bg-rescuetrack w-10 h-10 mb-2 opacity-80 tooltip tooltip-left tooltip-accent"
|
||||||
|
data-tip="Strecke Messen"
|
||||||
|
style={{
|
||||||
|
transform: "translateX(100%)",
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
/* ... */
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<RulerDimensionLine size={20} />
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="btn btn-circle bg-rescuetrack w-10 h-10 mb-2 opacity-80 tooltip tooltip-left tooltip-accent"
|
||||||
|
data-tip="Radius Messen"
|
||||||
|
onClick={() => {
|
||||||
|
/* ... */
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Radius size={20} />
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="btn btn-circle bg-rescuetrack w-10 h-10 opacity-80 tooltip tooltip-left tooltip-accent"
|
||||||
|
data-tip="Fläche Messen"
|
||||||
|
style={{
|
||||||
|
transform: "translateX(100%)",
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
/* ... */
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Scan size={20} />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Popup>
|
</Popup>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -161,9 +161,21 @@ const FMSStatusSelector = ({
|
|||||||
!dispatcherConnected && "cursor-not-allowed",
|
!dispatcherConnected && "cursor-not-allowed",
|
||||||
)}
|
)}
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: "var(--color-base-200)",
|
backgroundColor:
|
||||||
color: "gray",
|
hoveredStatus === status
|
||||||
|
? FMS_STATUS_COLORS[6]
|
||||||
|
: aircraft.fmsStatus === status
|
||||||
|
? FMS_STATUS_COLORS[status]
|
||||||
|
: "var(--color-base-200)",
|
||||||
|
color:
|
||||||
|
aircraft.fmsStatus === status
|
||||||
|
? "white"
|
||||||
|
: hoveredStatus === status
|
||||||
|
? "white"
|
||||||
|
: "gray",
|
||||||
}}
|
}}
|
||||||
|
onMouseEnter={() => setHoveredStatus(status)}
|
||||||
|
onMouseLeave={() => setHoveredStatus(null)}
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
await changeAircraftMutation.mutateAsync({
|
await changeAircraftMutation.mutateAsync({
|
||||||
id: aircraft.id,
|
id: aircraft.id,
|
||||||
|
|||||||
@@ -61,9 +61,36 @@ const Einsatzdetails = ({ mission }: { mission: Mission }) => {
|
|||||||
const { setMissionFormValues, setOpen } = usePannelStore((state) => state);
|
const { setMissionFormValues, setOpen } = usePannelStore((state) => state);
|
||||||
return (
|
return (
|
||||||
<div className="p-4 text-base-content">
|
<div className="p-4 text-base-content">
|
||||||
<h2 className="flex items-center gap-2 text-lg font-bold mb-3">
|
<div className="flex items-center justify-between mb-3">
|
||||||
<Flag /> Einsatzdetails
|
<h2 className="flex items-center gap-2 text-lg font-bold">
|
||||||
</h2>
|
<Flag /> Einsatzdetails
|
||||||
|
</h2>
|
||||||
|
{mission.state !== "draft" && (
|
||||||
|
<div
|
||||||
|
className="tooltip tooltip-primary tooltip-left font-semibold"
|
||||||
|
data-tip="Einsatzdaten übernehmen"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
className="btn btn-xs btn-primary btn-dash flex items-center gap-2"
|
||||||
|
onClick={() => {
|
||||||
|
setMissionFormValues({
|
||||||
|
...mission,
|
||||||
|
id: undefined,
|
||||||
|
hpgAmbulanceState: null,
|
||||||
|
hpgFireEngineState: null,
|
||||||
|
hpgPoliceState: null,
|
||||||
|
hpgLocationLat: undefined,
|
||||||
|
hpgLocationLng: undefined,
|
||||||
|
state: "draft",
|
||||||
|
});
|
||||||
|
setOpen(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Repeat2 size={16} />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
<ul className="text-base-content font-semibold">
|
<ul className="text-base-content font-semibold">
|
||||||
<li className="flex items-center gap-2 mb-1">
|
<li className="flex items-center gap-2 mb-1">
|
||||||
<BellRing size={16} /> {mission.missionKeywordCategory}
|
<BellRing size={16} /> {mission.missionKeywordCategory}
|
||||||
@@ -90,46 +117,48 @@ const Einsatzdetails = ({ mission }: { mission: Mission }) => {
|
|||||||
<LocateFixed size={16} /> {mission.addressZip} {mission.addressCity}
|
<LocateFixed size={16} /> {mission.addressZip} {mission.addressCity}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="divider mt-0 mb-0" />
|
{mission.state === "draft" && (
|
||||||
<div className="flex items-center gap-2 w-full">
|
<div>
|
||||||
<button
|
<div className="divider mt-0 mb-0" />
|
||||||
className="btn btn-sm btn-info btn-outline flex-3"
|
<div className="flex items-center gap-2 w-full">
|
||||||
onClick={() => sendAlertMutation.mutate(mission.id)}
|
<button
|
||||||
>
|
className="btn btn-sm btn-info btn-outline flex-3"
|
||||||
<span className="flex items-center gap-2">
|
onClick={() => sendAlertMutation.mutate(mission.id)}
|
||||||
<BellRing size={16} /> Alarmieren
|
>
|
||||||
</span>
|
<span className="flex items-center gap-2">
|
||||||
</button>
|
<BellRing size={16} /> Alarmieren
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
className="btn btn-sm btn-primary btn-dash flex items-center gap-2"
|
className="btn btn-sm btn-primary btn-dash flex items-center gap-2"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setMissionFormValues({
|
setMissionFormValues({
|
||||||
...mission,
|
...mission,
|
||||||
id: undefined,
|
id: undefined,
|
||||||
hpgAmbulanceState: null,
|
hpgAmbulanceState: null,
|
||||||
hpgFireEngineState: null,
|
hpgFireEngineState: null,
|
||||||
hpgPoliceState: null,
|
hpgPoliceState: null,
|
||||||
hpgLocationLat: undefined,
|
hpgLocationLat: undefined,
|
||||||
hpgLocationLng: undefined,
|
hpgLocationLng: undefined,
|
||||||
state: "draft",
|
state: "draft",
|
||||||
});
|
});
|
||||||
setOpen(true);
|
setOpen(true);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Repeat2 size={18} /> Daten übernehmen
|
<Repeat2 size={18} /> Daten übernehmen
|
||||||
</button>
|
</button>
|
||||||
{mission.state === "draft" && (
|
<button
|
||||||
<button
|
className="btn btn-sm btn-error btn-outline"
|
||||||
className="btn btn-sm btn-error btn-outline"
|
onClick={() => {
|
||||||
onClick={() => {
|
deleteMissionMutation.mutate(mission.id);
|
||||||
deleteMissionMutation.mutate(mission.id);
|
}}
|
||||||
}}
|
>
|
||||||
>
|
<Trash size={18} />
|
||||||
<Trash size={18} />
|
</button>
|
||||||
</button>
|
</div>
|
||||||
)}
|
</div>
|
||||||
</div>
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
"leaflet": "^1.9.4",
|
"leaflet": "^1.9.4",
|
||||||
"livekit-client": "^2.9.7",
|
"livekit-client": "^2.9.7",
|
||||||
"livekit-server-sdk": "^2.10.2",
|
"livekit-server-sdk": "^2.10.2",
|
||||||
"lucide-react": "^0.482.0",
|
"lucide-react": "^0.511.0",
|
||||||
"next": "^15.1.0",
|
"next": "^15.1.0",
|
||||||
"next-auth": "^4.24.11",
|
"next-auth": "^4.24.11",
|
||||||
"postcss": "^8.5.1",
|
"postcss": "^8.5.1",
|
||||||
|
|||||||
8
package-lock.json
generated
8
package-lock.json
generated
@@ -32,7 +32,7 @@
|
|||||||
"leaflet": "^1.9.4",
|
"leaflet": "^1.9.4",
|
||||||
"livekit-client": "^2.9.7",
|
"livekit-client": "^2.9.7",
|
||||||
"livekit-server-sdk": "^2.10.2",
|
"livekit-server-sdk": "^2.10.2",
|
||||||
"lucide-react": "^0.482.0",
|
"lucide-react": "^0.511.0",
|
||||||
"next": "^15.1.0",
|
"next": "^15.1.0",
|
||||||
"next-auth": "^4.24.11",
|
"next-auth": "^4.24.11",
|
||||||
"postcss": "^8.5.1",
|
"postcss": "^8.5.1",
|
||||||
@@ -84,9 +84,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"apps/dispatch/node_modules/lucide-react": {
|
"apps/dispatch/node_modules/lucide-react": {
|
||||||
"version": "0.482.0",
|
"version": "0.511.0",
|
||||||
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.482.0.tgz",
|
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.511.0.tgz",
|
||||||
"integrity": "sha512-XM8PzHzSrg8ATmmO+fzf+JyYlVVdQnJjuyLDj2p4V2zEtcKeBNAqAoJIGFv1x2HSBa7kT8gpYUxwdQ0g7nypfw==",
|
"integrity": "sha512-VK5a2ydJ7xm8GvBeKLS9mu1pVK6ucef9780JVUjw6bAjJL/QXnd4Y0p7SPeOUMC27YhzNCZvm5d/QX0Tp3rc0w==",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||||
|
|||||||
Reference in New Issue
Block a user