upd
This commit is contained in:
@@ -33,24 +33,20 @@ function CalendarPage() {
|
|||||||
const [scheduledSessions, setScheduledSessions] = useState<any[]>([]);
|
const [scheduledSessions, setScheduledSessions] = useState<any[]>([]);
|
||||||
|
|
||||||
async function selectDate(value: any) {
|
async function selectDate(value: any) {
|
||||||
await getScheduledSessions(value);
|
await getScheduledSessions("653675f420af0dadee9003ec", value);
|
||||||
|
|
||||||
setDate(value);
|
setDate(value);
|
||||||
setStep((prev) => prev + 1);
|
setStep((prev) => prev + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getScheduledSessions(value: Date) {
|
async function getScheduledSessions(buildId: string, date: Date) {
|
||||||
const username = params.username;
|
|
||||||
|
|
||||||
const result: any[] = await ky
|
const result: any[] = await ky
|
||||||
.get(
|
.get(
|
||||||
`${
|
`https://crm.stream.graff.tech/api/scheduled_sessions/${buildId}?date=${date.toISOString()}`
|
||||||
import.meta.env.VITE_COORD_URL
|
|
||||||
}/scheduled_sessions/${username}?date=${value.toISOString()}`
|
|
||||||
)
|
)
|
||||||
.json();
|
.json();
|
||||||
|
|
||||||
console.log(scheduledSessions);
|
console.log(result);
|
||||||
|
|
||||||
setScheduledSessions(result);
|
setScheduledSessions(result);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,18 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
/* eslint-disable react-hooks/exhaustive-deps */
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
import {
|
import {
|
||||||
add,
|
add,
|
||||||
|
differenceInDays,
|
||||||
eachDayOfInterval,
|
eachDayOfInterval,
|
||||||
endOfMonth,
|
endOfMonth,
|
||||||
format,
|
format,
|
||||||
getDay,
|
getDay,
|
||||||
|
isAfter,
|
||||||
|
isBefore,
|
||||||
isEqual,
|
isEqual,
|
||||||
|
isWithinInterval,
|
||||||
parse,
|
parse,
|
||||||
|
parseISO,
|
||||||
startOfToday,
|
startOfToday,
|
||||||
} from "date-fns";
|
} from "date-fns";
|
||||||
import { enUS, ru } from "date-fns/locale";
|
import { enUS, ru } from "date-fns/locale";
|
||||||
@@ -17,6 +23,7 @@ import { Trans } from "react-i18next";
|
|||||||
import i18n from "../i18n";
|
import i18n from "../i18n";
|
||||||
|
|
||||||
interface CalendarProps {
|
interface CalendarProps {
|
||||||
|
schedules: any[];
|
||||||
handleSelect: (day: Date) => void;
|
handleSelect: (day: Date) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -24,7 +31,7 @@ function classNames(...classes: (string | boolean)[]) {
|
|||||||
return classes.filter(Boolean).join(" ");
|
return classes.filter(Boolean).join(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
function Calendar({ handleSelect }: CalendarProps) {
|
function Calendar({ schedules, handleSelect }: CalendarProps) {
|
||||||
const today = startOfToday();
|
const today = startOfToday();
|
||||||
const [selectedDay, setSelectedDay] = useState<Date | null>(null);
|
const [selectedDay, setSelectedDay] = useState<Date | null>(null);
|
||||||
const [currentMonth, setCurrentMonth] = useState(format(today, "MMM-yyyy"));
|
const [currentMonth, setCurrentMonth] = useState(format(today, "MMM-yyyy"));
|
||||||
@@ -46,9 +53,11 @@ function Calendar({ handleSelect }: CalendarProps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (selectedDay !== null) {
|
console.log(schedules);
|
||||||
handleSelect(selectedDay);
|
|
||||||
}
|
if (!selectedDay) return;
|
||||||
|
|
||||||
|
handleSelect(selectedDay);
|
||||||
}, [selectedDay]);
|
}, [selectedDay]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -89,7 +98,16 @@ function Calendar({ handleSelect }: CalendarProps) {
|
|||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
disabled={day < today}
|
disabled={
|
||||||
|
day < today ||
|
||||||
|
schedules.some(
|
||||||
|
(schedule) =>
|
||||||
|
!isWithinInterval(day, {
|
||||||
|
start: parseISO(schedule.startDate),
|
||||||
|
end: parseISO(schedule.endDate),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
onClick={() => setSelectedDay(day)}
|
onClick={() => setSelectedDay(day)}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
selectedDay !== null &&
|
selectedDay !== null &&
|
||||||
|
|||||||
@@ -1,23 +1,47 @@
|
|||||||
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
/* eslint-disable no-irregular-whitespace */
|
/* eslint-disable no-irregular-whitespace */
|
||||||
import { Trans } from "react-i18next";
|
import { Trans } from "react-i18next";
|
||||||
import useSidebarTabStore from "../stores/useSidebarStore";
|
import useSidebarTabStore from "../stores/useSidebarStore";
|
||||||
import Calendar from "./Calendar";
|
import Calendar from "./Calendar";
|
||||||
import CloseIcon from "./icons/CloseIcon";
|
import CloseIcon from "./icons/CloseIcon";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import ky from "ky";
|
||||||
|
|
||||||
function SidebarTab1() {
|
function SidebarTab1() {
|
||||||
const [currentTab, setCurrentTab, setIsOpen, setSelectedDay] =
|
const [currentTab, setCurrentTab, setIsOpen, setSelectedDay, buildId] =
|
||||||
useSidebarTabStore((state) => [
|
useSidebarTabStore((state) => [
|
||||||
state.currentTab,
|
state.currentTab,
|
||||||
state.setCurrentTab,
|
state.setCurrentTab,
|
||||||
state.setIsOpen,
|
state.setIsOpen,
|
||||||
state.setSelectedDay,
|
state.setSelectedDay,
|
||||||
|
state.buildId,
|
||||||
]);
|
]);
|
||||||
|
const [schedules, setSchedules] = useState<any[]>();
|
||||||
|
|
||||||
function handleSelectDay(day: Date) {
|
function handleSelectDay(day: Date) {
|
||||||
setSelectedDay(day);
|
setSelectedDay(day);
|
||||||
setCurrentTab(currentTab + 1);
|
setCurrentTab(currentTab + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getSchedules() {
|
||||||
|
try {
|
||||||
|
const result: any[] = await ky
|
||||||
|
.get(`http://localhost:3001/schedules/builds/${buildId}`)
|
||||||
|
.json();
|
||||||
|
|
||||||
|
setSchedules(result);
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof Error) {
|
||||||
|
console.log("Error: ", error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getSchedules();
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="sm:p-8 p-6 flex flex-col justify-between sm:gap-8 gap-6 min-h-full">
|
<div className="sm:p-8 p-6 flex flex-col justify-between sm:gap-8 gap-6 min-h-full">
|
||||||
<div>
|
<div>
|
||||||
@@ -50,7 +74,14 @@ function SidebarTab1() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="sm:mt-8 mt-6">
|
<div className="sm:mt-8 mt-6">
|
||||||
<Calendar handleSelect={(day) => handleSelectDay(day)} />
|
{schedules ? (
|
||||||
|
<Calendar
|
||||||
|
schedules={schedules}
|
||||||
|
handleSelect={(day) => handleSelectDay(day)}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
"Загрузка данных..."
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
/* eslint-disable no-irregular-whitespace */
|
/* eslint-disable no-irregular-whitespace */
|
||||||
import { Trans } from "react-i18next";
|
import { Trans } from "react-i18next";
|
||||||
import useSidebarTabStore from "../stores/useSidebarStore";
|
import useSidebarTabStore from "../stores/useSidebarStore";
|
||||||
import TimeSelector from "./TimeSelector";
|
import TimeSelector from "./TimeSelector";
|
||||||
import CloseIcon from "./icons/CloseIcon";
|
import CloseIcon from "./icons/CloseIcon";
|
||||||
import { format } from "date-fns";
|
import { eachMinuteOfInterval, format, parse, parseISO } from "date-fns";
|
||||||
import i18n from "../i18n";
|
import i18n from "../i18n";
|
||||||
import { enUS, ru } from "date-fns/locale";
|
import { enUS, ru } from "date-fns/locale";
|
||||||
|
import ky from "ky";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
function SidebarTab2() {
|
function SidebarTab2() {
|
||||||
const [
|
const [
|
||||||
@@ -15,6 +19,7 @@ function SidebarTab2() {
|
|||||||
setSelectedTime,
|
setSelectedTime,
|
||||||
selectedDay,
|
selectedDay,
|
||||||
selectedTime,
|
selectedTime,
|
||||||
|
buildId,
|
||||||
] = useSidebarTabStore((state) => [
|
] = useSidebarTabStore((state) => [
|
||||||
state.currentTab,
|
state.currentTab,
|
||||||
state.setCurrentTab,
|
state.setCurrentTab,
|
||||||
@@ -22,13 +27,84 @@ function SidebarTab2() {
|
|||||||
state.setSelectedTime,
|
state.setSelectedTime,
|
||||||
state.selectedDay,
|
state.selectedDay,
|
||||||
state.selectedTime,
|
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) {
|
function handleSelectTime(time: string) {
|
||||||
setSelectedTime(time);
|
setSelectedTime(time);
|
||||||
setCurrentTab(currentTab + 1);
|
setCurrentTab(currentTab + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getSchedule() {
|
||||||
|
if (!selectedDay) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result: { [key: string]: any } = await ky
|
||||||
|
.get(
|
||||||
|
`http://localhost:3001/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(
|
||||||
|
`http://localhost:3001/scheduled_sessions/builds/${buildId}?date=${selectedDay?.toISOString()}`
|
||||||
|
)
|
||||||
|
.json();
|
||||||
|
|
||||||
|
setScheduledSessions(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getScheduledSessions();
|
||||||
|
}, [selectedDay]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!scheduledSessions) return;
|
||||||
|
|
||||||
|
getSchedule();
|
||||||
|
}, [scheduledSessions]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
generateScheduleTimes();
|
||||||
|
}, [schedule]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="sm:p-8 p-6 flex flex-col justify-between sm:gap-8 gap-6 min-h-full">
|
<div className="sm:p-8 p-6 flex flex-col justify-between sm:gap-8 gap-6 min-h-full">
|
||||||
<div>
|
<div>
|
||||||
@@ -57,22 +133,23 @@ function SidebarTab2() {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="border-b border-[#798FFF] p-4 text-center">
|
<div className="border-b border-[#798FFF] p-4 text-center">
|
||||||
<p className="leading-none font-gilroy font-semibold text-sm">
|
<p className="leading-none font-gilroy font-semibold text-sm">
|
||||||
{selectedTime ? (
|
<Trans i18nKey={"sidebar.time"}>Время</Trans>
|
||||||
selectedTime
|
|
||||||
) : (
|
|
||||||
<Trans i18nKey={"sidebar.time"}>Время</Trans>
|
|
||||||
)}
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-6">
|
<div className="mt-6">
|
||||||
<TimeSelector
|
{scheduleTimes && scheduleTimes.length > 0 ? (
|
||||||
handleSelect={(time: string) => handleSelectTime(time)}
|
<TimeSelector
|
||||||
/>
|
times={scheduleTimes}
|
||||||
|
handleSelect={(time) => handleSelectTime(time)}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
"Загрузка данных..."
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,32 +1,12 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
import { Trans } from "react-i18next";
|
import { Trans } from "react-i18next";
|
||||||
import useSidebarStore from "../stores/useSidebarStore";
|
|
||||||
|
|
||||||
interface TimeSelectorProps {
|
interface TimeSelectorProps {
|
||||||
|
times: any[];
|
||||||
handleSelect: (time: string) => void;
|
handleSelect: (time: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
function TimeSelector({ handleSelect }: TimeSelectorProps) {
|
function TimeSelector({ times, handleSelect }: TimeSelectorProps) {
|
||||||
const [selectedTime] = useSidebarStore((state) => [state.selectedTime]);
|
|
||||||
|
|
||||||
const times = [
|
|
||||||
{ value: "10:00", active: true },
|
|
||||||
{ value: "10:30", active: false },
|
|
||||||
{ value: "11:00", active: true },
|
|
||||||
{ value: "11:30", active: true },
|
|
||||||
{ value: "12:00", active: true },
|
|
||||||
{ value: "12:30", active: true },
|
|
||||||
{ value: "13:00", active: true },
|
|
||||||
{ value: "13:30", active: true },
|
|
||||||
{ value: "14:00", active: false },
|
|
||||||
{ value: "14:30", active: false },
|
|
||||||
{ value: "15:30", active: true },
|
|
||||||
{ value: "15:00", active: true },
|
|
||||||
{ value: "16:30", active: true },
|
|
||||||
{ value: "16:00", active: true },
|
|
||||||
{ value: "17:30", active: true },
|
|
||||||
{ value: "17:00", active: true },
|
|
||||||
];
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="grid grid-cols-4 gap-2 font-medium">
|
<div className="grid grid-cols-4 gap-2 font-medium">
|
||||||
@@ -37,9 +17,6 @@ function TimeSelector({ handleSelect }: TimeSelectorProps) {
|
|||||||
disabled={!time.active}
|
disabled={!time.active}
|
||||||
className={[
|
className={[
|
||||||
"min-w-[40px] h-10 text-[#798FFF] text-sm rounded-full border border-[#798FFF] flex justify-center items-center transition-colors hover:bg-[#798FFF] hover:bg-opacity-20 hover:text-white disabled:text-[#3D425C] disabled:hover:bg-transparent disabled:border-transparent",
|
"min-w-[40px] h-10 text-[#798FFF] text-sm rounded-full border border-[#798FFF] flex justify-center items-center transition-colors hover:bg-[#798FFF] hover:bg-opacity-20 hover:text-white disabled:text-[#3D425C] disabled:hover:bg-transparent disabled:border-transparent",
|
||||||
time.value === selectedTime
|
|
||||||
? "bg-[#798FFF] text-white"
|
|
||||||
: "text-[#798FFF]",
|
|
||||||
].join(" ")}
|
].join(" ")}
|
||||||
>
|
>
|
||||||
{time.value}
|
{time.value}
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ interface SidebarState {
|
|||||||
setPhone: (phone: string) => void;
|
setPhone: (phone: string) => void;
|
||||||
email: string;
|
email: string;
|
||||||
setEmail: (email: string) => void;
|
setEmail: (email: string) => void;
|
||||||
|
buildId: string;
|
||||||
|
setBuildId: (buildId: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const useSidebarStore = create<SidebarState>()(
|
const useSidebarStore = create<SidebarState>()(
|
||||||
@@ -36,6 +38,8 @@ const useSidebarStore = create<SidebarState>()(
|
|||||||
setPhone: (phone) => set(() => ({ phone })),
|
setPhone: (phone) => set(() => ({ phone })),
|
||||||
email: "",
|
email: "",
|
||||||
setEmail: (email) => set(() => ({ email })),
|
setEmail: (email) => set(() => ({ email })),
|
||||||
|
buildId: "653675f420af0dadee9003ec",
|
||||||
|
setBuildId: (buildId) => set(() => ({ buildId })),
|
||||||
})
|
})
|
||||||
// {
|
// {
|
||||||
// name: "tab-storage",
|
// name: "tab-storage",
|
||||||
|
|||||||
Reference in New Issue
Block a user