feat: Implement connected user API and integrate chat and report components

- Added API routes for fetching connected users, keywords, missions, and stations.
- Created a new QueryProvider component for managing query states and socket events.
- Introduced connection stores for dispatch and pilot, managing socket connections and states.
- Updated Prisma schema for connected aircraft model.
- Enhanced UI with toast notifications for status updates and chat interactions.
- Implemented query functions for fetching connected users and keywords with error handling.
This commit is contained in:
PxlLoewe
2025-05-07 00:43:45 -07:00
parent 152b3d4689
commit 50f42e99d3
49 changed files with 1040 additions and 701 deletions

View File

@@ -1,28 +1,57 @@
"use client";
import { useSession } from "next-auth/react";
import { useDispatchConnectionStore } from "../../../_store/connectionStore";
import { useRef, useState } from "react";
import { useDispatchConnectionStore } from "../../../_store/pilot/connectionStore";
import { useEffect, useRef, useState } from "react";
import { useQuery } from "@tanstack/react-query";
import { getStationsAPI } from "querys/stations";
export const ConnectionBtn = () => {
const modalRef = useRef<HTMLDialogElement>(null);
const connection = useDispatchConnectionStore((state) => state);
const [form, setForm] = useState({
logoffTime: "",
selectedZone: "LST_01",
const [form, setForm] = useState<{
logoffTime: string | null;
selectedStationId: number | null;
}>({
logoffTime: null,
selectedStationId: null,
});
const { data: stations } = useQuery({
queryKey: ["stations"],
queryFn: () => getStationsAPI(),
});
useEffect(() => {
/* getStations().then((data) => {
setStations(data);
if (data[0]) {
setForm({
...form,
selectedStationId: data[0].id,
});
}
}); */
}, [connection.status, form]);
const session = useSession();
const uid = session.data?.user?.id;
if (!uid) return null;
return (
<>
{!connection.isConnected ? (
<div className="rounded-box bg-base-200 flex justify-center items-center gap-2 p-1">
{connection.message.length > 0 && (
<span className="mx-2 text-error">{connection.message}</span>
)}
{connection.status === "disconnected" && (
<button
className="btn btn-soft btn-info"
className="btn btn-sm btn-soft btn-info "
onClick={() => modalRef.current?.showModal()}
>
Verbinden
</button>
) : (
)}
{connection.status == "connected" && (
<button
className="btn btn-soft btn-success"
onClick={() => modalRef.current?.showModal()}
@@ -33,17 +62,38 @@ export const ConnectionBtn = () => {
<dialog ref={modalRef} className="modal">
<div className="modal-box flex flex-col items-center justify-center">
{connection.isConnected ? (
{connection.status == "connected" ? (
<h3 className="text-lg font-bold mb-5">
Verbunden als{" "}
<span className="text-info">
&lt;{connection.selectedZone}&gt;
&lt;{connection.selectedStation?.bosCallsign}&gt;
</span>
</h3>
) : (
<h3 className="text-lg font-bold mb-5">Als Disponent anmelden</h3>
)}
<fieldset className="fieldset w-full">
<label className="floating-label w-full text-base">
<span>Station</span>
<select
onChange={(e) =>
setForm({
...form,
selectedStationId: parseInt(e.target.value),
})
}
value={form.selectedStationId ?? ""}
className="input w-full"
>
{stations?.map((station) => (
<option key={station.id} value={station.id}>
{station.bosCallsign}
</option>
))}
</select>
</label>
</fieldset>
<fieldset className="fieldset w-full mt-2">
<label className="floating-label w-full text-base">
<span>Logoff Zeit (UTC+1)</span>
<input
@@ -53,12 +103,12 @@ export const ConnectionBtn = () => {
logoffTime: e.target.value,
})
}
value={form.logoffTime}
value={form.logoffTime ?? ""}
type="time"
className="input w-full"
/>
</label>
{!connection.isConnected && (
{connection.status == "disconnected" && (
<p className="fieldset-label">
Du kannst diese Zeit später noch anpassen.
</p>
@@ -67,7 +117,7 @@ export const ConnectionBtn = () => {
<div className="modal-action flex justify-between w-full">
<form method="dialog" className="w-full flex justify-between">
<button className="btn btn-soft">Abbrechen</button>
{connection.isConnected ? (
{connection.status == "connected" ? (
<button
className="btn btn-soft btn-error"
type="submit"
@@ -83,7 +133,16 @@ export const ConnectionBtn = () => {
type="submit"
onSubmit={() => false}
onClick={() => {
connection.connect(uid, form.selectedZone, form.logoffTime);
connection.connect(
uid,
form.selectedStationId?.toString() || "",
form.logoffTime || "",
stations?.find(
(station) =>
station.id ===
parseInt(form.selectedStationId?.toString() || ""),
)!,
);
}}
className="btn btn-soft btn-info"
>
@@ -94,7 +153,7 @@ export const ConnectionBtn = () => {
</div>
</div>
</dialog>
</>
</div>
);
};