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