From 4091626bc84bbe3690d3005093dfa46e33afbdab Mon Sep 17 00:00:00 2001 From: c00b3r Date: Thu, 5 Jun 2025 13:31:21 +0500 Subject: [PATCH] feat: add ghost image and enhance CreateSessionModal with session existence check and improved server handling --- public/images/ghost.png | Bin 0 -> 18991 bytes src/components/DesktopCard.tsx | 5 +- src/components/Layout.tsx | 19 ++++ src/components/TableSelector.tsx | 1 - src/components/modals/CreateSessionModal.tsx | 94 +++++++++++++++---- 5 files changed, 96 insertions(+), 23 deletions(-) create mode 100644 public/images/ghost.png diff --git a/public/images/ghost.png b/public/images/ghost.png new file mode 100644 index 0000000000000000000000000000000000000000..12bc1bb8ad05a4b470eb02d1380e3251b90b0195 GIT binary patch literal 18991 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["servers"]); // const { mutate: createSession } = useMutation({ // mutationFn: () => @@ -34,7 +31,7 @@ export default function DesktopCard({ server }: IDesktopCardProps) { async function handleClickCreateSession() { setPosition("right"); - setModal(); + setModal(); } return ( diff --git a/src/components/Layout.tsx b/src/components/Layout.tsx index ac9d415..4071078 100644 --- a/src/components/Layout.tsx +++ b/src/components/Layout.tsx @@ -5,6 +5,10 @@ import api from "../utils/api"; import CurrentSessionCard from "./CurrentSessionCard"; import { ISession } from "../types/ISession"; import { AnimatePresence } from "motion/react"; +import NewButton from "./NewButton"; +import PlusIcon from "./icons/PlusIcon"; +import useModalStore from "../stores/useModalStore"; +import CreateSessionModal from "./modals/CreateSessionModal"; function Layout() { const { data: currentStartedSessions } = useQuery({ @@ -18,6 +22,8 @@ function Layout() { refetchInterval: 1000, }); + const { setModal, setPosition } = useModalStore(); + return (
@@ -35,6 +41,19 @@ function Layout() { /> ))} + { + setPosition("right"); + setModal(); + }} + > + + + + Создать сеанс +
); diff --git a/src/components/TableSelector.tsx b/src/components/TableSelector.tsx index 40c138b..b23bcf3 100644 --- a/src/components/TableSelector.tsx +++ b/src/components/TableSelector.tsx @@ -13,7 +13,6 @@ function TableSelector({ selectedTable, onSelect, }: TableSelectorProps) { - console.log(tables); return (
{tables.map((table) => ( diff --git a/src/components/modals/CreateSessionModal.tsx b/src/components/modals/CreateSessionModal.tsx index a6634db..17c9b23 100644 --- a/src/components/modals/CreateSessionModal.tsx +++ b/src/components/modals/CreateSessionModal.tsx @@ -10,27 +10,34 @@ import NewInput from "../NewInput.tsx"; import StartSessionIcon from "../icons/StartSessionIcon.tsx"; import NewButton from "../NewButton.tsx"; import ProjectSelector from "../ProjectSelector.tsx"; -import { useQueryClient, useMutation } from "@tanstack/react-query"; +import { useQueryClient, useMutation, useQuery } from "@tanstack/react-query"; + interface Props { - servers: IServer[] | undefined; - targetServer: IServer | null; + targetServerId: string | null; } -export default function CreateSessionModal({ - servers, - targetServer = null, -}: Props) { +export default function CreateSessionModal({ targetServerId }: Props) { const { setModal } = useModalStore(); const [name, setName] = useState(""); const [phone, setPhone] = useState(""); const [email, setEmail] = useState(""); + const [isSessionExists, setIsSessionExists] = useState(false); + const queryClient = useQueryClient(); + + const { data: servers } = useQuery({ + queryKey: ["servers"], + queryFn: () => api.get("servers?withLastSession=true").json(), + }); + + const targetServer = targetServerId + ? servers?.find((server) => server.id === targetServerId) || null + : null; + const [selectedServer, setSelectedServer] = useState( targetServer ); const [selectedApp, setSelectedApp] = useState(null); - const queryClient = useQueryClient(); - const { mutate: createClient } = useMutation({ mutationFn: () => { return api @@ -65,26 +72,61 @@ export default function CreateSessionModal({ }, }); + const { mutate: endSession } = useMutation({ + mutationKey: ["sessions", selectedServer?.sessions?.[0]?.id], + mutationFn: () => + api.put(`sessions/${selectedServer?.sessions?.[0]?.id}`, { + json: { status: "ending" }, + }), + onMutate: () => queryClient.invalidateQueries({ queryKey: ["sessions"] }), + }); + async function handleClickCreateSession(e: React.FormEvent) { e.preventDefault(); if (!name || !phone || !selectedServer || !selectedApp) return; - createClient(undefined, { - onSuccess: (client) => { - createSession(client.id); - }, - onError: (error) => { - console.log(error); - }, - }); + if ( + selectedServer?.sessions?.[0]?.status === "started" && + !isSessionExists + ) { + setIsSessionExists(true); + return; + } + + if (isSessionExists) { + endSession(undefined, { + onSuccess: () => { + createClient(undefined, { + onSuccess: (client) => { + createSession(client.id); + }, + onError: (error) => { + console.log(error); + }, + }); + }, + onError: (error) => { + console.log("Ошибка при завершении сессии:", error); + }, + }); + } else { + createClient(undefined, { + onSuccess: (client) => { + createSession(client.id); + }, + onError: (error) => { + console.log(error); + }, + }); + } } const ref = useRef(null); return (
@@ -131,6 +173,22 @@ export default function CreateSessionModal({ /> )}
+ {isSessionExists && ( +
+ ghost error +
+

Есть текущий сеанс

+

+ {`На выбранном столе есть текущий сеанс. + При запуске нового текущий будет завершен.`} +

+
+
+ )}