188 lines
6.1 KiB
TypeScript
188 lines
6.1 KiB
TypeScript
/* eslint-disable react-hooks/exhaustive-deps */
|
||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||
import { useEffect, useState } from "react";
|
||
import SelectUser from "./SelectUser";
|
||
import MoreIcon from "./icons/MoreIcon";
|
||
import api from "../utils/api";
|
||
import Button from "./Button";
|
||
import { Link } from "react-router-dom";
|
||
import IUser from "../types/IUser";
|
||
import useAuthStore from "../stores/useAuthStore";
|
||
import EntryIcon from "./icons/EntryIcon";
|
||
import { isAfter, subMinutes } from "date-fns";
|
||
|
||
interface CardProps {
|
||
companyId: string;
|
||
buildId: string;
|
||
scheduledSessionId: string;
|
||
scheduleSessionStartAt: string;
|
||
client?: {
|
||
name: string;
|
||
phone: string;
|
||
email: string;
|
||
};
|
||
manager?: IUser;
|
||
managers: IUser[];
|
||
handleSelect: (scheduledSessionId: string, managerId: string | null) => void;
|
||
}
|
||
|
||
function Card({
|
||
companyId,
|
||
buildId,
|
||
scheduledSessionId,
|
||
scheduleSessionStartAt,
|
||
client,
|
||
manager,
|
||
managers,
|
||
handleSelect,
|
||
}: CardProps) {
|
||
const { user } = useAuthStore();
|
||
const [isShow, setIsShow] = useState<boolean>(false);
|
||
const [availableManagers, setAvailableManagers] = useState<IUser[]>();
|
||
|
||
async function getAvailableManagers() {
|
||
const result: any[] = await api
|
||
.get(
|
||
`companies/${companyId}/builds/${buildId}/scheduledSessions/${scheduledSessionId}/availableManagers?startAt=${scheduleSessionStartAt}`
|
||
)
|
||
.json();
|
||
|
||
const filteredManagers = managers.filter((manager) =>
|
||
result.includes(manager.id)
|
||
);
|
||
|
||
setAvailableManagers(filteredManagers);
|
||
}
|
||
|
||
useEffect(() => {
|
||
if (!isShow) return;
|
||
getAvailableManagers();
|
||
}, [isShow]);
|
||
|
||
return (
|
||
<div className="relative flex flex-col gap-2">
|
||
<div className="w-[264px] h-[164px] px-3 py-2 bg-white border-r border-b border-[#DAE0E5] flex flex-col justify-between gap-2">
|
||
<div className="space-y-2">
|
||
<div className="flex justify-between">
|
||
<div className="">
|
||
<p className="text-[10px] font-semibold text-[#77828C]">Клиент</p>
|
||
<p className="text-sm">{client?.name || "Имя не указано"}</p>
|
||
</div>
|
||
{manager ? (
|
||
<div className="bg-[#E6F2FE] rounded-full px-2 h-[20px] flex items-center gap-1">
|
||
<div className="w-1 h-1 rounded-full bg-[#49A1F5]"></div>
|
||
<p className="text-[10px] font-semibold text-[#49A1F5]">
|
||
Готов
|
||
</p>
|
||
</div>
|
||
) : (
|
||
<div className="bg-[#F2DADA] rounded-full px-2 h-[20px] flex items-center gap-1">
|
||
<div className="w-1 h-1 rounded-full bg-[#EB5757]"></div>
|
||
<p className="text-[10px] font-semibold text-[#EB5757] pt-0.5">
|
||
Нет менеджера
|
||
</p>
|
||
</div>
|
||
)}
|
||
</div>
|
||
<div>
|
||
<p className="text-xs text-[#77828C] leading-tight">
|
||
{client?.phone || "Телефон не указан"}
|
||
</p>
|
||
<p className="text-xs text-[#77828C] leading-tight">
|
||
{client?.email || "Email не указан"}
|
||
</p>
|
||
</div>
|
||
</div>
|
||
<div className="flex justify-between items-center pt-2 py-1 border-t border-[#DAE0E5] h-[45px]">
|
||
<div className="flex items-center gap-2">
|
||
{manager ? (
|
||
<img
|
||
src={manager.avatar || "/images/no-avatar.png"}
|
||
alt=""
|
||
className="w-6 h-6 rounded-full"
|
||
/>
|
||
) : (
|
||
<div className="w-6 h-6 bg-[#E6ECF2] rounded-full"></div>
|
||
)}
|
||
<p className="text-xs font-semibold">
|
||
{manager ? manager.name : "Не назначен"}
|
||
</p>
|
||
</div>
|
||
|
||
<div className="flex gap-2">
|
||
{user?.role === "manager" &&
|
||
(manager ? (
|
||
isAfter(
|
||
new Date(),
|
||
subMinutes(new Date(scheduleSessionStartAt), 10)
|
||
) ? (
|
||
<Link
|
||
to={`${
|
||
import.meta.env.VITE_STREAM_URL
|
||
}/scheduled/${scheduledSessionId}?admin=true`}
|
||
target="_blank"
|
||
>
|
||
<Button>Начать</Button>
|
||
</Link>
|
||
) : (
|
||
manager.id === user.id && (
|
||
<Button
|
||
variant="secondary"
|
||
onClick={() => handleSelect(scheduledSessionId, null)}
|
||
>
|
||
Отменить
|
||
</Button>
|
||
)
|
||
)
|
||
) : (
|
||
<Button
|
||
variant="secondary"
|
||
onClick={() => handleSelect(scheduledSessionId, user.id)}
|
||
>
|
||
Выбрать
|
||
</Button>
|
||
))}
|
||
|
||
{user?.role === "admin" && (
|
||
<div className="flex gap-1">
|
||
{manager && (
|
||
<Link
|
||
to={`${
|
||
import.meta.env.VITE_STREAM_URL
|
||
}/scheduled/${scheduledSessionId}?admin=true`}
|
||
target="_blank"
|
||
>
|
||
<Button variant="secondary" icon={<EntryIcon />} onlyIcon />
|
||
</Link>
|
||
)}
|
||
<button
|
||
onClick={() => setIsShow(!isShow)}
|
||
className="p-1 text-[#77828C] hover:bg-neutral-100 rounded-lg"
|
||
>
|
||
<MoreIcon />
|
||
</button>
|
||
</div>
|
||
)}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="absolute z-10 pl-[calc(264px+8px)]">
|
||
{availableManagers && availableManagers.length > 0 && (
|
||
<SelectUser
|
||
shown={isShow}
|
||
selectedManagerId={manager?.id}
|
||
managers={availableManagers}
|
||
handleClick={(managerId) => (
|
||
handleSelect(scheduledSessionId, managerId), setIsShow(false)
|
||
)}
|
||
handleShown={() => setIsShow((prev) => !prev)}
|
||
/>
|
||
)}
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
export default Card;
|