upd
This commit is contained in:
@@ -0,0 +1,361 @@
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { FormEvent, useEffect, useState } from "react";
|
||||
import Calendar from "react-calendar";
|
||||
import "react-calendar/dist/Calendar.css";
|
||||
import "./CalendarPage.css";
|
||||
import {
|
||||
format,
|
||||
isBefore,
|
||||
differenceInBusinessDays,
|
||||
setHours,
|
||||
getHours,
|
||||
setMinutes,
|
||||
getMinutes,
|
||||
setSeconds,
|
||||
setMilliseconds,
|
||||
} from "date-fns";
|
||||
import ru from "date-fns/locale/ru";
|
||||
import ky from "ky";
|
||||
import { useParams } from "react-router-dom";
|
||||
import InputMask from "react-input-mask";
|
||||
|
||||
function CalendarPage() {
|
||||
const params = useParams();
|
||||
const [step, setStep] = useState<number>(1);
|
||||
const [date, setDate] = useState<Date>(new Date());
|
||||
const [name, setName] = useState<string>("");
|
||||
const [email, setEmail] = useState<string>("");
|
||||
const [phone, setPhone] = useState<string>("");
|
||||
const [link, setLink] = useState<string>("");
|
||||
const [datesAndTimes, setDatesAndTimes] = useState<any[]>([]);
|
||||
const [scheduledSessions, setScheduledSessions] = useState<any[]>([]);
|
||||
|
||||
async function selectDate(value: any) {
|
||||
await getScheduledSessions(value);
|
||||
|
||||
setDate(value);
|
||||
setStep((prev) => prev + 1);
|
||||
}
|
||||
|
||||
async function getScheduledSessions(value: Date) {
|
||||
const username = params.username;
|
||||
|
||||
const result: any[] = await ky
|
||||
.get(
|
||||
`${
|
||||
import.meta.env.VITE_COORD_URL
|
||||
}/scheduled_sessions/${username}?date=${value.toISOString()}`
|
||||
)
|
||||
.json();
|
||||
|
||||
console.log(scheduledSessions);
|
||||
|
||||
setScheduledSessions(result);
|
||||
}
|
||||
|
||||
function selectTime(value: any) {
|
||||
let newDate = date;
|
||||
newDate = setHours(date, getHours(value));
|
||||
newDate = setMinutes(newDate, getMinutes(value));
|
||||
newDate = setSeconds(newDate, 0);
|
||||
newDate = setMilliseconds(newDate, 0);
|
||||
|
||||
setDate(newDate);
|
||||
setStep((prev) => prev + 1);
|
||||
}
|
||||
|
||||
async function addSchedule(e: FormEvent) {
|
||||
e.preventDefault();
|
||||
|
||||
const username = params.username;
|
||||
const title = "nksJukovaDev";
|
||||
const startAt = date;
|
||||
|
||||
try {
|
||||
const result: any = await ky
|
||||
.post(`${import.meta.env.VITE_COORD_URL}/scheduled_sessions`, {
|
||||
json: {
|
||||
username,
|
||||
name,
|
||||
email,
|
||||
phone,
|
||||
title,
|
||||
startAt,
|
||||
},
|
||||
})
|
||||
.json();
|
||||
|
||||
if (!result.userInviteLink) {
|
||||
alert(result.error);
|
||||
return;
|
||||
}
|
||||
|
||||
setLink(result.userInviteLink);
|
||||
setName("");
|
||||
setEmail("");
|
||||
setPhone("");
|
||||
setStep(4);
|
||||
} catch (error: any) {
|
||||
alert(error.message);
|
||||
}
|
||||
}
|
||||
|
||||
async function getSessionScheduleSettings() {
|
||||
const username = params.username;
|
||||
|
||||
try {
|
||||
const result: any = await ky
|
||||
.get(
|
||||
`${
|
||||
import.meta.env.VITE_COORD_URL
|
||||
}/session_schedule_settings/${username}`
|
||||
)
|
||||
.json();
|
||||
|
||||
if (result.error) {
|
||||
console.log("Error: ", result.error);
|
||||
return;
|
||||
}
|
||||
|
||||
const { datesAndTimes } = result;
|
||||
|
||||
console.log(datesAndTimes);
|
||||
|
||||
setDatesAndTimes(datesAndTimes);
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
console.log(error.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
getSessionScheduleSettings();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="min-h-screen flex justify-center items-center p-8 rounded-lg text-white">
|
||||
{step === 1 && (
|
||||
<div className="space-y-8 w-80">
|
||||
<p className="text-4xl font-gilroy">
|
||||
Выберите
|
||||
<br />
|
||||
дату
|
||||
</p>
|
||||
<Calendar onChange={selectDate} value={date} minDate={new Date()} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{step === 2 && (
|
||||
<div className="space-y-8">
|
||||
<p className="text-4xl font-gilroy">
|
||||
Выберите
|
||||
<br />
|
||||
время
|
||||
</p>
|
||||
|
||||
<div className="space-y-4">
|
||||
<button
|
||||
onClick={() => setStep((prev) => prev - 1)}
|
||||
className="text-[#C5C7CE] flex items-center gap-1 bg-[#1C1D21] p-1 pr-4 text-xs rounded"
|
||||
>
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M15 19L8 12L15 5"
|
||||
stroke="#C5C7CE"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
<span>Выбор даты</span>
|
||||
</button>
|
||||
|
||||
<p className="text-xl font-gilroy">
|
||||
{format(date, "dd MMMM", { locale: ru })}
|
||||
</p>
|
||||
|
||||
<div className="grid grid-cols-4">
|
||||
{datesAndTimes.map(
|
||||
(dateAndTime: { value: Date; active: true }, index: number) =>
|
||||
!differenceInBusinessDays(date, new Date()) ? (
|
||||
isBefore(new Date(), new Date(dateAndTime.value)) && (
|
||||
<button
|
||||
key={index}
|
||||
onClick={() => selectTime(new Date(dateAndTime.value))}
|
||||
className="px-3 py-2 text-center rounded hover:bg-[#23242A] disabled:hover:bg-inherit disabled:opacity-25"
|
||||
disabled={
|
||||
scheduledSessions.filter(
|
||||
(session) => session.startAt === dateAndTime.value
|
||||
).length >= 3
|
||||
}
|
||||
>
|
||||
{format(new Date(dateAndTime.value), "HH:mm")}
|
||||
</button>
|
||||
)
|
||||
) : (
|
||||
<button
|
||||
key={index}
|
||||
onClick={() => selectTime(new Date(dateAndTime.value))}
|
||||
className="px-3 py-2 text-center rounded hover:bg-[#23242A] disabled:hover:bg-inherit disabled:opacity-25"
|
||||
disabled={
|
||||
scheduledSessions.filter(
|
||||
(session) => session.startAt === dateAndTime.value
|
||||
).length >= 3
|
||||
}
|
||||
>
|
||||
{format(new Date(dateAndTime.value), "HH:mm")}
|
||||
</button>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{step === 3 && (
|
||||
<div className="space-y-8 w-80">
|
||||
<p className="text-4xl font-gilroy">
|
||||
Расскажите
|
||||
<br />о себе
|
||||
</p>
|
||||
|
||||
<div className="space-y-4">
|
||||
<button
|
||||
onClick={() => setStep((prev) => prev - 1)}
|
||||
className="text-[#C5C7CE] flex items-center gap-1 bg-[#1C1D21] p-1 pr-4 text-xs rounded"
|
||||
>
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M15 19L8 12L15 5"
|
||||
stroke="#C5C7CE"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
<span>Выбор времени</span>
|
||||
</button>
|
||||
|
||||
<p className="text-xl font-gilroy">
|
||||
{format(date, "dd MMMM HH:mm", { locale: ru })}
|
||||
</p>
|
||||
|
||||
<form onSubmit={addSchedule} className="space-y-12">
|
||||
<div className="space-y-4">
|
||||
<div className="space-y-1">
|
||||
<p className="text-[#C5C7CE]">Имя</p>
|
||||
<input
|
||||
required
|
||||
type="text"
|
||||
className="px-4 py-3 bg-[#23242A] rounded outline-none w-full"
|
||||
placeholder="Константин"
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="space-y-1">
|
||||
<p className="text-[#C5C7CE]">Email</p>
|
||||
<input
|
||||
required
|
||||
type="email"
|
||||
className="px-4 py-3 bg-[#23242A] rounded outline-none w-full"
|
||||
placeholder="example@mail.ru"
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="space-y-1">
|
||||
<p className="text-[#C5C7CE]">Телефон</p>
|
||||
<InputMask
|
||||
mask={"+999999999999999"}
|
||||
maskChar={null}
|
||||
required
|
||||
type="tel"
|
||||
className="px-4 py-3 bg-[#23242A] rounded outline-none w-full"
|
||||
placeholder="+79009998877"
|
||||
value={phone}
|
||||
onChange={(e) => setPhone(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
className="px-4 py-2 bg-gradient w-full rounded"
|
||||
>
|
||||
Запланировать
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{step === 4 && (
|
||||
<div className="space-y-8 w-80">
|
||||
<p className="text-4xl font-gilroy">
|
||||
Просмотр
|
||||
<br />
|
||||
запланирован
|
||||
</p>
|
||||
|
||||
<div className="space-y-12">
|
||||
<p className="text-[#C5C7CE]">
|
||||
Ссылка для подключения и другая дополнительная информация будут
|
||||
отправлены на ваш почтовый адрес.
|
||||
</p>
|
||||
|
||||
<div className="space-y-4">
|
||||
<div className="space-y-1">
|
||||
<p>Скопируйте ссылку для поключения</p>
|
||||
<input
|
||||
type="text"
|
||||
className="px-4 py-3 bg-[#23242A] rounded outline-none w-full"
|
||||
defaultValue={link}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<p className="text-center">или</p>
|
||||
|
||||
<a
|
||||
href={link}
|
||||
target="_blank"
|
||||
className="inline-block px-4 py-2 bg-gradient w-full rounded text-center"
|
||||
>
|
||||
Подключиться
|
||||
</a>
|
||||
|
||||
<div className="h-0.5 bg-[#23242A]"></div>
|
||||
|
||||
<a
|
||||
onClick={() => setStep(1)}
|
||||
href="#"
|
||||
className="inline-block px-4 py-2 w-full rounded text-center bg-[#1C1D21] text-[#C5C7CE]"
|
||||
>
|
||||
На сайт жилого комплекса
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default CalendarPage;
|
||||
Reference in New Issue
Block a user