generated from cfpb/open-source-project-template
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[User Profile] - Layout View - Initial User Profile Form, Frontend Va…
…lidation Schema (#27) * feature: Profile Form -- Start Changes: - [feat] Created a link to the Profile Form - [feat] Created a route to the Profile Form - [feat] Started a Profile Form Component * feat: Profile form Changes: - [chore] Added `react-hook-form`, `zod` and `@hookform/resolvers` - [style] Started initial form look * feat: zod validation update Changes: - [chore] form update with available fields * feat: User Profile - Step 1 Changes: - [chore] Started a `store` folder for hooks - [style] Utilized the CFPB style for the User Profile form buttons - [feat] First Name and Last Name implemented on the User Profile * chore: Auto-populate email in User Profile with logged-in user email from useSblAuth hook * feat: Integrated Zustand/Immer, Step Forms Changes: - [feat]: Added `zustand` and `immer` for state management - [chore]: Renamed the initial User Profile form as a Step1Form - [chore]: Utilized User Profile state management via Zustand * chore: Added 'login.gov' notice to email field * chore: red border on missing first and last name fields * feat: added mock associated financial data for the validation schema * chore: InputEntry component Changes: - [chore]: Created the `InputEntry` component - [chore]: Created the `ProfileForm.data.ts` to place data and mock data - [feat]: Added `react-select` and `@types/react-select` packages * chore: added and yarn cache items * fix: added error border styling for the associated financial institution(s) field * feat: Initial User Profile form complete Changes: - [feat] Included all the initial validation schema fields - [feat] Included error messages for associated financial data - [chore] Included the `svgr` plugin to be able to import svg files * chore: set a link - submit a technical question * chore: added default margin for mobile responsiveness * fix: removed dead code * chore: fixed form padding * chore: Tailwind colors, Error SVG correction Changes: - [chore] added error and disabled color class in the tailwind config - [chore] added the correct error icon * chore: added additional notice regarding LEI to the User Profile form * chore: re-added @cfpb/cfpb-design-system * fix: removed `console.log` Co-authored-by: Meis <meissadia@gmail.com> * Update src/pages/ProfileForm/Step1Form.tsx - Removed `console.log` Co-authored-by: Meis <meissadia@gmail.com> * Update src/pages/ProfileForm/Step1Form.tsx Removed duplicate button Co-authored-by: Meis <meissadia@gmail.com> * Update src/pages/ProfileForm/Step1FormHeader.tsx Removed duplicate paragraph Co-authored-by: Meis <meissadia@gmail.com> * fix: fixed missing char --------- Co-authored-by: Meis <meissadia@gmail.com>
- Loading branch information
1 parent
835aaea
commit 9e33de0
Showing
62 changed files
with
1,554 additions
and
339 deletions.
There are no files selected for viewing
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added
BIN
+21.7 KB
.yarn/cache/@babel-helper-compilation-targets-npm-7.22.10-20c2c02a4f-f6f1896816.zip
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file removed
BIN
-26.6 KB
.yarn/cache/@cfpb-cfpb-atomic-component-npm-0.25.0-c4bbd70f82-9401dda027.zip
Binary file not shown.
Binary file removed
BIN
-12.6 KB
.yarn/cache/@cfpb-cfpb-buttons-npm-0.25.0-dfaea9b05b-b1c514f84a.zip
Binary file not shown.
Binary file not shown.
Binary file removed
BIN
-10.6 KB
.yarn/cache/@cfpb-cfpb-design-system-npm-0.25.0-473d1a319a-18b1a0a182.zip
Binary file not shown.
Binary file removed
BIN
-18.6 KB
.yarn/cache/@cfpb-cfpb-expandables-npm-0.25.0-b77980df66-428f009e03.zip
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file removed
BIN
-10.5 KB
.yarn/cache/@cfpb-cfpb-notifications-npm-0.25.0-b2f6626ace-ff82cf34eb.zip
Binary file not shown.
Binary file removed
BIN
-9.28 KB
.yarn/cache/@cfpb-cfpb-pagination-npm-0.25.0-7d17ac898e-7a03354737.zip
Binary file not shown.
Binary file not shown.
Binary file removed
BIN
-18.6 KB
.yarn/cache/@cfpb-cfpb-typography-npm-0.25.0-7c4042fc94-45766f77f7.zip
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added
BIN
+6.86 KB
.yarn/cache/@svgr-babel-plugin-add-jsx-attribute-npm-7.0.0-8de5ae8c89-ecdf432de3.zip
Binary file not shown.
Binary file added
BIN
+4.27 KB
.yarn/cache/@svgr-babel-plugin-remove-jsx-attribute-npm-7.0.0-a0d8c327ec-808ba216ee.zip
Binary file not shown.
Binary file added
BIN
+3.92 KB
.../cache/@svgr-babel-plugin-remove-jsx-empty-expression-npm-7.0.0-1809ec9d7b-da0cae989c.zip
Binary file not shown.
Binary file added
BIN
+4.88 KB
.../cache/@svgr-babel-plugin-replace-jsx-attribute-value-npm-7.0.0-17dcc8f130-e624918b54.zip
Binary file not shown.
Binary file added
BIN
+6.49 KB
.yarn/cache/@svgr-babel-plugin-svg-dynamic-title-npm-7.0.0-d05ee970aa-3ffc97cc61.zip
Binary file not shown.
Binary file added
BIN
+5.14 KB
.yarn/cache/@svgr-babel-plugin-svg-em-dimensions-npm-7.0.0-b0f780e432-0f98ee5269.zip
Binary file not shown.
Binary file added
BIN
+6.34 KB
...n/cache/@svgr-babel-plugin-transform-react-native-svg-npm-7.0.0-affc1645bd-2006796534.zip
Binary file not shown.
Binary file added
BIN
+10.3 KB
.yarn/cache/@svgr-babel-plugin-transform-svg-component-npm-7.0.0-20736a89d6-cf5be9c6b2.zip
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added
BIN
+20.3 KB
.yarn/cache/@svgr-hast-util-to-babel-ast-npm-7.0.0-5fa3241b27-c2168c36c8.zip
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { ReactComponent as ErrorSVG } from "assets/error.svg"; | ||
|
||
|
||
function ErrorIcon(): JSX.Element { | ||
return ( | ||
<div className='text-errorColor'> | ||
<ErrorSVG /> | ||
</div> | ||
) | ||
} | ||
|
||
export default ErrorIcon |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { ReactComponent as WarningErrorSVG } from "assets/warning-error.svg"; | ||
|
||
|
||
function WarningErrorIcon(): JSX.Element { | ||
return ( | ||
<div className='text-errorColor'> | ||
<WarningErrorSVG /> | ||
</div> | ||
) | ||
} | ||
|
||
export default WarningErrorIcon |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,4 +13,8 @@ | |
&:hover { | ||
color: #2284d5; | ||
} | ||
} | ||
|
||
[type='text']:focus { | ||
box-shadow: none; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import type { ReactNode } from 'react'; | ||
|
||
interface InputEntryProperties { | ||
id: string; | ||
label: string; | ||
errors: object; | ||
isDisabled: boolean; | ||
register: () => void; | ||
children: ReactNode | ||
} | ||
|
||
function InputEntry({id, errors, label, register, isDisabled = false, children}: InputEntryProperties) { | ||
return ( | ||
<div className="mb-6"> | ||
<label | ||
htmlFor={id} | ||
className="text-[1.125em] font-medium tracking-[inherit] leading-tight mb-2 inline-block w-full" | ||
> | ||
{label} | ||
</label> | ||
{children} | ||
<input | ||
type="text" | ||
id={id} | ||
className={`border w-full ${errors[id] ? 'border-errorColor border-2': ""} disabled:bg-disabledColor`} | ||
{...register(id)} | ||
disabled={isDisabled} | ||
/> | ||
{errors[id] ? <p className="text-base text-errorColor mt-2"> | ||
{errors[id].message} | ||
</p> : null} | ||
</div> | ||
) | ||
} | ||
|
||
export default InputEntry; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
interface FiDataType { | ||
bankName: string; | ||
leiID: string; | ||
agencyCode: number; | ||
} | ||
|
||
const fiData: FiDataType[] = [ | ||
{ | ||
bankName: "Suntrust Banks, Inc", | ||
leiID: "7E1PDLW1JLaTSoBS1Go3", | ||
agencyCode: 3 | ||
}, | ||
{ | ||
bankName: "JP Morgan, Inc", | ||
leiID: "8E1ODLE1JLaSVoBS1Bo2", | ||
agencyCode: 4 | ||
}, | ||
{ | ||
bankName: "Bank of America, Inc", | ||
leiID: "3E89DLE1JBaLEoBS1Co1", | ||
agencyCode: 4 | ||
}, | ||
]; | ||
|
||
export type { FiDataType }; | ||
export { fiData }; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
/* eslint-disable jsx-a11y/label-has-associated-control */ | ||
/* eslint-disable react/jsx-props-no-spreading */ | ||
import { zodResolver } from "@hookform/resolvers/zod"; | ||
import useSblAuth from 'api/useSblAuth'; | ||
import type { SubmitHandler } from "react-hook-form"; | ||
import { useForm } from "react-hook-form"; | ||
import { z } from "zod"; | ||
|
||
import ErrorIcon from 'components/ErrorIcon'; | ||
|
||
import Select from "react-select"; | ||
import Step1FormHeader from "./Step1FormHeader"; | ||
|
||
import { Button, Link } from 'design-system-react'; | ||
import InputEntry from "./InputEntry"; | ||
import { fiData } from './ProfileForm.data'; | ||
|
||
const financialInstitutionsSchema = z.object({ | ||
label: z.string(), | ||
value: z.string(), | ||
}); | ||
|
||
type FinancialInstitution = z.infer<typeof financialInstitutionsSchema>; | ||
|
||
const fiDataTypeSchema = z.object({ | ||
bankName: z.string(), | ||
leiID: z.string(), | ||
agencyCode: z.number() | ||
}) | ||
|
||
const fiOptions: FinancialInstitution[] = fiData.map(object => ({ | ||
label: object.bankName, | ||
value: object.leiID, | ||
})); | ||
|
||
const validationSchema = z | ||
.object({ | ||
firstName: z | ||
.string().min(1, { message: "First name is required" }), | ||
lastName: z | ||
.string().min(1, { message: "Last name is required" }), | ||
email: z.string().min(2, { message: "Email is required" }).email({ | ||
message: "Must be a valid email", | ||
}), | ||
financialInstitutions: financialInstitutionsSchema | ||
.array() | ||
.min(1, { message: "Please pick at least one associated financial institution." }), | ||
fiData: fiDataTypeSchema | ||
.array() | ||
.min(1, { message: "You should have associated financial institution information."}) | ||
}); | ||
|
||
type ValidationSchema = z.infer<typeof validationSchema>; | ||
|
||
function Step1Form(): JSX.Element { | ||
const auth = useSblAuth(); | ||
const email = auth.user?.profile.email; | ||
|
||
const defaultValues: ValidationSchema = { | ||
firstName: "", | ||
lastName: "", | ||
email: email ?? "", | ||
financialInstitutions: [], | ||
// fiData: fiData ?? [] | ||
fiData: [] | ||
}; | ||
|
||
const { | ||
register, | ||
handleSubmit, | ||
setValue, | ||
trigger, | ||
getValues, | ||
formState: { errors }, | ||
} = useForm<ValidationSchema>({ | ||
resolver: zodResolver(validationSchema), | ||
defaultValues | ||
}); | ||
|
||
const onSubmit: SubmitHandler<ValidationSchema> = (data) => { | ||
console.log('data:', data); | ||
} | ||
|
||
console.log('errors:', errors) | ||
|
||
|
||
const customStyles = { | ||
control: (provided, state) => ({ | ||
...provided, | ||
outline: state.isFocused ? '0.25rem solid #2491ff !important' : '', | ||
outlineOffset: state.isFocused ? '0 !important' : '' | ||
}), | ||
}; | ||
|
||
return ( | ||
<div className="ml-5 mr-5"> | ||
<div className="max-w-[1200px] mx-auto mb-12"> | ||
<div className="max-w-[770px] mx-auto"> | ||
<Step1FormHeader /> | ||
<form | ||
className="bg-[#F7F8F9] p-[30px] border" | ||
onSubmit={handleSubmit(onSubmit)} | ||
> | ||
<InputEntry label="First name" id="firstName" register={register} errors={errors} isDisabled={false} /> | ||
<InputEntry label="Last name" id="lastName" register={register} errors={errors} isDisabled={false} /> | ||
<InputEntry label="Email address" id="email" register={register} errors={errors} isDisabled> | ||
<p className="">Your email address is automatically pulled in from Login.gov.</p> | ||
</InputEntry> | ||
|
||
<div className="mt-8 mb-9"> | ||
<h4 className="text-[1.125em] font-medium tracking-[inherit] leading-tight mb-2 inline-block w-full">Associated financial institution(s)</h4> | ||
<p className="">Select the financial institution(s) that you are associated with.</p> | ||
<div className="mb-4"> | ||
<Select | ||
classNames={{ | ||
control: (state) => `!rounded-none !border !w-full " : '!border-inherit' }`, | ||
indicatorSeparator: (state) => '!mb-0 !mt-0 !border-inherit', | ||
indicatorsContainer: (state) => '!bg-disabledColor', | ||
dropdownIndicator: (state) => '!text-inherit', | ||
valueContainer: ()=> `${ (errors.financialInstitutions ?? errors.fiData) ? "!border-errorColor !border-2 !border-solid" : ""}`, | ||
}} | ||
options={fiOptions} | ||
isSearchable | ||
placeholder='' | ||
styles={customStyles} | ||
/> | ||
</div> | ||
{errors.fiData ? | ||
<div className="flex flex-row gap-3"> | ||
<ErrorIcon /> | ||
<div className='max-w-[587px]'> | ||
<h4 className='text text-[14px] font-medium mb-[0.35rem] leading-[19px]'>No results found in our database. | ||
</h4> | ||
<p className='text text-[14px] leading-[0.95rem]'>The financial institution/LEI you search for war not found in our database. If you recently registered for an LEI with GLEIF, your registration may still be in process. if you need further assistance please <Link href="#">submit a technical question</Link> to our help desk. | ||
</p> | ||
</div> | ||
</div> | ||
|
||
: null} | ||
|
||
</div> | ||
<Button | ||
appearance="primary" | ||
onClick={async ()=>{ | ||
const passesValidation = await trigger(); | ||
if (passesValidation) { | ||
// TODO: Post the submission | ||
} | ||
console.log("validationResult:", passesValidation) | ||
// console.log("getValues:", getValues()) | ||
// console.log('onclick errors', errors); | ||
}} | ||
label="Submit" | ||
size="default"> | ||
Submit | ||
</Button> | ||
|
||
|
||
</form> | ||
</div> | ||
</div> | ||
</div> | ||
); | ||
} | ||
|
||
export default Step1Form; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { Link } from 'design-system-react'; | ||
|
||
/** | ||
* | ||
* @returns Header for Step1Form | ||
*/ | ||
function Step1FormHeader(): JSX.Element { | ||
return ( | ||
<div className="max-w-[670px]"> | ||
<h1 className="text-[26px] md:text-[30px] font-semibold leading-tight mb-[0.44117647em]">Complete your user profile</h1> | ||
<p className="text-[18px] md:text-[20px] font-normal leading-tight mb-[30px]">In order to complete your user profile and access the filing platform your financial institution must have a Legal Entity Identifier (LEI). Visit the Global LEI Foundation (GLEIF) website for information on how to obtain an LEI for your institution.</p> | ||
<p className="leading-paragraph mb-[30px]"> | ||
In order to begin using the filing platform you must have a Legal Entity identifier (LEI) for your financial institution. Visit the <Link href="#">Global LEI Foundation (GLEIF)</Link> website for more information on how to obtain an LEI. | ||
</p> | ||
<p /> | ||
</div> | ||
) | ||
} | ||
|
||
export default Step1FormHeader; |
Oops, something went wrong.