Add Aircraft Popup Pages: Aircraft & Mission

This commit is contained in:
nocnico
2025-05-13 23:48:11 +02:00
parent 265f7618de
commit b1809dc5ef
2 changed files with 162 additions and 25 deletions

View File

@@ -23,11 +23,13 @@ import {
} from "_components/SmartPopup";
import FMSStatusHistory, {
FMSStatusSelector,
MissionTab,
RettungsmittelTab,
} from "./_components/AircraftMarkerTabs";
import { ConnectedAircraft, Station } from "@repo/db";
import { useQuery } from "@tanstack/react-query";
import { getConnectedAircraftsAPI } from "querys/aircrafts";
import { getMissionsAPI } from "querys/missions";
export const FMS_STATUS_COLORS: { [key: string]: string } = {
"0": "rgb(140,10,10)",
@@ -76,22 +78,39 @@ const AircraftPopupContent = ({
[currentTab, aircraft.id, setAircraftTab],
);
const { data: missions } = useQuery({
queryKey: ["missions"],
queryFn: () => getMissionsAPI(),
});
const mission = useMemo(() => {
return missions?.find(
(m) =>
(m.state === "running" || m.state === "draft") &&
m.missionStationIds.includes(aircraft.Station.id.toString()),
);
}, [missions, aircraft.Station.id]);
const renderTabContent = useMemo(() => {
switch (currentTab) {
case "home":
return <FMSStatusHistory />;
return <FMSStatusHistory aircraft={aircraft} />;
case "fms":
return <FMSStatusSelector aircraft={aircraft} />;
case "aircraft":
return <RettungsmittelTab />;
return <RettungsmittelTab aircraft={aircraft} />;
case "mission":
return <div>Mission Content</div>;
return mission ? (
<MissionTab mission={mission} />
) : (
<span className="text-gray-100">No mission available</span>
);
case "chat":
return <div>Chat Content</div>;
default:
return <span className="text-gray-100">Error</span>;
}
}, [currentTab, aircraft]);
}, [currentTab, aircraft, mission]);
const setOpenAircraftMarker = useMapStore(
(state) => state.setOpenAircraftMarker,

View File

@@ -1,38 +1,84 @@
"use client";
import React, { useState } from "react";
import { FMS_STATUS_COLORS, FMS_STATUS_TEXT_COLORS } from "../AircraftMarker";
import { ConnectedAircraft, Prisma, Station } from "@repo/db";
import { ConnectedAircraft, Mission, Prisma, Station } from "@repo/db";
import { toast } from "react-hot-toast";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { editConnectedAircraftAPI } from "querys/aircrafts";
import { useDispatchConnectionStore } from "_store/dispatch/connectionStore";
import { cn } from "helpers/cn";
import { PersonIcon } from "@radix-ui/react-icons";
import {
BellRing,
CircleGaugeIcon,
Clock,
CompassIcon,
Component,
GaugeIcon,
Hash,
ListCollapse,
LocateFixed,
MapPin,
Mountain,
Navigation,
RadioTower,
SirenIcon,
Sunset,
TextSearch,
} from "lucide-react";
const FMSStatusHistory = () => {
const FMSStatusHistory = ({
aircraft,
}: {
aircraft: ConnectedAircraft & { Station: Station };
}) => {
const dummyData = [
{ status: "3", time: "12:00" },
{ status: "4", time: "12:30" },
{ status: "7", time: "14:54" },
{ status: "8", time: "13:30" },
{ status: "1", time: "13:30" },
{ status: "8", time: "15:30" },
{ status: "1", time: "16:30" },
{ status: "4", time: "17:30" },
{ status: "7", time: "18:54" },
{ status: "8", time: "19:30" },
{ status: "1", time: "20:30" },
{ status: "4", time: "21:30" },
{ status: "7", time: "22:54" },
{ status: "8", time: "23:30" },
{ status: "1", time: "24:30" },
];
const aircraftUser =
typeof aircraft.publicUser === "string"
? JSON.parse(aircraft.publicUser)
: aircraft.publicUser;
return (
<div className="p-4">
<ul className="text-base-content font-semibold">
<li className="flex items-center gap-2 mb-1">
<PersonIcon className="w-5 h-5" /> {aircraftUser.fullName} (
{aircraftUser.publicId})
</li>
</ul>
<div className="divider mt-0 mb-0" />
<ul className="space-y-2">
{dummyData.map((entry, index) => (
<li key={index} className="flex items-center gap-2">
<span
className="font-bold text-base"
style={{
color: FMS_STATUS_TEXT_COLORS[entry.status],
}}
>
{entry.status}
</span>
<span className="text-base-content">{entry.time}</span>
</li>
))}
{dummyData
.reverse()
.slice(0, 6)
.map((entry, index) => (
<li key={index} className="flex items-center gap-2">
<span
className="font-bold text-base"
style={{
color: FMS_STATUS_TEXT_COLORS[entry.status],
}}
>
{entry.status}
</span>
<span className="text-base-content">{entry.time}</span>
</li>
))}
</ul>
</div>
);
@@ -108,12 +154,84 @@ const FMSStatusSelector = ({
);
};
const RettungsmittelTab = () => {
const RettungsmittelTab = ({
aircraft,
}: {
aircraft: ConnectedAircraft & { Station: Station };
}) => {
const station = aircraft.Station;
return (
<div className="flex gap-2 p-4">
<p className="text-base text-base-content">Aktuelle Rufgruppe: LST_01</p>
<div className="p-4 text-base-content">
<ul className="text-base-content font-semibold">
<li className="flex items-center gap-2 mb-1">
<Component size={16} /> Aktuelle Rufgruppe: LST_01
</li>
<li className="flex items-center gap-2 mb-1">
<RadioTower size={16} /> Leitstellenbereich: Florian Berlin
</li>
</ul>
<div className="divider mt-0 mb-0" />
<div className="flex items-center text-sm font-semibold justify-between pr-2 mt-2 mb-2">
<span className="flex items-center gap-2">
<Clock size={16} /> {station.is24h ? "24h Betrieb" : "Tagbetrieb"}
</span>
<span className="flex items-center gap-2">
<Sunset size={16} /> NVG: {station.hasNvg ? "Ja" : "Nein"}
</span>
<span className="flex items-center gap-2">
<Mountain size={16} /> Winch: {station.hasWinch ? "Ja" : "Nein"}
</span>
<span className="flex items-center gap-2">
<TextSearch size={16} /> {station.aircraftRegistration}
</span>
</div>
<div className="divider mt-0 mb-0" />
<div className="flex items-center text-sm font-semibold justify-between pr-2 mt-2">
<span className="flex items-center gap-2">
<CompassIcon size={16} /> HDG: {aircraft.posHeading}°
</span>
<span className="flex items-center gap-2">
<GaugeIcon size={16} /> SPD: {aircraft.posSpeed} kt
</span>
<span className="flex items-center gap-2">
<CircleGaugeIcon size={16} /> ALT: {aircraft.posAlt} ft
</span>
</div>
</div>
);
};
export { FMSStatusSelector, RettungsmittelTab };
const MissionTab = ({ mission }: { mission: Mission }) => {
return (
<div className="p-4 text-base-content">
<ul className="text-base-content font-semibold">
<li className="flex items-center gap-2 mb-1">
<BellRing size={16} /> {mission.missionKeywordCategory}
</li>
<li className="flex items-center gap-2 mb-1">
<ListCollapse size={16} />
{mission.missionKeywordName}
</li>
<li className="flex items-center gap-2 mt-3">
<Hash size={16} />
__{new Date().toISOString().slice(0, 10).replace(/-/g, "")}
{mission.id}
</li>
</ul>
<div className="divider mt-0 mb-0" />
<div className="text-sm font-semibold">
<p className="flex items-center gap-2">
<MapPin size={16} /> {mission.addressLat} {mission.addressLng}
</p>
<p className="flex items-center gap-2">
<Navigation size={16} /> {mission.addressStreet}
</p>
<p className="flex items-center gap-2">
<LocateFixed size={16} /> {mission.addressZip} {mission.addressCity}
</p>
</div>
</div>
);
};
export { FMSStatusSelector, RettungsmittelTab, MissionTab };
export default FMSStatusHistory;