x
This commit is contained in:
1 parent
406cad801b
commit
a2da091b15
21 files changed
+2454
-63
No files matched your search
@@ -0,0 +1,127 @@
|
||||
import { Link } from 'react-router-dom';
|
||||
import type { HeroVideoSectionPayload } from '@homaroma/types';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { getLocalizedField } from '../utils/localization';
|
||||
|
||||
interface DynamicHeroVideoProps {
|
||||
payload: HeroVideoSectionPayload;
|
||||
}
|
||||
|
||||
export default function DynamicHeroVideo({ payload }: DynamicHeroVideoProps) {
|
||||
const { t, i18n } = useTranslation();
|
||||
const lang = i18n.language;
|
||||
|
||||
const tagline = getLocalizedField(payload.tagline, lang);
|
||||
const title = getLocalizedField(payload.title, lang);
|
||||
const description = getLocalizedField(payload.description, lang);
|
||||
const buttonText = getLocalizedField(payload.buttonText, lang);
|
||||
const secondaryButtonText = getLocalizedField(payload.secondaryButtonText, lang);
|
||||
|
||||
const videoUrl = payload.videoUrl;
|
||||
const posterImageUrl = payload.posterImageUrl;
|
||||
const overlayOpacity = typeof payload.overlayOpacity === 'number' ? payload.overlayOpacity : 40;
|
||||
const height = payload.height || 'large';
|
||||
|
||||
const getHeightClass = (h: string) => {
|
||||
switch (h) {
|
||||
case 'full':
|
||||
return 'h-screen';
|
||||
case 'medium':
|
||||
return 'h-[60vh] min-h-[400px]';
|
||||
case 'large':
|
||||
default:
|
||||
return 'h-[85vh] min-h-[550px]';
|
||||
}
|
||||
};
|
||||
|
||||
const renderTitle = (text: string) => {
|
||||
if (!text) return null;
|
||||
return text.split('[').map((part, i) => {
|
||||
if (part.includes(']')) {
|
||||
const [accent, rest] = part.split(']');
|
||||
return (
|
||||
<span key={i}>
|
||||
<span className="text-pop-pink font-serif italic font-normal">
|
||||
{accent}
|
||||
</span>
|
||||
{rest}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
return <span key={i}>{part}</span>;
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<section
|
||||
className={`relative w-full ${getHeightClass(height)} overflow-hidden flex items-center justify-center`}
|
||||
style={{ backgroundColor: payload.backgroundColor || '#0B0F17', color: payload.textColor || '#FFFFFF' }}
|
||||
>
|
||||
{/* Background Video */}
|
||||
{videoUrl ? (
|
||||
<video
|
||||
autoPlay={payload.autoplay !== false}
|
||||
muted={payload.muted !== false}
|
||||
loop={payload.loop !== false}
|
||||
playsInline
|
||||
poster={posterImageUrl}
|
||||
className="absolute inset-0 w-full h-full object-cover z-0"
|
||||
>
|
||||
<source src={videoUrl} type="video/mp4" />
|
||||
<source src={videoUrl} type="video/webm" />
|
||||
{posterImageUrl && <img src={posterImageUrl} alt="Hero fallback" className="w-full h-full object-cover" />}
|
||||
</video>
|
||||
) : posterImageUrl ? (
|
||||
<img src={posterImageUrl} alt="Hero Poster" className="absolute inset-0 w-full h-full object-cover z-0" />
|
||||
) : null}
|
||||
|
||||
{/* Customizable Overlay Opacity */}
|
||||
<div
|
||||
className="absolute inset-0 z-10 bg-black transition-opacity"
|
||||
style={{ opacity: overlayOpacity / 100 }}
|
||||
></div>
|
||||
|
||||
{/* Overlay Typography Content */}
|
||||
<div className="relative z-20 mx-auto px-6 py-16 w-full max-w-5xl text-center space-y-6 flex flex-col items-center justify-center animate-fade-in">
|
||||
{tagline && (
|
||||
<p className="text-xs md:text-sm font-semibold uppercase tracking-[0.35em] text-pop-pink/90 drop-shadow-md">
|
||||
{tagline}
|
||||
</p>
|
||||
)}
|
||||
|
||||
<h1 className="font-serif text-4xl md:text-6xl lg:text-7xl font-light leading-tight tracking-wide drop-shadow-lg text-white">
|
||||
{renderTitle(title) || renderTitle(t('hero.defaultTitle'))}
|
||||
</h1>
|
||||
|
||||
{description && (
|
||||
<p className="max-w-2xl text-sm md:text-lg font-light leading-relaxed opacity-90 drop-shadow">
|
||||
{description}
|
||||
</p>
|
||||
)}
|
||||
|
||||
{/* Dual Action Buttons */}
|
||||
{(buttonText || secondaryButtonText) && (
|
||||
<div className="flex flex-wrap items-center justify-center gap-4 pt-4">
|
||||
{buttonText && payload.buttonLink && (
|
||||
<Link
|
||||
to={payload.buttonLink}
|
||||
className="px-8 py-3.5 bg-white text-neutral-900 font-medium text-xs uppercase tracking-widest hover:bg-pop-pink hover:text-white transition-all shadow-lg rounded-sm"
|
||||
>
|
||||
{buttonText}
|
||||
</Link>
|
||||
)}
|
||||
|
||||
{secondaryButtonText && payload.secondaryButtonLink && (
|
||||
<Link
|
||||
to={payload.secondaryButtonLink}
|
||||
className="px-8 py-3.5 bg-transparent border border-white/40 text-white font-medium text-xs uppercase tracking-widest hover:bg-white/10 hover:border-white transition-all rounded-sm backdrop-blur-sm"
|
||||
>
|
||||
{secondaryButtonText}
|
||||
</Link>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user