Files
crm.stream.graff.tech/client/src/components/modals/CreateScheduleModal.tsx
T
2025-04-03 17:58:09 +05:00

316 lines
12 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable react-hooks/exhaustive-deps */
/* eslint-disable no-irregular-whitespace */
import Button from "../Button";
import CloseIcon from "../icons/CloseIcon";
import Label from "../Label";
import { useEffect, useState } from "react";
import Select from "../Select";
import useModalStore from "../../stores/useModalStore";
import Input from "../Input";
import {
addDays,
eachMinuteOfInterval,
parse,
parseISO,
startOfDay,
} from "date-fns";
import api from "../../utils/api";
import ChoiceChips from "../ChoiceChips";
// import ISchedule from "../../types/ISchedule";
import DatePicker from "../DatePicker";
import IScheduledSession from "../../types/IScheduledSession";
import useStore from "../../stores/useStore";
import ISchedule from "../../types/ISchedule";
function CreateScheduleModal() {
const { company, selectedBuild, schedules, setSchedules } = useStore();
const setModal = useModalStore((state) => state.setModal);
const [date, setDate] = useState<Date>(startOfDay(new Date()));
const [startDate, setStartDate] = useState<Date>(startOfDay(new Date()));
const [sessionDuration, setSessionDuration] = useState<number>(30);
const [sessionBreak, setSessionBreak] = useState<number>(5);
const [startTime, setStartTime] = useState<string>("10:00");
const [endTime, setEndTime] = useState<string>("20:00");
const [weekends, setWeekends] = useState(["Сб", "Вс"]);
const [sessionsPerDay, setSessionsPerDay] = useState<number>();
async function getLastScheduledSessionDate() {
try {
const result: IScheduledSession | null = await api
.get(
`companies/${company?.id}/builds/${selectedBuild?.id}/last_scheduled_session`
)
.json();
if (!result || !result.startAt) return;
setStartDate(startOfDay(parseISO(result.startAt)));
} catch (error) {
alert((error as Error).message);
}
}
useEffect(() => {
getLastScheduledSessionDate();
}, []);
function calculateSessionsPerDay() {
// if (!startDate) return;
const sessionsPerDay = eachMinuteOfInterval(
{
start: parse(startTime, "HH:mm", new Date()),
end: parse(endTime, "HH:mm", new Date()),
},
{ step: sessionDuration + sessionBreak }
).length;
setSessionsPerDay(sessionsPerDay);
}
function changeEndTime(value: string) {
if (value.split(":")[0] > startTime.split(":")[0]) {
setEndTime(value);
}
}
async function addSchedule() {
try {
const result: ISchedule = await api
.post(
`companies/${company?.id}/builds/${selectedBuild?.id}/schedules`,
{
json: {
startDate: date,
startTime,
endTime,
weekends,
sessionDuration,
sessionBreak,
sessionsPerDay,
},
}
)
.json();
setSchedules([...schedules, result]);
} catch (error) {
alert((error as Error).message);
}
}
async function handleClickCreateSchedule() {
await addSchedule();
setModal(null);
}
useEffect(() => {
calculateSessionsPerDay();
}, [startDate, endTime, sessionDuration, sessionBreak, weekends]);
return (
<div className="bg-white text-sm relative z-10 rounded-lg w-[896px] shadow-md">
<div className="border-b border-[#DAE0E5] pl-2 pr-3 h-12 flex justify-between items-center">
<p className="p-4 font-semibold leading-[115%]">Создание расписания</p>
<Button
variant="secondary"
icon={<CloseIcon />}
onlyIcon
onClick={() => setModal(null)}
/>
</div>
<div className="border-b border-[#DAE0E5] flex">
<div className="w-full px-6 border-r border-[#DAE0E5]">
<div className="py-8 border-b border-[#DAE0E5] flex justify-between">
<div className="space-y-2">
<p className="font-semibold">Начало действия расписания</p>
<div className="w-[240px]">
<p className="text-xs text-[#77828C]">
Максимальный доступный клиенту промежуток для записи две
календарные недели
</p>
</div>
</div>
<div className="w-[296px] flex flex-col gap-3">
<div className="flex flex-col">
<Label value="Начало" />
{startDate && (
<DatePicker
defaultValue={addDays(startDate, 1)}
startDate={addDays(startDate, 1)}
onChange={(date) => setDate(date)}
/>
)}
</div>
</div>
</div>
<div className="py-8 border-b border-[#DAE0E5] space-y-4">
<div className="flex justify-between">
<div className="">
<p className="font-semibold">Рабочее время</p>
</div>
<div className="w-[296px]">
<div className="flex items-center gap-2">
<div className="flex flex-col gap-1">
<Label value="Начало" />
<Input
type="time"
value={startTime}
onChange={(value) => setStartTime(value)}
className="w-[137px]"
/>
</div>
<p className="mt-4 text-[#77828C]">-</p>
<div className="flex flex-col gap-1">
<Label value="Конец" />
<Input
type="time"
value={endTime}
onChange={changeEndTime}
className="w-[137px]"
/>
</div>
</div>
</div>
</div>
<div className="flex justify-between">
<div className="space-y-2">
<p className="font-semibold">Выходные дни</p>
<div className="w-[240px]">
<p className="text-xs font-[#77828C]">
В выбранные дни запись на демонстрацию для клиента будет
недоступна
</p>
</div>
</div>
<div className="w-[296px]">
<ChoiceChips
options={["Пн", "Вт", "Ср", "Чт", "Пт", "Сб", "Вс"]}
// selected={["Сб", "Вс"]}
onChange={(options) => setWeekends(options)}
/>
</div>
</div>
</div>
<div className="py-8 border-b border-[#DAE0E5] flex flex-col gap-8">
<div className="flex justify-between">
<div className="flex flex-col gap-2">
<p className="font-semibold">Продолжительность сеанса</p>
<p className="text-[#77828C] text-xs w-[240px]">
Влияет на количество ежедневно проводимых сессий
</p>
</div>
<div className="w-[296px]">
<Select
defaultValue={sessionDuration}
options={[
{ value: 5, text: "5 мин." },
{ value: 10, text: "10 мин." },
{ value: 15, text: "15 мин." },
{ value: 20, text: "20 мин." },
{ value: 25, text: "25 мин." },
{ value: 30, text: "30 мин." },
{ value: 35, text: "35 мин." },
{ value: 40, text: "40 мин." },
{ value: 45, text: "45 мин." },
{ value: 50, text: "50 мин." },
{ value: 55, text: "55 мин." },
{ value: 60, text: "60 мин." },
]}
handleChange={(value) => setSessionDuration(value)}
/>
</div>
</div>
<div className="flex justify-between">
<div className="flex flex-col gap-2">
<p className="font-semibold">Перерыв между сеансами</p>
<p className="text-[#77828C] text-xs w-[240px]">
Нужен, чтобы менеджеры успевали завершать один сеанс и
переходить к следующему
</p>
</div>
<div className="w-[296px]">
<Select
defaultValue={5}
options={[
{ value: 5, text: "5 мин." },
{ value: 10, text: "10 мин." },
{ value: 15, text: "15 мин." },
{ value: 20, text: "20 мин." },
{ value: 25, text: "25 мин." },
{ value: 30, text: "30 мин." },
{ value: 35, text: "35 мин." },
{ value: 40, text: "40 мин." },
{ value: 45, text: "45 мин." },
{ value: 50, text: "50 мин." },
{ value: 55, text: "55 мин." },
{ value: 60, text: "60 мин." },
]}
handleChange={(value) => setSessionBreak(value)}
/>
</div>
</div>
</div>
</div>
<div className="min-w-[296px]">
{/* <div className="p-4 border-b border-[#DAE0E5] ">
<p className="text-sm font-semibold">Статистика</p>
</div> */}
<div className="flex flex-col gap-4 p-4">
<p className="text-sm font-semibold">Предварительный просмотр</p>
<div className="flex flex-col gap-3 text-xs">
<div className="flex flex-col gap-2">
<div className="grid grid-cols-3">
<p className="col-span-2 text-[#77828C]">Cеансов в день</p>
<p>{sessionsPerDay}</p>
</div>
<div className="grid grid-cols-3">
<p className="col-span-2 text-[#77828C]">
Длительность сеанса
</p>
<p>{sessionDuration} мин.</p>
</div>
<div className="grid grid-cols-3">
<p className="col-span-2 text-[#77828C]">Между сеансами</p>
<p>{sessionBreak} мин.</p>
</div>
<div className="grid grid-cols-3">
<p className="col-span-2 text-[#77828C]">Время работы</p>
<p>
{startTime} - {endTime}
</p>
</div>
{/* <div className="grid grid-cols-3">
<p className="col-span-2 text-[#77828C]">Выходные дни</p>
<p className="flex flex-wrap gap-1">
{weekends.map((value) => (
<span>{value}</span>
))}
</p>
</div> */}
</div>
</div>
</div>
</div>
</div>
<div className="flex gap-2 px-6 py-3">
<Button onClick={handleClickCreateSchedule}>Создать</Button>
<Button variant="secondary" onClick={() => setModal(null)}>
Отмена
</Button>
</div>
</div>
);
}
export default CreateScheduleModal;