[resumes][feat] update submit form to be more compact (#414)

pull/415/head
Keane Chan 2 years ago committed by GitHub
parent 77d0714e33
commit 7bd6b0eeac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -60,7 +60,7 @@ export const SORT_OPTIONS: Record<string, string> = {
topComments: 'Most Comments', topComments: 'Most Comments',
}; };
export const ROLE: Array<FilterOption<RoleFilter>> = [ export const ROLES: Array<FilterOption<RoleFilter>> = [
{ {
label: 'Full-Stack Engineer', label: 'Full-Stack Engineer',
value: 'Full-Stack Engineer', value: 'Full-Stack Engineer',
@ -72,7 +72,7 @@ export const ROLE: Array<FilterOption<RoleFilter>> = [
{ label: 'Android Engineer', value: 'Android Engineer' }, { label: 'Android Engineer', value: 'Android Engineer' },
]; ];
export const EXPERIENCE: Array<FilterOption<ExperienceFilter>> = [ export const EXPERIENCES: Array<FilterOption<ExperienceFilter>> = [
{ label: 'Freshman', value: 'Freshman' }, { label: 'Freshman', value: 'Freshman' },
{ label: 'Sophomore', value: 'Sophomore' }, { label: 'Sophomore', value: 'Sophomore' },
{ label: 'Junior', value: 'Junior' }, { label: 'Junior', value: 'Junior' },
@ -91,16 +91,16 @@ export const EXPERIENCE: Array<FilterOption<ExperienceFilter>> = [
}, },
]; ];
export const LOCATION: Array<FilterOption<LocationFilter>> = [ export const LOCATIONS: Array<FilterOption<LocationFilter>> = [
{ label: 'Singapore', value: 'Singapore' }, { label: 'Singapore', value: 'Singapore' },
{ label: 'United States', value: 'United States' }, { label: 'United States', value: 'United States' },
{ label: 'India', value: 'India' }, { label: 'India', value: 'India' },
]; ];
export const INITIAL_FILTER_STATE: FilterState = { export const INITIAL_FILTER_STATE: FilterState = {
experience: Object.values(EXPERIENCE).map(({ value }) => value), experience: Object.values(EXPERIENCES).map(({ value }) => value),
location: Object.values(LOCATION).map(({ value }) => value), location: Object.values(LOCATIONS).map(({ value }) => value),
role: Object.values(ROLE).map(({ value }) => value), role: Object.values(ROLES).map(({ value }) => value),
}; };
export const SHORTCUTS: Array<Shortcut> = [ export const SHORTCUTS: Array<Shortcut> = [

@ -27,11 +27,11 @@ import type {
} from '~/components/resumes/browse/resumeFilters'; } from '~/components/resumes/browse/resumeFilters';
import { import {
BROWSE_TABS_VALUES, BROWSE_TABS_VALUES,
EXPERIENCE, EXPERIENCES,
INITIAL_FILTER_STATE, INITIAL_FILTER_STATE,
isInitialFilterState, isInitialFilterState,
LOCATION, LOCATIONS,
ROLE, ROLES,
SHORTCUTS, SHORTCUTS,
SORT_OPTIONS, SORT_OPTIONS,
} from '~/components/resumes/browse/resumeFilters'; } from '~/components/resumes/browse/resumeFilters';
@ -51,17 +51,17 @@ const filters: Array<Filter> = [
{ {
id: 'role', id: 'role',
label: 'Role', label: 'Role',
options: ROLE, options: ROLES,
}, },
{ {
id: 'experience', id: 'experience',
label: 'Experience', label: 'Experience',
options: EXPERIENCE, options: EXPERIENCES,
}, },
{ {
id: 'location', id: 'location',
label: 'Location', label: 'Location',
options: LOCATION, options: LOCATIONS,
}, },
]; ];

@ -18,11 +18,10 @@ import {
TextInput, TextInput,
} from '@tih/ui'; } from '@tih/ui';
import type { Filter } from '~/components/resumes/browse/resumeFilters';
import { import {
EXPERIENCE, EXPERIENCES,
LOCATION, LOCATIONS,
ROLE, ROLES,
} from '~/components/resumes/browse/resumeFilters'; } from '~/components/resumes/browse/resumeFilters';
import SubmissionGuidelines from '~/components/resumes/submit-form/SubmissionGuidelines'; import SubmissionGuidelines from '~/components/resumes/submit-form/SubmissionGuidelines';
@ -47,12 +46,6 @@ type IFormInput = {
title: string; title: string;
}; };
const selectors: Array<Filter> = [
{ id: 'role', label: 'Role', options: ROLE },
{ id: 'experience', label: 'Experience Level', options: EXPERIENCE },
{ id: 'location', label: 'Location', options: LOCATION },
];
type InitFormDetails = { type InitFormDetails = {
additionalInfo?: string; additionalInfo?: string;
experience: string; experience: string;
@ -261,138 +254,153 @@ export default function SubmitResumeForm({
onClose={() => setIsDialogShown(false)}> onClose={() => setIsDialogShown(false)}>
Note that your current input will not be saved! Note that your current input will not be saved!
</Dialog> </Dialog>
<div className="mx-20 space-y-4 py-8"> <form
<form onSubmit={handleSubmit(onSubmit)}> className="mt-8 w-full max-w-screen-lg space-y-6 self-center rounded-lg bg-white p-10 shadow-lg"
<h1 className="mb-4 text-2xl font-bold">Upload a resume</h1> onSubmit={handleSubmit(onSubmit)}>
{/* Title Section */} <h1 className="mb-4 text-center text-2xl font-semibold">
<div className="mb-4"> {isNewForm ? 'Upload a resume' : 'Update details'}
<TextInput </h1>
{...register('title', { required: true })} {/* Title Section */}
disabled={isLoading} <TextInput
label="Title" {...register('title', { required: true })}
placeholder={TITLE_PLACEHOLDER} disabled={isLoading}
required={true} label="Title"
onChange={(val) => setValue('title', val)} placeholder={TITLE_PLACEHOLDER}
/> required={true}
</div> onChange={(val) => setValue('title', val)}
{/* Selectors */} />
{selectors.map((item) => ( <div className="flex gap-12">
<div key={item.id} className="mb-4"> <Select
<Select {...register('role', { required: true })}
{...register(item.id, { required: true })} defaultValue={undefined}
disabled={isLoading} disabled={isLoading}
label={item.label} label="Role"
options={item.options} options={ROLES}
required={true} placeholder=" "
onChange={(val) => setValue(item.id, val)} required={true}
/> onChange={(val) => setValue('role', val)}
</div> />
))} <Select
{/* Upload resume form */} {...register('experience', { required: true })}
{isNewForm && ( disabled={isLoading}
<> label="Experience Level"
<p className="text-sm font-medium text-slate-700"> options={EXPERIENCES}
Upload resume (PDF format) placeholder=" "
<span aria-hidden="true" className="text-danger-500"> required={true}
{' '} onChange={(val) => setValue('experience', val)}
* />
</span> </div>
</p> <Select
<div className="mb-4"> {...register('location', { required: true })}
<div disabled={isLoading}
{...getRootProps()} label="Location"
className={clsx( options={LOCATIONS}
fileUploadError placeholder=" "
? 'border-danger-600' required={true}
: 'border-gray-300', onChange={(val) => setValue('location', val)}
'mt-2 flex cursor-pointer justify-center rounded-md border-2 border-dashed bg-gray-100 px-6 pt-5 pb-6', />
)}> {/* Upload resume form */}
<div className="space-y-1 text-center"> {isNewForm && (
{resumeFile == null ? ( <>
<ArrowUpCircleIcon className="m-auto h-10 w-10 text-indigo-500" /> <p className="text-sm font-medium text-slate-700">
) : ( Upload resume (PDF format)
<p <span aria-hidden="true" className="text-danger-500">
className="cursor-pointer underline underline-offset-1 hover:text-indigo-600" {' '}
onClick={onClickDownload}> *
{resumeFile.name} </span>
</p> </p>
)} <div className="mb-4">
<div className="flex items-center text-sm"> <div
<label {...getRootProps()}
className="rounded-md focus-within:outline-none focus-within:ring-2 focus-within:ring-indigo-500 focus-within:ring-offset-2" className={clsx(
htmlFor="file-upload"> fileUploadError ? 'border-danger-600' : 'border-gray-300',
<span className="mt-2 font-medium"> 'mt-2 flex cursor-pointer justify-center rounded-md border-2 border-dashed bg-gray-100 px-6 pt-5 pb-6',
Drop file here )}>
</span> <div className="space-y-1 text-center">
<span className="mr-1 ml-1 font-light">or</span> {resumeFile == null ? (
<span className="cursor-pointer font-medium text-indigo-600 hover:text-indigo-400"> <ArrowUpCircleIcon className="m-auto h-10 w-10 text-indigo-500" />
{resumeFile == null ) : (
? 'Select file' <p
: 'Replace file'} className="cursor-pointer underline underline-offset-1 hover:text-indigo-600"
</span> onClick={onClickDownload}>
<input {resumeFile.name}
{...register('file', { required: true })}
{...getInputProps()}
accept="application/pdf"
className="sr-only"
disabled={isLoading}
id="file-upload"
name="file-upload"
type="file"
/>
</label>
</div>
<p className="text-xs text-gray-500">
PDF up to {FILE_SIZE_LIMIT_MB}MB
</p> </p>
)}
<div className="flex items-center text-sm">
<label
className="rounded-md focus-within:outline-none focus-within:ring-2 focus-within:ring-indigo-500 focus-within:ring-offset-2"
htmlFor="file-upload">
<span className="mt-2 font-medium">
Drop file here
</span>
<span className="mr-1 ml-1 font-light">or</span>
<span className="cursor-pointer font-medium text-indigo-600 hover:text-indigo-400">
{resumeFile == null
? 'Select file'
: 'Replace file'}
</span>
<input
{...register('file', { required: true })}
{...getInputProps()}
accept="application/pdf"
className="sr-only"
disabled={isLoading}
id="file-upload"
name="file-upload"
type="file"
/>
</label>
</div> </div>
</div> <p className="text-xs text-gray-500">
{fileUploadError && ( PDF up to {FILE_SIZE_LIMIT_MB}MB
<p className="text-danger-600 text-sm">
{fileUploadError}
</p> </p>
)} </div>
</div> </div>
</> {fileUploadError && (
)} <p className="text-danger-600 text-sm">{fileUploadError}</p>
{/* Additional Info Section */} )}
<div className="mb-8"> </div>
<TextArea </>
{...register('additionalInfo')} )}
{/* Additional Info Section */}
<TextArea
{...register('additionalInfo')}
disabled={isLoading}
label="Additional Information"
placeholder={ADDITIONAL_INFO_PLACEHOLDER}
onChange={(val) => setValue('additionalInfo', val)}
/>
{/* Submission Guidelines */}
{isNewForm && (
<>
<SubmissionGuidelines />
<CheckboxInput
{...register('isChecked', { required: true })}
disabled={isLoading} disabled={isLoading}
label="Additional Information" label="I have read and will follow the guidelines stated."
placeholder={ADDITIONAL_INFO_PLACEHOLDER} onChange={(val) => setValue('isChecked', val)}
onChange={(val) => setValue('additionalInfo', val)}
/> />
</div> </>
{/* Submission Guidelines */} )}
<SubmissionGuidelines /> {/* Clear and Submit Buttons */}
<CheckboxInput <div className="flex justify-end gap-4">
{...register('isChecked', { required: true })} <Button
addonPosition="start"
disabled={isLoading} disabled={isLoading}
label="I have read and will follow the guidelines stated." label={isNewForm ? 'Clear' : 'Cancel'}
onChange={(val) => setValue('isChecked', val)} variant="tertiary"
onClick={onClickClear}
/> />
{/* Clear and Submit Buttons */} <Button
<div className="mt-4 flex justify-end gap-4"> addonPosition="start"
<Button disabled={isLoading}
addonPosition="start" isLoading={isLoading}
disabled={isLoading} label="Submit"
label={isNewForm ? 'Clear' : 'Cancel'} type="submit"
variant="tertiary" variant="primary"
onClick={onClickClear} />
/> </div>
<Button </form>
addonPosition="start"
disabled={isLoading}
isLoading={isLoading}
label="Submit"
type="submit"
variant="primary"
/>
</div>
</form>
</div>
</section> </section>
</main> </main>
</> </>

@ -10,7 +10,7 @@ module.exports = {
sans: ['Inter var', ...defaultTheme.fontFamily.sans], sans: ['Inter var', ...defaultTheme.fontFamily.sans],
}, },
colors: { colors: {
primary: colors.purple, primary: colors.indigo,
danger: colors.rose, danger: colors.rose,
info: colors.sky, info: colors.sky,
success: colors.emerald, success: colors.emerald,

Loading…
Cancel
Save