StationStatus Toast hinzugefügt #45

This commit is contained in:
PxlLoewe
2025-07-07 01:55:45 -07:00
parent 7682f191c7
commit 9e4a46c595
13 changed files with 170 additions and 140 deletions

View File

@@ -2,7 +2,7 @@
"use client";
import { toast } from "react-hot-toast";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { QueryClient, QueryClientProvider, useQuery } from "@tanstack/react-query";
import { ReactNode, useEffect, useState } from "react";
import { dispatchSocket } from "(app)/dispatch/socket";
import { Mission, NotificationPayload } from "@repo/db";
@@ -10,9 +10,11 @@ import { HPGnotificationToast } from "_components/customToasts/HPGnotification";
import { useMapStore } from "_store/mapStore";
import { AdminMessageToast } from "_components/customToasts/AdminMessage";
import { pilotSocket } from "(app)/pilot/socket";
import { StatusToast } from "_components/customToasts/StationStatusToast";
export function QueryProvider({ children }: { children: ReactNode }) {
const mapStore = useMapStore((s) => s);
const [queryClient] = useState(
() =>
new QueryClient({
@@ -73,6 +75,12 @@ export function QueryProvider({ children }: { children: ReactNode }) {
duration: 999999,
});
break;
case "station-status":
if (notification.status !== "5") return;
toast.custom((e) => <StatusToast event={notification} t={e} />, {
duration: 99999999 /* 30000 */,
});
break;
default:
toast("unbekanntes Notification-Event");
break;

View File

@@ -1,117 +1,102 @@
import { useState } from "react";
import { toast } from "react-hot-toast";
import { Prisma, StationStatus } from "@repo/db";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { BaseNotification } from "_components/customToasts/BaseNotification";
import { FMS_STATUS_COLORS } from "_helpers/fmsStatusColors";
import { editConnectedAircraftAPI, getConnectedAircraftsAPI } from "_querys/aircrafts";
import { getStationsAPI } from "_querys/stations";
import { useMapStore } from "_store/mapStore";
import { X } from "lucide-react";
import { Toast, toast } from "react-hot-toast";
interface ToastCard {
id: number;
title: string;
content: string;
}
const MapToastCard2 = () => {
const [cards, setCards] = useState<ToastCard[]>([]);
const [openCardId, setOpenCardId] = useState<number | null>(null);
const addCard = () => {
const newCard: ToastCard = {
id: Date.now(),
title: `Einsatz #${cards.length + 1}`,
content: `Inhalt von Einsatz #${cards.length + 1}.`,
};
setCards([...cards, newCard]);
// DEBUG
/* toast("😖 Christoph 31 sendet Status 4", {
duration: 10000,
}); */
// DEBUG
const toastId = toast.custom(
<div
style={{
display: "flex",
alignItems: "center",
lineHeight: 1.3,
willChange: "transform",
boxShadow:
"0 3px 10px rgba(0, 0, 0, 0.1), 0 3px 3px rgba(0, 0, 0, 0.05)",
maxWidth: "350px",
pointerEvents: "auto",
padding: "8px 10px",
borderRadius: "8px",
background: "var(--color-base-100)",
color: "var(--color-base-content)",
}}
>
<div
className="toastText flex items-center"
style={{
display: "flex",
justifyContent: "center",
margin: "4px 10px",
color: "inherit",
flex: "1 1 auto",
whiteSpace: "pre-line",
}}
>
😖 Christoph 31 sendet Status 5{" "}
<button
className="btn btn-sm btn-soft btn-accent ml-2"
onClick={() => toast.remove(toastId)}
>
U
</button>
</div>
</div>,
{
duration: 999999999,
},
);
// DEBUG
};
const removeCard = (id: number) => {
setCards(cards.filter((card) => card.id !== id));
};
const toggleCard = (id: number) => {
setOpenCardId(openCardId === id ? null : id);
};
return (
<div className="absolute top-4 right-4 z-[1000] flex flex-col space-y-4">
{/* DEBUG */}
<button
onClick={addCard}
className="mb-4 p-2 bg-blue-500 text-white rounded self-end"
>
Debug Einsatz
</button>
{/* DEBUG */}
{cards.map((card) => (
<div
key={card.id}
className="collapse collapse-arrow bg-base-100 border-base-300 border w-120 relative"
>
<input
type="checkbox"
className="absolute top-0 left-0 opacity-0"
checked={openCardId === card.id}
onChange={() => toggleCard(card.id)}
/>
<div className="collapse-title font-semibold flex justify-between items-center">
<span>{card.title}</span>
<button
className="btn btn-sm btn-circle btn-ghost z-10 absolute top-3.5 right-8"
onClick={(e) => {
removeCard(card.id);
}}
>
</button>
</div>
<div className="collapse-content text-sm">{card.content}</div>
</div>
))}
</div>
);
const QUICK_RESPONSE: Record<string, string[]> = {
"5": ["J", "c"],
};
export default MapToastCard2;
export const StatusToast = ({ event, t }: { event: StationStatus; t: Toast }) => {
const mapStore = useMapStore((s) => s);
const { data: connectedAircrafts } = useQuery({
queryKey: ["aircrafts"],
queryFn: () => getConnectedAircraftsAPI(),
refetchInterval: 10000,
});
const { data: stations } = useQuery({
queryKey: ["stations"],
queryFn: () => getStationsAPI(),
});
const queryClient = useQueryClient();
const changeAircraftMutation = useMutation({
mutationFn: async ({
id,
update,
}: {
id: number;
update: Prisma.ConnectedAircraftUpdateInput;
}) => {
await editConnectedAircraftAPI(id, update);
queryClient.invalidateQueries({
queryKey: ["aircrafts"],
});
},
});
const connectedAircraft = connectedAircrafts?.find((a) => a.id === event.data?.aircraftId);
const station = stations?.find((s) => s.id === event.data?.stationId);
if (!connectedAircraft || !station) return null;
return (
<BaseNotification>
<div className="flex flex-row gap-14 items-center">
<p>
<span
className="underline mr-1 cursor-pointer font-bold"
onClick={() => {
if (!connectedAircraft.posLat || !connectedAircraft.posLng) return;
mapStore.setOpenAircraftMarker({
open: [{ id: connectedAircraft.id, tab: "fms" }],
close: [],
});
mapStore.setMap({
center: [connectedAircraft.posLat, connectedAircraft.posLng],
zoom: 14,
});
}}
>
{station.bosCallsign}
</span>
sendet Status {connectedAircraft.fmsStatus}
</p>
<div className="flex gap-2 items-center">
{QUICK_RESPONSE[String(connectedAircraft.fmsStatus)]?.map((status) => (
<button
key={status}
className={
"flex justify-center items-center min-w-10 min-h-10 cursor-pointer text-lg font-bold"
}
style={{
backgroundColor: FMS_STATUS_COLORS[status],
color: "white",
}}
onClick={async () => {
await changeAircraftMutation.mutateAsync({
id: connectedAircraft.id,
update: {
fmsStatus: status,
},
});
toast.remove(t.id);
toast.success(`Status auf ${status} geändert`);
}}
>
{status}
</button>
))}
<button className="btn btn-ghost btn-sm" onClick={() => toast.remove(t.id)}>
<X size={16} />
</button>
</div>
</div>
</BaseNotification>
);
};

View File

@@ -180,7 +180,7 @@ const FMSStatusSelector = ({
fmsStatus: status,
},
});
toast.success(`Status changed to ${status}`);
toast.success(`Status auf ${status} geändert`);
}}
>
{status}
@@ -219,7 +219,6 @@ const FMSStatusSelector = ({
fmsStatus: status,
},
});
toast.success(`Status changed to ${status}`);
}}
>
{status}