This commit is contained in:
2024-06-12 20:06:30 +05:00
parent e155066534
commit a46547d1fe
19 changed files with 634 additions and 513 deletions
+107 -332
View File
@@ -1,52 +1,53 @@
/* eslint-disable react-hooks/exhaustive-deps */
/* eslint-disable @typescript-eslint/no-explicit-any */
import { useEffect, useRef, useState } from "react";
import Card from "../components/Card";
import EmptyCard from "../components/EmptyCard";
import TabButton from "../components/TabButton";
import BurgerIcon from "../components/icons/BurgerIcon";
import ChevronLeftIcon from "../components/icons/ChevronLeftIcon";
import ChevronRightIcon from "../components/icons/ChevronRightIcon";
import api from "../utils/api";
import useAuthStore from "../stores/useAuthStore";
import {
eachMinuteOfInterval,
format,
parse,
addDays,
subDays,
isAfter,
isEqual,
} from "date-fns";
import Button from "../components/Button";
import { useEffect, useRef, useState } from "react";
import Card from "../components/Card";
import EmptyCard from "../components/EmptyCard";
import TabButton from "../components/TabButton";
import api from "../utils/api";
import { ru } from "date-fns/locale";
import { Transition } from "react-transition-group";
import SpinnerIcon from "../components/icons/SpinnerIcon";
import useModalStore from "../stores/useModalStore";
import ModalContainer from "../components/ModalContainer";
import CreateScheduleModal from "../components/modals/CreateScheduleModal";
import MoreIcon from "../components/icons/MoreIcon";
import ISchedule from "../types/ISchedule";
import Calendar from "../components/Calendar";
import ChevronUpIcon from "../components/icons/ChevronUpIcon";
import { isEqual } from "lodash";
import _ from "lodash";
import useStore from "../stores/useStore";
import useAuthStore from "../stores/useAuthStore";
import Menu from "../components/Menu";
import Button from "../components/Button";
import Calendar from "../components/Calendar";
import Managers from "../components/Managers";
import Schedules from "../components/Schedules";
import SpinnerIcon from "../components/icons/SpinnerIcon";
import ModalContainer from "../components/ModalContainer";
import ChevronLeftIcon from "../components/icons/ChevronLeftIcon";
import ChevronRightIcon from "../components/icons/ChevronRightIcon";
function DashboardPage() {
const [user, setAccessToken] = useAuthStore((state) => [
state.user,
state.setAccessToken,
]);
const [company, setCompany] = useState<{ [key: string]: any }>();
const [selectedBuildManagers, setSelectedBuildManagers] = useState<any[]>();
const [builds, setBuilds] = useState<any[]>();
const [selectedBuild, setSelectedBuild] = useState<{ [key: string]: any }>();
const [schedules, setSchedules] = useState<ISchedule[]>();
const { user } = useAuthStore();
const {
company,
setCompany,
selectedBuild,
setSelectedBuild,
builds,
setBuilds,
managers,
setManagers,
schedules,
setSchedules,
selectedDay,
setSelectedDay,
} = useStore();
const [duration, setDuration] = useState<number>();
const [scheduledSessions, setScheduledSessions] = useState<any[]>();
const [generatedScheduledSessions, setGeneratedScheduledSessions] =
useState<any[]>();
const [selectedDate, setSelectedDate] = useState(new Date());
const [dateTimes, setDateTimes] = useState<Date[]>();
const [currentTime, setCurrentTime] = useState<string>(
format(new Date(), "HH:mm")
@@ -54,63 +55,19 @@ function DashboardPage() {
const [isLoadingScheduledSessions, setIsLoadingScheduledSessions] =
useState(true);
const scheduledSessionsRef = useRef<HTMLDivElement>(null);
const setModal = useModalStore((state) => state.setModal);
// const [selectedDate, setSelectedDate] = useState(
// format(new Date(), "d MMMM, yyyy", { locale: ru })
// );
function selectNextDay() {
setSelectedDate((prev) => addDays(prev, 1));
setSelectedDay(addDays(selectedDay, 1));
}
function selectPrevDay() {
setSelectedDate((prev) => subDays(prev, 1));
setSelectedDay(subDays(selectedDay, 1));
}
function selectCurrentDate() {
setSelectedDate(new Date());
setSelectedDay(new Date());
}
// useEffect(() => {
// console.log("schedules", schedules);
// if (!selectedDate || !selectedBuild || !schedules?.length) return;
// const foundSchedule = schedules.find(
// (schedule) =>
// isWithinInterval(selectedDate, {
// start: new Date(schedule.startDate),
// end: addDays(new Date(schedule.startDate), 14),
// }) && selectedBuild.id === schedule.buildId
// );
// console.log("foundSchedule", foundSchedule);
// if (foundSchedule) {
// const startDateTime = parse(
// foundSchedule.startTime,
// "HH:mm",
// selectedDate
// );
// const endDateTime = parse(foundSchedule.endTime, "HH:mm", selectedDate);
// const step = foundSchedule.sessionDuration + foundSchedule.sessionBreak;
// setDateTimes(
// eachMinuteOfInterval(
// {
// start: startDateTime,
// end: endDateTime,
// },
// { step }
// )
// );
// } else {
// setDateTimes(undefined);
// setGeneratedScheduledSessions(undefined);
// }
// }, [selectedDate, selectedBuild, schedules]);
function findSessionsByTime(time: Date) {
if (!scheduledSessions) return [];
@@ -122,6 +79,8 @@ function DashboardPage() {
}
function generateScheduledSessions() {
if (!selectedBuild) return;
const newGeneratedScheduledSession: any[] = [];
dateTimes?.forEach((time) => {
@@ -134,7 +93,7 @@ function DashboardPage() {
for (
let index = 0;
index < selectedBuild?.sessionLimit - foundSessionsByTime.length;
index < selectedBuild.sessionLimit - foundSessionsByTime.length;
index++
) {
sessions.push({});
@@ -150,36 +109,36 @@ function DashboardPage() {
}
useEffect(() => {
if (!scheduledSessions) return;
if (!scheduledSessions || !selectedBuild || !selectedDay) return;
generateScheduledSessions();
}, [scheduledSessions]);
}, [scheduledSessions, selectedBuild, selectedDay]);
useEffect(() => {
if (!schedules || !selectedDate || !selectedBuild) return;
if (!schedules || !selectedDay || !selectedBuild) return;
const foundSchedule = schedules.find((schedule) =>
isAfter(new Date(), new Date(schedule.startDate))
console.log("schedules", schedules);
const foundSchedule = schedules.find(
(schedule) => schedule.buildId === selectedBuild.id
);
if (!foundSchedule) return;
if (!foundSchedule) {
setDateTimes([]);
return;
}
const step = foundSchedule.sessionDuration + foundSchedule.sessionBreak; // 35
const newTimes = eachMinuteOfInterval(
{
start: parse(foundSchedule.startTime, "HH:mm", new Date(selectedDate)), // 11:00
end: parse(foundSchedule.endTime, "HH:mm", new Date(selectedDate)), // 20:00
start: parse(foundSchedule.startTime, "HH:mm", new Date(selectedDay)), // 11:00
end: parse(foundSchedule.endTime, "HH:mm", new Date(selectedDay)), // 20:00
},
{ step }
);
setDateTimes(newTimes);
setDuration(foundSchedule.sessionDuration);
}, [schedules, selectedDate, selectedBuild]);
useEffect(() => {
if (!schedules) return;
// const schedule = schedules.find(schedule => schedule.startDate);
}, [selectedDate, selectedBuild, schedules]);
}, [schedules, selectedDay, selectedBuild]);
async function getCompany() {
if (!user) {
@@ -224,7 +183,7 @@ function DashboardPage() {
const result: any = await api
.get(`companies/${company.id}/builds/${selectedBuild.id}/users`)
.json();
setSelectedBuildManagers(result);
setManagers(result);
} catch (error) {
if (error instanceof Error) {
console.log("Error: ", error.message);
@@ -250,7 +209,7 @@ function DashboardPage() {
.get(
`companies/${company.id}/builds/${
selectedBuild.id
}/scheduled_sessions?date=${selectedDate.toISOString()}`
}/scheduled_sessions?date=${selectedDay.toISOString()}`
)
.json();
@@ -264,39 +223,9 @@ function DashboardPage() {
if (useLoader) setIsLoadingScheduledSessions(false);
}
// function generateScheduledSessions() {
// if (!dateTimes || !scheduledSessions || !selectedBuild) return;
// const arr: any[][] = [];
// dateTimes.forEach((dateTime) => {
// const arr2 = [];
// const foundSessionsCount = scheduledSessions.filter((session) =>
// isEqual(session.startAt, dateTime)
// );
// arr2.push(dateTime);
// for (let i = 0; i < selectedBuild.sessionLimit; i++) {
// if (foundSessionsCount[i]) {
// arr2.push(foundSessionsCount[i]);
// } else {
// arr2.push({});
// }
// }
// arr.push(arr2);
// console.log("arr2", arr2);
// });
// setGeneratedScheduledSessions(arr);
// }
async function updateScheduledSessionManager(
scheduledSessionId: string,
managerId: string
managerId: string | null
) {
if (!company || !scheduledSessions) return;
@@ -325,6 +254,8 @@ function DashboardPage() {
async function getSchedules() {
if (!company || !selectedBuild) return;
console.log("selectedBuild.id", selectedBuild.id);
const result: any[] = await api
.get(`companies/${company.id}/builds/${selectedBuild.id}/schedules`)
.json();
@@ -355,33 +286,28 @@ function DashboardPage() {
}, [builds]);
useEffect(() => {
if (!selectedBuildManagers || !selectedDate || !selectedBuild) return;
if (!managers || !selectedDay || !selectedBuild) return;
getScheduledSessions(true);
const interval = setInterval(() => {
getScheduledSessions();
}, 3000);
}, 1000);
return () => {
clearInterval(interval);
};
}, [selectedBuildManagers, selectedDate, selectedBuild]);
}, [managers, selectedDay, selectedBuild]);
useEffect(() => {
if (!company || !selectedBuild) return;
getManagers();
console.log("selectedBuild", selectedBuild);
getSchedules();
getManagers();
}, [selectedBuild]);
// useEffect(() => {
// if (!scheduledSessions) return;
// generateScheduledSessions();
// }, [scheduledSessions]);
useEffect(() => {
// setIsLoadingScheduledSessions(true);
scheduledSessionsRef.current?.scrollTo({ top: 0, behavior: "smooth" });
}, [selectedDate, selectedBuild]);
}, [selectedDay, selectedBuild]);
return (
<div className="main h-screen flex">
@@ -392,7 +318,9 @@ function DashboardPage() {
<TabButton
key={build.id}
handleClick={() => setSelectedBuild(build)}
active={selectedBuild && build.id === selectedBuild.id}
active={
(selectedBuild && build.id === selectedBuild?.id) || false
}
>
{build.name}
</TabButton>
@@ -403,7 +331,7 @@ function DashboardPage() {
<p className="text-sm font-semibold">Расписание</p>
<div className="flex items-center gap-4">
<p className="text-sm font-semibold">
{format(selectedDate, "PPPP", { locale: ru })}
{format(selectedDay, "PPPP", { locale: ru })}
</p>
<div className="flex gap-1">
<Button
@@ -465,102 +393,50 @@ function DashboardPage() {
<p>{format(generatedScheduledSession.time, "HH:mm")}</p>
</div>
<div className="flex">
{generatedScheduledSession.sessions.map(
(session: any, index2: number) => {
const selectedManager = selectedBuildManagers?.find(
(manager) => manager.id == session.userId
);
{company &&
managers &&
selectedBuild &&
generatedScheduledSession.sessions.map(
(session: any, index2: number) => {
const selectedManager = managers.find(
(manager) => manager.id == session.userId
);
if (!_.isEmpty(session)) {
return (
<Card
key={index2}
companyId={company?.id}
buildId={selectedBuild?.id}
scheduledSessionId={session.id}
scheduleSessionStartAt={session.startAt}
client={session.client}
manager={selectedManager}
managers={selectedBuildManagers || []}
handleSelect={(scheduledSessionId, managerId) =>
updateScheduledSessionManager(
scheduledSessionId,
managerId
)
}
/>
);
} else {
return (
<EmptyCard
key={index2}
buildId={selectedBuild?.id}
startAt={generatedScheduledSession.time}
duration={duration!}
/>
);
if (!_.isEmpty(session)) {
return (
<Card
key={index2}
companyId={company.id}
buildId={selectedBuild.id}
scheduledSessionId={session.id}
scheduleSessionStartAt={session.startAt}
client={session.client}
manager={selectedManager}
managers={managers}
handleSelect={(scheduledSessionId, managerId) =>
updateScheduledSessionManager(
scheduledSessionId,
managerId
)
}
/>
);
} else {
return (
<EmptyCard
key={index2}
buildId={selectedBuild?.id}
startAt={generatedScheduledSession.time}
duration={duration!}
/>
);
}
}
}
)}
)}
</div>
</div>
)
)}
{/* {company &&
selectedBuild &&
user &&
generatedScheduledSessions?.map(
(generatedScheduledSession, index) => {
return (
<div key={index} className="flex">
{generatedScheduledSession.map(
(scheduledSession, index2) => {
if (index2 === 0) {
return (
<div
key={index2}
className="w-[84px] h-[164px] flex justify-center items-center text-sm font-semibold bg-[#F0F1F2] border-r border-b border-[#DAE0E5]"
>
{format(scheduledSession, "HH:mm")}
</div>
);
} else {
if (Object.keys(scheduledSession).length) {
const selectedManager = selectedBuildManagers?.find(
(manager) => manager.id == scheduledSession.userId
);
return (
<Card
key={index2}
companyId={company.id}
buildId={selectedBuild.id}
scheduledSessionId={scheduledSession.id}
scheduleSessionStartAt={
scheduledSession.startAt
}
client={scheduledSession.client}
manager={selectedManager}
managers={selectedBuildManagers || []}
handleSelect={(scheduledSessionId, managerId) =>
updateScheduledSessionManager(
scheduledSessionId,
managerId
)
}
/>
);
} else {
return <EmptyCard key={index2} />;
}
}
}
)}
</div>
);
}
)} */}
</div>
</div>
@@ -576,110 +452,9 @@ function DashboardPage() {
</button>
</div>
<div className="overflow-y-auto overflow-x-hidden">
<div className="p-4 space-y-2">
<div className="flex justify-between items-center">
<p className="text-sm font-semibold">Календарь</p>
<Button color="tertiary" icon={<ChevronUpIcon />} onlyIcon />
</div>
<Calendar
defaultValue={selectedDate}
onChange={(date) => setSelectedDate(date)}
/>
</div>
<div className="p-4 flex flex-col gap-4">
<p className="text-sm font-semibold">Расписание</p>
{schedules?.map((schedule) => (
<div key={schedule.id} className="flex flex-col gap-3 text-xs">
<p className="font-semibold flex gap-1">
<span>
Действует с{" "}
{format(new Date(schedule.startDate), "dd.MM.yyyy")}
</span>
{/* <span>-</span> */}
<span>
{/* {format(parseISO(schedule.endDate), "dd.MM.yyyy")} */}
</span>
</p>
<div className="flex flex-col gap-2">
<div className="grid grid-cols-3">
<p className="col-span-2 text-[#77828C]">Сеансов в день</p>
<p>{schedule.sessionsPerDay}</p>
</div>
<div className="grid grid-cols-3">
<p className="col-span-2 text-[#77828C]">
Длительность сеанса
</p>
<p>{schedule.sessionDuration} мин.</p>
</div>
<div className="grid grid-cols-3">
<p className="col-span-2 text-[#77828C]">Между сеансами</p>
<p>{schedule.sessionBreak} мин.</p>
</div>
<div className="grid grid-cols-3">
<p className="col-span-2 text-[#77828C]">Время работы</p>
<p>
{schedule.startTime} - {schedule.endTime}
</p>
</div>
</div>
</div>
))}
<Button
color="secondary"
className="w-full"
handleClick={() =>
setModal(
<CreateScheduleModal
companyId={company?.id}
buildId={selectedBuild?.id}
// schedules={schedules}
handleCreate={getSchedules}
/>
)
}
>
Добавить
</Button>
</div>
<div className="p-4 flex flex-col gap-4">
<p className="text-sm font-semibold">Менеджеры</p>
<div className="flex flex-col gap-2">
{selectedBuildManagers?.map((manager) => (
<div key={manager.id} className="flex justify-between">
<div className="flex items-center gap-2">
<img
src={manager.avatar}
alt=""
className="w-8 h-8 rounded-full"
/>
<p className="text-sm leading-[140%]">{manager.name}</p>
</div>
<Button
disabled
color="tertiary"
onlyIcon
icon={<MoreIcon />}
handleClick={() => {}}
/>
</div>
))}
</div>
<Button
disabled
color="secondary"
className="w-full"
handleClick={() => {}}
>
Добавить
</Button>
</div>
<Calendar />
<Schedules />
<Managers />
</div>
</div>