Dispatch Router-Struktur; AddPenalty Layout gefixed

This commit is contained in:
PxlLoewe
2025-06-27 15:52:28 -07:00
parent 782ba7669d
commit 91ed14ac08
47 changed files with 168 additions and 179 deletions

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 610 KiB

View 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 };
};

View 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]);
};