diff --git a/worklenz-frontend/public/locales/en/project-view-finance.json b/worklenz-frontend/public/locales/en/project-view-finance.json index 38121cdf..2c2d0325 100644 --- a/worklenz-frontend/public/locales/en/project-view-finance.json +++ b/worklenz-frontend/public/locales/en/project-view-finance.json @@ -32,7 +32,10 @@ "labourHoursColumn": "Labour Hours", "actions": "Actions", "selectJobTitle": "Select Job Title", - "ratecardsPluralText": "Rate Card Templates" + "ratecardsPluralText": "Rate Card Templates", + "deleteConfirm": "Are you sure ?", + "yes": "Yes", + "no": "No" } \ No newline at end of file diff --git a/worklenz-frontend/src/components/task-drawer/shared/info-tab/subtask-table.tsx b/worklenz-frontend/src/components/task-drawer/shared/info-tab/subtask-table.tsx index 5d63c177..45b48b96 100644 --- a/worklenz-frontend/src/components/task-drawer/shared/info-tab/subtask-table.tsx +++ b/worklenz-frontend/src/components/task-drawer/shared/info-tab/subtask-table.tsx @@ -166,9 +166,11 @@ const SubTaskTable = ({ subTasks, loadingSubTasks, refreshSubTasks, t }: SubTask { key: 'name', dataIndex: 'name', + title: 'Name', }, { key: 'priority', + title: 'Priority', render: (record: IProjectTask) => ( ( , }, { key: 'actionBtns', + title: 'Actions', width: 80, render: (record: IProjectTask) => ( @@ -230,7 +235,6 @@ const SubTaskTable = ({ subTasks, loadingSubTasks, refreshSubTasks, t }: SubTask {subTasks.length > 0 && ( record?.id || nanoid()} diff --git a/worklenz-frontend/src/features/finance/ratecard-drawer/ratecard-drawer.tsx b/worklenz-frontend/src/features/finance/ratecard-drawer/ratecard-drawer.tsx index 15a0d62a..2855cea0 100644 --- a/worklenz-frontend/src/features/finance/ratecard-drawer/ratecard-drawer.tsx +++ b/worklenz-frontend/src/features/finance/ratecard-drawer/ratecard-drawer.tsx @@ -1,4 +1,4 @@ -import { Drawer, Select, Typography, Flex, Button, Input, Table } from 'antd'; +import { Drawer, Select, Typography, Flex, Button, Input, Table, Popconfirm, Tooltip } from 'antd'; import React, { useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useAppSelector } from '../../../hooks/useAppSelector'; @@ -7,7 +7,8 @@ import { deleteRateCard, fetchRateCardById, fetchRateCards, toggleRatecardDrawer import { RatecardType, IJobType } from '@/types/project/ratecard.types'; import { IJobTitlesViewModel } from '@/types/job.types'; import { jobTitlesApiService } from '@/api/settings/job-titles/job-titles.api.service'; -import { DeleteOutlined } from '@ant-design/icons'; +import { DeleteOutlined, ExclamationCircleFilled } from '@ant-design/icons'; +import { colors } from '@/styles/colors'; interface PaginationType { current: number; @@ -220,7 +221,7 @@ const RatecardDrawer = ({ setAddingRowIndex(null); }} onBlur={() => { - if (roles[index].job_title_id === ""){ + if (roles[index].job_title_id === "") { handleDeleteRole(index); } setEditingRowIndex(null); @@ -244,7 +245,7 @@ const RatecardDrawer = ({ return ( setEditingRowIndex(index)} + // onClick={() => setEditingRowIndex(index)} > {record.jobtitle} @@ -259,6 +260,7 @@ const RatecardDrawer = ({ ( - + } > @@ -355,13 +371,13 @@ const RatecardDrawer = ({ pagination={false} footer={() => ( + type="dashed" + onClick={handleAddRole} + block + style={{ margin: 0, padding: 0 }} + > + {t('addRoleButton')} + )} /> diff --git a/worklenz-frontend/src/pages/projects/projectView/finance/ratecard-tab/reatecard-table/ratecard-table.tsx b/worklenz-frontend/src/pages/projects/projectView/finance/ratecard-tab/reatecard-table/ratecard-table.tsx index 2a92b505..410aa1ca 100644 --- a/worklenz-frontend/src/pages/projects/projectView/finance/ratecard-tab/reatecard-table/ratecard-table.tsx +++ b/worklenz-frontend/src/pages/projects/projectView/finance/ratecard-tab/reatecard-table/ratecard-table.tsx @@ -216,6 +216,7 @@ const RatecardTable: React.FC = () => { ((_, ref) => { }, tooltip: { callbacks: { - label: function(context: any) { + label: function (context: any) { const idx = context.dataIndex; const member = jsonData[idx]; const hours = member?.utilized_hours || '0.00'; - const percent = member?.utilization_percent || '0.00'; + const percent = parseFloat(member?.utilization_percent || '0.00'); const overUnder = member?.over_under_utilized_hours || '0.00'; + let status = ''; + let color = ''; + if (percent < 90) { + status = 'Under'; + } else if (percent <= 110) { + status = 'Optimal'; + } else { + status = 'Over'; + } return [ `${context.dataset.label}: ${hours} h`, `Utilization: ${percent}%`, - `Over/Under Utilized: ${overUnder} h` + `${status} Utilized: ${overUnder} h` ]; + }, + labelTextColor: function (context: any) { + const idx = context.dataIndex; + const member = jsonData[idx]; + const utilization = parseFloat(member?.utilization_percent || '0'); + if (utilization < 90) { + return '#FFB546'; + } else if (utilization >= 90 && utilization <= 110) { + return '#B2EF9A'; + } else { + return '#FE7173'; + } } } } @@ -145,7 +166,7 @@ const MembersTimeSheet = forwardRef((_, ref) => { const fetchChartData = async () => { try { setLoading(true); - + const selectedTeams = teams.filter(team => team.selected); const selectedProjects = filterProjects.filter(project => project.selected); const selectedCategories = categories.filter(category => category.selected); @@ -178,7 +199,7 @@ const MembersTimeSheet = forwardRef((_, ref) => { if (chartRef.current) { // Get the canvas element const canvas = chartRef.current.canvas; - + // Create a temporary canvas to draw with background const tempCanvas = document.createElement('canvas'); const tempCtx = tempCanvas.getContext('2d'); @@ -225,4 +246,4 @@ const MembersTimeSheet = forwardRef((_, ref) => { MembersTimeSheet.displayName = 'MembersTimeSheet'; -export default MembersTimeSheet; +export default MembersTimeSheet; \ No newline at end of file diff --git a/worklenz-frontend/src/pages/settings/ratecard/ratecard-settings.tsx b/worklenz-frontend/src/pages/settings/ratecard/ratecard-settings.tsx index 4e149e84..d236e91a 100644 --- a/worklenz-frontend/src/pages/settings/ratecard/ratecard-settings.tsx +++ b/worklenz-frontend/src/pages/settings/ratecard/ratecard-settings.tsx @@ -87,7 +87,7 @@ const RatecardSettings: React.FC = () => { useEffect(() => { fetchRateCards(); - }, [toggleRatecardDrawer]); + }, [toggleRatecardDrawer, dispatch]);