This commit is contained in:
Your Name committed 2026-09-28 07:45:46 +07:00
1 parent a39f5b8102
commit 6d3b13d360
5 files changed
+502 -64

No files matched your search

@@ -100,16 +100,159 @@ function HeroSection({ payload, lang }: { payload: Record<string, unknown>, lang
const { t } = useTranslation()
const i18nLang = useLang()
const resolvedLang = lang === 'all' ? i18nLang : lang
const tagline = localizedFromRecord(payload, 'tagline', resolvedLang)
const title = localizedFromRecord(payload, 'title', resolvedLang)
const description = localizedFromRecord(payload, 'description', resolvedLang)
const buttonText = localizedFromRecord(payload, 'buttonText', resolvedLang)
const rawTagline = localizedFromRecord(payload, 'tagline', resolvedLang)
const rawTitle = localizedFromRecord(payload, 'title', resolvedLang)
const rawDescription = localizedFromRecord(payload, 'description', resolvedLang)
const rawButtonText = localizedFromRecord(payload, 'buttonText', resolvedLang)
const imageUrl = typeof payload.imageUrl === 'string' ? payload.imageUrl : '/images/hero.png'
const buttonLink = typeof payload.buttonLink === 'string' ? payload.buttonLink : '/shop'
const desktopPosition = typeof payload.buttonPosition === 'string' ? payload.buttonPosition : 'center'
const mobilePosition = typeof payload.mobileButtonPosition === 'string' ? payload.mobileButtonPosition : desktopPosition
const focalPoint = typeof payload.focalPoint === 'object' && payload.focalPoint ? (payload.focalPoint as { x: string, y: string }) : undefined
// 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 || 'VIBRANT ELEGANCE') : ''
const hasTitle = payload.title !== undefined && payload.title !== null ? !!rawTitle?.trim() : true
const title = hasTitle ? (rawTitle || 'New Scent [Sanctuary]') : ''
const hasDescription = payload.description !== undefined && payload.description !== null ? !!rawDescription?.trim() : false
const description = hasDescription ? rawDescription : ''
const buttonText = rawButtonText !== undefined && rawButtonText !== null
? rawButtonText.trim()
: 'Explore Collection'
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'
}
}
}
const getDesktopPositionClasses = (pos: string) => {
switch (pos) {
case 'top-left':
return {
wrapper: 'md:justify-start md:items-start md:text-left md:pt-32 md:pb-12 md:pl-20 md:pr-8',
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-32 md:pb-12 md:px-8',
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-32 md:pb-12 md:pr-20 md:pl-8',
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-20 md:pr-8',
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-20 md:pl-8',
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-20 md:pr-8',
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-8',
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-20 md:pl-8',
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-8',
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">
<Image
src={imageUrl}
@@ -121,31 +264,35 @@ function HeroSection({ payload, lang }: { payload: Record<string, unknown>, lang
/>
<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 flex flex-col justify-center items-center">
<div className="space-y-6">
<div className={`relative z-10 w-full min-h-[85vh] sm:min-h-[90vh] md:min-h-full flex flex-col ${wrapperClasses}`}>
<div className={`w-full max-w-3xl flex flex-col space-y-5 ${contentClasses}`}>
{tagline && (
<p className="text-xs font-semibold uppercase tracking-[0.3em] text-[#EAEFEA] drop-shadow-md md:text-sm">
{tagline}
</p>
)}
<h1 className="ui-hero-title !text-white drop-shadow-lg">
{renderAccentTitle(title || '', 'ui-accent-text font-medium')}
</h1>
{title && (
<h1 className="ui-hero-title !text-white drop-shadow-lg">
{renderAccentTitle(title, 'ui-accent-text font-medium')}
</h1>
)}
{description && (
<p className="ui-hero-copy !text-white/90 drop-shadow-md">
<p className="ui-hero-copy !text-white/90 drop-shadow-md !pb-2">
{description}
</p>
)}
<div className="flex flex-col items-center justify-center gap-4 sm:gap-6 sm:flex-row pt-2">
<Link
href={buttonLink}
className="ui-hero-button shadow-lg shadow-black/30"
>
{buttonText || 'Explore Collection'}
</Link>
<div className={`flex flex-col sm:flex-row gap-4 sm:gap-6 w-full ${actionsClasses} pt-1`}>
{buttonText && (
<Link
href={buttonLink}
className="ui-hero-button shadow-lg shadow-black/30"
>
{buttonText}
</Link>
)}
<a
href="#categories"
className="ui-hero-link group !text-white flex items-center gap-1.5 drop-shadow-md"
className="ui-hero-link group !text-white flex items-center gap-1.5 drop-shadow-md hover:underline"
>
<span>{t('dynamic.heroLearnMore', { lng: resolvedLang })}</span>
<span className="transition-transform group-hover:translate-x-1">→</span>