Dispatch Router-Struktur; AddPenalty Layout gefixed
This commit is contained in:
132
apps/dispatch/app/(app)/pilot/_components/dme/Dme.tsx
Normal file
132
apps/dispatch/app/(app)/pilot/_components/dme/Dme.tsx
Normal file
@@ -0,0 +1,132 @@
|
||||
import { CSSProperties } from "react";
|
||||
import sQuadImageNoReflections from "./Melder_NoReflections.png";
|
||||
import sQuadReflection from "./reflektion.png";
|
||||
import { useButtons } from "./useButtons";
|
||||
import { useSounds } from "./useSounds";
|
||||
import Image from "next/image";
|
||||
import { useDmeStore } from "_store/pilot/dmeStore";
|
||||
|
||||
const DME_BUTTON_STYLES: CSSProperties = {
|
||||
cursor: "pointer",
|
||||
zIndex: "9999",
|
||||
backgroundColor: "transparent",
|
||||
border: "none",
|
||||
};
|
||||
|
||||
export interface DisplayLineProps {
|
||||
style?: CSSProperties;
|
||||
textLeft?: string;
|
||||
textMid?: string;
|
||||
textRight?: string;
|
||||
}
|
||||
|
||||
const DisplayLine = ({
|
||||
style = {},
|
||||
textLeft,
|
||||
textMid,
|
||||
textRight,
|
||||
}: DisplayLineProps) => {
|
||||
const INNER_TEXT_PARTS: CSSProperties = {
|
||||
fontFamily: "Melder",
|
||||
flex: "1",
|
||||
flexBasis: "auto",
|
||||
overflowWrap: "break-word",
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
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 Dme = () => {
|
||||
useSounds();
|
||||
const { handleButton } = useButtons();
|
||||
const lines = useDmeStore((state) => state.lines);
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
display: "grid",
|
||||
aspectRatio: "1037 / 800",
|
||||
color: "black",
|
||||
height: "auto",
|
||||
width: "auto",
|
||||
maxHeight: "100%",
|
||||
maxWidth: "100%",
|
||||
overflow: "hidden",
|
||||
gridTemplateColumns:
|
||||
"25.84% 6.08% 10.99% 11.57% 11.28% 10.90% 18.71% 4.63%",
|
||||
gridTemplateRows: "2.66% 9.3% 8.9% 7.2% 45.05% 27%",
|
||||
}}
|
||||
>
|
||||
<Image
|
||||
src={sQuadImageNoReflections}
|
||||
alt="sQuadImage"
|
||||
style={{
|
||||
zIndex: 0,
|
||||
height: "100%",
|
||||
width: "100%",
|
||||
gridArea: "1 / 1 / 10 / 10",
|
||||
}}
|
||||
/>
|
||||
<button
|
||||
onClick={handleButton("main")}
|
||||
style={{ gridArea: "2 / 7 / 4 / 8", ...DME_BUTTON_STYLES }}
|
||||
/>
|
||||
<button
|
||||
onClick={handleButton("menu")}
|
||||
style={{ gridArea: "3 / 2 / 4 / 3", ...DME_BUTTON_STYLES }}
|
||||
/>
|
||||
{/* <button
|
||||
onClick={handleButton('left')}
|
||||
style={{ gridArea: '3 / 4 / 4 / 5', ...DME_BUTTON_STYLES }}
|
||||
/>
|
||||
<button
|
||||
onClick={handleButton('right')}
|
||||
style={{ gridArea: '3 / 5 / 4 / 6', ...DME_BUTTON_STYLES }}
|
||||
/> */}
|
||||
<Image
|
||||
src={sQuadReflection}
|
||||
alt="sQuadImage"
|
||||
style={{
|
||||
zIndex: 1,
|
||||
height: "100%",
|
||||
width: "100%",
|
||||
gridArea: "1 / 1 / 10 / 10",
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
id="display"
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
justifyContent: "space-between",
|
||||
zIndex: "2",
|
||||
gridArea: "5 / 2 / 6 / 6",
|
||||
paddingTop: "10px",
|
||||
paddingLeft: "2px",
|
||||
paddingRight: "2px",
|
||||
overflowX: "hidden",
|
||||
overflowY: "auto",
|
||||
}}
|
||||
>
|
||||
{lines.map((l, i) => {
|
||||
return <DisplayLine key={`line-${i}`} {...l} />;
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 626 KiB |
BIN
apps/dispatch/app/(app)/pilot/_components/dme/reflektion.png
Normal file
BIN
apps/dispatch/app/(app)/pilot/_components/dme/reflektion.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 167 KiB |
BIN
apps/dispatch/app/(app)/pilot/_components/dme/squad-x15.jpg
Normal file
BIN
apps/dispatch/app/(app)/pilot/_components/dme/squad-x15.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 610 KiB |
37
apps/dispatch/app/(app)/pilot/_components/dme/useButtons.ts
Normal file
37
apps/dispatch/app/(app)/pilot/_components/dme/useButtons.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import { usePilotConnectionStore } from "_store/pilot/connectionStore";
|
||||
import { useDmeStore } from "_store/pilot/dmeStore";
|
||||
|
||||
import { useSession } from "next-auth/react";
|
||||
export const useButtons = () => {
|
||||
const { page, setPage } = useDmeStore((state) => state);
|
||||
const user = useSession().data?.user;
|
||||
const station = usePilotConnectionStore((state) => state.selectedStation);
|
||||
|
||||
const handleButton = (button: "main" | "menu" | "left" | "right") => () => {
|
||||
switch (button) {
|
||||
case "main":
|
||||
if (page === "mission" || page === "new-mission") {
|
||||
setPage({ page: "acknowledge" });
|
||||
}
|
||||
break;
|
||||
case "menu":
|
||||
if (page === "mission" || page === "new-mission") {
|
||||
setPage({ page: "acknowledge" });
|
||||
if (station && user) setPage({ page: "home", station, user });
|
||||
break;
|
||||
}
|
||||
if (station && user) {
|
||||
setPage({ page: "home", station, user });
|
||||
} else {
|
||||
setPage({ page: "error", error: "No station or user found" });
|
||||
}
|
||||
break;
|
||||
default:
|
||||
setPage({ page: "error", error: "Button now allowed" });
|
||||
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
return { handleButton };
|
||||
};
|
||||
64
apps/dispatch/app/(app)/pilot/_components/dme/useSounds.ts
Normal file
64
apps/dispatch/app/(app)/pilot/_components/dme/useSounds.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
"use client";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { getUserAPI } from "_querys/user";
|
||||
import { usePilotConnectionStore } from "_store/pilot/connectionStore";
|
||||
import { useDmeStore } from "_store/pilot/dmeStore";
|
||||
import { useSession } from "next-auth/react";
|
||||
import { useEffect, useRef } from "react";
|
||||
|
||||
export const useSounds = () => {
|
||||
const session = useSession();
|
||||
const { data: user } = useQuery({
|
||||
queryKey: ["user", session.data?.user.id],
|
||||
queryFn: () => getUserAPI(session.data!.user.id),
|
||||
});
|
||||
|
||||
const { page, setPage } = useDmeStore((state) => state);
|
||||
const mission = usePilotConnectionStore((state) => state.activeMission);
|
||||
|
||||
const newMissionSound = useRef<HTMLAudioElement | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof window !== "undefined") {
|
||||
newMissionSound.current = new Audio("/sounds/Melder3.wav");
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (user?.settingsDmeVolume) {
|
||||
if (newMissionSound.current) {
|
||||
newMissionSound.current.volume = user.settingsDmeVolume;
|
||||
}
|
||||
} else if (newMissionSound.current) {
|
||||
newMissionSound.current.volume = 0.8; // Default volume
|
||||
}
|
||||
}, [user?.settingsDmeVolume]);
|
||||
|
||||
useEffect(() => {
|
||||
const timeouts: NodeJS.Timeout[] = [];
|
||||
|
||||
if (page === "new-mission" && newMissionSound.current) {
|
||||
console.log("new-mission", mission);
|
||||
newMissionSound.current.currentTime = 0;
|
||||
newMissionSound.current.volume = 0.3;
|
||||
newMissionSound.current.play();
|
||||
if (mission) {
|
||||
timeouts.push(setTimeout(() => setPage({ page: "mission", mission }), 500));
|
||||
}
|
||||
} else if (page === "acknowledge") {
|
||||
newMissionSound.current?.pause();
|
||||
if (mission) {
|
||||
timeouts.push(setTimeout(() => setPage({ page: "mission", mission }), 500));
|
||||
} else {
|
||||
timeouts.push(
|
||||
setTimeout(() => setPage({ page: "error", error: "Einsatz nicht gebunden" }), 500),
|
||||
);
|
||||
}
|
||||
}
|
||||
return () => {
|
||||
timeouts.forEach((t) => {
|
||||
clearTimeout(t);
|
||||
});
|
||||
};
|
||||
}, [page, setPage, mission]);
|
||||
};
|
||||
Reference in New Issue
Block a user