93 lines
3.0 KiB
TypeScript
93 lines
3.0 KiB
TypeScript
import { AttachCircle, Calendar, TickSquare } from "iconsax-react";
|
|
import { useEffect, useRef, type FC } from "react";
|
|
import { Link } from "react-router-dom";
|
|
import { useTranslation } from "react-i18next";
|
|
import { Pages } from "../../../config/Pages";
|
|
import type { Task as TaskType } from "../types";
|
|
import UserAvatar from "./UserAvatar";
|
|
|
|
type Props = {
|
|
task: TaskType;
|
|
isDragging?: boolean;
|
|
onClick?: (task: TaskType) => void;
|
|
};
|
|
|
|
const Task: FC<Props> = ({ task, isDragging, onClick }) => {
|
|
const { t } = useTranslation("global");
|
|
const suppressClickRef = useRef(false);
|
|
|
|
useEffect(() => {
|
|
if (isDragging) {
|
|
suppressClickRef.current = true;
|
|
}
|
|
}, [isDragging]);
|
|
|
|
const handleClick = () => {
|
|
if (suppressClickRef.current) {
|
|
suppressClickRef.current = false;
|
|
return;
|
|
}
|
|
onClick?.(task);
|
|
};
|
|
|
|
return (
|
|
<div
|
|
onClick={handleClick}
|
|
className={`bg-white rounded-lg p-2 w-full min-w-0 max-w-full overflow-hidden cursor-grab active:cursor-grabbing transition-opacity touch-manipulation ${
|
|
isDragging ? "opacity-40 shadow-lg" : ""
|
|
}`}
|
|
>
|
|
{task.color ? <div className="h-10 rounded-lg" style={{ backgroundColor: task.color }} /> : null}
|
|
{task.tag ? (
|
|
<div className="bg-[#FF76C2] h-5 px-3 flex items-center mt-2 text-[10px] text-white rounded-md w-fit max-w-full truncate">
|
|
{task.tag}
|
|
</div>
|
|
) : null}
|
|
<div className="font-bold text-xs mt-2 break-words">{task.title}</div>
|
|
{task.ticketId ? (
|
|
<Link
|
|
to={Pages.ticket.detail + task.ticketId}
|
|
onClick={(e) => e.stopPropagation()}
|
|
className="mt-2 inline-flex items-center text-[10px] text-primary hover:underline"
|
|
>
|
|
{t("taskmanager.task_detail.related_ticket")}
|
|
</Link>
|
|
) : null}
|
|
<div className="mt-2 flex flex-wrap items-center gap-x-3 gap-y-1.5 text-xs">
|
|
<div className="flex items-center gap-1 text-[10px] min-w-0">
|
|
<Calendar size={16} color="#292D32" className="shrink-0" />
|
|
<div className="truncate">{task.dateRange}</div>
|
|
</div>
|
|
|
|
<div className="flex gap-1 shrink-0">
|
|
<AttachCircle size={16} color="#292D32" />
|
|
<div>{task.attachments}</div>
|
|
</div>
|
|
<div className="flex gap-1 shrink-0">
|
|
<TickSquare size={16} color="#292D32" />
|
|
<div>
|
|
{task.checklistDone}/{task.checklistTotal}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{task.users?.length ? (
|
|
<div className="mt-2 flex justify-end pl-1.5">
|
|
<div className="flex items-center -space-x-1.5 rtl:space-x-reverse">
|
|
{task.users.map((user) => (
|
|
<UserAvatar
|
|
key={user.id}
|
|
src={user.profilePic}
|
|
alt={`${user.firstName} ${user.lastName}`}
|
|
className="size-6 ring-2 ring-white"
|
|
/>
|
|
))}
|
|
</div>
|
|
</div>
|
|
) : null}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default Task;
|