fix update Section Block

This commit is contained in:
Your Name committed 2026-06-17 21:08:24 -04:00
1 parent 996dfdabd0
commit 6f67ee6077
47 files changed
+1792 -197

No files matched your search

+1 -1
View File
@@ -4,7 +4,7 @@ import type { Metadata } from 'next'
import DynamicPageRenderer from '../../components/dynamic/DynamicPageRenderer'
import { getCategoriesResult, getCmsPageResult } from '../../lib/cms'
const lang = 'th'
const lang = 'all'
const reservedSlugs = new Set([
'about',
+1 -1
View File
@@ -9,7 +9,7 @@ import { type ApiResult, fetchJsonResult, getCategoriesResult, getCmsPageResult
import { splitCmsLayoutSections } from '../../../lib/cms-sections'
import { resolveLocalized } from '../../../lib/localization'
const lang = 'th'
const lang = 'all'
type CategoryProductsResponse = {
category?: Category
+1 -1
View File
@@ -5,7 +5,7 @@ import DynamicPageRenderer from '../../components/dynamic/DynamicPageRenderer'
import { getCategoriesResult, getCmsPageResult } from '../../lib/cms'
import { splitCmsLayoutSections } from '../../lib/cms-sections'
const lang = 'th'
const lang = 'all'
export const metadata = {
title: 'Checkout | HomAroma',
+1 -1
View File
@@ -4,7 +4,7 @@ import DynamicPageRenderer from '../../components/dynamic/DynamicPageRenderer'
import { getActiveCouponsResult, getCategoriesResult, getCmsPageResult } from '../../lib/cms'
import { splitCmsLayoutSections } from '../../lib/cms-sections'
const lang = 'th'
const lang = 'all'
function formatDiscount(type: string, value: number) {
if (type === 'PERCENTAGE') return `${value}% OFF`
+65 -5
View File
@@ -4,16 +4,18 @@ import Navbar from '../components/Navbar';
import Footer from '../components/Footer';
import ClientProviders from '../components/ClientProviders';
import { API_BASE } from '../lib/api';
import type { MegaMenuPayload } from '../components/navigation/menuTypes';
import type { MenuItem, StoreSettings } from '@homaroma/types';
export const metadata: Metadata = {
title: 'HomAroma',
description: 'Pure Origins, Artisan Craft, Zero Compromise',
};
// Fetch categories for Navbar and Footer on the server
// Fetch categories for Navbar and Footer on the server (lang=all for client-side switching)
async function getCategories() {
try {
const res = await fetch(`${API_BASE}/categories`, { next: { revalidate: 3600 } });
const res = await fetch(`${API_BASE}/categories?lang=all`, { next: { revalidate: 3600 } });
if (!res.ok) return [];
return await res.json();
} catch (error) {
@@ -22,22 +24,80 @@ async function getCategories() {
}
}
// Fetch mega menu on the server — eliminates client-side flash
async function getMegaMenu(): Promise<MegaMenuPayload[]> {
try {
const res = await fetch(`${API_BASE}/menus/main`, { next: { revalidate: 300 } });
if (!res.ok) return [];
const data = await res.json() as { payload?: MegaMenuPayload[] };
return Array.isArray(data.payload) ? data.payload : [];
} catch (error) {
console.error('Failed to fetch mega menu in layout', error);
return [];
}
}
// Fetch footer menus (explore + support) on the server
async function getFooterMenus(): Promise<{ exploreMenu: MenuItem[]; supportMenu: MenuItem[] }> {
const fetchMenu = async (slug: string): Promise<MenuItem[]> => {
try {
const res = await fetch(`${API_BASE}/menus/${slug}`, { next: { revalidate: 300 } });
if (!res.ok) return [];
const data = await res.json() as { items?: MenuItem[] };
return Array.isArray(data.items)
? data.items.sort((a, b) => a.order - b.order)
: [];
} catch {
return [];
}
};
const [exploreMenu, supportMenu] = await Promise.all([
fetchMenu('footer-explore'),
fetchMenu('footer-support'),
]);
return { exploreMenu, supportMenu };
}
// Fetch store settings (social links, footer texts) on the server
async function getStoreSettings(): Promise<StoreSettings | null> {
try {
const res = await fetch(`${API_BASE}/settings`, { next: { revalidate: 600 } });
if (!res.ok) return null;
return await res.json() as StoreSettings;
} catch (error) {
console.error('Failed to fetch store settings in layout', error);
return null;
}
}
export default async function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
const categories = await getCategories();
const [categories, initialMenu, footerMenus, settings] = await Promise.all([
getCategories(),
getMegaMenu(),
getFooterMenus(),
getStoreSettings(),
]);
return (
<html lang="th" className="scroll-smooth">
<body className="min-h-screen bg-pop-bg text-pop-black font-sans antialiased">
<ClientProviders>
<Navbar categories={categories} />
<Navbar categories={categories} initialMenu={initialMenu} />
<main className="pt-[72px]">
{children}
</main>
<Footer categories={categories} />
<Footer
categories={categories}
exploreMenu={footerMenus.exploreMenu}
supportMenu={footerMenus.supportMenu}
settings={settings}
/>
</ClientProviders>
</body>
</html>
+1 -1
View File
@@ -8,7 +8,7 @@ import DynamicPageRenderer from '../../../components/dynamic/DynamicPageRenderer
import { getCategoriesResult, getCmsPageResult, getOrderResult } from '../../../lib/cms'
import { splitCmsLayoutSections } from '../../../lib/cms-sections'
const lang = 'th'
const lang = 'all'
function orderLabel(id: number) {
return `#${id.toString().padStart(4, '0')}`
+1 -1
View File
@@ -2,7 +2,7 @@ import type { Metadata } from 'next'
import DynamicPageRenderer from '../components/dynamic/DynamicPageRenderer'
import { getCategories, getCmsPage } from '../lib/cms'
const lang = 'th'
const lang = 'all'
export async function generateMetadata(): Promise<Metadata> {
const page = await getCmsPage('home', lang)
+1 -1
View File
@@ -9,7 +9,7 @@ import { getCategoriesResult, getCmsPageResult, getProduct, getProductResult, ge
import { splitCmsLayoutSections } from '../../../lib/cms-sections'
import { resolveLocalized } from '../../../lib/localization'
const lang = 'th'
const lang = 'all'
async function getRelated(categoryId: number, excludeId: number): Promise<Product[]> {
const result = await getProductsResult(`categoryId=${categoryId}`, lang)
+1 -1
View File
@@ -5,7 +5,7 @@ import ProfileClient from '../../components/ProfileClient'
import { getCategoriesResult, getCmsPageResult } from '../../lib/cms'
import { splitCmsLayoutSections } from '../../lib/cms-sections'
const lang = 'th'
const lang = 'all'
export const metadata = {
title: 'โปรไฟล์สมาชิก | HomAroma',
+1 -1
View File
@@ -3,7 +3,7 @@ import DynamicPageRenderer from '../../components/dynamic/DynamicPageRenderer'
import { getArticlesResult, getCategoriesResult, getCmsPageResult } from '../../lib/cms'
import { splitCmsLayoutSections } from '../../lib/cms-sections'
const lang = 'th'
const lang = 'all'
export const metadata = {
title: 'Scent Guide | HomAroma',
+1 -1
View File
@@ -5,7 +5,7 @@ import { getCategoriesResult, getCmsPageResult, getProductsResult } from '../../
import { splitCmsLayoutSections } from '../../lib/cms-sections'
import { resolveLocalized } from '../../lib/localization'
const lang = 'th'
const lang = 'all'
export const metadata = {
title: 'Search Products | HomAroma',
+1 -1
View File
@@ -6,7 +6,7 @@ import { getCategoriesResult, getCmsPageResult, getProductsResult } from '../../
import { splitCmsLayoutSections } from '../../lib/cms-sections'
import { resolveLocalized } from '../../lib/localization'
const lang = 'th'
const lang = 'all'
export const metadata = {
title: 'Shop Aroma Products | HomAroma',
+1 -1
View File
@@ -5,7 +5,7 @@ import TrackOrderClient from '../../components/TrackOrderClient'
import { getCategoriesResult, getCmsPageResult } from '../../lib/cms'
import { splitCmsLayoutSections } from '../../lib/cms-sections'
const lang = 'th'
const lang = 'all'
export const metadata = {
title: 'ติดตามคำสั่งซื้อ | HomAroma',
+1 -1
View File
@@ -5,7 +5,7 @@ import WishlistClient from '../../components/WishlistClient'
import { getCategoriesResult, getCmsPageResult } from '../../lib/cms'
import { splitCmsLayoutSections } from '../../lib/cms-sections'
const lang = 'th'
const lang = 'all'
export const metadata = {
title: 'Wishlist | HomAroma',