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…
Reference in new issue