180 lines
5.3 KiB
TypeScript
180 lines
5.3 KiB
TypeScript
/* eslint-disable react-hooks/exhaustive-deps */
|
||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||
/* eslint-disable no-irregular-whitespace */
|
||
import { Trans } from "react-i18next";
|
||
import useSidebarTabStore from "../stores/useSidebarStore";
|
||
import TimeSelector from "./TimeSelector";
|
||
import CloseIcon from "./icons/CloseIcon";
|
||
import { eachMinuteOfInterval, format, parse, parseISO } from "date-fns";
|
||
import i18n from "../i18n";
|
||
import { enUS, ru } from "date-fns/locale";
|
||
import ky from "ky";
|
||
import { useEffect, useState } from "react";
|
||
|
||
function SidebarTab2() {
|
||
const [
|
||
currentTab,
|
||
setCurrentTab,
|
||
setIsOpen,
|
||
setSelectedTime,
|
||
selectedDay,
|
||
selectedTime,
|
||
buildId,
|
||
] = useSidebarTabStore((state) => [
|
||
state.currentTab,
|
||
state.setCurrentTab,
|
||
state.setIsOpen,
|
||
state.setSelectedTime,
|
||
state.selectedDay,
|
||
state.selectedTime,
|
||
state.buildId,
|
||
]);
|
||
const [scheduledSessions, setScheduledSessions] = useState<any[]>();
|
||
const [schedule, setSchedule] = useState<{ [key: string]: any }>();
|
||
const [scheduleTimes, setScheduleTimes] = useState<any[]>();
|
||
|
||
function handleSelectTime(time: string) {
|
||
setSelectedTime(time);
|
||
setCurrentTab(currentTab + 1);
|
||
}
|
||
|
||
async function getSchedule() {
|
||
if (!selectedDay) return;
|
||
|
||
try {
|
||
const result: { [key: string]: any } = await ky
|
||
.get(
|
||
`${import.meta.env.VITE_CRM_API_URL}/schedules/builds/${buildId}?date=${selectedDay.toISOString()}`
|
||
)
|
||
.json();
|
||
|
||
setSchedule(result);
|
||
} catch (error) {
|
||
if (error instanceof Error) {
|
||
console.log("Error: ", error.message);
|
||
}
|
||
}
|
||
}
|
||
|
||
function generateScheduleTimes() {
|
||
if (!schedule || !scheduledSessions) return;
|
||
|
||
const step = schedule.sessionDuration + schedule.sessionBreak;
|
||
const times = eachMinuteOfInterval(
|
||
{
|
||
start: parse(schedule.startTime, "HH:mm", new Date()),
|
||
end: parse(schedule.endTime, "HH:mm", new Date()),
|
||
},
|
||
{ step }
|
||
);
|
||
|
||
const formatTimes = times.map((time) => ({
|
||
value: format(time, "HH:mm"),
|
||
active:
|
||
scheduledSessions.filter(
|
||
(scheduledSession) => scheduledSession.startAt === time.toISOString()
|
||
).length < 3,
|
||
}));
|
||
|
||
setScheduleTimes(formatTimes);
|
||
}
|
||
|
||
async function getScheduledSessions() {
|
||
if (!selectedDay) return;
|
||
|
||
const result: any[] = await ky
|
||
.get(
|
||
`${import.meta.env.VITE_CRM_API_URL}/scheduled_sessions/builds/${buildId}?date=${selectedDay?.toISOString()}`
|
||
)
|
||
.json();
|
||
|
||
setScheduledSessions(result);
|
||
}
|
||
|
||
useEffect(() => {
|
||
getScheduledSessions();
|
||
}, [selectedDay]);
|
||
|
||
useEffect(() => {
|
||
if (!scheduledSessions) return;
|
||
|
||
getSchedule();
|
||
}, [scheduledSessions]);
|
||
|
||
useEffect(() => {
|
||
generateScheduleTimes();
|
||
}, [schedule]);
|
||
|
||
return (
|
||
<div className="sm:p-8 p-6 flex flex-col justify-between sm:gap-8 gap-6 min-h-full">
|
||
<div>
|
||
<div className="flex items-start justify-between">
|
||
<p className="text-2xl text-gradient font-semibold font-gilroy w-fit leading-snug">
|
||
<Trans i18nKey={"sidebar.title1"}>Дата и время</Trans>
|
||
</p>
|
||
<button
|
||
onClick={() => setIsOpen(false)}
|
||
className="transition-opacity hover:opacity-50"
|
||
>
|
||
<CloseIcon />
|
||
</button>
|
||
</div>
|
||
|
||
<div className="mt-2">
|
||
<div className="grid grid-cols-2 gap-2">
|
||
<div className="border-b border-[#3D425C] p-4 text-center">
|
||
<p className="leading-none font-gilroy font-semibold text-sm">
|
||
{selectedDay &&
|
||
format(
|
||
selectedDay,
|
||
"dd MMMM",
|
||
i18n.language === "ru" ? { locale: ru } : { locale: enUS }
|
||
)}
|
||
</p>
|
||
</div>
|
||
|
||
<div className="border-b border-[#798FFF] p-4 text-center">
|
||
<p className="leading-none font-gilroy font-semibold text-sm">
|
||
<Trans i18nKey={"sidebar.time"}>Время</Trans>
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="mt-6">
|
||
{scheduleTimes && scheduleTimes.length > 0 ? (
|
||
<TimeSelector
|
||
times={scheduleTimes}
|
||
handleSelect={(time) => handleSelectTime(time)}
|
||
/>
|
||
) : (
|
||
"Загрузка данных..."
|
||
)}
|
||
</div>
|
||
</div>
|
||
|
||
<div className="flex flex-col sm:gap-6 gap-4">
|
||
<p className="text-center text-xs opacity-50 leading-tight">
|
||
<Trans i18nKey={"sidebar.notice"}>
|
||
Запись на демонстрацию работает в ознакомительном режиме и не
|
||
сохраняет введенные данные
|
||
</Trans>
|
||
</p>
|
||
|
||
<div className="flex sm:gap-4 gap-2">
|
||
<button
|
||
onClick={() => setCurrentTab(currentTab - 1)}
|
||
className="px-6 sm:py-4 py-3.5 border border-[#3D425C] rounded-full font-medium group w-full"
|
||
>
|
||
<span className="opacity-80 transition-opacity group-hover:opacity-100 sm:text-base text-sm">
|
||
<Trans i18nKey={"sidebar.buttonBack"}>Назад</Trans>
|
||
</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
export default SidebarTab2;
|