diff --git a/worklenz-frontend/public/locales/alb/home.json b/worklenz-frontend/public/locales/alb/home.json index 9dd14e4e..81821062 100644 --- a/worklenz-frontend/public/locales/alb/home.json +++ b/worklenz-frontend/public/locales/alb/home.json @@ -44,7 +44,9 @@ "refresh": "Rifresko", "recentActivity": "Aktiviteti i Fundit", "recentTasks": "Detyrat e Fundit", - "timeLoggedTasks": "Koha e Regjistruar", + "recentTasksSegment": "Detyrat e Fundit", + "timeLogged": "Koha e Regjistruar", + "timeLoggedSegment": "Koha e Regjistruar", "noRecentTasks": "Asnjë detyrë e fundit", "noTimeLoggedTasks": "Asnjë detyrë me kohë të regjistruar", "activityTag": "Aktiviteti", @@ -53,6 +55,8 @@ "activitySingular": "aktivitet", "activityPlural": "aktivitete", "recentTaskAriaLabel": "Detyrë e fundit:", - "timeLoggedTaskAriaLabel": "Detyrë me kohë të regjistruar:" + "timeLoggedTaskAriaLabel": "Detyrë me kohë të regjistruar:", + "errorLoadingRecentTasks": "Gabim në ngarkimin e detyrave të fundit", + "errorLoadingTimeLoggedTasks": "Gabim në ngarkimin e detyrave me kohë të regjistruar" } } diff --git a/worklenz-frontend/public/locales/de/home.json b/worklenz-frontend/public/locales/de/home.json index 03381614..bc9ff9ac 100644 --- a/worklenz-frontend/public/locales/de/home.json +++ b/worklenz-frontend/public/locales/de/home.json @@ -44,7 +44,9 @@ "refresh": "Aktualisieren", "recentActivity": "Aktuelle Aktivitäten", "recentTasks": "Aktuelle Aufgaben", - "timeLoggedTasks": "Erfasste Zeit", + "recentTasksSegment": "Aktuelle Aufgaben", + "timeLogged": "Erfasste Zeit", + "timeLoggedSegment": "Erfasste Zeit", "noRecentTasks": "Keine aktuellen Aufgaben", "noTimeLoggedTasks": "Keine Aufgaben mit erfasster Zeit", "activityTag": "Aktivität", @@ -53,6 +55,8 @@ "activitySingular": "Aktivität", "activityPlural": "Aktivitäten", "recentTaskAriaLabel": "Aktuelle Aufgabe:", - "timeLoggedTaskAriaLabel": "Aufgabe mit erfasster Zeit:" + "timeLoggedTaskAriaLabel": "Aufgabe mit erfasster Zeit:", + "errorLoadingRecentTasks": "Fehler beim Laden aktueller Aufgaben", + "errorLoadingTimeLoggedTasks": "Fehler beim Laden der Zeiterfassung" } } diff --git a/worklenz-frontend/public/locales/en/home.json b/worklenz-frontend/public/locales/en/home.json index 290316f0..cfd51310 100644 --- a/worklenz-frontend/public/locales/en/home.json +++ b/worklenz-frontend/public/locales/en/home.json @@ -44,7 +44,9 @@ "refresh": "Refresh", "recentActivity": "Recent Activity", "recentTasks": "Recent Tasks", - "timeLoggedTasks": "Time Logged", + "recentTasksSegment": "Recent Tasks", + "timeLogged": "Time Logged", + "timeLoggedSegment": "Time Logged", "noRecentTasks": "No recent tasks", "noTimeLoggedTasks": "No time logged tasks", "activityTag": "Activity", @@ -54,12 +56,7 @@ "activityPlural": "activities", "recentTaskAriaLabel": "Recent task:", "timeLoggedTaskAriaLabel": "Time logged task:", - "Recent Activity": "Recent Activity", - "Recent Tasks": "Recent Tasks", - "Time Logged Tasks": "Time Logged Tasks", - "Error Loading Recent Tasks": "Error loading recent tasks", - "Error Loading Time Logged Tasks": "Error loading time logged tasks", - "No Recent Tasks": "No recent tasks", - "No Time Logged Tasks": "No time logged tasks" + "errorLoadingRecentTasks": "Error loading recent tasks", + "errorLoadingTimeLoggedTasks": "Error loading time logged tasks" } } diff --git a/worklenz-frontend/public/locales/es/home.json b/worklenz-frontend/public/locales/es/home.json index 63403089..c2206148 100644 --- a/worklenz-frontend/public/locales/es/home.json +++ b/worklenz-frontend/public/locales/es/home.json @@ -43,7 +43,9 @@ "refresh": "Actualizar", "recentActivity": "Actividad Reciente", "recentTasks": "Tareas Recientes", - "timeLoggedTasks": "Tiempo Registrado", + "recentTasksSegment": "Tareas Recientes", + "timeLogged": "Tiempo Registrado", + "timeLoggedSegment": "Tiempo Registrado", "noRecentTasks": "No hay tareas recientes", "noTimeLoggedTasks": "No hay tareas con tiempo registrado", "activityTag": "Actividad", @@ -52,6 +54,8 @@ "activitySingular": "actividad", "activityPlural": "actividades", "recentTaskAriaLabel": "Tarea reciente:", - "timeLoggedTaskAriaLabel": "Tarea con tiempo registrado:" + "timeLoggedTaskAriaLabel": "Tarea con tiempo registrado:", + "errorLoadingRecentTasks": "Error al cargar tareas recientes", + "errorLoadingTimeLoggedTasks": "Error al cargar tareas con tiempo registrado" } } diff --git a/worklenz-frontend/public/locales/pt/home.json b/worklenz-frontend/public/locales/pt/home.json index 9a84464c..398f16c7 100644 --- a/worklenz-frontend/public/locales/pt/home.json +++ b/worklenz-frontend/public/locales/pt/home.json @@ -43,7 +43,9 @@ "refresh": "Atualizar", "recentActivity": "Atividade Recente", "recentTasks": "Tarefas Recentes", - "timeLoggedTasks": "Tempo Registrado", + "recentTasksSegment": "Tarefas Recentes", + "timeLogged": "Tempo Registrado", + "timeLoggedSegment": "Tempo Registrado", "noRecentTasks": "Nenhuma tarefa recente", "noTimeLoggedTasks": "Nenhuma tarefa com tempo registrado", "activityTag": "Atividade", @@ -52,6 +54,8 @@ "activitySingular": "atividade", "activityPlural": "atividades", "recentTaskAriaLabel": "Tarefa recente:", - "timeLoggedTaskAriaLabel": "Tarefa com tempo registrado:" + "timeLoggedTaskAriaLabel": "Tarefa com tempo registrado:", + "errorLoadingRecentTasks": "Erro ao carregar tarefas recentes", + "errorLoadingTimeLoggedTasks": "Erro ao carregar tarefas com tempo registrado" } } diff --git a/worklenz-frontend/public/locales/zh/home.json b/worklenz-frontend/public/locales/zh/home.json index c50e37ca..638e14f8 100644 --- a/worklenz-frontend/public/locales/zh/home.json +++ b/worklenz-frontend/public/locales/zh/home.json @@ -44,7 +44,9 @@ "refresh": "刷新", "recentActivity": "最近活动", "recentTasks": "最近任务", - "timeLoggedTasks": "时间记录", + "recentTasksSegment": "最近任务", + "timeLogged": "时间记录", + "timeLoggedSegment": "时间记录", "noRecentTasks": "没有最近任务", "noTimeLoggedTasks": "没有时间记录任务", "activityTag": "活动", @@ -53,6 +55,8 @@ "activitySingular": "活动", "activityPlural": "活动", "recentTaskAriaLabel": "最近任务:", - "timeLoggedTaskAriaLabel": "时间记录任务:" + "timeLoggedTaskAriaLabel": "时间记录任务:", + "errorLoadingRecentTasks": "加载最近任务时出错", + "errorLoadingTimeLoggedTasks": "加载时间记录任务时出错" } } \ No newline at end of file diff --git a/worklenz-frontend/src/features/home-page/user-activity.slice.ts b/worklenz-frontend/src/features/home-page/user-activity.slice.ts index bfe207f2..21bf5876 100644 --- a/worklenz-frontend/src/features/home-page/user-activity.slice.ts +++ b/worklenz-frontend/src/features/home-page/user-activity.slice.ts @@ -16,7 +16,7 @@ interface UserActivityState { } const initialState: UserActivityState = { - activeTab: ActivityFeedType.RECENT_TASKS, + activeTab: ActivityFeedType.TIME_LOGGED_TASKS, activities: [], loading: false, error: null, diff --git a/worklenz-frontend/src/pages/home/home-page.tsx b/worklenz-frontend/src/pages/home/home-page.tsx index 0e47a4b1..aba0890a 100644 --- a/worklenz-frontend/src/pages/home/home-page.tsx +++ b/worklenz-frontend/src/pages/home/home-page.tsx @@ -29,7 +29,9 @@ const SIDEBAR_MAX_WIDTH = 400; // Lazy load heavy components const TaskDrawer = React.lazy(() => import('@/components/task-drawer/task-drawer')); -const SurveyPromptModal = React.lazy(() => import('@/components/survey/SurveyPromptModal').then(m => ({ default: m.SurveyPromptModal }))); +const SurveyPromptModal = React.lazy(() => + import('@/components/survey/SurveyPromptModal').then(m => ({ default: m.SurveyPromptModal })) +); const HomePage = memo(() => { const dispatch = useAppDispatch(); @@ -109,18 +111,18 @@ const HomePage = memo(() => { - + + + + + - - - - - + diff --git a/worklenz-frontend/src/pages/home/todo-list/todo-list.tsx b/worklenz-frontend/src/pages/home/todo-list/todo-list.tsx index 28054667..d1ab980b 100644 --- a/worklenz-frontend/src/pages/home/todo-list/todo-list.tsx +++ b/worklenz-frontend/src/pages/home/todo-list/todo-list.tsx @@ -144,7 +144,7 @@ const TodoList = () => { -
+
{data?.body.length === 0 ? ( = React.memo(({ tasks }) const dispatch = useAppDispatch(); const { token } = theme.useToken(); - // Enhanced dark mode detection - const isDarkMode = useMemo(() => { - return token.colorBgContainer === '#1f1f1f' || - token.colorBgBase === '#141414' || - token.colorBgElevated === '#1f1f1f' || - document.documentElement.getAttribute('data-theme') === 'dark' || - document.body.classList.contains('dark'); - }, [token]); - const handleTaskClick = useCallback( (taskId: string, projectId: string) => { dispatch(setSelectedTaskId(taskId)); @@ -40,143 +31,63 @@ const TaskActivityList: React.FC = React.memo(({ tasks }) [dispatch] ); - // Enhanced styling with theme support - const listItemStyles = useMemo(() => ({ - padding: '16px 20px', - borderBottom: isDarkMode ? '1px solid #404040' : '1px solid #f0f2f5', - cursor: 'pointer', - transition: 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)', - borderRadius: '8px', - margin: '0 0 2px 0', - background: isDarkMode ? 'transparent' : 'transparent', - position: 'relative' as const, - overflow: 'hidden', - }), [isDarkMode]); - - const listItemHoverStyles = useMemo(() => ({ - background: isDarkMode - ? 'linear-gradient(135deg, #2a2a2a 0%, #353535 100%)' - : 'linear-gradient(135deg, #f8f9ff 0%, #f0f4ff 100%)', - borderColor: isDarkMode ? '#505050' : '#d1d9e6', - transform: 'translateY(-1px)', - boxShadow: isDarkMode - ? '0 4px 16px rgba(0, 0, 0, 0.3), 0 1px 4px rgba(0, 0, 0, 0.2)' - : '0 4px 16px rgba(24, 144, 255, 0.15), 0 1px 4px rgba(0, 0, 0, 0.1)', - }), [isDarkMode]); - - const iconStyles = useMemo(() => ({ - color: isDarkMode ? '#40a9ff' : '#1890ff', - fontSize: '16px', - padding: '8px', - borderRadius: '6px', - background: isDarkMode - ? 'linear-gradient(135deg, #1a2332 0%, #2a3441 100%)' - : 'linear-gradient(135deg, #e6f7ff 0%, #f0f8ff 100%)', - border: isDarkMode ? '1px solid #40a9ff20' : '1px solid #1890ff20', - display: 'flex', - alignItems: 'center', - justifyContent: 'center', - minWidth: '32px', - minHeight: '32px', - }), [isDarkMode]); - - const taskNameStyles = useMemo(() => ({ - color: isDarkMode ? '#ffffff' : '#1f2937', - fontSize: '15px', - fontWeight: 600, - lineHeight: '1.4', - }), [isDarkMode]); - - const tagStyles = useMemo(() => ({ - background: isDarkMode - ? 'linear-gradient(135deg, #1e40af 0%, #3b82f6 100%)' - : 'linear-gradient(135deg, #dbeafe 0%, #bfdbfe 100%)', - color: isDarkMode ? '#ffffff' : '#1e40af', - border: isDarkMode ? '1px solid #3b82f6' : '1px solid #93c5fd', - borderRadius: '6px', - fontSize: '11px', - fontWeight: 600, - padding: '2px 8px', - textTransform: 'uppercase' as const, - letterSpacing: '0.5px', - }), [isDarkMode]); - - const metaTextStyles = useMemo(() => ({ - color: isDarkMode ? '#9ca3af' : '#6b7280', - fontSize: '13px', - fontWeight: 500, - }), [isDarkMode]); - - const timeTextStyles = useMemo(() => ({ - color: isDarkMode ? '#8c8c8c' : '#9ca3af', - fontSize: '12px', - fontWeight: 400, - }), [isDarkMode]); - - const activityCountStyles = useMemo(() => ({ - color: isDarkMode ? '#10b981' : '#059669', - fontSize: '12px', - fontWeight: 600, - background: isDarkMode - ? 'linear-gradient(135deg, #064e3b20 0%, #065f4620 100%)' - : 'linear-gradient(135deg, #ecfdf5 0%, #d1fae5 100%)', - padding: '2px 6px', - borderRadius: '4px', - border: isDarkMode ? '1px solid #065f4640' : '1px solid #a7f3d040', - }), [isDarkMode]); - - return ( - ( - handleTaskClick(item.task_id, item.project_id)} - style={listItemStyles} - onMouseEnter={(e) => { - Object.assign(e.currentTarget.style, listItemHoverStyles); + const columns = [ + { + key: 'task', + render: (record: IUserRecentTask) => ( +
{ - Object.assign(e.currentTarget.style, listItemStyles); - }} - aria-label={`${t('recentTaskAriaLabel')} ${item.task_name}`} + onClick={() => handleTaskClick(record.task_id, record.project_id)} + aria-label={`${t('tasks.recentTaskAriaLabel')} ${record.task_name}`} > -
-
- +
+ +
+
+
+ + {record.task_name} +
-
-
- - {item.task_name} +
+ + {record.project_name} + + + + {fromNow(record.last_activity_at)} - - {t('activityTag')} - -
-
- - {item.project_name} - - - - {item.activity_count} {item.activity_count === 1 ? t('activitySingular') : t('activityPlural')} - - - - {moment(item.last_activity_at).fromNow()} - - - -
+
- - )} +
+ ), + }, + ]; + + return ( + ); }); diff --git a/worklenz-frontend/src/pages/home/user-activity-feed/time-logged-task-list.tsx b/worklenz-frontend/src/pages/home/user-activity-feed/time-logged-task-list.tsx index 0185c2c8..b436b72b 100644 --- a/worklenz-frontend/src/pages/home/user-activity-feed/time-logged-task-list.tsx +++ b/worklenz-frontend/src/pages/home/user-activity-feed/time-logged-task-list.tsx @@ -1,9 +1,9 @@ -import React, { useCallback, useMemo } from 'react'; -import { List, Typography, Tag, Tooltip, Space, theme } from 'antd'; -import { ClockCircleOutlined } from '@ant-design/icons'; -import moment from 'moment'; +import React, { useCallback } from 'react'; +import { Table, Typography, Tag, Tooltip, Space, theme } from '@/shared/antd-imports'; +import { ClockCircleOutlined } from '@/shared/antd-imports'; import { useTranslation } from 'react-i18next'; import { useAppDispatch } from '@/hooks/useAppDispatch'; +import { fromNow, formatDate } from '@/utils/dateUtils'; import { setSelectedTaskId, setShowTaskDrawer, @@ -22,15 +22,6 @@ const TimeLoggedTaskList: React.FC = React.memo(({ task const dispatch = useAppDispatch(); const { token } = theme.useToken(); - // Enhanced dark mode detection - const isDarkMode = useMemo(() => { - return token.colorBgContainer === '#1f1f1f' || - token.colorBgBase === '#141414' || - token.colorBgElevated === '#1f1f1f' || - document.documentElement.getAttribute('data-theme') === 'dark' || - document.body.classList.contains('dark'); - }, [token]); - const handleTaskClick = useCallback( (taskId: string, projectId: string) => { dispatch(setSelectedTaskId(taskId)); @@ -40,160 +31,134 @@ const TimeLoggedTaskList: React.FC = React.memo(({ task [dispatch] ); - // Enhanced styling with theme support - const listItemStyles = useMemo(() => ({ - padding: '16px 20px', - borderBottom: isDarkMode ? '1px solid #404040' : '1px solid #f0f2f5', - cursor: 'pointer', - transition: 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)', - borderRadius: '8px', - margin: '0 0 2px 0', - background: isDarkMode ? 'transparent' : 'transparent', - position: 'relative' as const, - overflow: 'hidden', - }), [isDarkMode]); - - const listItemHoverStyles = useMemo(() => ({ - background: isDarkMode - ? 'linear-gradient(135deg, #2a2a2a 0%, #353535 100%)' - : 'linear-gradient(135deg, #f6ffed 0%, #f0fff4 100%)', - borderColor: isDarkMode ? '#505050' : '#b7eb8f', - transform: 'translateY(-1px)', - boxShadow: isDarkMode - ? '0 4px 16px rgba(0, 0, 0, 0.3), 0 1px 4px rgba(0, 0, 0, 0.2)' - : '0 4px 16px rgba(82, 196, 26, 0.15), 0 1px 4px rgba(0, 0, 0, 0.1)', - }), [isDarkMode]); - - const iconStyles = useMemo(() => ({ - color: isDarkMode ? '#73d13d' : '#52c41a', - fontSize: '16px', - padding: '8px', - borderRadius: '6px', - background: isDarkMode - ? 'linear-gradient(135deg, #1b2918 0%, #273622 100%)' - : 'linear-gradient(135deg, #f6ffed 0%, #f0fff4 100%)', - border: isDarkMode ? '1px solid #52c41a20' : '1px solid #52c41a20', - display: 'flex', - alignItems: 'center', - justifyContent: 'center', - minWidth: '32px', - minHeight: '32px', - }), [isDarkMode]); - - const taskNameStyles = useMemo(() => ({ - color: isDarkMode ? '#ffffff' : '#1f2937', - fontSize: '15px', - fontWeight: 600, - lineHeight: '1.4', - }), [isDarkMode]); - - const timeLogTagStyles = useMemo(() => ({ - background: isDarkMode - ? 'linear-gradient(135deg, #365314 0%, #4d7c0f 100%)' - : 'linear-gradient(135deg, #f0fff4 0%, #d9f7be 100%)', - color: isDarkMode ? '#ffffff' : '#365314', - border: isDarkMode ? '1px solid #4d7c0f' : '1px solid #95de64', - borderRadius: '6px', - fontSize: '11px', - fontWeight: 600, - padding: '2px 8px', - textTransform: 'uppercase' as const, - letterSpacing: '0.5px', - }), [isDarkMode]); - - const timerTagStyles = useMemo(() => ({ - background: isDarkMode - ? 'linear-gradient(135deg, #0f766e 0%, #14b8a6 100%)' - : 'linear-gradient(135deg, #f0fdfa 0%, #ccfbf1 100%)', - color: isDarkMode ? '#ffffff' : '#0f766e', - border: isDarkMode ? '1px solid #14b8a6' : '1px solid #5eead4', - borderRadius: '6px', - fontSize: '10px', - fontWeight: 600, - padding: '1px 6px', - }), [isDarkMode]); - - const metaTextStyles = useMemo(() => ({ - color: isDarkMode ? '#9ca3af' : '#6b7280', - fontSize: '13px', - fontWeight: 500, - }), [isDarkMode]); - - const timeTextStyles = useMemo(() => ({ - color: isDarkMode ? '#8c8c8c' : '#9ca3af', - fontSize: '12px', - fontWeight: 400, - }), [isDarkMode]); - - const timeLoggedStyles = useMemo(() => ({ - color: isDarkMode ? '#73d13d' : '#52c41a', - fontSize: '13px', - fontWeight: 700, - background: isDarkMode - ? 'linear-gradient(135deg, #1b291820 0%, #27362220 100%)' - : 'linear-gradient(135deg, #f6ffed 0%, #f0fff4 100%)', - padding: '4px 8px', - borderRadius: '6px', - border: isDarkMode ? '1px solid #52c41a40' : '1px solid #b7eb8f40', - }), [isDarkMode]); + const columns = [ + { + key: 'task', + render: (record: IUserTimeLoggedTask) => ( +
handleTaskClick(record.task_id, record.project_id)} + aria-label={`${t('tasks.timeLoggedTaskAriaLabel')} ${record.task_name}`} + > + {/* Clock Icon */} +
+ +
+ + {/* Main Content */} +
+ {/* Task Name */} +
+ + {record.task_name} + +
+ + {/* Project Name */} + + {record.project_name} + +
+ + {/* Right Side - Time and Status */} +
+ {/* Time Logged */} +
+ + {record.total_time_logged_string} + + {record.logged_by_timer && ( + + {t('tasks.timerTag')} + + )} +
+ + {/* Time Ago */} + + + {fromNow(record.last_logged_at)} + + +
+
+ ), + }, + ]; return ( - ( - handleTaskClick(item.task_id, item.project_id)} - style={listItemStyles} - onMouseEnter={(e) => { - Object.assign(e.currentTarget.style, listItemHoverStyles); - }} - onMouseLeave={(e) => { - Object.assign(e.currentTarget.style, listItemStyles); - }} - aria-label={`${t('timeLoggedTaskAriaLabel')} ${item.task_name}`} - > -
-
- -
-
-
- - {item.task_name} - - - {t('timeLogTag')} - -
-
- - {item.project_name} - - - - {item.total_time_logged_string} - - {item.logged_by_timer && ( - - {t('timerTag')} - - )} - - - {moment(item.last_logged_at).fromNow()} - - - -
-
-
-
- )} + columns={columns} + rowKey="task_id" + showHeader={false} + pagination={false} + size="small" /> ); }); diff --git a/worklenz-frontend/src/pages/home/user-activity-feed/user-activity-feed.tsx b/worklenz-frontend/src/pages/home/user-activity-feed/user-activity-feed.tsx index fa014202..b0b57ded 100644 --- a/worklenz-frontend/src/pages/home/user-activity-feed/user-activity-feed.tsx +++ b/worklenz-frontend/src/pages/home/user-activity-feed/user-activity-feed.tsx @@ -1,6 +1,6 @@ import React, { useMemo, useCallback, useEffect } from 'react'; -import { Card, Segmented, Skeleton, Empty, Typography, Alert } from 'antd'; -import { ClockCircleOutlined, UnorderedListOutlined } from '@ant-design/icons'; +import { Card, Segmented, Skeleton, Empty, Typography, Alert, Button, Tooltip } from '@/shared/antd-imports'; +import { ClockCircleOutlined, UnorderedListOutlined, SyncOutlined } from '@/shared/antd-imports'; import { useTranslation } from 'react-i18next'; import { useAppSelector } from '@/hooks/useAppSelector'; import { useAppDispatch } from '@/hooks/useAppDispatch'; @@ -54,11 +54,12 @@ const UserActivityFeed: React.FC = () => { } // If it's an object with a data property (common API pattern) if (recentTasksData && typeof recentTasksData === 'object' && 'data' in recentTasksData) { - return Array.isArray(recentTasksData.data) ? recentTasksData.data : []; + const data = (recentTasksData as any).data; + return Array.isArray(data) ? data : []; } // If it's a different object structure, try to extract tasks if (recentTasksData && typeof recentTasksData === 'object') { - const possibleArrays = Object.values(recentTasksData).filter(Array.isArray); + const possibleArrays = Object.values(recentTasksData as any).filter(Array.isArray); return possibleArrays.length > 0 ? possibleArrays[0] : []; } return []; @@ -72,11 +73,12 @@ const UserActivityFeed: React.FC = () => { } // If it's an object with a data property (common API pattern) if (timeLoggedTasksData && typeof timeLoggedTasksData === 'object' && 'data' in timeLoggedTasksData) { - return Array.isArray(timeLoggedTasksData.data) ? timeLoggedTasksData.data : []; + const data = (timeLoggedTasksData as any).data; + return Array.isArray(data) ? data : []; } // If it's a different object structure, try to extract tasks if (timeLoggedTasksData && typeof timeLoggedTasksData === 'object') { - const possibleArrays = Object.values(timeLoggedTasksData).filter(Array.isArray); + const possibleArrays = Object.values(timeLoggedTasksData as any).filter(Array.isArray); return possibleArrays.length > 0 ? possibleArrays[0] : []; } return []; @@ -85,21 +87,21 @@ const UserActivityFeed: React.FC = () => { const segmentOptions = useMemo( () => [ { - value: ActivityFeedType.RECENT_TASKS, + value: ActivityFeedType.TIME_LOGGED_TASKS, label: ( -
- - {t('Recent Tasks')} -
+ + + {t('tasks.timeLoggedSegment')} + ), }, { - value: ActivityFeedType.TIME_LOGGED_TASKS, + value: ActivityFeedType.RECENT_TASKS, label: ( -
- - {t('Time Logged Tasks')} -
+ + + {t('tasks.recentTasksSegment')} + ), }, ], @@ -122,41 +124,77 @@ const UserActivityFeed: React.FC = () => { } }, [activeTab, refetchRecentTasks, refetchTimeLoggedTasks]); - const renderContent = () => { - if (activeTab === ActivityFeedType.RECENT_TASKS) { - if (loadingRecentTasks) { - return ; - } - if (recentTasksError) { - return ; - } - if (recentTasks.length === 0) { - return ; - } - return ; + const handleRefresh = useCallback(() => { + if (activeTab === ActivityFeedType.TIME_LOGGED_TASKS) { + refetchTimeLoggedTasks(); } else { + refetchRecentTasks(); + } + }, [activeTab, refetchRecentTasks, refetchTimeLoggedTasks]); + + const isLoading = activeTab === ActivityFeedType.TIME_LOGGED_TASKS ? loadingTimeLoggedTasks : loadingRecentTasks; + const currentCount = activeTab === ActivityFeedType.TIME_LOGGED_TASKS ? timeLoggedTasks.length : recentTasks.length; + + const renderContent = () => { + if (activeTab === ActivityFeedType.TIME_LOGGED_TASKS) { if (loadingTimeLoggedTasks) { return ; } if (timeLoggedTasksError) { - return ; + return ; } if (timeLoggedTasks.length === 0) { - return ; + return ; } - return ; + return ( +
+ +
+ ); + } else if (activeTab === ActivityFeedType.RECENT_TASKS) { + if (loadingRecentTasks) { + return ; + } + if (recentTasksError) { + return ; + } + if (recentTasks.length === 0) { + return ; + } + return ( +
+ +
+ ); } + return null; }; return ( - -
- -
+ + {t('tasks.recentActivity')} ({currentCount}) + + } + extra={ + +