upd
This commit is contained in:
@@ -1 +1 @@
|
||||
VITE_API_URL=http://192.168.1.250:3000
|
||||
VITE_API_URL=http://localhost:3000
|
||||
@@ -1,72 +0,0 @@
|
||||
import Button from "./Button";
|
||||
import SessionIcon from "./icons/SessionIcon";
|
||||
import Input from "./Input";
|
||||
import useQueryApps from "../queries/useQueryApps.ts";
|
||||
import useQueryServers from "../queries/useQueryServers.ts";
|
||||
import Select from "./Select.tsx";
|
||||
|
||||
export default function CreateSessionModal() {
|
||||
const { data: apps } = useQueryApps();
|
||||
|
||||
const { data: servers } = useQueryServers();
|
||||
|
||||
return (
|
||||
<div className="w-[27.222vw] h-full rounded-[0.833vw] bg-white p-[1.667vw] flex flex-col justify-between gap-[1.111vw]">
|
||||
<div className="gap-y-[1.111vw] flex flex-col justify-between">
|
||||
<div className="space-y-[0.556vw]">
|
||||
<div className="rounded-[0.556vw] w-fit p-[0.833vw] bg-[#2D68F60D]">
|
||||
<div className="min-w-[1.389vw] min-h-[1.389vw] text-[#2D68F6]">
|
||||
<SessionIcon />
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-[1.389vw]">Создание сеанса</p>
|
||||
<p className="text-[0.833vw] text-black/20">
|
||||
Укажите данные клиента, выберите менеджера и стол
|
||||
</p>
|
||||
</div>
|
||||
<hr className="border-black/10" />
|
||||
<div className="flex justify-between items-center">
|
||||
<p className="text-[0.972vw]">
|
||||
Имя <span className="text-[#C6C6C699]">*</span>
|
||||
</p>
|
||||
<div className="outline outline-black/10 rounded-[0.556vw] w-[13.889vw]">
|
||||
<Input placeholder="Константин" required />
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex justify-between items-center">
|
||||
<p className="text-[0.972vw]">
|
||||
Номер <span className="text-[#C6C6C699]">*</span>
|
||||
</p>
|
||||
<div className="outline outline-black/10 rounded-[0.556vw] w-[13.889vw]">
|
||||
<Input placeholder="+ 7 (999) 99 99 99" required type="tel" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex justify-between items-center">
|
||||
<p className="text-[0.972vw]">Электронная почта</p>
|
||||
<div className="outline outline-black/10 rounded-[0.556vw] w-[13.889vw]">
|
||||
<Input placeholder="sample@mail.ru" type="email" />
|
||||
</div>
|
||||
</div>
|
||||
{apps && (
|
||||
<div className="flex justify-between items-center">
|
||||
<p className="text-[0.972vw]">Приложение</p>
|
||||
<div className="outline outline-black/10 rounded-[0.556vw] w-[13.889vw]">
|
||||
<Select
|
||||
options={apps.map(({ id, name }) => ({ id, value: name }))}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<hr className="border-black/10" />
|
||||
</div>
|
||||
<div className="flex justify-between">
|
||||
<Button className="bg-[#F9F9F9] px-[2.222vw] py-[0.556vw] !rounded-[0.556vw]">
|
||||
<p className="text-black font-medium text-[0.972vw]">Отменить</p>
|
||||
</Button>
|
||||
<Button className="bg-[#2D68F6] px-[2.222vw] py-[0.556vw] !rounded-[0.556vw]">
|
||||
<p className="text-[0.972vw] font-medium">Запустить сеанс</p>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,79 +1,79 @@
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
import { useEffect, useRef } from 'react';
|
||||
import useModalStore from '../stores/useModalStore';
|
||||
import { AnimatePresence, motion } from 'motion/react';
|
||||
import CloseIcon from './icons/CloseIcon';
|
||||
import Button from './Button';
|
||||
|
||||
const duration = 300;
|
||||
import { useEffect, useRef } from "react";
|
||||
import useModalStore from "../stores/useModalStore";
|
||||
import { AnimatePresence, motion } from "motion/react";
|
||||
import CloseIcon from "./icons/CloseIcon";
|
||||
import Button from "./Button";
|
||||
import { clsx as cn } from "clsx";
|
||||
|
||||
function ModalContainer() {
|
||||
const { modal, setModal, isOpen, setIsOpen } = useModalStore();
|
||||
const { modal, setModal, position } = useModalStore();
|
||||
const divRef = useRef<HTMLDivElement>(null);
|
||||
const buttonRef = useRef<HTMLDivElement>(null);
|
||||
const backdropRef = useRef<HTMLDivElement>(null);
|
||||
const popoverRef = useRef<HTMLDivElement>(null);
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
function handleResize() {
|
||||
if (!popoverRef.current) return;
|
||||
|
||||
if (divRef.current!.clientHeight > popoverRef.current!.clientHeight) {
|
||||
buttonRef.current!.style.height = `${divRef.current!.clientHeight}px`;
|
||||
backdropRef.current!.style.height = `${divRef.current!.clientHeight}px`;
|
||||
} else {
|
||||
buttonRef.current!.style.height = `100%`;
|
||||
backdropRef.current!.style.height = `100%`;
|
||||
}
|
||||
}
|
||||
|
||||
function handleKeydown(e: KeyboardEvent) {
|
||||
if (e.key !== 'Escape') return;
|
||||
setIsOpen(false);
|
||||
if (e.key !== "Escape") return;
|
||||
setModal(null);
|
||||
}
|
||||
|
||||
useEffect(() => setIsOpen(!!modal), [modal]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isOpen) return;
|
||||
|
||||
setTimeout(() => {
|
||||
setModal(null);
|
||||
}, duration);
|
||||
}, [isOpen]);
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener('resize', handleResize);
|
||||
window.addEventListener('keydown', handleKeydown);
|
||||
window.addEventListener("resize", handleResize);
|
||||
window.addEventListener("keydown", handleKeydown);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('resize', handleResize);
|
||||
window.removeEventListener('keydown', handleKeydown);
|
||||
window.removeEventListener("resize", handleResize);
|
||||
window.removeEventListener("keydown", handleKeydown);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<AnimatePresence>
|
||||
{isOpen && (
|
||||
{modal && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
className={`h-full transition-opacity duration-300`}
|
||||
className="h-full"
|
||||
>
|
||||
<div
|
||||
ref={popoverRef}
|
||||
className="fixed inset-0 bg-black/70 overflow-y-auto flex flex-col items-end justify-center"
|
||||
className={cn(
|
||||
"fixed inset-0 bg-black/70 overflow-y-auto flex flex-col justify-center",
|
||||
position === "center" && "items-center",
|
||||
position === "right" && "items-end"
|
||||
)}
|
||||
>
|
||||
<div className="max-h-full">
|
||||
<div ref={divRef} className="p-[0.972vw] h-dvh">
|
||||
<div ref={divRef} className="p-[0.972vw]">
|
||||
<div
|
||||
ref={buttonRef}
|
||||
ref={backdropRef}
|
||||
className="absolute inset-0 cursor-pointer"
|
||||
onClick={() => setIsOpen(false)}
|
||||
onClick={() => setModal(null)}
|
||||
/>
|
||||
<div className="relative w-full h-full">
|
||||
<div
|
||||
ref={containerRef}
|
||||
className="relative w-full"
|
||||
// style={{
|
||||
// height: `calc(${backdropRef.current?.clientHeight}px - 0.972vw * 2)`,
|
||||
// }}
|
||||
>
|
||||
{modal}
|
||||
<Button
|
||||
onlyIcon
|
||||
className="absolute top-[1.667vw] right-[1.667vw] p-[0.556vw] !rounded-full bg-[#F9F9F9]"
|
||||
onClick={() => setIsOpen(false)}
|
||||
onClick={() => setModal(null)}
|
||||
>
|
||||
<span className="w-[1.389vw] h-[1.389vw] text-black">
|
||||
<CloseIcon />
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { IServer } from '../../types/IServer.ts';
|
||||
import Button from '../Button.tsx';
|
||||
import Input from '../Input.tsx';
|
||||
import DisplayIcon from '../icons/DisplayIcon.tsx';
|
||||
import { IServer } from "../../types/IServer.ts";
|
||||
import Button from "../Button.tsx";
|
||||
import Input from "../Input.tsx";
|
||||
import DisplayIcon from "../icons/DisplayIcon.tsx";
|
||||
|
||||
interface Props {
|
||||
servers: IServer[];
|
||||
@@ -9,7 +9,7 @@ interface Props {
|
||||
|
||||
export default function CreateSessionModal({ servers }: Props) {
|
||||
return (
|
||||
<div className="w-[34.375vw] rounded-[0.833vw] bg-white min-h-full p-[1.667vw] flex flex-col justify-between gap-[1.111vw]">
|
||||
<div className="w-[34.375vw] rounded-[0.833vw] bg-white p-[1.667vw] flex flex-col min-h-[calc(100dvh-0.972vw*2)] justify-between gap-[1.111vw]">
|
||||
<div className="gap-y-[1.111vw] flex flex-col justify-between">
|
||||
<div className="space-y-[0.556vw]">
|
||||
<div className="p-[0.833vw] ring-[0.069vw] ring-[#E6E6E6] w-fit rounded-[0.556vw]">
|
||||
|
||||
+20
-33
@@ -1,27 +1,32 @@
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { IUser } from '../types/IUser';
|
||||
import api from '../utils/api';
|
||||
import Sidebar from '../components/Sidebar';
|
||||
import { IServer } from '../types/IServer';
|
||||
import DesktopCard from '../components/DesktopCard';
|
||||
import Button from '../components/Button';
|
||||
import useModalStore from '../stores/useModalStore';
|
||||
import CreateSessionModal from '../components/modals/CreateSessionModal';
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { IUser } from "../types/IUser";
|
||||
import api from "../utils/api";
|
||||
import Sidebar from "../components/Sidebar";
|
||||
import { IServer } from "../types/IServer";
|
||||
import DesktopCard from "../components/DesktopCard";
|
||||
import Button from "../components/Button";
|
||||
import useModalStore from "../stores/useModalStore";
|
||||
import CreateSessionModal from "../components/modals/CreateSessionModal";
|
||||
|
||||
function DashboardPage() {
|
||||
const { data: me } = useQuery({
|
||||
queryKey: ['me'],
|
||||
queryFn: () => api.get('users/me').json<IUser>(),
|
||||
queryKey: ["me"],
|
||||
queryFn: () => api.get("users/me").json<IUser>(),
|
||||
});
|
||||
|
||||
const { data: servers } = useQuery({
|
||||
queryKey: ['servers'],
|
||||
queryFn: () => api.get('servers?withLastSession=true').json<IServer[]>(),
|
||||
queryKey: ["servers"],
|
||||
queryFn: () => api.get("servers?withLastSession=true").json<IServer[]>(),
|
||||
enabled: !!me,
|
||||
refetchInterval: 1000,
|
||||
});
|
||||
|
||||
const { setModal } = useModalStore();
|
||||
const { setModal, setPosition } = useModalStore();
|
||||
|
||||
function handleClickCreateSession() {
|
||||
setPosition("right");
|
||||
setModal(<CreateSessionModal servers={servers || []} />);
|
||||
}
|
||||
|
||||
// async function logout() {
|
||||
// return await api.get("auth/logout").json();
|
||||
@@ -37,22 +42,6 @@ function DashboardPage() {
|
||||
// }
|
||||
|
||||
return (
|
||||
// <div className="space-y-6">
|
||||
// <Header />
|
||||
// <div className="w-[952px] min-w-[952px] mx-auto">
|
||||
// <div className="flex gap-5">
|
||||
// <Sidebar />
|
||||
// <div className="main-content flex-1 bg-white rounded-xl p-8 w-full space-y-5">
|
||||
// {/* Main content */}
|
||||
// {servers?.map((server) => (
|
||||
// <DesktopCard key={server.id} server={server} />
|
||||
// ))}
|
||||
// </div>
|
||||
// </div>
|
||||
|
||||
// </div>
|
||||
// </div>
|
||||
|
||||
<div className="p-[0.833vw] flex gap-[0.833vw] h-dvh">
|
||||
<div className="w-[3.333vw] flex flex-col justify-between"></div>
|
||||
<div className="bg-white w-full rounded-[1.667vw] border border-black/5 p-[1.667vw] flex justify-between">
|
||||
@@ -74,9 +63,7 @@ function DashboardPage() {
|
||||
</div>
|
||||
</div>
|
||||
<div className="bg-green-200 w-[13.889vw]">
|
||||
<Button onClick={() => setModal(<CreateSessionModal />)}>
|
||||
открыть
|
||||
</Button>
|
||||
<Button onClick={handleClickCreateSession}>открыть</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -3,19 +3,25 @@ import { ReactNode } from "react";
|
||||
import { devtools } from "zustand/middleware";
|
||||
|
||||
interface State {
|
||||
isOpen: boolean;
|
||||
setIsOpen: (isOpen: boolean) => void;
|
||||
modal: ReactNode | null;
|
||||
setModal: (modal: ReactNode | null) => void;
|
||||
position: "center" | "right";
|
||||
setPosition: (position: "center" | "right") => void;
|
||||
}
|
||||
|
||||
const useModalStore = create<State>()(
|
||||
devtools(
|
||||
(set) => ({
|
||||
isOpen: false,
|
||||
setIsOpen: (isOpen) => set({ isOpen }),
|
||||
modal: null,
|
||||
setModal: (modal) => set({ modal }),
|
||||
setModal: (modal) => {
|
||||
if (!modal) {
|
||||
set({ position: "center" });
|
||||
}
|
||||
|
||||
set({ modal });
|
||||
},
|
||||
position: "center",
|
||||
setPosition: (position) => set({ position }),
|
||||
}),
|
||||
{
|
||||
name: "modal",
|
||||
|
||||
Reference in New Issue
Block a user