Skip to content

Commit

Permalink
feat: [View/Update institution profile] Create a shared page-level al…
Browse files Browse the repository at this point in the history
…ert for when API is unreachable (#1056)

Closes #1054

## Changes

- Create a shared page-level alert for when API is unreachable
- Add `API down` page-level alert to `Update institution profile` page

## How to test this PR

1. Visit [View institution
profile](http://localhost:8899/institution/123456789TESTBANK123)
2. Use Chrome devtools to block Institution API requests
<img width="522" alt="Screenshot 2024-11-13 at 10 51 26 AM"
src="https://github.com/user-attachments/assets/9b43f41d-deee-4f45-aa5c-aa1667d1adb3">
3. Reload page
4. Verify page-level alert and no crashes
5. Visit [Update institution
profile](http://localhost:8899/institution/123456789TESTBANK123/update)
6. Verify page-level alert and no crashes


## Screenshots
### View institution profile (api down)

![view-down](https://github.com/user-attachments/assets/8750142f-5e10-4b35-99d9-634b6c91251a)


### Update institution profile (api down)

![update-down](https://github.com/user-attachments/assets/2d80a9db-601b-4243-be19-0e36a49afa65)


### Update institution profile: LEI alert and Email domain(s) language

![update-missing-lei](https://github.com/user-attachments/assets/0b5b7346-f635-4542-b524-158bba903b1a)
  • Loading branch information
meissadia authored Nov 15, 2024
1 parent c81f5f1 commit ca0e05e
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 63 deletions.
80 changes: 46 additions & 34 deletions src/pages/Filing/UpdateFinancialProfile/UfpForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { Paragraph, TextIntroduction } from 'design-system-react';
import type { JSXElement } from 'design-system-react/dist/types/jsxElement';
import type { UpdateInstitutionType } from 'pages/Filing/UpdateFinancialProfile/types';
import { UpdateInstitutionSchema } from 'pages/Filing/UpdateFinancialProfile/types';
import { AlertInstitutionApiUnreachable } from 'pages/Filing/ViewInstitutionProfile/AlertInstitutionApiUnreachable';
import { scrollToElement } from 'pages/ProfileForm/ProfileFormUtils';
import { scenarios } from 'pages/Summary/Summary.data';
import { useMemo } from 'react';
Expand All @@ -31,14 +32,19 @@ import { formErrorsOrder } from './formErrorsOrder';

export default function UFPForm({
data,
isError = false,
}: {
data: InstitutionDetailsApiType;
isError: boolean;
}): JSXElement {
const { lei } = useParams();
const isRoutingEnabled = getIsRoutingEnabled();
const navigate = useNavigate();

const defaultValues = useMemo(() => buildProfileFormDefaults(data), [data]);
const defaultValues = useMemo(
() => (isError ? {} : buildProfileFormDefaults(data)),
[data, isError],
);

const {
trigger,
Expand All @@ -52,7 +58,9 @@ export default function UFPForm({
defaultValues,
});

const changedData = collectChangedData(watch(), dirtyFields, data);
const changedData = isError
? null
: collectChangedData(watch(), dirtyFields, data);

// Used for error scrolling
const formErrorHeaderId = 'UFPFormErrorHeader';
Expand Down Expand Up @@ -139,40 +147,44 @@ export default function UFPForm({
}
/>
</FormHeaderWrapper>
<FormErrorHeader<UpdateInstitutionType, IdFormHeaderErrorsType>
alertHeading='There was a problem updating your financial institution profile'
errors={orderedFormErrorsObject}
id={formErrorHeaderId}
formErrorHeaderObject={IdFormHeaderErrors}
keyLogicFunc={updateFinancialProfileKeyLogic}
/>
<FinancialInstitutionDetailsForm {...{ data }} />
<UpdateIdentifyingInformation
{...{ data, register, setValue, watch, formErrors }}
/>
<UpdateAffiliateInformation
{...{ register, formErrors, watch }}
heading='Update your parent entity information (if applicable)'
/>
<FormButtonGroup>
<Button
id='nav-submit'
label='Submit'
appearance='primary'
// eslint-disable-next-line @typescript-eslint/no-misused-promises
onClick={onSubmitButtonAction}
iconRight={isLoadingSubmitUpdateFinancialProfile ? 'updating' : ''}
disabled={!changedData}
type='submit'
<AlertInstitutionApiUnreachable isError={isError}>
<FormErrorHeader<UpdateInstitutionType, IdFormHeaderErrorsType>
alertHeading='There was a problem updating your financial institution profile'
errors={orderedFormErrorsObject}
id={formErrorHeaderId}
formErrorHeaderObject={IdFormHeaderErrors}
keyLogicFunc={updateFinancialProfileKeyLogic}
/>
<FinancialInstitutionDetailsForm {...{ data }} />
<UpdateIdentifyingInformation
{...{ data, register, setValue, watch, formErrors }}
/>
<Button
id='nav-reset'
label='Reset form'
appearance='warning'
onClick={onClearform}
asLink
<UpdateAffiliateInformation
{...{ register, formErrors, watch }}
heading='Update your parent entity information (if applicable)'
/>
</FormButtonGroup>
<FormButtonGroup>
<Button
id='nav-submit'
label='Submit'
appearance='primary'
// eslint-disable-next-line @typescript-eslint/no-misused-promises
onClick={onSubmitButtonAction}
iconRight={
isLoadingSubmitUpdateFinancialProfile ? 'updating' : ''
}
disabled={!changedData}
type='submit'
/>
<Button
id='nav-reset'
label='Reset form'
appearance='warning'
onClick={onClearform}
asLink
/>
</FormButtonGroup>
</AlertInstitutionApiUnreachable>
</FormWrapper>
</main>
);
Expand Down
8 changes: 1 addition & 7 deletions src/pages/Filing/UpdateFinancialProfile/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,22 @@ import { fetchInstitutionDetails } from 'api/requests';
import useSblAuth from 'api/useSblAuth';
import { LoadingContent } from 'components/Loading';
import type { JSXElement } from 'design-system-react/dist/types/jsxElement';
import { useError500 } from 'pages/Error/Error500';
import { useParams } from 'react-router-dom';
import UFPForm from './UfpForm';
import './updateFinancialProfile.less';

function UpdateFinancialProfile(): JSXElement {
const auth = useSblAuth();
const { lei } = useParams();
const redirect500 = useError500();

const { isLoading, isError, data } = useQuery(
[`institution-details-${lei}`],
async () => fetchInstitutionDetails(auth, lei),
);

if (isLoading) return <LoadingContent />;
if (isError)
return redirect500({
message: 'Unable to fetch institution details.',
});

return <UFPForm {...{ data }} />;
return <UFPForm {...{ data, isError }} />;

Check failure on line 21 in src/pages/Filing/UpdateFinancialProfile/index.tsx

View workflow job for this annotation

GitHub Actions / Lint / TSC

Type '{ data: { name: string; lei: string; hq_address_street_1: string; hq_address_city: string; hq_address_state: { code: string; name: string; }; hq_address_zip: string; is_active: boolean; tax_id: string; ... 14 more ...; top_holder_rssd_id?: string | ... 1 more ... | undefined; } | undefined; isError: boolean; }' is not assignable to type '{ data: { name: string; lei: string; hq_address_street_1: string; hq_address_city: string; hq_address_state: { code: string; name: string; }; hq_address_zip: string; is_active: boolean; tax_id: string; ... 14 more ...; top_holder_rssd_id?: string | ... 1 more ... | undefined; }; isError: boolean; }'.
}

export default UpdateFinancialProfile;
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import CommonLinks from 'components/CommonLinks';
import { Alert } from 'design-system-react';

export const MESSAGE_INSTITUTION_API_DOWN =
'A problem occurred when trying to load your profile';

export interface InstitutionApiErrorWrapperType {
isError?: boolean;
children: JSX.Element | JSX.Element[];
}

// Shared page-level alert for Institution API errors
export function AlertInstitutionApiUnreachable({
isError,
children,
}: InstitutionApiErrorWrapperType): JSX.Element {
if (isError)
return (
<Alert status='error' message={MESSAGE_INSTITUTION_API_DOWN}>
<p>
Try again in a few minutes. If this issues persists,{' '}
<CommonLinks.EmailSupportStaff
subject={`[Error] ${MESSAGE_INSTITUTION_API_DOWN}`}
/>
.
</p>
</Alert>
);

// eslint-disable-next-line react/jsx-no-useless-fragment
return <>{children}</>;
}

AlertInstitutionApiUnreachable.defaultProps = {
isError: false,
};

export default AlertInstitutionApiUnreachable;
32 changes: 10 additions & 22 deletions src/pages/Filing/ViewInstitutionProfile/index.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { useQuery } from '@tanstack/react-query';
import { fetchInstitutionDetails } from 'api/requests';
import useSblAuth from 'api/useSblAuth';
import CommonLinks from 'components/CommonLinks';
import CrumbTrail from 'components/CrumbTrail';
import FormHeaderWrapper from 'components/FormHeaderWrapper';
import FormWrapper from 'components/FormWrapper';
import { Link } from 'components/Link';
import { LoadingContent } from 'components/Loading';
import { Alert } from 'design-system-react';
import AlertInstitutionApiUnreachable from 'pages/Filing/ViewInstitutionProfile/AlertInstitutionApiUnreachable';
import { useParams } from 'react-router-dom';
import { AffiliateInformation } from './AffiliateInformation';
import { FinancialInstitutionDetails } from './FinancialInstitutionDetails';
Expand All @@ -25,25 +24,6 @@ function InstitutionDetails(): JSX.Element | null {

if (isLoading) return <LoadingContent />;

const errorMessage = 'A problem occurred when trying to load your profile';

const content = isError ? (
<Alert status='error' message={errorMessage}>
Try again in a few minutes. If this issues persists,{' '}
<CommonLinks.EmailSupportStaff subject={`[Error] ${errorMessage}`} />.
</Alert>
) : (
<>
<FinancialInstitutionDetails data={data} />
<IdentifyingInformation data={data} />
<AffiliateInformation data={data} />
{/* TODO: include history of changes after MVP
https://github.com/cfpb/sbl-project/issues/39
<ChangeHistory />
*/}
</>
);

return (
<main id='main'>
<CrumbTrail>
Expand All @@ -55,7 +35,15 @@ function InstitutionDetails(): JSX.Element | null {
<FormHeaderWrapper>
<PageIntro />
</FormHeaderWrapper>
{content}
<AlertInstitutionApiUnreachable isError={isError}>
<FinancialInstitutionDetails data={data} />

Check failure on line 39 in src/pages/Filing/ViewInstitutionProfile/index.tsx

View workflow job for this annotation

GitHub Actions / Lint / TSC

Type '{ name: string; lei: string; hq_address_street_1: string; hq_address_city: string; hq_address_state: { code: string; name: string; }; hq_address_zip: string; is_active: boolean; tax_id: string; ... 14 more ...; top_holder_rssd_id?: string | ... 1 more ... | undefined; } | undefined' is not assignable to type '{ name: string; lei: string; hq_address_street_1: string; hq_address_city: string; hq_address_state: { code: string; name: string; }; hq_address_zip: string; is_active: boolean; tax_id: string; ... 14 more ...; top_holder_rssd_id?: string | ... 1 more ... | undefined; }'.
<IdentifyingInformation data={data} />

Check failure on line 40 in src/pages/Filing/ViewInstitutionProfile/index.tsx

View workflow job for this annotation

GitHub Actions / Lint / TSC

Type '{ name: string; lei: string; hq_address_street_1: string; hq_address_city: string; hq_address_state: { code: string; name: string; }; hq_address_zip: string; is_active: boolean; tax_id: string; ... 14 more ...; top_holder_rssd_id?: string | ... 1 more ... | undefined; } | undefined' is not assignable to type '{ name: string; lei: string; hq_address_street_1: string; hq_address_city: string; hq_address_state: { code: string; name: string; }; hq_address_zip: string; is_active: boolean; tax_id: string; ... 14 more ...; top_holder_rssd_id?: string | ... 1 more ... | undefined; }'.
<AffiliateInformation data={data} />

Check failure on line 41 in src/pages/Filing/ViewInstitutionProfile/index.tsx

View workflow job for this annotation

GitHub Actions / Lint / TSC

Type '{ name: string; lei: string; hq_address_street_1: string; hq_address_city: string; hq_address_state: { code: string; name: string; }; hq_address_zip: string; is_active: boolean; tax_id: string; ... 14 more ...; top_holder_rssd_id?: string | ... 1 more ... | undefined; } | undefined' is not assignable to type '{ name: string; lei: string; hq_address_street_1: string; hq_address_city: string; hq_address_state: { code: string; name: string; }; hq_address_zip: string; is_active: boolean; tax_id: string; ... 14 more ...; top_holder_rssd_id?: string | ... 1 more ... | undefined; }'.
{/* TODO: include history of changes after MVP
https://github.com/cfpb/sbl-project/issues/39
<ChangeHistory />
*/}
</AlertInstitutionApiUnreachable>
</FormWrapper>
</main>
);
Expand Down

0 comments on commit ca0e05e

Please sign in to comment.