diff --git a/__tests__/Unit/Components/Tabs/Tab.test.tsx b/__tests__/Unit/Components/Tabs/Tab.test.tsx index f9a09fd51..8f2d42118 100644 --- a/__tests__/Unit/Components/Tabs/Tab.test.tsx +++ b/__tests__/Unit/Components/Tabs/Tab.test.tsx @@ -1,7 +1,10 @@ import Tabs from '@/components/Tabs'; -import { fireEvent, render, screen } from '@testing-library/react'; +import { fireEvent } from '@testing-library/react'; import { Tab, TABS } from '@/interfaces/task.type'; import { COMPLETED, DONE, AVAILABLE, UNASSINGED } from '@/constants/constants'; +import { renderWithRouter } from '@/test_utils/createMockRouter'; +import { store } from '@/app/store'; +import { Provider } from 'react-redux'; function changeName(name: string) { if (name === COMPLETED) { @@ -15,55 +18,113 @@ function changeName(name: string) { describe('Tabs Component', () => { const onSelectMock = jest.fn(); + const mockTasksCount = { + ASSIGNED: 2, + COMPLETED: 4, + AVAILABLE: 10, + IN_PROGRESS: 0, + NEEDS_REVIEW: 0, + IN_REVIEW: 0, + VERIFIED: 0, + MERGED: 0, + }; - it('should render all the buttons', () => { - render( - + test('should render all the buttons', () => { + const { queryAllByRole } = renderWithRouter( + + + ); - const presentTabs = screen.queryAllByRole('button'); + const presentTabs = queryAllByRole('button'); expect(presentTabs.length).toBe(TABS.length); }); - it('check if selectTab() is called with right key', () => { - render( - + test('check if selectTab() is called with right key', () => { + const { getByRole } = renderWithRouter( + + + ); - const assignedBtn = screen.getByRole('button', { name: /ASSIGNED/i }); + const assignedBtn = getByRole('button', { name: /ASSIGNED/i }); fireEvent.click(assignedBtn); expect(onSelectMock).toHaveBeenCalledWith(Tab.ASSIGNED); }); - it('Check if correct button is selected', () => { - render( - + test('Check if correct button is selected', () => { + const { getByRole } = renderWithRouter( + + + ); - const completedBtn = screen.getByRole('button', { name: /DONE/i }); + const completedBtn = getByRole('button', { name: /DONE/i }); expect(completedBtn).toHaveClass('active'); }); - it('should render all tabs passed with correct text', () => { - render( - + test('should render all tabs passed with correct text', () => { + const { getAllByRole } = renderWithRouter( + + + ); - const presentTabs = screen.getAllByRole('button'); + const presentTabs = getAllByRole('button'); for (let i = 0; i < presentTabs.length; i++) { expect(presentTabs[i].textContent).toBe(changeName(TABS[i])); } }); + + test('should change Tabs design and show tasks count if feature flag is on', () => { + const { getByRole, getAllByRole } = renderWithRouter( + + + , + { + query: { dev: 'true' }, + } + ); + + const presentTabs = getAllByRole('button'); + + // tasks count is rendered correctly on screen + for (let i = 0; i < presentTabs.length; i++) { + expect(presentTabs[i].textContent).toBe( + `${changeName(TABS[i])} (${mockTasksCount[TABS[i]]})` + ); + } + + // feature flag's css is applied correctly + for (let i = 0; i < presentTabs.length; i++) { + expect(presentTabs[i]).toHaveClass('featureFlagTabButton'); + } + + // active tab's feature flag css is applied correctly + const assignedBtn = getByRole('button', { + name: /assigned/i, + }); + expect(assignedBtn).toHaveClass('featureFlagActiveTab'); + }); }); diff --git a/src/components/Header/Header.module.scss b/src/components/Header/Header.module.scss index 490fe5b23..acaa0a832 100644 --- a/src/components/Header/Header.module.scss +++ b/src/components/Header/Header.module.scss @@ -1,15 +1,16 @@ .header { + padding-top: 0.6rem; display: flex; justify-content: center; - align-items: center; flex-wrap: wrap; - padding-top: 0.625rem; + align-items: center; + border-bottom: 1px solid var(--toastify-text-color-light); } .link { - padding: 0.625rem; + padding: 0.6rem; text-decoration: none; - font-weight: bold; + font-weight: 700; color: #041484; cursor: pointer; background: none; diff --git a/src/components/ProgressForm/ProgressForm.module.scss b/src/components/ProgressForm/ProgressForm.module.scss index b6a0c0b62..429b238e0 100644 --- a/src/components/ProgressForm/ProgressForm.module.scss +++ b/src/components/ProgressForm/ProgressForm.module.scss @@ -11,16 +11,6 @@ $similar-margin: $base-unit * 8; $section-padding-top-bottom: $base-unit * 30; $section-padding-left-right: $base-unit * 25; -.banner { - display: flex; - flex-direction: column; - align-items: flex-start; - justify-content: center; - width: 100%; - margin-top: $diff-margin; - margin-left: 8.2rem; -} - .mark { color: $color-red; text-decoration: underline; diff --git a/src/components/ProgressForm/ProgressHeader.tsx b/src/components/ProgressForm/ProgressHeader.tsx index af6940560..92e3866f7 100644 --- a/src/components/ProgressForm/ProgressHeader.tsx +++ b/src/components/ProgressForm/ProgressHeader.tsx @@ -7,17 +7,19 @@ const ProgressHeader: FC = ({ updateType, }) => { return ( -
-

- You have - - {totalMissedUpdates} missed - - {updateType} updates -

-

- Let's try to avoid having zero days -

+
+
+

+ You have + + {totalMissedUpdates} missed + + {updateType} updates +

+

+ Let's try to avoid having zero days +

+
); }; diff --git a/src/components/ProgressForm/ProgressLayout.tsx b/src/components/ProgressForm/ProgressLayout.tsx index 6537ba17c..7aeee00bf 100644 --- a/src/components/ProgressForm/ProgressLayout.tsx +++ b/src/components/ProgressForm/ProgressLayout.tsx @@ -20,12 +20,10 @@ const ProgressLayout: FC = () => { return ( <> -
- -
+

Task Updates

On {getCurrentDate()}

diff --git a/src/components/Tabs/Tabs.module.scss b/src/components/Tabs/Tabs.module.scss index 93badc756..6ea7c2ded 100644 --- a/src/components/Tabs/Tabs.module.scss +++ b/src/components/Tabs/Tabs.module.scss @@ -1,18 +1,51 @@ $theme-grey: #d4d4d5; +$theme-grey-light: #f1f1f5; +$gray-shade-color: #808080; +$gray-shade-color2: #5c5b5b; +$theme-dark-grey: #a1a5b7; +$theme-pink: #e30062; .tabButton { + border: none; + border-bottom: 1.8px solid $theme-grey; + font-size: 0.85rem; + font-weight: bold; + color: $gray-shade-color; + background: var(--toastify-color-light); + padding: 0.45rem 0.8rem; + border-radius: 0.2rem 0.2rem 0 0; + cursor: pointer; +} + +.tabButton:hover { + color: $gray-shade-color2; +} + +.tabButton:active { + background-color: $theme-grey-light; +} + +.active { + color: var(--toastify-color-dark); + border: 1.8px solid $theme-grey; + border-bottom: none; + background: var(--toastify-color-light); +} + +.featureFlagTabButton { background: white; border: none; padding: 12px 8px 8px; font-size: 0.8em; - border-radius: 5px 5px 0 0; - border-bottom: 1px solid $theme-grey; + border: none; cursor: pointer; + color: $theme-dark-grey; } -.active { +.featureFlagActiveTab { font-weight: bold; - border: 1px solid $theme-grey; - border-bottom: none; background: white; + border: none; + border-bottom: 3px solid $theme-pink; + color: black; } diff --git a/src/components/Tabs/index.tsx b/src/components/Tabs/index.tsx index a6fceb1d7..67f99e895 100644 --- a/src/components/Tabs/index.tsx +++ b/src/components/Tabs/index.tsx @@ -1,11 +1,13 @@ import styles from '@/components/Tabs/Tabs.module.scss'; -import { Tab } from '@/interfaces/task.type'; import { COMPLETED, DONE, AVAILABLE, UNASSINGED } from '@/constants/constants'; +import { Tab, tasksCountObject } from '@/interfaces/task.type'; +import { useRouter } from 'next/router'; type TabsProps = { tabs: Tab[]; onSelect: (tab: Tab) => void; activeTab: Tab; + tasksCount: tasksCountObject; }; function changeName(name: string) { if (name === COMPLETED) { @@ -17,20 +19,38 @@ function changeName(name: string) { } } -const Tabs = ({ tabs, onSelect, activeTab }: TabsProps) => ( - <> - {tabs.map((tab: Tab) => ( - - ))} - -); +const Tabs = ({ tabs, onSelect, activeTab, tasksCount }: TabsProps) => { + const router = useRouter(); + const { query } = router; + const isFeatureFlagOn = query.dev === 'true'; + return ( + <> + {tabs.map((tab: Tab) => ( + + ))} + + ); +}; export default Tabs; diff --git a/src/components/standup/index.tsx b/src/components/standup/index.tsx index 40e774614..160207471 100644 --- a/src/components/standup/index.tsx +++ b/src/components/standup/index.tsx @@ -73,12 +73,11 @@ const StandUpContainer: FC = () => { return ( <>
+
- -

Standup Update

void; activeTab: Tab; + tasksCount: tasksCountObject; }) => { return (
@@ -14,6 +16,7 @@ export const TabSection = ({ tabs={TABS as Tab[]} onSelect={onSelect} activeTab={activeTab} + tasksCount={tasksCount} />
); diff --git a/src/components/tasks/TaskList/TaskList.tsx b/src/components/tasks/TaskList/TaskList.tsx index 810e88534..6f8574dff 100644 --- a/src/components/tasks/TaskList/TaskList.tsx +++ b/src/components/tasks/TaskList/TaskList.tsx @@ -53,7 +53,7 @@ export default function TaskList({ } return ( - <> +
{filteredTasks.map((item: task) => ( )} - +
); } diff --git a/src/components/tasks/TasksContent.tsx b/src/components/tasks/TasksContent.tsx index 94765eccf..054abe9ec 100644 --- a/src/components/tasks/TasksContent.tsx +++ b/src/components/tasks/TasksContent.tsx @@ -3,7 +3,7 @@ import classNames from '@/styles/tasks.module.scss'; import { isUserAuthorizedContext } from '@/context/isUserAuthorized'; import updateTasksStatus from '@/helperFunctions/updateTasksStatus'; -import task, { Tab } from '@/interfaces/task.type'; +import task, { Tab, tasksCountObject } from '@/interfaces/task.type'; import { useContext, useState, useEffect } from 'react'; import { STATUS_ORDER } from '@/constants/task-status'; import { @@ -26,6 +26,20 @@ export const TasksContent = () => { const isUserAuthorized = useContext(isUserAuthorizedContext); const isEditable = isUserAuthorized && isEditMode; const [activeTab, setActiveTab] = useState(Tab.IN_PROGRESS); + + const startingTasksCount: tasksCountObject = { + ASSIGNED: 0, + COMPLETED: 0, + AVAILABLE: 0, + IN_PROGRESS: 0, + NEEDS_REVIEW: 0, + IN_REVIEW: 0, + VERIFIED: 0, + MERGED: 0, + }; + const [tasksCount, setTasksCount] = + useState(startingTasksCount); + // TODO: the below code should removed when mutation for updating tasks is implemented const [filteredTask, setFilteredTask] = useState([]); // TODO: the below code should removed when mutation for updating tasks is implemented @@ -37,9 +51,29 @@ export const TasksContent = () => { setActiveTab(tab); }; + function getTasksCount(passedTasksArray: task[]) { + const tasksCount: tasksCountObject = { + ASSIGNED: 0, + COMPLETED: 0, + AVAILABLE: 0, + IN_PROGRESS: 0, + NEEDS_REVIEW: 0, + IN_REVIEW: 0, + VERIFIED: 0, + MERGED: 0, + }; + passedTasksArray.forEach((task: task) => { + tasksCount[task.status as Tab] += 1; + }); + + return tasksCount; + } + // TODO: the useEffect should be removed when mutation for updating tasks is implemented useEffect(() => { if ('tasks' in response) { + const tasksCount = getTasksCount(response.tasks); + setTasksCount(tasksCount); const tasks = updateTasksStatus(response.tasks); tasks.sort((a: task, b: task) => +a.endsOn - +b.endsOn); tasks.sort( @@ -76,7 +110,11 @@ export const TasksContent = () => { return (
- +
{filteredTask[activeTab] ? (