react-app/src/pages/AccessRequest.tsx
import React, { useContext, useEffect, useMemo } from 'react';
import pendingImage from '@/assets/images/pending.svg';
import { Box, Button, Grid, Paper, Typography } from '@mui/material';
import AutocompleteFormField from '@/components/form/AutocompleteFormField';
import { useSSO } from '@bcgov/citz-imb-sso-react';
import { FormProvider, useForm } from 'react-hook-form';
import {
accessPendingBlurb,
accountInactiveBlurb,
awaitingRoleBlurb,
signupTermsAndConditionsClaim,
} from '@/constants/jsxSnippets';
import usePimsApi from '@/hooks/usePimsApi';
import { AccessRequest as AccessRequestType } from '@/hooks/api/useUsersApi';
import { AuthContext } from '@/contexts/authContext';
import { Navigate } from 'react-router-dom';
import TextFormField from '@/components/form/TextFormField';
import { useGroupedAgenciesApi } from '@/hooks/api/useGroupedAgenciesApi';
import { SnackBarContext } from '@/contexts/snackbarContext';
import { LookupContext } from '@/contexts/lookupContext';
import { getProvider } from '@/utilities/helperFunctions';
interface StatusPageTemplateProps {
blurb: JSX.Element;
}
const StatusPageTemplate = (props: StatusPageTemplateProps) => {
const { blurb } = props;
return (
<Box
display={'flex'}
flexDirection={'column'}
alignItems={'center'}
textAlign={'center'}
gap={'2rem'}
>
<img width={'300px'} src={pendingImage} />
<Typography>{blurb}</Typography>
</Box>
);
};
const RequestForm = ({ submitHandler }: { submitHandler: (d: any) => void }) => {
const keycloak = useSSO();
const agencyOptions = useGroupedAgenciesApi().agencyOptions;
const lookup = useContext(LookupContext);
const provider = useMemo(
() => getProvider(keycloak.user?.preferred_username, lookup?.data?.Config.bcscIdentifier),
[keycloak.user, lookup],
);
const formMethods = useForm({
defaultValues: {
Provider: provider,
FirstName: keycloak.user?.first_name,
LastName: keycloak.user?.last_name,
Email: keycloak.user?.email,
Notes: '',
Agency: '',
Position: '',
},
});
useEffect(() => {
formMethods.reset({
Provider: provider,
FirstName: keycloak.user?.first_name || '',
LastName: keycloak.user?.last_name || '',
Email: keycloak.user?.email || '',
Notes: '',
Agency: '',
Position: '',
});
}, [provider, keycloak.user]);
return (
<>
<FormProvider {...formMethods}>
<Grid spacing={2} container>
<Grid item xs={6}>
<TextFormField fullWidth name={'Provider'} label={'Provider'} disabled />
</Grid>
<Grid item xs={6}>
<TextFormField fullWidth name={'Email'} label={'Email'} disabled />
</Grid>
<Grid item xs={6}>
<TextFormField fullWidth name={'FirstName'} label={'First name'} disabled />
</Grid>
<Grid item xs={6}>
<TextFormField name={'LastName'} fullWidth label={'Last name'} disabled />
</Grid>
<Grid item xs={12}>
<AutocompleteFormField
required
allowNestedIndent
name={'AgencyId'}
label={'Your agency'}
options={agencyOptions ?? []}
/>
</Grid>
<Grid item xs={12}>
<TextFormField name={'Position'} fullWidth label={'Your position'} />
</Grid>
<Grid item xs={12}>
<TextFormField
name={'Note'}
multiline
fullWidth
label={'Notes (e.g. Reason for access)'}
/>
</Grid>
</Grid>
</FormProvider>
<Box mt={'2rem'} display="flex">
<Button
onClick={async () => {
const isValid = await formMethods.trigger();
if (isValid) {
submitHandler(formMethods.getValues());
}
}}
variant="contained"
color="primary"
sx={{ padding: '8px', width: '6rem', marginX: 'auto' }}
>
Submit
</Button>
</Box>
</>
);
};
export const AccessRequest = () => {
const api = usePimsApi();
const auth = useContext(AuthContext);
const snackbar = useContext(SnackBarContext);
const lookup = useContext(LookupContext);
const onSubmit = (data: AccessRequestType) => {
api.users.submitAccessRequest(data).then((response) => {
if (response.status === 201) {
auth.pimsUser.refreshData();
} else {
snackbar.setMessageState({
text: `Could not create account. Contact ${lookup.data.Config.contactEmail} for assistance.`,
open: true,
style: snackbar.styles.warning,
});
}
});
};
if (
auth.pimsUser?.data?.Status &&
auth.pimsUser?.data?.Status === 'Active' &&
auth.pimsUser?.data?.RoleId
) {
return <Navigate replace to={'/'} />;
}
const selectPageContent = () => {
if (auth.pimsUser.data?.Status === 'Active' && !auth.pimsUser.data?.RoleId) {
return (
<>
<Typography mb={'2rem'} variant="h2">
Awaiting Role
</Typography>
<StatusPageTemplate blurb={awaitingRoleBlurb()} />
</>
);
}
switch (auth.pimsUser.data?.Status) {
case 'OnHold':
return (
<>
<Typography mb={'2rem'} variant="h2">
Access Pending
</Typography>
<StatusPageTemplate blurb={accessPendingBlurb()} />
</>
);
case 'Disabled':
case 'Denied':
return (
<>
<Typography mb={'2rem'} variant="h2">
Account Inactive
</Typography>
<StatusPageTemplate blurb={accountInactiveBlurb()} />
</>
);
default:
return (
<>
<Typography mb={'2rem'} variant="h2">
Access Request
</Typography>
<RequestForm submitHandler={onSubmit} />
</>
);
}
};
return (
<Box
display="flex"
flexDirection={'column'}
width="600px"
marginX="auto"
alignSelf={'center'}
mt={'4rem'}
>
<Paper
sx={{
padding: '2.5rem',
borderRadius: '16px',
boxShadow: '0px 8px 20px 0px rgba(0, 0, 0, 0.04)',
}}
>
{selectPageContent()}
</Paper>
<Typography lineHeight={1.8} fontSize={'0.8rem'} mt={'1rem'} textAlign={'center'}>
{signupTermsAndConditionsClaim}
</Typography>
</Box>
);
};