detail modal task

This commit is contained in:
hamid zarghami
2026-06-16 16:31:49 +03:30
parent 8518662eee
commit c6559b3054
9 changed files with 194 additions and 5 deletions
@@ -0,0 +1,49 @@
import { Calendar, Paperclip2, Profile2User, Tag, TickSquare, type Icon } from "iconsax-react";
import { type FC } from "react";
import { useTranslation } from "react-i18next";
import type { TaskDetailTab } from "./types";
type TabItem = {
id: TaskDetailTab;
icon: Icon;
labelKey: string;
};
const TABS: TabItem[] = [
{ id: "labels", icon: Tag, labelKey: "taskmanager.task_detail.labels" },
{ id: "users", icon: Profile2User, labelKey: "taskmanager.task_detail.user_management" },
{ id: "checklist", icon: TickSquare, labelKey: "taskmanager.task_detail.checklist" },
{ id: "attachment", icon: Paperclip2, labelKey: "taskmanager.task_detail.attachment" },
{ id: "date", icon: Calendar, labelKey: "taskmanager.task_detail.date_settings" },
];
type Props = {
activeTab: TaskDetailTab | null;
onTabChange: (tab: TaskDetailTab) => void;
};
const TaskDetailActionBar: FC<Props> = ({ activeTab, onTabChange }) => {
const { t } = useTranslation("global");
return (
<div className="flex flex-wrap items-center gap-2">
{TABS.map(({ id, icon: Icon, labelKey }) => {
const isActive = activeTab === id;
return (
<button
key={id}
type="button"
onClick={() => onTabChange(id)}
className={`flex items-center gap-1.5 border border-white rounded-lg px-3 py-2 text-[11px] cursor-pointer transition-colors ${isActive ? "bg-white text-black" : "bg-white/50 text-[#292D32]"}`}
>
<Icon size={16} color="#292D32" />
<span>{t(labelKey)}</span>
</button>
);
})}
</div>
);
};
export default TaskDetailActionBar;
@@ -0,0 +1,26 @@
import { type FC } from "react";
import { useTranslation } from "react-i18next";
type Props = {
value?: string;
onChange?: (value: string) => void;
};
const TaskDetailDescription: FC<Props> = ({ value = "", onChange }) => {
const { t } = useTranslation("global");
return (
<div className="mt-6">
<div className="text-sm font-medium mb-2">{t("taskmanager.task_detail.description")}</div>
<textarea
value={value}
onChange={(e) => onChange?.(e.target.value)}
placeholder={t("taskmanager.task_detail.description_placeholder")}
rows={5}
className="w-full bg-white/25 rounded-xl px-4 py-3 text-xs outline-none resize-none placeholder:text-description"
/>
</div>
);
};
export default TaskDetailDescription;
@@ -0,0 +1,26 @@
import { ArrowDown2, CloseCircle } from "iconsax-react";
import { type FC } from "react";
type Props = {
statusLabel: string;
onClose: () => void;
};
const TaskDetailHeader: FC<Props> = ({ statusLabel, onClose }) => {
return (
<div className="flex items-center justify-between border-b border-border pb-4">
<button type="button" className="flex items-center gap-1.5 bg-white/60 rounded-full px-4 py-2 text-xs font-medium cursor-pointer">
<span>{statusLabel}</span>
<ArrowDown2 size={14} color="#292D32" />
</button>
<div className="flex items-center gap-2">
<button type="button" onClick={onClose} className="size-8 rounded-full bg-white/60 flex items-center justify-center cursor-pointer" aria-label="بستن">
<CloseCircle size={20} color="#292D32" />
</button>
</div>
</div>
);
};
export default TaskDetailHeader;
@@ -0,0 +1,44 @@
import { type FC, useEffect, useState } from "react";
import DefaulModal from "../../../../components/DefaulModal";
import type { Task } from "../../types";
import TaskDetailActionBar from "./TaskDetailActionBar";
import TaskDetailDescription from "./TaskDetailDescription";
import TaskDetailHeader from "./TaskDetailHeader";
import type { TaskDetailTab } from "./types";
type Props = {
open: boolean;
task: Task | null;
statusLabel: string;
onClose: () => void;
};
const TaskDetailModal: FC<Props> = ({ open, task, statusLabel, onClose }) => {
const [activeTab, setActiveTab] = useState<TaskDetailTab | null>(null);
const [description, setDescription] = useState("");
useEffect(() => {
if (!open) {
setActiveTab(null);
setDescription("");
}
}, [open]);
if (!task) return null;
return (
<DefaulModal open={open} close={onClose} width={680}>
<TaskDetailHeader statusLabel={statusLabel} onClose={onClose} />
<h2 className="mt-6 text-sm font-bold">{task.title}</h2>
<div className="mt-4">
<TaskDetailActionBar activeTab={activeTab} onTabChange={setActiveTab} />
</div>
<TaskDetailDescription value={description} onChange={setDescription} />
</DefaulModal>
);
};
export default TaskDetailModal;
@@ -0,0 +1 @@
export type TaskDetailTab = "labels" | "users" | "checklist" | "attachment" | "date";