Merge branch 'renovate/playwright' into 'main'
[ProtonMail-WebClient.git] / packages / account / sso / MembersAuthDevicesModal.tsx
blob9f77cd195ab0c63a4c486fe02750422367bb33a8
1 import { useEffect, useState } from 'react';
3 import type { Action, ThunkDispatch } from '@reduxjs/toolkit';
4 import { c, msgid } from 'ttag';
6 import { Button } from '@proton/atoms';
7 import {
8     type ModalProps,
9     ModalTwo,
10     ModalTwoContent,
11     ModalTwoFooter,
12     ModalTwoHeader,
13     useErrorHandler,
14     useModalState,
15 } from '@proton/components';
16 import { useLoadingByKey } from '@proton/hooks/useLoading';
17 import { baseUseDispatch } from '@proton/react-redux-store';
18 import type { ProtonThunkArguments } from '@proton/redux-shared-store-types';
19 import { BRAND_NAME } from '@proton/shared/lib/constants';
21 import ConfirmDenyMemberAuthDevice from './ConfirmDenyMemberAuthDevice';
22 import MemberAuthDevicesModal from './MemberAuthDevicesModal';
23 import MembersAuthDevicesList from './MembersAuthDevicesList';
24 import { rejectMemberAuthDevice } from './memberAuthDeviceActions';
25 import type { MemberAuthDevicesState, PendingAdminActivation, PendingAdminActivations } from './memberAuthDevices';
27 interface Props extends Omit<ModalProps<'div'>, 'children' | 'buttons'> {
28     pendingAdminActivationsWithMembers: PendingAdminActivations;
31 const MembersAuthDevicesModal = ({ pendingAdminActivationsWithMembers, ...rest }: Props) => {
32     const n = pendingAdminActivationsWithMembers.length;
33     const [pendingMemberAuthDevice, setPendingMemberAuthDevice] = useState<PendingAdminActivation | null>(null);
34     const [grantModalProps, setGrantModal, renderGrantModal] = useModalState();
35     const [denyModalProps, setDenyModal, renderDenyModal] = useModalState();
36     const errorHandler = useErrorHandler();
37     const dispatch = baseUseDispatch<ThunkDispatch<MemberAuthDevicesState, ProtonThunkArguments, Action>>();
38     const [loadingMap, , setLoading] = useLoadingByKey();
40     useEffect(() => {
41         if (!n) {
42             rest.onClose?.();
43         }
44     }, [n]);
46     return (
47         <>
48             {renderGrantModal && pendingMemberAuthDevice && (
49                 <MemberAuthDevicesModal
50                     pendingMemberAuthDevice={pendingMemberAuthDevice}
51                     {...grantModalProps}
52                     onExit={() => {
53                         setPendingMemberAuthDevice(null);
54                         grantModalProps.onExit();
55                     }}
56                 />
57             )}
58             {renderDenyModal && pendingMemberAuthDevice && (
59                 <ConfirmDenyMemberAuthDevice
60                     pendingMemberAuthDevice={pendingMemberAuthDevice}
61                     onConfirm={async () => {
62                         if (!pendingMemberAuthDevice) {
63                             return;
64                         }
65                         const { member, memberAuthDevice } = pendingMemberAuthDevice;
66                         try {
67                             setLoading(memberAuthDevice.ID, true);
68                             await dispatch(
69                                 rejectMemberAuthDevice({
70                                     type: 'reject',
71                                     memberID: member.ID,
72                                     memberAuthDevice,
73                                 })
74                             );
75                         } catch (e) {
76                             errorHandler(e);
77                         } finally {
78                             setLoading(memberAuthDevice.ID, false);
79                         }
80                     }}
81                     {...denyModalProps}
82                     onExit={() => {
83                         setPendingMemberAuthDevice(null);
84                         grantModalProps.onExit();
85                     }}
86                 />
87             )}
88             <ModalTwo {...rest} size="xlarge">
89                 <ModalTwoHeader title={c('sso').t`Grant access to users?`} />
90                 <ModalTwoContent>
91                     <p className="text-break">
92                         {c('sso').ngettext(
93                             msgid`${n} user is requesting your help to sign in to their ${BRAND_NAME} Account with single sign-on.`,
94                             `${n} users are requesting your help to sign in to their ${BRAND_NAME} Account with single sign-on.`,
95                             n
96                         )}
97                     </p>
98                     <div>
99                         <MembersAuthDevicesList
100                             pendingAdminActivationsWithMembers={pendingAdminActivationsWithMembers}
101                             loading={false}
102                             loadingMap={loadingMap}
103                             onApprove={(pendingAdminActivation) => {
104                                 setPendingMemberAuthDevice(pendingAdminActivation);
105                                 setGrantModal(true);
106                             }}
107                             onReject={(pendingAdminActivation) => {
108                                 setPendingMemberAuthDevice(pendingAdminActivation);
109                                 setDenyModal(true);
110                             }}
111                         />
112                     </div>
113                 </ModalTwoContent>
114                 <ModalTwoFooter>
115                     <div></div>
116                     <Button color="norm" onClick={rest.onClose}>{c('sso').t`Cancel`}</Button>
117                 </ModalTwoFooter>
118             </ModalTwo>
119         </>
120     );
123 export default MembersAuthDevicesModal;