upd
This commit is contained in:
@@ -1,14 +1,8 @@
|
|||||||
/* eslint-disable react-hooks/exhaustive-deps */
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
import { useEffect, useState } from "react";
|
import { ChangeEvent, useEffect, useState } from "react";
|
||||||
import Timeline from "./Timeline";
|
import Timeline from "./Timeline";
|
||||||
import {
|
import { format, getDate, setDate, setHours, startOfDay } from "date-fns";
|
||||||
format,
|
|
||||||
getDate,
|
|
||||||
setDate,
|
|
||||||
setHours,
|
|
||||||
startOfDay,
|
|
||||||
} from "date-fns";
|
|
||||||
// import useEventStore from "../stores/useEventStore";
|
// import useEventStore from "../stores/useEventStore";
|
||||||
import Button from "./Button";
|
import Button from "./Button";
|
||||||
import CloseIcon from "./icons/CloseIcon";
|
import CloseIcon from "./icons/CloseIcon";
|
||||||
@@ -16,15 +10,17 @@ import Input from "./Input";
|
|||||||
import Label from "./Label";
|
import Label from "./Label";
|
||||||
import api from "../utils/api";
|
import api from "../utils/api";
|
||||||
import useStore from "../stores/useStore";
|
import useStore from "../stores/useStore";
|
||||||
|
import Select2 from "./Select2";
|
||||||
|
import IScheduledSession from "../types/IScheduledSession";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
selectedDay: Date;
|
selectedDay: Date;
|
||||||
slots: number;
|
slots: number;
|
||||||
events: any[];
|
events: IScheduledSession[];
|
||||||
}
|
}
|
||||||
|
|
||||||
function Schedule({ selectedDay, slots, events }: Props) {
|
function Schedule({ selectedDay, slots, events }: Props) {
|
||||||
const { selectedBuild } = useStore();
|
const { company, builds, selectedBuild, setSelectedBuild } = useStore();
|
||||||
const [draftMode, setDraftMode] = useState<boolean>(false);
|
const [draftMode, setDraftMode] = useState<boolean>(false);
|
||||||
const [slot, setSlot] = useState<number>();
|
const [slot, setSlot] = useState<number>();
|
||||||
const [startAt, setStartAt] = useState<Date>();
|
const [startAt, setStartAt] = useState<Date>();
|
||||||
@@ -77,6 +73,7 @@ function Schedule({ selectedDay, slots, events }: Props) {
|
|||||||
await api
|
await api
|
||||||
.post(`scheduled_sessions`, {
|
.post(`scheduled_sessions`, {
|
||||||
json: {
|
json: {
|
||||||
|
companyId: company!.id,
|
||||||
buildId: selectedBuild?.id,
|
buildId: selectedBuild?.id,
|
||||||
slot,
|
slot,
|
||||||
startAt,
|
startAt,
|
||||||
@@ -97,9 +94,17 @@ function Schedule({ selectedDay, slots, events }: Props) {
|
|||||||
// setModal(null);
|
// setModal(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!builds) return;
|
||||||
|
|
||||||
|
setSelectedBuild(builds[0]);
|
||||||
|
|
||||||
|
console.log(builds);
|
||||||
|
}, [builds]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log("events", events);
|
console.log("events", events);
|
||||||
}, []);
|
}, [events]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative h-screen overflow-y-auto bg-[#F2F2F2] text-sm">
|
<div className="relative h-screen overflow-y-auto bg-[#F2F2F2] text-sm">
|
||||||
@@ -114,7 +119,7 @@ function Schedule({ selectedDay, slots, events }: Props) {
|
|||||||
key={index}
|
key={index}
|
||||||
className="border-r border-b border-[#DAE0E5] w-[264px] h-10 flex items-center pl-3 bg-[#F0F1F2]"
|
className="border-r border-b border-[#DAE0E5] w-[264px] h-10 flex items-center pl-3 bg-[#F0F1F2]"
|
||||||
>
|
>
|
||||||
<p className="font-semibold">Слот {index + 1}</p>
|
<p className="font-semibold">Сервер {index + 1}</p>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@@ -166,6 +171,24 @@ function Schedule({ selectedDay, slots, events }: Props) {
|
|||||||
<div className="px-4 space-y-2">
|
<div className="px-4 space-y-2">
|
||||||
<p className="font-semibold">Демонстрация</p>
|
<p className="font-semibold">Демонстрация</p>
|
||||||
<div className="">
|
<div className="">
|
||||||
|
<div className="py-1 space-y-1 text-xs">
|
||||||
|
<p className="text-[#77828C]">Выберите ЖК</p>
|
||||||
|
<Select2
|
||||||
|
defaultValue={selectedBuild?.build}
|
||||||
|
options={builds.map((build) => ({
|
||||||
|
value: build.build,
|
||||||
|
text: build.name,
|
||||||
|
}))}
|
||||||
|
onChange={(e: ChangeEvent<HTMLSelectElement>) =>
|
||||||
|
setSelectedBuild(
|
||||||
|
builds.find(
|
||||||
|
(build) =>
|
||||||
|
build.build === e.target.selectedOptions[0].value
|
||||||
|
)!
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<div className="grid items-center grid-cols-2 gap-4 py-1 text-xs">
|
<div className="grid items-center grid-cols-2 gap-4 py-1 text-xs">
|
||||||
<p className="text-[#77828C]">Дата и время</p>
|
<p className="text-[#77828C]">Дата и время</p>
|
||||||
<p className="">{format(startAt, "dd.MM.yyyy HH:mm")}</p>
|
<p className="">{format(startAt, "dd.MM.yyyy HH:mm")}</p>
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
import { ChangeEvent } from "react";
|
||||||
|
|
||||||
|
interface IOption {
|
||||||
|
value: string;
|
||||||
|
text: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
defaultValue?: string;
|
||||||
|
options: IOption[];
|
||||||
|
onChange: (e: ChangeEvent<HTMLSelectElement>) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Select2({ defaultValue, options, onChange }: Props) {
|
||||||
|
function handleChange(e: ChangeEvent<HTMLSelectElement>) {
|
||||||
|
onChange(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<select
|
||||||
|
onChange={handleChange}
|
||||||
|
defaultValue={defaultValue}
|
||||||
|
className="px-2 py-2.5 outline-none rounded-lg border border-[#DAE0E5] focus:border-[#49A1F5] transition-colors text-sm w-full h-10"
|
||||||
|
>
|
||||||
|
{options.map((option, index) => (
|
||||||
|
<option key={index} value={option.value}>
|
||||||
|
{option.text}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Select2;
|
||||||
@@ -4,9 +4,11 @@ import { useState, MouseEvent, useEffect, useRef } from "react";
|
|||||||
import TimelineSlot from "./TimelineSlot";
|
import TimelineSlot from "./TimelineSlot";
|
||||||
import { addMinutes, differenceInMinutes, format, startOfDay } from "date-fns";
|
import { addMinutes, differenceInMinutes, format, startOfDay } from "date-fns";
|
||||||
import Button from "./Button";
|
import Button from "./Button";
|
||||||
|
import IScheduledSession from "../types/IScheduledSession";
|
||||||
|
import useStore from "../stores/useStore";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
timelineEvents: any[];
|
timelineEvents: IScheduledSession[];
|
||||||
slot: number;
|
slot: number;
|
||||||
draftMode: boolean;
|
draftMode: boolean;
|
||||||
onChangeDraftMode: (draftMode: boolean) => void;
|
onChangeDraftMode: (draftMode: boolean) => void;
|
||||||
@@ -33,6 +35,7 @@ function Timeline({
|
|||||||
const ref = useRef<HTMLDivElement>(null);
|
const ref = useRef<HTMLDivElement>(null);
|
||||||
const [startAt, setStartAt] = useState<string>();
|
const [startAt, setStartAt] = useState<string>();
|
||||||
const [duration, setDuration] = useState<number>(30); // min
|
const [duration, setDuration] = useState<number>(30); // min
|
||||||
|
const { builds } = useStore();
|
||||||
|
|
||||||
function handleMouseDown(e: MouseEvent<HTMLDivElement>) {
|
function handleMouseDown(e: MouseEvent<HTMLDivElement>) {
|
||||||
if (draftMode) return;
|
if (draftMode) return;
|
||||||
@@ -168,10 +171,13 @@ function Timeline({
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="flex flex-col justify-between h-full">
|
<div className="flex flex-col justify-between h-full">
|
||||||
<p>
|
<div className="space-y-1">
|
||||||
{format(new Date(event.startAt), "HH:mm")} -{" "}
|
<p>
|
||||||
{format(new Date(event.endAt), "HH:mm")}
|
{format(new Date(event.startAt), "HH:mm")} -{" "}
|
||||||
</p>
|
{format(new Date(event.endAt), "HH:mm")}
|
||||||
|
</p>
|
||||||
|
<p>{builds.find((build) => build.id === event.buildId)?.name}</p>
|
||||||
|
</div>
|
||||||
<a
|
<a
|
||||||
href={`https://stream.graff.tech/scheduled/${event.id}?admin=true`}
|
href={`https://stream.graff.tech/scheduled/${event.id}?admin=true`}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ function CreateScheduledSessionModal({ buildId, startAt, duration }: Props) {
|
|||||||
onSubmit={addSchesuledSession}
|
onSubmit={addSchesuledSession}
|
||||||
>
|
>
|
||||||
<div className="p-2 pl-6 flex justify-between items-center border-b border-[#DAE0E5]">
|
<div className="p-2 pl-6 flex justify-between items-center border-b border-[#DAE0E5]">
|
||||||
<p className="font-semibold text-sm">Запланировать демонстрацию</p>
|
<p className="text-sm font-semibold">Запланировать демонстрацию</p>
|
||||||
<span className="text-[#77828C]">
|
<span className="text-[#77828C]">
|
||||||
<Button
|
<Button
|
||||||
color="tertiary"
|
color="tertiary"
|
||||||
@@ -68,18 +68,18 @@ function CreateScheduledSessionModal({ buildId, startAt, duration }: Props) {
|
|||||||
<div className="px-6 py-8 space-y-8 border-b border-[#DAE0E5]">
|
<div className="px-6 py-8 space-y-8 border-b border-[#DAE0E5]">
|
||||||
<div className="flex gap-4">
|
<div className="flex gap-4">
|
||||||
<div className="w-[240px]">
|
<div className="w-[240px]">
|
||||||
<p className="font-semibold text-sm">Демонстрация</p>
|
<p className="text-sm font-semibold">Демонстрация</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-[296px]">
|
<div className="w-[296px]">
|
||||||
<div className="grid grid-cols-2 gap-4 text-xs py-1">
|
<div className="grid grid-cols-2 gap-4 py-1 text-xs">
|
||||||
<p className="text-[#77828C]">Дата и время</p>
|
<p className="text-[#77828C]">Дата и время</p>
|
||||||
<p className="">{format(startAt, "dd.MM.yyyy HH:mm")}</p>
|
<p className="">{format(startAt, "dd.MM.yyyy HH:mm")}</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid grid-cols-2 gap-4 text-xs py-1">
|
<div className="grid grid-cols-2 gap-4 py-1 text-xs">
|
||||||
<p className="text-[#77828C]">Длительность сеанса</p>
|
<p className="text-[#77828C]">Длительность сеанса</p>
|
||||||
<p className="">{duration} мин.</p>
|
<p className="">{duration} мин.</p>
|
||||||
</div>
|
</div>
|
||||||
{/* <div className="grid grid-cols-2 gap-4 text-xs py-1">
|
{/* <div className="grid grid-cols-2 gap-4 py-1 text-xs">
|
||||||
<p className="text-[#77828C]">Жилой комплекс</p>
|
<p className="text-[#77828C]">Жилой комплекс</p>
|
||||||
<p className="">Название ЖК</p>
|
<p className="">Название ЖК</p>
|
||||||
</div> */}
|
</div> */}
|
||||||
@@ -90,7 +90,7 @@ function CreateScheduledSessionModal({ buildId, startAt, duration }: Props) {
|
|||||||
<div className="w-[240px]">
|
<div className="w-[240px]">
|
||||||
<div className="flex flex-col justify-between h-full">
|
<div className="flex flex-col justify-between h-full">
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<p className="font-semibold text-sm">Укажите данные клиента*</p>
|
<p className="text-sm font-semibold">Укажите данные клиента*</p>
|
||||||
<p className="text-xs text-[#77828C]">
|
<p className="text-xs text-[#77828C]">
|
||||||
На указанный почтовый адрес будет отправлена информация
|
На указанный почтовый адрес будет отправлена информация
|
||||||
необходимая для подключения
|
необходимая для подключения
|
||||||
|
|||||||
@@ -1,15 +1,7 @@
|
|||||||
/* eslint-disable react-hooks/exhaustive-deps */
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
import {
|
import { format, addDays, subDays } from "date-fns";
|
||||||
eachMinuteOfInterval,
|
|
||||||
format,
|
|
||||||
parse,
|
|
||||||
addDays,
|
|
||||||
subDays,
|
|
||||||
isEqual,
|
|
||||||
} from "date-fns";
|
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import TabButton from "../components/TabButton";
|
|
||||||
import api from "../utils/api";
|
import api from "../utils/api";
|
||||||
import { ru } from "date-fns/locale";
|
import { ru } from "date-fns/locale";
|
||||||
import useStore from "../stores/useStore";
|
import useStore from "../stores/useStore";
|
||||||
@@ -24,6 +16,7 @@ import ChevronRightIcon from "../components/icons/ChevronRightIcon";
|
|||||||
import IUser from "../types/IUser";
|
import IUser from "../types/IUser";
|
||||||
import IError from "../types/IError";
|
import IError from "../types/IError";
|
||||||
import Schedule from "../components/Schedule";
|
import Schedule from "../components/Schedule";
|
||||||
|
import IScheduledSession from "../types/IScheduledSession";
|
||||||
|
|
||||||
function DashboardPage() {
|
function DashboardPage() {
|
||||||
const { user } = useAuthStore();
|
const { user } = useAuthStore();
|
||||||
@@ -31,20 +24,19 @@ function DashboardPage() {
|
|||||||
company,
|
company,
|
||||||
setCompany,
|
setCompany,
|
||||||
selectedBuild,
|
selectedBuild,
|
||||||
setSelectedBuild,
|
|
||||||
builds,
|
builds,
|
||||||
setBuilds,
|
setBuilds,
|
||||||
managers,
|
managers,
|
||||||
setManagers,
|
setManagers,
|
||||||
schedules,
|
|
||||||
setSchedules,
|
|
||||||
selectedDay,
|
selectedDay,
|
||||||
setSelectedDay,
|
setSelectedDay,
|
||||||
} = useStore();
|
} = useStore();
|
||||||
const [, setDuration] = useState<number>();
|
// const [, setDuration] = useState<number>();
|
||||||
const [scheduledSessions, setScheduledSessions] = useState<any[]>();
|
const [scheduledSessions, setScheduledSessions] = useState<
|
||||||
const [, setGeneratedScheduledSessions] = useState<any[]>();
|
IScheduledSession[]
|
||||||
const [dateTimes, setDateTimes] = useState<Date[]>();
|
>([]);
|
||||||
|
// const [, setGeneratedScheduledSessions] = useState<any[]>();
|
||||||
|
// const [dateTimes, setDateTimes] = useState<Date[]>();
|
||||||
const [, setCurrentTime] = useState<string>(format(new Date(), "HH:mm"));
|
const [, setCurrentTime] = useState<string>(format(new Date(), "HH:mm"));
|
||||||
const [, setIsLoadingScheduledSessions] = useState(true);
|
const [, setIsLoadingScheduledSessions] = useState(true);
|
||||||
const scheduledSessionsRef = useRef<HTMLDivElement>(null);
|
const scheduledSessionsRef = useRef<HTMLDivElement>(null);
|
||||||
@@ -61,78 +53,6 @@ function DashboardPage() {
|
|||||||
setSelectedDay(new Date());
|
setSelectedDay(new Date());
|
||||||
}
|
}
|
||||||
|
|
||||||
function findSessionsByTime(time: Date) {
|
|
||||||
if (!scheduledSessions || !scheduledSessions.length) return [];
|
|
||||||
|
|
||||||
const foundScheduledSessions = scheduledSessions?.filter(
|
|
||||||
(scheduledSession) => isEqual(new Date(scheduledSession.startAt), time)
|
|
||||||
);
|
|
||||||
|
|
||||||
return foundScheduledSessions;
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateScheduledSessions() {
|
|
||||||
if (!selectedBuild) return;
|
|
||||||
|
|
||||||
const newGeneratedScheduledSession: any[] = [];
|
|
||||||
|
|
||||||
dateTimes?.forEach((time) => {
|
|
||||||
const foundSessionsByTime = findSessionsByTime(time);
|
|
||||||
const sessions: any[] = [];
|
|
||||||
|
|
||||||
if (foundSessionsByTime) {
|
|
||||||
sessions.push(...foundSessionsByTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (
|
|
||||||
let index = 0;
|
|
||||||
index < selectedBuild.sessionLimit - foundSessionsByTime.length;
|
|
||||||
index++
|
|
||||||
) {
|
|
||||||
sessions.push({});
|
|
||||||
}
|
|
||||||
|
|
||||||
newGeneratedScheduledSession.push({
|
|
||||||
time,
|
|
||||||
sessions,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
setGeneratedScheduledSessions(newGeneratedScheduledSession);
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!scheduledSessions || !selectedBuild || !selectedDay) return;
|
|
||||||
generateScheduledSessions();
|
|
||||||
}, [scheduledSessions, selectedBuild, selectedDay]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!schedules || !selectedDay || !selectedBuild) return;
|
|
||||||
|
|
||||||
console.log("schedules", schedules);
|
|
||||||
|
|
||||||
const foundSchedule = schedules.find(
|
|
||||||
(schedule) => schedule.buildId === selectedBuild.id
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!foundSchedule) {
|
|
||||||
setDateTimes([]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const step = foundSchedule.sessionDuration + foundSchedule.sessionBreak; // 35
|
|
||||||
const newTimes = eachMinuteOfInterval(
|
|
||||||
{
|
|
||||||
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, selectedDay, selectedBuild]);
|
|
||||||
|
|
||||||
async function getCompany() {
|
async function getCompany() {
|
||||||
if (!user) {
|
if (!user) {
|
||||||
console.log("No User", user);
|
console.log("No User", user);
|
||||||
@@ -141,6 +61,7 @@ function DashboardPage() {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const result: any = await api.get(`companies/${user.companyId}`).json();
|
const result: any = await api.get(`companies/${user.companyId}`).json();
|
||||||
|
|
||||||
setCompany(result);
|
setCompany(result);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof Error) {
|
if (error instanceof Error) {
|
||||||
@@ -159,6 +80,7 @@ function DashboardPage() {
|
|||||||
const result: any = await api
|
const result: any = await api
|
||||||
.get(`companies/${user.companyId}/builds`)
|
.get(`companies/${user.companyId}/builds`)
|
||||||
.json();
|
.json();
|
||||||
|
|
||||||
setBuilds(result);
|
setBuilds(result);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof Error) {
|
if (error instanceof Error) {
|
||||||
@@ -196,22 +118,19 @@ function DashboardPage() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!selectedBuild || !selectedBuild.id) {
|
|
||||||
console.log("No selectedBuild");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (useLoader) setIsLoadingScheduledSessions(true);
|
if (useLoader) setIsLoadingScheduledSessions(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result: any = await api
|
const result: any = await api
|
||||||
.get(
|
.get(
|
||||||
`companies/${company.id}/builds/${
|
`companies/${
|
||||||
selectedBuild.id
|
company.id
|
||||||
}/scheduled_sessions?date=${selectedDay.toISOString()}`
|
}/scheduled_sessions?date=${selectedDay.toISOString()}`
|
||||||
)
|
)
|
||||||
.json();
|
.json();
|
||||||
|
|
||||||
|
console.log(result);
|
||||||
|
|
||||||
setScheduledSessions(result);
|
setScheduledSessions(result);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof Error) {
|
if (error instanceof Error) {
|
||||||
@@ -222,44 +141,6 @@ function DashboardPage() {
|
|||||||
if (useLoader) setIsLoadingScheduledSessions(false);
|
if (useLoader) setIsLoadingScheduledSessions(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// async function updateScheduledSessionManager(
|
|
||||||
// scheduledSessionId: string,
|
|
||||||
// managerId: string | null
|
|
||||||
// ) {
|
|
||||||
// if (!company || !scheduledSessions) return;
|
|
||||||
|
|
||||||
// try {
|
|
||||||
// const result: any = await api
|
|
||||||
// .put(
|
|
||||||
// `companies/${company.id}/scheduled_sessions/${scheduledSessionId}`,
|
|
||||||
// {
|
|
||||||
// json: { userId: managerId },
|
|
||||||
// }
|
|
||||||
// )
|
|
||||||
// .json();
|
|
||||||
|
|
||||||
// setScheduledSessions(
|
|
||||||
// scheduledSessions.map((scheduledSession) =>
|
|
||||||
// scheduledSession.id === result.id ? result : scheduledSession
|
|
||||||
// )
|
|
||||||
// );
|
|
||||||
// } catch (error) {
|
|
||||||
// if (error instanceof Error) {
|
|
||||||
// console.log("Error: ", error.message);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
async function getSchedules() {
|
|
||||||
if (!company || !selectedBuild) return;
|
|
||||||
|
|
||||||
const result: any[] = await api
|
|
||||||
.get(`companies/${company.id}/builds/${selectedBuild.id}/schedules`)
|
|
||||||
.json();
|
|
||||||
|
|
||||||
setSchedules(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getCompany();
|
getCompany();
|
||||||
|
|
||||||
@@ -274,16 +155,19 @@ function DashboardPage() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!company) return;
|
if (!company) return;
|
||||||
|
|
||||||
getBuilds();
|
getBuilds();
|
||||||
}, [company]);
|
}, [company]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!builds) return;
|
if (!builds) return;
|
||||||
setSelectedBuild(builds[0]);
|
|
||||||
|
getManagers();
|
||||||
}, [builds]);
|
}, [builds]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!managers || !selectedDay || !selectedBuild) return;
|
if (!managers || !selectedDay || !company || !builds) return;
|
||||||
|
|
||||||
getScheduledSessions(true);
|
getScheduledSessions(true);
|
||||||
|
|
||||||
const interval = setInterval(() => {
|
const interval = setInterval(() => {
|
||||||
@@ -293,35 +177,17 @@ function DashboardPage() {
|
|||||||
return () => {
|
return () => {
|
||||||
clearInterval(interval);
|
clearInterval(interval);
|
||||||
};
|
};
|
||||||
}, [managers, selectedDay, selectedBuild]);
|
}, [managers, selectedDay, company, builds]);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!company || !selectedBuild) return;
|
|
||||||
|
|
||||||
getSchedules();
|
|
||||||
getManagers();
|
|
||||||
}, [selectedBuild]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
scheduledSessionsRef.current?.scrollTo({ top: 0, behavior: "smooth" });
|
scheduledSessionsRef.current?.scrollTo({ top: 0, behavior: "smooth" });
|
||||||
}, [selectedDay, selectedBuild]);
|
}, [selectedDay]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex h-screen main">
|
<div className="flex h-screen main">
|
||||||
<div className="flex flex-col w-full left">
|
<div className="flex flex-col w-full left">
|
||||||
<div className="flex bg-[#F0F1F2]">
|
<div className="flex bg-[#F0F1F2]">
|
||||||
<Menu />
|
<Menu />
|
||||||
{builds?.map((build) => (
|
|
||||||
<TabButton
|
|
||||||
key={build.id}
|
|
||||||
handleClick={() => setSelectedBuild(build)}
|
|
||||||
active={
|
|
||||||
(selectedBuild && build.id === selectedBuild?.id) || false
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{build.name}
|
|
||||||
</TabButton>
|
|
||||||
))}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex justify-between items-center px-4 py-2 h-12 border-r border-b border-[#DAE0E5]">
|
<div className="flex justify-between items-center px-4 py-2 h-12 border-r border-b border-[#DAE0E5]">
|
||||||
@@ -436,10 +302,10 @@ function DashboardPage() {
|
|||||||
)}
|
)}
|
||||||
</div> */}
|
</div> */}
|
||||||
|
|
||||||
{selectedBuild?.sessionLimit && scheduledSessions && (
|
{company && scheduledSessions && (
|
||||||
<Schedule
|
<Schedule
|
||||||
selectedDay={selectedDay}
|
selectedDay={selectedDay}
|
||||||
slots={selectedBuild.sessionLimit}
|
slots={company.sessionLimit}
|
||||||
events={scheduledSessions}
|
events={scheduledSessions}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
interface ICompany {
|
interface ICompany {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
|
sessionLimit: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ICompany;
|
export default ICompany;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ interface IScheduledSession {
|
|||||||
id: string;
|
id: string;
|
||||||
companyId: string;
|
companyId: string;
|
||||||
buildId: string;
|
buildId: string;
|
||||||
|
slot: number;
|
||||||
startAt: string;
|
startAt: string;
|
||||||
endAt: string;
|
endAt: string;
|
||||||
client?: unknown;
|
client?: unknown;
|
||||||
|
|||||||
@@ -21,14 +21,14 @@ companySchema.virtual("users", {
|
|||||||
foreignField: "companyId",
|
foreignField: "companyId",
|
||||||
});
|
});
|
||||||
|
|
||||||
companySchema.virtual("scheduledSessions", {
|
companySchema.virtual("builds", {
|
||||||
ref: "Scheduled_Session",
|
ref: "Build",
|
||||||
localField: "_id",
|
localField: "_id",
|
||||||
foreignField: "companyId",
|
foreignField: "companyId",
|
||||||
});
|
});
|
||||||
|
|
||||||
companySchema.virtual("builds", {
|
companySchema.virtual("scheduledSessions", {
|
||||||
ref: "Build",
|
ref: "Scheduled_Session",
|
||||||
localField: "_id",
|
localField: "_id",
|
||||||
foreignField: "companyId",
|
foreignField: "companyId",
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ const scheduledSessionSchema = new Schema(
|
|||||||
companyId: {
|
companyId: {
|
||||||
type: Schema.Types.ObjectId,
|
type: Schema.Types.ObjectId,
|
||||||
ref: "Company",
|
ref: "Company",
|
||||||
// required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
buildId: {
|
buildId: {
|
||||||
type: Schema.Types.ObjectId,
|
type: Schema.Types.ObjectId,
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ router.get("/:id/builds/:buildId/users", async (req, res) => {
|
|||||||
res.json(users);
|
res.json(users);
|
||||||
});
|
});
|
||||||
|
|
||||||
router.get("/:id/builds/:buildId/scheduled_sessions", async (req, res) => {
|
router.get("/:id/scheduled_sessions", async (req, res) => {
|
||||||
if (req.params.id != res.locals.user.companyId) {
|
if (req.params.id != res.locals.user.companyId) {
|
||||||
res.json({ error: "Access denied" });
|
res.json({ error: "Access denied" });
|
||||||
return;
|
return;
|
||||||
@@ -82,22 +82,16 @@ router.get("/:id/builds/:buildId/scheduled_sessions", async (req, res) => {
|
|||||||
const date = parseISO(req.query.date as string);
|
const date = parseISO(req.query.date as string);
|
||||||
|
|
||||||
const company: any = await Company.findById(req.params.id).populate({
|
const company: any = await Company.findById(req.params.id).populate({
|
||||||
path: "builds",
|
path: "scheduledSessions",
|
||||||
match: {
|
match: {
|
||||||
_id: req.params.buildId,
|
startAt: {
|
||||||
},
|
$gte: startOfDay(date),
|
||||||
populate: {
|
$lte: endOfDay(date),
|
||||||
path: "scheduledSessions",
|
|
||||||
match: {
|
|
||||||
startAt: {
|
|
||||||
$gte: startOfDay(date),
|
|
||||||
$lte: endOfDay(date),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const { scheduledSessions } = company.builds[0];
|
const { scheduledSessions } = company;
|
||||||
|
|
||||||
res.json(scheduledSessions);
|
res.json(scheduledSessions);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -75,9 +75,9 @@ router.get("/:buildId", async (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.post("/", async (req, res) => {
|
router.post("/", async (req, res) => {
|
||||||
const { buildId, slot, startAt, client, duration } = req.body;
|
const { companyId, buildId, slot, startAt, client, duration } = req.body;
|
||||||
|
|
||||||
if (!buildId || !startAt || !slot) {
|
if (!companyId || !buildId || !startAt || !slot) {
|
||||||
return res.json({
|
return res.json({
|
||||||
status: "error",
|
status: "error",
|
||||||
message: "Parameters `buildId`, `startAt`, `slot` are required!", // Параметры `buildId`, `startAt`, `slot` обязательны!
|
message: "Parameters `buildId`, `startAt`, `slot` are required!", // Параметры `buildId`, `startAt`, `slot` обязательны!
|
||||||
@@ -104,6 +104,7 @@ router.post("/", async (req, res) => {
|
|||||||
|
|
||||||
if (duration) {
|
if (duration) {
|
||||||
const scheduledSessions = await ScheduledSession.find({
|
const scheduledSessions = await ScheduledSession.find({
|
||||||
|
companyId,
|
||||||
buildId,
|
buildId,
|
||||||
slot,
|
slot,
|
||||||
startAt: {
|
startAt: {
|
||||||
@@ -141,6 +142,7 @@ router.post("/", async (req, res) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const scheduledSession = await ScheduledSession.create({
|
const scheduledSession = await ScheduledSession.create({
|
||||||
|
companyId,
|
||||||
buildId,
|
buildId,
|
||||||
slot,
|
slot,
|
||||||
startAt: startAtISO,
|
startAt: startAtISO,
|
||||||
|
|||||||
Reference in New Issue
Block a user