[offers][feat] Add plaintext breadcrumb (#364)

This commit is contained in:
Ai Ling
2022-10-12 02:26:31 +08:00
committed by GitHub
parent 9285847bb7
commit d59da5d186
4 changed files with 73 additions and 31 deletions

View File

@ -0,0 +1,23 @@
type BreadcrumbsProps = Readonly<{
currentStep: number;
stepLabels: Array<string>;
}>;
export function Breadcrumbs({ stepLabels, currentStep }: BreadcrumbsProps) {
return (
<div className="flex space-x-1">
{stepLabels.map((label, index) => (
<>
{index === currentStep ? (
<p className="text-sm text-purple-700">{label}</p>
) : (
<p className="text-sm text-gray-400">{label}</p>
)}
{index !== stepLabels.length - 1 && (
<p className="text-sm text-gray-400">{'>'}</p>
)}
</>
))}
</div>
);
}

View File

@ -67,20 +67,20 @@ type SpecificYoe = {
}; };
type FullTimeExperience = { type FullTimeExperience = {
level: string; level?: string;
totalCompensation: Money; totalCompensation?: Money;
}; };
type InternshipExperience = { type InternshipExperience = {
monthlySalary: Money; monthlySalary?: Money;
}; };
type GeneralExperience = { type GeneralExperience = {
companyId: string; companyId?: string;
durationInMonths: number; durationInMonths?: number;
jobType: string; jobType?: string;
specialization: string; specialization?: string;
title: string; title?: string;
}; };
export type Experience = export type Experience =
@ -88,26 +88,26 @@ export type Experience =
| (GeneralExperience & InternshipExperience); | (GeneralExperience & InternshipExperience);
type Education = { type Education = {
endDate: Date; endDate?: Date;
field: string; field?: string;
school: string; school?: string;
startDate: Date; startDate?: Date;
type: string; type?: string;
}; };
type BackgroundFormData = { type BackgroundFormData = {
educations: Array<Education>; educations: Array<Education>;
experiences: Array<Experience>; experiences: Array<Experience>;
specificYoes: Array<SpecificYoe>; specificYoes: Array<SpecificYoe>;
totalYoe: number; totalYoe?: number;
}; };
export type SubmitOfferFormData = { export type OfferProfileFormData = {
background: BackgroundFormData; background: BackgroundFormData;
offers: Array<OfferDetailsFormData>; offers: Array<OfferDetailsFormData>;
}; };
export type OfferPostData = { export type OfferProfilePostData = {
background: BackgroundFormData; background: BackgroundFormData;
offers: Array<OfferDetailsPostData>; offers: Array<OfferDetailsPostData>;
}; };

View File

@ -4,35 +4,34 @@ import { FormProvider, useForm } from 'react-hook-form';
import { ArrowLeftIcon, ArrowRightIcon } from '@heroicons/react/20/solid'; import { ArrowLeftIcon, ArrowRightIcon } from '@heroicons/react/20/solid';
import { Button } from '@tih/ui'; import { Button } from '@tih/ui';
import { Breadcrumbs } from '~/components/offers/Breadcrumb';
import BackgroundForm from '~/components/offers/forms/BackgroundForm'; import BackgroundForm from '~/components/offers/forms/BackgroundForm';
import OfferAnalysis from '~/components/offers/forms/OfferAnalysis'; import OfferAnalysis from '~/components/offers/forms/OfferAnalysis';
import OfferDetailsForm from '~/components/offers/forms/OfferDetailsForm'; import OfferDetailsForm from '~/components/offers/forms/OfferDetailsForm';
import OfferProfileSave from '~/components/offers/forms/OfferProfileSave'; import OfferProfileSave from '~/components/offers/forms/OfferProfileSave';
import type { import type {
OfferDetailsFormData, OfferDetailsFormData,
SubmitOfferFormData, OfferProfileFormData,
} from '~/components/offers/types'; } from '~/components/offers/types';
import { JobType } from '~/components/offers/types';
import type { Month } from '~/components/shared/MonthYearPicker'; import type { Month } from '~/components/shared/MonthYearPicker';
import { cleanObject, removeInvalidMoneyData } from '~/utils/offers/form'; import { cleanObject, removeInvalidMoneyData } from '~/utils/offers/form';
import { getCurrentMonth, getCurrentYear } from '~/utils/offers/time'; import { getCurrentMonth, getCurrentYear } from '~/utils/offers/time';
import { trpc } from '~/utils/trpc'; import { trpc } from '~/utils/trpc';
function Breadcrumbs() {
return (
<p className="mb-4 text-right text-sm text-gray-400">
{'Offer details > Background > Analysis > Save'}
</p>
);
}
const defaultOfferValues = { const defaultOfferValues = {
background: {
educations: [],
experiences: [{ jobType: JobType.FullTime }],
specificYoes: [],
},
offers: [ offers: [
{ {
comments: '', comments: '',
companyId: '', companyId: '',
job: {}, job: {},
jobType: 'FULLTIME', jobType: JobType.FullTime,
location: '', location: '',
monthYearReceived: { monthYearReceived: {
month: getCurrentMonth() as Month, month: getCurrentMonth() as Month,
@ -47,11 +46,12 @@ type FormStep = {
component: JSX.Element; component: JSX.Element;
hasNext: boolean; hasNext: boolean;
hasPrevious: boolean; hasPrevious: boolean;
label: string;
}; };
export default function OffersSubmissionPage() { export default function OffersSubmissionPage() {
const [formStep, setFormStep] = useState(0); const [formStep, setFormStep] = useState(0);
const formMethods = useForm<SubmitOfferFormData>({ const formMethods = useForm<OfferProfileFormData>({
defaultValues: defaultOfferValues, defaultValues: defaultOfferValues,
mode: 'all', mode: 'all',
}); });
@ -62,20 +62,30 @@ export default function OffersSubmissionPage() {
component: <OfferDetailsForm key={0} />, component: <OfferDetailsForm key={0} />,
hasNext: true, hasNext: true,
hasPrevious: false, hasPrevious: false,
label: 'Offer details',
}, },
{ {
component: <BackgroundForm key={1} />, component: <BackgroundForm key={1} />,
hasNext: false, hasNext: false,
hasPrevious: true, hasPrevious: true,
label: 'Background',
},
{
component: <OfferAnalysis key={2} />,
hasNext: true,
hasPrevious: false,
label: 'Analysis',
}, },
{ component: <OfferAnalysis key={2} />, hasNext: true, hasPrevious: false },
{ {
component: <OfferProfileSave key={3} />, component: <OfferProfileSave key={3} />,
hasNext: false, hasNext: false,
hasPrevious: false, hasPrevious: false,
label: 'Save',
}, },
]; ];
const formStepsLabels = formSteps.map((step) => step.label);
const nextStep = async (currStep: number) => { const nextStep = async (currStep: number) => {
if (currStep === 0) { if (currStep === 0) {
const result = await trigger('offers'); const result = await trigger('offers');
@ -98,7 +108,7 @@ export default function OffersSubmissionPage() {
}, },
}); });
const onSubmit: SubmitHandler<SubmitOfferFormData> = async (data) => { const onSubmit: SubmitHandler<OfferProfileFormData> = async (data) => {
const result = await trigger(); const result = await trigger();
if (!result) { if (!result) {
return; return;
@ -118,6 +128,9 @@ export default function OffersSubmissionPage() {
(specificYoe) => specificYoe.domain && specificYoe.yoe > 0, (specificYoe) => specificYoe.domain && specificYoe.yoe > 0,
); );
if (Object.entries(postData.background.experiences[0]).length === 1) {
postData.background.experiences = [];
}
createMutation.mutate(postData); createMutation.mutate(postData);
}; };
@ -125,7 +138,9 @@ export default function OffersSubmissionPage() {
<div className="fixed h-full w-full overflow-y-scroll"> <div className="fixed h-full w-full overflow-y-scroll">
<div className="mb-20 flex justify-center"> <div className="mb-20 flex justify-center">
<div className="my-5 block w-full max-w-screen-md rounded-lg bg-white py-10 px-10 shadow-lg"> <div className="my-5 block w-full max-w-screen-md rounded-lg bg-white py-10 px-10 shadow-lg">
<Breadcrumbs /> <div className="mb-4 flex justify-end">
<Breadcrumbs currentStep={formStep} stepLabels={formStepsLabels} />
</div>
<FormProvider {...formMethods}> <FormProvider {...formMethods}>
<form onSubmit={handleSubmit(onSubmit)}> <form onSubmit={handleSubmit(onSubmit)}>
{formSteps[formStep].component} {formSteps[formStep].component}

View File

@ -46,7 +46,11 @@ export function removeInvalidMoneyData(object: any) {
if (k === 'currency') { if (k === 'currency') {
if (object.value === undefined) { if (object.value === undefined) {
delete object[k]; delete object[k];
} else if (object.value === null || object.value !== object.value) { } else if (
object.value === null ||
object.value !== object.value ||
object.value === ''
) {
delete object[k]; delete object[k];
delete object.value; delete object.value;
} }