Files
var-monorepo/apps/dispatch/app/_components/left/Report.tsx
2025-06-30 16:38:57 +02:00

161 lines
5.1 KiB
TypeScript

"use client";
import { ExclamationTriangleIcon, PaperPlaneIcon } from "@radix-ui/react-icons";
import { useSession } from "next-auth/react";
import { useEffect, useState } from "react";
import { cn } from "@repo/shared-components";
import { toast } from "react-hot-toast";
import { useLeftMenuStore } from "_store/leftMenuStore";
import { asPublicUser } from "@repo/db";
import { useQuery } from "@tanstack/react-query";
import { getConnectedDispatcherAPI } from "_querys/dispatcher";
import { sendReportAPI } from "_querys/report";
import { getConnectedAircraftsAPI } from "_querys/aircrafts";
export const Report = () => {
const { setChatOpen, setReportTabOpen, reportTabOpen, setOwnId } = useLeftMenuStore();
const [sending, setSending] = useState(false);
const session = useSession();
const [selectedPlayer, setSelectedPlayer] = useState<string>("default");
const [message, setMessage] = useState<string>("");
useEffect(() => {
if (!session.data?.user.id) return;
setOwnId(session.data.user.id);
}, [session, setOwnId]);
const { data: dispatcher } = useQuery({
queryKey: ["dispatcher"],
queryFn: () => getConnectedDispatcherAPI(),
refetchInterval: 10000,
});
const { data: aircrafts } = useQuery({
queryKey: ["aircrafts"],
queryFn: () => getConnectedAircraftsAPI(),
refetchInterval: 10000,
});
const filteredDispatcher = dispatcher?.filter((d) => d.userId !== session.data?.user.id);
const filteredAircrafts = aircrafts?.filter((a) => a.userId !== session.data?.user.id);
return (
<div
className={cn("dropdown dropdown-right dropdown-center", reportTabOpen && "dropdown-open")}
>
<div className="indicator">
<button
className="btn btn-soft btn-sm btn-error"
onClick={() => {
setChatOpen(false);
setReportTabOpen(!reportTabOpen);
}}
>
<ExclamationTriangleIcon className="w-4 h-4" />
</button>
</div>
{reportTabOpen && (
<div
tabIndex={0}
className="dropdown-content card bg-base-200 w-150 shadow-md z-[1100] ml-2 border-1 border-error"
>
<div className="card-body">
<button
className="absolute top-2 right-2 btn btn-xs btn-circle btn-ghost"
onClick={() => setReportTabOpen(false)}
type="button"
>
<span className="text-xl leading-none">&times;</span>
</button>
<h2 className="inline-flex items-center gap-2 text-lg font-bold mb-2">
<ExclamationTriangleIcon /> Report senden
</h2>
<div className="join">
<select
className="select select-sm w-full"
value={selectedPlayer}
onChange={(e) => setSelectedPlayer(e.target.value)}
>
{!filteredDispatcher?.length && !filteredAircrafts?.length && (
<option disabled value="default">
Keine Nutzer gefunden
</option>
)}
{(filteredDispatcher?.length || filteredAircrafts?.length) && (
<option disabled value="default">
Nutzer auswählen
</option>
)}
{filteredDispatcher?.map((dispatcher) => (
<option key={dispatcher.userId} value={dispatcher.userId}>
{dispatcher.zone} - {asPublicUser(dispatcher.publicUser).fullName}
</option>
))}
{filteredAircrafts?.map((aircraft) => (
<option key={aircraft.userId} value={aircraft.userId}>
{aircraft.Station.bosCallsignShort} -{" "}
{asPublicUser(aircraft.publicUser).fullName}
</option>
))}
</select>
</div>
<div className="join mt-4">
<div className="w-full">
<label className="input join-item w-full">
<input
type="text"
required
className="w-full"
placeholder="Nachricht eingeben"
onChange={(e) => setMessage(e.target.value)}
value={message}
/>
</label>
</div>
<button
className="btn btn-soft join-item"
onClick={(e) => {
e.preventDefault();
if (message.length < 1 || !selectedPlayer) return;
const selectedDispatcher = filteredDispatcher?.find(
(d) => d.userId === selectedPlayer,
);
const dispatcher = selectedDispatcher ? selectedDispatcher.zone : null;
const selectedAircraft = filteredAircrafts?.find(
(a) => a.userId === selectedPlayer,
);
const pilot = selectedAircraft ? selectedAircraft.Station.bosCallsignShort : null;
setSending(true);
sendReportAPI({
text: message,
senderUserId: session.data!.user.id,
reportedUserId: selectedPlayer,
reportedUserRole: dispatcher ?? pilot ?? "Offline",
})
.then(() => {
toast.success("Report gesendet");
setMessage("");
setSending(false);
})
.catch((err) => {
toast.error(`Fehler beim Senden des Reports: ${err}`);
setSending(false);
});
}}
disabled={sending}
>
{sending ? (
<span className="loading loading-spinner loading-sm"></span>
) : (
<PaperPlaneIcon />
)}
</button>
</div>
</div>
</div>
)}
</div>
);
};