Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Design Review - Point of Contact #548

Merged
merged 80 commits into from
May 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
ff3abb9
useeffect refactor wip
shindigira May 20, 2024
ec36f11
refactor(contact): useEffect is now cleaner and with typescript
shindigira May 20, 2024
ca1959a
content(contact): updated the TextIntroduction and the SectionIntrod…
shindigira May 20, 2024
61c67d9
content(contact): updated text
shindigira May 21, 2024
1aa20bb
refactor(contact link): utilizes the RegulationB in commonLinks
shindigira May 21, 2024
4a25256
refactor(getZodKeys): import updates
shindigira May 21, 2024
e2b64e2
Merge branch 'main' of github.com:cfpb/sbl-frontend into 483-design-r…
shindigira May 21, 2024
f071c8a
content(contact): updated states.json to include states abbrev
shindigira May 21, 2024
afa44a5
chore(routes - poc): commented out unused route
shindigira May 21, 2024
4aec735
enhancement(poc): updated layout
shindigira May 21, 2024
a4c4051
content(poc): states updated with 6 us territories
shindigira May 21, 2024
c65c671
TODO comment
shindigira May 21, 2024
75dbf88
conflict
shindigira May 21, 2024
cb74dae
TODO: fix 'isDirty'
shindigira May 21, 2024
0d68f3e
feat(contact): added additional text to zip code and phone number
shindigira May 21, 2024
626c085
content(contact): State or territory
shindigira May 21, 2024
d361f39
feat(contact): Added success alert if previously submitted poc was su…
shindigira May 21, 2024
a0aaf37
comment
shindigira May 21, 2024
e245365
fix: [Point of Contact] Recognize isDirty when changing State input
meissadia May 22, 2024
8e60e78
feat(contact): input error styling
shindigira May 22, 2024
88d0f6a
Merge branch '483-design-review-poc' of github.com:cfpb/sbl-frontend …
shindigira May 22, 2024
53220c7
reinstated isDirty
shindigira May 22, 2024
f19e2e1
chore(contact): disable success alert on 'clear form'
shindigira May 22, 2024
51fbf52
chore(contact):flipped order of phone and email in error header
shindigira May 22, 2024
d768bb8
Merge branch 'main' of github.com:cfpb/sbl-frontend into 483-design-r…
shindigira May 22, 2024
e30ceb7
chore(contact): errorAlertHeader becomes alertHeading
shindigira May 22, 2024
7721cf8
chore(TextInput uses): explicit showError -- affects nothing, TextInp…
shindigira May 22, 2024
78860ee
refactor(formErrorHeader): accepts an object of error header messages
shindigira May 22, 2024
8389bf0
refactor(CompleteUserProfile): Updated fieldlevel and formErrorHeader…
shindigira May 22, 2024
59a1ff4
refactor(formErrorHeader): complete your user profile no associations…
shindigira May 22, 2024
0ab8d73
removed comment
shindigira May 22, 2024
6913d1f
refactor(formErrorHeader): types of financial institution handling
shindigira May 22, 2024
db70306
chore(ufp form error headers): wip
shindigira May 22, 2024
dc8f9ee
refactor(ufp): progress
shindigira May 23, 2024
6e4805c
refactor(formErrorHeader): UpdateYourFinancialProfile form's field an…
shindigira May 23, 2024
e969e57
allow empty parent_lei top_holder_lei -- .or(z.literal(''))
shindigira May 23, 2024
a0fc4fa
refactor(formErrorHeader): moved fieldlevel errors and error header m…
shindigira May 23, 2024
f4934ec
style(contact): 10px between secondary text in the form
shindigira May 23, 2024
6957cae
Merge branch '483-design-review-poc' of github.com:cfpb/sbl-frontend …
shindigira May 23, 2024
0c45b51
style(InputEntry): 30px --> 15px between inputs
shindigira May 23, 2024
1a2a165
resolved merge conflict
shindigira May 23, 2024
6dc5a7f
filing link update
shindigira May 23, 2024
14a38ac
typos
shindigira May 23, 2024
98b27a1
Updated Update your financial profile based on figma - Second pass
shindigira May 23, 2024
1740248
updated content on ufp
shindigira May 23, 2024
686f40e
updated content on both complete your user profile forms - second pass
shindigira May 23, 2024
3c47c38
set order of errors in ufp
shindigira May 23, 2024
54c0289
updated Types of FI - second pass
shindigira May 23, 2024
0e40c1d
updated poc field errors and header errors - second pass
shindigira May 23, 2024
855eebc
updated poc -- conditional alert error heading
shindigira May 24, 2024
400caf2
Missed two typos
shindigira May 24, 2024
d40d365
added condition alert heading for types of fi
shindigira May 24, 2024
9c9695b
an LEI
shindigira May 24, 2024
9f6dca6
helper text added to poc
shindigira May 24, 2024
17eb4ab
feat(contact): states and territories now come from a fetched endpoint
shindigira May 24, 2024
e722a7d
Merge branch 'main' of github.com:cfpb/sbl-frontend into 483-design-r…
shindigira May 24, 2024
daf5ee7
Merge branch '483-design-review-poc' of github.com:cfpb/sbl-frontend …
shindigira May 24, 2024
d78235f
utilized helperText
shindigira May 24, 2024
7c6d060
updated view your financial profile content - second pass
shindigira May 24, 2024
fc3b836
one word change
shindigira May 24, 2024
5545e45
style(InputEntry): reset margin between InputEntry's to 30px
shindigira May 24, 2024
e8d7ae4
updated types of FI -- third pass
shindigira May 24, 2024
7c671f2
fix: 0.938 problem
shindigira May 24, 2024
143e495
style fix -- between state and zip
shindigira May 24, 2024
b3e5b58
enhancement(contact): if there is even just one formatting error, cha…
shindigira May 24, 2024
1a58245
ufp update
shindigira May 24, 2024
bf035c9
complete user profile more content updates
shindigira May 24, 2024
8e50e3d
one more content update
shindigira May 24, 2024
92b972a
CUPNF change
shindigira May 24, 2024
a923241
CupNFZodSchemaErrors.financialInstitutionsMin update
shindigira May 24, 2024
7852e40
hyphen
shindigira May 24, 2024
c107af1
refactor(formErrorHeader), [Point of Contact] Field-level Errors Upda…
shindigira May 24, 2024
aa83a09
Merge branch '483-design-review-poc-and-formerrorheader-refactor' of …
shindigira May 24, 2024
e9b775f
resolvedmerge conflicts
shindigira May 24, 2024
119c169
alphabetic sorting of states and terroitories
shindigira May 25, 2024
facb567
removed comment
shindigira May 25, 2024
9bd3deb
Merge branch 'main' of github.com:cfpb/sbl-frontend into 483-design-r…
shindigira May 25, 2024
4002027
remove unused comment
shindigira May 26, 2024
45d502c
chore(formErrorHeader): typescript typings
shindigira May 26, 2024
e183095
Merge branch 'main' into 483-design-review-poc
shindigira May 28, 2024
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
2 changes: 1 addition & 1 deletion nginx/nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ http {
try_files '' /index.html;
}

# Security Basline - Added to meet requirement 19
# Security Baseline - Added to meet requirement 19
location ~ /\. { deny all; return 404; }

# deny running scripts inside core system folders
Expand Down
8 changes: 0 additions & 8 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -315,14 +315,6 @@ export default function App(): ReactElement {
</ProtectedRoute>
}
/>
<Route
path='/point-of-contact'
element={
<ProtectedRoute {...ProtectedRouteAuthorizations}>
<PointOfContact />
</ProtectedRoute>
}
/>
<Route
path='/institution/:lei/type'
element={
Expand Down
15 changes: 15 additions & 0 deletions src/api/requests/fetchAddressStates.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { request } from 'api/axiosService';
import type { SblAuthProperties } from 'api/useSblAuth';
import type { StateFetchedType } from 'types/filingTypes';

export const fetchAddressStates = async (
auth: SblAuthProperties,
): Promise<NonNullable<StateFetchedType[]>> => {
return request<undefined, NonNullable<StateFetchedType[]>>({
url: `/v1/institutions/address-states`,
method: 'get',
headers: { Authorization: `Bearer ${auth.user?.access_token}` },
});
};

export default fetchAddressStates;
27 changes: 21 additions & 6 deletions src/components/CommonLinks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,17 +82,32 @@ function UploadANewFile({
);
}

const RegulationBSectionUrls: Record<string, string> = {
const RegulationBSectionUrls = {
'§ 1002.109(a)(1)(ii)':
'/2023/05/31/2023-07230/small-business-lending-under-the-equal-credit-opportunity-act-regulation-b#p-4302',
'§ 1002.109(b)(10)':
'/2023/05/31/2023-07230/small-business-lending-under-the-equal-credit-opportunity-act-regulation-b#p-4322',
};

function RegulationB({ section }: { section: string }): React.ReactNode {
'§ 1002.109(b)(3)':
'/2023/05/31/2023-07230/small-business-lending-under-the-equal-credit-opportunity-act-regulation-b#p-4309',
'§ 1002.109(b)(9)':
'/2023/05/31/2023-07230/small-business-lending-under-the-equal-credit-opportunity-act-regulation-b#p-4733',
} as const;

export type RegulationBSectionUrlsKey = keyof typeof RegulationBSectionUrls;
export type RegulationBSectionUrlsValues =
(typeof RegulationBSectionUrls)[RegulationBSectionUrlsKey];

function RegulationB({
section,
}: {
section: RegulationBSectionUrlsKey;
}): JSX.Element {
const baseUrl = 'https://www.federalregister.gov/documents';
const sectionUrl = RegulationBSectionUrls[section];
if (!sectionUrl) return section;
const sectionUrl = RegulationBSectionUrls[
section
] satisfies RegulationBSectionUrlsValues;
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (!sectionUrl) return section as unknown as JSX.Element;
return (
<Link href={baseUrl + sectionUrl} target='_blank'>
{section}
Expand Down
13 changes: 7 additions & 6 deletions src/components/CrumbTrail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@ import { Children } from 'react';

const SINGLE_CHILD = 1;

interface CrumbTrailProperties {
children: ReactNode | ReactNode[];
}

const length = 10;
const separatorKeys = Array.from({ length }).map((_, index) => `key-${index}`);
const INCREMENT_BY_ONE = 1;

function CrumbTrail({ children }: CrumbTrailProperties): JSX.Element | null {
function CrumbTrail({
className,
children,
}: JSX.IntrinsicElements['div']): JSX.Element | null {
let items: ReactNode[] = [];

// eslint-disable-next-line unicorn/no-null
Expand Down Expand Up @@ -46,7 +45,9 @@ function CrumbTrail({ children }: CrumbTrailProperties): JSX.Element | null {
}

return (
<div className='mx-auto my-[1.875rem] max-w-[48.125rem] font-normal'>
<div
className={`mx-auto my-[1.875rem] max-w-[48.125rem] font-normal ${className}`}
>
{items}
</div>
);
Expand Down
9 changes: 7 additions & 2 deletions src/components/FieldGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,14 @@ interface FieldGroupProperties {
children: ReactNode;
}

function FieldGroup({ children }: FieldGroupProperties): JSX.Element {
function FieldGroup({
className,
children,
}: FieldGroupProperties & JSX.IntrinsicElements['div']): JSX.Element {
return (
<div className='field-group box-border max-w-[48.125rem] !border !border-solid !border-cfpbBorderColor bg-[#F7F8F9] p-[1.875rem]'>
<div
className={`field-group box-border max-w-[48.125rem] !border !border-solid !border-cfpbBorderColor bg-[#F7F8F9] p-[1.875rem] ${className}`}
>
{children}
</div>
);
Expand Down
210 changes: 210 additions & 0 deletions src/components/FormErrorHeader.data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
// Constants used between error objects
export const OtherMin =
'You must enter a type of financial institution when “Other” is selected.';

// Types of Financial Institutions - Zod Schema Error Messages
export const UpdateTOIZodSchemaErrors = {
financialInstitutionMin: 'You must select a type of financial institution.',
OtherMin,
} as const;

export type UpdateTOIZodSchemaErrorsType = typeof UpdateTOIZodSchemaErrors;
export type UpdateTOIZodSchemaErrorsKeys =
keyof typeof UpdateTOIZodSchemaErrors;
export type UpdateTOIZodSchemaErrorsValues =
(typeof UpdateTOIZodSchemaErrors)[UpdateTOIZodSchemaErrorsKeys];

// CompleteYourUserProfile - Form Header Error Messages
export type UpdateTOIFormHeaderErrorsType = Record<
UpdateTOIZodSchemaErrorsValues,
string
>;
export const UpdateTOIFormHeaderErrors: UpdateTOIFormHeaderErrorsType = {
[UpdateTOIZodSchemaErrors.financialInstitutionMin]:
'Select your type of financial institution',
[UpdateTOIZodSchemaErrors.OtherMin]:
'Enter a type of financial institution for “Other”',
} as const;
export type UpdateTOIFormHeaderErrorsValues =
(typeof UpdateTOIFormHeaderErrors)[UpdateTOIZodSchemaErrorsValues];

// CompleteYourUserProfile (No Associations) - Zod Schema Error Messages
export const CupNFZodSchemaErrors = {
firstNameMin: 'You must enter your first name.',
lastNameMin: 'You must enter your last name.',
emailMin: 'You must enter your email address.',
emailRegex: 'You must have a valid email address in the correct format.',
financialInstitutionsMin:
'You must enter in at least one financial institution.',
financialInstitutionNameMin:
'You must enter your financial institution name.',
financialInstitutionLeiMin: 'You must enter an LEI.',
financialInstitutionLeiRegex: 'You must enter a valid LEI.',
} as const;

export type CupNFZodSchemaErrorsType = typeof CupNFZodSchemaErrors;
export type CupNFZodSchemaErrorsKeys = keyof typeof CupNFZodSchemaErrors;
export type CupNFZodSchemaErrorsValues =
(typeof CupNFZodSchemaErrors)[CupNFZodSchemaErrorsKeys];

// CompleteYourUserProfile (No Associations) - Form Header Error Messages
export type CupNFFormHeaderErrorsType = Record<
CupNFZodSchemaErrorsValues,
string
>;
export const CupNFFormHeaderErrors: CupNFFormHeaderErrorsType = {
[CupNFZodSchemaErrors.firstNameMin]: 'Enter your first name',
[CupNFZodSchemaErrors.lastNameMin]: 'Enter your last name',
[CupNFZodSchemaErrors.emailMin]: 'Enter your email address',
[CupNFZodSchemaErrors.emailRegex]:
'The email address must be in the proper format',
[CupNFZodSchemaErrors.financialInstitutionsMin]:
'Enter in at least one financial institution',
[CupNFZodSchemaErrors.financialInstitutionNameMin]:
'Enter your financial institution name',
[CupNFZodSchemaErrors.financialInstitutionLeiMin]:
'Enter an LEI for your financial institution',
[CupNFZodSchemaErrors.financialInstitutionLeiRegex]:
'Enter a valid LEI for your financial institution ',
} as const;
export type CupNFFormHeaderErrorsValues =
(typeof CupNFFormHeaderErrors)[CupNFZodSchemaErrorsValues];

// CompleteYourUserProfile - Zod Schema Error Messages
export const CupZodSchemaErrors = {
firstNameMin: 'You must enter your first name.',
lastNameMin: 'You must enter your last name.',
emailMin: 'You must enter your email address.',
emailRegex: 'You must have a valid email address in the correct format.',
financialInstitutionsMin: 'You must select a financial institution.',
} as const;

export type CupZodSchemaErrorsType = typeof CupZodSchemaErrors;
export type CupZodSchemaErrorsKeys = keyof typeof CupZodSchemaErrors;
export type CupZodSchemaErrorsValues =
(typeof CupZodSchemaErrors)[CupZodSchemaErrorsKeys];

// CompleteYourUserProfile - Form Header Error Messages
export type CupFormHeaderErrorsType = Record<CupZodSchemaErrorsValues, string>;
export const CupFormHeaderErrors: CupFormHeaderErrorsType = {
[CupZodSchemaErrors.firstNameMin]: 'Enter your first name',
[CupZodSchemaErrors.lastNameMin]: 'Enter your last name',
[CupZodSchemaErrors.emailMin]: 'Enter your email address',
[CupZodSchemaErrors.emailRegex]:
'The email address must be in the proper format',
[CupZodSchemaErrors.financialInstitutionsMin]:
'Select your financial institution',
} as const;
export type CupFormHeaderErrorsValues =
(typeof CupFormHeaderErrors)[CupZodSchemaErrorsValues];

// Institution Details - Zod Schema Error Messages
export const IdZodSchemaErrors = {
financialInstitutionLeiMin: CupNFZodSchemaErrors.financialInstitutionLeiMin,
financialInstitutionLeiRegex:
CupNFZodSchemaErrors.financialInstitutionLeiRegex,
financialInstitutionNameMin: CupNFZodSchemaErrors.financialInstitutionNameMin,
rssd_idNumber: 'You must enter a valid RSSD ID.',
rssd_idRegex: 'You must enter a valid RSSD ID.',
parent_rssd_idNumber: 'You must enter a valid parent RSSD ID.',
parent_rssd_idRegex: 'You must enter a valid parent RSSD ID.',
top_holder_rssd_idNumber: 'You must enter a valid top holder RSSD ID.',
top_holder_rssd_idRegex: 'You must enter a valid top holder RSSD ID.',
taxIdSchemaRegex: 'You must enter a valid TIN.',
OtherMin,
financialInstitutionParentLeiRegex: 'You must enter a valid parent LEI.',
financialInstitutionTopHolderLeiRegex:
'You must enter a valid top holder LEI.',
} as const;

export type IdZodSchemaErrorsType = typeof IdZodSchemaErrors;
export type IdZodSchemaErrorsKeys = keyof typeof IdZodSchemaErrors;
export type IdZodSchemaErrorsValues =
(typeof IdZodSchemaErrors)[IdZodSchemaErrorsKeys];

// Institution Details - Form Header Error Messages
export type IdFormHeaderErrorsType = Record<
IdZodSchemaErrorsValues,
CupNFFormHeaderErrorsValues
>;
export const IdFormHeaderErrors: IdFormHeaderErrorsType = {
[IdZodSchemaErrors.financialInstitutionLeiMin]:
CupNFFormHeaderErrors[IdZodSchemaErrors.financialInstitutionLeiMin],
[IdZodSchemaErrors.financialInstitutionLeiRegex]:
CupNFFormHeaderErrors[IdZodSchemaErrors.financialInstitutionLeiRegex],
[IdZodSchemaErrors.financialInstitutionNameMin]:
CupNFFormHeaderErrors[IdZodSchemaErrors.financialInstitutionNameMin],
[IdZodSchemaErrors.rssd_idNumber]: 'Enter a valid RSSD ID',
[IdZodSchemaErrors.rssd_idRegex]: 'Enter a valid RSSD ID',
[IdZodSchemaErrors.parent_rssd_idNumber]:
'Enter a valid RSSD ID for your immediate parent entity',
[IdZodSchemaErrors.parent_rssd_idRegex]:
'Enter a valid RSSD ID for your immediate parent entity',
[IdZodSchemaErrors.top_holder_rssd_idNumber]:
'Enter a valid RSSD ID for your top-holding parent entity',
[IdZodSchemaErrors.top_holder_rssd_idRegex]:
'Enter a valid RSSD ID for your top-holding parent entity',
[IdZodSchemaErrors.taxIdSchemaRegex]: 'Enter a valid TIN',
[IdZodSchemaErrors.OtherMin]:
'Enter a type of financial institution for “Other”',
[IdZodSchemaErrors.financialInstitutionParentLeiRegex]:
'Enter a valid LEI for your immediate parent entity',
[IdZodSchemaErrors.financialInstitutionTopHolderLeiRegex]:
'Enter a valid LEI for your top-holding parent entity',
} as const;
export type IdFormHeaderErrorsValues =
(typeof IdFormHeaderErrors)[IdZodSchemaErrorsValues];

// Point of Contact - Zod Schema Error Messages
export const PocZodSchemaErrors = {
firstNameMin:
'You must enter the first name of the point of contact for your submission.',
lastNameMin:
'You must enter the last name of the point of contact for your submission.',
phoneMin:
'You must enter the phone number of the point of contact for your submission.',
phoneRegex: 'You must enter a valid phone number.',
emailMin:
'You must enter the email address of the point of contact for your submission.',
emailRegex: 'You must enter a valid email address.',
hq_address_street_1Min:
'You must enter the street address of the point of contact for your submission.',
hq_address_cityMin:
'You must enter the city of the point of contact for your submission.',
hq_address_stateMin:
'You must select the state or territory of the point of contact for your submission.',
hq_address_zipMin:
'You must enter the ZIP code of the point of contact for your submission.',
hq_address_zipRegex: 'You must enter a valid ZIP code.',
} as const;

export type PocZodSchemaErrorsType = typeof PocZodSchemaErrors;
export type PocZodSchemaErrorsKeys = keyof typeof PocZodSchemaErrors;
export type PocZodSchemaErrorsValues =
(typeof PocZodSchemaErrors)[PocZodSchemaErrorsKeys];

// Point of Contact - Form Header Error Messages
export type PocFormHeaderErrorsType = Record<PocZodSchemaErrorsValues, string>;
export const PocFormHeaderErrors: PocFormHeaderErrorsType = {
[PocZodSchemaErrors.firstNameMin]:
'Enter the first name of the point of contact',
[PocZodSchemaErrors.lastNameMin]:
'Enter the last name of the point of contact',
[PocZodSchemaErrors.phoneMin]:
'Enter the phone number of the point of contact',
[PocZodSchemaErrors.phoneRegex]: 'Enter a valid phone number',
[PocZodSchemaErrors.emailMin]:
'Enter the email address of the point of contact',
[PocZodSchemaErrors.emailRegex]: 'Enter a valid email address',
[PocZodSchemaErrors.hq_address_street_1Min]:
'Enter the street address of the point of contact',
[PocZodSchemaErrors.hq_address_cityMin]:
'Enter the city of the point of contact',
[PocZodSchemaErrors.hq_address_stateMin]:
'Select the state or territory of the point of contact',
[PocZodSchemaErrors.hq_address_zipMin]:
'Enter the ZIP code of the point of contact',
[PocZodSchemaErrors.hq_address_zipRegex]: 'Enter a valid ZIP code',
} as const;
export type PocFormHeaderErrorsValues =
(typeof PocFormHeaderErrors)[PocZodSchemaErrorsValues];
Loading