diff --git a/src/Assets/Icon/ic-close.svg b/src/Assets/Icon/ic-close.svg index 0a7ddd517..609edae40 100644 --- a/src/Assets/Icon/ic-close.svg +++ b/src/Assets/Icon/ic-close.svg @@ -1,3 +1,9 @@ - - + + + + + + + + diff --git a/src/Shared/Components/BulkSelection/BulkSelection.tsx b/src/Shared/Components/BulkSelection/BulkSelection.tsx index ef0b74277..6d119ada4 100644 --- a/src/Shared/Components/BulkSelection/BulkSelection.tsx +++ b/src/Shared/Components/BulkSelection/BulkSelection.tsx @@ -1,5 +1,6 @@ import BulkSelectionDropdownItems from './BulkSelectionDropdownItems' import { CHECKBOX_VALUE, Checkbox, PopupMenu, noop } from '../../../Common' +import { useBulkSelection } from './BulkSelectionProvider' import { BulkSelectionDropdownItemsType, BulkSelectionEvents, BulkSelectionProps } from './types' import { BULK_DROPDOWN_TEST_ID, BulkSelectionOptionsLabels } from './constants' import { ReactComponent as ICChevronDown } from '../../../Assets/Icon/ic-chevron-down.svg' @@ -7,13 +8,8 @@ import { ReactComponent as ICCheckSquare } from '../../../Assets/Icon/ic-check-s import { ReactComponent as ICCheckAll } from '../../../Assets/Icon/ic-check-all.svg' import { ReactComponent as ICClose } from '../../../Assets/Icon/ic-close.svg' -const BulkSelection = ({ - checkboxValue, - isChecked, - selectedIdentifiers, - handleBulkSelection, - showPagination, -}: BulkSelectionProps) => { +const BulkSelection = ({ showPagination }: BulkSelectionProps) => { + const { handleBulkSelection, selectedIdentifiers, isChecked, checkboxValue } = useBulkSelection() const areOptionsSelected = Object.keys(selectedIdentifiers).length > 0 const BulkSelectionItems: BulkSelectionDropdownItemsType[] = [ { diff --git a/src/Shared/Components/BulkSelection/UseBulkSelection.tsx b/src/Shared/Components/BulkSelection/BulkSelectionProvider.tsx similarity index 54% rename from src/Shared/Components/BulkSelection/UseBulkSelection.tsx rename to src/Shared/Components/BulkSelection/BulkSelectionProvider.tsx index 9f0cecac7..0d77e7b38 100644 --- a/src/Shared/Components/BulkSelection/UseBulkSelection.tsx +++ b/src/Shared/Components/BulkSelection/BulkSelectionProvider.tsx @@ -1,17 +1,36 @@ -import { useState } from 'react' -import { SELECT_ALL_ACROSS_PAGES_LOCATOR, getInvalidActionMessage } from './constants' +import { createContext, useContext, useMemo, useState } from 'react' +import { BULK_SELECTION_CONTEXT_ERROR, SELECT_ALL_ACROSS_PAGES_LOCATOR, getInvalidActionMessage } from './constants' import { BulkSelectionEvents, + GetBulkSelectionCheckboxValuesType, HandleBulkSelectionType, SelectAllDialogStatus, UseBulkSelectionProps, UseBulkSelectionReturnType, } from './types' +import { CHECKBOX_VALUE, noop } from '../../../Common' + +// giving type any here since not exporting this context, rather using it through useBulkSelection hook which is typed +const BulkSelectionContext = createContext>({ + selectedIdentifiers: {}, + handleBulkSelection: noop, + isChecked: false, + checkboxValue: CHECKBOX_VALUE.CHECKED, +}) + +export const useBulkSelection = () => { + const context = useContext>(BulkSelectionContext) + if (!context) { + throw new Error(BULK_SELECTION_CONTEXT_ERROR) + } + return context +} -const useBulkSelection = ({ +export const BulkSelectionProvider = ({ + children, identifiers, getSelectAllDialogStatus, -}: UseBulkSelectionProps): UseBulkSelectionReturnType => { +}: UseBulkSelectionProps) => { const [selectedIdentifiers, setSelectedIdentifiers] = useState({} as T) const setIdentifiersAfterClear = (newIdentifiers: T, selectedIds: (number | string)[]) => { @@ -90,10 +109,52 @@ const useBulkSelection = ({ } } - return { - handleBulkSelection, - selectedIdentifiers, + const getBulkSelectionCheckboxValues = (): GetBulkSelectionCheckboxValuesType => { + const selectedIdentifiersArray = Object.keys(selectedIdentifiers) + if (selectedIdentifiersArray.length === 0) { + return { + isChecked: false, + checkboxValue: CHECKBOX_VALUE.CHECKED, + } + } + + // if selectedIdentifiers contains select all across pages locator then it means all are selected + if (selectedIdentifiers[SELECT_ALL_ACROSS_PAGES_LOCATOR]) { + return { + isChecked: true, + checkboxValue: CHECKBOX_VALUE.BULK_CHECKED, + } + } + + // if all the identifiers are selected then CHECKED else intermediate + const areAllPresentIdentifiersSelected = selectedIdentifiersArray.every( + (identifierId) => identifiers[identifierId], + ) + + if (areAllPresentIdentifiersSelected) { + return { + isChecked: true, + checkboxValue: CHECKBOX_VALUE.CHECKED, + } + } + + return { + isChecked: true, + checkboxValue: CHECKBOX_VALUE.INTERMEDIATE, + } } -} -export default useBulkSelection + const { isChecked, checkboxValue } = getBulkSelectionCheckboxValues() + + const value = useMemo( + () => ({ + selectedIdentifiers, + handleBulkSelection, + isChecked, + checkboxValue, + }), + [selectedIdentifiers, handleBulkSelection, isChecked, checkboxValue], + ) + + return {children} +} diff --git a/src/Shared/Components/BulkSelection/constants.tsx b/src/Shared/Components/BulkSelection/constants.tsx index 357bcf2f0..ca3387317 100644 --- a/src/Shared/Components/BulkSelection/constants.tsx +++ b/src/Shared/Components/BulkSelection/constants.tsx @@ -10,3 +10,4 @@ export const BulkSelectionOptionsLabels = { // Considering application can not be named as * export const SELECT_ALL_ACROSS_PAGES_LOCATOR = '*' as const export const getInvalidActionMessage = (action: string) => `Invalid action ${action} passed to useBulkSelection` +export const BULK_SELECTION_CONTEXT_ERROR = 'useBulkSelection must be used within BulkSelectionContext' diff --git a/src/Shared/Components/BulkSelection/index.ts b/src/Shared/Components/BulkSelection/index.ts index 1f1f82ca8..0befd8109 100644 --- a/src/Shared/Components/BulkSelection/index.ts +++ b/src/Shared/Components/BulkSelection/index.ts @@ -1,4 +1,4 @@ export { default as BulkSelection } from './BulkSelection' -export { default as useBulkSelection } from './UseBulkSelection' +export * from './BulkSelectionProvider' export * from './types' export * from './constants' diff --git a/src/Shared/Components/BulkSelection/types.tsx b/src/Shared/Components/BulkSelection/types.tsx index a288e4718..4bdbd4ac6 100644 --- a/src/Shared/Components/BulkSelection/types.tsx +++ b/src/Shared/Components/BulkSelection/types.tsx @@ -18,14 +18,17 @@ export interface HandleBulkSelectionType { } } -export interface UseBulkSelectionReturnType { +export interface GetBulkSelectionCheckboxValuesType { + isChecked: boolean + checkboxValue: CHECKBOX_VALUE +} + +export interface UseBulkSelectionReturnType extends GetBulkSelectionCheckboxValuesType { selectedIdentifiers: T handleBulkSelection: ({ action, data }: HandleBulkSelectionType) => void } -export interface BulkSelectionProps extends UseBulkSelectionReturnType { - checkboxValue: CHECKBOX_VALUE - isChecked: boolean +export interface BulkSelectionProps { showPagination: boolean } @@ -38,7 +41,7 @@ export interface BulkSelectionDropdownItemsType { export interface BulkSelectionDropdownItemsProps extends BulkSelectionDropdownItemsType, - Pick, 'handleBulkSelection'> {} + Pick, 'handleBulkSelection'> {} export enum SelectAllDialogStatus { OPEN = 'OPEN', @@ -58,4 +61,5 @@ export interface UseBulkSelectionProps { * Act as buffer between select all across pages and select all on page state */ getSelectAllDialogStatus: () => SelectAllDialogStatus + children?: React.ReactNode }