mirror of
https://github.com/yangshun/tech-interview-handbook.git
synced 2025-07-18 12:02:11 +08:00
[offers][fix] tweak submit offer job type selector (#487)
This commit is contained in:
50
apps/portal/src/components/offers/JobTypeTabs.tsx
Normal file
50
apps/portal/src/components/offers/JobTypeTabs.tsx
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import clsx from 'clsx';
|
||||||
|
import { JobType } from '@prisma/client';
|
||||||
|
|
||||||
|
import { JobTypeLabel } from './types';
|
||||||
|
|
||||||
|
type Props = Readonly<{
|
||||||
|
onChange: (jobType: JobType) => void;
|
||||||
|
value: JobType;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
const tabs = [
|
||||||
|
{
|
||||||
|
label: JobTypeLabel.FULLTIME,
|
||||||
|
value: JobType.FULLTIME,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: JobTypeLabel.INTERN,
|
||||||
|
value: JobType.INTERN,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function JobTypeTabs({ value, onChange }: Props) {
|
||||||
|
return (
|
||||||
|
<div className="block">
|
||||||
|
<nav
|
||||||
|
aria-label="Job Types"
|
||||||
|
className="isolate flex divide-x divide-slate-200 rounded-lg border border-slate-200 bg-white">
|
||||||
|
{tabs.map((tab, tabIdx) => (
|
||||||
|
<button
|
||||||
|
key={tab.value}
|
||||||
|
aria-current={tab.value === value ? 'page' : undefined}
|
||||||
|
className={clsx(
|
||||||
|
tab.value === value
|
||||||
|
? 'bg-primary-100 text-primary-700 hover:bg-primary-200'
|
||||||
|
: 'text-slate-500 hover:bg-slate-50 hover:text-slate-700',
|
||||||
|
tabIdx === 0 && 'rounded-l-lg',
|
||||||
|
tabIdx === tabs.length - 1 && 'rounded-r-lg',
|
||||||
|
'focus:ring-primary-500 group relative min-w-0 flex-1 overflow-hidden py-3 px-4 text-center font-medium focus:z-10',
|
||||||
|
)}
|
||||||
|
type="button"
|
||||||
|
onClick={() => {
|
||||||
|
onChange(tab.value);
|
||||||
|
}}>
|
||||||
|
<span>{tab.label}</span>
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
@ -32,6 +32,7 @@ import FormMonthYearPicker from '../../forms/FormMonthYearPicker';
|
|||||||
import FormSelect from '../../forms/FormSelect';
|
import FormSelect from '../../forms/FormSelect';
|
||||||
import FormTextArea from '../../forms/FormTextArea';
|
import FormTextArea from '../../forms/FormTextArea';
|
||||||
import FormTextInput from '../../forms/FormTextInput';
|
import FormTextInput from '../../forms/FormTextInput';
|
||||||
|
import JobTypeTabs from '../../JobTypeTabs';
|
||||||
import type { OfferFormData } from '../../types';
|
import type { OfferFormData } from '../../types';
|
||||||
import { JobTypeLabel } from '../../types';
|
import { JobTypeLabel } from '../../types';
|
||||||
import {
|
import {
|
||||||
@ -103,7 +104,7 @@ function FullTimeOfferDetailsForm({
|
|||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-5 flex grid grid-cols-2 space-x-3">
|
<div className="mb-5 grid grid-cols-2 space-x-3">
|
||||||
<div>
|
<div>
|
||||||
<CompaniesTypeahead
|
<CompaniesTypeahead
|
||||||
required={true}
|
required={true}
|
||||||
@ -527,35 +528,17 @@ export default function OfferDetailsForm({
|
|||||||
<h5 className="mb-8 text-center text-4xl font-bold text-slate-900">
|
<h5 className="mb-8 text-center text-4xl font-bold text-slate-900">
|
||||||
Fill in your offer details
|
Fill in your offer details
|
||||||
</h5>
|
</h5>
|
||||||
<div className="flex w-full justify-center">
|
<div>
|
||||||
<div className="mx-5 w-1/3">
|
<JobTypeTabs
|
||||||
<Button
|
value={jobType}
|
||||||
display="block"
|
onChange={(newJobType) => {
|
||||||
label={JobTypeLabel.FULLTIME}
|
if (newJobType === jobType) {
|
||||||
size="md"
|
return;
|
||||||
variant={jobType === JobType.FULLTIME ? 'secondary' : 'tertiary'}
|
}
|
||||||
onClick={() => {
|
|
||||||
if (jobType === JobType.FULLTIME) {
|
setDialogOpen(true);
|
||||||
return;
|
}}
|
||||||
}
|
/>
|
||||||
setDialogOpen(true);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="mx-5 w-1/3">
|
|
||||||
<Button
|
|
||||||
display="block"
|
|
||||||
label={JobTypeLabel.INTERN}
|
|
||||||
size="md"
|
|
||||||
variant={jobType === JobType.INTERN ? 'secondary' : 'tertiary'}
|
|
||||||
onClick={() => {
|
|
||||||
if (jobType === JobType.INTERN) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setDialogOpen(true);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<OfferDetailsFormArray
|
<OfferDetailsFormArray
|
||||||
fieldArrayValues={fieldArrayValues}
|
fieldArrayValues={fieldArrayValues}
|
||||||
|
@ -39,6 +39,7 @@ export default function OffersHomePage() {
|
|||||||
<JobTitlesTypeahead
|
<JobTitlesTypeahead
|
||||||
isLabelHidden={true}
|
isLabelHidden={true}
|
||||||
placeholder="Software Engineer"
|
placeholder="Software Engineer"
|
||||||
|
textSize="inherit"
|
||||||
onSelect={(option) => {
|
onSelect={(option) => {
|
||||||
if (option) {
|
if (option) {
|
||||||
setjobTitleFilter(option.value);
|
setjobTitleFilter(option.value);
|
||||||
@ -56,6 +57,7 @@ export default function OffersHomePage() {
|
|||||||
<CompaniesTypeahead
|
<CompaniesTypeahead
|
||||||
isLabelHidden={true}
|
isLabelHidden={true}
|
||||||
placeholder="All Companies"
|
placeholder="All Companies"
|
||||||
|
textSize="inherit"
|
||||||
onSelect={(option) => {
|
onSelect={(option) => {
|
||||||
if (option) {
|
if (option) {
|
||||||
setCompanyFilter(option.value);
|
setCompanyFilter(option.value);
|
||||||
|
@ -28,7 +28,7 @@ export default function Tabs<T>({ label, tabs, value, onChange }: Props<T>) {
|
|||||||
children: tab.label,
|
children: tab.label,
|
||||||
className: clsx(
|
className: clsx(
|
||||||
isSelected
|
isSelected
|
||||||
? 'bg-indigo-100 text-indigo-700'
|
? 'bg-primary-100 text-primary-700'
|
||||||
: 'hover:bg-slate-100 text-slate-500 hover:text-slate-700',
|
: 'hover:bg-slate-100 text-slate-500 hover:text-slate-700',
|
||||||
'px-3 py-2 font-medium text-sm rounded-md',
|
'px-3 py-2 font-medium text-sm rounded-md',
|
||||||
),
|
),
|
||||||
|
Reference in New Issue
Block a user