From 24943999932e426506b5c76499f75b94e06bfaf5 Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Wed, 9 Jul 2025 13:12:28 -0400 Subject: [PATCH] feature/IO-3291-Tasks-Notifications: Checkpoint --- .../task-center/task-center.component.jsx | 108 ++++++++--------- .../task-center/task-center.styles.scss | 112 ++++++++---------- 2 files changed, 103 insertions(+), 117 deletions(-) diff --git a/client/src/components/task-center/task-center.component.jsx b/client/src/components/task-center/task-center.component.jsx index 0012c85f1..fcb361e50 100644 --- a/client/src/components/task-center/task-center.component.jsx +++ b/client/src/components/task-center/task-center.component.jsx @@ -4,6 +4,7 @@ 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"; const { Title } = Typography; @@ -11,6 +12,12 @@ const TaskCenterComponent = forwardRef(({ visible, tasks, loading, onTaskClick, 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"); @@ -20,8 +27,7 @@ const TaskCenterComponent = forwardRef(({ visible, tasks, loading, onTaskClick, 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: "header", label }, ...data.map((task) => ({ type: "task", task }))] : []; + const makeGroup = (label, data) => (data.length ? [{ type: "section", label, tasks: data }] : []); return [ ...makeGroup(t("tasks.labels.overdue"), overdue), @@ -31,63 +37,51 @@ const TaskCenterComponent = forwardRef(({ visible, tasks, loading, onTaskClick, ]; }, [tasks, t]); - const renderTask = (index, task) => { - const handleClick = () => onTaskClick(task.id); - - const getPriorityColor = (priority) => { - switch (priority) { - case 1: - return "red"; - case 2: - return "orange"; - case 3: - return "green"; - default: - return null; - } - }; - - const priorityColor = getPriorityColor(task.priority); - - return ( -
- -
-
- {task.title} - {task.due_date && ( - - {t("tasks.labels.due")}: {day(task.due_date).fromNow()} - - )} -
- - {/*{task.description &&
{task.description}
}*/} - -
- {t("notifications.labels.ro-number", { - ro_number: task.job?.ro_number || t("general.labels.na") - })} -
-
-
-
- ); - }; - const renderItem = (index, item) => { - if (item.type === "header") { - return ( -
- - {item.label} - -
- ); + const getPriorityColor = (priority) => { + switch (priority) { + case 1: + return "red"; + case 2: + return "orange"; + case 3: + return "green"; + default: + return null; } - - return renderTask(index, item.task); }; + const renderSection = (section, index) => ( +
+ + {sectionIcons[section.label]} + {section.label} + + + + {section.tasks.map((task) => { + const priorityColor = getPriorityColor(task.priority); + return ( + 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 && } +
+
+ ); + return (
@@ -99,7 +93,7 @@ const TaskCenterComponent = forwardRef(({ visible, tasks, loading, onTaskClick, ref={virtuosoRef} style={{ height: "400px", width: "100%" }} data={groupedItems} - itemContent={renderItem} + itemContent={(index, section) => renderSection(section, index)} /> {tasks.length < totalTasks && ( diff --git a/client/src/components/task-center/task-center.styles.scss b/client/src/components/task-center/task-center.styles.scss index 81c825f09..6ac4ef255 100644 --- a/client/src/components/task-center/task-center.styles.scss +++ b/client/src/components/task-center/task-center.styles.scss @@ -28,20 +28,19 @@ h3 { margin: 0; font-size: 13px; - color: rgba(0, 0, 0, 0.85); } } .task-section { - margin-bottom: 2px; + margin: 0; + padding: 0; } .section-title { padding: 3px 10px; - background: #f5f5f5; margin: 0; font-size: 12px; - color: rgba(0, 0, 0, 0.85); + background: #f5f5f5; font-weight: 500; border-bottom: 1px solid #e8e8e8; position: sticky; @@ -49,64 +48,52 @@ z-index: 1; } - .task-item { - padding: 6px 10px; - border-bottom: 1px solid #f0f0f0; - background: #fff; - cursor: pointer; - - &:hover { - background: #f5f5f5; - } - - .task-content { - display: flex; - flex-direction: column; - gap: 2px; - } - - .task-header-row { - display: flex; - justify-content: space-between; - align-items: center; - - .task-title { - font-size: 13px; - font-weight: 600; - color: rgba(0, 0, 0, 0.9); - margin-right: 6px; - flex: 1; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - - .task-due-date { - font-size: 11px; - color: rgba(0, 0, 0, 0.45); - white-space: nowrap; - } - } - - .task-description { - font-size: 12px; - color: rgba(0, 0, 0, 0.65); - } - - .task-ro-number { - font-size: 11px; - color: rgba(0, 0, 0, 0.45); - } - } - - .ant-badge { + .task-table { width: 100%; - .ant-badge-dot { - width: 6px; - height: 6px; - top: 2px; - right: 2px; + border-collapse: collapse; + + .task-row { + cursor: pointer; + border-bottom: 1px solid #f0f0f0; + + &:hover { + background: #f5f5f5; + } + + td { + padding: 6px 8px; + vertical-align: top; + font-size: 12px; + line-height: 1.2; + } + + .task-title-cell { + width: 100%; + max-width: 300px; // or whatever fits your layout + + .task-title { + font-weight: 500; + 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); + } + } + + .task-due-cell { + text-align: right; + white-space: nowrap; + color: rgba(0, 0, 0, 0.45); + } } } @@ -129,4 +116,9 @@ cursor: not-allowed; } } + + .ReactVirtuoso__item { + margin: 0 !important; + padding: 0 !important; + } }