From bc1a07251522af0e747b1f8ed797b4767e32bf05 Mon Sep 17 00:00:00 2001 From: Davor Date: Tue, 19 Jul 2022 00:21:06 +0200 Subject: [PATCH] implement progress steps component --- src/components/Form/Select/Select.tsx | 2 +- src/components/Modal/Modal/Modal.tsx | 6 +- src/components/Modal/Modal/types.ts | 1 + src/components/Steps/ProgressSteps.tsx | 107 ++++++++ src/components/Steps/index.ts | 1 + src/components/Steps/types.ts | 20 ++ src/components/UserModal/consts.ts | 2 +- src/components/index.ts | 1 + .../MultipleUsersModal/MultipleUsersModal.tsx | 251 +++++++++++++----- 9 files changed, 318 insertions(+), 73 deletions(-) create mode 100644 src/components/Steps/ProgressSteps.tsx create mode 100644 src/components/Steps/index.ts create mode 100644 src/components/Steps/types.ts diff --git a/src/components/Form/Select/Select.tsx b/src/components/Form/Select/Select.tsx index aad51fa..06a5322 100644 --- a/src/components/Form/Select/Select.tsx +++ b/src/components/Form/Select/Select.tsx @@ -26,7 +26,7 @@ export const Select = ({ control, name, label, options, disabled = false }: Sele value={field.value ? field.value : ''} // input value name={name} // send down the input name ref={field.ref} // send input ref, so we can focus on input when error appear - className="shadow-sm focus:ring-primary-500 focus:border-primary-500 block w-full sm:text-sm border-gray-300 rounded-md" + className="block shadow-sm focus:ring-primary-500 focus:border-primary-500 block w-full sm:text-sm border-gray-300 rounded-md" disabled={disabled} > {options?.map((option) => ( diff --git a/src/components/Modal/Modal/Modal.tsx b/src/components/Modal/Modal/Modal.tsx index 048b315..e61aaee 100644 --- a/src/components/Modal/Modal/Modal.tsx +++ b/src/components/Modal/Modal/Modal.tsx @@ -12,6 +12,7 @@ export const Modal: React.FC = ({ useCancelButton = false, isLoading = false, leftActions = <>, + saveButtonDisabled = false, }) => { const cancelButtonRef = useRef(null); const saveButtonRef = useRef(null); @@ -86,9 +87,12 @@ export const Modal: React.FC = ({
diff --git a/src/components/Modal/Modal/types.ts b/src/components/Modal/Modal/types.ts index afd720c..e679e69 100644 --- a/src/components/Modal/Modal/types.ts +++ b/src/components/Modal/Modal/types.ts @@ -8,4 +8,5 @@ export type ModalProps = { useCancelButton?: boolean; isLoading?: boolean; leftActions?: React.ReactNode; + saveButtonDisabled?: boolean; }; diff --git a/src/components/Steps/ProgressSteps.tsx b/src/components/Steps/ProgressSteps.tsx new file mode 100644 index 0000000..2a24d67 --- /dev/null +++ b/src/components/Steps/ProgressSteps.tsx @@ -0,0 +1,107 @@ +import _ from 'lodash'; +import React from 'react'; +import { ProgressStepsProps, ProgressStepStatus } from './types'; + +export const ProgressSteps: React.FC = ({ steps, onNext, onPrevious, onStepClick, children }) => { + const handleNext = () => { + if (onNext) { + onNext(); + } + }; + const handlePrevious = () => { + if (onPrevious) { + onPrevious(); + } + }; + + const showNextPage = () => { + if (onNext) { + return _.some(steps, { status: ProgressStepStatus.Upcoming }); + } + return false; + }; + + const showPreviousPage = () => { + if (onPrevious) { + return _.some(steps, { status: ProgressStepStatus.Complete }); + } + return false; + }; + + const handleStepClick = (stepId: string) => { + if (onStepClick) { + onStepClick(stepId); + } + }; + + return ( + <> + + + {children} + + {(showNextPage() || showPreviousPage()) && ( +
+
+ {showNextPage() && ( + + )} + {showPreviousPage() && ( + + )} +
+
+ )} + + ); +}; diff --git a/src/components/Steps/index.ts b/src/components/Steps/index.ts new file mode 100644 index 0000000..2bc8859 --- /dev/null +++ b/src/components/Steps/index.ts @@ -0,0 +1 @@ +export { ProgressSteps } from './ProgressSteps'; diff --git a/src/components/Steps/types.ts b/src/components/Steps/types.ts new file mode 100644 index 0000000..3eed8b3 --- /dev/null +++ b/src/components/Steps/types.ts @@ -0,0 +1,20 @@ +export type ProgressStepsProps = { + steps: ProgressStepInfo[]; + onNext?: () => void; + onPrevious?: () => void; + onStepClick?: (stepId: string) => void; +}; + +export interface ProgressStepInfo { + id: string; + name: string; + status: ProgressStepStatus; + component?: React.ReactNode; + href?: string; +} + +export enum ProgressStepStatus { + Complete = 0, + Current = 1, + Upcoming = 2, +} diff --git a/src/components/UserModal/consts.ts b/src/components/UserModal/consts.ts index 2229a23..f156652 100644 --- a/src/components/UserModal/consts.ts +++ b/src/components/UserModal/consts.ts @@ -24,12 +24,12 @@ export const appAccessList = [ ]; export const allAppAccessList = [ - ...appAccessList, { name: 'dashboard', image: '/assets/logo-small.svg', label: 'Dashboard', }, + ...appAccessList, ]; export const initialAppRoles = [ diff --git a/src/components/index.ts b/src/components/index.ts index 565e17d..aff49e2 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -5,3 +5,4 @@ export { Banner } from './Banner'; export { Tabs } from './Tabs'; export { Modal, ConfirmationModal } from './Modal'; export { UserModal } from './UserModal'; +export { ProgressSteps } from './Steps'; diff --git a/src/modules/users/components/MultipleUsersModal/MultipleUsersModal.tsx b/src/modules/users/components/MultipleUsersModal/MultipleUsersModal.tsx index 63e3021..02200e8 100644 --- a/src/modules/users/components/MultipleUsersModal/MultipleUsersModal.tsx +++ b/src/modules/users/components/MultipleUsersModal/MultipleUsersModal.tsx @@ -1,25 +1,172 @@ -import React from 'react'; +import React, { useEffect, useState } from 'react'; import _ from 'lodash'; -import { useFieldArray, useForm } from 'react-hook-form'; +import { useFieldArray, useForm, useWatch } from 'react-hook-form'; -import { Modal, Tabs } from 'src/components'; +import { Banner, Modal, ProgressSteps } from 'src/components'; import { Select, TextArea } from 'src/components/Form'; import { MultipleUsersData, UserRole, useUsers } from 'src/services/users'; import { allAppAccessList } from 'src/components/UserModal/consts'; +import { ProgressStepInfo, ProgressStepStatus } from 'src/components/Steps/types'; import { initialMultipleUsersForm, MultipleUsersModalProps } from './types'; export const MultipleUsersModal = ({ open, onClose }: MultipleUsersModalProps) => { + const [steps, setSteps] = useState([]); + const [isAdminRoleSelected, setAdminRoleSelected] = useState(false); const { createUsers, userModalLoading } = useUsers(); const { control, handleSubmit } = useForm({ defaultValues: initialMultipleUsersForm, }); - const { fields } = useFieldArray({ + const { fields, update } = useFieldArray({ control, name: 'appRoles', }); + const dashboardRole = useWatch({ + control, + name: 'appRoles.0.role', + }); + + const csvDataWatch = useWatch({ + control, + name: 'csvUserData', + }); + + useEffect(() => { + const isAdminDashboardRoleSelected = dashboardRole === UserRole.Admin; + setAdminRoleSelected(isAdminDashboardRoleSelected); + if (isAdminDashboardRoleSelected) { + fields.forEach((field, index) => update(index, { name: field.name, role: UserRole.Admin })); + } else { + fields.forEach((field, index) => update(index, { name: field.name, role: UserRole.User })); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [dashboardRole]); + + const renderUsersCsvDataInput = () => { + return ( +
+
+

CSV data

+
+
+