This commit is contained in:
PxlLoewe
2025-06-03 13:45:44 -07:00
17 changed files with 7025 additions and 115 deletions

View File

@@ -10,8 +10,8 @@
},
"packageManager": "pnpm@10.11.0",
"devDependencies": {
"@repo/db": "*",
"@repo/typescript-config": "*",
"@repo/db": "workspace:*",
"@repo/typescript-config": "workspace:*",
"@types/cookie-parser": "^1.4.8",
"@types/cors": "^2.8.18",
"@types/express": "^5.0.2",

View File

@@ -1,13 +1,12 @@
"use client";
import { useLeftMenuStore } from "_store/leftMenuStore";
import { useSession } from "next-auth/react";
import { cn } from "_helpers/cn";
import { ListCollapse, Plane } from "lucide-react";
import { useQuery } from "@tanstack/react-query";
import { getMissionsAPI } from "_querys/missions";
import { MissionsOnStations, Station } from "@repo/db";
import { Station } from "@repo/db";
import { getConnectedAircraftsAPI } from "_querys/aircrafts";
import { FMS_STATUS_COLORS, FMS_STATUS_TEXT_COLORS } from "_components/map/AircraftMarker";
import { FMS_STATUS_COLORS, FMS_STATUS_TEXT_COLORS } from "_helpers/fmsStatusColors";
import { useMapStore } from "_store/mapStore";
import { useDispatchConnectionStore } from "_store/dispatch/connectionStore";
@@ -68,7 +67,7 @@ export const SituationBoard = () => {
{/* head */}
<thead>
<tr>
<th>ID</th>
<th>E-Nr.</th>
<th>Stichwort</th>
<th>Stadt</th>
<th>Stationen</th>
@@ -76,39 +75,42 @@ export const SituationBoard = () => {
</thead>
<tbody>
{/* row 1 */}
{missions?.map((mission) => (
<tr
onDoubleClick={() => {
setOpenMissionMarker({
open: [
{
id: mission.id,
tab: "home",
},
],
close: [],
});
setMap({
center: {
lat: mission.addressLat,
lng: mission.addressLng,
},
zoom: 14,
});
}}
key={mission.id}
className={cn(mission.state === "draft" && "bg-base-300")}
>
<td>{mission.publicId}</td>
<td>{mission.missionKeywordAbbreviation}</td>
<td>{mission.addressCity}</td>
<td>
{(mission as any).MissionsOnStations?.map(
(mos: { Station: Station }) => mos.Station?.bosCallsignShort,
).join(", ")}
</td>
</tr>
))}
{missions?.map(
(mission) =>
(dispatcherConnected || mission.state !== "draft") && (
<tr
onDoubleClick={() => {
setOpenMissionMarker({
open: [
{
id: mission.id,
tab: "home",
},
],
close: [],
});
setMap({
center: {
lat: mission.addressLat,
lng: mission.addressLng,
},
zoom: 14,
});
}}
key={mission.id}
className={cn(mission.state === "draft" && "missionListItem")}
>
<td>{mission.publicId}</td>
<td>{mission.missionKeywordAbbreviation}</td>
<td>{mission.addressCity}</td>
<td>
{(mission as any).MissionsOnStations?.map(
(mos: { Station: Station }) => mos.Station?.bosCallsignShort,
).join(", ")}
</td>
</tr>
),
)}
</tbody>
</table>
</div>

View File

@@ -16,53 +16,7 @@ import { useQuery } from "@tanstack/react-query";
import { getConnectedAircraftPositionLogAPI, getConnectedAircraftsAPI } from "_querys/aircrafts";
import { getMissionsAPI } from "_querys/missions";
import { checkSimulatorConnected } from "_helpers/simulatorConnected";
export const FMS_STATUS_COLORS: { [key: string]: string } = {
"0": "rgb(140,10,10)",
"1": "rgb(10,134,25)",
"2": "rgb(10,134,25)",
"3": "rgb(140,10,10)",
"4": "rgb(140,10,10)",
"5": "rgb(231,77,22)",
"6": "rgb(85,85,85)",
"7": "rgb(140,10,10)",
"8": "rgb(186,105,0)",
"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 } = {
"0": "rgb(243,27,25)",
"1": "rgb(9,212,33)",
"2": "rgb(9,212,33)",
"3": "rgb(243,27,25)",
"4": "rgb(243,27,25)",
"5": "rgb(251,176,158)",
"6": "rgb(153,153,153)",
"7": "rgb(243,27,25)",
"8": "rgb(255,143,0)",
"9": "rgb(9,212,33)",
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)",
};
import { FMS_STATUS_COLORS, FMS_STATUS_TEXT_COLORS } from "_helpers/fmsStatusColors";
const AircraftPopupContent = ({
aircraft,

View File

@@ -1,6 +1,6 @@
"use client";
import React, { useState } from "react";
import { FMS_STATUS_COLORS, FMS_STATUS_TEXT_COLORS } from "../AircraftMarker";
import { FMS_STATUS_COLORS, FMS_STATUS_TEXT_COLORS } from "_helpers/fmsStatusColors";
import {
ConnectedAircraft,
getPublicUser,

View File

@@ -3,7 +3,7 @@ import { useQuery } from "@tanstack/react-query";
import { SmartPopup, useSmartPopup } from "_components/SmartPopup";
import { useDispatchConnectionStore } from "_store/dispatch/connectionStore";
import { useMapStore } from "_store/mapStore";
import { FMS_STATUS_COLORS, FMS_STATUS_TEXT_COLORS } from "_components/map/AircraftMarker";
import { FMS_STATUS_COLORS, FMS_STATUS_TEXT_COLORS } from "_helpers/fmsStatusColors";
import { MISSION_STATUS_COLORS, MISSION_STATUS_TEXT_COLORS } from "_components/map/MissionMarkers";
import { cn } from "_helpers/cn";
import { checkSimulatorConnected } from "_helpers/simulatorConnected";

View File

@@ -1,6 +1,6 @@
"use client";
import React, { useEffect, useState } from "react";
import { FMS_STATUS_TEXT_COLORS } from "../AircraftMarker";
import { FMS_STATUS_TEXT_COLORS } from "_helpers/fmsStatusColors";
import { toast } from "react-hot-toast";
import {
Ban,

View File

@@ -8,12 +8,15 @@ export default function ModeSwitchDropdown() {
const path = usePathname();
return (
<details className="dropdown z-[9999]">
<summary className="btn m-1">
<div className="dropdown z-[9999]">
<div tabIndex={0} role="button" className="btn m-1">
<ArrowLeftRight /> {path.includes("pilot") && "Pilot"}
{path.includes("dispatch") && "Leitstelle"}
</summary>
<ul className="menu dropdown-content bg-base-100 rounded-box z-1 w-52 p-2 shadow-sm">
</div>
<ul
tabIndex={0}
className="menu dropdown-content bg-base-100 rounded-box z-1 w-52 p-2 shadow-sm"
>
<li>
<Link href={"/dispatch"}>
<Workflow /> Leitstelle
@@ -25,6 +28,6 @@ export default function ModeSwitchDropdown() {
</Link>
</li>
</ul>
</details>
</div>
);
}

View File

@@ -0,0 +1,46 @@
export const FMS_STATUS_COLORS: { [key: string]: string } = {
"0": "rgb(140,10,10)",
"1": "rgb(10,134,25)",
"2": "rgb(10,134,25)",
"3": "rgb(140,10,10)",
"4": "rgb(140,10,10)",
"5": "rgb(231,77,22)",
"6": "rgb(85,85,85)",
"7": "rgb(140,10,10)",
"8": "rgb(186,105,0)",
"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 } = {
"0": "rgb(243,27,25)",
"1": "rgb(9,212,33)",
"2": "rgb(9,212,33)",
"3": "rgb(243,27,25)",
"4": "rgb(243,27,25)",
"5": "rgb(251,176,158)",
"6": "rgb(153,153,153)",
"7": "rgb(243,27,25)",
"8": "rgb(255,143,0)",
"9": "rgb(9,212,33)",
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)",
};

View File

@@ -276,7 +276,7 @@ export const MissionForm = () => {
<>
<select
{...form.register("missionKeywordCategory")}
className="select select-primary select-bordered w-full"
className="select select-primary select-bordered w-full mb-4"
onChange={(e) => {
const firstKeyword = keywords?.find(
(k) => k.category === form.watch("missionKeywordCategory"),
@@ -305,7 +305,7 @@ export const MissionForm = () => {
)}
<select
{...form.register("missionKeywordAbbreviation")}
className="select select-primary select-bordered w-full"
className="select select-primary select-bordered w-full mb-4"
onChange={(e) => {
const keyword = keywords?.find((k) => k.abreviation === e.target.value);
form.setValue("missionKeywordName", keyword?.name || (null as any));
@@ -332,10 +332,10 @@ export const MissionForm = () => {
<div className="mb-4">
<select
{...form.register("hpgMissionString")}
className="select select-primary select-bordered w-full"
className="select select-primary select-bordered w-full mb-2"
value={form.watch("hpgMissionString") || ""}
>
<option disabled value="">
<option disabled value="please_select">
Einsatz Szenario auswählen...
</option>
{keywords &&

View File

@@ -56,3 +56,8 @@
.leaflet-popup-close-button {
display: none;
}
.missionListItem {
background-color: color-mix(in oklab, var(--color-info) 8%, var(--color-base-100));
color: var(--color-info, var(--color-base-content));
}

View File

@@ -43,6 +43,7 @@ export default async function RootLayout({
background: "var(--color-base-100)",
color: "var(--color-base-content)",
},
duration: 4000,
}}
position="top-left"
reverseOrder={false}

View File

@@ -26,7 +26,7 @@ export const ConnectedDispatcher = () => {
{/* <div className="collapse-title font-semibold">Kein Disponent Online</div> */}
<div className="collapse-title font-semibold flex items-center justify-between">
<span>
{connections} {connections > 1 ? "Verbundene Mitglieder" : "Verbundenes Mitglied"}
{connections} {connections == 1 ? "Verbundene Mitglieder" : "Verbundenes Mitglied"}
</span>
<div className="gap-2 flex items-center">
<div

View File

@@ -18,9 +18,9 @@
"@livekit/track-processors": "^0.5.7",
"@next-auth/prisma-adapter": "^1.0.7",
"@radix-ui/react-icons": "^1.3.2",
"@repo/db": "*",
"@repo/eslint-config": "*",
"@repo/typescript-config": "*",
"@repo/db": "workspace:*",
"@repo/eslint-config": "workspace:*",
"@repo/typescript-config": "workspace:*",
"@tailwindcss/postcss": "^4.1.8",
"@tanstack/react-query": "^5.79.0",
"@types/jsonwebtoken": "^9.0.9",

View File

@@ -14,8 +14,8 @@
},
"dependencies": {
"@react-email/components": "^0.0.41",
"@repo/db": "*",
"@repo/typescript-config": "*",
"@repo/db": "workspace:*",
"@repo/typescript-config": "workspace:*",
"@types/cors": "^2.8.18",
"@types/express": "^5.0.2",
"@types/node": "^22.15.29",

View File

@@ -33,6 +33,7 @@ import { ChartBarBigIcon, Check, Eye, PlaneIcon, Timer, X } from "lucide-react";
import Link from "next/link";
import { ColumnDef } from "@tanstack/react-table";
import { Error } from "_components/Error";
import { useSession } from "next-auth/react";
interface ProfileFormProps {
user: User;
@@ -40,6 +41,7 @@ interface ProfileFormProps {
export const ProfileForm: React.FC<ProfileFormProps> = ({ user }: ProfileFormProps) => {
const [isLoading, setIsLoading] = useState(false);
const session = useSession();
const form = useForm<UserOptionalDefaults>({
defaultValues: user,
resolver: zodResolver(UserOptionalDefaultsSchema),
@@ -131,6 +133,7 @@ export const ProfileForm: React.FC<ProfileFormProps> = ({ user }: ProfileFormPro
form={form}
name="permissions"
label="Permissions"
isDisabled={user.permissions.length > (session.data?.user?.permissions?.length ?? 0)}
options={Object.entries(PERMISSION).map(([key, value]) => ({
label: value,
value: key,

View File

@@ -13,9 +13,9 @@
"@hookform/resolvers": "^5.0.1",
"@next-auth/prisma-adapter": "^1.0.7",
"@radix-ui/react-icons": "^1.3.2",
"@repo/db": "*",
"@repo/eslint-config": "*",
"@repo/typescript-config": "*",
"@repo/db": "workspace:*",
"@repo/eslint-config": "workspace:*",
"@repo/typescript-config": "workspace:*",
"@tanstack/react-query": "^5.79.0",
"@tanstack/react-table": "^8.21.3",
"@uiw/react-md-editor": "^4.0.7",

6912
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff