This commit is contained in:
2025-06-04 16:43:21 +05:00
parent 411281c574
commit 931e468e75
5 changed files with 164 additions and 107 deletions
+61 -51
View File
@@ -10,7 +10,7 @@ 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";
interface Props {
servers: IServer[] | undefined;
targetServer: IServer | null;
@@ -28,89 +28,99 @@ export default function CreateSessionModal({
targetServer
);
const [selectedApp, setSelectedApp] = useState<IApp | null>(null);
const queryClient = useQueryClient();
async function createClient() {
return await api
.post("clients", {
json: {
name,
phone,
email,
},
})
.json<IClient>();
}
const { mutate: createClient } = useMutation({
mutationFn: () => {
return api
.post("clients", {
json: {
name,
phone,
email,
},
})
.json<IClient>();
},
});
async function createSession(clientId: string) {
return await api
.post("sessions", {
json: {
clientId,
serverId: selectedServer?.id,
appId: selectedApp?.id,
},
})
.json<ISession>();
}
const { mutate: createSession } = useMutation({
mutationFn: (clientId: string) => {
return api
.post("sessions", {
json: {
clientId,
serverId: selectedServer?.id,
appId: selectedApp?.id,
},
})
.json<ISession>();
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["sessions"] });
queryClient.invalidateQueries({ queryKey: ["servers"] });
setModal(null);
},
});
async function handleClickCreateSession(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();
if (!name || !phone || !selectedServer || !selectedApp) return;
try {
const client = await createClient();
await createSession(client.id);
setModal(null);
} catch (error) {
console.log(error);
}
createClient(undefined, {
onSuccess: (client) => {
createSession(client.id);
},
onError: (error) => {
console.log(error);
},
});
}
const ref = useRef<HTMLFormElement>(null);
return (
<form
className='rounded-[2.222vw] w-[25vw] min-h-[calc(100dvh-2.222vw)] bg-[#F0F0F0] flex flex-col overflow-hidden'
className="rounded-[2.222vw] w-[25vw] min-h-[calc(100dvh-2.222vw)] bg-[#F0F0F0] flex flex-col overflow-hidden"
onSubmit={handleClickCreateSession}
ref={ref}
>
<div className='w-full h-[4.861vw] flex items-center justify-center'>
<p className='title-s font-medium'>Новый сеанс</p>
<div className="w-full h-[4.861vw] flex items-center justify-center">
<p className="title-s font-medium">Новый сеанс</p>
</div>
<div className='w-full h-[6.944vw] bg-[url(/images/Table.png)] bg-no-repeat bg-top bg-[length:9.306vw]' />
<div className='bg-white rounded-t-[2.222vw] p-[1.389vw] flex flex-col gap-y-[1.667vw] flex-1 overflow-y-auto'>
<div className="w-full h-[6.944vw] bg-[url(/images/Table.png)] bg-no-repeat bg-top bg-[length:9.306vw]" />
<div className="bg-white rounded-t-[2.222vw] p-[1.389vw] flex flex-col gap-y-[1.667vw] flex-1 overflow-y-auto">
<TableSelector
tables={servers || []}
selectedTable={selectedServer}
onSelect={setSelectedServer}
/>
<div className='flex flex-col gap-y-[0.833vw]'>
<p className='title-s font-medium'>Укажите данные клиента</p>
<div className='flex flex-col gap-y-[0.556vw]'>
<div className="flex flex-col gap-y-[0.833vw]">
<p className="title-s font-medium">Укажите данные клиента</p>
<div className="flex flex-col gap-y-[0.556vw]">
<NewInput
value={phone}
onChange={(e) => setPhone(e.target.value)}
placeholder='Номер телефона'
placeholder="Номер телефона"
required
/>
<NewInput
value={name}
onChange={(e) => setName(e.target.value)}
placeholder='Имя'
placeholder="Имя"
required
/>
<NewInput
type='email'
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder='Электронная почта'
placeholder="Электронная почта"
/>
</div>
</div>
<div className='flex flex-col gap-y-[0.833vw]'>
<p className='title-s font-medium'>Выберите параметры сеанса</p>
<div className="flex flex-col gap-y-[0.833vw]">
<p className="title-s font-medium">Выберите параметры сеанса</p>
{selectedServer?.apps?.length && selectedServer?.apps?.length > 0 && (
<ProjectSelector
projects={selectedServer?.apps || []}
@@ -120,16 +130,16 @@ export default function CreateSessionModal({
)}
</div>
<NewButton
type='submit'
type="submit"
disabled={
!ref.current?.checkValidity() || !selectedServer || !selectedApp
}
variant='cta'
size='large'
className='sticky bottom-[1.111vw]'
variant="cta"
size="large"
className="sticky bottom-[1.111vw]"
>
<div className='rounded-full bg-[#9184F6] in-disabled:bg-transparent px-[0.278vw] py-[0.208vw] size-[1.111vw]'>
<div className='w-[0.694vw] h-[0.556vw]'>
<div className="rounded-full bg-[#9184F6] in-disabled:bg-transparent px-[0.278vw] py-[0.208vw] size-[1.111vw]">
<div className="w-[0.694vw] h-[0.556vw]">
<StartSessionIcon />
</div>
</div>
+75 -21
View File
@@ -2,55 +2,109 @@ import { IServer } from "../../types/IServer";
import FlashIcon from "../icons/FlashIcon";
import NewButton from "../NewButton";
import ChevronRightIcon from "../icons/ChevronRightIcon";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import api from "../../utils/api";
import useModalStore from "../../stores/useModalStore";
import { ISession } from "../../types/ISession";
function CurrentSessionModal({ server }: { server: IServer }) {
console.log(server.client?.name);
const queryClient = useQueryClient();
const { setModal } = useModalStore();
const { mutate: endSession } = useMutation({
mutationKey: ["sessions", server.sessions?.[0]?.id],
mutationFn: () =>
api.put(`sessions/${server.sessions?.[0]?.id}`, {
json: { status: "ending" },
}),
onMutate: () => queryClient.invalidateQueries({ queryKey: ["sessions"] }),
});
const { data: currentServer } = useQuery({
queryKey: ["sessions", server.sessions?.[0]?.id],
queryFn: () =>
api.get(`sessions/${server.sessions?.[0]?.id}`).json<ISession>(),
});
console.log(currentServer);
return (
<div className='w-[25vw] bg-[#FFFFFF] rounded-4xl px-[1.389vw]'>
<h2 className='title-s font-medium text-center py-[1.806vw]'>
<div className="w-[25vw] bg-[#FFFFFF] rounded-4xl px-[1.389vw] pb-[1.389vw]">
<h2 className="title-s font-medium text-center py-[1.806vw]">
Текущий сеанс
</h2>
<div className='flex flex-col gap-[1.667vw]'>
<div className='py-[1.389vw] flex gap-[0.833vw] border border-b-[#F6F6F6] border-t-0 border-r-0 border-l-0'>
<div className="flex flex-col gap-[1.667vw]">
<div className="py-[1.389vw] flex gap-[0.833vw] border border-b-[#F6F6F6] border-t-0 border-r-0 border-l-0">
<div className='size-[4.444vw] bg-[#F6F6F6] rounded-xl bg-[url("/images/super-table.png")] bg-no-repeat bg-[length:2.222vw] bg-center'></div>
<div className='flex flex-col gap-[0.278vw] self-center '>
<div className='flex gap-[0.278vw]'>
<p className='title-s font-medium'>{server.name}</p>
<p className='flex justify-center items-center gap-[0.139vw] caption-s font-medium text-[#7B60F3]'>
<div className="flex flex-col gap-[0.278vw] self-center ">
<div className="flex gap-[0.278vw]">
<p className="title-s font-medium">{server.name}</p>
<p className="flex justify-center items-center gap-[0.139vw] caption-s font-medium text-[#7B60F3]">
<FlashIcon />
Сеанс идёт 24:05
</p>
</div>
<div>
<p className='caption-s font-medium text-[#BDBDBD]'>
<p className="caption-s font-medium text-[#BDBDBD]">
{server.location}
</p>
</div>
</div>
</div>
<div className='flex flex-col gap-[0.833vw]'>
<h2 className='title-s font-medium'>Параметры сеанса</h2>
<div className="flex flex-col gap-[0.833vw]">
<h2 className="title-s font-medium">Параметры сеанса</h2>
<div>
<NewButton variant='secondary' className='w-full'>
<div className='flex flex-col gap-[0.278vw] w-full text-left h-[2.222vw]'>
<p className='caption-s font-medium text-[#BDBDBD]'>Клиент</p>
<p className='text-s font-medium'>{server.client?.name}</p>
<NewButton variant="secondary" className="w-full">
<div className="flex flex-col gap-[0.278vw] w-full text-left h-[2.222vw]">
<p className="caption-s font-medium text-[#BDBDBD]">Клиент</p>
<p className="text-s font-medium">{server.client?.name}</p>
</div>
<div className='flex gap-[0.556vw] items-center w-[7.639vw]'>
<div className="flex gap-[0.556vw] items-center">
{!server.client?.email && (
<p className='caption-s font-medium text-[#7B60F3] whitespace-nowrap'>
<p className="caption-s font-medium text-[#7B60F3] whitespace-nowrap">
Добавьте email
</p>
)}
<span className='w-[1.389vw] h-[1.389vw] flex items-center justify-center text-[#7B60F3]'>
<span className="w-[1.389vw] h-[1.389vw] flex items-center justify-center text-[#7B60F3]">
<ChevronRightIcon />
</span>
</div>
</NewButton>
</div>
</div>
<div>
<h2 className='title-s font-medium'>Детали</h2>
<div className="flex flex-col gap-[0.833vw]">
<h2 className="title-s font-medium">Детали</h2>
<div>
<div className="flex gap-[0.556vw]">
<p className="caption-s font-medium text-[#BDBDBD]">Менеджер:</p>
<p className="caption-s font-medium">{server.owner?.fullname}</p>
</div>
<div className="flex gap-[0.556vw]">
<p className="caption-s font-medium text-[#BDBDBD]">
Сценарии проживания:
</p>
<p className="caption-s font-medium">Добавить в бэкенд</p>
</div>
</div>
</div>
<div className="flex flex-col gap-[0.556vw]">
<NewButton
variant="critical"
className="w-full"
onClick={() => {
endSession();
setModal(null);
}}
>
Завершить сеанс
</NewButton>
<NewButton
variant="primary"
className="w-full"
onClick={() => setModal(null)}
>
Закрыть
</NewButton>
</div>
</div>
</div>
+1
View File
@@ -27,6 +27,7 @@ function EditTable({ table }: { table: IServer }) {
setModal(null);
},
});
return (
<div className='bg-[#F0F0F0] rounded-4xl w-[25vw] flex flex-col justify-center items-center'>
<h3 className='title-s font-medium py-[1.806vw]'>Редатирование стола</h3>