diff --git a/client/src/components/task-center/task-center.component.jsx b/client/src/components/task-center/task-center.component.jsx index fcb361e50..e1e39771b 100644 --- a/client/src/components/task-center/task-center.component.jsx +++ b/client/src/components/task-center/task-center.component.jsx @@ -1,109 +1,131 @@ import { Virtuoso } from "react-virtuoso"; -import { Badge, Spin, Typography } from "antd"; +import { Badge, Button, Spin, Tooltip, Typography } from "antd"; import { useTranslation } from "react-i18next"; import { forwardRef, useMemo, useRef } from "react"; import day from "../../utils/day.js"; import "./task-center.styles.scss"; -import { ArrowRightOutlined, CalendarOutlined, ClockCircleOutlined, QuestionCircleOutlined } from "@ant-design/icons"; +import { + ArrowRightOutlined, + CalendarOutlined, + ClockCircleOutlined, + PlusCircleOutlined, + QuestionCircleOutlined +} from "@ant-design/icons"; const { Title } = Typography; -const TaskCenterComponent = forwardRef(({ visible, tasks, loading, onTaskClick, onLoadMore, totalTasks }, ref) => { - const { t } = useTranslation(); - const virtuosoRef = useRef(null); +const TaskCenterComponent = forwardRef( + ({ visible, tasks, loading, onTaskClick, onLoadMore, totalTasks, createNewTask }, ref) => { + const { t } = useTranslation(); + const virtuosoRef = useRef(null); - const sectionIcons = { - [t("tasks.labels.overdue")]: , - [t("tasks.labels.due_today")]: , - [t("tasks.labels.upcoming")]: , - [t("tasks.labels.no_due_date")]: - }; - const groupedItems = useMemo(() => { - const now = day(); - const today = now.startOf("day"); + const sectionIcons = { + [t("tasks.labels.overdue")]: , + [t("tasks.labels.due_today")]: , + [t("tasks.labels.upcoming")]: , + [t("tasks.labels.no_due_date")]: + }; + const groupedItems = useMemo(() => { + const now = day(); + const today = now.startOf("day"); - const overdue = tasks.filter((t) => t.due_date && day(t.due_date).isBefore(today)); - const dueToday = tasks.filter((t) => t.due_date && day(t.due_date).isSame(today, "day")); - const upcoming = tasks.filter((t) => t.due_date && day(t.due_date).isAfter(today)); - const noDueDate = tasks.filter((t) => !t.due_date); + const overdue = tasks.filter((t) => t.due_date && day(t.due_date).isBefore(today)); + const dueToday = tasks.filter((t) => t.due_date && day(t.due_date).isSame(today, "day")); + const upcoming = tasks.filter((t) => t.due_date && day(t.due_date).isAfter(today)); + const noDueDate = tasks.filter((t) => !t.due_date); - const makeGroup = (label, data) => (data.length ? [{ type: "section", label, tasks: data }] : []); + const makeGroup = (label, data) => (data.length ? [{ type: "section", label, tasks: data }] : []); - return [ - ...makeGroup(t("tasks.labels.overdue"), overdue), - ...makeGroup(t("tasks.labels.due_today"), dueToday), - ...makeGroup(t("tasks.labels.upcoming"), upcoming), - ...makeGroup(t("tasks.labels.no_due_date"), noDueDate) - ]; - }, [tasks, t]); + return [ + ...makeGroup(t("tasks.labels.overdue"), overdue), + ...makeGroup(t("tasks.labels.due_today"), dueToday), + ...makeGroup(t("tasks.labels.upcoming"), upcoming), + ...makeGroup(t("tasks.labels.no_due_date"), noDueDate) + ]; + }, [tasks, t]); - const getPriorityColor = (priority) => { - switch (priority) { - case 1: - return "red"; - case 2: - return "orange"; - case 3: - return "green"; - default: - return null; - } - }; + const getPriorityColor = (priority) => { + switch (priority) { + case 1: + return "red"; + case 2: + return "orange"; + case 3: + return "green"; + default: + return null; + } + }; - const renderSection = (section, index) => ( -
- - {sectionIcons[section.label]} - {section.label} - - - - {section.tasks.map((task) => { - const priorityColor = getPriorityColor(task.priority); - return ( - onTaskClick(task.id)}> - + ); - return ( -
-
-

{t("tasks.labels.my_tasks_center")}

- {loading && } + return task.description ? ( + + {rowContent} + + ) : ( + rowContent + ); + })} +
+
-
{task.title}
-
- {t("notifications.labels.ro-number", { - ro_number: task.job?.ro_number || t("general.labels.na") - })} + const renderSection = (section, index) => ( +
+
+ {sectionIcons[section.label]} + {section.label} +
+ + + {section.tasks.map((task) => { + const priorityColor = getPriorityColor(task.priority); + const rowContent = ( + onTaskClick(task.id)}> +
+
+ - - - - ); - })} - -
+
{task.title}
+
+ {t("notifications.labels.ro-number", { + ro_number: task.job?.ro_number || t("general.labels.na") + })} +
+
+ {task.due_date && {day(task.due_date).fromNow()}} + {!!priorityColor && } + - {task.due_date && {day(task.due_date).fromNow()}} - {!!priorityColor && } -
-
- ); +
+ ); - renderSection(section, index)} - /> + return ( +
+
+

{t("tasks.labels.my_tasks_center")}

+
+ - )} -
- ); -}); + {loading && } +
+
+ + renderSection(section, index)} + /> + + {tasks.length < totalTasks && ( + + )} + + ); + } +); TaskCenterComponent.displayName = "TaskCenterComponent"; export default TaskCenterComponent; diff --git a/client/src/components/task-center/task-center.container.jsx b/client/src/components/task-center/task-center.container.jsx index 2f1b38b00..4237aab34 100644 --- a/client/src/components/task-center/task-center.container.jsx +++ b/client/src/components/task-center/task-center.container.jsx @@ -78,6 +78,10 @@ const TaskCenterContainer = ({ visible, onClose, bodyshop, currentUser, setTaskU [tasks, setTaskUpsertContext] ); + const createNewTask = () => { + setTaskUpsertContext({ actions: {}, context: {} }); + }; + return ( ); }; diff --git a/client/src/components/task-center/task-center.styles.scss b/client/src/components/task-center/task-center.styles.scss index 6ac4ef255..b19f7148e 100644 --- a/client/src/components/task-center/task-center.styles.scss +++ b/client/src/components/task-center/task-center.styles.scss @@ -2,8 +2,8 @@ position: absolute; top: 64px; right: 0; - width: 400px; - max-width: 400px; + width: 500px; + max-width: 500px; background: #fff; color: rgba(0, 0, 0, 0.85); border: 1px solid #d9d9d9; @@ -26,8 +26,21 @@ background: #fafafa; h3 { + font-size: 14px; margin: 0; - font-size: 13px; + } + + .create-task-button { + border: none; + color: white; + padding: 4px 12px; + border-radius: 4px; + cursor: pointer; + font-weight: 500; + + &:hover { + background-color: #40a9ff; + } } } @@ -39,15 +52,20 @@ .section-title { padding: 3px 10px; margin: 0; - font-size: 12px; + //font-size: 12px; background: #f5f5f5; - font-weight: 500; + font-weight: 650; border-bottom: 1px solid #e8e8e8; position: sticky; top: 0; z-index: 1; } + .task-row-container { + margin-top: 15px; + margin-bottom: 15px; + } + .task-table { width: 100%; @@ -64,28 +82,29 @@ td { padding: 6px 8px; vertical-align: top; - font-size: 12px; + //font-size: 12px; line-height: 1.2; } .task-title-cell { width: 100%; - max-width: 300px; // or whatever fits your layout + max-width: 350px; // or whatever fits your layout .task-title { - font-weight: 500; + font-size: 16px; + font-weight: 550; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; // Or a specific width if you want more control display: inline-block; vertical-align: middle; + } .task-ro-number { - margin-top: 5px; - font-size: 11px; - color: rgba(0, 0, 0, 0.45); + margin-top: 20px; + color: #1677ff; } } @@ -104,7 +123,7 @@ color: white; border: none; border-radius: 4px; - font-size: 12px; + //font-size: 12px; cursor: pointer; &:hover {