x
This commit is contained in:
1 parent
a39f5b8102
commit
6d3b13d360
5 files changed
+502
-64
No files matched your search
@@ -11,12 +11,30 @@ export default function DynamicHero({ payload }: DynamicHeroProps) {
|
||||
const { t, i18n } = useTranslation();
|
||||
const lang = i18n.language;
|
||||
const { imageUrl, buttonLink } = payload;
|
||||
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 desktopPosition = (payload as any).buttonPosition || 'center';
|
||||
const mobilePosition = (payload as any).mobileButtonPosition || desktopPosition;
|
||||
const focalPoint = typeof payload.focalPoint === 'object' && payload.focalPoint ? (payload.focalPoint as { x: string, y: string }) : undefined;
|
||||
|
||||
// Localized values
|
||||
const rawTagline = getLocalizedField(payload.tagline, lang);
|
||||
const rawTitle = getLocalizedField(payload.title, lang);
|
||||
const rawDescription = getLocalizedField(payload.description, lang);
|
||||
const rawButtonText = getLocalizedField(payload.buttonText, lang);
|
||||
|
||||
// If fields are explicitly defined as empty strings, respect them as empty
|
||||
const hasTagline = payload.tagline !== undefined && payload.tagline !== null ? !!rawTagline?.trim() : true;
|
||||
const tagline = hasTagline ? (rawTagline || t('hero.defaultTagline')) : '';
|
||||
|
||||
const hasTitle = payload.title !== undefined && payload.title !== null ? !!rawTitle?.trim() : true;
|
||||
const title = hasTitle ? (rawTitle || t('hero.defaultTitle')) : '';
|
||||
|
||||
const hasDescription = payload.description !== undefined && payload.description !== null ? !!rawDescription?.trim() : false;
|
||||
const description = hasDescription ? rawDescription : '';
|
||||
|
||||
const buttonText = rawButtonText !== undefined && rawButtonText !== null
|
||||
? rawButtonText.trim()
|
||||
: t('hero.exploreCollection');
|
||||
|
||||
const renderTitle = (text: string) => {
|
||||
if (!text) return null;
|
||||
return text.split('[').map((part, i) => {
|
||||
@@ -35,8 +53,137 @@ export default function DynamicHero({ payload }: DynamicHeroProps) {
|
||||
});
|
||||
};
|
||||
|
||||
// Map 9-box grid position to mobile flex classes
|
||||
const getMobilePositionClasses = (pos: string) => {
|
||||
switch (pos) {
|
||||
case 'top-left':
|
||||
return {
|
||||
wrapper: 'justify-start items-start text-left pt-20 pb-12 pl-6 pr-6',
|
||||
content: 'items-start text-left',
|
||||
actions: 'items-start justify-start'
|
||||
};
|
||||
case 'top-center':
|
||||
return {
|
||||
wrapper: 'justify-start items-center text-center pt-20 pb-12 px-6',
|
||||
content: 'items-center text-center',
|
||||
actions: 'items-center justify-center'
|
||||
};
|
||||
case 'top-right':
|
||||
return {
|
||||
wrapper: 'justify-start items-end text-right pt-20 pb-12 pr-6 pl-6',
|
||||
content: 'items-end text-right',
|
||||
actions: 'items-end justify-end'
|
||||
};
|
||||
case 'center-left':
|
||||
return {
|
||||
wrapper: 'justify-center items-start text-left py-16 pl-6 pr-6',
|
||||
content: 'items-start text-left',
|
||||
actions: 'items-start justify-start'
|
||||
};
|
||||
case 'center-right':
|
||||
return {
|
||||
wrapper: 'justify-center items-end text-right py-16 pr-6 pl-6',
|
||||
content: 'items-end text-right',
|
||||
actions: 'items-end justify-end'
|
||||
};
|
||||
case 'bottom-left':
|
||||
return {
|
||||
wrapper: 'justify-end items-start text-left pt-12 pb-16 pl-6 pr-6',
|
||||
content: 'items-start text-left',
|
||||
actions: 'items-start justify-start'
|
||||
};
|
||||
case 'bottom-center':
|
||||
return {
|
||||
wrapper: 'justify-end items-center text-center pt-12 pb-16 px-6',
|
||||
content: 'items-center text-center',
|
||||
actions: 'items-center justify-center'
|
||||
};
|
||||
case 'bottom-right':
|
||||
return {
|
||||
wrapper: 'justify-end items-end text-right pt-12 pb-16 pr-6 pl-6',
|
||||
content: 'items-end text-right',
|
||||
actions: 'items-end justify-end'
|
||||
};
|
||||
case 'center':
|
||||
default:
|
||||
return {
|
||||
wrapper: 'justify-center items-center text-center py-16 px-6',
|
||||
content: 'items-center text-center',
|
||||
actions: 'items-center justify-center'
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// Map 9-box grid position to desktop (md:) flex classes
|
||||
const getDesktopPositionClasses = (pos: string) => {
|
||||
switch (pos) {
|
||||
case 'top-left':
|
||||
return {
|
||||
wrapper: 'md:justify-start md:items-start md:text-left md:pt-28 md:pb-12 md:pl-16 md:pr-6',
|
||||
content: 'md:items-start md:text-left',
|
||||
actions: 'md:items-start md:justify-start'
|
||||
};
|
||||
case 'top-center':
|
||||
return {
|
||||
wrapper: 'md:justify-start md:items-center md:text-center md:pt-28 md:pb-12 md:px-6',
|
||||
content: 'md:items-center md:text-center',
|
||||
actions: 'md:items-center md:justify-center'
|
||||
};
|
||||
case 'top-right':
|
||||
return {
|
||||
wrapper: 'md:justify-start md:items-end md:text-right md:pt-28 md:pb-12 md:pr-16 md:pl-6',
|
||||
content: 'md:items-end md:text-right',
|
||||
actions: 'md:items-end md:justify-end'
|
||||
};
|
||||
case 'center-left':
|
||||
return {
|
||||
wrapper: 'md:justify-center md:items-start md:text-left md:py-16 md:pl-16 md:pr-6',
|
||||
content: 'md:items-start md:text-left',
|
||||
actions: 'md:items-start md:justify-start'
|
||||
};
|
||||
case 'center-right':
|
||||
return {
|
||||
wrapper: 'md:justify-center md:items-end md:text-right md:py-16 md:pr-16 md:pl-6',
|
||||
content: 'md:items-end md:text-right',
|
||||
actions: 'md:items-end md:justify-end'
|
||||
};
|
||||
case 'bottom-left':
|
||||
return {
|
||||
wrapper: 'md:justify-end md:items-start md:text-left md:pt-12 md:pb-24 md:pl-16 md:pr-6',
|
||||
content: 'md:items-start md:text-left',
|
||||
actions: 'md:items-start md:justify-start'
|
||||
};
|
||||
case 'bottom-center':
|
||||
return {
|
||||
wrapper: 'md:justify-end md:items-center md:text-center md:pt-12 md:pb-24 md:px-6',
|
||||
content: 'md:items-center md:text-center',
|
||||
actions: 'md:items-center md:justify-center'
|
||||
};
|
||||
case 'bottom-right':
|
||||
return {
|
||||
wrapper: 'md:justify-end md:items-end md:text-right md:pt-12 md:pb-24 md:pr-16 md:pl-6',
|
||||
content: 'md:items-end md:text-right',
|
||||
actions: 'md:items-end md:justify-end'
|
||||
};
|
||||
case 'center':
|
||||
default:
|
||||
return {
|
||||
wrapper: 'md:justify-center md:items-center md:text-center md:py-16 md:px-6',
|
||||
content: 'md:items-center md:text-center',
|
||||
actions: 'md:items-center md:justify-center'
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const mClasses = getMobilePositionClasses(mobilePosition);
|
||||
const dClasses = getDesktopPositionClasses(desktopPosition);
|
||||
|
||||
const wrapperClasses = `${mClasses.wrapper} ${dClasses.wrapper}`;
|
||||
const contentClasses = `${mClasses.content} ${dClasses.content}`;
|
||||
const actionsClasses = `${mClasses.actions} ${dClasses.actions}`;
|
||||
|
||||
return (
|
||||
<section className="relative w-full min-h-[85vh] sm:min-h-[90vh] md:h-[90vh] md:aspect-[21/9] flex items-center justify-center bg-night-950 overflow-hidden">
|
||||
<section className="relative w-full min-h-[85vh] sm:min-h-[90vh] md:h-[90vh] md:aspect-[21/9] flex bg-night-950 overflow-hidden">
|
||||
<div className="absolute inset-0 w-full h-full z-0">
|
||||
<img
|
||||
src={imageUrl || `${import.meta.env.VITE_API_URL.replace('/api', '')}/assets/hero.png`}
|
||||
@@ -51,32 +198,40 @@ export default function DynamicHero({ payload }: DynamicHeroProps) {
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-black/85 via-black/45 to-black/30 md:bg-black/35" />
|
||||
</div>
|
||||
|
||||
<div className="relative z-10 mx-auto py-16 px-6 sm:px-8 w-full max-w-4xl space-y-6 text-center animate-fade-in flex flex-col justify-center items-center">
|
||||
<p className="text-white/80 font-semibold tracking-[0.3em] text-xs md:text-sm uppercase drop-shadow-md">
|
||||
{tagline || t('hero.defaultTagline')}
|
||||
</p>
|
||||
<h1 className="ui-hero-title !text-white drop-shadow-lg">
|
||||
{renderTitle(title) || renderTitle(t('hero.defaultTitle'))}
|
||||
</h1>
|
||||
{description && (
|
||||
<p className="ui-hero-copy !text-white/90 drop-shadow-md !pb-2">
|
||||
{description}
|
||||
</p>
|
||||
)}
|
||||
<div className="flex flex-col sm:flex-row gap-4 sm:gap-6 items-center justify-center pt-2">
|
||||
<Link
|
||||
to={buttonLink || "/shop"}
|
||||
className="ui-button-secondary shadow-lg shadow-black/30"
|
||||
>
|
||||
{buttonText || t('hero.exploreCollection')}
|
||||
</Link>
|
||||
<a
|
||||
href="#categories"
|
||||
className="ui-dark-link !text-white group flex items-center gap-1.5 drop-shadow-md hover:underline"
|
||||
>
|
||||
<span>{t('hero.learnMore')}</span>
|
||||
<span className="group-hover:translate-x-1 transition-transform">→</span>
|
||||
</a>
|
||||
<div className={`relative z-10 w-full min-h-[85vh] sm:min-h-[90vh] md:min-h-full flex flex-col ${wrapperClasses} animate-fade-in`}>
|
||||
<div className={`w-full max-w-3xl flex flex-col space-y-5 ${contentClasses}`}>
|
||||
{tagline && (
|
||||
<p className="text-white/80 font-semibold tracking-[0.3em] text-xs md:text-sm uppercase drop-shadow-md">
|
||||
{tagline}
|
||||
</p>
|
||||
)}
|
||||
{title && (
|
||||
<h1 className="ui-hero-title !text-white drop-shadow-lg">
|
||||
{renderTitle(title)}
|
||||
</h1>
|
||||
)}
|
||||
{description && (
|
||||
<p className="ui-hero-copy !text-white/90 drop-shadow-md !pb-2">
|
||||
{description}
|
||||
</p>
|
||||
)}
|
||||
<div className={`flex flex-col sm:flex-row gap-4 sm:gap-6 w-full ${actionsClasses} pt-1`}>
|
||||
{buttonText && (
|
||||
<Link
|
||||
to={buttonLink || "/shop"}
|
||||
className="ui-button-secondary shadow-lg shadow-black/30"
|
||||
>
|
||||
{buttonText}
|
||||
</Link>
|
||||
)}
|
||||
<a
|
||||
href="#categories"
|
||||
className="ui-dark-link !text-white group flex items-center gap-1.5 drop-shadow-md hover:underline"
|
||||
>
|
||||
<span>{t('hero.learnMore')}</span>
|
||||
<span className="group-hover:translate-x-1 transition-transform">→</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
Reference in new issue
Block a user