[offers][feat] add offer profile tab and background tab component

pull/345/head
Zhang Ziqing 3 years ago
parent a1cd0f4e9b
commit 78e1eb81bd

@ -0,0 +1,60 @@
import {
BuildingLibraryIcon,
LightBulbIcon,
} from '@heroicons/react/24/outline';
// To be replaced by form enums
// eslint-disable-next-line no-shadow
export enum EducationBackgroundType {
Bachelor = 'Bachelor',
Diploma = 'Diploma',
Masters = 'Masters',
PhD = 'PhD',
Professional = 'Professional',
Seconday = 'Secondary',
SelfTaught = 'Self-taught',
}
type EducationEntity = {
backgroundType?: EducationBackgroundType;
field?: string;
fromMonth?: string;
school?: string;
toMonth?: string;
};
type Props = Readonly<{
education: EducationEntity;
}>;
export default function EducationCard({
education: { backgroundType, field, fromMonth, school, toMonth },
}: Props) {
return (
<div className="mx-8 my-4 block rounded-lg bg-white py-4 shadow-md">
<div className="flex justify-between px-8">
<div className="flex flex-col">
<div className="flex flex-row">
<LightBulbIcon className="mr-1 h-5" />
<span className="ml-1 font-bold">
{field
? `${backgroundType ?? 'N/A'}, ${field}`
: backgroundType ?? `N/A`}
</span>
</div>
{school && (
<div className="flex flex-row">
<BuildingLibraryIcon className="mr-1 h-5" />
<span className="ml-1">{school}</span>
</div>
)}
</div>
{(fromMonth || toMonth) && (
<div className="font-light text-gray-400">
<p>{`${fromMonth ?? 'N/A'} - ${toMonth ?? 'N/A'}`}</p>
</div>
)}
</div>
</div>
);
}

@ -0,0 +1,124 @@
import {
BuildingOffice2Icon,
ChatBubbleBottomCenterTextIcon,
CurrencyDollarIcon,
ScaleIcon,
} from '@heroicons/react/24/outline';
import { HorizontalDivider } from '@tih/ui';
type OfferEntity = {
base?: string;
bonus?: string;
companyName: string;
duration?: string; // For background
jobLevel?: string;
jobTitle: string;
location: string;
monthlySalary?: string;
negotiationStrategy?: string;
otherComment?: string;
receivedMonth: string;
stocks?: string;
totalCompensation?: string;
};
type Props = Readonly<{
offer: OfferEntity;
}>;
export default function OfferCard({
offer: {
companyName = 'Meta',
jobTitle = 'Senior Engineer',
jobLevel,
location = 'Singapore',
receivedMonth = 'Jun 2021',
totalCompensation = '350.1k',
base = '0k',
stocks = '0k',
bonus = '0k',
duration,
monthlySalary,
negotiationStrategy,
otherComment,
},
}: Props) {
function UpperSection() {
return (
<div className="flex justify-between px-8">
<div className="flex flex-col">
<div className="flex flex-row">
<BuildingOffice2Icon className="mr-1 h-5" />
<span className="font-bold">
{location ? `${companyName}, ${location}` : companyName}
</span>
</div>
<div className="ml-6 flex flex-row">
<p>{jobLevel ? `${jobTitle}, ${jobLevel}` : jobTitle}</p>
</div>
</div>
{receivedMonth && (
<div className="font-light text-gray-400">
<p>{receivedMonth}</p>
</div>
)}
{duration && (
<div className="font-light text-gray-400">
<p>{duration}</p>
</div>
)}
</div>
);
}
function BottomSection() {
return (
<div className="px-8">
<div className="flex flex-col py-2">
<div className="flex flex-row">
<CurrencyDollarIcon className="mr-1 h-5" />
<p>
{totalCompensation
? `TC: ${totalCompensation}`
: `Monthly Salary: ${monthlySalary}`}
</p>
</div>
{totalCompensation && (
<div className="ml-6 flex flex-row font-light text-gray-400">
<p>
Base / year: {base} Stocks / year: {stocks} Bonus / year:{' '}
{bonus}
</p>
</div>
)}
</div>
{negotiationStrategy && (
<div className="flex flex-col py-2">
<div className="flex flex-row">
<ScaleIcon className="h-5 w-5" />
<span className="overflow-wrap ml-2">
"{negotiationStrategy}"
</span>
</div>
</div>
)}
{otherComment && (
<div className="flex flex-col py-2">
<div className="flex flex-row">
<ChatBubbleBottomCenterTextIcon className="h-8 w-8" />
<span className="overflow-wrap ml-2">"{otherComment}"</span>
</div>
</div>
)}
</div>
);
}
return (
<div className="mx-8 my-4 block rounded-lg bg-white py-4 shadow-md">
<UpperSection />
<HorizontalDivider />
<BottomSection />
</div>
);
}

@ -0,0 +1,12 @@
export default function ProfilePhotoHolder() {
return (
<span className="inline-block h-16 w-16 overflow-hidden rounded-full bg-gray-100">
<svg
className="h-full w-full text-gray-300"
fill="currentColor"
viewBox="0 0 24 24">
<path d="M24 20.993V24H0v-2.996A14.977 14.977 0 0112.004 15c4.904 0 9.26 2.354 11.996 5.993zM16.002 8.999a4 4 0 11-8 0 4 4 0 018 0z" />
</svg>
</span>
);
}

@ -0,0 +1,241 @@
import { useState } from 'react';
import {
AcademicCapIcon,
BookmarkSquareIcon,
BriefcaseIcon,
BuildingOffice2Icon,
CalendarDaysIcon,
PencilSquareIcon,
TrashIcon,
} from '@heroicons/react/24/outline';
import { Button, Tabs, TextArea } from '@tih/ui';
import { EducationBackgroundType } from '~/components/offers/profile/EducationCard';
import EducationCard from '~/components/offers/profile/EducationCard';
import OfferCard from '~/components/offers/profile/OfferCard';
import ProfilePhotoHolder from '~/components/offers/profile/ProfilePhotoHolder';
export default function OfferProfile() {
const [selectedTab, setSelectedTab] = useState('offers');
// Const [isDialogOpen, setIsDialogOpen] = useState(false);
function renderActionList() {
return (
// <div>
// <Button
// label="Open"
// variant="primary"
// onClick={() => setIsDialogOpen(true)}
// />
// {isDialogOpen && (
// <Dialog
// primaryButton={
// <Button
// display="block"
// label="OK"
// variant="primary"
// onClick={() => setIsDialogOpen(false)}
// />
// }
// secondaryButton={
// <Button
// display="block"
// label="Cancel"
// variant="tertiary"
// onClick={() => setIsDialogOpen(false)}
// />
// }
// title="Lorem ipsum, dolor sit amet"
// onClose={() => setIsDialogOpen(false)}>
// <div>
// Lorem ipsum, dolor sit amet consectetur adipisicing elit. Eius
// aliquam laudantium explicabo pariatur iste dolorem animi vitae
// error totam. At sapiente aliquam accusamus facere veritatis.
// </div>
// </Dialog>
// )}
// </div>
<div className="space-x-2">
<Button
icon={BookmarkSquareIcon}
isLabelHidden={true}
label="Save to user account"
size="md"
variant="tertiary"
/>
<Button
icon={PencilSquareIcon}
isLabelHidden={true}
label="Edit"
size="md"
variant="tertiary"
/>
<Button
icon={TrashIcon}
isLabelHidden={true}
label="Delete"
size="md"
variant="tertiary"
/>
</div>
);
}
function ProfileHeader() {
return (
<div className="relative h-40 bg-white p-4">
<div className="justify-left flex h-1/2">
<div className="mx-4 mt-2">
<ProfilePhotoHolder />
</div>
<div className="w-full">
<div className="justify-left flex ">
<h2 className="flex w-4/5 text-2xl font-bold">anonymised-name</h2>
<div className="flex h-8 w-1/5 justify-end">
{renderActionList()}
</div>
</div>
<div className="flex flex-row">
<BuildingOffice2Icon className="mr-2.5 h-5" />
<span className="mr-2 font-bold">Current:</span>
<span>Level 4 Google</span>
</div>
<div className="flex flex-row">
<CalendarDaysIcon className="mr-2.5 h-5" />
<span className="mr-2 font-bold">YOE:</span>
<span>4</span>
</div>
</div>
</div>
<div className="absolute left-8 bottom-1 content-center">
<Tabs
label="Profile Detail Navigation"
tabs={[
{
label: 'Offers',
value: 'offers',
},
{
label: 'Background',
value: 'background',
},
{
label: 'Offer Engine Analysis',
value: 'offerEngineAnalysis',
},
]}
value={selectedTab}
onChange={(value) => setSelectedTab(value)}
/>
</div>
</div>
);
}
function ProfileDetails() {
if (selectedTab === 'offers') {
return (
<>
{[
{
base: undefined,
bonus: undefined,
companyName: 'Meta',
id: 1,
jobLevel: 'G5',
jobTitle: 'Software Engineer',
location: 'Singapore',
monthlySalary: undefined,
negotiationStrategy:
'Nostrud nulla aliqua deserunt commodo id aute.',
otherComment:
'Pariatur ut est voluptate incididunt consequat do veniam quis irure adipisicing. Deserunt laborum dolor quis voluptate enim.',
receivedMonth: 'Jun 2022',
stocks: undefined,
totalCompensation: undefined,
},
{
companyName: 'Meta',
id: 2,
jobLevel: 'G5',
jobTitle: 'Software Engineer',
location: 'Singapore',
receivedMonth: 'Jun 2022',
},
{
companyName: 'Meta',
id: 3,
jobLevel: 'G5',
jobTitle: 'Software Engineer',
location: 'Singapore',
receivedMonth: 'Jun 2022',
},
].map((offer) => (
<OfferCard key={offer.id} offer={offer} />
))}
</>
);
}
if (selectedTab === 'background') {
return (
<>
<div className="mx-8 my-4 flex flex-row">
<BriefcaseIcon className="mr-1 h-5" />
<span className="font-bold">Work Experience</span>
</div>
<OfferCard
offer={{
base: undefined,
bonus: undefined,
companyName: 'Prefer not to say',
jobLevel: 'G4',
jobTitle: 'N/A',
location: '',
monthlySalary: '1,400k',
receivedMonth: '',
stocks: undefined,
totalCompensation: undefined,
}}
/>
<div className="mx-8 my-4 flex flex-row">
<AcademicCapIcon className="mr-1 h-5" />
<span className="font-bold">Education</span>
</div>
<EducationCard
education={{
backgroundType: EducationBackgroundType.Bachelor,
field: 'CS',
fromMonth: 'Aug 2019',
school: 'NUS',
toMonth: 'May 2021',
}}
/>
</>
);
}
return <div>Detail page for {selectedTab}</div>;
}
function ProfileComments() {
return (
<div className="m-4">
<h2 className="text-2xl font-bold">Discussions</h2>
<TextArea label="Comment" placeholder="Type your comment here" />
</div>
);
}
return (
<div className="mb-4 flex flex h-screen w-screen items-center justify-center divide-x">
<div className="h-full w-2/3 divide-y">
<ProfileHeader />
<div className="h-4/5 w-full overflow-y-scroll pb-32">
<ProfileDetails />
</div>
</div>
<div className="h-full w-1/3 bg-white">
<ProfileComments />
</div>
</div>
);
}
Loading…
Cancel
Save