Buchungen werden in Connect Modal angezeigt (Pilot), new Booking form improvement

This commit is contained in:
PxlLoewe
2025-09-28 12:19:14 +02:00
parent ebeb2cf93a
commit dc4a3ab4d8
4 changed files with 140 additions and 27 deletions

View File

@@ -6,9 +6,10 @@ import { useMutation, useQuery } from "@tanstack/react-query";
import { getStationsAPI } from "_querys/stations";
import { editConnectedAircraftAPI, getConnectedAircraftsAPI } from "_querys/aircrafts";
import { Prisma } from "@repo/db";
import { Button, getNextDateWithTime } from "@repo/shared-components";
import { Button, cn, getNextDateWithTime } from "@repo/shared-components";
import { Select } from "_components/Select";
import { Radio } from "lucide-react";
import { Calendar, Radio } from "lucide-react";
import { getBookingsAPI } from "_querys/bookings";
export const ConnectionBtn = () => {
const modalRef = useRef<HTMLDialogElement>(null);
@@ -27,6 +28,19 @@ export const ConnectionBtn = () => {
queryKey: ["stations"],
queryFn: () => getStationsAPI(),
});
const { data: bookings } = useQuery({
queryKey: ["bookings"],
queryFn: () =>
getBookingsAPI({
startTime: {
lte: new Date(Date.now() + 8 * 60 * 60 * 1000),
},
endTime: {
gte: new Date(),
},
}),
});
const aircraftMutation = useMutation({
mutationFn: ({
change,
@@ -62,6 +76,7 @@ export const ConnectionBtn = () => {
const session = useSession();
const uid = session.data?.user?.id;
if (!uid) return null;
console.log(bookings);
return (
<div className="rounded-box bg-base-200 flex items-center justify-center gap-2 p-1">
{connection.message.length > 0 && (
@@ -117,20 +132,39 @@ export const ConnectionBtn = () => {
(option as { component: React.ReactNode }).component
}
options={
stations?.map((station) => ({
value: station.id.toString(),
label: station.bosCallsign,
component: (
<div>
<span className="flex items-center gap-2">
{connectedAircrafts?.find((a) => a.stationId == station.id) && (
<Radio className="text-warning" size={15} />
)}
{station.bosCallsign}
</span>
</div>
),
})) ?? []
stations?.map((station) => {
const booking = bookings?.find((b) => b.stationId == station.id);
return {
value: station.id.toString(),
label: station.bosCallsign,
component: (
<div>
<span className="flex items-center gap-2">
{connectedAircrafts?.find((a) => a.stationId == station.id) && (
<Radio className="text-warning" size={15} />
)}
{booking && (
<div
className="tooltip tooltip-right"
data-tip={`${new Date(booking.startTime).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })} - ${new Date(booking.endTime).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })} Uhr gebucht von ${booking.userId == session.data?.user?.id ? "dir" : booking.User.fullName}`}
>
<Calendar
className={
cn(
"text-warning",
booking?.userId === session.data?.user?.id,
) && "text-success"
}
size={15}
/>
</div>
)}
{station.bosCallsign}
</span>
</div>
),
};
}) ?? []
}
/>
</div>

View File

@@ -0,0 +1,36 @@
import { Booking, Prisma, PublicUser, Station } from "@repo/db";
import axios from "axios";
export const getBookingsAPI = async (filter: Prisma.BookingWhereInput) => {
const res = await axios.get<
(Booking & {
Station: Station;
User: PublicUser;
})[]
>("/api/bookings", {
params: {
filter: JSON.stringify(filter),
},
});
if (res.status !== 200) {
throw new Error("Failed to fetch stations");
}
return res.data;
};
export const createBookingAPI = async (booking: Omit<Prisma.BookingCreateInput, "User">) => {
const response = await axios.post("/api/bookings", booking);
if (response.status !== 201) {
console.error("Error creating booking:", response);
throw new Error("Failed to create booking");
}
return response.data;
};
export const deleteBookingAPI = async (bookingId: string) => {
const response = await axios.delete(`/api/bookings/${bookingId}`);
if (!response.status.toString().startsWith("2")) {
throw new Error("Failed to delete booking");
}
return bookingId;
};

View File

@@ -0,0 +1,42 @@
import { getPublicUser, prisma } from "@repo/db";
import { getServerSession } from "api/auth/[...nextauth]/auth";
import { NextRequest, NextResponse } from "next/server";
export const GET = async (req: NextRequest) => {
try {
const session = await getServerSession();
if (!session?.user) {
return NextResponse.json({ error: "Not authenticated" }, { status: 401 });
}
const { searchParams } = req.nextUrl;
const filter = JSON.parse(searchParams.get("filter") || "{}");
const bookings = await prisma.booking.findMany({
where: filter,
include: {
User: true,
Station: {
select: {
id: true,
bosCallsign: true,
bosCallsignShort: true,
},
},
},
orderBy: {
startTime: "asc",
},
});
return NextResponse.json(
bookings.map((b) => ({
...b,
User: b.User ? getPublicUser(b.User) : null,
})),
);
} catch (error) {
console.error("Error fetching bookings:", error);
return NextResponse.json({ error: "Internal server error" }, { status: 500 });
}
};