[offers][feat] integrate profile delete API and set loading status (#367)
parent
b87afb1383
commit
7d15aa43cf
@ -0,0 +1,58 @@
|
|||||||
|
import { ClipboardDocumentIcon, ShareIcon } from '@heroicons/react/24/outline';
|
||||||
|
import { Button, Spinner } from '@tih/ui';
|
||||||
|
|
||||||
|
type ProfileHeaderProps = Readonly<{
|
||||||
|
handleCopyEditLink: () => void;
|
||||||
|
handleCopyPublicLink: () => void;
|
||||||
|
isDisabled: boolean;
|
||||||
|
isEditable: boolean;
|
||||||
|
isLoading: boolean;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
export default function ProfileComments({
|
||||||
|
handleCopyEditLink,
|
||||||
|
handleCopyPublicLink,
|
||||||
|
isDisabled,
|
||||||
|
isEditable,
|
||||||
|
isLoading,
|
||||||
|
}: ProfileHeaderProps) {
|
||||||
|
if (isLoading) {
|
||||||
|
return (
|
||||||
|
<div className="col-span-10 pt-4">
|
||||||
|
<Spinner display="block" size="lg" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div className="m-4">
|
||||||
|
<div className="flex-end flex justify-end space-x-4">
|
||||||
|
{isEditable && (
|
||||||
|
<Button
|
||||||
|
addonPosition="start"
|
||||||
|
disabled={isDisabled}
|
||||||
|
icon={ClipboardDocumentIcon}
|
||||||
|
isLabelHidden={false}
|
||||||
|
label="Copy profile edit link"
|
||||||
|
size="sm"
|
||||||
|
variant="secondary"
|
||||||
|
onClick={handleCopyEditLink}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<Button
|
||||||
|
addonPosition="start"
|
||||||
|
disabled={isDisabled}
|
||||||
|
icon={ShareIcon}
|
||||||
|
isLabelHidden={false}
|
||||||
|
label="Copy public link"
|
||||||
|
size="sm"
|
||||||
|
variant="secondary"
|
||||||
|
onClick={handleCopyPublicLink}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<h2 className="mt-2 text-2xl font-bold">
|
||||||
|
Discussions feature coming soon
|
||||||
|
</h2>
|
||||||
|
{/* <TextArea label="Comment" placeholder="Type your comment here" /> */}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
@ -0,0 +1,79 @@
|
|||||||
|
import { AcademicCapIcon, BriefcaseIcon } from '@heroicons/react/24/outline';
|
||||||
|
import { Spinner } from '@tih/ui';
|
||||||
|
|
||||||
|
import EducationCard from '~/components/offers/profile/EducationCard';
|
||||||
|
import OfferCard from '~/components/offers/profile/OfferCard';
|
||||||
|
import type { BackgroundCard, OfferEntity } from '~/components/offers/types';
|
||||||
|
import { EducationBackgroundType } from '~/components/offers/types';
|
||||||
|
|
||||||
|
type ProfileHeaderProps = Readonly<{
|
||||||
|
background?: BackgroundCard;
|
||||||
|
isLoading: boolean;
|
||||||
|
offers: Array<OfferEntity>;
|
||||||
|
selectedTab: string;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
export default function ProfileDetails({
|
||||||
|
background,
|
||||||
|
isLoading,
|
||||||
|
offers,
|
||||||
|
selectedTab,
|
||||||
|
}: ProfileHeaderProps) {
|
||||||
|
if (isLoading) {
|
||||||
|
return (
|
||||||
|
<div className="col-span-10 pt-4">
|
||||||
|
<Spinner display="block" size="lg" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (selectedTab === 'offers') {
|
||||||
|
if (offers && offers.length !== 0) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{[...offers].map((offer) => (
|
||||||
|
<OfferCard key={offer.id} offer={offer} />
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
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>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (selectedTab === 'background') {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{background?.experiences && 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>
|
||||||
|
<OfferCard offer={background?.experiences[0]} />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{background?.educations && 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>
|
||||||
|
<EducationCard
|
||||||
|
education={{
|
||||||
|
endDate: background.educations[0].endDate,
|
||||||
|
field: background.educations[0].field,
|
||||||
|
school: background.educations[0].school,
|
||||||
|
startDate: background.educations[0].startDate,
|
||||||
|
type: EducationBackgroundType.Bachelor,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return <div>Detail page for {selectedTab}</div>;
|
||||||
|
}
|
@ -0,0 +1,167 @@
|
|||||||
|
import { useState } from 'react';
|
||||||
|
import {
|
||||||
|
BookmarkSquareIcon,
|
||||||
|
BuildingOffice2Icon,
|
||||||
|
CalendarDaysIcon,
|
||||||
|
PencilSquareIcon,
|
||||||
|
TrashIcon,
|
||||||
|
} from '@heroicons/react/24/outline';
|
||||||
|
import { Button, Dialog, Spinner, Tabs } from '@tih/ui';
|
||||||
|
|
||||||
|
import type { BackgroundCard } from '~/components/offers/types';
|
||||||
|
|
||||||
|
import ProfilePhotoHolder from './ProfilePhotoHolder';
|
||||||
|
|
||||||
|
type ProfileHeaderProps = Readonly<{
|
||||||
|
background?: BackgroundCard;
|
||||||
|
handleDelete: () => void;
|
||||||
|
isEditable: boolean;
|
||||||
|
isLoading: boolean;
|
||||||
|
selectedTab: string;
|
||||||
|
setSelectedTab: (tab: string) => void;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
export default function ProfileHeader({
|
||||||
|
background,
|
||||||
|
handleDelete,
|
||||||
|
isEditable,
|
||||||
|
isLoading,
|
||||||
|
selectedTab,
|
||||||
|
setSelectedTab,
|
||||||
|
}: ProfileHeaderProps) {
|
||||||
|
const [isDialogOpen, setIsDialogOpen] = useState(false);
|
||||||
|
|
||||||
|
function renderActionList() {
|
||||||
|
return (
|
||||||
|
<div className="space-x-2">
|
||||||
|
<Button
|
||||||
|
disabled={isLoading}
|
||||||
|
icon={BookmarkSquareIcon}
|
||||||
|
isLabelHidden={true}
|
||||||
|
label="Save to user account"
|
||||||
|
size="md"
|
||||||
|
variant="tertiary"
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
disabled={isLoading}
|
||||||
|
icon={PencilSquareIcon}
|
||||||
|
isLabelHidden={true}
|
||||||
|
label="Edit"
|
||||||
|
size="md"
|
||||||
|
variant="tertiary"
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
disabled={isLoading}
|
||||||
|
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);
|
||||||
|
handleDelete();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
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 be gone. You will not be able to access or
|
||||||
|
recover it.
|
||||||
|
</div>
|
||||||
|
</Dialog>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isLoading) {
|
||||||
|
return (
|
||||||
|
<div className="col-span-10 pt-4">
|
||||||
|
<Spinner display="block" size="lg" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div className="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 flex-1">
|
||||||
|
<h2 className="flex w-4/5 text-2xl font-bold">
|
||||||
|
{background?.profileName ?? 'anonymous'}
|
||||||
|
</h2>
|
||||||
|
{isEditable && (
|
||||||
|
<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>{`${background?.experiences[0].companyName ?? '-'} ${
|
||||||
|
background?.experiences[0].jobLevel
|
||||||
|
} ${background?.experiences[0].jobTitle}`}</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-row">
|
||||||
|
<CalendarDaysIcon className="mr-2.5 h-5" />
|
||||||
|
<span className="mr-2 font-bold">YOE:</span>
|
||||||
|
<span className="mr-4">{background?.totalYoe}</span>
|
||||||
|
{background?.specificYoes &&
|
||||||
|
background?.specificYoes.length > 0 &&
|
||||||
|
background?.specificYoes.map(({ domain, yoe }) => {
|
||||||
|
return (
|
||||||
|
<span
|
||||||
|
key={domain}
|
||||||
|
className="mr-4">{`${domain}: ${yoe}`}</span>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-8">
|
||||||
|
<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>
|
||||||
|
);
|
||||||
|
}
|
Loading…
Reference in new issue