x
This commit is contained in:
1 parent
e87176dba3
commit
80e715da76
3 files changed
+59
-8
No files matched your search
@@ -1,9 +1,12 @@
|
||||
import { useEffect } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { API_BASE } from '@homaroma/types'
|
||||
|
||||
export default function ThemeInjector() {
|
||||
const { i18n } = useTranslation()
|
||||
|
||||
useEffect(() => {
|
||||
const lang = localStorage.getItem('app_lang') || 'en'
|
||||
const lang = i18n.language || localStorage.getItem('app_lang') || 'en'
|
||||
|
||||
fetch(`${API_BASE}/settings?lang=${lang}`)
|
||||
.then(res => res.ok ? res.json() : null)
|
||||
@@ -11,6 +14,52 @@ export default function ThemeInjector() {
|
||||
if (!settings) return
|
||||
const root = document.documentElement
|
||||
|
||||
// --- Global SEO & Document Title ---
|
||||
const pageTitle = settings.defaultSeoTitle || settings.brandName
|
||||
if (pageTitle) {
|
||||
document.title = pageTitle
|
||||
}
|
||||
|
||||
if (settings.defaultSeoDescription) {
|
||||
let metaDesc = document.querySelector('meta[name="description"]')
|
||||
if (!metaDesc) {
|
||||
metaDesc = document.createElement('meta')
|
||||
metaDesc.setAttribute('name', 'description')
|
||||
document.head.appendChild(metaDesc)
|
||||
}
|
||||
metaDesc.setAttribute('content', settings.defaultSeoDescription)
|
||||
}
|
||||
|
||||
if (pageTitle) {
|
||||
let ogTitle = document.querySelector('meta[property="og:title"]')
|
||||
if (!ogTitle) {
|
||||
ogTitle = document.createElement('meta')
|
||||
ogTitle.setAttribute('property', 'og:title')
|
||||
document.head.appendChild(ogTitle)
|
||||
}
|
||||
ogTitle.setAttribute('content', pageTitle)
|
||||
}
|
||||
|
||||
if (settings.defaultSeoDescription) {
|
||||
let ogDesc = document.querySelector('meta[property="og:description"]')
|
||||
if (!ogDesc) {
|
||||
ogDesc = document.createElement('meta')
|
||||
ogDesc.setAttribute('property', 'og:description')
|
||||
document.head.appendChild(ogDesc)
|
||||
}
|
||||
ogDesc.setAttribute('content', settings.defaultSeoDescription)
|
||||
}
|
||||
|
||||
if (settings.defaultOgImage) {
|
||||
let ogImg = document.querySelector('meta[property="og:image"]')
|
||||
if (!ogImg) {
|
||||
ogImg = document.createElement('meta')
|
||||
ogImg.setAttribute('property', 'og:image')
|
||||
document.head.appendChild(ogImg)
|
||||
}
|
||||
ogImg.setAttribute('content', settings.defaultOgImage)
|
||||
}
|
||||
|
||||
// --- Theme tokens ---
|
||||
const tokens = settings?.themeTokens
|
||||
if (tokens && typeof tokens === 'object') {
|
||||
@@ -48,8 +97,8 @@ export default function ThemeInjector() {
|
||||
root.style.setProperty('--scroll-reveal-style', style)
|
||||
root.style.setProperty('--scroll-reveal-duration', `${duration}ms`)
|
||||
})
|
||||
.catch(err => console.error('Failed to inject theme in SPA:', err))
|
||||
}, [])
|
||||
.catch(err => console.error('Failed to inject theme/SEO in SPA:', err))
|
||||
}, [i18n.language])
|
||||
|
||||
return null
|
||||
}
|
||||
@@ -12,20 +12,21 @@ import type { CSSProperties } from 'react';
|
||||
export async function generateMetadata({ params }: { params: Promise<{ lang: string }> }): Promise<Metadata> {
|
||||
const { lang } = await params;
|
||||
const settings = await getStoreSettings(lang);
|
||||
const brandName = settings?.brandName || '';
|
||||
const brandName = settings?.brandName || 'HomAroma';
|
||||
const defaultTitle = settings?.defaultSeoTitle || brandName;
|
||||
const description = settings?.defaultSeoDescription || settings?.footerDescription || 'Pure Origins, Artisan Craft, Zero Compromise';
|
||||
const ogImage = settings?.defaultOgImage;
|
||||
|
||||
return {
|
||||
title: {
|
||||
template: `%s | ${brandName}`,
|
||||
default: brandName,
|
||||
default: defaultTitle,
|
||||
},
|
||||
description,
|
||||
metadataBase: new URL(process.env.NEXT_PUBLIC_SITE_URL || 'http://localhost:3000'),
|
||||
openGraph: ogImage
|
||||
? {
|
||||
title: brandName,
|
||||
title: defaultTitle,
|
||||
description,
|
||||
images: [ogImage],
|
||||
}
|
||||
|
||||
@@ -15,10 +15,11 @@ export async function generateMetadata({ params }: Props): Promise<Metadata> {
|
||||
getStoreSettings(lang),
|
||||
])
|
||||
|
||||
const title = page?.seoTitle || page?.title || undefined
|
||||
const title = page?.seoTitle || settings?.defaultSeoTitle || (page?.title && page.title !== 'Home' && page.title !== 'หน้าแรก' ? page.title : undefined) || settings?.brandName || undefined
|
||||
const description =
|
||||
page?.seoDescription ||
|
||||
settings?.defaultSeoDescription ||
|
||||
settings?.footerDescription ||
|
||||
(settings?.brandName ? `${settings.brandName} - Pure Origins, Artisan Craft` : 'Pure Origins, Artisan Craft')
|
||||
const ogImage = page?.ogImageUrl || settings?.defaultOgImage
|
||||
|
||||
@@ -29,7 +30,7 @@ export async function generateMetadata({ params }: Props): Promise<Metadata> {
|
||||
lang,
|
||||
openGraph: ogImage
|
||||
? {
|
||||
title: page?.seoTitle || page?.title || settings?.brandName || undefined,
|
||||
title,
|
||||
description,
|
||||
images: [ogImage],
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user