[offers][refactor] tweak profile page UI

pull/500/head
Yangshun Tay 2 years ago
parent 4b327b5132
commit 36541b5244

@ -37,28 +37,28 @@ export default function DashboardProfileCard({
</h4>
<div className="mt-1 flex flex-col sm:mt-0 sm:flex-row sm:flex-wrap sm:space-x-4">
{company?.name && (
<div className="mt-2 flex items-center text-sm text-gray-500">
<div className="mt-2 flex items-center text-sm text-slate-500">
<BuildingOfficeIcon
aria-hidden="true"
className="mr-1.5 h-5 w-5 flex-shrink-0 text-gray-400"
className="mr-1.5 h-5 w-5 flex-shrink-0 text-slate-400"
/>
{company.name}
</div>
)}
{location && (
<div className="mt-2 flex items-center text-sm text-gray-500">
<div className="mt-2 flex items-center text-sm text-slate-500">
<MapPinIcon
aria-hidden="true"
className="mr-1.5 h-5 w-5 flex-shrink-0 text-gray-400"
className="mr-1.5 h-5 w-5 flex-shrink-0 text-slate-400"
/>
{location.cityName}
</div>
)}
{level && (
<div className="mt-2 flex items-center text-sm text-gray-500">
<div className="mt-2 flex items-center text-sm text-slate-500">
<ArrowTrendingUpIcon
aria-hidden="true"
className="mr-1.5 h-5 w-5 flex-shrink-0 text-gray-400"
className="mr-1.5 h-5 w-5 flex-shrink-0 text-slate-400"
/>
{level}
</div>

@ -13,12 +13,12 @@ export default function EducationCard({
education: { type, field, startDate, endDate, school },
}: 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">
<div className="block rounded-lg border border-slate-200 bg-white p-4 text-sm ">
<div className="flex justify-between">
<div>
<div className="flex items-center">
<LightBulbIcon className="mr-1 h-5" />
<span className="ml-1 font-bold">
<span className="text-semibold ml-1">
{field ? `${type ?? 'N/A'}, ${field}` : type ?? `N/A`}
</span>
</div>

@ -1,17 +1,13 @@
import {
BuildingOffice2Icon,
ChatBubbleBottomCenterTextIcon,
CurrencyDollarIcon,
ScaleIcon,
} from '@heroicons/react/24/outline';
import { HorizontalDivider } from '@tih/ui';
ArrowTrendingUpIcon,
BuildingOfficeIcon,
MapPinIcon,
} from '@heroicons/react/20/solid';
import { JobTypeLabel } from '~/components/offers/constants';
import type { OfferDisplayData } from '~/components/offers/types';
import {
getCompanyDisplayText,
getJobDisplayText,
} from '~/utils/offers/string';
import { getLocationDisplayText } from '~/utils/offers/string';
type Props = Readonly<{
offer: OfferDisplayData;
@ -37,32 +33,55 @@ export default function OfferCard({
}: Props) {
function UpperSection() {
return (
<div className="flex justify-between px-8">
<div className="flex flex-col">
{(companyName || location) && (
<div className="flex flex-row">
<span>
<BuildingOffice2Icon className="mr-3 h-5" />
</span>
<span className="font-bold">
{getCompanyDisplayText(companyName, location)}
</span>
<div className="px-4 py-5 sm:px-6">
<div className="flex justify-between">
<div>
<h3 className="text-lg font-medium leading-6 text-slate-900">
{jobTitle} {jobType && <>({JobTypeLabel[jobType]})</>}
</h3>
<div className="mt-1 flex flex-row flex-wrap space-x-4 sm:mt-0">
{companyName && (
<div className="mt-2 flex items-center text-sm text-slate-500">
<BuildingOfficeIcon
aria-hidden="true"
className="mr-1.5 h-5 w-5 flex-shrink-0 text-slate-400"
/>
{companyName}
</div>
)}
{location && (
<div className="mt-2 flex items-center text-sm text-slate-500">
<MapPinIcon
aria-hidden="true"
className="mr-1.5 h-5 w-5 flex-shrink-0 text-slate-400"
/>
{getLocationDisplayText(location)}
</div>
)}
{jobLevel && (
<div className="mt-2 flex items-center text-sm text-slate-500">
<ArrowTrendingUpIcon
aria-hidden="true"
className="mr-1.5 h-5 w-5 flex-shrink-0 text-slate-400"
/>
{jobLevel}
</div>
)}
</div>
)}
<div className="ml-8 flex flex-row">
<p>{getJobDisplayText(jobTitle, jobLevel, jobType)}</p>
</div>
</div>
{!duration && receivedMonth && (
<div className="font-light text-slate-400">
<p>{receivedMonth}</p>
</div>
)}
{duration && (
<div className="font-light text-slate-400">
<p>{`${duration} months`}</p>
<div className="space-y-2">
{!duration && receivedMonth && (
<div className="text-sm text-slate-500">
<p>{receivedMonth}</p>
</div>
)}
{duration && (
<div className="text-sm text-slate-500">
<p>{`${duration} months`}</p>
</div>
)}
</div>
)}
</div>
</div>
);
}
@ -78,60 +97,69 @@ export default function OfferCard({
}
return (
<>
<HorizontalDivider />
<div className="px-8">
<div className="flex flex-col py-2">
{(totalCompensation || monthlySalary) && (
<div className="flex flex-row">
<span>
<CurrencyDollarIcon className="mr-3 h-5" />
</span>
<span>
<p>
{totalCompensation && `TC: ${totalCompensation}`}
{monthlySalary && `Monthly Salary: ${monthlySalary}`}
</p>
</span>
</div>
)}
{(base || stocks || bonus) && totalCompensation && (
<div className="ml-8 flex flex-row font-light">
<p>
Base / year: {base ?? 'N/A'} Stocks / year:{' '}
{stocks ?? 'N/A'} Bonus / year: {bonus ?? 'N/A'}
</p>
</div>
)}
</div>
<div className="border-t border-slate-200 px-4 py-5 sm:px-6">
<dl className="grid grid-cols-2 gap-x-4 gap-y-8 sm:grid-cols-4">
{totalCompensation && (
<div className="col-span-1">
<dt className="text-sm font-medium text-slate-500">
Total Compensation
</dt>
<dd className="mt-1 text-sm text-slate-900">
{totalCompensation}
</dd>
</div>
)}
{monthlySalary && (
<div className="col-span-1">
<dt className="text-sm font-medium text-slate-500">
Monthly Salary
</dt>
<dd className="mt-1 text-sm text-slate-900">{monthlySalary}</dd>
</div>
)}
{base && (
<div className="col-span-1">
<dt className="text-sm font-medium text-slate-500">
Base Salary
</dt>
<dd className="mt-1 text-sm text-slate-900">{base}</dd>
</div>
)}
{stocks && (
<div className="col-span-1">
<dt className="text-sm font-medium text-slate-500">Stocks</dt>
<dd className="mt-1 text-sm text-slate-900">{stocks}</dd>
</div>
)}
{bonus && (
<div className="col-span-1">
<dt className="text-sm font-medium text-slate-500">Bonus</dt>
<dd className="mt-1 text-sm text-slate-900">{bonus}</dd>
</div>
)}
{negotiationStrategy && (
<div className="flex flex-col py-2">
<div className="flex flex-row">
<span>
<ScaleIcon className="h-5 w-5" />
</span>
<span className="overflow-wrap ml-2">
"{negotiationStrategy}"
</span>
</div>
<div className="col-span-2">
<dt className="text-sm font-medium text-slate-500">
Negotiation Strategy
</dt>
<dd className="mt-1 text-sm text-slate-900">
{negotiationStrategy}
</dd>
</div>
)}
{otherComment && (
<div className="flex flex-col py-2">
<div className="flex flex-row">
<span>
<ChatBubbleBottomCenterTextIcon className="h-5 w-5" />
</span>
<span className="overflow-wrap ml-2">"{otherComment}"</span>
</div>
<div className="col-span-2">
<dt className="text-sm font-medium text-slate-500">Others</dt>
<dd className="mt-1 text-sm text-slate-900">{otherComment}</dd>
</div>
)}
</div>
</>
</dl>
</div>
);
}
return (
<div className="mx-8 my-4 block rounded-md border-b border-gray-300 bg-white py-4">
<div className="block rounded-lg border border-slate-200 bg-white">
<UpperSection />
<BottomSection />
</div>

@ -25,19 +25,19 @@ type ProfileOffersProps = Readonly<{
}>;
function ProfileOffers({ offers }: ProfileOffersProps) {
if (offers.length !== 0) {
if (offers.length === 0) {
return (
<>
{offers.map((offer) => (
<OfferCard key={offer.id} offer={offer} />
))}
</>
<div className="p-4">
<p className="font-semibold">No offers are attached.</p>
</div>
);
}
return (
<div className="mx-8 my-4 flex flex-row">
<BriefcaseIcon className="mr-1 h-5" />
<span className="font-bold">No offer is attached.</span>
<div className="space-y-4 p-4">
{offers.map((offer) => (
<OfferCard key={offer.id} offer={offer} />
))}
</div>
);
}
@ -49,33 +49,37 @@ type ProfileBackgroundProps = Readonly<{
function ProfileBackground({ background }: ProfileBackgroundProps) {
if (!background?.experiences?.length && !background?.educations?.length) {
return (
<div className="mx-8 my-4">
<div className="p-4">
<p>No background information available.</p>
</div>
);
}
return (
<>
<div className="space-y-8 p-4">
{background?.experiences?.length > 0 && (
<>
<div className="mx-8 my-4 flex flex-row">
<BriefcaseIcon className="mr-1 h-5" />
<span className="font-bold">Work Experience</span>
<div className="space-y-2">
<div className="flex items-center space-x-2 text-slate-500">
<BriefcaseIcon className="h-5" />
<h3 className="text-sm font-semibold uppercase tracking-wide">
Work Experience
</h3>
</div>
<OfferCard offer={background.experiences[0]} />
</>
</div>
)}
{background?.educations?.length > 0 && (
<>
<div className="mx-8 my-4 flex flex-row">
<AcademicCapIcon className="mr-1 h-5" />
<span className="font-bold">Education</span>
<div className="space-y-2">
<div className="flex items-center space-x-2 text-slate-500">
<AcademicCapIcon className="h-5" />
<h3 className="text-sm font-semibold uppercase tracking-wide">
Education
</h3>
</div>
<EducationCard education={background.educations[0]} />
</>
</div>
)}
</>
</div>
);
}
@ -114,7 +118,7 @@ function ProfileAnalysis({
}
return (
<div className="mx-8 my-4">
<div className="p-4">
{!analysis ? (
<p>No analysis available.</p>
) : (
@ -165,12 +169,15 @@ export default function ProfileDetails({
</div>
);
}
if (selectedTab === ProfileDetailTab.OFFERS) {
return <ProfileOffers offers={offers} />;
}
if (selectedTab === ProfileDetailTab.BACKGROUND) {
return <ProfileBackground background={background} />;
}
if (selectedTab === ProfileDetailTab.ANALYSIS) {
return (
<ProfileAnalysis

@ -233,20 +233,20 @@ export default function ProfileHeader({
const { experiences, totalYoe, specificYoes, profileName } = background;
return (
<div className="grid-rows-2 bg-white p-4">
<div className="flex grid grid-cols-5 md:grid-cols-7">
<div className="jsutify-start col-span-5 flex">
<div className="ml-0 mr-2 mt-2 h-16 w-16 md:mx-4">
<div className="grid-rows-2 bg-white">
<div className="grid grid-cols-5 p-4 md:grid-cols-7">
<div className="col-span-5 flex justify-start space-x-4">
<div className="mt-2 h-16 w-16">
<ProfilePhotoHolder />
</div>
<div>
<div className="space-y-1">
<h2 className="flex text-2xl font-bold">
{profileName ?? 'anonymous'}
</h2>
{(experiences[0]?.companyName ||
experiences[0]?.jobLevel ||
experiences[0]?.jobTitle) && (
<div className="flex flex-row text-slate-600">
<div className="flex items-center text-sm text-slate-600">
<span>
<BuildingOffice2Icon className="mr-2.5 h-5 w-5" />
</span>
@ -262,7 +262,7 @@ export default function ProfileHeader({
</p>
</div>
)}
<div className="flex flex-row text-slate-600">
<div className="flex items-center text-sm text-slate-600">
<CalendarDaysIcon className="mr-2.5 h-5" />
<p>
<span className="mr-2 font-bold">YOE:</span>
@ -286,7 +286,7 @@ export default function ProfileHeader({
</div>
)}
</div>
<div className="mt-4">
<div className="border-t border-slate-200 p-4">
<Tabs
label="Profile Detail Navigation"
tabs={profileDetailTabs}

@ -215,7 +215,7 @@ export default function OfferProfile() {
setSelectedTab={setSelectedTab}
/>
</div>
<div className="pb-4">
<div>
<ProfileDetails
analysis={analysis}
background={background}

@ -4,11 +4,11 @@ import { JobTypeLabel } from '~/components/offers/constants';
import type { Location } from '~/types/offers';
function joinWithComma(...strings: Array<string | null | undefined>) {
export function joinWithComma(...strings: Array<string | null | undefined>) {
return strings.filter((value) => !!value).join(', ');
}
function getLocationDisplayText({ cityName, countryName }: Location) {
export function getLocationDisplayText({ cityName, countryName }: Location) {
return cityName === countryName
? cityName
: joinWithComma(cityName, countryName);

Loading…
Cancel
Save