commitpull/348/head3ad2f6bf3b
Author: Zhang Ziqing <zhangziqing9926@gmail.com> Date: Sun Oct 9 23:22:38 2022 +0800 [offers][feat] add offer table commit78e1eb81bd
Author: Zhang Ziqing <zhangziqing9926@gmail.com> Date: Sun Oct 9 17:17:46 2022 +0800 [offers][feat] add offer profile tab and background tab component
parent
cf5af1a5c7
commit
670777474b
@ -1,23 +1,14 @@
|
|||||||
import type { ProductNavigationItems } from '~/components/global/ProductNavigation';
|
import type { ProductNavigationItems } from '~/components/global/ProductNavigation';
|
||||||
|
|
||||||
const navigation: ProductNavigationItems = [
|
const navigation: ProductNavigationItems = [
|
||||||
{
|
{ href: '/offers', name: 'Home' },
|
||||||
children: [
|
{ href: '/submit', name: 'Benchmark your offer' },
|
||||||
{ href: '#', name: 'Technical Support' },
|
|
||||||
{ href: '#', name: 'Sales' },
|
|
||||||
{ href: '#', name: 'General' },
|
|
||||||
],
|
|
||||||
href: '#',
|
|
||||||
name: 'Inboxes',
|
|
||||||
},
|
|
||||||
{ children: [], href: '#', name: 'Reporting' },
|
|
||||||
{ children: [], href: '#', name: 'Settings' },
|
|
||||||
];
|
];
|
||||||
|
|
||||||
const config = {
|
const config = {
|
||||||
navigation,
|
navigation,
|
||||||
showGlobalNav: true,
|
showGlobalNav: false,
|
||||||
title: 'Offers',
|
title: 'Tech Offers Repo',
|
||||||
};
|
};
|
||||||
|
|
||||||
export default config;
|
export default config;
|
||||||
|
@ -0,0 +1,190 @@
|
|||||||
|
import { useState } from 'react';
|
||||||
|
import { HorizontalDivider, Pagination, Select, Tabs } from '@tih/ui';
|
||||||
|
|
||||||
|
import CurrencySelector from '~/components/offers/util/currency/CurrencySelector';
|
||||||
|
|
||||||
|
type TableRow = {
|
||||||
|
company: string;
|
||||||
|
date: string;
|
||||||
|
salary: string;
|
||||||
|
title: string;
|
||||||
|
yoe: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-shadow
|
||||||
|
enum YOE_CATEGORY {
|
||||||
|
INTERN = 0,
|
||||||
|
ENTRY = 1,
|
||||||
|
MID = 2,
|
||||||
|
SENIOR = 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function OffersTable() {
|
||||||
|
const [currency, setCurrency] = useState('SGD');
|
||||||
|
const [selectedTab, setSelectedTab] = useState(YOE_CATEGORY.ENTRY);
|
||||||
|
const [selectedPage, setSelectedPage] = useState(1);
|
||||||
|
|
||||||
|
function renderTabs() {
|
||||||
|
return (
|
||||||
|
<div className="flex justify-center">
|
||||||
|
<div className="w-fit">
|
||||||
|
<Tabs
|
||||||
|
label="Table Navigation"
|
||||||
|
tabs={[
|
||||||
|
{
|
||||||
|
label: 'Fresh Grad (0-3 YOE)',
|
||||||
|
value: YOE_CATEGORY.ENTRY,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Mid (4-7 YOE)',
|
||||||
|
value: YOE_CATEGORY.MID,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Senior (8+ YOE)',
|
||||||
|
value: YOE_CATEGORY.SENIOR,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Internship',
|
||||||
|
value: YOE_CATEGORY.INTERN,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
value={selectedTab}
|
||||||
|
onChange={(value) => setSelectedTab(value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderFilters() {
|
||||||
|
return (
|
||||||
|
<div className="m-4 flex items-center justify-between">
|
||||||
|
<div className="justify-left flex items-center space-x-2">
|
||||||
|
<span>All offers in</span>
|
||||||
|
<CurrencySelector
|
||||||
|
handleCurrencyChange={(value: string) => setCurrency(value)}
|
||||||
|
selectedCurrency={currency}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<Select
|
||||||
|
disabled={true}
|
||||||
|
isLabelHidden={true}
|
||||||
|
label=""
|
||||||
|
options={[
|
||||||
|
{
|
||||||
|
label: 'Latest Submitted',
|
||||||
|
value: 'latest-submitted',
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
value="latest-submitted"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderHeader() {
|
||||||
|
return (
|
||||||
|
<thead className="bg-gray-50 text-xs uppercase text-gray-700 dark:bg-gray-700 dark:text-gray-400">
|
||||||
|
<tr>
|
||||||
|
{[
|
||||||
|
'Company',
|
||||||
|
'Title',
|
||||||
|
'YOE',
|
||||||
|
'TC/year',
|
||||||
|
'Date offered',
|
||||||
|
'Actions',
|
||||||
|
].map((header) => (
|
||||||
|
<th key={header} className="py-3 px-6" scope="col">
|
||||||
|
{header}
|
||||||
|
</th>
|
||||||
|
))}
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderRow({ company, title, yoe, salary, date }: TableRow) {
|
||||||
|
return (
|
||||||
|
<tr className="border-b bg-white hover:bg-gray-50 dark:border-gray-700 dark:bg-gray-800 dark:hover:bg-gray-600">
|
||||||
|
<th
|
||||||
|
className="whitespace-nowrap py-4 px-6 font-medium text-gray-900 dark:text-white"
|
||||||
|
scope="row">
|
||||||
|
{company}
|
||||||
|
</th>
|
||||||
|
<td className="py-4 px-6">{title}</td>
|
||||||
|
<td className="py-4 px-6">{yoe}</td>
|
||||||
|
<td className="py-4 px-6">{salary}</td>
|
||||||
|
<td className="py-4 px-6">{date}</td>
|
||||||
|
<td className="space-x-4 py-4 px-6">
|
||||||
|
<a
|
||||||
|
className="font-medium text-indigo-600 hover:underline dark:text-indigo-500"
|
||||||
|
href="#">
|
||||||
|
View Profile
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
className="font-medium text-indigo-600 hover:underline dark:text-indigo-500"
|
||||||
|
href="#">
|
||||||
|
Comment
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderPagination() {
|
||||||
|
return (
|
||||||
|
<nav
|
||||||
|
aria-label="Table navigation"
|
||||||
|
className="flex items-center justify-between p-4">
|
||||||
|
<span className="text-sm font-normal text-gray-500 dark:text-gray-400">
|
||||||
|
Showing{' '}
|
||||||
|
<span className="font-semibold text-gray-900 dark:text-white">
|
||||||
|
1-10
|
||||||
|
</span>{' '}
|
||||||
|
of{' '}
|
||||||
|
<span className="font-semibold text-gray-900 dark:text-white">
|
||||||
|
1000
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<Pagination
|
||||||
|
current={selectedPage}
|
||||||
|
end={10}
|
||||||
|
label="Pagination"
|
||||||
|
pagePadding={1}
|
||||||
|
start={1}
|
||||||
|
onSelect={(page) => setSelectedPage(page)}
|
||||||
|
/>
|
||||||
|
</nav>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="w-5/6">
|
||||||
|
{renderTabs()}
|
||||||
|
<HorizontalDivider />
|
||||||
|
<div className="relative w-full overflow-x-auto shadow-md sm:rounded-lg">
|
||||||
|
{renderFilters()}
|
||||||
|
<table className="w-full text-left text-sm text-gray-500 dark:text-gray-400">
|
||||||
|
{renderHeader()}
|
||||||
|
<tbody>
|
||||||
|
{renderRow({
|
||||||
|
company: 'Shopee',
|
||||||
|
date: 'May 2022',
|
||||||
|
salary: 'TC/yr',
|
||||||
|
title: 'SWE',
|
||||||
|
yoe: '5',
|
||||||
|
})}
|
||||||
|
{renderRow({
|
||||||
|
company: 'Shopee',
|
||||||
|
date: 'May 2022',
|
||||||
|
salary: 'TC/yr',
|
||||||
|
title: 'SWE',
|
||||||
|
yoe: '5',
|
||||||
|
})}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{renderPagination()}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
@ -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,172 @@
|
|||||||
|
// eslint-disable-next-line no-shadow
|
||||||
|
export enum Currency {
|
||||||
|
AED = 'AED', // United Arab Emirates Dirham
|
||||||
|
AFN = 'AFN', // Afghanistan Afghani
|
||||||
|
ALL = 'ALL', // Albania Lek
|
||||||
|
AMD = 'AMD', // Armenia Dram
|
||||||
|
ANG = 'ANG', // Netherlands Antilles Guilder
|
||||||
|
AOA = 'AOA', // Angola Kwanza
|
||||||
|
ARS = 'ARS', // Argentina Peso
|
||||||
|
AUD = 'AUD', // Australia Dollar
|
||||||
|
AWG = 'AWG', // Aruba Guilder
|
||||||
|
AZN = 'AZN', // Azerbaijan New Manat
|
||||||
|
BAM = 'BAM', // Bosnia and Herzegovina Convertible Marka
|
||||||
|
BBD = 'BBD', // Barbados Dollar
|
||||||
|
BDT = 'BDT', // Bangladesh Taka
|
||||||
|
BGN = 'BGN', // Bulgaria Lev
|
||||||
|
BHD = 'BHD', // Bahrain Dinar
|
||||||
|
BIF = 'BIF', // Burundi Franc
|
||||||
|
BMD = 'BMD', // Bermuda Dollar
|
||||||
|
BND = 'BND', // Brunei Darussalam Dollar
|
||||||
|
BOB = 'BOB', // Bolivia Bolíviano
|
||||||
|
BRL = 'BRL', // Brazil Real
|
||||||
|
BSD = 'BSD', // Bahamas Dollar
|
||||||
|
BTN = 'BTN', // Bhutan Ngultrum
|
||||||
|
BWP = 'BWP', // Botswana Pula
|
||||||
|
BYR = 'BYR', // Belarus Ruble
|
||||||
|
BZD = 'BZD', // Belize Dollar
|
||||||
|
CAD = 'CAD', // Canada Dollar
|
||||||
|
CDF = 'CDF', // Congo/Kinshasa Franc
|
||||||
|
CHF = 'CHF', // Switzerland Franc
|
||||||
|
CLP = 'CLP', // Chile Peso
|
||||||
|
CNY = 'CNY', // China Yuan Renminbi
|
||||||
|
COP = 'COP', // Colombia Peso
|
||||||
|
CRC = 'CRC', // Costa Rica Colon
|
||||||
|
CUC = 'CUC', // Cuba Convertible Peso
|
||||||
|
CUP = 'CUP', // Cuba Peso
|
||||||
|
CVE = 'CVE', // Cape Verde Escudo
|
||||||
|
CZK = 'CZK', // Czech Republic Koruna
|
||||||
|
DJF = 'DJF', // Djibouti Franc
|
||||||
|
DKK = 'DKK', // Denmark Krone
|
||||||
|
DOP = 'DOP', // Dominican Republic Peso
|
||||||
|
DZD = 'DZD', // Algeria Dinar
|
||||||
|
EGP = 'EGP', // Egypt Pound
|
||||||
|
ERN = 'ERN', // Eritrea Nakfa
|
||||||
|
ETB = 'ETB', // Ethiopia Birr
|
||||||
|
EUR = 'EUR', // Euro Member Countries
|
||||||
|
FJD = 'FJD', // Fiji Dollar
|
||||||
|
FKP = 'FKP', // Falkland Islands (Malvinas) Pound
|
||||||
|
GBP = 'GBP', // United Kingdom Pound
|
||||||
|
GEL = 'GEL', // Georgia Lari
|
||||||
|
GGP = 'GGP', // Guernsey Pound
|
||||||
|
GHS = 'GHS', // Ghana Cedi
|
||||||
|
GIP = 'GIP', // Gibraltar Pound
|
||||||
|
GMD = 'GMD', // Gambia Dalasi
|
||||||
|
GNF = 'GNF', // Guinea Franc
|
||||||
|
GTQ = 'GTQ', // Guatemala Quetzal
|
||||||
|
GYD = 'GYD', // Guyana Dollar
|
||||||
|
HKD = 'HKD', // Hong Kong Dollar
|
||||||
|
HNL = 'HNL', // Honduras Lempira
|
||||||
|
HRK = 'HRK', // Croatia Kuna
|
||||||
|
HTG = 'HTG', // Haiti Gourde
|
||||||
|
HUF = 'HUF', // Hungary Forint
|
||||||
|
IDR = 'IDR', // Indonesia Rupiah
|
||||||
|
ILS = 'ILS', // Israel Shekel
|
||||||
|
IMP = 'IMP', // Isle of Man Pound
|
||||||
|
INR = 'INR', // India Rupee
|
||||||
|
IQD = 'IQD', // Iraq Dinar
|
||||||
|
IRR = 'IRR', // Iran Rial
|
||||||
|
ISK = 'ISK', // Iceland Krona
|
||||||
|
JEP = 'JEP', // Jersey Pound
|
||||||
|
JMD = 'JMD', // Jamaica Dollar
|
||||||
|
JOD = 'JOD', // Jordan Dinar
|
||||||
|
JPY = 'JPY', // Japan Yen
|
||||||
|
KES = 'KES', // Kenya Shilling
|
||||||
|
KGS = 'KGS', // Kyrgyzstan Som
|
||||||
|
KHR = 'KHR', // Cambodia Riel
|
||||||
|
KMF = 'KMF', // Comoros Franc
|
||||||
|
KPW = 'KPW', // Korea (North) Won
|
||||||
|
KRW = 'KRW', // Korea (South) Won
|
||||||
|
KWD = 'KWD', // Kuwait Dinar
|
||||||
|
KYD = 'KYD', // Cayman Islands Dollar
|
||||||
|
KZT = 'KZT', // Kazakhstan Tenge
|
||||||
|
LAK = 'LAK', // Laos Kip
|
||||||
|
LBP = 'LBP', // Lebanon Pound
|
||||||
|
LKR = 'LKR', // Sri Lanka Rupee
|
||||||
|
LRD = 'LRD', // Liberia Dollar
|
||||||
|
LSL = 'LSL', // Lesotho Loti
|
||||||
|
LYD = 'LYD', // Libya Dinar
|
||||||
|
MAD = 'MAD', // Morocco Dirham
|
||||||
|
MDL = 'MDL', // Moldova Leu
|
||||||
|
MGA = 'MGA', // Madagascar Ariary
|
||||||
|
MKD = 'MKD', // Macedonia Denar
|
||||||
|
MMK = 'MMK', // Myanmar (Burma) Kyat
|
||||||
|
MNT = 'MNT', // Mongolia Tughrik
|
||||||
|
MOP = 'MOP', // Macau Pataca
|
||||||
|
MRO = 'MRO', // Mauritania Ouguiya
|
||||||
|
MUR = 'MUR', // Mauritius Rupee
|
||||||
|
MVR = 'MVR', // Maldives (Maldive Islands) Rufiyaa
|
||||||
|
MWK = 'MWK', // Malawi Kwacha
|
||||||
|
MXN = 'MXN', // Mexico Peso
|
||||||
|
MYR = 'MYR', // Malaysia Ringgit
|
||||||
|
MZN = 'MZN', // Mozambique Metical
|
||||||
|
NAD = 'NAD', // Namibia Dollar
|
||||||
|
NGN = 'NGN', // Nigeria Naira
|
||||||
|
NIO = 'NIO', // Nicaragua Cordoba
|
||||||
|
NOK = 'NOK', // Norway Krone
|
||||||
|
NPR = 'NPR', // Nepal Rupee
|
||||||
|
NZD = 'NZD', // New Zealand Dollar
|
||||||
|
OMR = 'OMR', // Oman Rial
|
||||||
|
PAB = 'PAB', // Panama Balboa
|
||||||
|
PEN = 'PEN', // Peru Sol
|
||||||
|
PGK = 'PGK', // Papua New Guinea Kina
|
||||||
|
PHP = 'PHP', // Philippines Peso
|
||||||
|
PKR = 'PKR', // Pakistan Rupee
|
||||||
|
PLN = 'PLN', // Poland Zloty
|
||||||
|
PYG = 'PYG', // Paraguay Guarani
|
||||||
|
QAR = 'QAR', // Qatar Riyal
|
||||||
|
RON = 'RON', // Romania New Leu
|
||||||
|
RSD = 'RSD', // Serbia Dinar
|
||||||
|
RUB = 'RUB', // Russia Ruble
|
||||||
|
RWF = 'RWF', // Rwanda Franc
|
||||||
|
SAR = 'SAR', // Saudi Arabia Riyal
|
||||||
|
SBD = 'SBD', // Solomon Islands Dollar
|
||||||
|
SCR = 'SCR', // Seychelles Rupee
|
||||||
|
SDG = 'SDG', // Sudan Pound
|
||||||
|
SEK = 'SEK', // Sweden Krona
|
||||||
|
SGD = 'SGD', // Singapore Dollar
|
||||||
|
SHP = 'SHP', // Saint Helena Pound
|
||||||
|
SLL = 'SLL', // Sierra Leone Leone
|
||||||
|
SOS = 'SOS', // Somalia Shilling
|
||||||
|
SPL = 'SPL', // Seborga Luigino
|
||||||
|
SRD = 'SRD', // Suriname Dollar
|
||||||
|
STD = 'STD', // São Tomé and Príncipe Dobra
|
||||||
|
SVC = 'SVC', // El Salvador Colon
|
||||||
|
SYP = 'SYP', // Syria Pound
|
||||||
|
SZL = 'SZL', // Swaziland Lilangeni
|
||||||
|
THB = 'THB', // Thailand Baht
|
||||||
|
TJS = 'TJS', // Tajikistan Somoni
|
||||||
|
TMT = 'TMT', // Turkmenistan Manat
|
||||||
|
TND = 'TND', // Tunisia Dinar
|
||||||
|
TOP = 'TOP', // Tonga Pa'anga
|
||||||
|
TRY = 'TRY', // Turkey Lira
|
||||||
|
TTD = 'TTD', // Trinidad and Tobago Dollar
|
||||||
|
TVD = 'TVD', // Tuvalu Dollar
|
||||||
|
TWD = 'TWD', // Taiwan New Dollar
|
||||||
|
TZS = 'TZS', // Tanzania Shilling
|
||||||
|
UAH = 'UAH', // Ukraine Hryvnia
|
||||||
|
UGX = 'UGX', // Uganda Shilling
|
||||||
|
USD = 'USD', // United States Dollar
|
||||||
|
UYU = 'UYU', // Uruguay Peso
|
||||||
|
UZS = 'UZS', // Uzbekistan Som
|
||||||
|
VEF = 'VEF', // Venezuela Bolivar
|
||||||
|
VND = 'VND', // Viet Nam Dong
|
||||||
|
VUV = 'VUV', // Vanuatu Vatu
|
||||||
|
WST = 'WST', // Samoa Tala
|
||||||
|
XAF = 'XAF', // Communauté Financière Africaine (BEAC) CFA Franc BEAC
|
||||||
|
XCD = 'XCD', // East Caribbean Dollar
|
||||||
|
XDR = 'XDR', // International Monetary Fund (IMF) Special Drawing Rights
|
||||||
|
XOF = 'XOF', // Communauté Financière Africaine (BCEAO) Franc
|
||||||
|
XPF = 'XPF', // Comptoirs Français du Pacifique (CFP) Franc
|
||||||
|
YER = 'YER', // Yemen Rial
|
||||||
|
ZAR = 'ZAR', // South Africa Rand
|
||||||
|
ZMW = 'ZMW', // Zambia Kwacha
|
||||||
|
ZWD = 'ZWD', // Zimbabwe Dollar
|
||||||
|
}
|
||||||
|
|
||||||
|
export const CURRENCY_OPTIONS = Object.entries(Currency).map(
|
||||||
|
([key, value]) => ({
|
||||||
|
label: key,
|
||||||
|
value,
|
||||||
|
}),
|
||||||
|
);
|
@ -0,0 +1,30 @@
|
|||||||
|
import { Select } from '@tih/ui';
|
||||||
|
|
||||||
|
import { Currency } from '~/components/offers/util/currency/CurrencyEnum';
|
||||||
|
|
||||||
|
const currencyOptions = Object.entries(Currency).map(([key, value]) => ({
|
||||||
|
label: key,
|
||||||
|
value,
|
||||||
|
}));
|
||||||
|
|
||||||
|
type Props = Readonly<{
|
||||||
|
handleCurrencyChange: (currency: string) => void;
|
||||||
|
selectedCurrency: string;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
export default function CurrencySelector({
|
||||||
|
selectedCurrency,
|
||||||
|
handleCurrencyChange,
|
||||||
|
}: Props) {
|
||||||
|
return (
|
||||||
|
<Select
|
||||||
|
display="inline"
|
||||||
|
isLabelHidden={true}
|
||||||
|
label="Select fruit"
|
||||||
|
name=""
|
||||||
|
options={currencyOptions}
|
||||||
|
value={selectedCurrency}
|
||||||
|
onChange={(currency: string) => handleCurrencyChange(currency)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
export function formatDate(value: Date | number | string) {
|
||||||
|
const date = new Date(value);
|
||||||
|
// Const day = date.toLocaleString('default', { day: '2-digit' });
|
||||||
|
const month = date.toLocaleString('default', { month: 'short' });
|
||||||
|
const year = date.toLocaleString('default', { year: 'numeric' });
|
||||||
|
return `${month} ${year}`;
|
||||||
|
}
|
@ -0,0 +1,256 @@
|
|||||||
|
import { useState } from 'react';
|
||||||
|
import {
|
||||||
|
AcademicCapIcon,
|
||||||
|
BookmarkSquareIcon,
|
||||||
|
BriefcaseIcon,
|
||||||
|
BuildingOffice2Icon,
|
||||||
|
CalendarDaysIcon,
|
||||||
|
ClipboardDocumentIcon,
|
||||||
|
PencilSquareIcon,
|
||||||
|
ShareIcon,
|
||||||
|
TrashIcon,
|
||||||
|
} from '@heroicons/react/24/outline';
|
||||||
|
import { Button, Dialog, Tabs } 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 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"
|
||||||
|
onClick={() => setIsDialogOpen(true)}
|
||||||
|
/>
|
||||||
|
{isDialogOpen && (
|
||||||
|
<Dialog
|
||||||
|
isShown={isDialogOpen}
|
||||||
|
primaryButton={
|
||||||
|
<Button
|
||||||
|
display="block"
|
||||||
|
label="Delete"
|
||||||
|
variant="primary"
|
||||||
|
onClick={() => setIsDialogOpen(false)}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
secondaryButton={
|
||||||
|
<Button
|
||||||
|
display="block"
|
||||||
|
label="Cancel"
|
||||||
|
variant="tertiary"
|
||||||
|
onClick={() => setIsDialogOpen(false)}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
title="Are you sure you want to delete this offer profile?"
|
||||||
|
onClose={() => setIsDialogOpen(false)}>
|
||||||
|
<div>
|
||||||
|
All comments will gone. You will not be able to access or recover
|
||||||
|
it.
|
||||||
|
</div>
|
||||||
|
</Dialog>
|
||||||
|
)}
|
||||||
|
</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">
|
||||||
|
<div className="flex-end flex justify-end space-x-4">
|
||||||
|
<Button
|
||||||
|
addonPosition="start"
|
||||||
|
icon={ClipboardDocumentIcon}
|
||||||
|
isLabelHidden={false}
|
||||||
|
label="Copy profile edit link"
|
||||||
|
size="sm"
|
||||||
|
variant="secondary"
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
addonPosition="start"
|
||||||
|
icon={ShareIcon}
|
||||||
|
isLabelHidden={false}
|
||||||
|
label="Copy public link"
|
||||||
|
size="sm"
|
||||||
|
variant="secondary"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<h2 className="mt-2 text-2xl font-bold">
|
||||||
|
Discussions feature coming soon
|
||||||
|
</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