diff --git a/apps/dispatch-server/routes/aircraft.ts b/apps/dispatch-server/routes/aircraft.ts index fa665438..c3ff5d44 100644 --- a/apps/dispatch-server/routes/aircraft.ts +++ b/apps/dispatch-server/routes/aircraft.ts @@ -2,7 +2,6 @@ import { AdminMessage, getPublicUser, MissionLog, - MissionSdsStatusLog, NotificationPayload, Prisma, prisma, @@ -131,44 +130,6 @@ router.patch("/:id", async (req, res) => { } }); -router.post("/:id/send-sds-message", async (req, res) => { - const { id } = req.params; - const { sdsMessage } = req.body as { sdsMessage: MissionSdsStatusLog }; - - if (!sdsMessage.data.stationId || !id) { - res.status(400).json({ error: "Missing aircraftId or stationId" }); - return; - } - - await prisma.mission.updateMany({ - where: { - state: "running", - missionStationIds: { - has: sdsMessage.data.stationId, - }, - }, - data: { - missionLog: { - push: sdsMessage as unknown as Prisma.InputJsonValue, - }, - }, - }); - - io.to( - sdsMessage.data.direction === "to-lst" ? "dispatchers" : `station:${sdsMessage.data.stationId}`, - ).emit(sdsMessage.data.direction === "to-lst" ? "notification" : "sds-status", { - type: "station-status", - status: sdsMessage.data.status, - message: "SDS Status Message", - data: { - aircraftId: parseInt(id), - stationId: sdsMessage.data.stationId, - }, - } as NotificationPayload); - - res.sendStatus(204); -}); - // Kick a connectedAircraft by ID router.delete("/:id", async (req, res) => { const { id } = req.params; diff --git a/apps/dispatch/Dockerfile b/apps/dispatch/Dockerfile index 1236c9d6..315d8d76 100644 --- a/apps/dispatch/Dockerfile +++ b/apps/dispatch/Dockerfile @@ -1,12 +1,12 @@ FROM node:22-alpine AS base -ARG NEXT_PUBLIC_DISPATCH_URL="http://localhost:3001" -ARG NEXT_PUBLIC_DISPATCH_SERVER_URL="http://localhost:4001" -ARG NEXT_PUBLIC_HUB_URL="http://localhost:3002" -ARG NEXT_PUBLIC_DISPATCH_SERVICE_ID="1" -ARG NEXT_PUBLIC_LIVEKIT_URL="http://localhost:7880" -ARG NEXT_PUBLIC_DISCORD_URL="https://discord.com" -ARG NEXT_PUBLIC_OPENAIP_ACCESS="" +ARG NEXT_PUBLIC_DISPATCH_URL +ARG NEXT_PUBLIC_DISPATCH_SERVER_URL +ARG NEXT_PUBLIC_HUB_URL +ARG NEXT_PUBLIC_DISPATCH_SERVICE_ID +ARG NEXT_PUBLIC_LIVEKIT_URL +ARG NEXT_PUBLIC_DISCORD_URL +ARG NEXT_PUBLIC_OPENAIP_ACCESS ENV NEXT_PUBLIC_DISPATCH_SERVER_URL=$NEXT_PUBLIC_DISPATCH_SERVER_URL ENV NEXT_PUBLIC_DISPATCH_URL=$NEXT_PUBLIC_DISPATCH_URL @@ -16,13 +16,13 @@ ENV NEXT_PUBLIC_LIVEKIT_URL=$NEXT_PUBLIC_LIVEKIT_URL ENV NEXT_PUBLIC_OPENAIP_ACCESS=$NEXT_PUBLIC_OPENAIP_ACCESS ENV NEXT_PUBLIC_DISCORD_URL=$NEXT_PUBLIC_DISCORD_URL -FROM base AS builder - ENV PNPM_HOME="/usr/local/pnpm" ENV PATH="${PNPM_HOME}:${PATH}" RUN corepack enable && corepack prepare pnpm@latest --activate RUN pnpm add -g turbo@^2.5 + +FROM base AS builder RUN apk update RUN apk add --no-cache libc6-compat @@ -31,20 +31,12 @@ WORKDIR /usr/app RUN echo "NEXT_PUBLIC_HUB_URL is: $NEXT_PUBLIC_HUB_URL" RUN echo "NEXT_PUBLIC_DISPATCH_SERVICE_ID is: $NEXT_PUBLIC_DISPATCH_SERVICE_ID" RUN echo "NEXT_PUBLIC_DISPATCH_SERVER_URL is: $NEXT_PUBLIC_DISPATCH_SERVER_URL" -RUN echo "NEXT_PUBLIC_LIVEKIT_URL is: $NEXT_PUBLIC_LIVEKIT_URL" COPY . . RUN turbo prune dispatch --docker FROM base AS installer - -ENV PNPM_HOME="/usr/local/pnpm" -ENV PATH="${PNPM_HOME}:${PATH}" -RUN corepack enable && corepack prepare pnpm@latest --activate - -RUN pnpm add -g turbo@^2.5 - RUN apk update RUN apk add --no-cache libc6-compat @@ -58,22 +50,19 @@ COPY --from=builder /usr/app/out/full/ . RUN turbo run build -FROM node:22-alpine AS runner +FROM base AS runner WORKDIR /usr/app # Don't run production as root RUN addgroup --system --gid 1001 nodejs RUN adduser --system --uid 1001 nextjs +USER nextjs # Automatically leverage output traces to reduce image size # https://nextjs.org/docs/advanced-features/output-file-tracing -COPY --from=installer --chown=nextjs:nodejs /usr/app/apps/dispatch/.next/standalone ./ -COPY --from=installer --chown=nextjs:nodejs /usr/app/apps/dispatch/.next/static ./apps/dispatch/.next/static -COPY --from=installer --chown=nextjs:nodejs /usr/app/apps/dispatch/public ./apps/dispatch/public - -USER nextjs +COPY --from=installer --chown=nextjs:nodejs /usr/app/ ./ # Expose the application port -EXPOSE 3000 +EXPOSE 3001 -CMD ["node", "apps/dispatch/server.js"] \ No newline at end of file +CMD ["pnpm", "--dir", "apps/dispatch", "run", "start"] \ No newline at end of file diff --git a/apps/dispatch/app/(app)/dispatch/_components/navbar/_components/Connection.tsx b/apps/dispatch/app/(app)/dispatch/_components/navbar/_components/Connection.tsx index 039d7ac2..f1450f19 100644 --- a/apps/dispatch/app/(app)/dispatch/_components/navbar/_components/Connection.tsx +++ b/apps/dispatch/app/(app)/dispatch/_components/navbar/_components/Connection.tsx @@ -14,7 +14,7 @@ export const ConnectionBtn = () => { const connection = useDispatchConnectionStore((state) => state); const [form, setForm] = useState({ logoffTime: "", - selectedZone: "VAR_LST_RD_01", + selectedZone: "LST_01", ghostMode: false, }); const changeDispatcherMutation = useMutation({ diff --git a/apps/dispatch/app/(app)/pilot/_components/mrt/Base.tsx b/apps/dispatch/app/(app)/pilot/_components/mrt/Base.tsx deleted file mode 100644 index 169b7d24..00000000 --- a/apps/dispatch/app/(app)/pilot/_components/mrt/Base.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { useEffect } from "react"; // ...existing code... -import { useMrtStore } from "_store/pilot/MrtStore"; -import Image from "next/image"; -import DAY_BASE_IMG from "./images/Base_NoScreen_Day.png"; -import NIGHT_BASE_IMG from "./images/Base_NoScreen_Night.png"; - -export const MrtBase = () => { - const { nightMode, setNightMode, page } = useMrtStore((state) => state); - - useEffect(() => { - const checkNightMode = () => { - const currentHour = new Date().getHours(); - setNightMode(currentHour >= 22 || currentHour < 8); - }; - - checkNightMode(); // Initial check - const intervalId = setInterval(checkNightMode, 60000); // Check every minute - - return () => clearInterval(intervalId); // Cleanup on unmount - }, [setNightMode]); // ...existing code... - - return ( - - ); -}; diff --git a/apps/dispatch/app/(app)/pilot/_components/mrt/MRT.png b/apps/dispatch/app/(app)/pilot/_components/mrt/MRT.png new file mode 100644 index 00000000..a9c552b1 Binary files /dev/null and b/apps/dispatch/app/(app)/pilot/_components/mrt/MRT.png differ diff --git a/apps/dispatch/app/(app)/pilot/_components/mrt/MRT_MESSAGE.png b/apps/dispatch/app/(app)/pilot/_components/mrt/MRT_MESSAGE.png new file mode 100644 index 00000000..a0e80ae6 Binary files /dev/null and b/apps/dispatch/app/(app)/pilot/_components/mrt/MRT_MESSAGE.png differ diff --git a/apps/dispatch/app/(app)/pilot/_components/mrt/Mrt.tsx b/apps/dispatch/app/(app)/pilot/_components/mrt/Mrt.tsx index 0fda6281..5d271921 100644 --- a/apps/dispatch/app/(app)/pilot/_components/mrt/Mrt.tsx +++ b/apps/dispatch/app/(app)/pilot/_components/mrt/Mrt.tsx @@ -1,9 +1,22 @@ import { CSSProperties } from "react"; +import MrtImage from "./MRT.png"; +import MrtMessageImage from "./MRT_MESSAGE.png"; +import { useButtons } from "./useButtons"; +import { useSounds } from "./useSounds"; import "./mrt.css"; -import { MrtBase } from "./Base"; -import { MrtDisplay } from "./MrtDisplay"; -import { MrtButtons } from "./MrtButtons"; -import { MrtPopups } from "./MrtPopups"; +import Image from "next/image"; +import { useMrtStore } from "_store/pilot/MrtStore"; + +const MRT_BUTTON_STYLES: CSSProperties = { + cursor: "pointer", + zIndex: "9999", + backgroundColor: "transparent", + border: "none", +}; +const MRT_DISPLAYLINE_STYLES: CSSProperties = { + color: "white", + zIndex: 1, +}; export interface DisplayLineProps { lineStyle?: CSSProperties; @@ -14,7 +27,45 @@ export interface DisplayLineProps { textSize: "1" | "2" | "3" | "4"; } +const DisplayLine = ({ + style = {}, + textLeft, + textMid, + textRight, + textSize, + lineStyle, +}: DisplayLineProps) => { + const INNER_TEXT_PARTS: CSSProperties = { + fontFamily: "Melder", + flex: "1", + flexBasis: "auto", + overflowWrap: "break-word", + ...lineStyle, + }; + + return ( +
+ {textLeft} + {textMid} + {textRight} +
+ ); +}; + export const Mrt = () => { + useSounds(); + const { handleButton } = useButtons(); + const { lines, page } = useMrtStore((state) => state); + return (
{ maxHeight: "100%", maxWidth: "100%", color: "white", - gridTemplateColumns: - "9.75% 4.23% 8.59% 7.30% 1.16% 7.30% 1.23% 7.16% 1.09% 7.30% 3.68% 4.23% 5.59% 6.07% 1.91% 6.07% 1.84% 6.21% 9.28%", - gridTemplateRows: - "21.55% 11.83% 3.55% 2.50% 9.46% 2.76% 0.66% 4.99% 6.83% 3.55% 1.97% 9.99% 4.20% 11.04% 5.12%", + gridTemplateColumns: "21.83% 4.43% 24.42% 18.08% 5.93% 1.98% 6.00% 1.69% 6.00% 9.35%", + gridTemplateRows: "21.58% 11.87% 3.55% 5.00% 6.84% 0.53% 3.03% 11.84% 3.55% 11.84% 20.39%", }} > - - - - + {page !== "sds" && ( + MrtImage + )} + {page === "sds" && ( + MrtImage-Message + )} + +
); }; diff --git a/apps/dispatch/app/(app)/pilot/_components/mrt/MrtButtons.tsx b/apps/dispatch/app/(app)/pilot/_components/mrt/MrtButtons.tsx deleted file mode 100644 index a7942466..00000000 --- a/apps/dispatch/app/(app)/pilot/_components/mrt/MrtButtons.tsx +++ /dev/null @@ -1,150 +0,0 @@ -import { CSSProperties, useRef } from "react"; -import { useButtons } from "./useButtons"; - -const MRT_BUTTON_STYLES: CSSProperties = { - cursor: "pointer", - zIndex: "9999", - backgroundColor: "transparent", - border: "none", -}; - -interface MrtButtonProps { - onClick: () => void; - onHold?: () => void; - style: CSSProperties; -} - -const MrtButton = ({ onClick, onHold, style }: MrtButtonProps) => { - const timeoutRef = useRef(null); - - const handleMouseDown = () => { - if (!onHold) return; - timeoutRef.current = setTimeout(handleTimeoutExpired, 500); - }; - - const handleTimeoutExpired = () => { - timeoutRef.current = null; - if (onHold) { - onHold(); - } - }; - - const handleMouseUp = () => { - if (timeoutRef.current) { - clearTimeout(timeoutRef.current); - onClick(); - } - }; - - return ( - ))} diff --git a/apps/dispatch/app/_components/QueryProvider.tsx b/apps/dispatch/app/_components/QueryProvider.tsx index 345d2fb1..d5b2799a 100644 --- a/apps/dispatch/app/_components/QueryProvider.tsx +++ b/apps/dispatch/app/_components/QueryProvider.tsx @@ -63,15 +63,14 @@ export function QueryProvider({ children }: { children: ReactNode }) { }; const handleNotification = (notification: NotificationPayload) => { - console.log("Received notification:", notification); const playNotificationSound = () => { if (notificationSound.current) { - notificationSound.current.currentTime = 0; - notificationSound.current - .play() - .catch((e) => console.error("Notification sound error:", e)); - } - }; + notificationSound.current.currentTime = 0; + notificationSound.current + .play() + .catch((e) => console.error("Notification sound error:", e)); + } + } switch (notification.type) { case "hpg-validation": @@ -91,7 +90,6 @@ export function QueryProvider({ children }: { children: ReactNode }) { }); break; case "station-status": - console.log("station Status", QUICK_RESPONSE[notification.status]); if (!QUICK_RESPONSE[notification.status]) return; toast.custom((e) => , { duration: 60000, @@ -108,7 +106,7 @@ export function QueryProvider({ children }: { children: ReactNode }) { break; case "mission-closed": toast("Dein aktueller Einsatz wurde geschlossen."); - + break; default: toast("unbekanntes Notification-Event"); diff --git a/apps/dispatch/app/_components/customToasts/StationStatusToast.tsx b/apps/dispatch/app/_components/customToasts/StationStatusToast.tsx index a3d3b64a..0b163e79 100644 --- a/apps/dispatch/app/_components/customToasts/StationStatusToast.tsx +++ b/apps/dispatch/app/_components/customToasts/StationStatusToast.tsx @@ -1,16 +1,14 @@ -import { getPublicUser, MissionSdsStatusLog, StationStatus } from "@repo/db"; +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 { getConnectedAircraftsAPI } from "_querys/aircrafts"; +import { editConnectedAircraftAPI, getConnectedAircraftsAPI } from "_querys/aircrafts"; import { getLivekitRooms } from "_querys/livekit"; -import { sendSdsStatusMessageAPI } from "_querys/missions"; import { getStationsAPI } from "_querys/stations"; import { useAudioStore } from "_store/audioStore"; import { useMapStore } from "_store/mapStore"; import { X } from "lucide-react"; -import { useSession } from "next-auth/react"; -import { useEffect, useRef } from "react"; +import { useEffect, useRef, useState } from "react"; import { Toast, toast } from "react-hot-toast"; export const QUICK_RESPONSE: Record = { @@ -24,8 +22,6 @@ export const StatusToast = ({ event, t }: { event: StationStatus; t: Toast }) => const status5Sounds = useRef(null); const status9Sounds = useRef(null); - const session = useSession(); - const { data: livekitRooms } = useQuery({ queryKey: ["livekit-rooms"], queryFn: () => getLivekitRooms(), @@ -50,7 +46,7 @@ export const StatusToast = ({ event, t }: { event: StationStatus; t: Toast }) => status9Sounds.current = new Audio("/sounds/status-9.mp3"); } }, []); - + const [aircraftDataAcurate, setAircraftDataAccurate] = useState(false); //const mapStore = useMapStore((s) => s); const { setOpenAircraftMarker, setMap } = useMapStore((store) => store); @@ -69,16 +65,29 @@ export const StatusToast = ({ event, t }: { event: StationStatus; t: Toast }) => const station = stations?.find((s) => s.id === event.data?.stationId); const queryClient = useQueryClient(); - const sendSdsStatusMutation = useMutation({ - mutationFn: async ({ sdsMessage }: { sdsMessage: MissionSdsStatusLog }) => { - if (!connectedAircraft?.id) throw new Error("No connected aircraft"); - await sendSdsStatusMessageAPI({ sdsMessage, aircraftId: connectedAircraft?.id }); + const changeAircraftMutation = useMutation({ + mutationFn: async ({ + id, + update, + }: { + id: number; + update: Prisma.ConnectedAircraftUpdateInput; + }) => { + await editConnectedAircraftAPI(id, update); queryClient.invalidateQueries({ - queryKey: ["missions"], + queryKey: ["aircrafts"], }); }, }); + useEffect(() => { + if (event.status !== connectedAircraft?.fmsStatus && aircraftDataAcurate) { + toast.remove(t.id); + } else if (event.status == connectedAircraft?.fmsStatus && !aircraftDataAcurate) { + setAircraftDataAccurate(true); + } + }, [aircraftDataAcurate, connectedAircraft, event.status, t.id]); + useEffect(() => { let soundRef: React.RefObject | null = null; switch (event.status) { @@ -94,8 +103,7 @@ export const StatusToast = ({ event, t }: { event: StationStatus; t: Toast }) => default: soundRef = null; } - - if (audioRoom && livekitUser?.roomName && audioRoom !== livekitUser?.roomName) { + if (audioRoom !== livekitUser?.roomName) { toast.remove(t.id); return; } @@ -113,8 +121,7 @@ export const StatusToast = ({ event, t }: { event: StationStatus; t: Toast }) => }; }, [event.status, livekitUser?.roomName, audioRoom, t.id]); - console.log(connectedAircraft, station); - if (!connectedAircraft || !station || !session.data) return null; + if (!connectedAircraft || !station) return null; return (
@@ -155,18 +162,10 @@ export const StatusToast = ({ event, t }: { event: StationStatus; t: Toast }) => toast.error("Keine Flugzeug-ID gefunden"); return; } - await sendSdsStatusMutation.mutateAsync({ - sdsMessage: { - type: "sds-status-log", - auto: false, - data: { - direction: "to-aircraft", - stationId: event.data.stationId!, - station: station, - user: getPublicUser(session.data?.user), - status, - }, - timeStamp: new Date().toISOString(), + await changeAircraftMutation.mutateAsync({ + id: event.data?.aircraftId, + update: { + fmsStatus: status, }, }); toast.remove(t.id); diff --git a/apps/dispatch/app/_components/map/AircraftMarker.tsx b/apps/dispatch/app/_components/map/AircraftMarker.tsx index 3961690d..9c0adaf3 100644 --- a/apps/dispatch/app/_components/map/AircraftMarker.tsx +++ b/apps/dispatch/app/_components/map/AircraftMarker.tsx @@ -2,7 +2,7 @@ import { Marker, Polyline, useMap } from "react-leaflet"; import { DivIcon, Marker as LMarker, Popup as LPopup } from "leaflet"; import { useMapStore } from "_store/mapStore"; import { Fragment, useCallback, useEffect, useRef, useState, useMemo } from "react"; -import { cn } from "@repo/shared-components"; +import { checkSimulatorConnected, cn } from "@repo/shared-components"; import { ChevronsRightLeft, House, MessageSquareText, Minimize2 } from "lucide-react"; import { SmartPopup, calculateAnchor, useSmartPopup } from "_components/SmartPopup"; import FMSStatusHistory, { @@ -396,11 +396,27 @@ const AircraftMarker = ({ aircraft }: { aircraft: ConnectedAircraft & { Station: }; export const AircraftLayer = () => { - const { data: aircrafts } = useQuery({ - queryKey: ["connected-aircrafts", "map"], - queryFn: () => getConnectedAircraftsAPI(), - refetchInterval: 15000, - }); + const [aircrafts, setAircrafts] = useState<(ConnectedAircraft & { Station: Station })[]>([]); + + useEffect(() => { + const fetchAircrafts = async () => { + try { + const res = await fetch("/api/aircrafts"); + if (!res.ok) { + throw new Error("Failed to fetch aircrafts"); + } + const data: (ConnectedAircraft & { Station: Station })[] = await res.json(); + setAircrafts(data.filter((a) => checkSimulatorConnected(a))); + } catch (error) { + console.error("Failed to fetch aircrafts:", error); + } + }; + + fetchAircrafts(); + const interval = setInterval(fetchAircrafts, 10_000); + + return () => clearInterval(interval); + }, []); const { setMap } = useMapStore((state) => state); const map = useMap(); const { diff --git a/apps/dispatch/app/_components/map/_components/AircraftMarkerTabs.tsx b/apps/dispatch/app/_components/map/_components/AircraftMarkerTabs.tsx index 0dae2e20..97e529ab 100644 --- a/apps/dispatch/app/_components/map/_components/AircraftMarkerTabs.tsx +++ b/apps/dispatch/app/_components/map/_components/AircraftMarkerTabs.tsx @@ -9,7 +9,6 @@ import { Mission, MissionLog, MissionSdsLog, - MissionSdsStatusLog, MissionStationLog, Prisma, PublicUser, @@ -41,7 +40,7 @@ import { TextSearch, } from "lucide-react"; import { useSession } from "next-auth/react"; -import { sendSdsMessageAPI, sendSdsStatusMessageAPI } from "_querys/missions"; +import { sendSdsMessageAPI } from "_querys/missions"; import { getLivekitRooms } from "_querys/livekit"; import { findLeitstelleForPosition } from "_helpers/findLeitstelleinPoint"; import { formatDistance } from "date-fns"; @@ -55,13 +54,9 @@ const FMSStatusHistory = ({ mission?: Mission; }) => { const log = ((mission?.missionLog as unknown as MissionLog[]) || []) - .filter( - (entry) => - (entry.type === "station-log" || entry.type == "sds-status-log") && - entry.data.stationId === aircraft.Station.id, - ) + .filter((entry) => entry.type === "station-log" && entry.data.stationId === aircraft.Station.id) .reverse() - .splice(0, 6) as (MissionStationLog | MissionSdsStatusLog)[]; + .splice(0, 6) as MissionStationLog[]; const aircraftUser: PublicUser = typeof aircraft.publicUser === "string" ? JSON.parse(aircraft.publicUser) : aircraft.publicUser; @@ -108,13 +103,10 @@ const FMSStatusHistory = ({ - {entry.type === "sds-status-log" ? entry.data.status : entry.data.newFMSstatus} + {entry.data.newFMSstatus} {new Date(entry.timeStamp).toLocaleTimeString([], { @@ -134,7 +126,6 @@ const FMSStatusSelector = ({ }: { aircraft: ConnectedAircraft & { Station: Station }; }) => { - const session = useSession(); const dispatcherConnected = useDispatchConnectionStore((s) => s.status) === "connected"; const [hoveredStatus, setHoveredStatus] = useState(null); const queryClient = useQueryClient(); @@ -153,20 +144,6 @@ const FMSStatusSelector = ({ }, }); - const sendSdsStatusMutation = useMutation({ - mutationFn: async ({ sdsMessage }: { sdsMessage: MissionSdsStatusLog }) => { - if (!aircraft?.id) throw new Error("No connected aircraft"); - await sendSdsStatusMessageAPI({ sdsMessage, aircraftId: aircraft?.id }); - queryClient.invalidateQueries({ - queryKey: ["missions"], - }); - }, - }); - - if (!session.data?.user) { - return null; - } - return (
@@ -236,21 +213,12 @@ const FMSStatusSelector = ({ onMouseEnter={() => setHoveredStatus(status)} onMouseLeave={() => setHoveredStatus(null)} onClick={async () => { - await sendSdsStatusMutation.mutateAsync({ - sdsMessage: { - type: "sds-status-log", - auto: false, - timeStamp: new Date().toISOString(), - data: { - status: status, - direction: "to-aircraft", - stationId: aircraft.Station.id, - station: aircraft.Station, - user: getPublicUser(session.data?.user), - }, + await changeAircraftMutation.mutateAsync({ + id: aircraft.id, + update: { + fmsStatus: status, }, }); - toast.success(`SDS Status ${status} gesendet`); }} > {status} @@ -410,9 +378,7 @@ const SDSTab = ({ ?.slice() .reverse() .filter( - (entry) => - (entry.type === "sds-log" || entry.type == "sds-status-log") && - entry.data.stationId === aircraft.Station.id, + (entry) => entry.type === "sds-log" && entry.data.stationId === aircraft.Station.id, ) || [], [mission?.missionLog, aircraft.Station.id], ); @@ -505,7 +471,7 @@ const SDSTab = ({ )}
    {log.map((entry, index) => { - const sdsEntry = entry as MissionSdsLog | MissionSdsStatusLog; + const sdsEntry = entry as MissionSdsLog; return (
  • @@ -523,9 +489,7 @@ const SDSTab = ({ {sdsEntry.data.user.firstname?.[0]?.toUpperCase() ?? "?"} {sdsEntry.data.user.lastname?.[0]?.toUpperCase() ?? "?"} - - {sdsEntry.type == "sds-log" ? sdsEntry.data.message : sdsEntry.data.status} - + {sdsEntry.data.message}
  • ); })} diff --git a/apps/dispatch/app/_components/map/_components/MissionMarkerTabs.tsx b/apps/dispatch/app/_components/map/_components/MissionMarkerTabs.tsx index a02ef87c..dcb042e1 100644 --- a/apps/dispatch/app/_components/map/_components/MissionMarkerTabs.tsx +++ b/apps/dispatch/app/_components/map/_components/MissionMarkerTabs.tsx @@ -726,11 +726,7 @@ const FMSStatusHistory = ({ mission }: { mission: Mission }) => { {entry.data.station.bosCallsign} ); - if ( - entry.type === "message-log" || - entry.type === "sds-log" || - entry.type === "sds-status-log" - ) + if (entry.type === "message-log" || entry.type === "sds-log") return (
  • @@ -745,10 +741,9 @@ const FMSStatusHistory = ({ mission }: { mission: Mission }) => { color: FMS_STATUS_TEXT_COLORS[6], }} > - {entry.type == "sds-status-log" && entry.data.direction == "to-lst" - ? entry.data.station.bosCallsignShort - : `${entry.data.user.firstname?.[0]?.toUpperCase() ?? "?"}${entry.data.user.lastname?.[0]?.toUpperCase() ?? "?"}`} - {(entry.type === "sds-log" || entry.type === "sds-status-log") && ( + {entry.data.user.firstname?.[0]?.toUpperCase() ?? "?"} + {entry.data.user.lastname?.[0]?.toUpperCase() ?? "?"} + {entry.type === "sds-log" && ( <> { /> - {entry.type == "sds-status-log" && entry.data.direction == "to-aircraft" - ? entry.data.station.bosCallsignShort - : "LST"} + {entry.data.station.bosCallsignShort} )} - - {entry.type === "sds-log" || entry.type === "message-log" - ? entry.data.message - : entry.data.status} - + {entry.data.message}
  • ); if ( diff --git a/apps/dispatch/app/_data/fmsStatusDescription.ts b/apps/dispatch/app/_data/fmsStatusDescription.ts index c83c4551..3ca69b0c 100644 --- a/apps/dispatch/app/_data/fmsStatusDescription.ts +++ b/apps/dispatch/app/_data/fmsStatusDescription.ts @@ -24,30 +24,3 @@ export const fmsStatusDescription: { [key: string]: string } = { o: "Warten, alle Abfrageplätze belegt", u: "Verstanden", }; - -export const fmsStatusDescriptionShort: { [key: string]: string } = { - NaN: "Keine D.", - "0": "Prio. Sprechen", - "1": "E.-bereit Funk", - "2": "E.-bereit Wache", - "3": "E.-übernahme", - "4": "Einsatzort", - "5": "Sprechwunsch", - "6": "Nicht e.-bereit", - "7": "Einsatzgeb.", - "8": "Bed. Verfügbar", - "9": "F-anmeldung", - E: "Einsatzabbruch", - C: "Melden Sie Einsatzübernahme", - F: "Kommen Sie über Draht", - H: "Fahren Sie Wache an", - J: "Sprechen Sie", - L: "Geben Sie Lagemeldung", - P: "Einsatz mit Polizei", - U: "Ungültige Statusfolge", - c: "Status korrigieren", - d: "Nennen Sie Transportziel", - h: "Zielklinik verständigt", - o: "Warten, alle Abfrageplätze belegt", - u: "Verstanden", -}; diff --git a/apps/dispatch/app/_data/livekitRooms.ts b/apps/dispatch/app/_data/livekitRooms.ts index f98a61aa..1bbb1ae0 100644 --- a/apps/dispatch/app/_data/livekitRooms.ts +++ b/apps/dispatch/app/_data/livekitRooms.ts @@ -1,7 +1 @@ -export const ROOMS = [ - { name: "VAR_LST_RD_01", id: "2201" }, - { name: "VAR_LST_RD_02", id: "2202" }, - { name: "VAR_LST_RD_03", id: "2203" }, - { name: "VAR_LST_RD_04", id: "2204" }, - { name: "VAR_LST_RD_05", id: "2205" }, -]; +export const ROOMS = ["LST_01", "LST_02", "LST_03", "LST_04", "LST_05"]; diff --git a/apps/dispatch/app/_querys/missions.ts b/apps/dispatch/app/_querys/missions.ts index bab144c4..240591c1 100644 --- a/apps/dispatch/app/_querys/missions.ts +++ b/apps/dispatch/app/_querys/missions.ts @@ -1,4 +1,4 @@ -import { Mission, MissionSdsLog, MissionSdsStatusLog, Prisma } from "@repo/db"; +import { Mission, MissionSdsLog, Prisma } from "@repo/db"; import axios from "axios"; import { serverApi } from "_helpers/axios"; @@ -29,20 +29,6 @@ export const editMissionAPI = async (id: number, mission: Prisma.MissionUpdateIn const respone = await serverApi.patch(`/mission/${id}`, mission); return respone.data; }; - -export const sendSdsStatusMessageAPI = async ({ - sdsMessage, - aircraftId, -}: { - aircraftId: number; - sdsMessage: MissionSdsStatusLog; -}) => { - const respone = await serverApi.post(`/aircrafts/${aircraftId}/send-sds-message`, { - sdsMessage, - }); - return respone.data; -}; - export const sendSdsMessageAPI = async ({ missionId, sdsMessage, diff --git a/apps/dispatch/app/_store/audioStore.ts b/apps/dispatch/app/_store/audioStore.ts index 72aabd9f..7ce25c64 100644 --- a/apps/dispatch/app/_store/audioStore.ts +++ b/apps/dispatch/app/_store/audioStore.ts @@ -21,13 +21,12 @@ import { useDispatchConnectionStore } from "_store/dispatch/connectionStore"; import { changeDispatcherAPI } from "_querys/dispatcher"; import { getRadioStream } from "_helpers/radioEffect"; import { usePilotConnectionStore } from "_store/pilot/connectionStore"; -import { ROOMS } from "_data/livekitRooms"; let interval: NodeJS.Timeout; type TalkState = { addSpeakingParticipant: (participant: Participant) => void; - connect: (room: (typeof ROOMS)[number] | undefined, role: string) => void; + connect: (roomName: string, role: string) => void; connectionQuality: ConnectionQuality; disconnect: () => void; isTalking: boolean; @@ -45,8 +44,6 @@ type TalkState = { radioVolume: number; dmeVolume: number; }; - selectedRoom?: (typeof ROOMS)[number]; - setSelectedRoom: (room: (typeof ROOMS)[number]) => void; speakingParticipants: Participant[]; state: "connecting" | "connected" | "disconnected" | "error"; toggleTalking: () => void; @@ -75,10 +72,6 @@ export const useAudioStore = create((set, get) => ({ remoteParticipants: 0, connectionQuality: ConnectionQuality.Unknown, room: null, - selectedRoom: ROOMS[0], - setSelectedRoom: (room) => { - set({ selectedRoom: room }); - }, resetSpeakingParticipants: (source: string) => { set({ speakingParticipants: [], @@ -124,11 +117,11 @@ export const useAudioStore = create((set, get) => ({ (oldSettings.micDeviceId !== newSettings.micDeviceId || oldSettings.micVolume !== newSettings.micVolume) ) { - const { room, disconnect, connect, selectedRoom } = get(); + const { room, disconnect, connect } = get(); const role = room?.localParticipant.attributes.role; - if (selectedRoom || role) { + if (room?.name || role) { disconnect(); - connect(selectedRoom, role || "user"); + connect(room?.name || "", role || "user"); } } }, @@ -167,7 +160,7 @@ export const useAudioStore = create((set, get) => ({ set((state) => ({ isTalking: !state.isTalking, transmitBlocked: false })); }, - connect: async (_room, role) => { + connect: async (roomName, role) => { set({ state: "connecting" }); try { @@ -179,16 +172,13 @@ export const useAudioStore = create((set, get) => ({ connectedRoom.removeAllListeners(); } - const { selectedRoom } = get(); - const url = process.env.NEXT_PUBLIC_LIVEKIT_URL; if (!url) return console.error("NEXT_PUBLIC_LIVEKIT_URL not set"); - const token = await getToken(_room?.name || selectedRoom?.name || "VAR_LST_RD_01"); + const token = await getToken(roomName); if (!token) throw new Error("Fehlende Berechtigung"); const room = new Room({}); await room.prepareConnection(url, token); - const roomConnectedSound = new Audio("/sounds/403.wav"); room // Connection events .on(RoomEvent.Connected, async () => { @@ -196,7 +186,7 @@ export const useAudioStore = create((set, get) => ({ if (dispatchState.status === "connected" && dispatchState.connectedDispatcher?.id) { changeDispatcherAPI(dispatchState.connectedDispatcher?.id, { - zone: _room?.name || selectedRoom?.name || "VAR_LST_RD_01", + zone: roomName, ghostMode: dispatchState.ghostMode, }); } @@ -218,7 +208,7 @@ export const useAudioStore = create((set, get) => ({ source: Track.Source.Microphone, }); await publishedTrack.mute(); - roomConnectedSound.play(); + set({ localRadioTrack: publishedTrack }); set({ state: "connected", room, isTalking: false, message: null }); diff --git a/apps/dispatch/app/_store/dispatch/connectionStore.ts b/apps/dispatch/app/_store/dispatch/connectionStore.ts index 9663e473..c7a646aa 100644 --- a/apps/dispatch/app/_store/dispatch/connectionStore.ts +++ b/apps/dispatch/app/_store/dispatch/connectionStore.ts @@ -27,7 +27,7 @@ export const useDispatchConnectionStore = create((set) => ({ setHideDraftMissions: (hide) => set({ hideDraftMissions: hide }), connectedDispatcher: null, message: "", - selectedZone: "VAR_LST_RD_01", + selectedZone: "LST_01", logoffTime: "", ghostMode: false, connect: async (uid, selectedZone, logoffTime, ghostMode) => @@ -48,7 +48,7 @@ export const useDispatchConnectionStore = create((set) => ({ dispatchSocket.on("connect", () => { const { logoffTime, selectedZone, ghostMode } = useDispatchConnectionStore.getState(); - useAudioStore.getState().connect(undefined, selectedZone || "Leitstelle"); + useAudioStore.getState().connect("LST_01", selectedZone || "Leitstelle"); dispatchSocket.emit("connect-dispatch", { logoffTime, selectedZone, diff --git a/apps/dispatch/app/_store/pilot/MrtStore.ts b/apps/dispatch/app/_store/pilot/MrtStore.ts index f8432402..3678f49a 100644 --- a/apps/dispatch/app/_store/pilot/MrtStore.ts +++ b/apps/dispatch/app/_store/pilot/MrtStore.ts @@ -1,92 +1,173 @@ +import { MissionSdsLog, Station } from "@repo/db"; +import { fmsStatusDescription } from "_data/fmsStatusDescription"; +import { DisplayLineProps } from "(app)/pilot/_components/mrt/Mrt"; import { create } from "zustand"; +import { syncTabs } from "zustand-sync-tabs"; -interface SetOffPageParams { - page: "off"; -} - -interface SetStartupPageParams { - page: "startup"; +interface SetSdsPageParams { + page: "sds"; + station: Station; + sdsMessage: MissionSdsLog; } interface SetHomePageParams { page: "home"; + station: Station; + fmsStatus: string; } -interface SetVoicecallPageParams { - page: "voice-call"; -} -interface SetSdsReceivedPopupParams { - popup: "sds-received"; +interface SetSendingStatusPageParams { + page: "sending-status"; + station: Station; } -interface SetGroupSelectionPopupParams { - popup: "group-selection"; +interface SetNewStatusPageParams { + page: "new-status"; + station: Station; } -interface SetStatusSentPopupParams { - popup: "status-sent"; -} - -interface SetLoginPopupParams { - popup: "login"; -} - -interface SetSdsSentPopupParams { - popup: "sds-sent"; -} - -export type SetPageParams = +type SetPageParams = | SetHomePageParams - | SetOffPageParams - | SetStartupPageParams - | SetVoicecallPageParams; - -export type SetPopupParams = - | SetStatusSentPopupParams - | SetSdsSentPopupParams - | SetGroupSelectionPopupParams - | SetSdsReceivedPopupParams - | SetLoginPopupParams; - -interface StringifiedData { - sdsText?: string; - sentSdsText?: string; - - groupSelectionGroupId?: string; - callTextHeader?: string; -} + | SetSendingStatusPageParams + | SetSdsPageParams + | SetNewStatusPageParams; interface MrtStore { page: SetPageParams["page"]; - popup?: SetPopupParams["popup"]; - stringifiedData: StringifiedData; - setStringifiedData: (data: Partial) => void; + lines: DisplayLineProps[]; setPage: (pageData: SetPageParams) => void; - setPopup: (popupData: SetPopupParams | null) => void; - - // internal - updateIntervall?: number; - nightMode: boolean; - setNightMode: (nightMode: boolean) => void; + setLines: (lines: MrtStore["lines"]) => void; } -export const useMrtStore = create((set) => ({ - page: "off", - nightMode: false, - stringifiedData: { - groupSelectionGroupId: "2201", - }, - setNightMode: (nightMode) => set({ nightMode }), - setStringifiedData: (data) => - set((state) => ({ - stringifiedData: { ...state.stringifiedData, ...data }, - })), - setPopup: (popupData) => { - set({ popup: popupData ? popupData.popup : undefined }); - }, - setPage: (pageData) => { - set({ page: pageData.page }); - }, -})); +export const useMrtStore = create( + syncTabs( + (set) => ({ + page: "home", + pageData: { + message: "", + }, + lines: [ + { + textLeft: "VAR.#", + textSize: "2", + }, + { + textLeft: "No Data", + textSize: "3", + }, + ], + setLines: (lines) => set({ lines }), + setPage: (pageData) => { + switch (pageData.page) { + case "home": { + const { station, fmsStatus } = pageData as SetHomePageParams; + set({ + page: "home", + lines: [ + { + textLeft: `${station?.bosCallsign}`, + style: { fontWeight: "bold" }, + textSize: "2", + }, + { textLeft: "ILS VAR#", textSize: "3" }, + { + textLeft: fmsStatus, + style: { fontWeight: "extrabold" }, + textSize: "4", + }, + { + textLeft: fmsStatusDescription[fmsStatus], + textSize: "1", + }, + ], + }); + break; + } + + case "sending-status": { + const { station } = pageData as SetSendingStatusPageParams; + set({ + page: "sending-status", + lines: [ + { + textLeft: `${station?.bosCallsign}`, + style: { fontWeight: "bold" }, + textSize: "2", + }, + { textLeft: "ILS VAR#", textSize: "3" }, + { + textMid: "sending...", + style: { fontWeight: "bold" }, + textSize: "4", + }, + { + textLeft: "Status wird gesendet...", + textSize: "1", + }, + ], + }); + break; + } + case "new-status": { + const { station } = pageData as SetNewStatusPageParams; + set({ + page: "new-status", + lines: [ + { + textLeft: `${station?.bosCallsign}`, + style: { fontWeight: "bold" }, + textSize: "2", + }, + { textLeft: "ILS VAR#", textSize: "3" }, + { + textLeft: "empfangen", + style: { fontWeight: "bold" }, + textSize: "4", + }, + ], + }); + break; + } + case "sds": { + const { sdsMessage } = pageData as SetSdsPageParams; + const msg = sdsMessage.data.message; + set({ + page: "sds", + lines: [ + { + textLeft: `SDS-Nachricht`, + style: { fontWeight: "bold" }, + textSize: "2", + }, + { + textLeft: msg, + style: { + whiteSpace: "normal", + overflowWrap: "break-word", + wordBreak: "break-word", + display: "block", + maxWidth: "100%", + maxHeight: "100%", + overflow: "auto", + textOverflow: "ellipsis", + lineHeight: "1.2em", + }, + textSize: "2", + }, + ], + }); + break; + } + default: + set({ page: "home" }); + break; + } + }, + }), + { + name: "mrt-store", // unique name + }, + ), +); diff --git a/apps/dispatch/app/_store/pilot/connectionStore.ts b/apps/dispatch/app/_store/pilot/connectionStore.ts index 1ca44645..e9fc29f8 100644 --- a/apps/dispatch/app/_store/pilot/connectionStore.ts +++ b/apps/dispatch/app/_store/pilot/connectionStore.ts @@ -86,7 +86,7 @@ pilotSocket.on("connect", () => { usePilotConnectionStore.setState({ status: "connected", message: "" }); const { logoffTime, selectedStation, debug } = usePilotConnectionStore.getState(); dispatchSocket.disconnect(); - useAudioStore.getState().connect(undefined, selectedStation?.bosCallsignShort || "pilot"); + useAudioStore.getState().connect("LST_01", selectedStation?.bosCallsignShort || "pilot"); pilotSocket.emit("connect-pilot", { logoffTime, @@ -109,7 +109,7 @@ pilotSocket.on("connect-message", (data) => { }); pilotSocket.on("disconnect", () => { - usePilotConnectionStore.setState({ status: "disconnected", connectedAircraft: null }); + usePilotConnectionStore.setState({ status: "disconnected" }); useAudioStore.getState().disconnect(); }); @@ -142,13 +142,11 @@ pilotSocket.on("mission-alert", (data: Mission & { Stations: Station[] }) => { }); pilotSocket.on("sds-message", (sdsMessage: MissionSdsLog) => { - console.log("Received sds-message via socket:", sdsMessage); const station = usePilotConnectionStore.getState().selectedStation; if (!station) return; - useMrtStore.getState().setPopup({ - popup: "sds-received", - }); - useMrtStore.getState().setStringifiedData({ - sdsText: sdsMessage.data.message, + useMrtStore.getState().setPage({ + page: "sds", + station, + sdsMessage, }); }); diff --git a/apps/dispatch/app/_store/pilot/dmeStore.ts b/apps/dispatch/app/_store/pilot/dmeStore.ts index 19b81b4a..bf17fb77 100644 --- a/apps/dispatch/app/_store/pilot/dmeStore.ts +++ b/apps/dispatch/app/_store/pilot/dmeStore.ts @@ -1,6 +1,7 @@ import { Mission, Station, User } from "@repo/db"; import { DisplayLineProps } from "(app)/pilot/_components/dme/Dme"; import { create } from "zustand"; +import { syncTabs } from "zustand-sync-tabs"; interface SetHomePageParams { page: "home"; @@ -44,190 +45,197 @@ interface MrtStore { let interval: NodeJS.Timeout | null = null; -export const useDmeStore = create((set) => ({ - page: "home", - pageData: { - message: "", - }, - lines: [ - { - textLeft: "", - }, - { - textMid: "VAR . DME# No Data", - textSize: "2", - }, - { - textLeft: "", - }, - ], - setLines: (lines) => set({ lines }), - latestMission: null, - setPage: (pageData) => { - if (interval) clearInterval(interval); - switch (pageData.page) { - case "home": { - const setHomePage = () => - set({ - page: "home", - lines: [ - { - textMid: pageData.station.bosCallsign - ? `${pageData.station.bosCallsign}` - : "no Data", - style: { fontWeight: "bold" }, - }, - { textMid: "⠀" }, - { - textMid: new Date().toLocaleDateString("de-DE", { - year: "numeric", - month: "2-digit", - day: "2-digit", - }), - }, - { - textMid: new Date().toLocaleTimeString(), - style: { fontWeight: "bold" }, - }, - { textMid: "⠀" }, - { - textMid: `${pageData.user.lastname} ${pageData.user.firstname}`, - }, - { textMid: "⠀" }, - ], - }); - setHomePage(); +export const useDmeStore = create( + syncTabs( + (set) => ({ + page: "home", + pageData: { + message: "", + }, + lines: [ + { + textLeft: "", + }, + { + textMid: "VAR . DME# No Data", + textSize: "2", + }, + { + textLeft: "", + }, + ], + setLines: (lines) => set({ lines }), + latestMission: null, + setPage: (pageData) => { + if (interval) clearInterval(interval); + switch (pageData.page) { + case "home": { + const setHomePage = () => + set({ + page: "home", + lines: [ + { + textMid: pageData.station.bosCallsign + ? `${pageData.station.bosCallsign}` + : "no Data", + style: { fontWeight: "bold" }, + }, + { textMid: "⠀" }, + { + textMid: new Date().toLocaleDateString("de-DE", { + year: "numeric", + month: "2-digit", + day: "2-digit", + }), + }, + { + textMid: new Date().toLocaleTimeString(), + style: { fontWeight: "bold" }, + }, + { textMid: "⠀" }, + { + textMid: `${pageData.user.lastname} ${pageData.user.firstname}`, + }, + { textMid: "⠀" }, + ], + }); + setHomePage(); - interval = setInterval(() => { - setHomePage(); - }, 1000); - break; - } + interval = setInterval(() => { + setHomePage(); + }, 1000); + break; + } - case "new-mission": { - set({ - page: "new-mission", - lines: [ - { textMid: "⠀" }, - { - textMid: "new mission received", - style: { fontWeight: "bold" }, - }, - { textMid: "⠀" }, - ], - }); - break; - } - case "mission": { - set({ - latestMission: pageData.mission, - page: "mission", - lines: [ - { - textLeft: `${pageData.mission.missionKeywordAbbreviation}`, - textRight: pageData.mission.Stations.map((s) => s.bosCallsignShort).join(","), - style: { fontWeight: "bold" }, - }, - ...(pageData.mission.type == "primär" - ? [ - { - textMid: `${pageData.mission.missionKeywordName}`, - style: { fontWeight: "bold" }, - }, - ] - : []), + case "new-mission": { + set({ + page: "new-mission", + lines: [ + { textMid: "⠀" }, + { + textMid: "new mission received", + style: { fontWeight: "bold" }, + }, + { textMid: "⠀" }, + ], + }); + break; + } + case "mission": { + set({ + latestMission: pageData.mission, + page: "mission", + lines: [ + { + textLeft: `${pageData.mission.missionKeywordAbbreviation}`, + textRight: pageData.mission.Stations.map((s) => s.bosCallsignShort).join(","), + style: { fontWeight: "bold" }, + }, + ...(pageData.mission.type == "primär" + ? [ + { + textMid: `${pageData.mission.missionKeywordName}`, + style: { fontWeight: "bold" }, + }, + ] + : []), - { textLeft: `${pageData.mission.addressStreet}` }, - { - textLeft: `${pageData.mission.addressZip} ${pageData.mission.addressCity}`, - }, - { - textMid: "Weitere Standortinformationen:", - style: { fontWeight: "bold" }, - }, - { - textLeft: pageData.mission.addressAdditionalInfo || "keine Daten", - }, - ...(pageData.mission.type === "sekundär" - ? [ - { - textMid: "Zielort:", - style: { fontWeight: "bold" }, - }, - { - textLeft: pageData.mission.addressMissionDestination || "keine Daten", - }, - ] - : []), - ...(pageData.mission.missionPatientInfo && - pageData.mission.missionPatientInfo.length > 0 - ? [ - { - textMid: "Patienteninfos:", - style: { fontWeight: "bold" }, - }, - { - textLeft: pageData.mission.missionPatientInfo, - }, - ] - : []), - ...(pageData.mission.missionAdditionalInfo && - pageData.mission.missionAdditionalInfo.length > 0 - ? [ - { - textMid: "Weitere Infos:", - style: { fontWeight: "bold" }, - }, - { - textLeft: pageData.mission.missionAdditionalInfo, - }, - ] - : []), - ], - }); - break; - } - case "error": { - set({ - page: "error", - lines: [ - { textMid: "Fehler:" }, - { - textMid: pageData.error, - style: { fontWeight: "bold" }, - }, - { textMid: "⠀" }, - ], - }); - break; - } - case "acknowledge": { - set({ - page: "acknowledge", - lines: [ - { textMid: "⠀" }, - { - textMid: "Einsatz angenommen", - style: { fontWeight: "bold" }, - }, - { textMid: "⠀" }, - ], - }); - break; - } - default: - set({ - page: "error", - lines: [ - { textMid: "Fehler:" }, - { - textMid: `Unbekannte Seite`, - style: { fontWeight: "bold" }, - }, - { textMid: "⠀" }, - ], - }); - break; - } - }, -})); + { textLeft: `${pageData.mission.addressStreet}` }, + { + textLeft: `${pageData.mission.addressZip} ${pageData.mission.addressCity}`, + }, + { + textMid: "Weitere Standortinformationen:", + style: { fontWeight: "bold" }, + }, + { + textLeft: pageData.mission.addressAdditionalInfo || "keine Daten", + }, + ...(pageData.mission.type === "sekundär" + ? [ + { + textMid: "Zielort:", + style: { fontWeight: "bold" }, + }, + { + textLeft: pageData.mission.addressMissionDestination || "keine Daten", + }, + ] + : []), + ...(pageData.mission.missionPatientInfo && + pageData.mission.missionPatientInfo.length > 0 + ? [ + { + textMid: "Patienteninfos:", + style: { fontWeight: "bold" }, + }, + { + textLeft: pageData.mission.missionPatientInfo, + }, + ] + : []), + ...(pageData.mission.missionAdditionalInfo && + pageData.mission.missionAdditionalInfo.length > 0 + ? [ + { + textMid: "Weitere Infos:", + style: { fontWeight: "bold" }, + }, + { + textLeft: pageData.mission.missionAdditionalInfo, + }, + ] + : []), + ], + }); + break; + } + case "error": { + set({ + page: "error", + lines: [ + { textMid: "Fehler:" }, + { + textMid: pageData.error, + style: { fontWeight: "bold" }, + }, + { textMid: "⠀" }, + ], + }); + break; + } + case "acknowledge": { + set({ + page: "acknowledge", + lines: [ + { textMid: "⠀" }, + { + textMid: "Einsatz angenommen", + style: { fontWeight: "bold" }, + }, + { textMid: "⠀" }, + ], + }); + break; + } + default: + set({ + page: "error", + lines: [ + { textMid: "Fehler:" }, + { + textMid: `Unbekannte Seite`, + style: { fontWeight: "bold" }, + }, + { textMid: "⠀" }, + ], + }); + break; + } + }, + }), + { + name: "dme-store", // unique name + }, + ), +); diff --git a/apps/dispatch/app/globals.css b/apps/dispatch/app/globals.css index 979f4a4d..876c3519 100644 --- a/apps/dispatch/app/globals.css +++ b/apps/dispatch/app/globals.css @@ -9,11 +9,6 @@ src: url("/fonts/MelderV2.ttf") format("truetype"); /* Chrome 4+, Firefox 3.5, Opera 10+, Safari 3—5 */ } -@font-face { - font-family: "Bahnschrift"; - src: url("/fonts/bahnschrift.ttf") format("truetype"); /* Chrome 4+, Firefox 3.5, Opera 10+, Safari 3—5 */ -} - @theme { --color-rescuetrack: #46b7a3; --color-rescuetrack-highlight: #ff4500; diff --git a/apps/dispatch/next-env.d.ts b/apps/dispatch/next-env.d.ts index c4b7818f..1b3be084 100644 --- a/apps/dispatch/next-env.d.ts +++ b/apps/dispatch/next-env.d.ts @@ -1,6 +1,5 @@ /// /// -import "./.next/dev/types/routes.d.ts"; // NOTE: This file should not be edited // see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/apps/dispatch/next.config.js b/apps/dispatch/next.config.js index eab71bb8..4678774e 100644 --- a/apps/dispatch/next.config.js +++ b/apps/dispatch/next.config.js @@ -1,6 +1,4 @@ /** @type {import('next').NextConfig} */ -const nextConfig = { - output: "standalone", -}; +const nextConfig = {}; export default nextConfig; diff --git a/apps/dispatch/package.json b/apps/dispatch/package.json index ccddbcaa..914efa9f 100644 --- a/apps/dispatch/package.json +++ b/apps/dispatch/package.json @@ -60,6 +60,7 @@ "tailwindcss": "^4.1.11", "typescript": "^5.8.3", "zod": "^3.25.67", - "zustand": "^5.0.6" + "zustand": "^5.0.6", + "zustand-sync-tabs": "^0.2.2" } } diff --git a/apps/dispatch/public/fonts/bahnschrift.ttf b/apps/dispatch/public/fonts/bahnschrift.ttf deleted file mode 100644 index 2c121b3d..00000000 Binary files a/apps/dispatch/public/fonts/bahnschrift.ttf and /dev/null differ diff --git a/apps/dispatch/public/sounds/1504.wav b/apps/dispatch/public/sounds/1504.wav deleted file mode 100644 index edde45b8..00000000 Binary files a/apps/dispatch/public/sounds/1504.wav and /dev/null differ diff --git a/apps/dispatch/public/sounds/403.wav b/apps/dispatch/public/sounds/403.wav deleted file mode 100644 index 3d855dc6..00000000 Binary files a/apps/dispatch/public/sounds/403.wav and /dev/null differ diff --git a/apps/dispatch/public/sounds/775.wav b/apps/dispatch/public/sounds/775.wav deleted file mode 100644 index bb406ab5..00000000 Binary files a/apps/dispatch/public/sounds/775.wav and /dev/null differ diff --git a/apps/hub/Dockerfile b/apps/hub/Dockerfile index 6c5c55af..6467ccbb 100644 --- a/apps/hub/Dockerfile +++ b/apps/hub/Dockerfile @@ -1,5 +1,9 @@ FROM node:22-alpine AS base + +ENV PNPM_HOME="/usr/local/pnpm" +ENV PATH="${PNPM_HOME}:${PATH}" + ARG NEXT_PUBLIC_HUB_URL ARG NEXT_PUBLIC_HUB_SERVER_URL ARG NEXT_PUBLIC_DISCORD_URL @@ -12,13 +16,13 @@ ENV NEXT_PUBLIC_DISCORD_URL=${NEXT_PUBLIC_DISCORD_URL} ENV NEXT_PUBLIC_MOODLE_URL=${NEXT_PUBLIC_MOODLE_URL} ENV NEXT_PUBLIC_DISPATCH_URL=${NEXT_PUBLIC_DISPATCH_URL} -FROM base AS builder - -ENV PNPM_HOME="/usr/local/pnpm" -ENV PATH="${PNPM_HOME}:${PATH}" - RUN corepack enable && corepack prepare pnpm@latest --activate + + +RUN echo "NEXT_PUBLIC_DISCORD_URL=${NEXT_PUBLIC_DISCORD_URL}" RUN pnpm add -g turbo@^2.5 + +FROM base AS builder RUN apk update RUN apk add --no-cache libc6-compat @@ -29,13 +33,6 @@ COPY . . RUN turbo prune hub --docker FROM base AS installer - -ENV PNPM_HOME="/usr/local/pnpm" -ENV PATH="${PNPM_HOME}:${PATH}" - -RUN corepack enable && corepack prepare pnpm@latest --activate -RUN pnpm add -g turbo@^2.5 - RUN apk update RUN apk add --no-cache libc6-compat @@ -47,24 +44,21 @@ RUN pnpm install # Build the project COPY --from=builder /usr/app/out/full/ . -RUN turbo run build --filter=hub... +RUN turbo run build -FROM node:22-alpine AS runner +FROM base AS runner WORKDIR /usr/app # Don't run production as root RUN addgroup --system --gid 1001 nodejs RUN adduser --system --uid 1001 nextjs +USER nextjs # Automatically leverage output traces to reduce image size # https://nextjs.org/docs/advanced-features/output-file-tracing -COPY --from=installer --chown=nextjs:nodejs /usr/app/apps/hub/.next/standalone ./ -COPY --from=installer --chown=nextjs:nodejs /usr/app/apps/hub/.next/static ./apps/hub/.next/static -COPY --from=installer --chown=nextjs:nodejs /usr/app/apps/hub/public ./apps/hub/public - -USER nextjs +COPY --from=installer --chown=nextjs:nodejs /usr/app/ ./ # Expose the application port EXPOSE 3000 -CMD ["node", "apps/hub/server.js"] \ No newline at end of file +CMD ["pnpm", "--dir", "apps/hub", "run", "start"] \ No newline at end of file diff --git a/apps/hub/app/(app)/admin/event/_components/Form.tsx b/apps/hub/app/(app)/admin/event/_components/Form.tsx index f2726311..0059d196 100644 --- a/apps/hub/app/(app)/admin/event/_components/Form.tsx +++ b/apps/hub/app/(app)/admin/event/_components/Form.tsx @@ -264,7 +264,6 @@ export const Form = ({ event }: { event?: Event }) => { showSearch getFilter={(searchTerm) => ({ - AND: [{ eventId: event?.id }], OR: [ { User: { diff --git a/apps/hub/app/(app)/admin/user/[id]/_components/forms.tsx b/apps/hub/app/(app)/admin/user/[id]/_components/forms.tsx index 25789965..d04c5309 100644 --- a/apps/hub/app/(app)/admin/user/[id]/_components/forms.tsx +++ b/apps/hub/app/(app)/admin/user/[id]/_components/forms.tsx @@ -776,19 +776,13 @@ export const AdminForm = ({ {discordAccount && ( - {discordAccount.avatar ? ( - Discord Avatar - ) : ( -
    - N/A -
    - )} + Discord Avatar {discordAccount.username} {discordAccount.discordId} @@ -798,20 +792,15 @@ export const AdminForm = ({ {formerDiscordAccounts.map((account) => ( - {account.DiscordAccount && - (account.DiscordAccount.avatar ? ( - Discord Avatar - ) : ( -
    - N/A -
    - ))} + {account.DiscordAccount && ( + Discord Avatar + )} {account.DiscordAccount?.username || "Unbekannt"} {account.DiscordAccount?.discordId || "Unbekannt"} diff --git a/apps/hub/next.config.ts b/apps/hub/next.config.ts index 174231d1..f681ee94 100644 --- a/apps/hub/next.config.ts +++ b/apps/hub/next.config.ts @@ -2,7 +2,6 @@ /* const removeImports = require("next-remove-imports")(); */ /* const nextConfig = removeImports({}); */ const nextConfig = { - output: "standalone", images: { domains: ["cdn.discordapp.com", "nextcloud.virtualairrescue.com"], }, diff --git a/package.json b/package.json index da08da6d..f66adf1d 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "node": ">=18", "pnpm": ">=10" }, - "packageManager": "pnpm@10.28.0", + "packageManager": "pnpm@10.13.1", "workspaces": [ "apps/*", "packages/*" diff --git a/packages/database/prisma/json/MissionVehicleLog.ts b/packages/database/prisma/json/MissionVehicleLog.ts index c7de840c..7bceda67 100644 --- a/packages/database/prisma/json/MissionVehicleLog.ts +++ b/packages/database/prisma/json/MissionVehicleLog.ts @@ -1,5 +1,4 @@ import { Station } from "../../generated/client"; -import { StationStatus } from "./SocketEvents"; import { PublicUser } from "./User"; export interface MissionVehicleLog { @@ -38,19 +37,6 @@ export interface MissionSdsLog { }; } -export interface MissionSdsStatusLog { - type: "sds-status-log"; - auto: false; - timeStamp: string; - data: { - direction: "to-lst" | "to-aircraft"; - stationId: number; - station: Station; - user: PublicUser; - status: string; - }; -} - export interface MissionMessageLog { type: "message-log"; auto: false; @@ -104,5 +90,4 @@ export type MissionLog = | MissionAlertLogAuto | MissionCompletedLog | MissionVehicleLog - | MissionReopenedLog - | MissionSdsStatusLog; + | MissionReopenedLog; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9a37750f..21252307 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -16,12 +16,9 @@ overrides: next@>=15.0.0 <=15.4.4: '>=15.4.5' next@>=15.0.0-canary.0 <15.4.7: '>=15.4.7' next@>=15.4.0-canary.0 <15.4.8: '>=15.4.8' - next@>=15.4.0-canary.0 <15.4.9: '>=15.4.9' nodemailer@<7.0.7: '>=7.0.7' nodemailer@<=7.0.10: '>=7.0.11' playwright@<1.55.1: '>=1.55.1' - preact@>=10.26.5 <10.26.10: '>=10.26.10' - qs@<6.14.1: '>=6.14.1' importers: @@ -130,7 +127,7 @@ importers: version: 0.5.8(@types/dom-mediacapture-transform@0.1.11)(livekit-client@2.15.3(@types/dom-mediacapture-record@1.0.22)) '@next-auth/prisma-adapter': specifier: ^1.0.7 - version: 1.0.7(@prisma/client@6.12.0(prisma@6.12.0(typescript@5.8.3))(typescript@5.8.3))(next-auth@4.24.13(next@16.1.1(@opentelemetry/api@1.9.0)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(nodemailer@7.0.11)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)) + version: 1.0.7(@prisma/client@6.12.0(prisma@6.12.0(typescript@5.8.3))(typescript@5.8.3))(next-auth@4.24.13(next@15.4.8(@babel/core@7.27.7)(@opentelemetry/api@1.9.0)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(nodemailer@7.0.11)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)) '@radix-ui/react-icons': specifier: ^1.3.2 version: 1.3.2(react@19.1.0) @@ -210,11 +207,11 @@ importers: specifier: ^0.525.0 version: 0.525.0(react@19.1.0) next: - specifier: '>=15.4.9' - version: 16.1.1(@opentelemetry/api@1.9.0)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + specifier: ^15.4.8 + version: 15.4.8(@babel/core@7.27.7)(@opentelemetry/api@1.9.0)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) next-auth: specifier: '>=4.24.12' - version: 4.24.13(next@16.1.1(@opentelemetry/api@1.9.0)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(nodemailer@7.0.11)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + version: 4.24.13(next@15.4.8(@babel/core@7.27.7)(@opentelemetry/api@1.9.0)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(nodemailer@7.0.11)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) npm: specifier: ^11.4.2 version: 11.4.2 @@ -260,6 +257,9 @@ importers: zustand: specifier: ^5.0.6 version: 5.0.6(@types/react@19.1.8)(react@19.1.0) + zustand-sync-tabs: + specifier: ^0.2.2 + version: 0.2.2(zustand@5.0.6(@types/react@19.1.8)(react@19.1.0)) apps/dispatch-server: dependencies: @@ -365,7 +365,7 @@ importers: version: 5.1.1(react-hook-form@7.60.0(react@19.1.0)) '@next-auth/prisma-adapter': specifier: ^1.0.7 - version: 1.0.7(@prisma/client@6.12.0(prisma@6.12.0(typescript@5.8.3))(typescript@5.8.3))(next-auth@4.24.13(next@16.1.1(@babel/core@7.27.7)(@opentelemetry/api@1.9.0)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(nodemailer@7.0.11)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)) + version: 1.0.7(@prisma/client@6.12.0(prisma@6.12.0(typescript@5.8.3))(typescript@5.8.3))(next-auth@4.24.13(next@15.4.8(@babel/core@7.27.7)(@opentelemetry/api@1.9.0)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(nodemailer@7.0.11)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)) '@radix-ui/react-icons': specifier: ^1.3.2 version: 1.3.2(react@19.1.0) @@ -439,11 +439,11 @@ importers: specifier: ^2.30.1 version: 2.30.1 next: - specifier: '>=15.4.9' - version: 16.1.1(@babel/core@7.27.7)(@opentelemetry/api@1.9.0)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + specifier: ^15.4.8 + version: 15.4.8(@babel/core@7.27.7)(@opentelemetry/api@1.9.0)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) next-auth: specifier: '>=4.24.12' - version: 4.24.13(next@16.1.1(@babel/core@7.27.7)(@opentelemetry/api@1.9.0)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(nodemailer@7.0.11)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + version: 4.24.13(next@15.4.8(@babel/core@7.27.7)(@opentelemetry/api@1.9.0)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(nodemailer@7.0.11)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) next-remove-imports: specifier: ^1.0.12 version: 1.0.12(webpack@5.99.9) @@ -791,8 +791,8 @@ packages: '@emnapi/runtime@1.4.3': resolution: {integrity: sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==} - '@emnapi/runtime@1.8.1': - resolution: {integrity: sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==} + '@emnapi/runtime@1.4.5': + resolution: {integrity: sha512-++LApOtY0pEEz1zrd9vy1/zXVaVJJ/EbAF3u0fXIzPJEDtnITsBGbbK0EkM72amhl/R5b+5xx0Y/QhcVOpuulg==} '@emnapi/wasi-threads@1.0.2': resolution: {integrity: sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA==} @@ -1079,139 +1079,124 @@ packages: resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} engines: {node: '>=18.18'} - '@img/colour@1.0.0': - resolution: {integrity: sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==} - engines: {node: '>=18'} - - '@img/sharp-darwin-arm64@0.34.5': - resolution: {integrity: sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==} + '@img/sharp-darwin-arm64@0.34.3': + resolution: {integrity: sha512-ryFMfvxxpQRsgZJqBd4wsttYQbCxsJksrv9Lw/v798JcQ8+w84mBWuXwl+TT0WJ/WrYOLaYpwQXi3sA9nTIaIg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [darwin] - '@img/sharp-darwin-x64@0.34.5': - resolution: {integrity: sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==} + '@img/sharp-darwin-x64@0.34.3': + resolution: {integrity: sha512-yHpJYynROAj12TA6qil58hmPmAwxKKC7reUqtGLzsOHfP7/rniNGTL8tjWX6L3CTV4+5P4ypcS7Pp+7OB+8ihA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [darwin] - '@img/sharp-libvips-darwin-arm64@1.2.4': - resolution: {integrity: sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==} + '@img/sharp-libvips-darwin-arm64@1.2.0': + resolution: {integrity: sha512-sBZmpwmxqwlqG9ueWFXtockhsxefaV6O84BMOrhtg/YqbTaRdqDE7hxraVE3y6gVM4eExmfzW4a8el9ArLeEiQ==} cpu: [arm64] os: [darwin] - '@img/sharp-libvips-darwin-x64@1.2.4': - resolution: {integrity: sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==} + '@img/sharp-libvips-darwin-x64@1.2.0': + resolution: {integrity: sha512-M64XVuL94OgiNHa5/m2YvEQI5q2cl9d/wk0qFTDVXcYzi43lxuiFTftMR1tOnFQovVXNZJ5TURSDK2pNe9Yzqg==} cpu: [x64] os: [darwin] - '@img/sharp-libvips-linux-arm64@1.2.4': - resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==} + '@img/sharp-libvips-linux-arm64@1.2.0': + resolution: {integrity: sha512-RXwd0CgG+uPRX5YYrkzKyalt2OJYRiJQ8ED/fi1tq9WQW2jsQIn0tqrlR5l5dr/rjqq6AHAxURhj2DVjyQWSOA==} cpu: [arm64] os: [linux] - '@img/sharp-libvips-linux-arm@1.2.4': - resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==} + '@img/sharp-libvips-linux-arm@1.2.0': + resolution: {integrity: sha512-mWd2uWvDtL/nvIzThLq3fr2nnGfyr/XMXlq8ZJ9WMR6PXijHlC3ksp0IpuhK6bougvQrchUAfzRLnbsen0Cqvw==} cpu: [arm] os: [linux] - '@img/sharp-libvips-linux-ppc64@1.2.4': - resolution: {integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==} + '@img/sharp-libvips-linux-ppc64@1.2.0': + resolution: {integrity: sha512-Xod/7KaDDHkYu2phxxfeEPXfVXFKx70EAFZ0qyUdOjCcxbjqyJOEUpDe6RIyaunGxT34Anf9ue/wuWOqBW2WcQ==} cpu: [ppc64] os: [linux] - '@img/sharp-libvips-linux-riscv64@1.2.4': - resolution: {integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==} - cpu: [riscv64] - os: [linux] - - '@img/sharp-libvips-linux-s390x@1.2.4': - resolution: {integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==} + '@img/sharp-libvips-linux-s390x@1.2.0': + resolution: {integrity: sha512-eMKfzDxLGT8mnmPJTNMcjfO33fLiTDsrMlUVcp6b96ETbnJmd4uvZxVJSKPQfS+odwfVaGifhsB07J1LynFehw==} cpu: [s390x] os: [linux] - '@img/sharp-libvips-linux-x64@1.2.4': - resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==} + '@img/sharp-libvips-linux-x64@1.2.0': + resolution: {integrity: sha512-ZW3FPWIc7K1sH9E3nxIGB3y3dZkpJlMnkk7z5tu1nSkBoCgw2nSRTFHI5pB/3CQaJM0pdzMF3paf9ckKMSE9Tg==} cpu: [x64] os: [linux] - '@img/sharp-libvips-linuxmusl-arm64@1.2.4': - resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==} + '@img/sharp-libvips-linuxmusl-arm64@1.2.0': + resolution: {integrity: sha512-UG+LqQJbf5VJ8NWJ5Z3tdIe/HXjuIdo4JeVNADXBFuG7z9zjoegpzzGIyV5zQKi4zaJjnAd2+g2nna8TZvuW9Q==} cpu: [arm64] os: [linux] - '@img/sharp-libvips-linuxmusl-x64@1.2.4': - resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==} + '@img/sharp-libvips-linuxmusl-x64@1.2.0': + resolution: {integrity: sha512-SRYOLR7CXPgNze8akZwjoGBoN1ThNZoqpOgfnOxmWsklTGVfJiGJoC/Lod7aNMGA1jSsKWM1+HRX43OP6p9+6Q==} cpu: [x64] os: [linux] - '@img/sharp-linux-arm64@0.34.5': - resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==} + '@img/sharp-linux-arm64@0.34.3': + resolution: {integrity: sha512-QdrKe3EvQrqwkDrtuTIjI0bu6YEJHTgEeqdzI3uWJOH6G1O8Nl1iEeVYRGdj1h5I21CqxSvQp1Yv7xeU3ZewbA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] - '@img/sharp-linux-arm@0.34.5': - resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==} + '@img/sharp-linux-arm@0.34.3': + resolution: {integrity: sha512-oBK9l+h6KBN0i3dC8rYntLiVfW8D8wH+NPNT3O/WBHeW0OQWCjfWksLUaPidsrDKpJgXp3G3/hkmhptAW0I3+A==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm] os: [linux] - '@img/sharp-linux-ppc64@0.34.5': - resolution: {integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==} + '@img/sharp-linux-ppc64@0.34.3': + resolution: {integrity: sha512-GLtbLQMCNC5nxuImPR2+RgrviwKwVql28FWZIW1zWruy6zLgA5/x2ZXk3mxj58X/tszVF69KK0Is83V8YgWhLA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [ppc64] os: [linux] - '@img/sharp-linux-riscv64@0.34.5': - resolution: {integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==} - engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} - cpu: [riscv64] - os: [linux] - - '@img/sharp-linux-s390x@0.34.5': - resolution: {integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==} + '@img/sharp-linux-s390x@0.34.3': + resolution: {integrity: sha512-3gahT+A6c4cdc2edhsLHmIOXMb17ltffJlxR0aC2VPZfwKoTGZec6u5GrFgdR7ciJSsHT27BD3TIuGcuRT0KmQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [s390x] os: [linux] - '@img/sharp-linux-x64@0.34.5': - resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==} + '@img/sharp-linux-x64@0.34.3': + resolution: {integrity: sha512-8kYso8d806ypnSq3/Ly0QEw90V5ZoHh10yH0HnrzOCr6DKAPI6QVHvwleqMkVQ0m+fc7EH8ah0BB0QPuWY6zJQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] - '@img/sharp-linuxmusl-arm64@0.34.5': - resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==} + '@img/sharp-linuxmusl-arm64@0.34.3': + resolution: {integrity: sha512-vAjbHDlr4izEiXM1OTggpCcPg9tn4YriK5vAjowJsHwdBIdx0fYRsURkxLG2RLm9gyBq66gwtWI8Gx0/ov+JKQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] - '@img/sharp-linuxmusl-x64@0.34.5': - resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==} + '@img/sharp-linuxmusl-x64@0.34.3': + resolution: {integrity: sha512-gCWUn9547K5bwvOn9l5XGAEjVTTRji4aPTqLzGXHvIr6bIDZKNTA34seMPgM0WmSf+RYBH411VavCejp3PkOeQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] - '@img/sharp-wasm32@0.34.5': - resolution: {integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==} + '@img/sharp-wasm32@0.34.3': + resolution: {integrity: sha512-+CyRcpagHMGteySaWos8IbnXcHgfDn7pO2fiC2slJxvNq9gDipYBN42/RagzctVRKgxATmfqOSulgZv5e1RdMg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [wasm32] - '@img/sharp-win32-arm64@0.34.5': - resolution: {integrity: sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==} + '@img/sharp-win32-arm64@0.34.3': + resolution: {integrity: sha512-MjnHPnbqMXNC2UgeLJtX4XqoVHHlZNd+nPt1kRPmj63wURegwBhZlApELdtxM2OIZDRv/DFtLcNhVbd1z8GYXQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [win32] - '@img/sharp-win32-ia32@0.34.5': - resolution: {integrity: sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==} + '@img/sharp-win32-ia32@0.34.3': + resolution: {integrity: sha512-xuCdhH44WxuXgOM714hn4amodJMZl3OEvf0GVTm0BEyMeA2to+8HEdRPShH0SLYptJY1uBw+SCFP9WVQi1Q/cw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [ia32] os: [win32] - '@img/sharp-win32-x64@0.34.5': - resolution: {integrity: sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==} + '@img/sharp-win32-x64@0.34.3': + resolution: {integrity: sha512-OWwz05d++TxzLEv4VnsTz5CmZ6mI6S05sfQGEMrNrQcOEERbX46332IvE7pO/EUiw7jUrrS40z/M7kPyjfl04g==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [win32] @@ -1292,56 +1277,56 @@ packages: '@prisma/client': '>=2.26.0 || >=3' next-auth: '>=4.24.12' - '@next/env@16.1.1': - resolution: {integrity: sha512-3oxyM97Sr2PqiVyMyrZUtrtM3jqqFxOQJVuKclDsgj/L728iZt/GyslkN4NwarledZATCenbk4Offjk1hQmaAA==} + '@next/env@15.4.8': + resolution: {integrity: sha512-LydLa2MDI1NMrOFSkO54mTc8iIHSttj6R6dthITky9ylXV2gCGi0bHQjVCtLGRshdRPjyh2kXbxJukDtBWQZtQ==} '@next/eslint-plugin-next@15.4.2': resolution: {integrity: sha512-k0rjdWjXBY6tAOty1ckrMETE6Mx66d85NsgcAIdDp7/cXOsTJ93ywmbg3uUcpxX5TUHFEcCWI5mb8nPhwCe9jg==} - '@next/swc-darwin-arm64@16.1.1': - resolution: {integrity: sha512-JS3m42ifsVSJjSTzh27nW+Igfha3NdBOFScr9C80hHGrWx55pTrVL23RJbqir7k7/15SKlrLHhh/MQzqBBYrQA==} + '@next/swc-darwin-arm64@15.4.8': + resolution: {integrity: sha512-Pf6zXp7yyQEn7sqMxur6+kYcywx5up1J849psyET7/8pG2gQTVMjU3NzgIt8SeEP5to3If/SaWmaA6H6ysBr1A==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@next/swc-darwin-x64@16.1.1': - resolution: {integrity: sha512-hbyKtrDGUkgkyQi1m1IyD3q4I/3m9ngr+V93z4oKHrPcmxwNL5iMWORvLSGAf2YujL+6HxgVvZuCYZfLfb4bGw==} + '@next/swc-darwin-x64@15.4.8': + resolution: {integrity: sha512-xla6AOfz68a6kq3gRQccWEvFC/VRGJmA/QuSLENSO7CZX5WIEkSz7r1FdXUjtGCQ1c2M+ndUAH7opdfLK1PQbw==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@next/swc-linux-arm64-gnu@16.1.1': - resolution: {integrity: sha512-/fvHet+EYckFvRLQ0jPHJCUI5/B56+2DpI1xDSvi80r/3Ez+Eaa2Yq4tJcRTaB1kqj/HrYKn8Yplm9bNoMJpwQ==} + '@next/swc-linux-arm64-gnu@15.4.8': + resolution: {integrity: sha512-y3fmp+1Px/SJD+5ntve5QLZnGLycsxsVPkTzAc3zUiXYSOlTPqT8ynfmt6tt4fSo1tAhDPmryXpYKEAcoAPDJw==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-arm64-musl@16.1.1': - resolution: {integrity: sha512-MFHrgL4TXNQbBPzkKKur4Fb5ICEJa87HM7fczFs2+HWblM7mMLdco3dvyTI+QmLBU9xgns/EeeINSZD6Ar+oLg==} + '@next/swc-linux-arm64-musl@15.4.8': + resolution: {integrity: sha512-DX/L8VHzrr1CfwaVjBQr3GWCqNNFgyWJbeQ10Lx/phzbQo3JNAxUok1DZ8JHRGcL6PgMRgj6HylnLNndxn4Z6A==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-x64-gnu@16.1.1': - resolution: {integrity: sha512-20bYDfgOQAPUkkKBnyP9PTuHiJGM7HzNBbuqmD0jiFVZ0aOldz+VnJhbxzjcSabYsnNjMPsE0cyzEudpYxsrUQ==} + '@next/swc-linux-x64-gnu@15.4.8': + resolution: {integrity: sha512-9fLAAXKAL3xEIFdKdzG5rUSvSiZTLLTCc6JKq1z04DR4zY7DbAPcRvNm3K1inVhTiQCs19ZRAgUerHiVKMZZIA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-linux-x64-musl@16.1.1': - resolution: {integrity: sha512-9pRbK3M4asAHQRkwaXwu601oPZHghuSC8IXNENgbBSyImHv/zY4K5udBusgdHkvJ/Tcr96jJwQYOll0qU8+fPA==} + '@next/swc-linux-x64-musl@15.4.8': + resolution: {integrity: sha512-s45V7nfb5g7dbS7JK6XZDcapicVrMMvX2uYgOHP16QuKH/JA285oy6HcxlKqwUNaFY/UC6EvQ8QZUOo19cBKSA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-win32-arm64-msvc@16.1.1': - resolution: {integrity: sha512-bdfQkggaLgnmYrFkSQfsHfOhk/mCYmjnrbRCGgkMcoOBZ4n+TRRSLmT/CU5SATzlBJ9TpioUyBW/vWFXTqQRiA==} + '@next/swc-win32-arm64-msvc@15.4.8': + resolution: {integrity: sha512-KjgeQyOAq7t/HzAJcWPGA8X+4WY03uSCZ2Ekk98S9OgCFsb6lfBE3dbUzUuEQAN2THbwYgFfxX2yFTCMm8Kehw==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@next/swc-win32-x64-msvc@16.1.1': - resolution: {integrity: sha512-Ncwbw2WJ57Al5OX0k4chM68DKhEPlrXBaSXDCi2kPi5f4d8b3ejr3RRJGfKBLrn2YJL5ezNS7w2TZLHSti8CMw==} + '@next/swc-win32-x64-msvc@15.4.8': + resolution: {integrity: sha512-Exsmf/+42fWVnLMaZHzshukTBxZrSwuuLKFvqhGHJ+mC1AokqieLY/XzAl3jc/CqhXLqLY3RRjkKJ9YnLPcRWg==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -2573,10 +2558,6 @@ packages: resolution: {integrity: sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==} engines: {node: ^4.5.0 || >= 5.9} - baseline-browser-mapping@2.9.14: - resolution: {integrity: sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg==} - hasBin: true - batch-processor@1.0.0: resolution: {integrity: sha512-xoLQD8gmmR32MeuBHgH0Tzd5PuSZx71ZsbhVxOCRbgktZEPe4SQy7s9Z50uPp0F/f7iw2XmkHN2xkgbMfckMDA==} @@ -2715,6 +2696,13 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + color-string@1.9.1: + resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} + + color@4.2.3: + resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} + engines: {node: '>=12.5.0'} + combined-stream@1.0.8: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} @@ -2895,10 +2883,6 @@ packages: resolution: {integrity: sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==} engines: {node: '>=8'} - detect-libc@2.1.2: - resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} - engines: {node: '>=8'} - devlop@1.1.0: resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} @@ -3560,6 +3544,9 @@ packages: is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + is-arrayish@0.3.2: + resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} + is-async-function@2.1.1: resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==} engines: {node: '>= 0.4'} @@ -4187,7 +4174,7 @@ packages: resolution: {integrity: sha512-sgObCfcfL7BzIK76SS5TnQtc3yo2Oifp/yIpfv6fMfeBOiBJkDWF3A2y9+yqnmJ4JKc2C+nMjSjmgDeTwgN1rQ==} peerDependencies: '@auth/core': 0.34.3 - next: '>=15.4.9' + next: '>=15.4.8' nodemailer: '>=7.0.11' react: ^17.0.2 || ^18 || ^19 react-dom: ^17.0.2 || ^18 || ^19 @@ -4200,9 +4187,9 @@ packages: next-remove-imports@1.0.12: resolution: {integrity: sha512-3tdL6VuSykJ/mcUwxfjQ+Fd4OpEmrwWVHtLZ/fhNcSaToWCutUp7nrfIww7/4CURe9I7BDCQE9AWl4fkY3YZOQ==} - next@16.1.1: - resolution: {integrity: sha512-QI+T7xrxt1pF6SQ/JYFz95ro/mg/1Znk5vBebsWwbpejj1T0A23hO7GYEaVac9QUOT2BIMiuzm0L99ooq7k0/w==} - engines: {node: '>=20.9.0'} + next@15.4.8: + resolution: {integrity: sha512-jwOXTz/bo0Pvlf20FSb6VXVeWRssA2vbvq9SdrOPEg9x8E1B27C2rQtvriAn600o9hH61kjrVRexEffv3JybuA==} + engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} hasBin: true peerDependencies: '@opentelemetry/api': ^1.1.0 @@ -4495,10 +4482,10 @@ packages: preact-render-to-string@5.2.6: resolution: {integrity: sha512-JyhErpYOvBV1hEPwIxc/fHWXPfnEGdRKxc8gFdAZ7XV4tlzyzG847XAyEZqoDnynP88akM4eaHcSOzNcLWFguw==} peerDependencies: - preact: '>=10.26.10' + preact: '>=10' - preact@10.28.2: - resolution: {integrity: sha512-lbteaWGzGHdlIuiJ0l2Jq454m6kcpI1zNje6d8MlGAFlYvP2GO4ibnat7P74Esfz4sPTdM6UxtTwh/d3pwM9JA==} + preact@10.26.9: + resolution: {integrity: sha512-SSjF9vcnF27mJK1XyFMNJzFd5u3pQiATFqoaDy03XuN00u4ziveVVEGt5RKJrDR8MHE/wJo9Nnad56RLzS2RMA==} prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} @@ -4614,8 +4601,8 @@ packages: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} - qs@6.14.1: - resolution: {integrity: sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==} + qs@6.14.0: + resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==} engines: {node: '>=0.6'} queue-microtask@1.2.3: @@ -4885,11 +4872,6 @@ packages: engines: {node: '>=10'} hasBin: true - semver@7.7.3: - resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} - engines: {node: '>=10'} - hasBin: true - send@1.2.0: resolution: {integrity: sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==} engines: {node: '>= 18'} @@ -4916,8 +4898,8 @@ packages: setprototypeof@1.2.0: resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} - sharp@0.34.5: - resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==} + sharp@0.34.3: + resolution: {integrity: sha512-eX2IQ6nFohW4DbvHIOLRB3MHFpYqaqvXd3Tp5e/T/dSH83fxaNJQRvDMhASmkNTsNTVF2/OOopzRCt7xokgPfg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} shebang-command@2.0.0: @@ -4948,6 +4930,9 @@ packages: resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} engines: {node: '>= 0.4'} + simple-swizzle@0.2.2: + resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} + simple-update-notifier@2.0.0: resolution: {integrity: sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==} engines: {node: '>=10'} @@ -5483,6 +5468,11 @@ packages: zod@3.25.67: resolution: {integrity: sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw==} + zustand-sync-tabs@0.2.2: + resolution: {integrity: sha512-i2pQPm5SGBIq50v7tt6XFXZSR/iJNErOslS5HzMKJVd06+xDyBCXioxEap0Ke6u98+a49fU5QRqzypo21wMe9A==} + peerDependencies: + zustand: 3-5 + zustand@5.0.6: resolution: {integrity: sha512-ihAqNeUVhe0MAD+X8M5UzqyZ9k3FFZLBTtqo6JLPwV53cbRB/mJwBI0PxcIgqhBBHlEs8G45OTDTMq3gNcLq3A==} engines: {node: '>=12.20.0'} @@ -5603,7 +5593,7 @@ snapshots: '@babel/parser': 7.27.7 '@babel/template': 7.27.2 '@babel/types': 7.27.7 - debug: 4.4.1 + debug: 4.4.1(supports-color@5.5.0) globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -5675,7 +5665,7 @@ snapshots: tslib: 2.8.1 optional: true - '@emnapi/runtime@1.8.1': + '@emnapi/runtime@1.4.5': dependencies: tslib: 2.8.1 optional: true @@ -5834,7 +5824,7 @@ snapshots: '@eslint/config-array@0.21.0': dependencies: '@eslint/object-schema': 2.1.6 - debug: 4.4.3 + debug: 4.4.1(supports-color@5.5.0) minimatch: 3.1.2 transitivePeerDependencies: - supports-color @@ -5852,7 +5842,7 @@ snapshots: '@eslint/eslintrc@3.3.1': dependencies: ajv: 6.12.6 - debug: 4.4.1 + debug: 4.4.1(supports-color@5.5.0) espree: 10.4.0 globals: 14.0.0 ignore: 5.3.2 @@ -5920,101 +5910,90 @@ snapshots: '@humanwhocodes/retry@0.4.3': {} - '@img/colour@1.0.0': - optional: true - - '@img/sharp-darwin-arm64@0.34.5': + '@img/sharp-darwin-arm64@0.34.3': optionalDependencies: - '@img/sharp-libvips-darwin-arm64': 1.2.4 + '@img/sharp-libvips-darwin-arm64': 1.2.0 optional: true - '@img/sharp-darwin-x64@0.34.5': + '@img/sharp-darwin-x64@0.34.3': optionalDependencies: - '@img/sharp-libvips-darwin-x64': 1.2.4 + '@img/sharp-libvips-darwin-x64': 1.2.0 optional: true - '@img/sharp-libvips-darwin-arm64@1.2.4': + '@img/sharp-libvips-darwin-arm64@1.2.0': optional: true - '@img/sharp-libvips-darwin-x64@1.2.4': + '@img/sharp-libvips-darwin-x64@1.2.0': optional: true - '@img/sharp-libvips-linux-arm64@1.2.4': + '@img/sharp-libvips-linux-arm64@1.2.0': optional: true - '@img/sharp-libvips-linux-arm@1.2.4': + '@img/sharp-libvips-linux-arm@1.2.0': optional: true - '@img/sharp-libvips-linux-ppc64@1.2.4': + '@img/sharp-libvips-linux-ppc64@1.2.0': optional: true - '@img/sharp-libvips-linux-riscv64@1.2.4': + '@img/sharp-libvips-linux-s390x@1.2.0': optional: true - '@img/sharp-libvips-linux-s390x@1.2.4': + '@img/sharp-libvips-linux-x64@1.2.0': optional: true - '@img/sharp-libvips-linux-x64@1.2.4': + '@img/sharp-libvips-linuxmusl-arm64@1.2.0': optional: true - '@img/sharp-libvips-linuxmusl-arm64@1.2.4': + '@img/sharp-libvips-linuxmusl-x64@1.2.0': optional: true - '@img/sharp-libvips-linuxmusl-x64@1.2.4': - optional: true - - '@img/sharp-linux-arm64@0.34.5': + '@img/sharp-linux-arm64@0.34.3': optionalDependencies: - '@img/sharp-libvips-linux-arm64': 1.2.4 + '@img/sharp-libvips-linux-arm64': 1.2.0 optional: true - '@img/sharp-linux-arm@0.34.5': + '@img/sharp-linux-arm@0.34.3': optionalDependencies: - '@img/sharp-libvips-linux-arm': 1.2.4 + '@img/sharp-libvips-linux-arm': 1.2.0 optional: true - '@img/sharp-linux-ppc64@0.34.5': + '@img/sharp-linux-ppc64@0.34.3': optionalDependencies: - '@img/sharp-libvips-linux-ppc64': 1.2.4 + '@img/sharp-libvips-linux-ppc64': 1.2.0 optional: true - '@img/sharp-linux-riscv64@0.34.5': + '@img/sharp-linux-s390x@0.34.3': optionalDependencies: - '@img/sharp-libvips-linux-riscv64': 1.2.4 + '@img/sharp-libvips-linux-s390x': 1.2.0 optional: true - '@img/sharp-linux-s390x@0.34.5': + '@img/sharp-linux-x64@0.34.3': optionalDependencies: - '@img/sharp-libvips-linux-s390x': 1.2.4 + '@img/sharp-libvips-linux-x64': 1.2.0 optional: true - '@img/sharp-linux-x64@0.34.5': + '@img/sharp-linuxmusl-arm64@0.34.3': optionalDependencies: - '@img/sharp-libvips-linux-x64': 1.2.4 + '@img/sharp-libvips-linuxmusl-arm64': 1.2.0 optional: true - '@img/sharp-linuxmusl-arm64@0.34.5': + '@img/sharp-linuxmusl-x64@0.34.3': optionalDependencies: - '@img/sharp-libvips-linuxmusl-arm64': 1.2.4 + '@img/sharp-libvips-linuxmusl-x64': 1.2.0 optional: true - '@img/sharp-linuxmusl-x64@0.34.5': - optionalDependencies: - '@img/sharp-libvips-linuxmusl-x64': 1.2.4 - optional: true - - '@img/sharp-wasm32@0.34.5': + '@img/sharp-wasm32@0.34.3': dependencies: - '@emnapi/runtime': 1.8.1 + '@emnapi/runtime': 1.4.5 optional: true - '@img/sharp-win32-arm64@0.34.5': + '@img/sharp-win32-arm64@0.34.3': optional: true - '@img/sharp-win32-ia32@0.34.5': + '@img/sharp-win32-ia32@0.34.3': optional: true - '@img/sharp-win32-x64@0.34.5': + '@img/sharp-win32-x64@0.34.3': optional: true '@interactjs/types@1.10.27': {} @@ -6086,44 +6065,39 @@ snapshots: '@tybys/wasm-util': 0.9.0 optional: true - '@next-auth/prisma-adapter@1.0.7(@prisma/client@6.12.0(prisma@6.12.0(typescript@5.8.3))(typescript@5.8.3))(next-auth@4.24.13(next@16.1.1(@babel/core@7.27.7)(@opentelemetry/api@1.9.0)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(nodemailer@7.0.11)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))': + '@next-auth/prisma-adapter@1.0.7(@prisma/client@6.12.0(prisma@6.12.0(typescript@5.8.3))(typescript@5.8.3))(next-auth@4.24.13(next@15.4.8(@babel/core@7.27.7)(@opentelemetry/api@1.9.0)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(nodemailer@7.0.11)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))': dependencies: '@prisma/client': 6.12.0(prisma@6.12.0(typescript@5.8.3))(typescript@5.8.3) - next-auth: 4.24.13(next@16.1.1(@babel/core@7.27.7)(@opentelemetry/api@1.9.0)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(nodemailer@7.0.11)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + next-auth: 4.24.13(next@15.4.8(@babel/core@7.27.7)(@opentelemetry/api@1.9.0)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(nodemailer@7.0.11)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@next-auth/prisma-adapter@1.0.7(@prisma/client@6.12.0(prisma@6.12.0(typescript@5.8.3))(typescript@5.8.3))(next-auth@4.24.13(next@16.1.1(@opentelemetry/api@1.9.0)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(nodemailer@7.0.11)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))': - dependencies: - '@prisma/client': 6.12.0(prisma@6.12.0(typescript@5.8.3))(typescript@5.8.3) - next-auth: 4.24.13(next@16.1.1(@opentelemetry/api@1.9.0)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(nodemailer@7.0.11)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - - '@next/env@16.1.1': {} + '@next/env@15.4.8': {} '@next/eslint-plugin-next@15.4.2': dependencies: fast-glob: 3.3.1 - '@next/swc-darwin-arm64@16.1.1': + '@next/swc-darwin-arm64@15.4.8': optional: true - '@next/swc-darwin-x64@16.1.1': + '@next/swc-darwin-x64@15.4.8': optional: true - '@next/swc-linux-arm64-gnu@16.1.1': + '@next/swc-linux-arm64-gnu@15.4.8': optional: true - '@next/swc-linux-arm64-musl@16.1.1': + '@next/swc-linux-arm64-musl@15.4.8': optional: true - '@next/swc-linux-x64-gnu@16.1.1': + '@next/swc-linux-x64-gnu@15.4.8': optional: true - '@next/swc-linux-x64-musl@16.1.1': + '@next/swc-linux-x64-musl@15.4.8': optional: true - '@next/swc-win32-arm64-msvc@16.1.1': + '@next/swc-win32-arm64-msvc@15.4.8': optional: true - '@next/swc-win32-x64-msvc@16.1.1': + '@next/swc-win32-x64-msvc@15.4.8': optional: true '@nodelib/fs.scandir@2.1.5': @@ -7749,7 +7723,7 @@ snapshots: '@typescript-eslint/types': 8.37.0 '@typescript-eslint/typescript-estree': 8.37.0(typescript@5.8.3) '@typescript-eslint/visitor-keys': 8.37.0 - debug: 4.4.1 + debug: 4.4.1(supports-color@5.5.0) eslint: 9.31.0(jiti@2.4.2) typescript: 5.8.3 transitivePeerDependencies: @@ -7759,7 +7733,7 @@ snapshots: dependencies: '@typescript-eslint/tsconfig-utils': 8.37.0(typescript@5.8.3) '@typescript-eslint/types': 8.37.0 - debug: 4.4.1 + debug: 4.4.1(supports-color@5.5.0) typescript: 5.8.3 transitivePeerDependencies: - supports-color @@ -7778,7 +7752,7 @@ snapshots: '@typescript-eslint/types': 8.37.0 '@typescript-eslint/typescript-estree': 8.37.0(typescript@5.8.3) '@typescript-eslint/utils': 8.37.0(eslint@9.31.0(jiti@2.4.2))(typescript@5.8.3) - debug: 4.4.1 + debug: 4.4.1(supports-color@5.5.0) eslint: 9.31.0(jiti@2.4.2) ts-api-utils: 2.1.0(typescript@5.8.3) typescript: 5.8.3 @@ -7793,7 +7767,7 @@ snapshots: '@typescript-eslint/tsconfig-utils': 8.37.0(typescript@5.8.3) '@typescript-eslint/types': 8.37.0 '@typescript-eslint/visitor-keys': 8.37.0 - debug: 4.4.1 + debug: 4.4.1(supports-color@5.5.0) fast-glob: 3.3.3 is-glob: 4.0.3 minimatch: 9.0.5 @@ -8163,8 +8137,6 @@ snapshots: base64id@2.0.0: {} - baseline-browser-mapping@2.9.14: {} - batch-processor@1.0.0: {} bcp-47-match@2.0.3: {} @@ -8185,7 +8157,7 @@ snapshots: http-errors: 2.0.0 iconv-lite: 0.7.0 on-finished: 2.4.1 - qs: 6.14.1 + qs: 6.14.0 raw-body: 3.0.2 type-is: 2.0.1 transitivePeerDependencies: @@ -8302,6 +8274,18 @@ snapshots: color-name@1.1.4: {} + color-string@1.9.1: + dependencies: + color-name: 1.1.4 + simple-swizzle: 0.2.2 + optional: true + + color@4.2.3: + dependencies: + color-convert: 2.0.1 + color-string: 1.9.1 + optional: true + combined-stream@1.0.8: dependencies: delayed-stream: 1.0.0 @@ -8424,10 +8408,6 @@ snapshots: dependencies: ms: 2.1.3 - debug@4.4.1: - dependencies: - ms: 2.1.3 - debug@4.4.1(supports-color@5.5.0): dependencies: ms: 2.1.3 @@ -8466,9 +8446,6 @@ snapshots: detect-libc@2.0.4: {} - detect-libc@2.1.2: - optional: true - devlop@1.1.0: dependencies: dequal: 2.0.3 @@ -8770,7 +8747,7 @@ snapshots: eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.31.0(jiti@2.4.2)): dependencies: '@nolyfill/is-core-module': 1.0.39 - debug: 4.4.1 + debug: 4.4.1(supports-color@5.5.0) eslint: 9.31.0(jiti@2.4.2) get-tsconfig: 4.10.1 is-bun-module: 2.0.0 @@ -8907,7 +8884,7 @@ snapshots: ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.6 - debug: 4.4.3 + debug: 4.4.1(supports-color@5.5.0) escape-string-regexp: 4.0.0 eslint-scope: 8.4.0 eslint-visitor-keys: 4.2.1 @@ -8978,7 +8955,7 @@ snapshots: once: 1.4.0 parseurl: 1.3.3 proxy-addr: 2.0.7 - qs: 6.14.1 + qs: 6.14.0 range-parser: 1.2.1 router: 2.2.0 send: 1.2.0 @@ -9435,6 +9412,9 @@ snapshots: is-arrayish@0.2.1: {} + is-arrayish@0.3.2: + optional: true + is-async-function@2.1.1: dependencies: async-function: 1.0.0 @@ -10206,34 +10186,17 @@ snapshots: neo-async@2.6.2: {} - next-auth@4.24.13(next@16.1.1(@babel/core@7.27.7)(@opentelemetry/api@1.9.0)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(nodemailer@7.0.11)(react-dom@19.1.0(react@19.1.0))(react@19.1.0): + next-auth@4.24.13(next@15.4.8(@babel/core@7.27.7)(@opentelemetry/api@1.9.0)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(nodemailer@7.0.11)(react-dom@19.1.0(react@19.1.0))(react@19.1.0): dependencies: '@babel/runtime': 7.27.6 '@panva/hkdf': 1.2.1 cookie: 0.7.2 jose: 4.15.9 - next: 16.1.1(@babel/core@7.27.7)(@opentelemetry/api@1.9.0)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + next: 15.4.8(@babel/core@7.27.7)(@opentelemetry/api@1.9.0)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) oauth: 0.9.15 openid-client: 5.7.1 - preact: 10.28.2 - preact-render-to-string: 5.2.6(preact@10.28.2) - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) - uuid: 8.3.2 - optionalDependencies: - nodemailer: 7.0.11 - - next-auth@4.24.13(next@16.1.1(@opentelemetry/api@1.9.0)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(nodemailer@7.0.11)(react-dom@19.1.0(react@19.1.0))(react@19.1.0): - dependencies: - '@babel/runtime': 7.27.6 - '@panva/hkdf': 1.2.1 - cookie: 0.7.2 - jose: 4.15.9 - next: 16.1.1(@opentelemetry/api@1.9.0)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - oauth: 0.9.15 - openid-client: 5.7.1 - preact: 10.28.2 - preact-render-to-string: 5.2.6(preact@10.28.2) + preact: 10.26.9 + preact-render-to-string: 5.2.6(preact@10.26.9) react: 19.1.0 react-dom: 19.1.0(react@19.1.0) uuid: 8.3.2 @@ -10249,54 +10212,27 @@ snapshots: - supports-color - webpack - next@16.1.1(@babel/core@7.27.7)(@opentelemetry/api@1.9.0)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0): + next@15.4.8(@babel/core@7.27.7)(@opentelemetry/api@1.9.0)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0): dependencies: - '@next/env': 16.1.1 + '@next/env': 15.4.8 '@swc/helpers': 0.5.15 - baseline-browser-mapping: 2.9.14 caniuse-lite: 1.0.30001726 postcss: 8.4.31 react: 19.1.0 react-dom: 19.1.0(react@19.1.0) styled-jsx: 5.1.6(@babel/core@7.27.7)(react@19.1.0) optionalDependencies: - '@next/swc-darwin-arm64': 16.1.1 - '@next/swc-darwin-x64': 16.1.1 - '@next/swc-linux-arm64-gnu': 16.1.1 - '@next/swc-linux-arm64-musl': 16.1.1 - '@next/swc-linux-x64-gnu': 16.1.1 - '@next/swc-linux-x64-musl': 16.1.1 - '@next/swc-win32-arm64-msvc': 16.1.1 - '@next/swc-win32-x64-msvc': 16.1.1 + '@next/swc-darwin-arm64': 15.4.8 + '@next/swc-darwin-x64': 15.4.8 + '@next/swc-linux-arm64-gnu': 15.4.8 + '@next/swc-linux-arm64-musl': 15.4.8 + '@next/swc-linux-x64-gnu': 15.4.8 + '@next/swc-linux-x64-musl': 15.4.8 + '@next/swc-win32-arm64-msvc': 15.4.8 + '@next/swc-win32-x64-msvc': 15.4.8 '@opentelemetry/api': 1.9.0 '@playwright/test': 1.52.0 - sharp: 0.34.5 - transitivePeerDependencies: - - '@babel/core' - - babel-plugin-macros - - next@16.1.1(@opentelemetry/api@1.9.0)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0): - dependencies: - '@next/env': 16.1.1 - '@swc/helpers': 0.5.15 - baseline-browser-mapping: 2.9.14 - caniuse-lite: 1.0.30001726 - postcss: 8.4.31 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) - styled-jsx: 5.1.6(react@19.1.0) - optionalDependencies: - '@next/swc-darwin-arm64': 16.1.1 - '@next/swc-darwin-x64': 16.1.1 - '@next/swc-linux-arm64-gnu': 16.1.1 - '@next/swc-linux-arm64-musl': 16.1.1 - '@next/swc-linux-x64-gnu': 16.1.1 - '@next/swc-linux-x64-musl': 16.1.1 - '@next/swc-win32-arm64-msvc': 16.1.1 - '@next/swc-win32-x64-msvc': 16.1.1 - '@opentelemetry/api': 1.9.0 - '@playwright/test': 1.52.0 - sharp: 0.34.5 + sharp: 0.34.3 transitivePeerDependencies: - '@babel/core' - babel-plugin-macros @@ -10517,12 +10453,12 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 - preact-render-to-string@5.2.6(preact@10.28.2): + preact-render-to-string@5.2.6(preact@10.26.9): dependencies: - preact: 10.28.2 + preact: 10.26.9 pretty-format: 3.8.0 - preact@10.28.2: {} + preact@10.26.9: {} prelude-ls@1.2.1: {} @@ -10577,7 +10513,7 @@ snapshots: punycode@2.3.1: {} - qs@6.14.1: + qs@6.14.0: dependencies: side-channel: 1.1.0 @@ -10957,9 +10893,6 @@ snapshots: semver@7.7.2: {} - semver@7.7.3: - optional: true - send@1.2.0: dependencies: debug: 4.4.1(supports-color@5.5.0) @@ -11013,36 +10946,34 @@ snapshots: setprototypeof@1.2.0: {} - sharp@0.34.5: + sharp@0.34.3: dependencies: - '@img/colour': 1.0.0 - detect-libc: 2.1.2 - semver: 7.7.3 + color: 4.2.3 + detect-libc: 2.0.4 + semver: 7.7.2 optionalDependencies: - '@img/sharp-darwin-arm64': 0.34.5 - '@img/sharp-darwin-x64': 0.34.5 - '@img/sharp-libvips-darwin-arm64': 1.2.4 - '@img/sharp-libvips-darwin-x64': 1.2.4 - '@img/sharp-libvips-linux-arm': 1.2.4 - '@img/sharp-libvips-linux-arm64': 1.2.4 - '@img/sharp-libvips-linux-ppc64': 1.2.4 - '@img/sharp-libvips-linux-riscv64': 1.2.4 - '@img/sharp-libvips-linux-s390x': 1.2.4 - '@img/sharp-libvips-linux-x64': 1.2.4 - '@img/sharp-libvips-linuxmusl-arm64': 1.2.4 - '@img/sharp-libvips-linuxmusl-x64': 1.2.4 - '@img/sharp-linux-arm': 0.34.5 - '@img/sharp-linux-arm64': 0.34.5 - '@img/sharp-linux-ppc64': 0.34.5 - '@img/sharp-linux-riscv64': 0.34.5 - '@img/sharp-linux-s390x': 0.34.5 - '@img/sharp-linux-x64': 0.34.5 - '@img/sharp-linuxmusl-arm64': 0.34.5 - '@img/sharp-linuxmusl-x64': 0.34.5 - '@img/sharp-wasm32': 0.34.5 - '@img/sharp-win32-arm64': 0.34.5 - '@img/sharp-win32-ia32': 0.34.5 - '@img/sharp-win32-x64': 0.34.5 + '@img/sharp-darwin-arm64': 0.34.3 + '@img/sharp-darwin-x64': 0.34.3 + '@img/sharp-libvips-darwin-arm64': 1.2.0 + '@img/sharp-libvips-darwin-x64': 1.2.0 + '@img/sharp-libvips-linux-arm': 1.2.0 + '@img/sharp-libvips-linux-arm64': 1.2.0 + '@img/sharp-libvips-linux-ppc64': 1.2.0 + '@img/sharp-libvips-linux-s390x': 1.2.0 + '@img/sharp-libvips-linux-x64': 1.2.0 + '@img/sharp-libvips-linuxmusl-arm64': 1.2.0 + '@img/sharp-libvips-linuxmusl-x64': 1.2.0 + '@img/sharp-linux-arm': 0.34.3 + '@img/sharp-linux-arm64': 0.34.3 + '@img/sharp-linux-ppc64': 0.34.3 + '@img/sharp-linux-s390x': 0.34.3 + '@img/sharp-linux-x64': 0.34.3 + '@img/sharp-linuxmusl-arm64': 0.34.3 + '@img/sharp-linuxmusl-x64': 0.34.3 + '@img/sharp-wasm32': 0.34.3 + '@img/sharp-win32-arm64': 0.34.3 + '@img/sharp-win32-ia32': 0.34.3 + '@img/sharp-win32-x64': 0.34.3 optional: true shebang-command@2.0.0: @@ -11081,6 +11012,11 @@ snapshots: side-channel-map: 1.0.1 side-channel-weakmap: 1.0.2 + simple-swizzle@0.2.2: + dependencies: + is-arrayish: 0.3.2 + optional: true + simple-update-notifier@2.0.0: dependencies: semver: 7.7.2 @@ -11238,11 +11174,6 @@ snapshots: optionalDependencies: '@babel/core': 7.27.7 - styled-jsx@5.1.6(react@19.1.0): - dependencies: - client-only: 0.0.1 - react: 19.1.0 - stylis@4.2.0: {} supports-color@5.5.0: @@ -11712,6 +11643,10 @@ snapshots: zod@3.25.67: {} + zustand-sync-tabs@0.2.2(zustand@5.0.6(@types/react@19.1.8)(react@19.1.0)): + dependencies: + zustand: 5.0.6(@types/react@19.1.8)(react@19.1.0) + zustand@5.0.6(@types/react@19.1.8)(react@19.1.0): optionalDependencies: '@types/react': 19.1.8 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index bcd69006..0b5b71e6 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -23,9 +23,6 @@ overrides: next@>=15.0.0 <=15.4.4: '>=15.4.5' next@>=15.0.0-canary.0 <15.4.7: '>=15.4.7' next@>=15.4.0-canary.0 <15.4.8: '>=15.4.8' - next@>=15.4.0-canary.0 <15.4.9: '>=15.4.9' nodemailer@<7.0.7: '>=7.0.7' nodemailer@<=7.0.10: '>=7.0.11' playwright@<1.55.1: '>=1.55.1' - preact@>=10.26.5 <10.26.10: '>=10.26.10' - qs@<6.14.1: '>=6.14.1'