This commit is contained in:
2023-10-25 13:24:38 +05:00
parent efd370e79e
commit 6aac2a1811
6 changed files with 154 additions and 51 deletions
+4 -8
View File
@@ -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);
} }
+23 -5
View File
@@ -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 &&
+33 -2
View File
@@ -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>
+87 -10
View File
@@ -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>
+3 -26
View File
@@ -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}
+4
View File
@@ -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",