[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