From 6fbb8c49a88cfb84c25ef92775db5c5ffdece052 Mon Sep 17 00:00:00 2001 From: PxlLoewe <72106766+PxlLoewe@users.noreply.github.com> Date: Mon, 21 Jul 2025 11:43:29 -0700 Subject: [PATCH] Heliport Search, Station connection history table, reworked mission close functionality --- apps/core-server/modules/chron.ts | 106 ++++++-------- .../app/_components/navbar/Settings.tsx | 2 +- apps/hub/app/(app)/admin/heliport/page.tsx | 6 +- .../(app)/admin/station/_components/Form.tsx | 133 +++++++++++++++--- .../admin/user/[id]/_components/forms.tsx | 52 +++---- 5 files changed, 185 insertions(+), 114 deletions(-) diff --git a/apps/core-server/modules/chron.ts b/apps/core-server/modules/chron.ts index 7f8764db..8cfe33c6 100644 --- a/apps/core-server/modules/chron.ts +++ b/apps/core-server/modules/chron.ts @@ -2,6 +2,39 @@ import { MissionLog, NotificationPayload, prisma } from "@repo/db"; import { io } from "index"; import cron from "node-cron"; +const removeMission = async (id: number, reason: string) => { + const log: MissionLog = { + type: "completed-log", + auto: true, + timeStamp: new Date().toISOString(), + data: {}, + }; + + const updatedMission = await prisma.mission.update({ + where: { + id: id, + }, + data: { + state: "finished", + missionLog: { + push: log as any, + }, + }, + }); + io.to("dispatchers").emit("new-mission", { updatedMission }); + io.to("dispatchers").emit("notification", { + type: "mission-auto-close", + status: "chron", + message: `Einsatz ${updatedMission.publicId} wurde aufgrund ${reason} geschlossen.`, + data: { + missionId: updatedMission.id, + publicMissionId: updatedMission.publicId, + }, + } as NotificationPayload); + + console.log(`Mission ${updatedMission.id} closed due to inactivity.`); +}; + const removeClosedMissions = async () => { const oldMissions = await prisma.mission.findMany({ where: { @@ -15,18 +48,6 @@ const removeClosedMissions = async () => { const lastAlertTime = lastAlert ? new Date(lastAlert.timeStamp) : null; - const aircraftsInMission = await prisma.connectedAircraft.findMany({ - where: { - stationId: { - in: mission.missionStationIds, - }, - }, - }); - - const allConnectedAircraftsInIdleStatus = aircraftsInMission.every((a) => - ["1", "2", "6"].includes(a.fmsStatus), - ); - const allStationsInMissionChangedFromStatus4to1Or8to1 = mission.missionStationIds.every( (stationId) => { const status4Log = (mission.missionLog as unknown as MissionLog[]).findIndex((l) => { @@ -69,67 +90,24 @@ const removeClosedMissions = async () => { }, ); - const missionHastManualReactivation = (mission.missionLog as unknown as MissionLog[]).some( + const missionHasManualReactivation = (mission.missionLog as unknown as MissionLog[]).some( (l) => l.type === "reopened-log", ); - console.log({ - missionId: mission.publicId, - allConnectedAircraftsInIdleStatus, - lastAlertTime, - allStationsInMissionChangedFromStatus4to1Or8to1, - missionHastManualReactivation, - }); - if ( - !allConnectedAircraftsInIdleStatus // If some aircrafts are still active, do not close the mission - ) - return; - const now = new Date(); + if (missionHasManualReactivation) return; + if (!lastAlertTime) return; // Case 1: Forgotten Mission, last alert more than 3 Hours ago - // Case 2: All stations in mission changed from status 4 to 1 or from status 8 to 1 - if ( - !( - now.getTime() - lastAlertTime.getTime() > 1000 * 60 * 180 || - allStationsInMissionChangedFromStatus4to1Or8to1 - ) || - missionHastManualReactivation - ) - return; + const now = new Date(); + if (now.getTime() - lastAlertTime.getTime() > 1000 * 60 * 180) + return removeMission(mission.id, "inaktivität"); - const log: MissionLog = { - type: "completed-log", - auto: true, - timeStamp: new Date().toISOString(), - data: {}, - }; - - const updatedMission = await prisma.mission.update({ - where: { - id: mission.id, - }, - data: { - state: "finished", - missionLog: { - push: log as any, - }, - }, - }); - io.to("dispatchers").emit("new-mission", { updatedMission }); - io.to("dispatchers").emit("notification", { - type: "mission-auto-close", - status: "chron", - message: `Einsatz ${updatedMission.publicId} wurde aufgrund ${allStationsInMissionChangedFromStatus4to1Or8to1 ? "des Freimeldens aller Stationen" : "von Inaktivität"} geschlossen.`, - data: { - missionId: updatedMission.id, - publicMissionId: updatedMission.publicId, - }, - } as NotificationPayload); - console.log(`Mission ${mission.id} closed due to inactivity.`); + // Case 2: All stations in mission changed from status 4 to 1/6 or from status 8 to 1/6 + if (allStationsInMissionChangedFromStatus4to1Or8to1) + return removeMission(mission.id, "dem freimelden aller Stationen"); }); }; - const removeConnectedAircrafts = async () => { const connectedAircrafts = await prisma.connectedAircraft.findMany({ where: { diff --git a/apps/dispatch/app/_components/navbar/Settings.tsx b/apps/dispatch/app/_components/navbar/Settings.tsx index 07a3bbd7..15f42bbb 100644 --- a/apps/dispatch/app/_components/navbar/Settings.tsx +++ b/apps/dispatch/app/_components/navbar/Settings.tsx @@ -225,7 +225,7 @@ export const SettingsBtn = () => {
{
+
diff --git a/apps/hub/app/(app)/admin/station/_components/Form.tsx b/apps/hub/app/(app)/admin/station/_components/Form.tsx
index a6e2d8eb..207fae6a 100644
--- a/apps/hub/app/(app)/admin/station/_components/Form.tsx
+++ b/apps/hub/app/(app)/admin/station/_components/Form.tsx
@@ -2,20 +2,26 @@
import { zodResolver } from "@hookform/resolvers/zod";
import { StationOptionalDefaultsSchema } from "@repo/db/zod";
import { useForm } from "react-hook-form";
-import { BosUse, Country, Station } from "@repo/db";
-import { FileText, LocateIcon, PlaneIcon } from "lucide-react";
+import { BosUse, ConnectedAircraft, Country, Station, User } from "@repo/db";
+import { FileText, LocateIcon, PlaneIcon, UserIcon } from "lucide-react";
import { Input } from "../../../../_components/ui/Input";
-import { useState } from "react";
import { deleteStation, upsertStation } from "../action";
import { Button } from "../../../../_components/ui/Button";
import { redirect } from "next/navigation";
import toast from "react-hot-toast";
+import { PaginatedTable, PaginatedTableRef } from "_components/PaginatedTable";
+import { ColumnDef } from "@tanstack/react-table";
+import Link from "next/link";
+import { deletePilotHistory } from "(app)/admin/user/action";
+import { useRef } from "react";
+import { cn } from "@repo/shared-components";
export const StationForm = ({ station }: { station?: Station }) => {
const form = useForm({
resolver: zodResolver(StationOptionalDefaultsSchema),
defaultValues: station,
});
+ const dispoTableRef = useRef {form.formState.errors.firstname.message} Berechtigung Schnellauswahl
-
{
/>
-
-
{
/>
-