[offers][feat] integrate profile API and offer API (#360)

pull/362/head
Zhang Ziqing 2 years ago committed by GitHub
parent b52db41965
commit 73e1f76570
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,16 +1,22 @@
import { useState } from 'react'; import { useRouter } from 'next/router';
import { useEffect, useState } from 'react';
import { HorizontalDivider, Pagination, Select, Tabs } from '@tih/ui'; import { HorizontalDivider, Pagination, Select, Tabs } from '@tih/ui';
import CurrencySelector from '~/utils/offers/currency/CurrencySelector'; import CurrencySelector from '~/utils/offers/currency/CurrencySelector';
import { formatDate } from '~/utils/offers/time';
import { trpc } from '~/utils/trpc';
type TableRow = { type OfferTableRow = {
company: string; company: string;
date: string; date: string;
salary: string; id: string;
profileId: string;
salary: number | undefined;
title: string; title: string;
yoe: string; yoe: number;
}; };
// To be changed to backend enum
// eslint-disable-next-line no-shadow // eslint-disable-next-line no-shadow
enum YOE_CATEGORY { enum YOE_CATEGORY {
INTERN = 0, INTERN = 0,
@ -19,10 +25,81 @@ enum YOE_CATEGORY {
SENIOR = 3, SENIOR = 3,
} }
export default function OffersTable() { type OffersTableProps = {
const [currency, setCurrency] = useState('SGD'); companyFilter: string;
jobTitleFilter: string;
};
type Pagination = {
currentPage: number;
numOfItems: number;
numOfPages: number;
totalItems: number;
};
const NUMBER_OF_OFFERS_IN_PAGE = 10;
export default function OffersTable({ jobTitleFilter }: OffersTableProps) {
const router = useRouter();
const [currency, setCurrency] = useState('SGD'); // TODO
const [selectedTab, setSelectedTab] = useState(YOE_CATEGORY.ENTRY); const [selectedTab, setSelectedTab] = useState(YOE_CATEGORY.ENTRY);
const [selectedPage, setSelectedPage] = useState(1); const [pagination, setPagination] = useState<Pagination>({
currentPage: 1,
numOfItems: 1,
numOfPages: 0,
totalItems: 0,
});
const [offers, setOffers] = useState<Array<OfferTableRow>>([]);
useEffect(() => {
setPagination({
currentPage: 1,
numOfItems: 1,
numOfPages: 0,
totalItems: 0,
});
}, [selectedTab]);
trpc.useQuery(
[
'offers.list',
{
// Company: companyFilter, // TODO
limit: NUMBER_OF_OFFERS_IN_PAGE,
location: 'Singapore, Singapore',
offset: pagination.currentPage - 1,
sortBy: '-monthYearReceived',
title: jobTitleFilter,
yoeCategory: selectedTab,
},
],
{
onSuccess: (response) => {
const filteredData = response.data.map((res) => {
return {
company: res.company.name,
date: formatDate(res.monthYearReceived),
id: res.OffersFullTime
? res.OffersFullTime!.id
: res.OffersIntern!.id,
profileId: res.profileId,
salary: res.OffersFullTime
? res.OffersFullTime?.totalCompensation.value
: res.OffersIntern?.monthlySalary.value,
title: res.OffersFullTime ? res.OffersFullTime?.level : '',
yoe: 100,
};
});
setOffers(filteredData);
setPagination({
currentPage: (response.paging.currPage as number) + 1,
numOfItems: response.paging.numOfItemsInPage,
numOfPages: response.paging.numOfPages,
totalItems: response.paging.totalNumberOfOffers,
});
},
},
);
function renderTabs() { function renderTabs() {
return ( return (
@ -103,9 +180,27 @@ export default function OffersTable() {
); );
} }
function renderRow({ company, title, yoe, salary, date }: TableRow) { const handleClickViewProfile = (profileId: string) => {
router.push(`/offers/profile/${profileId}`);
};
const handlePageChange = (currPage: number) => {
setPagination({ ...pagination, currentPage: currPage });
};
function renderRow({
company,
title,
yoe,
salary,
date,
profileId,
id,
}: OfferTableRow) {
return ( return (
<tr className="border-b bg-white hover:bg-gray-50 dark:border-gray-700 dark:bg-gray-800 dark:hover:bg-gray-600"> <tr
key={id}
className="border-b bg-white hover:bg-gray-50 dark:border-gray-700 dark:bg-gray-800 dark:hover:bg-gray-600">
<th <th
className="whitespace-nowrap py-4 px-6 font-medium text-gray-900 dark:text-white" className="whitespace-nowrap py-4 px-6 font-medium text-gray-900 dark:text-white"
scope="row"> scope="row">
@ -118,14 +213,14 @@ export default function OffersTable() {
<td className="space-x-4 py-4 px-6"> <td className="space-x-4 py-4 px-6">
<a <a
className="font-medium text-indigo-600 hover:underline dark:text-indigo-500" className="font-medium text-indigo-600 hover:underline dark:text-indigo-500"
href="#"> onClick={() => handleClickViewProfile(profileId)}>
View Profile View Profile
</a> </a>
<a {/* <a
className="font-medium text-indigo-600 hover:underline dark:text-indigo-500" className="font-medium text-indigo-600 hover:underline dark:text-indigo-500"
href="#"> href="#">
Comment Comment
</a> </a> */}
</td> </td>
</tr> </tr>
); );
@ -137,22 +232,30 @@ export default function OffersTable() {
aria-label="Table navigation" aria-label="Table navigation"
className="flex items-center justify-between p-4"> className="flex items-center justify-between p-4">
<span className="text-sm font-normal text-gray-500 dark:text-gray-400"> <span className="text-sm font-normal text-gray-500 dark:text-gray-400">
Showing{' '} Showing
<span className="font-semibold text-gray-900 dark:text-white"> <span className="font-semibold text-gray-900 dark:text-white">
1-10 {` ${
</span>{' '} (pagination.currentPage - 1) * NUMBER_OF_OFFERS_IN_PAGE + 1
of{' '} } - ${
(pagination.currentPage - 1) * NUMBER_OF_OFFERS_IN_PAGE +
offers.length
} `}
</span>
{`of `}
<span className="font-semibold text-gray-900 dark:text-white"> <span className="font-semibold text-gray-900 dark:text-white">
1000 {pagination.totalItems}
{/* {pagination.numOfPages * NUMBER_OF_OFFERS_IN_PAGE} */}
</span> </span>
</span> </span>
<Pagination <Pagination
current={selectedPage} current={pagination.currentPage}
end={10} end={pagination.numOfPages}
label="Pagination" label="Pagination"
pagePadding={1} pagePadding={1}
start={1} start={1}
onSelect={(page) => setSelectedPage(page)} onSelect={(currPage) => {
handlePageChange(currPage);
}}
/> />
</nav> </nav>
); );
@ -167,20 +270,7 @@ export default function OffersTable() {
<table className="w-full text-left text-sm text-gray-500 dark:text-gray-400"> <table className="w-full text-left text-sm text-gray-500 dark:text-gray-400">
{renderHeader()} {renderHeader()}
<tbody> <tbody>
{renderRow({ {offers.map((offer: OfferTableRow) => renderRow(offer))}
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> </tbody>
</table> </table>
{renderPagination()} {renderPagination()}

@ -3,14 +3,14 @@ import {
LightBulbIcon, LightBulbIcon,
} from '@heroicons/react/24/outline'; } from '@heroicons/react/24/outline';
import type { EducationBackgroundType } from '../types'; import type { EducationBackgroundType } from '~/components/offers/types';
type EducationEntity = { type EducationEntity = {
backgroundType?: EducationBackgroundType; endDate?: string;
field?: string; field?: string;
fromMonth?: string;
school?: string; school?: string;
toMonth?: string; startDate?: string;
type?: EducationBackgroundType;
}; };
type Props = Readonly<{ type Props = Readonly<{
@ -18,7 +18,7 @@ type Props = Readonly<{
}>; }>;
export default function EducationCard({ export default function EducationCard({
education: { backgroundType, field, fromMonth, school, toMonth }, education: { type, field, startDate, endDate, school },
}: Props) { }: Props) {
return ( return (
<div className="mx-8 my-4 block rounded-lg bg-white py-4 shadow-md"> <div className="mx-8 my-4 block rounded-lg bg-white py-4 shadow-md">
@ -27,9 +27,7 @@ export default function EducationCard({
<div className="flex flex-row"> <div className="flex flex-row">
<LightBulbIcon className="mr-1 h-5" /> <LightBulbIcon className="mr-1 h-5" />
<span className="ml-1 font-bold"> <span className="ml-1 font-bold">
{field {field ? `${type ?? 'N/A'}, ${field}` : type ?? `N/A`}
? `${backgroundType ?? 'N/A'}, ${field}`
: backgroundType ?? `N/A`}
</span> </span>
</div> </div>
{school && ( {school && (
@ -39,9 +37,11 @@ export default function EducationCard({
</div> </div>
)} )}
</div> </div>
{(fromMonth || toMonth) && ( {(startDate || endDate) && (
<div className="font-light text-gray-400"> <div className="font-light text-gray-400">
<p>{`${fromMonth ?? 'N/A'} - ${toMonth ?? 'N/A'}`}</p> <p>{`${startDate ? startDate : 'N/A'} - ${
endDate ? endDate : 'N/A'
}`}</p>
</div> </div>
)} )}
</div> </div>

@ -6,18 +6,19 @@ import {
} from '@heroicons/react/24/outline'; } from '@heroicons/react/24/outline';
import { HorizontalDivider } from '@tih/ui'; import { HorizontalDivider } from '@tih/ui';
type OfferEntity = { export type OfferEntity = {
base?: string; base?: string;
bonus?: string; bonus?: string;
companyName: string; companyName: string;
duration?: string; // For background duration?: string;
id?: string;
jobLevel?: string; jobLevel?: string;
jobTitle: string; jobTitle: string;
location: string; location?: string;
monthlySalary?: string; monthlySalary?: string;
negotiationStrategy?: string; negotiationStrategy?: string;
otherComment?: string; otherComment?: string;
receivedMonth: string; receivedMonth?: string;
stocks?: string; stocks?: string;
totalCompensation?: string; totalCompensation?: string;
}; };
@ -57,14 +58,14 @@ export default function OfferCard({
<p>{jobLevel ? `${jobTitle}, ${jobLevel}` : jobTitle}</p> <p>{jobLevel ? `${jobTitle}, ${jobLevel}` : jobTitle}</p>
</div> </div>
</div> </div>
{receivedMonth && ( {!duration && receivedMonth && (
<div className="font-light text-gray-400"> <div className="font-light text-gray-400">
<p>{receivedMonth}</p> <p>{receivedMonth}</p>
</div> </div>
)} )}
{duration && ( {duration && (
<div className="font-light text-gray-400"> <div className="font-light text-gray-400">
<p>{duration}</p> <p>{`${duration} months`}</p>
</div> </div>
)} )}
</div> </div>

@ -1,5 +1,6 @@
/* eslint-disable no-shadow */ /* eslint-disable no-shadow */
import type { MonthYear } from '../shared/MonthYearPicker'; import type { OfferEntity } from '~/components/offers/profile/OfferCard';
import type { MonthYear } from '~/components/shared/MonthYearPicker';
/* /*
* Offer Profile * Offer Profile
@ -82,7 +83,7 @@ type GeneralExperience = {
title: string; title: string;
}; };
type Experience = export type Experience =
| (FullTimeExperience & GeneralExperience) | (FullTimeExperience & GeneralExperience)
| (GeneralExperience & InternshipExperience); | (GeneralExperience & InternshipExperience);
@ -110,3 +111,19 @@ export type OfferPostData = {
background: BackgroundFormData; background: BackgroundFormData;
offers: Array<OfferDetailsPostData>; offers: Array<OfferDetailsPostData>;
}; };
type EducationDisplay = {
endDate?: string;
field: string;
school: string;
startDate?: string;
type: string;
};
export type BackgroundCard = {
educations: Array<EducationDisplay>;
experiences: Array<OfferEntity>;
profileName: string;
specificYoes: Array<SpecificYoe>;
totalYoe: string;
};

@ -6,8 +6,7 @@ import OffersTitle from '~/components/offers/OffersTitle';
import CompaniesTypeahead from '~/components/shared/CompaniesTypeahead'; import CompaniesTypeahead from '~/components/shared/CompaniesTypeahead';
export default function OffersHomePage() { export default function OffersHomePage() {
const [jobTitleFilter, setjobTitleFilter] = useState('Software engineers'); const [jobTitleFilter, setjobTitleFilter] = useState('Software Engineer');
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [companyFilter, setCompanyFilter] = useState('All companies'); const [companyFilter, setCompanyFilter] = useState('All companies');
return ( return (
@ -23,20 +22,20 @@ export default function OffersHomePage() {
label="Select a job title" label="Select a job title"
options={[ options={[
{ {
label: 'Software engineers', label: 'Software Engineer',
value: 'Software engineers', value: 'Software Engineer',
}, },
{ {
label: 'Frontend engineers', label: 'Frontend Engineer',
value: 'Frontend engineers', value: 'Frontend Engineer',
}, },
{ {
label: 'Backend engineers', label: 'Backend Engineer',
value: 'Backend engineers', value: 'Backend Engineer',
}, },
{ {
label: 'Full-stack engineers', label: 'Full-stack Engineer',
value: 'Full-stack engineers', value: 'Full-stack Engineer',
}, },
]} ]}
value={jobTitleFilter} value={jobTitleFilter}
@ -53,7 +52,10 @@ export default function OffersHomePage() {
</div> </div>
</div> </div>
<div className="flex justify-center bg-white pb-20 pt-10"> <div className="flex justify-center bg-white pb-20 pt-10">
<OffersTable /> <OffersTable
companyFilter={companyFilter}
jobTitleFilter={jobTitleFilter}
/>
</div> </div>
</main> </main>
); );

@ -1,3 +1,5 @@
import Error from 'next/error';
import { useRouter } from 'next/router';
import { useState } from 'react'; import { useState } from 'react';
import { import {
AcademicCapIcon, AcademicCapIcon,
@ -13,13 +15,129 @@ import {
import { Button, Dialog, Tabs } from '@tih/ui'; import { Button, Dialog, Tabs } from '@tih/ui';
import EducationCard from '~/components/offers/profile/EducationCard'; import EducationCard from '~/components/offers/profile/EducationCard';
import type { OfferEntity } from '~/components/offers/profile/OfferCard';
import OfferCard from '~/components/offers/profile/OfferCard'; import OfferCard from '~/components/offers/profile/OfferCard';
import ProfilePhotoHolder from '~/components/offers/profile/ProfilePhotoHolder'; import ProfilePhotoHolder from '~/components/offers/profile/ProfilePhotoHolder';
import type { BackgroundCard } from '~/components/offers/types';
import { EducationBackgroundType } from '~/components/offers/types'; import { EducationBackgroundType } from '~/components/offers/types';
import { formatDate } from '~/utils/offers/time';
import { trpc } from '~/utils/trpc';
export default function OfferProfile() { export default function OfferProfile() {
const ErrorPage = (
<Error statusCode={404} title="Requested profile does not exist." />
);
const router = useRouter();
const { offerProfileId, token = '' } = router.query;
const [isEditable, setIsEditable] = useState(false);
const [background, setBackground] = useState<BackgroundCard>();
const [offers, setOffers] = useState<Array<OfferEntity>>([]);
const [selectedTab, setSelectedTab] = useState('offers'); const [selectedTab, setSelectedTab] = useState('offers');
const [isDialogOpen, setIsDialogOpen] = useState(false); const [isDialogOpen, setIsDialogOpen] = useState(false);
const detailsQuery = trpc.useQuery(
[
'offers.profile.listOne',
{ profileId: offerProfileId as string, token: token as string },
],
{
enabled: typeof offerProfileId === 'string',
onSuccess: (data) => {
const filteredOffers: Array<OfferEntity> = data!.offers.map((res) => {
if (res.OffersFullTime) {
const filteredOffer: OfferEntity = {
base: res.OffersFullTime.baseSalary.value
? `${res.OffersFullTime.baseSalary.value} ${res.OffersFullTime.baseSalary.currency}`
: '',
bonus: res.OffersFullTime.bonus.value
? `${res.OffersFullTime.bonus.value} ${res.OffersFullTime.bonus.currency}`
: '',
companyName: res.company.name,
id: res.OffersFullTime.id,
jobLevel: res.OffersFullTime.level,
jobTitle: res.OffersFullTime.title,
location: res.location,
negotiationStrategy: res.negotiationStrategy || '',
otherComment: res.comments || '',
receivedMonth: formatDate(res.monthYearReceived),
stocks: res.OffersFullTime.stocks.value
? `${res.OffersFullTime.stocks.value} ${res.OffersFullTime.stocks.currency}`
: '',
totalCompensation: res.OffersFullTime.totalCompensation.value
? `${res.OffersFullTime.totalCompensation.value} ${res.OffersFullTime.totalCompensation.currency}`
: '',
};
return filteredOffer;
}
const filteredOffer: OfferEntity = {
companyName: res.company.name,
id: res.OffersIntern!.id,
jobTitle: res.OffersIntern!.title,
location: res.location,
monthlySalary: res.OffersIntern!.monthlySalary.value
? `${res.OffersIntern!.monthlySalary.value} ${
res.OffersIntern!.monthlySalary.currency
}`
: '',
negotiationStrategy: res.negotiationStrategy || '',
otherComment: res.comments || '',
receivedMonth: formatDate(res.monthYearReceived),
};
return filteredOffer;
});
setOffers(filteredOffers ?? []);
if (data?.background) {
const filteredBackground: BackgroundCard = {
educations: [
{
endDate: data?.background.educations[0].endDate
? formatDate(data.background.educations[0].endDate)
: '-',
field: data.background.educations[0].field || '-',
school: data.background.educations[0].school || '-',
startDate: data.background.educations[0].startDate
? formatDate(data.background.educations[0].startDate)
: '-',
type: data.background.educations[0].type || '-',
},
],
experiences: [
{
companyName:
data.background.experiences[0].company?.name ?? '-',
duration:
String(data.background.experiences[0].durationInMonths) ??
'-',
jobLevel: data.background.experiences[0].level ?? '',
jobTitle: data.background.experiences[0].title ?? '-',
monthlySalary: data.background.experiences[0].monthlySalary
?.value
? `${data.background.experiences[0].monthlySalary?.value} ${data.background.experiences[0].monthlySalary?.currency}`
: `-`,
totalCompensation: data.background.experiences[0]
.totalCompensation?.value
? `${data.background.experiences[0].totalCompensation?.value} ${data.background.experiences[0].totalCompensation?.currency}`
: ``,
},
],
profileName: data.profileName,
specificYoes: data.background.specificYoes ?? [],
totalYoe: String(data.background.totalYoe) || '-',
};
setBackground(filteredBackground);
}
setIsEditable(data?.isEditable ?? false);
},
},
);
function renderActionList() { function renderActionList() {
return ( return (
<div className="space-x-2"> <div className="space-x-2">
@ -67,8 +185,8 @@ export default function OfferProfile() {
title="Are you sure you want to delete this offer profile?" title="Are you sure you want to delete this offer profile?"
onClose={() => setIsDialogOpen(false)}> onClose={() => setIsDialogOpen(false)}>
<div> <div>
All comments will gone. You will not be able to access or recover All comments will be gone. You will not be able to access or
it. recover it.
</div> </div>
</Dialog> </Dialog>
)} )}
@ -84,20 +202,36 @@ export default function OfferProfile() {
</div> </div>
<div className="w-full"> <div className="w-full">
<div className="justify-left flex "> <div className="justify-left flex ">
<h2 className="flex w-4/5 text-2xl font-bold">anonymised-name</h2> <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"> <div className="flex h-8 w-1/5 justify-end">
{renderActionList()} {isEditable && renderActionList()}
</div> </div>
)}
</div> </div>
<div className="flex flex-row"> <div className="flex flex-row">
<BuildingOffice2Icon className="mr-2.5 h-5" /> <BuildingOffice2Icon className="mr-2.5 h-5" />
<span className="mr-2 font-bold">Current:</span> <span className="mr-2 font-bold">Current:</span>
<span>Level 4 Google</span> <span>{`${background?.experiences[0].companyName ?? '-'} ${
background?.experiences[0].jobLevel
} ${background?.experiences[0].jobTitle}`}</span>
</div> </div>
<div className="flex flex-row"> <div className="flex flex-row">
<CalendarDaysIcon className="mr-2.5 h-5" /> <CalendarDaysIcon className="mr-2.5 h-5" />
<span className="mr-2 font-bold">YOE:</span> <span className="mr-2 font-bold">YOE:</span>
<span>4</span> <span className="mr-4">{background?.totalYoe}</span>
{background?.specificYoes &&
background?.specificYoes.length > 0 &&
background?.specificYoes.map(({ domain, yoe }) => (
<>
<span
key={domain}
className="mr-2">{`${domain} : ${yoe}`}</span>
<span>{background?.totalYoe}</span>
</>
))}
</div> </div>
</div> </div>
</div> </div>
@ -131,41 +265,7 @@ export default function OfferProfile() {
if (selectedTab === 'offers') { if (selectedTab === 'offers') {
return ( return (
<> <>
{[ {[...offers].map((offer) => (
{
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} /> <OfferCard key={offer.id} offer={offer} />
))} ))}
</> </>
@ -173,39 +273,34 @@ export default function OfferProfile() {
} }
if (selectedTab === 'background') { if (selectedTab === 'background') {
return ( return (
<>
{background?.experiences && background?.experiences.length > 0 && (
<> <>
<div className="mx-8 my-4 flex flex-row"> <div className="mx-8 my-4 flex flex-row">
<BriefcaseIcon className="mr-1 h-5" /> <BriefcaseIcon className="mr-1 h-5" />
<span className="font-bold">Work Experience</span> <span className="font-bold">Work Experience</span>
</div> </div>
<OfferCard <OfferCard offer={background?.experiences[0]} />
offer={{ </>
base: undefined, )}
bonus: undefined, {background?.educations && background?.educations.length > 0 && (
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"> <div className="mx-8 my-4 flex flex-row">
<AcademicCapIcon className="mr-1 h-5" /> <AcademicCapIcon className="mr-1 h-5" />
<span className="font-bold">Education</span> <span className="font-bold">Education</span>
</div> </div>
<EducationCard <EducationCard
education={{ education={{
backgroundType: EducationBackgroundType.Bachelor, endDate: background.educations[0].endDate,
field: 'CS', field: background.educations[0].field,
fromMonth: 'Aug 2019', school: background.educations[0].school,
school: 'NUS', startDate: background.educations[0].startDate,
toMonth: 'May 2021', type: EducationBackgroundType.Bachelor,
}} }}
/> />
</> </>
)}
</>
); );
} }
return <div>Detail page for {selectedTab}</div>; return <div>Detail page for {selectedTab}</div>;
@ -215,6 +310,7 @@ export default function OfferProfile() {
return ( return (
<div className="m-4"> <div className="m-4">
<div className="flex-end flex justify-end space-x-4"> <div className="flex-end flex justify-end space-x-4">
{isEditable && (
<Button <Button
addonPosition="start" addonPosition="start"
icon={ClipboardDocumentIcon} icon={ClipboardDocumentIcon}
@ -222,7 +318,14 @@ export default function OfferProfile() {
label="Copy profile edit link" label="Copy profile edit link"
size="sm" size="sm"
variant="secondary" variant="secondary"
onClick={() => {
// TODO: Add notification
navigator.clipboard.writeText(
`${router.pathname}/${offerProfileId}?token=${token}`,
);
}}
/> />
)}
<Button <Button
addonPosition="start" addonPosition="start"
icon={ShareIcon} icon={ShareIcon}
@ -230,6 +333,12 @@ export default function OfferProfile() {
label="Copy public link" label="Copy public link"
size="sm" size="sm"
variant="secondary" variant="secondary"
onClick={() => {
// TODO: Add notification
navigator.clipboard.writeText(
`${window.location.origin}/offers/profile/${offerProfileId}`,
);
}}
/> />
</div> </div>
<h2 className="mt-2 text-2xl font-bold"> <h2 className="mt-2 text-2xl font-bold">
@ -241,6 +350,8 @@ export default function OfferProfile() {
} }
return ( return (
<>
{detailsQuery.isError && ErrorPage}
<div className="mb-4 flex flex h-screen w-screen items-center justify-center divide-x"> <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"> <div className="h-full w-2/3 divide-y">
<ProfileHeader /> <ProfileHeader />
@ -252,5 +363,6 @@ export default function OfferProfile() {
<ProfileComments /> <ProfileComments />
</div> </div>
</div> </div>
</>
); );
} }

Loading…
Cancel
Save