[web] marketing/testimonials: add Tyler Holdren
This commit is contained in:
parent
05e40bf6f0
commit
5cfb117809
|
|
@ -1 +1,3 @@
|
|||
<svg viewBox="0 0 384 512" xmlns="http://www.w3.org/2000/svg"><path fill="#808080" d="m318.7 268.7c-.2-36.7 16.4-64.4 50-84.8-18.8-26.9-47.2-41.7-84.7-44.6-35.5-2.8-74.3 20.7-88.5 20.7-15 0-49.4-19.7-76.4-19.7-55.8.9-115.1 44.5-115.1 133.2q0 39.3 14.4 81.2c12.8 36.7 59 126.7 107.2 125.2 25.2-.6 43-17.9 75.8-17.9 31.8 0 48.3 17.9 76.4 17.9 48.6-.7 90.4-82.5 102.6-119.3-65.2-30.7-61.7-90-61.7-91.9zm-56.6-164.2c27.3-32.4 24.8-61.9 24-72.5-24.1 1.4-52 16.4-67.9 34.9-17.5 19.8-27.8 44.3-25.6 71.9 26.1 2 49.9-11.4 69.5-34.3z"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="814" height="1000">
|
||||
<path d="M788.1 340.9c-5.8 4.5-108.2 62.2-108.2 190.5 0 148.4 130.3 200.9 134.2 202.2-.6 3.2-20.7 71.9-68.7 141.9-42.8 61.6-87.5 123.1-155.5 123.1s-85.5-39.5-164-39.5c-76.5 0-103.7 40.8-165.9 40.8s-105.6-57-155.5-127C46.7 790.7 0 663 0 541.8c0-194.4 126.4-297.5 250.8-297.5 66.1 0 121.2 43.4 162.7 43.4 39.5 0 101.1-46 176.3-46 28.5 0 130.9 2.6 198.3 99.2zm-234-181.5c31.1-36.9 53.1-88.1 53.1-139.3 0-7.1-.6-14.3-1.9-20.1-50.6 1.9-110.8 33.7-147.1 75.8-28.5 32.4-55.1 83.6-55.1 135.5 0 7.8 1.3 15.6 1.9 18.1 3.2.6 8.4 1.3 13.6 1.3 45.4 0 102.5-30.4 135.5-71.3z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 534 B After Width: | Height: | Size: 660 B |
Binary file not shown.
|
After Width: | Height: | Size: 39 KiB |
|
|
@ -9,6 +9,7 @@ import Anchor from '~/components/ui/Anchor';
|
|||
import Avatar from '~/components/ui/Avatar';
|
||||
import Divider from '~/components/ui/Divider';
|
||||
import { headingCVA } from '~/components/ui/Heading';
|
||||
import Img from '~/components/ui/Img';
|
||||
import Text, { textVariants } from '~/components/ui/Text';
|
||||
import { themeTextSubtitleColor } from '~/components/ui/theme';
|
||||
|
||||
|
|
@ -20,6 +21,9 @@ type TestimonialCardProps = Readonly<{
|
|||
anonymous: boolean;
|
||||
authorThumbnailUrl?: string | null;
|
||||
authorUrl?: string | null;
|
||||
companyLogoUrl?: string | null;
|
||||
createdAt: string;
|
||||
featuredOffer?: string | null;
|
||||
id: string;
|
||||
location?: string | null;
|
||||
name?: string | null;
|
||||
|
|
@ -28,15 +32,33 @@ type TestimonialCardProps = Readonly<{
|
|||
variant?: 'compact' | 'full';
|
||||
}>;
|
||||
|
||||
function TestimonialCard({
|
||||
function formatDate(
|
||||
inputDate: string, // YYYY-MM-DD format
|
||||
) {
|
||||
const date = new Date(inputDate);
|
||||
const options: Intl.DateTimeFormatOptions = {
|
||||
month: 'short',
|
||||
year: 'numeric',
|
||||
};
|
||||
const formatter = new Intl.DateTimeFormat('en-US', options);
|
||||
|
||||
return formatter.format(date);
|
||||
}
|
||||
|
||||
function AuthTestimonialSliderCard({
|
||||
authorThumbnailUrl,
|
||||
authorUrl,
|
||||
companyLogoUrl,
|
||||
createdAt,
|
||||
featuredOffer,
|
||||
location,
|
||||
name,
|
||||
testimonial,
|
||||
title,
|
||||
variant = 'full',
|
||||
}: TestimonialCardProps) {
|
||||
const intl = useIntl();
|
||||
|
||||
return (
|
||||
<div className={clsx('flex flex-col justify-between gap-6')}>
|
||||
<div className={clsx('flex items-center gap-4', themeTextSubtitleColor)}>
|
||||
|
|
@ -66,50 +88,78 @@ function TestimonialCard({
|
|||
{testimonial}
|
||||
</blockquote>
|
||||
<figcaption
|
||||
className={clsx('flex flex-col gap-4 sm:flex-row sm:items-center')}>
|
||||
className={clsx('flex flex-col gap-5 sm:flex-row sm:items-center')}>
|
||||
{authorThumbnailUrl && (
|
||||
<Avatar
|
||||
alt={name ?? ''}
|
||||
decoding="async"
|
||||
loading="lazy"
|
||||
size="lg"
|
||||
src={authorThumbnailUrl}
|
||||
/>
|
||||
<div className="relative">
|
||||
<Avatar
|
||||
alt={name ?? ''}
|
||||
decoding="async"
|
||||
loading="lazy"
|
||||
size="lg"
|
||||
src={authorThumbnailUrl}
|
||||
/>
|
||||
{featuredOffer && companyLogoUrl && (
|
||||
<div
|
||||
className={clsx(
|
||||
'grid place-items-center rounded-full p-1',
|
||||
'absolute -bottom-0 -right-2',
|
||||
'bg-white',
|
||||
)}>
|
||||
<Img
|
||||
alt={featuredOffer}
|
||||
className={clsx('size-4', 'object-contain')}
|
||||
src={companyLogoUrl}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
className={clsx(
|
||||
'flex gap-x-2 gap-y-0.5',
|
||||
variant === 'full' ? 'flex-row flex-wrap' : 'flex-col',
|
||||
)}>
|
||||
{name &&
|
||||
(() => {
|
||||
if (!authorUrl) {
|
||||
return (
|
||||
<Text size="body1" weight="medium">
|
||||
{name}
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
<div className="flex flex-col">
|
||||
<div>
|
||||
{name &&
|
||||
(() => {
|
||||
if (!authorUrl) {
|
||||
return (
|
||||
<Text size="body1" weight="medium">
|
||||
{name}
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Anchor
|
||||
className={textVariants({
|
||||
size: 'body1',
|
||||
weight: 'medium',
|
||||
})}
|
||||
href={authorUrl}
|
||||
variant="flat">
|
||||
{name}
|
||||
</Anchor>
|
||||
);
|
||||
})()}
|
||||
<Text
|
||||
className="block"
|
||||
color="secondary"
|
||||
size="body1"
|
||||
weight="medium">
|
||||
{[title, location].filter(Boolean).join(', ')}
|
||||
</Text>
|
||||
return (
|
||||
<Anchor
|
||||
className={textVariants({
|
||||
size: 'body1',
|
||||
weight: 'medium',
|
||||
})}
|
||||
href={authorUrl}
|
||||
variant="flat">
|
||||
{name}
|
||||
</Anchor>
|
||||
);
|
||||
})()}
|
||||
<Text color="secondary" size="body1" weight="medium">
|
||||
, {[title, location].filter(Boolean).join(', ')}
|
||||
</Text>
|
||||
</div>
|
||||
<div>
|
||||
{featuredOffer && (
|
||||
<Text color="secondary" size="body2">
|
||||
{intl.formatMessage({
|
||||
defaultMessage: 'Offer from',
|
||||
description: 'Offer from companies',
|
||||
id: '9R/+sv',
|
||||
})}{' '}
|
||||
<Text color="subtitle" weight="medium">
|
||||
{featuredOffer}
|
||||
</Text>
|
||||
,{' '}
|
||||
</Text>
|
||||
)}
|
||||
<Text color="secondary" size="body2">
|
||||
{formatDate(createdAt)}
|
||||
</Text>
|
||||
</div>
|
||||
</div>
|
||||
</figcaption>
|
||||
</div>
|
||||
|
|
@ -122,15 +172,20 @@ type Props = Readonly<{
|
|||
|
||||
export default function AuthTestimonialSlider({ variant = 'full' }: Props) {
|
||||
const intl = useIntl();
|
||||
const testimonials = InterviewsMarketingTestimonialsDict(intl);
|
||||
const marketingTestimonials = InterviewsMarketingTestimonialsDict(intl);
|
||||
const [authTestimonials, setAuthTestimonials] = useState(() =>
|
||||
shuffle([
|
||||
testimonials.cliffordFung,
|
||||
testimonials.yugantJoshi,
|
||||
testimonials.deannaTran,
|
||||
testimonials.locChuong,
|
||||
testimonials.edWang,
|
||||
testimonials.lunghaoLee,
|
||||
marketingTestimonials.tylerHoldren,
|
||||
marketingTestimonials.jessieShen,
|
||||
marketingTestimonials.praveenKumar,
|
||||
marketingTestimonials.faithMorante,
|
||||
marketingTestimonials.anubhavKhanna,
|
||||
marketingTestimonials.lamTran,
|
||||
marketingTestimonials.cliffordFung,
|
||||
marketingTestimonials.yugantJoshi,
|
||||
marketingTestimonials.deannaTran,
|
||||
marketingTestimonials.locChuong,
|
||||
marketingTestimonials.edWang,
|
||||
]),
|
||||
);
|
||||
const [currentIndex, setCurrentIndex] = useState(0);
|
||||
|
|
@ -166,7 +221,7 @@ export default function AuthTestimonialSlider({ variant = 'full' }: Props) {
|
|||
exit={{ opacity: 0 }}
|
||||
initial={{ opacity: 0 }}
|
||||
transition={{ duration: 1, ease: 'easeInOut' }}>
|
||||
<TestimonialCard
|
||||
<AuthTestimonialSliderCard
|
||||
{...authTestimonials[currentIndex]}
|
||||
variant={variant}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ export default function InterviewsMarketingHero() {
|
|||
});
|
||||
|
||||
const testimonials = [
|
||||
marketingTestimonials.tylerHoldren,
|
||||
marketingTestimonials.jessieShen,
|
||||
marketingTestimonials.praveenKumar,
|
||||
marketingTestimonials.faithMorante,
|
||||
|
|
|
|||
|
|
@ -1171,6 +1171,26 @@ export function InterviewsMarketingTestimonialsDict(intl: IntlShape) {
|
|||
}),
|
||||
title: 'Frontend Engineer',
|
||||
};
|
||||
const tylerHoldren: InterviewsMarketingTestimonial = {
|
||||
anonymous: false,
|
||||
authorThumbnailUrl: '/img/testimonials/users/tyler-holdren.webp',
|
||||
authorUrl: 'https://www.linkedin.com/in/tyler-holdren/',
|
||||
companyLogoUrl: '/img/testimonials/company/apple.svg',
|
||||
createdAt: '2025-09-04',
|
||||
featured: true,
|
||||
featuredOffer: 'Apple',
|
||||
id: 'tyler-holdren',
|
||||
location: 'New York, US',
|
||||
name: 'Tyler Holdren',
|
||||
offers: [],
|
||||
testimonial: intl.formatMessage({
|
||||
defaultMessage:
|
||||
"GreatFrontEnd completely transformed my interview prep. I went from feeling uncertain in my JS fundamentals to being able to impress my interviewers with my depth of knowledge and understanding. The coding solutions are official, optimal, and explained by the authors with unmatched clarity, rigor, and evidence. The system design docs are also next-level, breaking down front-end architecture in a way that's clear and approachable, which enabled me to speak confidently in my interviews. I directly attribute my success in navigating the interview landscape to consistent, focused effort and the quality of the content on this platform.",
|
||||
description: 'User testimonial for GreatFrontEnd Interviews',
|
||||
id: 'PMSHEJ',
|
||||
}),
|
||||
title: 'Software Engineer',
|
||||
};
|
||||
// Const template: InterviewsMarketingTestimonial = {
|
||||
// anonymous: false,
|
||||
// authorThumbnailUrl: 'TO_BE_FILLED',
|
||||
|
|
@ -1242,6 +1262,7 @@ export function InterviewsMarketingTestimonialsDict(intl: IntlShape) {
|
|||
skarKing,
|
||||
skykillz,
|
||||
t4d95,
|
||||
tylerHoldren,
|
||||
uncleTito,
|
||||
vali,
|
||||
vietnam,
|
||||
|
|
|
|||
Loading…
Reference in New Issue