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

[chore] address feedback for onboarding #90

Merged
merged 8 commits into from
May 24, 2024
8 changes: 7 additions & 1 deletion src/app/onboarding/availability/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export default function Page() {
const onboarding = useGuardedOnboarding();
const { backlinkHref, ebbTo, pageProgress } = useOnboardingNavigation();
const { push } = useRouter();
const [availabilityError, setAvailabilityError] = useState('');
jinkang-0 marked this conversation as resolved.
Show resolved Hide resolved

// scroll to top
useScrollToTop();
Expand Down Expand Up @@ -184,8 +185,13 @@ export default function Page() {
<TextAreaInput
placeholder="I won't be available from..."
defaultValue={field.value ?? ''}
error={fieldState.error?.message}
error={fieldState.error?.message ?? availabilityError}
onChange={newValue => {
setAvailabilityError(
newValue.length > 400
? 'Please keep it within 400 characters'
: '',
);
onboarding.updateProfile({
availability_description: newValue,
});
Expand Down
109 changes: 93 additions & 16 deletions src/app/onboarding/legal-credentials/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client';

import { useEffect, useMemo } from 'react';
import { useEffect, useMemo, useState } from 'react';
import { zodResolver } from '@hookform/resolvers/zod';
import { useRouter } from 'next/navigation';
import { FormProvider, useForm } from 'react-hook-form';
Expand All @@ -17,6 +17,7 @@ import {
import Icon from '@/components/Icon';
import InputDropdown from '@/components/InputDropdown';
import RadioGroup from '@/components/RadioGroup';
import TextAreaInput from '@/components/TextAreaInput';
import TextInput from '@/components/TextInput';
import { usStates } from '@/data/citiesAndStates';
import { attorneyCredentialSchema } from '@/data/formSchemas';
Expand All @@ -34,6 +35,7 @@ export default function Page() {
const onboarding = useGuardedOnboarding();
const { backlinkHref, ebbTo, pageProgress } = useOnboardingNavigation();
const { push } = useRouter();
const [commentError, setCommentError] = useState('');

// scroll to top
useScrollToTop();
Expand All @@ -45,14 +47,21 @@ export default function Page() {
stateBarred: onboarding.profile.state_barred ?? undefined,
barNumber: onboarding.profile.bar_number ?? undefined,
eoirRegistered: onboarding.profile.eoir_registered ?? undefined,
legalCredentialComment:
onboarding.profile.legal_credential_comment ?? undefined,
barred:
onboarding.profile.bar_number === undefined
? undefined
: onboarding.profile.bar_number !== 'Not Barred',
jinkang-0 marked this conversation as resolved.
Show resolved Hide resolved
},
});

const formValues = form.watch();
const isEmpty = useMemo(
() =>
!(formValues.stateBarred && formValues.barNumber) ||
formValues.eoirRegistered === undefined,
formValues.eoirRegistered === undefined ||
(!formValues.barred && !formValues.legalCredentialComment),
[formValues],
);

Expand Down Expand Up @@ -108,8 +117,8 @@ export default function Page() {
/>
</FormControl>
<FormDescription>
If you are barred in multiple states, choose your preferred
state
If you are barred in multiple states, please choose your
preferred state
</FormDescription>
<FormMessage />
</FormItem>
Expand All @@ -118,30 +127,64 @@ export default function Page() {

<FormField
control={form.control}
name="barNumber"
name="barred"
render={({ field, fieldState }) => (
<FormItem>
<FormLabel>
What is your attorney bar number in this state?
</FormLabel>
<FormLabel>Do you have a bar number in this state?</FormLabel>
<FormControl>
<TextInput
errorText={fieldState.error?.message}
placeholder="123456"
type="text"
defaultValue={field.value}
<RadioGroup
name="barred"
defaultValue={formatTruthy(
field.value,
'Yes',
'No',
undefined,
)}
options={['Yes', 'No']}
error={fieldState.error?.message}
onChange={newValue => {
const bool = newValue === 'Yes';
const barNum = bool ? '' : 'Not Barred';
onboarding.updateProfile({
bar_number: newValue,
bar_number: barNum,
});
field.onChange(newValue);
form.setValue('barNumber', barNum);
field.onChange(bool);
}}
/>
</FormControl>
</FormItem>
)}
/>

{formValues.barred && (
<FormField
control={form.control}
name="barNumber"
render={({ field, fieldState }) => (
<FormItem>
<FormLabel>
What is your attorney bar number in this state?
</FormLabel>
<FormControl>
<TextInput
errorText={fieldState.error?.message}
placeholder="123456"
type="text"
defaultValue={field.value}
onChange={newValue => {
onboarding.updateProfile({
bar_number: newValue,
});
field.onChange(newValue);
}}
/>
</FormControl>
</FormItem>
)}
/>
)}

<FormField
control={form.control}
name="eoirRegistered"
Expand All @@ -153,7 +196,7 @@ export default function Page() {
</FormLabel>
<FormControl>
<RadioGroup
name="registered"
name="eoirRegistered"
defaultValue={formatTruthy(
field.value,
'Yes',
Expand All @@ -173,6 +216,40 @@ export default function Page() {
)}
/>

<FormField
control={form.control}
name="legalCredentialComment"
render={({ field, fieldState }) => (
<FormItem>
<FormLabel $required={!formValues.barred}>
Is there anything about your bar status we should know?
{formValues.barred && ' (optional)'}
</FormLabel>
<FormControl>
<TextAreaInput
placeholder="There are some extenuating circumstances with..."
defaultValue={field.value ?? ''}
error={fieldState.error?.message ?? commentError}
onChange={newValue => {
setCommentError(
newValue.length > 400
? 'Please keep it within 400 characters'
: '',
);
onboarding.updateProfile({
legal_credential_comment: newValue,
});
field.onChange(newValue);
}}
/>
</FormControl>
<FormDescription>
For example, if you were formerly barred but is not currently.
jinkang-0 marked this conversation as resolved.
Show resolved Hide resolved
</FormDescription>
</FormItem>
)}
/>

<Flex $gap="40px">
<BigButton type="button" onClick={() => ebbTo(backlinkHref)}>
Back
Expand Down
3 changes: 2 additions & 1 deletion src/components/Buttons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ interface ButtonProps {
const ButtonStyles = css<ButtonProps>`
${sans.style}
appearance: none;
color: ${({ $primaryColor }) => ($primaryColor ? 'white' : COLORS.blueMid)};
color: ${({ $primaryColor, $secondaryColor }) =>
$primaryColor ? 'white' : $secondaryColor || COLORS.blueMid};
background: ${({ $primaryColor }) => $primaryColor || 'white'};
padding: 10px 20px;
border-radius: 5px;
Expand Down
8 changes: 4 additions & 4 deletions src/components/RadioGroup/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,13 @@ export default function RadioGroup({
)}
<GroupContainer>
{options.map(o => (
<RadioLabel key={o} htmlFor={o}>
<RadioLabel key={o} htmlFor={`${name}${o}`}>
<RadioInput
type="radio"
id={o}
id={`${name}${o}`}
name={name}
value={value}
checked={value ? value === o : undefined}
value={`${name}${o}`}
checked={value ? value === `${name}${o}` : undefined}
defaultChecked={defaultValue === o}
onChange={() => handleChange(o)}
/>
Expand Down
77 changes: 68 additions & 9 deletions src/components/SettingsSection/RolesSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import DateInput from '../DateInput';
import { FormMessage } from '../Form';
import InputDropdown from '../InputDropdown';
import RadioGroup from '../RadioGroup';
import TextAreaInput from '../TextAreaInput';
import TextInput from '../TextInput';

const getFormDefaults = (
Expand All @@ -50,6 +51,11 @@ const getFormDefaults = (
: undefined,
stateBarred: profile.state_barred,
roles: defaultRole,
barred:
profile.bar_number === undefined
? undefined
: profile.bar_number !== 'Not Barred',
legalCredentialComment: profile.legal_credential_comment,
};

return defaultValue;
Expand Down Expand Up @@ -104,14 +110,15 @@ export default function RolesSection() {
eoir_registered:
isAttorney || isLegalFellow ? values.eoirRegistered : null,
expected_bar_date: isLegalFellow ? values.expectedBarDate : null,
legal_credential_comment: values.legalCredentialComment || null,
}),
profile.setRoles(rolesToUpdate),
]);

setIsEditing(false);
};

const { roles } = form.watch();
const { roles, barred } = form.watch();
const isAttorney = roles === 'ATTORNEY' || roles === 'ATTORNEY,INTERPRETER';
const isLegalFellow =
roles === 'LEGAL_FELLOW' || roles === 'LEGAL_FELLOW,INTERPRETER';
Expand Down Expand Up @@ -227,18 +234,46 @@ export default function RolesSection() {

<SettingField
control={form.control}
name="barNumber"
label="Attorney Bar Number"
name="barred"
label="Has Bar Number"
extractValue={v => formatTruthy(v, 'Yes', 'No', 'N/A')}
render={({ field, fieldState }) => (
<TextInput
errorText={fieldState.error?.message}
placeholder="123456"
type="text"
defaultValue={field.value ?? ''}
onChange={field.onChange}
<RadioGroup
name="barred"
defaultValue={formatTruthy(
field.value,
'Yes',
'No',
undefined,
)}
options={['Yes', 'No']}
error={fieldState.error?.message}
onChange={newValue => {
const bool = newValue === 'Yes';
const barNum = bool ? '' : 'Not Barred';
form.setValue('barNumber', barNum);
field.onChange(bool);
}}
/>
)}
/>

{barred && (
<SettingField
control={form.control}
name="barNumber"
label="Attorney Bar Number"
render={({ field, fieldState }) => (
<TextInput
errorText={fieldState.error?.message}
placeholder="123456"
type="text"
defaultValue={field.value ?? ''}
onChange={field.onChange}
/>
)}
/>
)}
</>
)}

Expand Down Expand Up @@ -300,6 +335,30 @@ export default function RolesSection() {
)}
/>
) : null}

{isAttorney && (
<SettingField
control={form.control}
name="legalCredentialComment"
label={
barred
? 'Additional Information (optional)'
: 'Additional Information'
}
required={!barred}
extractValue={v => v ?? 'N/A'}
render={({ field, fieldState }) => (
<TextAreaInput
placeholder="There are some extenuating circumstances with..."
defaultValue={field.value ?? ''}
error={fieldState.error?.message}
onChange={newValue => {
field.onChange(newValue);
}}
/>
)}
/>
)}
</SettingSection>
</form>
</FormProvider>
Expand Down
8 changes: 7 additions & 1 deletion src/components/SettingsSection/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { createContext, useContext, useMemo } from 'react';
import { ControllerProps, FieldPath, FieldValues } from 'react-hook-form';
import COLORS from '@/styles/colors';
import { Flex } from '@/styles/containers';
import { Spinner } from '@/styles/spinner';
import { H2, P } from '@/styles/text';
Expand Down Expand Up @@ -54,7 +55,12 @@ export function SettingSection({

{isEditing ? (
<Flex $gap="1.25rem" $justify="end">
<Button type="button" onClick={() => cancelEdit?.()}>
<Button
type="button"
$secondaryColor={COLORS.redDark}
$tertiaryColor={COLORS.redDarker}
jinkang-0 marked this conversation as resolved.
Show resolved Hide resolved
onClick={() => cancelEdit?.()}
>
Discard Changes
</Button>
<BlueButton type="submit" disabled={isSubmitting}>
Expand Down
Loading
Loading