167 lines
5.4 KiB
TypeScript
167 lines
5.4 KiB
TypeScript
import { type FC, useState } from "react";
|
|
import TaskDetailAttachmentPopover from "./attachment/TaskDetailAttachmentPopover";
|
|
import { DEFAULT_DATE_RANGE } from "./date/constants";
|
|
import TaskDetailDatePopover from "./date/TaskDetailDatePopover";
|
|
import type DateObject from "react-date-object";
|
|
import { DEFAULT_CHECKLISTS } from "./checklist/constants";
|
|
import TaskDetailChecklistPopover from "./checklist/TaskDetailChecklistPopover";
|
|
import type { TaskChecklist } from "./checklist/types";
|
|
import { DEFAULT_LABELS } from "./labels/constants";
|
|
import TaskDetailLabelsPopover from "./labels/TaskDetailLabelsPopover";
|
|
import type { LabelsView, TaskLabel } from "./labels/types";
|
|
import TaskDetailActionBar from "./TaskDetailActionBar";
|
|
import TaskDetailMetadataPreview from "./TaskDetailMetadataPreview";
|
|
import type { TaskDetailTab } from "./types";
|
|
import { DEFAULT_USERS } from "./users/constants";
|
|
import TaskDetailUsersPopover from "./users/TaskDetailUsersPopover";
|
|
|
|
type Props = {
|
|
activeTab: TaskDetailTab | null;
|
|
onTabChange: (tab: TaskDetailTab) => void;
|
|
};
|
|
|
|
const TaskDetailToolbar: FC<Props> = ({ activeTab, onTabChange }) => {
|
|
const [labelsView, setLabelsView] = useState<LabelsView>("list");
|
|
const [labels, setLabels] = useState<TaskLabel[]>(DEFAULT_LABELS);
|
|
const [selectedLabelIds, setSelectedLabelIds] = useState<Set<string>>(new Set(["1"]));
|
|
const [selectedUserIds, setSelectedUserIds] = useState<Set<string>>(new Set(["1"]));
|
|
const [checklists, setChecklists] = useState<TaskChecklist[]>(DEFAULT_CHECKLISTS);
|
|
const [startDate, setStartDate] = useState<DateObject | null>(DEFAULT_DATE_RANGE.startDate);
|
|
const [endDate, setEndDate] = useState<DateObject | null>(DEFAULT_DATE_RANGE.endDate);
|
|
|
|
const selectedLabels = labels.filter((label) => selectedLabelIds.has(label.id));
|
|
const selectedUsers = DEFAULT_USERS.filter((user) => selectedUserIds.has(user.id));
|
|
const isLabelsOpen = activeTab === "labels";
|
|
const isUsersOpen = activeTab === "users";
|
|
const isChecklistOpen = activeTab === "checklist";
|
|
const isAttachmentOpen = activeTab === "attachment";
|
|
const isDateOpen = activeTab === "date";
|
|
|
|
const handleTabChange = (tab: TaskDetailTab) => {
|
|
if (tab === "labels" && activeTab !== "labels") {
|
|
setLabelsView("list");
|
|
}
|
|
onTabChange(tab);
|
|
};
|
|
|
|
const handleLabelToggle = (id: string) => {
|
|
setSelectedLabelIds((prev) => {
|
|
const next = new Set(prev);
|
|
if (next.has(id)) {
|
|
next.delete(id);
|
|
} else {
|
|
next.add(id);
|
|
}
|
|
return next;
|
|
});
|
|
};
|
|
|
|
const handleUserToggle = (id: string) => {
|
|
setSelectedUserIds((prev) => {
|
|
const next = new Set(prev);
|
|
if (next.has(id)) {
|
|
next.delete(id);
|
|
} else {
|
|
next.add(id);
|
|
}
|
|
return next;
|
|
});
|
|
};
|
|
|
|
const handleCreate = (title: string, color: string) => {
|
|
const newLabel: TaskLabel = {
|
|
id: crypto.randomUUID(),
|
|
title,
|
|
color,
|
|
};
|
|
setLabels((prev) => [...prev, newLabel]);
|
|
setSelectedLabelIds((prev) => new Set([...prev, newLabel.id]));
|
|
setLabelsView("list");
|
|
};
|
|
|
|
const handleChecklistClose = () => {
|
|
if (isChecklistOpen) onTabChange("checklist");
|
|
};
|
|
|
|
const handleChecklistCreate = (title: string, _copyFromId: string) => {
|
|
const newChecklist: TaskChecklist = {
|
|
id: crypto.randomUUID(),
|
|
title,
|
|
};
|
|
setChecklists((prev) => [...prev, newChecklist]);
|
|
handleChecklistClose();
|
|
};
|
|
|
|
const handleAttachmentClose = () => {
|
|
if (isAttachmentOpen) onTabChange("attachment");
|
|
};
|
|
|
|
const handleAttachmentCreate = (_data: { file?: File; title: string; linkId: string }) => {
|
|
handleAttachmentClose();
|
|
};
|
|
|
|
const handleDateClose = () => {
|
|
if (isDateOpen) onTabChange("date");
|
|
};
|
|
|
|
const handleDateSubmit = (data: { startDate: DateObject | null; endDate: DateObject | null }) => {
|
|
setStartDate(data.startDate);
|
|
setEndDate(data.endDate);
|
|
handleDateClose();
|
|
};
|
|
|
|
return (
|
|
<div className="relative">
|
|
<TaskDetailActionBar
|
|
activeTab={activeTab}
|
|
onTabChange={handleTabChange}
|
|
labelsPopover={
|
|
isLabelsOpen ? (
|
|
<TaskDetailLabelsPopover
|
|
view={labelsView}
|
|
labels={labels}
|
|
selectedIds={selectedLabelIds}
|
|
onViewChange={setLabelsView}
|
|
onToggle={handleLabelToggle}
|
|
onCreate={handleCreate}
|
|
/>
|
|
) : null
|
|
}
|
|
usersPopover={
|
|
isUsersOpen ? (
|
|
<TaskDetailUsersPopover users={DEFAULT_USERS} selectedIds={selectedUserIds} onToggle={handleUserToggle} />
|
|
) : null
|
|
}
|
|
checklistPopover={
|
|
isChecklistOpen ? (
|
|
<TaskDetailChecklistPopover
|
|
checklists={checklists}
|
|
onClose={handleChecklistClose}
|
|
onSubmit={handleChecklistCreate}
|
|
/>
|
|
) : null
|
|
}
|
|
attachmentPopover={
|
|
isAttachmentOpen ? (
|
|
<TaskDetailAttachmentPopover onClose={handleAttachmentClose} onSubmit={handleAttachmentCreate} />
|
|
) : null
|
|
}
|
|
datePopover={
|
|
isDateOpen ? (
|
|
<TaskDetailDatePopover onClose={handleDateClose} onSubmit={handleDateSubmit} />
|
|
) : null
|
|
}
|
|
/>
|
|
|
|
<TaskDetailMetadataPreview
|
|
selectedLabels={selectedLabels}
|
|
selectedUsers={selectedUsers}
|
|
startDate={startDate}
|
|
endDate={endDate}
|
|
/>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default TaskDetailToolbar;
|