mirror of
https://github.com/yangshun/tech-interview-handbook.git
synced 2025-07-30 13:43:59 +08:00
[offers][refactor] tweak submit and analysis steps UI
This commit is contained in:
@ -1,6 +1,6 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { HorizontalDivider, Spinner, Tabs } from '@tih/ui';
|
import { Alert, HorizontalDivider, Spinner, Tabs } from '@tih/ui';
|
||||||
|
|
||||||
import OfferPercentileAnalysisText from './OfferPercentileAnalysisText';
|
import OfferPercentileAnalysisText from './OfferPercentileAnalysisText';
|
||||||
import OfferProfileCard from './OfferProfileCard';
|
import OfferProfileCard from './OfferProfileCard';
|
||||||
@ -22,17 +22,19 @@ function OfferAnalysisContent({
|
|||||||
if (!analysis || analysis.noOfOffers === 0) {
|
if (!analysis || analysis.noOfOffers === 0) {
|
||||||
if (tab === OVERALL_TAB) {
|
if (tab === OVERALL_TAB) {
|
||||||
return (
|
return (
|
||||||
<p className="m-10">
|
<Alert title="Insufficient data to compare with" variant="info">
|
||||||
You are the first to submit an offer for your job title and YOE! Check
|
You are among the first to submit an offer for your job title and
|
||||||
back later when there are more submissions.
|
years of experience! Check back later when there are more submissions.
|
||||||
</p>
|
</Alert>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<p className="m-10">
|
<Alert title="Insufficient data to compare with" variant="info">
|
||||||
You are the first to submit an offer for this company, job title and
|
You are among the first to submit an offer for this company, job title
|
||||||
YOE! Check back later when there are more submissions.
|
and years of experience! Check back later when there are more
|
||||||
</p>
|
submissions.
|
||||||
|
</Alert>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
|
@ -73,58 +73,67 @@ export default function OffersProfileSave({
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex w-full justify-center">
|
<div className="flex w-full justify-center pb-10">
|
||||||
<div className="max-w-2xl text-center">
|
<div className="max-w-2xl text-center">
|
||||||
<h5 className="mb-6 text-4xl font-bold text-slate-900">
|
<h2 className="block text-center text-3xl font-bold leading-8 tracking-tight text-gray-900 sm:text-4xl">
|
||||||
Save for future edits
|
Save for future edits
|
||||||
</h5>
|
</h2>
|
||||||
<p className="mb-2 text-slate-900">We value your privacy.</p>
|
<p className="mt-4 text-xl leading-8 text-slate-500">
|
||||||
<p className="mb-5 text-slate-900">
|
We value your privacy
|
||||||
To keep you offer profile strictly anonymous, only people who have the
|
|
||||||
link below can edit it.
|
|
||||||
</p>
|
</p>
|
||||||
<div className="mb-20 grid grid-cols-12 gap-4">
|
<div className="mt-6 max-w-md text-slate-500">
|
||||||
<div className="col-span-11">
|
<div className="bg-info-50 rounded-lg p-6">
|
||||||
<TextInput
|
<p className="sm:tex-base text-sm">
|
||||||
disabled={true}
|
To keep your offer profile strictly anonymous, it is not linked to
|
||||||
isLabelHidden={true}
|
your user account. Only people who have the link below can edit
|
||||||
label="Edit link"
|
it. If you want to edit the profile in future, store the link
|
||||||
value={getProfileLink(profileId, token)}
|
somewhere.
|
||||||
|
</p>
|
||||||
|
<div className="mt-4 flex gap-4">
|
||||||
|
<div className="grow">
|
||||||
|
<TextInput
|
||||||
|
disabled={true}
|
||||||
|
isLabelHidden={true}
|
||||||
|
label="Edit link"
|
||||||
|
value={getProfileLink(profileId, token)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
icon={DocumentDuplicateIcon}
|
||||||
|
isLabelHidden={true}
|
||||||
|
label="Copy"
|
||||||
|
variant="info"
|
||||||
|
onClick={() => {
|
||||||
|
copyProfileLink(profileId, token);
|
||||||
|
showToast({
|
||||||
|
title: `Profile edit link copied to clipboard!`,
|
||||||
|
variant: 'success',
|
||||||
|
});
|
||||||
|
gaEvent({
|
||||||
|
action: 'offers.profile_submission_copy_edit_profile_link',
|
||||||
|
category: 'engagement',
|
||||||
|
label: 'Copy Edit Profile Link in Profile Submission',
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p className="mt-6 text-xs sm:text-sm">
|
||||||
|
If you do not want to manually store the link somewhere else, you
|
||||||
|
can add this offers profile to your user account by clicking the
|
||||||
|
button below. It will still only be editable by you.
|
||||||
|
</p>
|
||||||
|
<div className="mt-6">
|
||||||
|
<Button
|
||||||
|
disabled={isSavedQuery.isLoading || isSaved}
|
||||||
|
icon={isSaved ? CheckIcon : BookmarkSquareIcon}
|
||||||
|
isLoading={saveMutation.isLoading || isSavedQuery.isLoading}
|
||||||
|
label={isSaved ? 'Added to account' : 'Add to your account'}
|
||||||
|
size="sm"
|
||||||
|
variant="secondary"
|
||||||
|
onClick={handleSave}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Button
|
|
||||||
icon={DocumentDuplicateIcon}
|
|
||||||
isLabelHidden={true}
|
|
||||||
label="Copy"
|
|
||||||
variant="primary"
|
|
||||||
onClick={() => {
|
|
||||||
copyProfileLink(profileId, token);
|
|
||||||
showToast({
|
|
||||||
title: `Profile edit link copied to clipboard!`,
|
|
||||||
variant: 'success',
|
|
||||||
});
|
|
||||||
gaEvent({
|
|
||||||
action: 'offers.profile_submission_copy_edit_profile_link',
|
|
||||||
category: 'engagement',
|
|
||||||
label: 'Copy Edit Profile Link in Profile Submission',
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<p className="mb-5 text-slate-900">
|
|
||||||
If you do not want to keep the edit link, you can opt to save this
|
|
||||||
profile under your account's dashboard. It will still only be editable
|
|
||||||
by you.
|
|
||||||
</p>
|
|
||||||
<div className="mb-20">
|
|
||||||
<Button
|
|
||||||
disabled={isSavedQuery.isLoading || isSaved}
|
|
||||||
icon={isSaved ? CheckIcon : BookmarkSquareIcon}
|
|
||||||
isLoading={saveMutation.isLoading || isSavedQuery.isLoading}
|
|
||||||
label={isSaved ? 'Saved to user profile' : 'Save to user profile'}
|
|
||||||
variant="primary"
|
|
||||||
onClick={handleSave}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -15,10 +15,12 @@ export default function OffersSubmissionAnalysis({
|
|||||||
return (
|
return (
|
||||||
<div className="mb-8">
|
<div className="mb-8">
|
||||||
<h5 className="mb-8 text-center text-4xl font-bold text-slate-900">
|
<h5 className="mb-8 text-center text-4xl font-bold text-slate-900">
|
||||||
Result
|
Offer Analysis
|
||||||
</h5>
|
</h5>
|
||||||
{!analysis && (
|
{!analysis && (
|
||||||
<p className="mb-8 text-center">Error generating analysis.</p>
|
<p className="text-error-500 mb-8 text-center">
|
||||||
|
Error generating analysis.
|
||||||
|
</p>
|
||||||
)}
|
)}
|
||||||
{analysis && (
|
{analysis && (
|
||||||
<OfferAnalysis
|
<OfferAnalysis
|
||||||
|
@ -267,7 +267,7 @@ export default function OffersSubmissionForm({
|
|||||||
<div ref={pageRef} className="w-full overflow-y-scroll">
|
<div ref={pageRef} className="w-full overflow-y-scroll">
|
||||||
<div className="flex justify-center">
|
<div className="flex justify-center">
|
||||||
<div className="block w-full max-w-screen-md overflow-hidden rounded-lg sm:shadow-lg md:my-10">
|
<div className="block w-full max-w-screen-md overflow-hidden rounded-lg sm:shadow-lg md:my-10">
|
||||||
<div className="bg-primary-100 flex justify-center px-4 py-4 sm:px-6 lg:px-8">
|
<div className="flex justify-center bg-slate-100 px-4 py-4 sm:px-6 lg:px-8">
|
||||||
<Breadcrumbs
|
<Breadcrumbs
|
||||||
currentStep={step}
|
currentStep={step}
|
||||||
setStep={setStep}
|
setStep={setStep}
|
||||||
|
@ -78,48 +78,50 @@ export default function OffersSubmissionResult() {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{!getAnalysis.isLoading && (
|
{!getAnalysis.isLoading && (
|
||||||
<div ref={pageRef} className="fixed h-full w-full overflow-y-scroll">
|
<div ref={pageRef} className="w-full overflow-y-scroll">
|
||||||
<div className="mb-20 flex justify-center">
|
<div className="flex justify-center">
|
||||||
<div className="my-5 block w-full max-w-screen-md rounded-lg bg-white py-10 px-10 shadow-lg">
|
<div className="block w-full max-w-screen-md overflow-hidden rounded-lg sm:shadow-lg md:my-10">
|
||||||
<div className="mb-4 flex justify-end">
|
<div className="flex justify-center bg-slate-100 px-4 py-4 sm:px-6 lg:px-8">
|
||||||
<Breadcrumbs
|
<Breadcrumbs
|
||||||
currentStep={step}
|
currentStep={step}
|
||||||
setStep={setStep}
|
setStep={setStep}
|
||||||
steps={breadcrumbSteps}
|
steps={breadcrumbSteps}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{steps[step]}
|
<div className="bg-white p-6 sm:p-10">
|
||||||
{step === 0 && (
|
{steps[step]}
|
||||||
<div className="flex justify-end">
|
{step === 0 && (
|
||||||
<Button
|
<div className="flex justify-end">
|
||||||
disabled={false}
|
<Button
|
||||||
icon={ArrowRightIcon}
|
disabled={false}
|
||||||
label="Next"
|
icon={ArrowRightIcon}
|
||||||
variant="secondary"
|
label="Next"
|
||||||
onClick={() => setStep(step + 1)}
|
variant="primary"
|
||||||
/>
|
onClick={() => setStep(step + 1)}
|
||||||
</div>
|
/>
|
||||||
)}
|
</div>
|
||||||
{step === 1 && (
|
)}
|
||||||
<div className="flex items-center justify-between">
|
{step === 1 && (
|
||||||
<Button
|
<div className="flex items-center justify-between">
|
||||||
addonPosition="start"
|
<Button
|
||||||
icon={ArrowLeftIcon}
|
addonPosition="start"
|
||||||
label="Previous"
|
icon={ArrowLeftIcon}
|
||||||
variant="secondary"
|
label="Previous"
|
||||||
onClick={() => setStep(step - 1)}
|
variant="secondary"
|
||||||
/>
|
onClick={() => setStep(step - 1)}
|
||||||
<Button
|
/>
|
||||||
href={getProfilePath(
|
<Button
|
||||||
offerProfileId as string,
|
href={getProfilePath(
|
||||||
token as string,
|
offerProfileId as string,
|
||||||
)}
|
token as string,
|
||||||
icon={EyeIcon}
|
)}
|
||||||
label="View your profile"
|
icon={EyeIcon}
|
||||||
variant="primary"
|
label="View your profile"
|
||||||
/>
|
variant="primary"
|
||||||
</div>
|
/>
|
||||||
)}
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -12,10 +12,7 @@ import { createValidationRegex } from '~/utils/offers/zodRegex';
|
|||||||
import { createRouter } from '../context';
|
import { createRouter } from '../context';
|
||||||
|
|
||||||
const getOrder = (prefix: string) => {
|
const getOrder = (prefix: string) => {
|
||||||
if (prefix === '+') {
|
return prefix === '+' ? 'asc' : 'desc';
|
||||||
return 'asc';
|
|
||||||
}
|
|
||||||
return 'desc';
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const sortingKeysMap = {
|
const sortingKeysMap = {
|
||||||
|
Reference in New Issue
Block a user