[offers][fix] Add warning dialogs

pull/366/head
Ai Ling 3 years ago
parent 1eed5227c4
commit 7cb84a58ca

@ -1,14 +1,10 @@
import { useState } from 'react'; import { useState } from 'react';
import type { import type { FieldValues, UseFieldArrayReturn } from 'react-hook-form';
FieldValues,
UseFieldArrayRemove,
UseFieldArrayReturn,
} from 'react-hook-form';
import { useFormContext } from 'react-hook-form'; import { useFormContext } from 'react-hook-form';
import { useFieldArray } from 'react-hook-form'; import { useFieldArray } from 'react-hook-form';
import { PlusIcon } from '@heroicons/react/20/solid'; import { PlusIcon } from '@heroicons/react/20/solid';
import { TrashIcon } from '@heroicons/react/24/outline'; import { TrashIcon } from '@heroicons/react/24/outline';
import { Button } from '@tih/ui'; import { Button, Dialog } from '@tih/ui';
import FormMonthYearPicker from './components/FormMonthYearPicker'; import FormMonthYearPicker from './components/FormMonthYearPicker';
import FormSelect from './components/FormSelect'; import FormSelect from './components/FormSelect';
@ -26,17 +22,18 @@ import type {
FullTimeOfferDetailsFormData, FullTimeOfferDetailsFormData,
InternshipOfferDetailsFormData, InternshipOfferDetailsFormData,
} from '../types'; } from '../types';
import { JobTypeLabel } from '../types';
import { JobType } from '../types'; import { JobType } from '../types';
import { CURRENCY_OPTIONS } from '../../../utils/offers/currency/CurrencyEnum'; import { CURRENCY_OPTIONS } from '../../../utils/offers/currency/CurrencyEnum';
type FullTimeOfferDetailsFormProps = Readonly<{ type FullTimeOfferDetailsFormProps = Readonly<{
index: number; index: number;
remove: UseFieldArrayRemove; setDialogOpen: (isOpen: boolean) => void;
}>; }>;
function FullTimeOfferDetailsForm({ function FullTimeOfferDetailsForm({
index, index,
remove, setDialogOpen,
}: FullTimeOfferDetailsFormProps) { }: FullTimeOfferDetailsFormProps) {
const { register, formState } = useFormContext<{ const { register, formState } = useFormContext<{
offers: Array<FullTimeOfferDetailsFormData>; offers: Array<FullTimeOfferDetailsFormData>;
@ -228,7 +225,7 @@ function FullTimeOfferDetailsForm({
icon={TrashIcon} icon={TrashIcon}
label="Delete" label="Delete"
variant="secondary" variant="secondary"
onClick={() => remove(index)} onClick={() => setDialogOpen(true)}
/> />
)} )}
</div> </div>
@ -236,53 +233,14 @@ function FullTimeOfferDetailsForm({
); );
} }
type OfferDetailsFormArrayProps = Readonly<{
fieldArrayValues: UseFieldArrayReturn<FieldValues, 'offers', 'id'>;
jobType: JobType;
}>;
function OfferDetailsFormArray({
fieldArrayValues,
jobType,
}: OfferDetailsFormArrayProps) {
const { append, remove, fields } = fieldArrayValues;
return (
<div>
{fields.map((item, index) =>
jobType === JobType.FullTime ? (
<FullTimeOfferDetailsForm
key={`offer.${item.id}`}
index={index}
remove={remove}
/>
) : (
<InternshipOfferDetailsForm
key={`offer.${item.id}`}
index={index}
remove={remove}
/>
),
)}
<Button
display="block"
icon={PlusIcon}
label="Add another offer"
size="lg"
variant="tertiary"
onClick={() => append({})}
/>
</div>
);
}
type InternshipOfferDetailsFormProps = Readonly<{ type InternshipOfferDetailsFormProps = Readonly<{
index: number; index: number;
remove: UseFieldArrayRemove; setDialogOpen: (isOpen: boolean) => void;
}>; }>;
function InternshipOfferDetailsForm({ function InternshipOfferDetailsForm({
index, index,
remove, setDialogOpen,
}: InternshipOfferDetailsFormProps) { }: InternshipOfferDetailsFormProps) {
const { register, formState } = useFormContext<{ const { register, formState } = useFormContext<{
offers: Array<InternshipOfferDetailsFormData>; offers: Array<InternshipOfferDetailsFormData>;
@ -409,7 +367,9 @@ function InternshipOfferDetailsForm({
icon={TrashIcon} icon={TrashIcon}
label="Delete" label="Delete"
variant="secondary" variant="secondary"
onClick={() => remove(index)} onClick={() => {
setDialogOpen(true);
}}
/> />
)} )}
</div> </div>
@ -417,20 +377,99 @@ function InternshipOfferDetailsForm({
); );
} }
type OfferDetailsFormArrayProps = Readonly<{
fieldArrayValues: UseFieldArrayReturn<FieldValues, 'offers', 'id'>;
jobType: JobType;
}>;
function OfferDetailsFormArray({
fieldArrayValues,
jobType,
}: OfferDetailsFormArrayProps) {
const { append, remove, fields } = fieldArrayValues;
const [isDialogOpen, setDialogOpen] = useState(false);
return (
<div>
{fields.map((item, index) => {
return (
<>
{jobType === JobType.FullTime ? (
<FullTimeOfferDetailsForm
key={`offer.${item.id}`}
index={index}
setDialogOpen={setDialogOpen}
/>
) : (
<InternshipOfferDetailsForm
key={`offer.${item.id}`}
index={index}
setDialogOpen={setDialogOpen}
/>
)}
<Dialog
isShown={isDialogOpen}
primaryButton={
<Button
display="block"
label="OK"
variant="primary"
onClick={() => {
remove(index);
setDialogOpen(false);
}}
/>
}
secondaryButton={
<Button
display="block"
label="Cancel"
variant="tertiary"
onClick={() => setDialogOpen(false)}
/>
}
title="Remove this offer"
onClose={() => setDialogOpen(false)}>
<p>
Are you sure you want to remove this offer? This action cannot
be reversed.
</p>
</Dialog>
</>
);
})}
<Button
display="block"
icon={PlusIcon}
label="Add another offer"
size="lg"
variant="tertiary"
onClick={() => append({})}
/>
</div>
);
}
export default function OfferDetailsForm() { export default function OfferDetailsForm() {
const [jobType, setJobType] = useState(JobType.FullTime); const [jobType, setJobType] = useState(JobType.FullTime);
const [isDialogOpen, setDialogOpen] = useState(false);
const { control, register } = useFormContext(); const { control, register } = useFormContext();
const fieldArrayValues = useFieldArray({ control, name: 'offers' }); const fieldArrayValues = useFieldArray({ control, name: 'offers' });
const changeJobType = (jobTypeChosen: JobType) => () => { const toggleJobType = () => {
if (jobType === jobTypeChosen) { if (jobType === JobType.FullTime) {
return; setJobType(JobType.Internship);
} else {
setJobType(JobType.FullTime);
} }
setJobType(jobTypeChosen);
fieldArrayValues.remove(); fieldArrayValues.remove();
}; };
const switchJobTypeLabel = () =>
jobType === JobType.FullTime
? JobTypeLabel.INTERNSHIP
: JobTypeLabel.FULLTIME;
return ( return (
<div className="mb-5"> <div className="mb-5">
<h5 className="mb-8 text-center text-4xl font-bold text-gray-900"> <h5 className="mb-8 text-center text-4xl font-bold text-gray-900">
@ -440,20 +479,30 @@ export default function OfferDetailsForm() {
<div className="mx-5 w-1/3"> <div className="mx-5 w-1/3">
<Button <Button
display="block" display="block"
label="Full-time" label={JobTypeLabel.FULLTIME}
size="md" size="md"
variant={jobType === JobType.FullTime ? 'secondary' : 'tertiary'} variant={jobType === JobType.FullTime ? 'secondary' : 'tertiary'}
onClick={changeJobType(JobType.FullTime)} onClick={() => {
if (jobType === JobType.FullTime) {
return;
}
setDialogOpen(true);
}}
{...register(`offers.${0}.jobType`)} {...register(`offers.${0}.jobType`)}
/> />
</div> </div>
<div className="mx-5 w-1/3"> <div className="mx-5 w-1/3">
<Button <Button
display="block" display="block"
label="Internship" label={JobTypeLabel.INTERNSHIP}
size="md" size="md"
variant={jobType === JobType.Internship ? 'secondary' : 'tertiary'} variant={jobType === JobType.Internship ? 'secondary' : 'tertiary'}
onClick={changeJobType(JobType.Internship)} onClick={() => {
if (jobType === JobType.Internship) {
return;
}
setDialogOpen(true);
}}
{...register(`offers.${0}.jobType`)} {...register(`offers.${0}.jobType`)}
/> />
</div> </div>
@ -462,6 +511,32 @@ export default function OfferDetailsForm() {
fieldArrayValues={fieldArrayValues} fieldArrayValues={fieldArrayValues}
jobType={jobType} jobType={jobType}
/> />
<Dialog
isShown={isDialogOpen}
primaryButton={
<Button
display="block"
label="Switch"
variant="primary"
onClick={() => {
toggleJobType();
setDialogOpen(false);
}}
/>
}
secondaryButton={
<Button
display="block"
label="Cancel"
variant="tertiary"
onClick={() => setDialogOpen(false)}
/>
}
title={`Switch to ${switchJobTypeLabel()}`}
onClose={() => setDialogOpen(false)}>
{`Are you sure you want to switch to ${switchJobTypeLabel()}? The data you
entered in the ${JobTypeLabel[jobType]} section will disappear.`}
</Dialog>
</div> </div>
); );
} }

@ -1,4 +1,3 @@
/* eslint-disable no-shadow */
import type { MonthYear } from '~/components/shared/MonthYearPicker'; import type { MonthYear } from '~/components/shared/MonthYearPicker';
/* /*
@ -10,6 +9,11 @@ export enum JobType {
Internship = 'INTERNSHIP', Internship = 'INTERNSHIP',
} }
export const JobTypeLabel = {
FULLTIME: 'Full-time',
INTERNSHIP: 'Internship',
};
export enum EducationBackgroundType { export enum EducationBackgroundType {
Bachelor = 'Bachelor', Bachelor = 'Bachelor',
Diploma = 'Diploma', Diploma = 'Diploma',

Loading…
Cancel
Save