added mrt, dev
This commit is contained in:
@@ -48,6 +48,10 @@ router.patch("/:id", async (req, res) => {
|
|||||||
"update-connectedAircraft",
|
"update-connectedAircraft",
|
||||||
updatedConnectedAircraft,
|
updatedConnectedAircraft,
|
||||||
);
|
);
|
||||||
|
io.to(`user:${updatedConnectedAircraft.userId}`).emit(
|
||||||
|
"aircraft-update",
|
||||||
|
updatedConnectedAircraft,
|
||||||
|
);
|
||||||
res.json(updatedConnectedAircraft);
|
res.json(updatedConnectedAircraft);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
|
|||||||
@@ -76,6 +76,11 @@ export const handleConnectPilot =
|
|||||||
io.to("dispatchers").emit("pilots-update");
|
io.to("dispatchers").emit("pilots-update");
|
||||||
io.to("pilots").emit("pilots-update");
|
io.to("pilots").emit("pilots-update");
|
||||||
|
|
||||||
|
io.to(`user:${connectedAircraftEntry.userId}`).emit(
|
||||||
|
"aircraft-update",
|
||||||
|
connectedAircraftEntry,
|
||||||
|
);
|
||||||
|
|
||||||
// Add a listener for station-specific events
|
// Add a listener for station-specific events
|
||||||
socket.on(`station:${stationId}:event`, async (data) => {
|
socket.on(`station:${stationId}:event`, async (data) => {
|
||||||
console.log(`Received event for station ${stationId}:`, data);
|
console.log(`Received event for station ${stationId}:`, data);
|
||||||
|
|||||||
46
apps/dispatch/app/_store/pilot/MrtStore.ts
Normal file
46
apps/dispatch/app/_store/pilot/MrtStore.ts
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
import { DisplayLineProps } from "pilot/_components/mrt/Mrt";
|
||||||
|
import { create } from "zustand";
|
||||||
|
import { syncTabs } from "zustand-sync-tabs";
|
||||||
|
|
||||||
|
type Page = "home" | "sending-status" | "new-status" | "error";
|
||||||
|
|
||||||
|
type PageData = {
|
||||||
|
home: undefined;
|
||||||
|
"sending-status": undefined;
|
||||||
|
"new-status": undefined;
|
||||||
|
error: {
|
||||||
|
message: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
interface MrtStore {
|
||||||
|
page: Page;
|
||||||
|
pageData: PageData[Page];
|
||||||
|
|
||||||
|
lines: DisplayLineProps[];
|
||||||
|
|
||||||
|
setPage: <P extends Page>(page: P, pageData?: PageData[P]) => void;
|
||||||
|
setLines: (lines: MrtStore["lines"]) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useMrtStore = create<MrtStore>(
|
||||||
|
syncTabs(
|
||||||
|
(set) => ({
|
||||||
|
page: "home",
|
||||||
|
pageData: {
|
||||||
|
message: "",
|
||||||
|
},
|
||||||
|
lines: Array.from(Array(10).keys()).map(() => ({
|
||||||
|
textLeft: "",
|
||||||
|
textMid: "",
|
||||||
|
textRight: "",
|
||||||
|
textSize: "1",
|
||||||
|
})),
|
||||||
|
setLines: (lines) => set({ lines }),
|
||||||
|
setPage: (page, pageData) => set({ page, pageData }),
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
name: "mrt-store", // unique name
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
@@ -1,12 +1,14 @@
|
|||||||
import { create } from "zustand";
|
import { create } from "zustand";
|
||||||
import { dispatchSocket } from "../../dispatch/socket";
|
import { dispatchSocket } from "../../dispatch/socket";
|
||||||
import { Mission, Station } from "@repo/db";
|
import { ConnectedAircraft, Mission, Station } from "@repo/db";
|
||||||
import { pilotSocket } from "pilot/socket";
|
import { pilotSocket } from "pilot/socket";
|
||||||
|
import { useMrtStore } from "_store/pilot/MrtStore";
|
||||||
|
|
||||||
interface ConnectionStore {
|
interface ConnectionStore {
|
||||||
status: "connected" | "disconnected" | "connecting" | "error";
|
status: "connected" | "disconnected" | "connecting" | "error";
|
||||||
message: string;
|
message: string;
|
||||||
selectedStation: Station | null;
|
selectedStation: Station | null;
|
||||||
|
connectedAircraft: ConnectedAircraft | null;
|
||||||
activeMission:
|
activeMission:
|
||||||
| (Mission & {
|
| (Mission & {
|
||||||
Stations: Station[];
|
Stations: Station[];
|
||||||
@@ -25,6 +27,7 @@ export const usePilotConnectionStore = create<ConnectionStore>((set) => ({
|
|||||||
status: "disconnected",
|
status: "disconnected",
|
||||||
message: "",
|
message: "",
|
||||||
selectedStation: null,
|
selectedStation: null,
|
||||||
|
connectedAircraft: null,
|
||||||
activeMission: null,
|
activeMission: null,
|
||||||
connect: async (uid, stationId, logoffTime, station) =>
|
connect: async (uid, stationId, logoffTime, station) =>
|
||||||
new Promise((resolve) => {
|
new Promise((resolve) => {
|
||||||
@@ -68,6 +71,13 @@ pilotSocket.on("force-disconnect", (reason: string) => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
pilotSocket.on("aircraft-update", (data) => {
|
||||||
|
usePilotConnectionStore.setState({
|
||||||
|
connectedAircraft: data,
|
||||||
|
});
|
||||||
|
useMrtStore.getState().setLines(getNew);
|
||||||
|
});
|
||||||
|
|
||||||
pilotSocket.on("mission-alert", (data) => {
|
pilotSocket.on("mission-alert", (data) => {
|
||||||
usePilotConnectionStore.setState({
|
usePilotConnectionStore.setState({
|
||||||
activeMission: data,
|
activeMission: data,
|
||||||
|
|||||||
@@ -3,6 +3,11 @@
|
|||||||
themes: dark, nord;
|
themes: dark, nord;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Melder";
|
||||||
|
src: url("/fonts/MelderV2.ttf") format("truetype"); /* Chrome 4+, Firefox 3.5, Opera 10+, Safari 3—5 */
|
||||||
|
}
|
||||||
|
|
||||||
@theme {
|
@theme {
|
||||||
--color-rescuetrack: #46b7a3;
|
--color-rescuetrack: #46b7a3;
|
||||||
--color-rescuetrack-highlight: #ff4500;
|
--color-rescuetrack-highlight: #ff4500;
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import "./globals.css";
|
|||||||
import { NextAuthSessionProvider } from "./_components/AuthSessionProvider";
|
import { NextAuthSessionProvider } from "./_components/AuthSessionProvider";
|
||||||
import { getServerSession } from "./api/auth/[...nextauth]/auth";
|
import { getServerSession } from "./api/auth/[...nextauth]/auth";
|
||||||
import { Toaster } from "react-hot-toast";
|
import { Toaster } from "react-hot-toast";
|
||||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
||||||
import { QueryProvider } from "_components/QueryProvider";
|
import { QueryProvider } from "_components/QueryProvider";
|
||||||
|
|
||||||
const geistSans = localFont({
|
const geistSans = localFont({
|
||||||
|
|||||||
BIN
apps/dispatch/app/pilot/_components/mrt/MRT.png
Normal file
BIN
apps/dispatch/app/pilot/_components/mrt/MRT.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 194 KiB |
183
apps/dispatch/app/pilot/_components/mrt/Mrt.tsx
Normal file
183
apps/dispatch/app/pilot/_components/mrt/Mrt.tsx
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
import { CSSProperties } from "react";
|
||||||
|
import MrtImage from "./MRT.png";
|
||||||
|
import { useButtons } from "./useButtons";
|
||||||
|
import { useSounds } from "./useSounds";
|
||||||
|
import "./mrt.css";
|
||||||
|
import Image from "next/image";
|
||||||
|
import { useMrtStore } from "_store/pilot/MrtStore";
|
||||||
|
|
||||||
|
const MRT_BUTTON_STYLES: CSSProperties = {
|
||||||
|
cursor: "pointer",
|
||||||
|
zIndex: "9999",
|
||||||
|
backgroundColor: "transparent",
|
||||||
|
border: "none",
|
||||||
|
};
|
||||||
|
const MRT_DISPLAYLINE_STYLES: CSSProperties = {
|
||||||
|
color: "white",
|
||||||
|
zIndex: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface DisplayLineProps {
|
||||||
|
style?: CSSProperties;
|
||||||
|
textLeft?: string;
|
||||||
|
textMid?: string;
|
||||||
|
textRight?: string;
|
||||||
|
textSize: "1" | "2" | "3" | "4";
|
||||||
|
}
|
||||||
|
|
||||||
|
const DisplayLine = ({
|
||||||
|
style = {},
|
||||||
|
textLeft,
|
||||||
|
textMid,
|
||||||
|
textRight,
|
||||||
|
textSize,
|
||||||
|
}: DisplayLineProps) => {
|
||||||
|
const INNER_TEXT_PARTS: CSSProperties = {
|
||||||
|
fontFamily: "Melder",
|
||||||
|
flex: "1",
|
||||||
|
flexBasis: "auto",
|
||||||
|
overflowWrap: "break-word",
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={`text-${textSize}`}
|
||||||
|
style={{
|
||||||
|
fontFamily: "Famirids",
|
||||||
|
display: "flex",
|
||||||
|
flexWrap: "wrap",
|
||||||
|
...style,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span style={INNER_TEXT_PARTS}>{textLeft}</span>
|
||||||
|
<span style={{ textAlign: "center", ...INNER_TEXT_PARTS }}>
|
||||||
|
{textMid}
|
||||||
|
</span>
|
||||||
|
<span style={{ textAlign: "end", ...INNER_TEXT_PARTS }}>{textRight}</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Mrt = () => {
|
||||||
|
useSounds();
|
||||||
|
const { handleButton } = useButtons();
|
||||||
|
const lines = useMrtStore((state) => state.lines);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
id="mrt-container"
|
||||||
|
style={{
|
||||||
|
containerName: "mrtContainer",
|
||||||
|
display: "grid",
|
||||||
|
aspectRatio: "1466 / 760",
|
||||||
|
height: "auto",
|
||||||
|
width: "auto",
|
||||||
|
maxHeight: "100%",
|
||||||
|
maxWidth: "100%",
|
||||||
|
overflow: "hidden",
|
||||||
|
color: "white",
|
||||||
|
gridTemplateColumns:
|
||||||
|
"21.83% 4.43% 24.42% 18.08% 5.93% 1.98% 6.00% 1.69% 6.00% 9.35%",
|
||||||
|
gridTemplateRows:
|
||||||
|
"21.58% 11.87% 3.55% 5.00% 6.84% 0.53% 3.03% 11.84% 3.55% 11.84% 20.39%",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Image
|
||||||
|
src={MrtImage}
|
||||||
|
alt="MrtImage"
|
||||||
|
style={{
|
||||||
|
zIndex: 0,
|
||||||
|
height: "100%",
|
||||||
|
width: "100%",
|
||||||
|
gridArea: "1 / 1 / 13 / 13",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
onClick={handleButton("1")}
|
||||||
|
style={{ gridArea: "2 / 5 / 3 / 6", ...MRT_BUTTON_STYLES }}
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
onClick={handleButton("2")}
|
||||||
|
style={{ gridArea: "2 / 7 / 3 / 7", ...MRT_BUTTON_STYLES }}
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
onClick={handleButton("3")}
|
||||||
|
style={{ gridArea: "2 / 9 / 3 / 10", ...MRT_BUTTON_STYLES }}
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
onClick={handleButton("4")}
|
||||||
|
style={{ gridArea: "4 / 5 / 6 / 6", ...MRT_BUTTON_STYLES }}
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
onClick={handleButton("5")}
|
||||||
|
style={{ gridArea: "4 / 7 / 6 / 7", ...MRT_BUTTON_STYLES }}
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
onClick={handleButton("6")}
|
||||||
|
style={{ gridArea: "4 / 9 / 6 / 10", ...MRT_BUTTON_STYLES }}
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
onClick={handleButton("7")}
|
||||||
|
style={{ gridArea: "8 / 5 / 9 / 6", ...MRT_BUTTON_STYLES }}
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
onClick={handleButton("8")}
|
||||||
|
style={{ gridArea: "8 / 7 / 9 / 7", ...MRT_BUTTON_STYLES }}
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
onClick={handleButton("9")}
|
||||||
|
style={{ gridArea: "8 / 9 / 9 / 10", ...MRT_BUTTON_STYLES }}
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
onClick={handleButton("0")}
|
||||||
|
style={{ gridArea: "10 / 7 / 11 / 8", ...MRT_BUTTON_STYLES }}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{lines[0] && (
|
||||||
|
<DisplayLine
|
||||||
|
{...lines[0]}
|
||||||
|
style={{
|
||||||
|
gridArea: "4 / 3 / 5 / 4",
|
||||||
|
marginLeft: "9px",
|
||||||
|
marginTop: "auto",
|
||||||
|
...MRT_DISPLAYLINE_STYLES,
|
||||||
|
...lines[0]?.style,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{lines[1] && (
|
||||||
|
<DisplayLine
|
||||||
|
{...lines[1]}
|
||||||
|
style={{
|
||||||
|
gridArea: "5 / 3 / 7 / 4",
|
||||||
|
marginLeft: "3px",
|
||||||
|
marginTop: "auto",
|
||||||
|
...MRT_DISPLAYLINE_STYLES,
|
||||||
|
...lines[1].style,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{lines[2] && (
|
||||||
|
<DisplayLine
|
||||||
|
{...lines[2]}
|
||||||
|
style={{
|
||||||
|
gridArea: "8 / 2 / 9 / 4",
|
||||||
|
...MRT_DISPLAYLINE_STYLES,
|
||||||
|
...lines[2]?.style,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{lines[3] && (
|
||||||
|
<DisplayLine
|
||||||
|
{...lines[3]}
|
||||||
|
style={{
|
||||||
|
gridArea: "9 / 2 / 10 / 4",
|
||||||
|
marginRight: "10px",
|
||||||
|
...MRT_DISPLAYLINE_STYLES,
|
||||||
|
...lines[3]?.style,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
32
apps/dispatch/app/pilot/_components/mrt/mrt.css
Normal file
32
apps/dispatch/app/pilot/_components/mrt/mrt.css
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#mrt-container {
|
||||||
|
container-name: mrtContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@container mrtContainer (inline-size < 600px) {
|
||||||
|
#mrt-container .text-1 {
|
||||||
|
font-size: 12px;
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
#mrt-container .text-2 {
|
||||||
|
font-size: 99px;
|
||||||
|
}
|
||||||
|
#mrt-container .text-3 {
|
||||||
|
font-size: 25px;
|
||||||
|
}
|
||||||
|
#mrt-container .text-4 {
|
||||||
|
font-size: 45px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#mrt-container .text-1 {
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
#mrt-container .text-2 {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
#mrt-container .text-3 {
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
#mrt-container .text-4 {
|
||||||
|
font-size: 25px;
|
||||||
|
}
|
||||||
140
apps/dispatch/app/pilot/_components/mrt/useButtons.ts
Normal file
140
apps/dispatch/app/pilot/_components/mrt/useButtons.ts
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
import { useSession } from "next-auth/react";
|
||||||
|
import { usePilotConnectionStore } from "_store/pilot/connectionStore";
|
||||||
|
import { useMrtStore } from "_store/pilot/MrtStore";
|
||||||
|
import { editConnectedAircraftAPI } from "querys/aircrafts";
|
||||||
|
import { Station } from "@repo/db";
|
||||||
|
import { DisplayLineProps } from "pilot/_components/mrt/Mrt";
|
||||||
|
|
||||||
|
export const fmsStatusDescription: { [key: string]: string } = {
|
||||||
|
NaN: "Keine Daten",
|
||||||
|
"0": "Prio. Sprechwunsch",
|
||||||
|
"1": "Frei auf Funk",
|
||||||
|
"2": "Einsatzbereit am LRZ",
|
||||||
|
"3": "Auf dem Weg",
|
||||||
|
"4": "Am Einsatzort",
|
||||||
|
"5": "Sprechwunsch",
|
||||||
|
"6": "Nicht einsatzbereit",
|
||||||
|
"7": "Patient aufgenommen",
|
||||||
|
"8": "Am Transportziel",
|
||||||
|
"9": "Fremdanmeldung",
|
||||||
|
E: "Indent/Abbruch/Einsatzbefehl abgebrochen",
|
||||||
|
C: "Anmelden zur Übernahme des Einsatzes",
|
||||||
|
F: "Kommen über Draht",
|
||||||
|
H: "Fahren auf Wache",
|
||||||
|
J: "Sprechaufforderung",
|
||||||
|
L: "Lagebericht abgeben",
|
||||||
|
P: "Einsatz mit Polizei/Pause machen",
|
||||||
|
U: "Ungültiger Status",
|
||||||
|
c: "Status korrigieren",
|
||||||
|
d: "Transportziel angeben",
|
||||||
|
h: "Zielklinik verständigt",
|
||||||
|
o: "Warten, alle Abfrageplätze belegt",
|
||||||
|
u: "Verstanden",
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getSendingLines = (station: Station): DisplayLineProps[] => {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
textLeft: `VAR#.${station?.bosCallsign}123`,
|
||||||
|
style: { fontWeight: "bold" },
|
||||||
|
textSize: "2",
|
||||||
|
},
|
||||||
|
{ textLeft: "ILS VAR#", textSize: "3" },
|
||||||
|
{
|
||||||
|
textMid: "sending...",
|
||||||
|
style: { fontWeight: "bold" },
|
||||||
|
textSize: "4",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
textLeft: "Status wird gesendet...",
|
||||||
|
textSize: "1",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getHomeLines = (
|
||||||
|
station: Station,
|
||||||
|
fmsStatus: string,
|
||||||
|
): DisplayLineProps[] => {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
textLeft: `VAR#.${station?.bosCallsign}`,
|
||||||
|
style: { fontWeight: "bold" },
|
||||||
|
textSize: "2",
|
||||||
|
},
|
||||||
|
{ textLeft: "ILS VAR#", textSize: "3" },
|
||||||
|
{
|
||||||
|
textLeft: fmsStatus,
|
||||||
|
style: { fontWeight: "extrabold" },
|
||||||
|
textSize: "4",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
textLeft: fmsStatusDescription[fmsStatus],
|
||||||
|
textSize: "1",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getNewStatusLines = (
|
||||||
|
station: Station,
|
||||||
|
fmsStatus: string,
|
||||||
|
): DisplayLineProps[] => {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
textLeft: `VAR#.${station?.bosCallsign}`,
|
||||||
|
style: { fontWeight: "bold" },
|
||||||
|
textSize: "2",
|
||||||
|
},
|
||||||
|
{ textLeft: "ILS VAR#", textSize: "3" },
|
||||||
|
{
|
||||||
|
textLeft: fmsStatus,
|
||||||
|
style: { fontWeight: "extrabold" },
|
||||||
|
textSize: "4",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
textLeft: fmsStatusDescription[fmsStatus],
|
||||||
|
textSize: "1",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useButtons = () => {
|
||||||
|
const user = useSession().data?.user;
|
||||||
|
const station = usePilotConnectionStore((state) => state.selectedStation);
|
||||||
|
const connectedAircraft = usePilotConnectionStore(
|
||||||
|
(state) => state.connectedAircraft,
|
||||||
|
);
|
||||||
|
|
||||||
|
const { page, setLines } = useMrtStore((state) => state);
|
||||||
|
|
||||||
|
const handleButton =
|
||||||
|
(button: "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" | "0") =>
|
||||||
|
() => {
|
||||||
|
if (!station) return;
|
||||||
|
if (!connectedAircraft?.id) return;
|
||||||
|
if (
|
||||||
|
button === "1" ||
|
||||||
|
button === "2" ||
|
||||||
|
button === "3" ||
|
||||||
|
button === "4" ||
|
||||||
|
button === "5" ||
|
||||||
|
button === "6" ||
|
||||||
|
button === "7" ||
|
||||||
|
button === "8" ||
|
||||||
|
button === "9" ||
|
||||||
|
button === "0"
|
||||||
|
) {
|
||||||
|
if (page !== "home") return;
|
||||||
|
setLines(getSendingLines(station));
|
||||||
|
|
||||||
|
setTimeout(async () => {
|
||||||
|
await editConnectedAircraftAPI(connectedAircraft!.id, {
|
||||||
|
fmsStatus: button,
|
||||||
|
});
|
||||||
|
setLines(getNewStatusLines(station, button));
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return { handleButton };
|
||||||
|
};
|
||||||
66
apps/dispatch/app/pilot/_components/mrt/useSounds.ts
Normal file
66
apps/dispatch/app/pilot/_components/mrt/useSounds.ts
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
"use client";
|
||||||
|
import { usePilotConnectionStore } from "_store/pilot/connectionStore";
|
||||||
|
import { useMrtStore } from "_store/pilot/MrtStore";
|
||||||
|
import { editConnectedAircraftAPI } from "querys/aircrafts";
|
||||||
|
import { useEffect, useRef } from "react";
|
||||||
|
|
||||||
|
const MRTstatusSound = new Audio("/sounds/MRT-status.mp3");
|
||||||
|
const MrtMessageReceivedSound = new Audio("/sounds/MRT-message-received.mp3");
|
||||||
|
|
||||||
|
export const useSounds = () => {
|
||||||
|
const mrtState = useMrtStore((state) => state);
|
||||||
|
const { connectedAircraft, selectedStation } = usePilotConnectionStore(
|
||||||
|
(state) => state,
|
||||||
|
);
|
||||||
|
|
||||||
|
const fmsStatus = connectedAircraft?.fmsStatus || "NaN";
|
||||||
|
|
||||||
|
const previousFmsStatus = useRef(fmsStatus || "6");
|
||||||
|
const timeout = useRef<NodeJS.Timeout>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const handleSoundEnd = () => {
|
||||||
|
mrtState.setPage("home");
|
||||||
|
};
|
||||||
|
|
||||||
|
const playSound = (sound: HTMLAudioElement) => {
|
||||||
|
sound.play();
|
||||||
|
sound.addEventListener("ended", handleSoundEnd);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!connectedAircraft) return;
|
||||||
|
if (mrtState.page === "new-status") {
|
||||||
|
if (fmsStatus === "J") {
|
||||||
|
playSound(MrtMessageReceivedSound);
|
||||||
|
|
||||||
|
timeout.current = setTimeout(() => {
|
||||||
|
editConnectedAircraftAPI(connectedAircraft.id, {
|
||||||
|
fmsStatus: previousFmsStatus.current,
|
||||||
|
});
|
||||||
|
}, 5000);
|
||||||
|
} else if (previousFmsStatus.current !== fmsStatus) {
|
||||||
|
playSound(MRTstatusSound);
|
||||||
|
} else {
|
||||||
|
handleSoundEnd();
|
||||||
|
}
|
||||||
|
if (!timeout.current) {
|
||||||
|
previousFmsStatus.current = fmsStatus || "6";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return () => {
|
||||||
|
if (timeout.current) clearTimeout(timeout.current);
|
||||||
|
[MRTstatusSound, MrtMessageReceivedSound].forEach((sound) => {
|
||||||
|
sound.removeEventListener("ended", handleSoundEnd);
|
||||||
|
sound.pause();
|
||||||
|
sound.currentTime = 0;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}, [
|
||||||
|
mrtState,
|
||||||
|
fmsStatus,
|
||||||
|
connectedAircraft,
|
||||||
|
selectedStation,
|
||||||
|
previousFmsStatus,
|
||||||
|
timeout,
|
||||||
|
]);
|
||||||
|
};
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
|
import { Mrt } from "pilot/_components/mrt/Mrt";
|
||||||
import { Chat } from "../_components/left/Chat";
|
import { Chat } from "../_components/left/Chat";
|
||||||
import { Report } from "../_components/left/Report";
|
import { Report } from "../_components/left/Report";
|
||||||
import { usePilotConnectionStore } from "_store/pilot/connectionStore";
|
import { usePilotConnectionStore } from "_store/pilot/connectionStore";
|
||||||
@@ -19,6 +20,9 @@ const DispatchPage = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>{JSON.stringify(activeMission)}</div>
|
<div>{JSON.stringify(activeMission)}</div>
|
||||||
|
<div>
|
||||||
|
<Mrt />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -32,7 +32,8 @@
|
|||||||
"react-leaflet": "^5.0.0-rc.2",
|
"react-leaflet": "^5.0.0-rc.2",
|
||||||
"socket.io-client": "^4.8.1",
|
"socket.io-client": "^4.8.1",
|
||||||
"tailwindcss": "^4.0.14",
|
"tailwindcss": "^4.0.14",
|
||||||
"zustand": "^5.0.3"
|
"zustand": "^5.0.3",
|
||||||
|
"zustand-sync-tabs": "^0.2.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@repo/eslint-config": "*",
|
"@repo/eslint-config": "*",
|
||||||
|
|||||||
BIN
apps/dispatch/public/fonts/00TT.ttf
Normal file
BIN
apps/dispatch/public/fonts/00TT.ttf
Normal file
Binary file not shown.
BIN
apps/dispatch/public/fonts/Famirids..ttf
Normal file
BIN
apps/dispatch/public/fonts/Famirids..ttf
Normal file
Binary file not shown.
BIN
apps/dispatch/public/fonts/MelderV1.ttf
Normal file
BIN
apps/dispatch/public/fonts/MelderV1.ttf
Normal file
Binary file not shown.
BIN
apps/dispatch/public/fonts/MelderV2.ttf
Normal file
BIN
apps/dispatch/public/fonts/MelderV2.ttf
Normal file
Binary file not shown.
BIN
apps/dispatch/public/fonts/MelderV3.ttf
Normal file
BIN
apps/dispatch/public/fonts/MelderV3.ttf
Normal file
Binary file not shown.
BIN
apps/dispatch/public/fonts/MelderV4.ttf
Normal file
BIN
apps/dispatch/public/fonts/MelderV4.ttf
Normal file
Binary file not shown.
BIN
apps/dispatch/public/fonts/VCR_OSD_MONO.ttf
Normal file
BIN
apps/dispatch/public/fonts/VCR_OSD_MONO.ttf
Normal file
Binary file not shown.
BIN
apps/dispatch/public/sounds/MRT-message-received.mp3
Normal file
BIN
apps/dispatch/public/sounds/MRT-message-received.mp3
Normal file
Binary file not shown.
BIN
apps/dispatch/public/sounds/MRT-status.mp3
Normal file
BIN
apps/dispatch/public/sounds/MRT-status.mp3
Normal file
Binary file not shown.
@@ -107,7 +107,7 @@ export const ReportAdmin = ({
|
|||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
role="button"
|
role="button"
|
||||||
className="btn btn-warning"
|
className="btn btn-sm btn-warning"
|
||||||
onSubmit={() => false}
|
onSubmit={() => false}
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
await editReport(report.id, {
|
await editReport(report.id, {
|
||||||
|
|||||||
Binary file not shown.
16
package-lock.json
generated
16
package-lock.json
generated
@@ -42,7 +42,8 @@
|
|||||||
"react-leaflet": "^5.0.0-rc.2",
|
"react-leaflet": "^5.0.0-rc.2",
|
||||||
"socket.io-client": "^4.8.1",
|
"socket.io-client": "^4.8.1",
|
||||||
"tailwindcss": "^4.0.14",
|
"tailwindcss": "^4.0.14",
|
||||||
"zustand": "^5.0.3"
|
"zustand": "^5.0.3",
|
||||||
|
"zustand-sync-tabs": "^0.2.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@repo/eslint-config": "*",
|
"@repo/eslint-config": "*",
|
||||||
@@ -18008,6 +18009,19 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/zustand-sync-tabs": {
|
||||||
|
"version": "0.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/zustand-sync-tabs/-/zustand-sync-tabs-0.2.2.tgz",
|
||||||
|
"integrity": "sha512-i2pQPm5SGBIq50v7tt6XFXZSR/iJNErOslS5HzMKJVd06+xDyBCXioxEap0Ke6u98+a49fU5QRqzypo21wMe9A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/mayank1513"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"zustand": "3-5"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/zwitch": {
|
"node_modules/zwitch": {
|
||||||
"version": "2.0.4",
|
"version": "2.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz",
|
||||||
|
|||||||
Reference in New Issue
Block a user