118 lines
4.3 KiB
TypeScript
118 lines
4.3 KiB
TypeScript
import React from 'react';
|
|
import Image from 'next/image';
|
|
import Reveal from '@/components/Reveal';
|
|
import { Badge, Heading } from '@/components/ui';
|
|
import TrackedLink from '@/components/analytics/TrackedLink';
|
|
import { getButtonClasses, ButtonOverlay } from '@/components/ui/Button';
|
|
|
|
export interface TeamProfileProps {
|
|
name: string;
|
|
role: string;
|
|
image?: any;
|
|
quote?: string;
|
|
description?: string;
|
|
linkedinUrl?: string;
|
|
linkedinLabel?: string;
|
|
colorScheme?: 'light' | 'dark';
|
|
layout?: 'imageLeft' | 'imageRight';
|
|
}
|
|
|
|
export const TeamProfile: React.FC<TeamProfileProps> = (props) => {
|
|
const {
|
|
name,
|
|
role,
|
|
image,
|
|
quote,
|
|
description,
|
|
linkedinUrl,
|
|
linkedinLabel,
|
|
colorScheme,
|
|
layout,
|
|
} = props;
|
|
|
|
const imgSrc = image?.sizes?.card?.url || image?.url;
|
|
const isDark = colorScheme === 'dark';
|
|
const isImageRight = layout === 'imageRight';
|
|
|
|
return (
|
|
<article className="relative bg-white overflow-hidden">
|
|
<div className="flex flex-col lg:flex-row">
|
|
<Reveal
|
|
className={`w-full lg:w-1/2 p-6 md:p-24 lg:p-32 flex flex-col justify-center relative ${isImageRight ? 'order-2 lg:order-1' : 'order-2'} ${isDark ? 'bg-primary-dark text-white' : 'bg-neutral-light text-saturated'}`}
|
|
>
|
|
<div className="relative z-10">
|
|
<Badge variant={isDark ? 'accent' : 'saturated'} className="mb-4 md:mb-8">
|
|
{role}
|
|
</Badge>
|
|
<Heading
|
|
level={2}
|
|
className={`${isDark ? 'text-white' : 'text-saturated'} mb-6 md:mb-10 text-3xl md:text-5xl`}
|
|
>
|
|
{name}
|
|
</Heading>
|
|
{quote && (
|
|
<div className="relative mb-6 md:mb-12">
|
|
<div
|
|
className={`absolute -left-4 md:-left-8 top-0 bottom-0 w-1 md:w-1.5 ${isDark ? 'bg-accent' : 'bg-saturated'} rounded-full`}
|
|
/>
|
|
<p
|
|
className={`text-lg md:text-2xl font-bold italic leading-relaxed pl-5 md:pl-8 ${isDark ? 'text-white/90' : 'text-text-secondary'}`}
|
|
>
|
|
{quote}
|
|
</p>
|
|
</div>
|
|
)}
|
|
{description && (
|
|
<p
|
|
className={`text-base md:text-xl leading-relaxed mb-6 md:mb-12 max-w-xl ${isDark ? 'text-white/70' : 'text-text-secondary'}`}
|
|
>
|
|
{description}
|
|
</p>
|
|
)}
|
|
{linkedinUrl && (
|
|
<TrackedLink
|
|
href={linkedinUrl}
|
|
className={getButtonClasses(isDark ? 'accent' : 'saturated', 'lg')}
|
|
eventProperties={{
|
|
type: 'social_linkedin',
|
|
person: name,
|
|
location: 'team_page',
|
|
}}
|
|
>
|
|
<span className={`relative z-10 flex items-center justify-center gap-2 transition-colors duration-500 ${isDark ? 'group-hover/btn:text-primary-dark' : 'group-hover/btn:text-white'}`}>
|
|
{linkedinLabel || 'LinkedIn'}
|
|
<span className="ml-3 transition-transform group-hover/btn:translate-x-2">
|
|
→
|
|
</span>
|
|
</span>
|
|
<ButtonOverlay variant={isDark ? 'accent' : 'saturated'} />
|
|
</TrackedLink>
|
|
)}
|
|
</div>
|
|
</Reveal>
|
|
<Reveal
|
|
className={`w-full lg:w-1/2 relative min-h-[400px] md:min-h-[600px] lg:min-h-screen overflow-hidden ${isImageRight ? 'order-1 lg:order-2' : 'order-1'}`}
|
|
>
|
|
{imgSrc && (
|
|
<>
|
|
<Image
|
|
src={imgSrc}
|
|
alt={name}
|
|
fill
|
|
className="object-cover scale-105 hover:scale-100 transition-transform duration-1000"
|
|
style={{
|
|
objectPosition: `${image?.focalX ?? 50}% ${image?.focalY ?? 50}%`,
|
|
}}
|
|
sizes="(max-width: 1024px) 100vw, 50vw"
|
|
/>
|
|
<div
|
|
className={`absolute inset-0 ${isDark ? 'bg-gradient-to-t from-primary-dark/60 lg:bg-gradient-to-r lg:from-primary-dark/20 to-transparent' : 'bg-gradient-to-t from-white/60 lg:bg-gradient-to-l lg:from-primary-dark/20 to-transparent'}`}
|
|
/>
|
|
</>
|
|
)}
|
|
</Reveal>
|
|
</div>
|
|
</article>
|
|
);
|
|
};
|