x
This commit is contained in:
1 parent
f7aa4d099f
commit
ab3e53c4da
33 files changed
+290
-69
No files matched your search
@@ -1,5 +1,6 @@
|
||||
import { notFound } from 'next/navigation'
|
||||
import type { Metadata } from 'next'
|
||||
import { generateSeoMetadata } from '@/lib/seo'
|
||||
|
||||
import DynamicPageRenderer from '@/components/dynamic/DynamicPageRenderer'
|
||||
import { getCategoriesResult, getCmsPageResult } from '@/lib/cms'
|
||||
@@ -38,9 +39,12 @@ export async function generateMetadata({ params }: { params: Promise<{ slug: str
|
||||
const pageResult = await getCmsPageResult(slug, lang)
|
||||
if (!pageResult.ok || !pageResult.data.isPublished) return { title: 'Page Not Found | HomAroma' }
|
||||
|
||||
return {
|
||||
return generateSeoMetadata({
|
||||
title: `${pageResult.data.title} | HomAroma`,
|
||||
}
|
||||
description: `HomAroma - ${pageResult.data.title}`,
|
||||
path: `/${slug}`,
|
||||
lang,
|
||||
})
|
||||
}
|
||||
|
||||
export default async function CmsCustomPage({ params }: { params: Promise<{ slug: string, lang: string }> }) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import Link from '@/components/LocalizedLink'
|
||||
import { generateSeoMetadata } from '@/lib/seo'
|
||||
|
||||
const PILLARS = [
|
||||
{
|
||||
@@ -25,9 +26,14 @@ const STATS = [
|
||||
{ value: '100%', label: 'Natural Extracts' },
|
||||
]
|
||||
|
||||
export const metadata = {
|
||||
title: 'About Us | HomAroma',
|
||||
description: 'Born from a passion for stillness. HomAroma began in 2019 as a Bangkok studio crafting botanical aroma blends.',
|
||||
export async function generateMetadata({ params }: { params: Promise<{ lang: string }> }) {
|
||||
const { lang } = await params;
|
||||
return generateSeoMetadata({
|
||||
title: 'About Us | HomAroma',
|
||||
description: 'Born from a passion for stillness. HomAroma began in 2019 as a Bangkok studio crafting botanical aroma blends.',
|
||||
path: '/about',
|
||||
lang,
|
||||
});
|
||||
}
|
||||
|
||||
export default function AboutPage() {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import Link from '@/components/LocalizedLink'
|
||||
import { notFound } from 'next/navigation'
|
||||
import type { Metadata } from 'next'
|
||||
import { generateSeoMetadata } from '@/lib/seo'
|
||||
import { ArrowLeft } from 'lucide-react'
|
||||
import type { Article } from '@homaroma/types'
|
||||
|
||||
@@ -13,20 +14,22 @@ async function getArticle(slug: string): Promise<Article | null> {
|
||||
} catch { return null }
|
||||
}
|
||||
|
||||
export async function generateMetadata({ params }: { params: Promise<{ slug: string }> }): Promise<Metadata> {
|
||||
const { slug } = await params
|
||||
export async function generateMetadata({ params }: { params: Promise<{ slug: string, lang: string }> }): Promise<Metadata> {
|
||||
const { slug, lang } = await params
|
||||
const article = await getArticle(slug)
|
||||
if (!article) return { title: 'Article Not Found | HomAroma' }
|
||||
return {
|
||||
return generateSeoMetadata({
|
||||
title: `${article.title} | HomAroma Scent Guide`,
|
||||
description: article.content.replace(/<[^>]+>/g, '').slice(0, 160),
|
||||
path: `/article/${slug}`,
|
||||
lang,
|
||||
openGraph: {
|
||||
title: article.title,
|
||||
images: article.coverImage ? [article.coverImage] : [],
|
||||
type: 'article',
|
||||
publishedTime: article.createdAt,
|
||||
},
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export default async function ArticleReaderPage({ params }: { params: Promise<{ slug: string }> }) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import Link from '@/components/LocalizedLink'
|
||||
import { notFound } from 'next/navigation'
|
||||
import type { Metadata } from 'next'
|
||||
import { generateSeoMetadata } from '@/lib/seo'
|
||||
import type { Category, Product } from '@homaroma/types'
|
||||
import { getCategoryImage } from '@homaroma/types'
|
||||
import DynamicPageRenderer from '@/components/dynamic/DynamicPageRenderer'
|
||||
@@ -26,10 +27,12 @@ export async function generateMetadata({ params }: { params: Promise<{ id: strin
|
||||
const result = await getCategoryProducts(id, lang)
|
||||
const categoryName = result.ok && result.data.category ? resolveLocalized(result.data.category.name, lang) : ''
|
||||
|
||||
return {
|
||||
return generateSeoMetadata({
|
||||
title: categoryName ? `${categoryName} | HomAroma` : 'Category | HomAroma',
|
||||
description: categoryName ? `Shop ${categoryName} products from HomAroma.` : 'Shop HomAroma category products.',
|
||||
}
|
||||
path: `/category/${id}`,
|
||||
lang,
|
||||
})
|
||||
}
|
||||
|
||||
export default async function CategoryPage({ params }: { params: Promise<{ id: string, lang: string }> }) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { CreditCard } from 'lucide-react'
|
||||
import { generateSeoMetadata } from '@/lib/seo'
|
||||
|
||||
import CheckoutClient from '@/components/CheckoutClient'
|
||||
import DynamicPageRenderer from '@/components/dynamic/DynamicPageRenderer'
|
||||
@@ -6,9 +7,14 @@ import { getCategoriesResult, getCmsPageResult } from '@/lib/cms'
|
||||
import { splitCmsLayoutSections } from '@/lib/cms-sections'
|
||||
|
||||
// lang is extracted from params
|
||||
export const metadata = {
|
||||
title: 'Checkout | HomAroma',
|
||||
description: 'ตรวจสอบรายการสินค้า กรอกข้อมูลจัดส่ง และสร้างคำสั่งซื้อ HomAroma',
|
||||
export async function generateMetadata({ params }: { params: Promise<{ lang: string }> }) {
|
||||
const { lang } = await params;
|
||||
return generateSeoMetadata({
|
||||
title: 'Checkout | HomAroma',
|
||||
description: 'ตรวจสอบรายการสินค้า กรอกข้อมูลจัดส่ง และสร้างคำสั่งซื้อ HomAroma',
|
||||
path: '/checkout',
|
||||
lang,
|
||||
});
|
||||
}
|
||||
|
||||
export default async function CheckoutPage({ params }: { params: Promise<{ lang: string }> }) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import Link from '@/components/LocalizedLink'
|
||||
import { Ticket, ArrowRight } from 'lucide-react'
|
||||
import { generateSeoMetadata } from '@/lib/seo'
|
||||
import DynamicPageRenderer from '@/components/dynamic/DynamicPageRenderer'
|
||||
import { getActiveCouponsResult, getCategoriesResult, getCmsPageResult } from '@/lib/cms'
|
||||
import { splitCmsLayoutSections } from '@/lib/cms-sections'
|
||||
@@ -12,9 +13,14 @@ function formatDiscount(type: string, value: number) {
|
||||
return `${value}`
|
||||
}
|
||||
|
||||
export const metadata = {
|
||||
title: 'โปรโมชั่นและคูปองส่วนลด | HomAroma',
|
||||
description: 'รวมรหัสส่วนลดและโปรโมชั่นพิเศษจาก HomAroma สำหรับการสั่งซื้อน้ำหอมและผลิตภัณฑ์อโรม่าที่คุณชื่นชอบ',
|
||||
export async function generateMetadata({ params }: { params: Promise<{ lang: string }> }) {
|
||||
const { lang } = await params;
|
||||
return generateSeoMetadata({
|
||||
title: 'โปรโมชั่นและคูปองส่วนลด | HomAroma',
|
||||
description: 'รวมรหัสส่วนลดและโปรโมชั่นพิเศษจาก HomAroma สำหรับการสั่งซื้อน้ำหอมและผลิตภัณฑ์อโรม่าที่คุณชื่นชอบ',
|
||||
path: '/coupons',
|
||||
lang,
|
||||
});
|
||||
}
|
||||
|
||||
export default async function CouponsPage({ params }: { params: Promise<{ lang: string }> }) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { Metadata } from 'next';
|
||||
import { notFound } from 'next/navigation';
|
||||
import '../globals.css';
|
||||
import Navbar from '@/components/Navbar';
|
||||
import Footer from '@/components/Footer';
|
||||
@@ -6,6 +7,7 @@ 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';
|
||||
import { isSupportedLocale } from '@/lib/locales';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'HomAroma',
|
||||
@@ -82,6 +84,10 @@ export default async function RootLayout({
|
||||
}) {
|
||||
const { lang } = await params;
|
||||
|
||||
if (!isSupportedLocale(lang)) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
const [categories, initialMenu, footerMenus, settings] = await Promise.all([
|
||||
getCategories(lang),
|
||||
getMegaMenu(lang),
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import Link from '@/components/LocalizedLink'
|
||||
import { notFound } from 'next/navigation'
|
||||
import type { Metadata } from 'next'
|
||||
import { generateSeoMetadata } from '@/lib/seo'
|
||||
import { CheckCircle2, Clock, PackageCheck, Truck } from 'lucide-react'
|
||||
import { formatPrice } from '@homaroma/types'
|
||||
|
||||
@@ -34,16 +35,18 @@ function statusTone(status: string) {
|
||||
return 'bg-gray-50 text-gray-700 border-gray-100'
|
||||
}
|
||||
|
||||
export async function generateMetadata({ params }: { params: Promise<{ id: string }> }): Promise<Metadata> {
|
||||
const { id } = await params
|
||||
export async function generateMetadata({ params }: { params: Promise<{ id: string, lang: string }> }): Promise<Metadata> {
|
||||
const { id, lang } = await params
|
||||
const result = await getOrderResult(id)
|
||||
|
||||
if (!result.ok) return { title: 'Order Not Found | HomAroma' }
|
||||
|
||||
return {
|
||||
return generateSeoMetadata({
|
||||
title: `Order ${orderLabel(result.data.id)} | HomAroma`,
|
||||
description: `ตรวจสอบสถานะคำสั่งซื้อ ${orderLabel(result.data.id)} จาก HomAroma`,
|
||||
}
|
||||
path: `/order/${id}`,
|
||||
lang,
|
||||
})
|
||||
}
|
||||
|
||||
export default async function OrderStatusPage({ params }: { params: Promise<{ id: string, lang: string }> }) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { Metadata } from 'next'
|
||||
import { generateSeoMetadata } from '@/lib/seo'
|
||||
import DynamicPageRenderer from '@/components/dynamic/DynamicPageRenderer'
|
||||
import { getCategories, getCmsPage } from '@/lib/cms'
|
||||
import { splitCmsLayoutSections } from '@/lib/cms-sections'
|
||||
@@ -11,10 +12,12 @@ export async function generateMetadata({ params }: Props): Promise<Metadata> {
|
||||
const { lang } = await params
|
||||
const page = await getCmsPage('home', lang)
|
||||
|
||||
return {
|
||||
return generateSeoMetadata({
|
||||
title: page?.title ? `${page.title} | HomAroma` : 'HomAroma',
|
||||
description: 'Premium aromatherapy, home fragrance, and botanical scent products from HomAroma.',
|
||||
}
|
||||
path: '',
|
||||
lang,
|
||||
})
|
||||
}
|
||||
|
||||
export default async function HomePage({ params }: Props) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import Link from '@/components/LocalizedLink'
|
||||
import { notFound } from 'next/navigation'
|
||||
import type { Metadata } from 'next'
|
||||
import { generateSeoMetadata } from '@/lib/seo'
|
||||
import { getCategoryImage, type Product } from '@homaroma/types'
|
||||
import AddToCartSection from '@/components/AddToCartSection'
|
||||
import DynamicPageRenderer from '@/components/dynamic/DynamicPageRenderer'
|
||||
@@ -25,15 +26,17 @@ export async function generateMetadata({ params }: { params: Promise<{ id: strin
|
||||
const categoryName = resolveCategoryName(product.category, lang)
|
||||
const description = resolveLocalized(product.description, lang)
|
||||
|
||||
return {
|
||||
return generateSeoMetadata({
|
||||
title: `${productName} ${categoryName ? `| ${categoryName}` : ''} | HomAroma`,
|
||||
description: description || `Premium ${categoryName} from HomAroma.`,
|
||||
path: `/products/${id}`,
|
||||
lang,
|
||||
openGraph: {
|
||||
title: productName,
|
||||
description,
|
||||
images: product.images?.[0]?.url ? [product.images[0].url] : [],
|
||||
},
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export default async function ProductDetailPage({ params }: { params: Promise<{ id: string, lang: string }> }) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { User } from 'lucide-react'
|
||||
import { generateSeoMetadata } from '@/lib/seo'
|
||||
|
||||
import DynamicPageRenderer from '@/components/dynamic/DynamicPageRenderer'
|
||||
import ProfileClient from '@/components/ProfileClient'
|
||||
@@ -6,9 +7,14 @@ import { getCategoriesResult, getCmsPageResult } from '@/lib/cms'
|
||||
import { splitCmsLayoutSections } from '@/lib/cms-sections'
|
||||
|
||||
// lang is extracted from params
|
||||
export const metadata = {
|
||||
title: 'โปรไฟล์สมาชิก | HomAroma',
|
||||
description: 'จัดการโปรไฟล์สมาชิก HomAroma ประวัติคำสั่งซื้อ คะแนนสะสม และสมุดที่อยู่จัดส่ง',
|
||||
export async function generateMetadata({ params }: { params: Promise<{ lang: string }> }) {
|
||||
const { lang } = await params;
|
||||
return generateSeoMetadata({
|
||||
title: 'โปรไฟล์สมาชิก | HomAroma',
|
||||
description: 'จัดการโปรไฟล์สมาชิก HomAroma ประวัติคำสั่งซื้อ คะแนนสะสม และสมุดที่อยู่จัดส่ง',
|
||||
path: '/profile',
|
||||
lang,
|
||||
});
|
||||
}
|
||||
|
||||
export default async function ProfilePage({ params }: { params: Promise<{ lang: string }> }) {
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
import Link from '@/components/LocalizedLink'
|
||||
import { generateSeoMetadata } from '@/lib/seo'
|
||||
import DynamicPageRenderer from '@/components/dynamic/DynamicPageRenderer'
|
||||
import { getArticlesResult, getCategoriesResult, getCmsPageResult } from '@/lib/cms'
|
||||
import { splitCmsLayoutSections } from '@/lib/cms-sections'
|
||||
|
||||
// lang is extracted from params
|
||||
export const metadata = {
|
||||
title: 'Scent Guide | HomAroma',
|
||||
description: 'Explore our collection of aroma articles, guides, and sensory knowledge to find your perfect scent.',
|
||||
export async function generateMetadata({ params }: { params: Promise<{ lang: string }> }) {
|
||||
const { lang } = await params;
|
||||
return generateSeoMetadata({
|
||||
title: 'Scent Guide | HomAroma',
|
||||
description: 'Explore our collection of aroma articles, guides, and sensory knowledge to find your perfect scent.',
|
||||
path: '/scent-guide',
|
||||
lang,
|
||||
});
|
||||
}
|
||||
|
||||
export default async function ScentGuidePage({ params }: { params: Promise<{ lang: string }> }) {
|
||||
|
||||
@@ -1,13 +1,19 @@
|
||||
import Link from '@/components/LocalizedLink'
|
||||
import { generateSeoMetadata } from '@/lib/seo'
|
||||
import DynamicPageRenderer from '@/components/dynamic/DynamicPageRenderer'
|
||||
import ProductCard from '@/components/ProductCard'
|
||||
import { getCategoriesResult, getCmsPageResult, getProductsResult } from '@/lib/cms'
|
||||
import { splitCmsLayoutSections } from '@/lib/cms-sections'
|
||||
import { resolveLocalized } from '@/lib/localization'
|
||||
|
||||
export const metadata = {
|
||||
title: 'Search Products | HomAroma',
|
||||
description: 'Search HomAroma products by scent, category, or keyword.',
|
||||
export async function generateMetadata({ params }: { params: Promise<{ lang: string }> }) {
|
||||
const { lang } = await params;
|
||||
return generateSeoMetadata({
|
||||
title: 'Search Products | HomAroma',
|
||||
description: 'Search HomAroma products by scent, category, or keyword.',
|
||||
path: '/search',
|
||||
lang,
|
||||
});
|
||||
}
|
||||
|
||||
export default async function SearchPage({ searchParams, params }: { searchParams: Promise<{ q?: string | string[] }>, params: Promise<{ lang: string }> }) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import Link from '@/components/LocalizedLink'
|
||||
import { generateSeoMetadata } from '@/lib/seo'
|
||||
import DynamicPageRenderer from '@/components/dynamic/DynamicPageRenderer'
|
||||
import ProductCard from '@/components/ProductCard'
|
||||
import ShopCouponBridge from '@/components/ShopCouponBridge'
|
||||
@@ -7,9 +8,14 @@ import { splitCmsLayoutSections } from '@/lib/cms-sections'
|
||||
import { resolveLocalized } from '@/lib/localization'
|
||||
|
||||
// lang is extracted from params
|
||||
export const metadata = {
|
||||
title: 'Shop Aroma Products | HomAroma',
|
||||
description: 'Browse HomAroma aroma oils, reed diffusers, room sprays, and premium scent products.',
|
||||
export async function generateMetadata({ params }: { params: Promise<{ lang: string }> }) {
|
||||
const { lang } = await params;
|
||||
return generateSeoMetadata({
|
||||
title: 'Shop Aroma Products | HomAroma',
|
||||
description: 'Browse HomAroma aroma oils, reed diffusers, room sprays, and premium scent products.',
|
||||
path: '/shop',
|
||||
lang,
|
||||
});
|
||||
}
|
||||
|
||||
export default async function ShopPage({ searchParams, params }: { searchParams: Promise<{ coupon?: string | string[] }>, params: Promise<{ lang: string }> }) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { MapPin } from 'lucide-react'
|
||||
import { generateSeoMetadata } from '@/lib/seo'
|
||||
|
||||
import DynamicPageRenderer from '@/components/dynamic/DynamicPageRenderer'
|
||||
import TrackOrderClient from '@/components/TrackOrderClient'
|
||||
@@ -6,9 +7,14 @@ import { getCategoriesResult, getCmsPageResult } from '@/lib/cms'
|
||||
import { splitCmsLayoutSections } from '@/lib/cms-sections'
|
||||
|
||||
// lang is extracted from params
|
||||
export const metadata = {
|
||||
title: 'ติดตามคำสั่งซื้อ | HomAroma',
|
||||
description: 'ตรวจสอบสถานะคำสั่งซื้อ HomAroma ด้วยหมายเลขคำสั่งซื้อและเบอร์โทรศัพท์ที่ใช้สั่งซื้อ',
|
||||
export async function generateMetadata({ params }: { params: Promise<{ lang: string }> }) {
|
||||
const { lang } = await params;
|
||||
return generateSeoMetadata({
|
||||
title: 'ติดตามคำสั่งซื้อ | HomAroma',
|
||||
description: 'ตรวจสอบสถานะคำสั่งซื้อ HomAroma ด้วยหมายเลขคำสั่งซื้อและเบอร์โทรศัพท์ที่ใช้สั่งซื้อ',
|
||||
path: '/track',
|
||||
lang,
|
||||
});
|
||||
}
|
||||
|
||||
export default async function TrackPage({ params }: { params: Promise<{ lang: string }> }) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Heart } from 'lucide-react'
|
||||
import { generateSeoMetadata } from '@/lib/seo'
|
||||
|
||||
import DynamicPageRenderer from '@/components/dynamic/DynamicPageRenderer'
|
||||
import WishlistClient from '@/components/WishlistClient'
|
||||
@@ -6,9 +7,14 @@ import { getCategoriesResult, getCmsPageResult } from '@/lib/cms'
|
||||
import { splitCmsLayoutSections } from '@/lib/cms-sections'
|
||||
|
||||
// lang is extracted from params
|
||||
export const metadata = {
|
||||
title: 'Wishlist | HomAroma',
|
||||
description: 'รายการสินค้าที่คุณบันทึกไว้ใน Wishlist ของ HomAroma',
|
||||
export async function generateMetadata({ params }: { params: Promise<{ lang: string }> }) {
|
||||
const { lang } = await params;
|
||||
return generateSeoMetadata({
|
||||
title: 'Wishlist | HomAroma',
|
||||
description: 'รายการสินค้าที่คุณบันทึกไว้ใน Wishlist ของ HomAroma',
|
||||
path: '/wishlist',
|
||||
lang,
|
||||
});
|
||||
}
|
||||
|
||||
export default async function WishlistPage({ params }: { params: Promise<{ lang: string }> }) {
|
||||
|
||||
@@ -7,7 +7,16 @@ export default function robots(): MetadataRoute.Robots {
|
||||
rules: {
|
||||
userAgent: '*',
|
||||
allow: '/',
|
||||
disallow: ['/api/', '/_next/', '/profile/', '/checkout/', '/order/'],
|
||||
disallow: [
|
||||
'/api/',
|
||||
'/_next/',
|
||||
'/*/profile/',
|
||||
'/*/checkout/',
|
||||
'/*/order/',
|
||||
'/profile/',
|
||||
'/checkout/',
|
||||
'/order/'
|
||||
],
|
||||
},
|
||||
sitemap: `${baseUrl}/sitemap.xml`,
|
||||
};
|
||||
|
||||
Reference in new issue
Block a user