mirror of
https://github.com/yangshun/tech-interview-handbook.git
synced 2025-07-27 20:22:33 +08:00
[offers][feat] add event tracking and save to profile in submisison page (#465)
* [offers][feat] add event tracking and save to profile in form * [offers][refactor] refactor feature page * [offers][fix] fix offer table border for action column
This commit is contained in:
@ -12,7 +12,6 @@ const navigationAuthenticated: ProductNavigationItems = [
|
||||
];
|
||||
|
||||
const config = {
|
||||
// TODO: Change this to your own GA4 measurement ID.
|
||||
googleAnalyticsMeasurementID: 'G-34XRGLEVCF',
|
||||
logo: (
|
||||
<img alt="Tech Offers Repo" className="h-8 w-auto" src="/offers-logo.svg" />
|
||||
|
@ -2,6 +2,7 @@ import { useRouter } from 'next/router';
|
||||
import { ArrowRightIcon, XMarkIcon } from '@heroicons/react/24/outline';
|
||||
import { Button, useToast } from '@tih/ui';
|
||||
|
||||
import { useGoogleAnalytics } from '~/components/global/GoogleAnalytics';
|
||||
import DashboardOfferCard from '~/components/offers/dashboard/DashboardOfferCard';
|
||||
|
||||
import { formatDate } from '~/utils/offers/time';
|
||||
@ -10,7 +11,6 @@ import { trpc } from '~/utils/trpc';
|
||||
import ProfilePhotoHolder from '../profile/ProfilePhotoHolder';
|
||||
|
||||
import type { UserProfile, UserProfileOffer } from '~/types/offers';
|
||||
|
||||
type Props = Readonly<{
|
||||
profile: UserProfile;
|
||||
}>;
|
||||
@ -22,6 +22,7 @@ export default function DashboardProfileCard({
|
||||
const router = useRouter();
|
||||
const trpcContext = trpc.useContext();
|
||||
const PROFILE_URL = `/offers/profile/${id}?token=${token}`;
|
||||
const { event: gaEvent } = useGoogleAnalytics();
|
||||
const removeSavedProfileMutation = trpc.useMutation(
|
||||
'offers.user.profile.removeFromUserProfile',
|
||||
{
|
||||
@ -97,7 +98,14 @@ export default function DashboardProfileCard({
|
||||
label="Read full profile"
|
||||
size="md"
|
||||
variant="secondary"
|
||||
onClick={() => router.push(PROFILE_URL)}
|
||||
onClick={() => {
|
||||
gaEvent({
|
||||
action: 'offers.view_profile_from_dashboard',
|
||||
category: 'engagement',
|
||||
label: 'View profile from dashboard',
|
||||
});
|
||||
router.push(PROFILE_URL);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
Before Width: | Height: | Size: 994 KiB After Width: | Height: | Size: 994 KiB |
Before Width: | Height: | Size: 923 KiB After Width: | Height: | Size: 923 KiB |
@ -1,9 +1,14 @@
|
||||
// Import { useState } from 'react';
|
||||
// import { setTimeout } from 'timers';
|
||||
import { useState } from 'react';
|
||||
import { DocumentDuplicateIcon } from '@heroicons/react/20/solid';
|
||||
import { BookmarkSquareIcon, CheckIcon } from '@heroicons/react/24/outline';
|
||||
import { Button, TextInput, useToast } from '@tih/ui';
|
||||
|
||||
import { useGoogleAnalytics } from '~/components/global/GoogleAnalytics';
|
||||
|
||||
import { copyProfileLink, getProfileLink } from '~/utils/offers/link';
|
||||
import { trpc } from '~/utils/trpc';
|
||||
|
||||
type OfferProfileSaveProps = Readonly<{
|
||||
profileId: string;
|
||||
@ -15,16 +20,39 @@ export default function OffersProfileSave({
|
||||
token,
|
||||
}: OfferProfileSaveProps) {
|
||||
const { showToast } = useToast();
|
||||
// Const [isSaving, setSaving] = useState(false);
|
||||
// const [isSaved, setSaved] = useState(false);
|
||||
const { event: gaEvent } = useGoogleAnalytics();
|
||||
const [isSaved, setSaved] = useState(false);
|
||||
|
||||
// Const saveProfile = () => {
|
||||
// setSaving(true);
|
||||
// setTimeout(() => {
|
||||
// setSaving(false);
|
||||
// setSaved(true);
|
||||
// }, 5);
|
||||
// };
|
||||
const saveMutation = trpc.useMutation(
|
||||
['offers.user.profile.addToUserProfile'],
|
||||
{
|
||||
onError: () => {
|
||||
showToast({
|
||||
title: `Failed to saved to dashboard!`,
|
||||
variant: 'failure',
|
||||
});
|
||||
},
|
||||
onSuccess: () => {
|
||||
showToast({
|
||||
title: `Saved to your repository!`,
|
||||
variant: 'success',
|
||||
});
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
const handleSave = () => {
|
||||
saveMutation.mutate({
|
||||
profileId,
|
||||
token: token as string,
|
||||
});
|
||||
setSaved(true);
|
||||
gaEvent({
|
||||
action: 'offers.profile_submission_save_to_profile',
|
||||
category: 'engagement',
|
||||
label: 'Save to profile in profile submission',
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex w-full justify-center">
|
||||
@ -57,24 +85,29 @@ export default function OffersProfileSave({
|
||||
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">
|
||||
<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 user account. It will still only be editable by
|
||||
you.
|
||||
profile under your account's respository. It will still only be
|
||||
editable by you.
|
||||
</p>
|
||||
<div className="mb-20">
|
||||
<Button
|
||||
disabled={isSaved}
|
||||
icon={isSaved ? CheckIcon : BookmarkSquareIcon}
|
||||
isLoading={isSaving}
|
||||
isLoading={saveMutation.isLoading}
|
||||
label={isSaved ? 'Saved to user profile' : 'Save to user profile'}
|
||||
variant="primary"
|
||||
onClick={saveProfile}
|
||||
onClick={handleSave}
|
||||
/>
|
||||
</div> */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -6,6 +6,7 @@ import { ArrowLeftIcon, ArrowRightIcon } from '@heroicons/react/20/solid';
|
||||
import { JobType } from '@prisma/client';
|
||||
import { Button } from '@tih/ui';
|
||||
|
||||
import { useGoogleAnalytics } from '~/components/global/GoogleAnalytics';
|
||||
import type { BreadcrumbStep } from '~/components/offers/Breadcrumb';
|
||||
import { Breadcrumbs } from '~/components/offers/Breadcrumb';
|
||||
import BackgroundForm from '~/components/offers/offersSubmission/submissionForm/BackgroundForm';
|
||||
@ -101,6 +102,7 @@ export default function OffersSubmissionForm({
|
||||
token: editToken,
|
||||
});
|
||||
const [isSubmitted, setIsSubmitted] = useState(false);
|
||||
const { event: gaEvent } = useGoogleAnalytics();
|
||||
|
||||
const router = useRouter();
|
||||
const pageRef = useRef<HTMLDivElement>(null);
|
||||
@ -215,6 +217,11 @@ export default function OffersSubmissionForm({
|
||||
} else {
|
||||
createOrUpdateMutation.mutate({ background, offers });
|
||||
}
|
||||
gaEvent({
|
||||
action: 'offers.submit_profile',
|
||||
category: 'submission',
|
||||
label: 'Submit profile',
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
@ -278,7 +285,14 @@ export default function OffersSubmissionForm({
|
||||
icon={ArrowRightIcon}
|
||||
label="Next"
|
||||
variant="secondary"
|
||||
onClick={() => goToNextStep(step)}
|
||||
onClick={() => {
|
||||
goToNextStep(step);
|
||||
gaEvent({
|
||||
action: 'offers.profile_submission_navigate_next',
|
||||
category: 'submission',
|
||||
label: 'Navigate next',
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
@ -288,7 +302,14 @@ export default function OffersSubmissionForm({
|
||||
icon={ArrowLeftIcon}
|
||||
label="Previous"
|
||||
variant="secondary"
|
||||
onClick={() => setStep(step - 1)}
|
||||
onClick={() => {
|
||||
setStep(step - 1);
|
||||
gaEvent({
|
||||
action: 'offers.profile_submission_navigation_back',
|
||||
category: 'submission',
|
||||
label: 'Navigate back',
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
disabled={isSubmitting || isSubmitSuccessful}
|
||||
|
@ -9,6 +9,7 @@ import {
|
||||
useToast,
|
||||
} from '@tih/ui';
|
||||
|
||||
import { useGoogleAnalytics } from '~/components/global/GoogleAnalytics';
|
||||
import ExpandableCommentCard from '~/components/offers/profile/comments/ExpandableCommentCard';
|
||||
import Tooltip from '~/components/offers/util/Tooltip';
|
||||
|
||||
@ -40,6 +41,7 @@ export default function ProfileComments({
|
||||
const [currentReply, setCurrentReply] = useState<string>('');
|
||||
const [replies, setReplies] = useState<Array<Reply>>();
|
||||
const { showToast } = useToast();
|
||||
const { event: gaEvent } = useGoogleAnalytics();
|
||||
|
||||
const commentsQuery = trpc.useQuery(
|
||||
['offers.comments.getComments', { profileId }],
|
||||
@ -121,6 +123,11 @@ export default function ProfileComments({
|
||||
variant="secondary"
|
||||
onClick={() => {
|
||||
copyProfileLink(profileId, token);
|
||||
gaEvent({
|
||||
action: 'offers.copy_profile_edit_link',
|
||||
category: 'engagement',
|
||||
label: 'Copy Profile Edit Link',
|
||||
});
|
||||
showToast({
|
||||
title: `Profile edit link copied to clipboard!`,
|
||||
variant: 'success',
|
||||
@ -140,6 +147,11 @@ export default function ProfileComments({
|
||||
variant="secondary"
|
||||
onClick={() => {
|
||||
copyProfileLink(profileId);
|
||||
gaEvent({
|
||||
action: 'offers.copy_profile_public_link',
|
||||
category: 'engagement',
|
||||
label: 'Copy Profile Public Link',
|
||||
});
|
||||
showToast({
|
||||
title: `Public profile link copied to clipboard!`,
|
||||
variant: 'success',
|
||||
|
@ -27,7 +27,7 @@ export default function OfferTableRow({
|
||||
<td className="py-4 px-6">{formatDate(monthYearReceived)}</td>
|
||||
<td
|
||||
className={clsx(
|
||||
'sticky right-0 bg-white py-4 px-6 drop-shadow md:drop-shadow-none',
|
||||
'sticky right-0 py-4 px-6 drop-shadow md:drop-shadow-none',
|
||||
)}>
|
||||
<Link
|
||||
className="text-primary-600 dark:text-primary-500 font-medium hover:underline"
|
||||
|
@ -2,6 +2,7 @@ import clsx from 'clsx';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { DropdownMenu, Spinner } from '@tih/ui';
|
||||
|
||||
import { useGoogleAnalytics } from '~/components/global/GoogleAnalytics';
|
||||
import OffersTablePagination from '~/components/offers/table/OffersTablePagination';
|
||||
import {
|
||||
OfferTableFilterOptions,
|
||||
@ -39,6 +40,7 @@ export default function OffersTable({
|
||||
const [selectedFilter, setSelectedFilter] = useState(
|
||||
OfferTableFilterOptions[0].value,
|
||||
);
|
||||
const { event: gaEvent } = useGoogleAnalytics();
|
||||
useEffect(() => {
|
||||
setPagination({
|
||||
currentPage: 0,
|
||||
@ -90,13 +92,18 @@ export default function OffersTable({
|
||||
label={itemLabel}
|
||||
onClick={() => {
|
||||
setSelectedTab(value);
|
||||
gaEvent({
|
||||
action: `offers.table_filter_yoe_category_${value}`,
|
||||
category: 'engagement',
|
||||
label: 'Filter by YOE category',
|
||||
});
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</DropdownMenu>
|
||||
<div className="divide-x-slate-200 flex items-center space-x-4 divide-x">
|
||||
<div className="justify-left flex items-center space-x-2">
|
||||
<span>All offers in</span>
|
||||
<span>View all offers in</span>
|
||||
<CurrencySelector
|
||||
handleCurrencyChange={(value: string) => setCurrency(value)}
|
||||
selectedCurrency={currency}
|
||||
|
@ -8,11 +8,11 @@ import {
|
||||
UsersIcon,
|
||||
} from '@heroicons/react/24/outline';
|
||||
|
||||
import offersAnalysis from '~/components/offers/landing/images/offers-analysis.png';
|
||||
import offersBrowse from '~/components/offers/landing/images/offers-browse.png';
|
||||
import offersProfile from '~/components/offers/landing/images/offers-profile.png';
|
||||
import LeftTextCard from '~/components/offers/landing/LeftTextCard';
|
||||
import RightTextCard from '~/components/offers/landing/RightTextCard';
|
||||
import offersAnalysis from '~/components/offers/features/images/offers-analysis.png';
|
||||
import offersBrowse from '~/components/offers/features/images/offers-browse.png';
|
||||
import offersProfile from '~/components/offers/features/images/offers-profile.png';
|
||||
import LeftTextCard from '~/components/offers/features/LeftTextCard';
|
||||
import RightTextCard from '~/components/offers/features/RightTextCard';
|
||||
import { HOME_URL } from '~/components/offers/types';
|
||||
|
||||
const features = [
|
||||
@ -38,32 +38,32 @@ const features = [
|
||||
|
||||
const footerNavigation = {
|
||||
social: [
|
||||
{
|
||||
href: '#',
|
||||
icon: (props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) => (
|
||||
<svg fill="currentColor" viewBox="0 0 24 24" {...props}>
|
||||
<path
|
||||
clipRule="evenodd"
|
||||
d="M22 12c0-5.523-4.477-10-10-10S2 6.477 2 12c0 4.991 3.657 9.128 8.438 9.878v-6.987h-2.54V12h2.54V9.797c0-2.506 1.492-3.89 3.777-3.89 1.094 0 2.238.195 2.238.195v2.46h-1.26c-1.243 0-1.63.771-1.63 1.562V12h2.773l-.443 2.89h-2.33v6.988C18.343 21.128 22 16.991 22 12z"
|
||||
fillRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
),
|
||||
name: 'Facebook',
|
||||
},
|
||||
{
|
||||
href: '#',
|
||||
icon: (props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) => (
|
||||
<svg fill="currentColor" viewBox="0 0 24 24" {...props}>
|
||||
<path
|
||||
clipRule="evenodd"
|
||||
d="M12.315 2c2.43 0 2.784.013 3.808.06 1.064.049 1.791.218 2.427.465a4.902 4.902 0 011.772 1.153 4.902 4.902 0 011.153 1.772c.247.636.416 1.363.465 2.427.048 1.067.06 1.407.06 4.123v.08c0 2.643-.012 2.987-.06 4.043-.049 1.064-.218 1.791-.465 2.427a4.902 4.902 0 01-1.153 1.772 4.902 4.902 0 01-1.772 1.153c-.636.247-1.363.416-2.427.465-1.067.048-1.407.06-4.123.06h-.08c-2.643 0-2.987-.012-4.043-.06-1.064-.049-1.791-.218-2.427-.465a4.902 4.902 0 01-1.772-1.153 4.902 4.902 0 01-1.153-1.772c-.247-.636-.416-1.363-.465-2.427-.047-1.024-.06-1.379-.06-3.808v-.63c0-2.43.013-2.784.06-3.808.049-1.064.218-1.791.465-2.427a4.902 4.902 0 011.153-1.772A4.902 4.902 0 015.45 2.525c.636-.247 1.363-.416 2.427-.465C8.901 2.013 9.256 2 11.685 2h.63zm-.081 1.802h-.468c-2.456 0-2.784.011-3.807.058-.975.045-1.504.207-1.857.344-.467.182-.8.398-1.15.748-.35.35-.566.683-.748 1.15-.137.353-.3.882-.344 1.857-.047 1.023-.058 1.351-.058 3.807v.468c0 2.456.011 2.784.058 3.807.045.975.207 1.504.344 1.857.182.466.399.8.748 1.15.35.35.683.566 1.15.748.353.137.882.3 1.857.344 1.054.048 1.37.058 4.041.058h.08c2.597 0 2.917-.01 3.96-.058.976-.045 1.505-.207 1.858-.344.466-.182.8-.398 1.15-.748.35-.35.566-.683.748-1.15.137-.353.3-.882.344-1.857.048-1.055.058-1.37.058-4.041v-.08c0-2.597-.01-2.917-.058-3.96-.045-.976-.207-1.505-.344-1.858a3.097 3.097 0 00-.748-1.15 3.098 3.098 0 00-1.15-.748c-.353-.137-.882-.3-1.857-.344-1.023-.047-1.351-.058-3.807-.058zM12 6.865a5.135 5.135 0 110 10.27 5.135 5.135 0 010-10.27zm0 1.802a3.333 3.333 0 100 6.666 3.333 3.333 0 000-6.666zm5.338-3.205a1.2 1.2 0 110 2.4 1.2 1.2 0 010-2.4z"
|
||||
fillRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
),
|
||||
name: 'Instagram',
|
||||
},
|
||||
// {
|
||||
// href: '#',
|
||||
// icon: (props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) => (
|
||||
// <svg fill="currentColor" viewBox="0 0 24 24" {...props}>
|
||||
// <path
|
||||
// clipRule="evenodd"
|
||||
// d="M22 12c0-5.523-4.477-10-10-10S2 6.477 2 12c0 4.991 3.657 9.128 8.438 9.878v-6.987h-2.54V12h2.54V9.797c0-2.506 1.492-3.89 3.777-3.89 1.094 0 2.238.195 2.238.195v2.46h-1.26c-1.243 0-1.63.771-1.63 1.562V12h2.773l-.443 2.89h-2.33v6.988C18.343 21.128 22 16.991 22 12z"
|
||||
// fillRule="evenodd"
|
||||
// />
|
||||
// </svg>
|
||||
// ),
|
||||
// name: 'Facebook',
|
||||
// },
|
||||
// {
|
||||
// href: '#',
|
||||
// icon: (props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) => (
|
||||
// <svg fill="currentColor" viewBox="0 0 24 24" {...props}>
|
||||
// <path
|
||||
// clipRule="evenodd"
|
||||
// d="M12.315 2c2.43 0 2.784.013 3.808.06 1.064.049 1.791.218 2.427.465a4.902 4.902 0 011.772 1.153 4.902 4.902 0 011.153 1.772c.247.636.416 1.363.465 2.427.048 1.067.06 1.407.06 4.123v.08c0 2.643-.012 2.987-.06 4.043-.049 1.064-.218 1.791-.465 2.427a4.902 4.902 0 01-1.153 1.772 4.902 4.902 0 01-1.772 1.153c-.636.247-1.363.416-2.427.465-1.067.048-1.407.06-4.123.06h-.08c-2.643 0-2.987-.012-4.043-.06-1.064-.049-1.791-.218-2.427-.465a4.902 4.902 0 01-1.772-1.153 4.902 4.902 0 01-1.153-1.772c-.247-.636-.416-1.363-.465-2.427-.047-1.024-.06-1.379-.06-3.808v-.63c0-2.43.013-2.784.06-3.808.049-1.064.218-1.791.465-2.427a4.902 4.902 0 011.153-1.772A4.902 4.902 0 015.45 2.525c.636-.247 1.363-.416 2.427-.465C8.901 2.013 9.256 2 11.685 2h.63zm-.081 1.802h-.468c-2.456 0-2.784.011-3.807.058-.975.045-1.504.207-1.857.344-.467.182-.8.398-1.15.748-.35.35-.566.683-.748 1.15-.137.353-.3.882-.344 1.857-.047 1.023-.058 1.351-.058 3.807v.468c0 2.456.011 2.784.058 3.807.045.975.207 1.504.344 1.857.182.466.399.8.748 1.15.35.35.683.566 1.15.748.353.137.882.3 1.857.344 1.054.048 1.37.058 4.041.058h.08c2.597 0 2.917-.01 3.96-.058.976-.045 1.505-.207 1.858-.344.466-.182.8-.398 1.15-.748.35-.35.566-.683.748-1.15.137-.353.3-.882.344-1.857.048-1.055.058-1.37.058-4.041v-.08c0-2.597-.01-2.917-.058-3.96-.045-.976-.207-1.505-.344-1.858a3.097 3.097 0 00-.748-1.15 3.098 3.098 0 00-1.15-.748c-.353-.137-.882-.3-1.857-.344-1.023-.047-1.351-.058-3.807-.058zM12 6.865a5.135 5.135 0 110 10.27 5.135 5.135 0 010-10.27zm0 1.802a3.333 3.333 0 100 6.666 3.333 3.333 0 000-6.666zm5.338-3.205a1.2 1.2 0 110 2.4 1.2 1.2 0 010-2.4z"
|
||||
// fillRule="evenodd"
|
||||
// />
|
||||
// </svg>
|
||||
// ),
|
||||
// name: 'Instagram',
|
||||
// },
|
||||
{
|
||||
href: 'https://github.com/yangshun/tech-interview-handbook',
|
||||
icon: (props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) => (
|
||||
@ -87,6 +87,11 @@ export default function LandingPage() {
|
||||
{/* Hero section */}
|
||||
<div className="relative h-full">
|
||||
<div className="relative px-4 py-16 sm:px-6 sm:py-24 lg:py-32 lg:px-8">
|
||||
<img
|
||||
alt="Tech Offers Repo"
|
||||
className="mx-auto mb-8 w-auto"
|
||||
src="/offers-logo.svg"
|
||||
/>
|
||||
<h1 className="text-center text-4xl font-bold tracking-tight sm:text-5xl lg:text-6xl">
|
||||
<span>Choosing offers </span>
|
||||
<span className="from-primary-600 -mb-1 mr-2 bg-gradient-to-r to-purple-500 bg-clip-text pb-1 pr-4 italic text-transparent">
|
||||
@ -121,16 +126,16 @@ export default function LandingPage() {
|
||||
/>
|
||||
<div className="relative">
|
||||
<LeftTextCard
|
||||
description="An offer profile includes not only offers that a person received in their application cycle, but also background information such as education and work experience. Use offer profiles to help you better contextualize offers."
|
||||
description="Filter relevant offers by job title, company, submission date, salary and more."
|
||||
icon={
|
||||
<InformationCircleIcon
|
||||
<TableCellsIcon
|
||||
aria-hidden="true"
|
||||
className="h-6 w-6 text-white"
|
||||
/>
|
||||
}
|
||||
imageAlt="Offer table page"
|
||||
imageSrc={offersProfile}
|
||||
title="Choosing an offer needs context"
|
||||
imageSrc={offersBrowse}
|
||||
title="Stay informed of recent offers"
|
||||
/>
|
||||
</div>
|
||||
<div className="mt-36">
|
||||
@ -149,16 +154,16 @@ export default function LandingPage() {
|
||||
</div>
|
||||
<div className="mt-36">
|
||||
<LeftTextCard
|
||||
description="Filter relevant offers by job title, company, submission date, salary and more."
|
||||
description="An offer profile includes not only offers that a person received in their application cycle, but also background information such as education and work experience. Use offer profiles to help you better contextualize offers."
|
||||
icon={
|
||||
<TableCellsIcon
|
||||
<InformationCircleIcon
|
||||
aria-hidden="true"
|
||||
className="h-6 w-6 text-white"
|
||||
/>
|
||||
}
|
||||
imageAlt="Offer table page"
|
||||
imageSrc={offersBrowse}
|
||||
title="Stay informed of recent offers"
|
||||
imageSrc={offersProfile}
|
||||
title="Choosing an offer needs context"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -2,6 +2,7 @@ import Link from 'next/link';
|
||||
import { useState } from 'react';
|
||||
import { Banner } from '@tih/ui';
|
||||
|
||||
import { useGoogleAnalytics } from '~/components/global/GoogleAnalytics';
|
||||
import OffersTable from '~/components/offers/table/OffersTable';
|
||||
import CompaniesTypeahead from '~/components/shared/CompaniesTypeahead';
|
||||
import JobTitlesTypeahead from '~/components/shared/JobTitlesTypahead';
|
||||
@ -9,6 +10,7 @@ import JobTitlesTypeahead from '~/components/shared/JobTitlesTypahead';
|
||||
export default function OffersHomePage() {
|
||||
const [jobTitleFilter, setjobTitleFilter] = useState('software-engineer');
|
||||
const [companyFilter, setCompanyFilter] = useState('');
|
||||
const { event: gaEvent } = useGoogleAnalytics();
|
||||
|
||||
return (
|
||||
<main className="flex-1 overflow-y-auto">
|
||||
@ -40,6 +42,11 @@ export default function OffersHomePage() {
|
||||
onSelect={(option) => {
|
||||
if (option) {
|
||||
setjobTitleFilter(option.value);
|
||||
gaEvent({
|
||||
action: `offers.table_filter_job_title_${option.value}`,
|
||||
category: 'engagement',
|
||||
label: 'Filter by job title',
|
||||
});
|
||||
}
|
||||
}}
|
||||
/>
|
||||
@ -50,6 +57,11 @@ export default function OffersHomePage() {
|
||||
onSelect={(option) => {
|
||||
if (option) {
|
||||
setCompanyFilter(option.value);
|
||||
gaEvent({
|
||||
action: 'offers.table_filter_company',
|
||||
category: 'engagement',
|
||||
label: 'Filter by company',
|
||||
});
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
@ -70,7 +70,12 @@ export default function OffersSubmissionResult() {
|
||||
return (
|
||||
<>
|
||||
{getAnalysis.isLoading && (
|
||||
<Spinner className="m-10" display="block" size="lg" />
|
||||
<div className="flex h-screen w-screen">
|
||||
<div className="m-auto mx-auto w-screen justify-center">
|
||||
<Spinner display="block" size="lg" />
|
||||
<div className="text-center">Loading...</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{!getAnalysis.isLoading && (
|
||||
<div ref={pageRef} className="fixed h-full w-full overflow-y-scroll">
|
||||
@ -98,6 +103,7 @@ export default function OffersSubmissionResult() {
|
||||
{step === 1 && (
|
||||
<div className="flex items-center justify-between">
|
||||
<Button
|
||||
addonPosition="start"
|
||||
icon={ArrowLeftIcon}
|
||||
label="Previous"
|
||||
variant="secondary"
|
||||
|
Reference in New Issue
Block a user