[offers][fix] Fix offer analysis and save

pull/403/head
Ai Ling 3 years ago
parent 0adec461d0
commit fc06de187c

@ -1,12 +1,11 @@
import Error from 'next/error';
import { useEffect } from 'react'; import { useEffect } from 'react';
import { useState } from 'react'; import { useState } from 'react';
import { HorizontalDivider, Spinner, Tabs } from '@tih/ui'; import { HorizontalDivider, Spinner, Tabs } from '@tih/ui';
import { trpc } from '~/utils/trpc'; import { trpc } from '~/utils/trpc';
import OfferPercentileAnalysis from '../analysis/OfferPercentileAnalysis'; import OfferPercentileAnalysis from './analysis/OfferPercentileAnalysis';
import OfferProfileCard from '../analysis/OfferProfileCard'; import OfferProfileCard from './analysis/OfferProfileCard';
import { OVERALL_TAB } from '../constants'; import { OVERALL_TAB } from '../constants';
import type { import type {
@ -105,21 +104,20 @@ export default function OfferAnalysis({ profileId }: OfferAnalysisProps) {
]; ];
return ( return (
<> analysis && (
{getAnalysisResult.isError && (
<Error
statusCode={404}
title="An error occurred while generating profile analysis."
/>
)}
{!getAnalysisResult.isError && analysis && (
<div> <div>
<h5 className="mb-2 text-center text-4xl font-bold text-gray-900"> <h5 className="mb-2 text-center text-4xl font-bold text-gray-900">
Result Result
</h5> </h5>
{getAnalysisResult.isLoading ? ( {getAnalysisResult.isError && (
<p className="m-10 text-center">
An error occurred while generating profile analysis.
</p>
)}
{getAnalysisResult.isLoading && (
<Spinner className="m-10" display="block" size="lg" /> <Spinner className="m-10" display="block" size="lg" />
) : ( )}
{!getAnalysisResult.isError && !getAnalysisResult.isLoading && (
<div> <div>
<Tabs <Tabs
label="Result Navigation" label="Result Navigation"
@ -132,7 +130,6 @@ export default function OfferAnalysis({ profileId }: OfferAnalysisProps) {
</div> </div>
)} )}
</div> </div>
)} )
</>
); );
} }

@ -1,13 +1,30 @@
import { useRouter } from 'next/router';
import { useState } from 'react'; import { useState } from 'react';
import { setTimeout } from 'timers'; import { setTimeout } from 'timers';
import { CheckIcon, DocumentDuplicateIcon } from '@heroicons/react/20/solid'; import { CheckIcon, DocumentDuplicateIcon } from '@heroicons/react/20/solid';
import { BookmarkSquareIcon, EyeIcon } from '@heroicons/react/24/outline'; import { BookmarkSquareIcon, EyeIcon } from '@heroicons/react/24/outline';
import { Button, TextInput } from '@tih/ui'; import { Button, TextInput } from '@tih/ui';
export default function OfferProfileSave() { import {
copyProfileLink,
getProfileLink,
getProfilePath,
} from '~/utils/offers/link';
type OfferProfileSaveProps = Readonly<{
profileId: string;
token?: string;
}>;
export default function OfferProfileSave({
profileId,
token,
}: OfferProfileSaveProps) {
const [linkCopied, setLinkCopied] = useState(false); const [linkCopied, setLinkCopied] = useState(false);
const [isSaving, setSaving] = useState(false); const [isSaving, setSaving] = useState(false);
const [isSaved, setSaved] = useState(false); const [isSaved, setSaved] = useState(false);
const router = useRouter();
const saveProfile = () => { const saveProfile = () => {
setSaving(true); setSaving(true);
setTimeout(() => { setTimeout(() => {
@ -27,13 +44,13 @@ export default function OfferProfileSave() {
To keep you offer profile strictly anonymous, only people who have the To keep you offer profile strictly anonymous, only people who have the
link below can edit it. link below can edit it.
</p> </p>
<div className="mb-20 grid grid-cols-12 gap-4"> <div className="mb-5 grid grid-cols-12 gap-4">
<div className="col-span-11"> <div className="col-span-11">
<TextInput <TextInput
disabled={true} disabled={true}
isLabelHidden={true} isLabelHidden={true}
label="Edit link" label="Edit link"
value="link.myprofile-auto-generate..." value={getProfileLink(profileId, token)}
/> />
</div> </div>
<Button <Button
@ -41,10 +58,12 @@ export default function OfferProfileSave() {
isLabelHidden={true} isLabelHidden={true}
label="Copy" label="Copy"
variant="primary" variant="primary"
onClick={() => setLinkCopied(true)} onClick={() => {
copyProfileLink(profileId, token), setLinkCopied(true);
}}
/> />
</div> </div>
<div className="mb-5"> <div className="mb-20">
{linkCopied && ( {linkCopied && (
<p className="text-purple-700">Link copied to clipboard!</p> <p className="text-purple-700">Link copied to clipboard!</p>
)} )}
@ -60,13 +79,18 @@ export default function OfferProfileSave() {
disabled={isSaved} disabled={isSaved}
icon={isSaved ? CheckIcon : BookmarkSquareIcon} icon={isSaved ? CheckIcon : BookmarkSquareIcon}
isLoading={isSaving} isLoading={isSaving}
label="Save to user profile" label={isSaved ? 'Saved to user profile' : 'Save to user profile'}
variant="primary" variant="primary"
onClick={saveProfile} onClick={saveProfile}
/> />
</div> </div>
<div className="mb-10"> <div className="mb-10">
<Button icon={EyeIcon} label="View your profile" variant="special" /> <Button
icon={EyeIcon}
label="View your profile"
variant="special"
onClick={() => router.push(getProfilePath(profileId, token))}
/>
</div> </div>
</div> </div>
</div> </div>

@ -3,7 +3,7 @@ import { UserCircleIcon } from '@heroicons/react/24/outline';
import { HorizontalDivider } from '~/../../../packages/ui/dist'; import { HorizontalDivider } from '~/../../../packages/ui/dist';
import { formatDate } from '~/utils/offers/time'; import { formatDate } from '~/utils/offers/time';
import { JobType } from '../types'; import { JobType } from '../../types';
import type { AnalysisOffer } from '~/types/offers'; import type { AnalysisOffer } from '~/types/offers';

@ -5,6 +5,7 @@ import { Button, HorizontalDivider, Spinner, TextArea } from '@tih/ui';
import ExpandableCommentCard from '~/components/offers/profile/comments/ExpandableCommentCard'; import ExpandableCommentCard from '~/components/offers/profile/comments/ExpandableCommentCard';
import { copyProfileLink } from '~/utils/offers/link';
import { trpc } from '~/utils/trpc'; import { trpc } from '~/utils/trpc';
import type { OffersDiscussion, Reply } from '~/types/offers'; import type { OffersDiscussion, Reply } from '~/types/offers';
@ -84,19 +85,6 @@ export default function ProfileComments({
} }
} }
function handleCopyEditLink() {
// TODO: Add notification
navigator.clipboard.writeText(
`${window.location.origin}/offers/profile/${profileId}?token=${token}`,
);
}
function handleCopyPublicLink() {
navigator.clipboard.writeText(
`${window.location.origin}/offers/profile/${profileId}`,
);
}
if (isLoading) { if (isLoading) {
return ( return (
<div className="col-span-10 pt-4"> <div className="col-span-10 pt-4">
@ -116,7 +104,7 @@ export default function ProfileComments({
label="Copy profile edit link" label="Copy profile edit link"
size="sm" size="sm"
variant="secondary" variant="secondary"
onClick={handleCopyEditLink} onClick={() => copyProfileLink(profileId, token)}
/> />
)} )}
<Button <Button
@ -127,7 +115,7 @@ export default function ProfileComments({
label="Copy public link" label="Copy public link"
size="sm" size="sm"
variant="secondary" variant="secondary"
onClick={handleCopyPublicLink} onClick={() => copyProfileLink(profileId)}
/> />
</div> </div>
<h2 className="mt-2 mb-6 text-2xl font-bold">Discussions</h2> <h2 className="mt-2 mb-6 text-2xl font-bold">Discussions</h2>

@ -8,6 +8,7 @@ import ProfileHeader from '~/components/offers/profile/ProfileHeader';
import type { BackgroundCard, OfferEntity } from '~/components/offers/types'; import type { BackgroundCard, OfferEntity } from '~/components/offers/types';
import { convertCurrencyToString } from '~/utils/offers/currency'; import { convertCurrencyToString } from '~/utils/offers/currency';
import { getProfilePath } from '~/utils/offers/link';
import { formatDate } from '~/utils/offers/time'; import { formatDate } from '~/utils/offers/time';
import { trpc } from '~/utils/trpc'; import { trpc } from '~/utils/trpc';
@ -38,7 +39,7 @@ export default function OfferProfile() {
} }
// If the profile is not editable with a wrong token, redirect to the profile page // If the profile is not editable with a wrong token, redirect to the profile page
if (!data?.isEditable && token !== '') { if (!data?.isEditable && token !== '') {
router.push(`/offers/profile/${offerProfileId}`); router.push(getProfilePath(offerProfileId as string));
} }
setIsEditable(data?.isEditable ?? false); setIsEditable(data?.isEditable ?? false);

@ -96,7 +96,13 @@ export default function OffersSubmissionPage() {
label: 'Analysis', label: 'Analysis',
}, },
{ {
component: <OfferProfileSave key={3} />, component: (
<OfferProfileSave
key={3}
profileId={createProfileResponse?.id || ''}
token={createProfileResponse?.token}
/>
),
hasNext: false, hasNext: false,
hasPrevious: false, hasPrevious: false,
label: 'Save', label: 'Save',

@ -216,7 +216,7 @@ export const offersAnalysisRouter = createRouter()
// TODO: Shift yoe out of background to make it mandatory // TODO: Shift yoe out of background to make it mandatory
if ( if (
!overallHighestOffer.profile.background || !overallHighestOffer.profile.background ||
!overallHighestOffer.profile.background.totalYoe overallHighestOffer.profile.background.totalYoe === undefined
) { ) {
throw new TRPCError({ throw new TRPCError({
code: 'BAD_REQUEST', code: 'BAD_REQUEST',

@ -0,0 +1,15 @@
export function getProfileLink(profileId: string, token?: string) {
return `${window.location.origin}${getProfilePath(profileId, token)}`;
}
export function copyProfileLink(profileId: string, token?: string) {
// TODO: Add notification
navigator.clipboard.writeText(getProfileLink(profileId, token));
}
export function getProfilePath(profileId: string, token?: string) {
if (token) {
return `/offers/profile/${profileId}?token=${token}`;
}
return `/offers/profile/${profileId}`;
}
Loading…
Cancel
Save