From 31f52765f93168936b7a46264944f65526a2e456 Mon Sep 17 00:00:00 2001 From: Lanskikh Date: Wed, 4 Jun 2025 19:41:00 +0500 Subject: [PATCH] upd --- .env | 6 +- bun.lock | 3 + package.json | 1 + src/components/CurrentSessionCard.tsx | 68 +++++++++++++++++++ src/components/Layout.tsx | 30 +++++++- src/components/SessionCard.tsx | 13 ++-- src/components/icons/FlashIcon.tsx | 12 ++-- src/components/modals/CreateSessionModal.tsx | 6 +- src/components/modals/CurrentSessionModal.tsx | 57 ++++++++++++++-- src/pages/DashboardPage.tsx | 30 ++++---- src/types/IServer.ts | 4 -- src/types/ISession.ts | 1 + 12 files changed, 183 insertions(+), 48 deletions(-) create mode 100644 src/components/CurrentSessionCard.tsx diff --git a/.env b/.env index 26dcac8..a87f462 100644 --- a/.env +++ b/.env @@ -1,5 +1 @@ -<<<<<<< HEAD -VITE_API_URL=http://192.168.1.204:3000/ -======= -VITE_API_URL=http://192.168.1.204:3000 ->>>>>>> b8d191113582cbbfeaea9d0bea544c445a25c2ac +VITE_API_URL=http://192.168.1.170:3000/ diff --git a/bun.lock b/bun.lock index f8b40bd..6e89087 100644 --- a/bun.lock +++ b/bun.lock @@ -10,6 +10,7 @@ "@tanstack/react-query": "^5.67.3", "@uidotdev/usehooks": "^2.4.1", "clsx": "^2.1.1", + "date-fns": "^4.1.0", "ky": "^1.7.5", "motion": "^12.5.0", "react": "^19.0.0", @@ -381,6 +382,8 @@ "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="], + "date-fns": ["date-fns@4.1.0", "", {}, "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg=="], + "debug": ["debug@4.4.0", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA=="], "dedent": ["dedent@1.5.3", "", { "peerDependencies": { "babel-plugin-macros": "^3.1.0" }, "optionalPeers": ["babel-plugin-macros"] }, "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ=="], diff --git a/package.json b/package.json index 2eb888c..1dfa3a8 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "@tanstack/react-query": "^5.67.3", "@uidotdev/usehooks": "^2.4.1", "clsx": "^2.1.1", + "date-fns": "^4.1.0", "ky": "^1.7.5", "motion": "^12.5.0", "react": "^19.0.0", diff --git a/src/components/CurrentSessionCard.tsx b/src/components/CurrentSessionCard.tsx new file mode 100644 index 0000000..824bff4 --- /dev/null +++ b/src/components/CurrentSessionCard.tsx @@ -0,0 +1,68 @@ +import FlashIcon from "./icons/FlashIcon"; +import { ISession } from "../types/ISession"; +import NewButton from "./NewButton"; +import api from "../utils/api"; +import { useMutation, useQueryClient } from "@tanstack/react-query"; +import ChevronRightIcon from "./icons/ChevronRightIcon"; +import { motion } from "motion/react"; + +function CurrentSessionCard({ + session, + index, +}: { + session: ISession; + index: number; +}) { + const queryClient = useQueryClient(); + + const { mutate: endSession } = useMutation({ + mutationKey: ["sessions", session.id], + mutationFn: () => + api.put(`sessions/${session.id}`, { json: { status: "ending" } }), + onMutate: () => { + queryClient.invalidateQueries({ queryKey: ["sessions"] }); + queryClient.invalidateQueries({ queryKey: ["last-started"] }); + queryClient.invalidateQueries({ queryKey: ["servers"] }); + }, + }); + + return ( + +
+ + + +
+

+ Текущий сеанс +

+
+

+ {session.server.name} +

+
+

+ {session.owner.fullname} +

+
+
+ + + +
+ endSession()}> + Завершить сеанс + + + ); +} + +export default CurrentSessionCard; diff --git a/src/components/Layout.tsx b/src/components/Layout.tsx index 9a128ce..ac9d415 100644 --- a/src/components/Layout.tsx +++ b/src/components/Layout.tsx @@ -1,15 +1,41 @@ import { Outlet } from "react-router"; import Navbar from "./Navbar"; +import { useQuery } from "@tanstack/react-query"; +import api from "../utils/api"; +import CurrentSessionCard from "./CurrentSessionCard"; +import { ISession } from "../types/ISession"; +import { AnimatePresence } from "motion/react"; function Layout() { + const { data: currentStartedSessions } = useQuery({ + queryKey: ["sessions", "last-started"], + queryFn: () => + api + .get("sessions", { + searchParams: { limit: 3, status: "started" }, + }) + .json(), + refetchInterval: 1000, + }); + return ( -
+
-
+
+ + {currentStartedSessions?.map((session, index, { length }) => ( + + ))} + +
); } diff --git a/src/components/SessionCard.tsx b/src/components/SessionCard.tsx index 707c99c..db1f79f 100644 --- a/src/components/SessionCard.tsx +++ b/src/components/SessionCard.tsx @@ -1,14 +1,13 @@ import { ISession } from "../types/ISession"; function SessionCard({ session }: { session: ISession }) { - console.log(session); return ( -
-
-
-
-

{session.owner.fullname}

-

+

+
+
+
+

{session.owner.fullname}

+

Клиент: {session.client.name} •  {session.app.name}

diff --git a/src/components/icons/FlashIcon.tsx b/src/components/icons/FlashIcon.tsx index bfa2724..85995c5 100644 --- a/src/components/icons/FlashIcon.tsx +++ b/src/components/icons/FlashIcon.tsx @@ -1,15 +1,13 @@ function FlashIcon() { return ( ); diff --git a/src/components/modals/CreateSessionModal.tsx b/src/components/modals/CreateSessionModal.tsx index babf83e..a6634db 100644 --- a/src/components/modals/CreateSessionModal.tsx +++ b/src/components/modals/CreateSessionModal.tsx @@ -28,6 +28,7 @@ export default function CreateSessionModal({ targetServer ); const [selectedApp, setSelectedApp] = useState(null); + const queryClient = useQueryClient(); const { mutate: createClient } = useMutation({ @@ -56,8 +57,9 @@ export default function CreateSessionModal({ }) .json(); }, - onSuccess: () => { + onMutate: () => { queryClient.invalidateQueries({ queryKey: ["sessions"] }); + queryClient.invalidateQueries({ queryKey: ["last-started"] }); queryClient.invalidateQueries({ queryKey: ["servers"] }); setModal(null); }, @@ -121,7 +123,7 @@ export default function CreateSessionModal({

Выберите параметры сеанса

- {selectedServer?.apps?.length && selectedServer?.apps?.length > 0 && ( + {selectedServer?.apps && selectedServer?.apps?.length > 0 && ( queryClient.invalidateQueries({ queryKey: ["sessions"] }), }); - const { data: currentServer } = useQuery({ + const { data: currentSession } = useQuery({ queryKey: ["sessions", server.sessions?.[0]?.id], queryFn: () => api.get(`sessions/${server.sessions?.[0]?.id}`).json(), }); - console.log(currentServer); + console.log(currentSession); + + const [now, setNow] = useState(Date.now()); + + useEffect(() => { + const interval = setInterval(() => { + setNow(Date.now()); + }, 1000); + return () => clearInterval(interval); + }, []); + + useEffect(() => { + if (!currentSession) return; + const duration = intervalToDuration({ + start: currentSession.createdAt, + end: now, + }); + const hours = (duration.hours || 0).toString().padStart(2, "0"); + const minutes = (duration.minutes || 0).toString().padStart(2, "0"); + const seconds = (duration.seconds || 0).toString().padStart(2, "0"); + console.log(`${hours}:${minutes}:${seconds}`); + }, [currentSession, now]); + + if (!currentSession) return null; return (
@@ -41,7 +66,23 @@ function CurrentSessionModal({ server }: { server: IServer }) {

{server.name}

- Сеанс идёт 24:05 + Сеанс идёт{" "} + {(() => { + const duration = intervalToDuration({ + start: currentSession.createdAt, + end: now, + }); + const hours = (duration.hours || 0) + .toString() + .padStart(2, "0"); + const minutes = (duration.minutes || 0) + .toString() + .padStart(2, "0"); + const seconds = (duration.seconds || 0) + .toString() + .padStart(2, "0"); + return `${hours}:${minutes}:${seconds}`; + })()}

@@ -57,10 +98,12 @@ function CurrentSessionModal({ server }: { server: IServer }) {

Клиент

-

{server.client?.name}

+

+ {currentSession.client.name} +

- {!server.client?.email && ( + {!currentSession.client.email && (

Добавьте email

@@ -77,7 +120,9 @@ function CurrentSessionModal({ server }: { server: IServer }) {

Менеджер:

-

{server.owner?.fullname}

+

+ {currentSession.owner.fullname} +

diff --git a/src/pages/DashboardPage.tsx b/src/pages/DashboardPage.tsx index 1ada217..70f2d5e 100644 --- a/src/pages/DashboardPage.tsx +++ b/src/pages/DashboardPage.tsx @@ -43,25 +43,25 @@ function DashboardPage() { // } return ( -

-
-
-
-

Интерактивные столы

+
+
+
+
+

Интерактивные столы

-
+
{servers?.map((server) => ( ))}
-
-
-

Последние сеансы

-
-
+
+
+

Последние сеансы

+
+
{sessions ?.filter((session) => session.status === "ended") .map((session) => ( @@ -69,12 +69,12 @@ function DashboardPage() { ))}

Смотреть всё

- +
diff --git a/src/types/IServer.ts b/src/types/IServer.ts index f9f6bd4..03b3b0f 100644 --- a/src/types/IServer.ts +++ b/src/types/IServer.ts @@ -1,6 +1,4 @@ import { IApp } from "./IApp"; -import { IClient } from "./IClient"; -import { IOwner } from "./IOwner"; import { ISession } from "./ISession"; export interface IServer { @@ -12,6 +10,4 @@ export interface IServer { sessions?: ISession[]; apps?: IApp[]; status: "online" | "offline"; - client?: IClient; - owner?: IOwner; } diff --git a/src/types/ISession.ts b/src/types/ISession.ts index 15bda42..7461e3b 100644 --- a/src/types/ISession.ts +++ b/src/types/ISession.ts @@ -14,4 +14,5 @@ export interface ISession { client: IUser; app: IApp; owner: IOwner; + createdAt: Date; }