Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
166 changes: 166 additions & 0 deletions src/context/ConfirmationContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
import React, { useReducer } from 'react';
import { ActionType, createAction, getType } from 'typesafe-actions';
import { Button, ButtonVariant, Modal, ModalVariant } from '@patternfly/react-core';

interface Options {
title: string;
titleIconVariant?:
| 'success'
| 'danger'
| 'warning'
| 'info'
| 'default'
| React.ComponentType<any>;
message: string | React.ReactNode;
confirmBtnLabel: string;
cancelBtnLabel: string;
confirmBtnVariant: ButtonVariant;
onConfirm: () => void;
}

const openAction = createAction('open')<Options>();
const enableProcessingAction = createAction('enableProcessing')();
const closeAction = createAction('close')();

interface IConfirmmationContext {
open: (options: Options) => void;
enableProcessing: () => void;
close: () => void;
}

const ConfirmationContext = React.createContext<IConfirmmationContext>({
open: () => undefined,
enableProcessing: () => undefined,
close: () => undefined,
});

//

export type Action = ActionType<
typeof openAction | typeof enableProcessingAction | typeof closeAction
>;

export type State = Readonly<{
isOpen: boolean;
isProcessing: boolean;

title: string;
titleIconVariant?:
| 'success'
| 'danger'
| 'warning'
| 'info'
| 'default'
| React.ComponentType<any>;
message: string | React.ReactNode;
confirmBtnLabel: string;
cancelBtnLabel: string;
confirmBtnVariant: ButtonVariant;

hideCancelBtn: boolean;

onConfirm: () => void;
}>;

export const defaultState: State = {
isOpen: false,
isProcessing: false,

title: '',
titleIconVariant: undefined,
message: '',
confirmBtnLabel: 'Confirm',
cancelBtnLabel: 'Cancel',
confirmBtnVariant: ButtonVariant.primary,

hideCancelBtn: false,

onConfirm: () => undefined,
};

const reducer = (state: State, action: Action): State => {
switch (action.type) {
case getType(openAction):
return {
...state,
...action.payload,
isOpen: true,
};
case getType(enableProcessingAction):
return {
...state,
isProcessing: true,
};
case getType(closeAction):
return defaultState;
default:
return state;
}
};

//

interface IConfirmationContextProviderProps {
children: React.ReactNode;
}

export const ConfirmationContextProvider: React.FunctionComponent<IConfirmationContextProviderProps> =
({ children }: IConfirmationContextProviderProps) => {
const [state, dispatch] = useReducer(reducer, { ...defaultState });

const onOpen = (options: Options) => dispatch(openAction(options));
const onProcessing = () => dispatch(enableProcessingAction());
const onCancel = () => {
dispatch(closeAction());
};

const confirmBtn = (
<Button
key="confirm"
aria-label="confirm"
variant={state.confirmBtnVariant}
isDisabled={state.isProcessing}
onClick={state.onConfirm}
>
{state.confirmBtnLabel}
</Button>
);

const cancelBtn = !state.hideCancelBtn ? (
<Button
key="cancel"
aria-label="cancel"
variant={ButtonVariant.link}
isDisabled={state.isProcessing}
onClick={onCancel}
>
{state.cancelBtnLabel}
</Button>
) : undefined;

return (
<ConfirmationContext.Provider
value={{
open: onOpen,
enableProcessing: onProcessing,
close: onCancel,
}}
>
{children}
<Modal
variant={ModalVariant.small}
title={state.title}
titleIconVariant={state.titleIconVariant}
isOpen={state.isOpen}
onClose={onCancel}
aria-label="confirm-dialog"
actions={!state.hideCancelBtn ? [confirmBtn, cancelBtn] : [confirmBtn]}
>
{state.message}
</Modal>
</ConfirmationContext.Provider>
);
};

export const useConfirmationContext = (): IConfirmmationContext =>
React.useContext(ConfirmationContext);
1 change: 1 addition & 0 deletions src/context/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./ConfirmationContext";
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ export * from './hooks/useModal';
export * from './hooks/useTable';
export * from './hooks/useTableControls';
export * from './hooks/useToolbar';

export * from './context/ConfirmationContext';