diff --git a/src/components/Reports/PeopleTableDetails.jsx b/src/components/Reports/PeopleTableDetails.jsx index 17d29ea540..508513c8fe 100644 --- a/src/components/Reports/PeopleTableDetails.jsx +++ b/src/components/Reports/PeopleTableDetails.jsx @@ -4,6 +4,12 @@ import { useTable } from 'react-table'; import styles from './PeopleTableDetails.module.css'; import TableFilter from './TableFilter/TableFilter'; +/** + * TaskResourceCell Component + * Renders the primary profile pictures for assigned resources (up to 2), + * a collapse/expand toggle button for additional resources, and a hidden/visible + * container for extra resources when expanded. + */ export function TaskResourceCell({ row, column, @@ -57,6 +63,10 @@ export function TaskResourceCell({ ); } +/** + * YesNoCell Component + * Renders a centered checkmark for 'Yes' values or a cross mark otherwise. + */ export function YesNoCell({ value }) { return (
@@ -65,11 +75,21 @@ export function YesNoCell({ value }) { ); } +/** + * CenteredValueCell Component + * Renders any standard text value centered within its table cell. + */ export function CenteredValueCell({ value }) { return
{value}
; } +/** + * PeopleTableDetails Main Component + * Manages filtering states, table data configuration using react-table, + * desktop table layout, and responsive mobile card view. + */ function PeopleTableDetails(props) { + // Filter search states const [name, setName] = useState(''); const [priority, setPriority] = useState(''); const [status, setStatus] = useState(''); @@ -140,7 +160,6 @@ function PeopleTableDetails(props) { return filteredList; }; - // REFACTORED: Toggle using state instead of direct DOM manipulation const toggleMoreResources = useCallback((id) => { setExpandedTasks((prev) => ({ ...prev, @@ -244,6 +263,7 @@ function PeopleTableDetails(props) { Clear Filters
+
@@ -283,8 +303,53 @@ function PeopleTableDetails(props) {
+ +
+ {filteredTasks.map((task) => ( +
+
+ {task.taskName} + {task.status || 'Started'} +
+
+
+
Priority
+
{task.priority}
+
+
+
Resources
+
+ {(task.resources || []).flat().map((res, i) => ( + {res.name} + ))} +
+
+
+
Active
+
{task.active}
+
+
+
Assign
+
{task.assign}
+
+
+
Estimated Hours
+
{task.estimatedHours}
+
+
+
Start Date
+
{task.startDate}
+
+
+
End Date
+
{task.endDate}
+
+
+
+ ))} +
); } -export default PeopleTableDetails; +export default PeopleTableDetails; \ No newline at end of file diff --git a/src/components/Reports/PeopleTableDetails.module.css b/src/components/Reports/PeopleTableDetails.module.css index 2a293a9ed9..db2024613b 100644 --- a/src/components/Reports/PeopleTableDetails.module.css +++ b/src/components/Reports/PeopleTableDetails.module.css @@ -1,4 +1,3 @@ -/* stylelint-disable declaration-property-value-no-unknown, no-descending-specificity */ .wrapper { overflow-x: auto; width: 100%; @@ -55,7 +54,6 @@ overflow: hidden; } -/* Profile picture styling */ .img-circle { border-radius: 50%; height: 30px; @@ -95,11 +93,16 @@ color: #f1f1f1; } +.people-table-row-dark { + background-color: transparent !important; + color: #fff !important; + border-bottom: 1px solid #444 !important; +} + .people-table-row:hover { background-color: #fafafa; } -/* ✅ merged hover style */ .people-table-row-dark:hover { background-color: #232946 !important; color: #fff !important; @@ -153,7 +156,7 @@ .extra { display: none; - border: collapse; + border: none; } .extra1 { @@ -173,32 +176,54 @@ } .task-card-dark { - color: black; + color: #fff; + background-color: #232946; + border: 1px solid #444; } .task-header { background-color: #eee7f8; display: flex; justify-content: space-between; + align-items: flex-start; + gap: 10px; padding: 15px; border-top-left-radius: 10px; border-top-right-radius: 10px; - align-items: flex-start; +} + +.task-card-dark .task-header { + background-color: #1a1a2e; + color: #fff; } .task-status { display: flex; align-items: center; - padding: 5px 10px; + justify-content: center; + padding: 4px 10px; border-radius: 20px; background-color: #ffc107; color: #fff; - width: fit-content; - margin-left: 5px; + flex-shrink: 0; + white-space: nowrap; + margin-left: 0; +} + +.task-card-dark .task-status { + background-color: #ca50db; + color: #fff; } .task-info { display: flex; + padding: 6px 0; + border-bottom: 1px solid #f2f2f2; +} + +.task-card-dark .task-info { + border-bottom: 1px solid #374151; + color: #fff; } .sub-head { @@ -206,12 +231,22 @@ text-align: end; width: 50%; padding-right: 2%; + color: #4b5563; +} + +.task-card-dark .sub-head { + color: #9ca3af; } .sub-details { text-align: start; width: 50%; padding-left: 2%; + color: #1f2937; +} + +.task-card-dark .sub-details { + color: #fff; } .table-filter-container { @@ -249,74 +284,39 @@ color: #e7b1ef; } -/* Dark mode styling for Clear Filters button */ -.wrapperDark .tasks-table-clear-filter-button { - background-color: #232946 !important; - border: 2px solid #5A67D8 !important; - color: #fff !important; -} - -.wrapperDark .tasks-table-clear-filter-button:hover { - background-color: #1C2541 !important; - border-color: #ca50db !important; -} - .people-report-task-name { - overflow-wrap: break-word; - min-width: 200px; + flex: 1; + font-weight: 600; + font-size: 16px; text-align: left; -} - -.task-name-word-break { - word-break: break-all; + overflow-wrap: break-word; } .people-table-scrollable { - max-height: 600px; - overflow-y: auto; width: 100%; + max-height: 600px; + overflow: auto; + -webkit-overflow-scrolling: touch; + box-sizing: border-box; } -.peopleTableReact { - width: 100%; - min-width: 720px; - border-collapse: collapse; -} - -.peopleTableReact th, -.peopleTableReact td { - padding: 8px; - text-align: left; - overflow-wrap: break-word; - vertical-align: middle; -} - -.peopleTableReact th { - background-color: #eee7f8; - font-size: 18px; -} - -.peopleTableReact td { - border-bottom: 1px solid #f8f7f8; - font-size: 16px; +.people-table-scrollable::-webkit-scrollbar { + height: 8px; + width: 8px; } -.peopleTableReact th:first-child, -.peopleTableReact td:first-child { - width: 28%; -} - -.peopleTableReact th:nth-child(4), -.peopleTableReact td:nth-child(4) { - width: 14%; +.people-table-scrollable::-webkit-scrollbar-track { + background: #162032; + border-radius: 4px; } -.peopleTableReact tbody tr:hover { - background-color: #fafafa; +.people-table-scrollable::-webkit-scrollbar-thumb { + background: #4b5563; + border-radius: 4px; } -.people-table-row-dark td { - border-color: #374151; +.people-table-scrollable::-webkit-scrollbar-thumb:hover { + background: #6b7280; } .reports-table-head-dark th { @@ -324,81 +324,68 @@ color: #f9fafb; } -.wrapperDark .people-table-scrollable { - background-color: #162032; - border: 1px solid #3a4460; - border-radius: 8px; - padding: 4px 0; -} - -/* Dark mode for mobile modal cards */ -.task-card.task-card-dark { - background-color: #232946; - color: #fff; - border: 1px solid #444; -} - -.task-card.task-card-dark .task-header { - background-color: #1a1a2e; - color: #fff; +.reports-table-head-dark { + background-color: #1a1a2e !important; + color: #fff !important; + border-bottom: 1px solid #444 !important; } -.task-card.task-card-dark .task-status { - background-color: #ca50db; - color: #fff; +.people-table-row-dark td { + border-color: #374151; } -.task-card.task-card-dark .task-info { - color: #fff; +.peopleTableReact { + width: 100%; + min-width: 850px; + border-collapse: collapse; } -.task-card.task-card-dark .sub-head, -.task-card.task-card-dark .sub-details { - color: #fff; +.peopleTableReact th, +.peopleTableReact td { + padding: 8px; + text-align: left; + overflow-wrap: break-word; + vertical-align: middle; } -/* Modal textarea dark mode */ -.task-card-dark .rectangle { - background: #232946; - color: #fff; - border: 1.5px solid #444; +.peopleTableReact th:first-child, +.peopleTableReact td:first-child { + width: 28%; + min-width: 260px; + max-width: 350px; + overflow-wrap: break-word; } -/* Desktop table dark mode */ -.reports-table-head-dark { - background-color: #1a1a2e !important; +.people-table-row-dark > div, +.reports-table-head-dark > div { color: #fff !important; } -.people-table-row-dark { - background-color: transparent !important; - color: #fff !important; +.centerColumn { + text-align: center !important; } -.people-table-row-dark > div, -.reports-table-head-dark > div { - color: #fff !important; +:global(.dark-mode) .peopleTableReact { + background-color: #1b2a41; + color: #f9fafb; } -.people-table-row-dark .people-table-center-cell, -.people-table-row-dark .people-table-end-cell { - color: #fff !important; +:global(.dark-mode) .people-table-row-dark { + background-color: #1b2a41 !important; + color: #f9fafb !important; } -/* Table cell border for dark mode */ -.people-table-row-dark, -.reports-table-head-dark { - border-bottom: 1px solid #444 !important; +.mobileCardContainer { + display: none; } -/* Table textarea dark mode */ -.people-table-row-dark .rectangle, -.reports-table-head-dark .rectangle { - background: #232946; - color: #fff; - border: 1px solid #444; -} +@media (width <= 600px) { + .people-table-scrollable { + display: none !important; + } -.centerColumn { - text-align: center !important; + .mobileCardContainer { + display: block !important; + width: 100%; + } } \ No newline at end of file diff --git a/src/components/Reports/__tests__/PeopleTableDetails.test.jsx b/src/components/Reports/__tests__/PeopleTableDetails.test.jsx index b7bfd66c84..6589022558 100644 --- a/src/components/Reports/__tests__/PeopleTableDetails.test.jsx +++ b/src/components/Reports/__tests__/PeopleTableDetails.test.jsx @@ -64,9 +64,9 @@ describe('Unit Test case for PeopleTableDetails component', () => { it('Test 3 : Verify row data renders', () => { render(); - expect(screen.getByText('Task 1')).toBeInTheDocument(); - expect(screen.getByText('Task 2')).toBeInTheDocument(); - expect(screen.getByText('Task 3')).toBeInTheDocument(); + expect(screen.getAllByText('Task 1')[0]).toBeInTheDocument(); + expect(screen.getAllByText('Task 2')[0]).toBeInTheDocument(); + expect(screen.getAllByText('Task 3')[0]).toBeInTheDocument(); }); it('displays a task with no resources and no start date', () => { @@ -78,7 +78,7 @@ describe('Unit Test case for PeopleTableDetails component', () => { render(); - expect(screen.getByText('Unassigned task')).toBeInTheDocument(); + expect(screen.getAllByText('Unassigned task')[0]).toBeInTheDocument(); }); it('Test 5 : Verify no toggle button if resources < 2', () => { @@ -88,14 +88,14 @@ describe('Unit Test case for PeopleTableDetails component', () => { it('Test 6 : Verify button renders if resources > 2', () => { render(); - expect(screen.getByRole('button', { name: /^\d+\+$/ })).toBeInTheDocument(); + expect(screen.getAllByRole('button', { name: /^\d+\+$/ })[0]).toBeInTheDocument(); }); it('shows resource toggle button when there are more than 2 resources', () => { render(); - expect(screen.getByText('Project 2')).toBeInTheDocument(); - const toggleButton = screen.getByText('1+'); + expect(screen.getAllByText('Project 2')[0]).toBeInTheDocument(); + const toggleButton = screen.getAllByText('1+')[0]; expect(toggleButton).toBeInTheDocument(); }); @@ -103,7 +103,7 @@ describe('Unit Test case for PeopleTableDetails component', () => { const taskId = taskFixtureThreeNamedResources[0]._id; render(); - const toggleButton = screen.getByRole('button', { name: /^\d+\+$/ }); + const toggleButton = screen.getAllByRole('button', { name: /^\d+\+$/ })[0]; expect(toggleButton).toBeInTheDocument(); expect(screen.getByTestId(`extra-resources-${taskId}`)).toBeInTheDocument(); @@ -112,13 +112,13 @@ describe('Unit Test case for PeopleTableDetails component', () => { display: 'table-cell', }); - fireEvent.click(screen.getByRole('button', { name: /^\d+\+$/ })); + fireEvent.click(screen.getAllByRole('button', { name: /^\d+\+$/ })[0]); expect(screen.getByTestId(`extra-resources-${taskId}`)).toHaveStyle({ display: 'none' }); }); it('Test 8 : Verify remaining resource count displayed', () => { render(); - expect(screen.getByText('2+')).toBeInTheDocument(); + expect(screen.getAllByText('2+')[0]).toBeInTheDocument(); }); }); @@ -137,7 +137,7 @@ describe('TaskResourceCell', () => { {...baseProps} />, ); - expect(screen.getByText('1+')).toBeInTheDocument(); + expect(screen.getAllByText('1+')[0]).toBeInTheDocument(); }); it('shows the extra-resources block when the task is in expandedTasks', () => { @@ -163,7 +163,7 @@ describe('TaskResourceCell', () => { toggleMoreResources={toggleMoreResources} />, ); - fireEvent.click(screen.getByText('1+')); + fireEvent.click(screen.getAllByText('1+')[0]); expect(toggleMoreResources).toHaveBeenCalledWith(task._id); }); }); @@ -185,4 +185,4 @@ describe('CenteredValueCell', () => { render(); expect(screen.getByText('2022-01-01')).toHaveStyle({ textAlign: 'center' }); }); -}); +}); \ No newline at end of file