Files
var-monorepo/apps/dispatch/app/_components/left/Report.tsx
2025-06-13 20:09:13 -07:00

150 lines
4.7 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 "_helpers/cn";
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">
<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 dispatcher = filteredDispatcher?.find((d) => d.userId === selectedPlayer)
? "Disponent"
: null;
const pilot = filteredAircrafts?.find((a) => a.userId === selectedPlayer)
? "Pilot"
: 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>
);
};