164 lines
6.9 KiB
TypeScript
164 lines
6.9 KiB
TypeScript
import Image from 'next/image'
|
|
import Link from 'next/link'
|
|
import { ArrowRight, Home, Search, ShoppingBag } from 'lucide-react'
|
|
import { getPathWithLocale, type Locale } from '@/lib/locales'
|
|
|
|
const copy = {
|
|
th: {
|
|
eyebrow: 'ไม่พบหน้านี้',
|
|
title: 'เส้นทางนี้ยังไม่มีกลิ่นที่ตามหา',
|
|
description: 'ลิงก์อาจถูกย้าย ลบ หรือยังไม่ได้เผยแพร่ ลองกลับไปเลือกสินค้าหรือค้นหากลิ่นที่เหมาะกับพื้นที่ของคุณ',
|
|
home: 'กลับหน้าแรก',
|
|
shop: 'เลือกสินค้า',
|
|
search: 'ค้นหาสินค้า',
|
|
guide: 'คู่มือเลือกกลิ่น',
|
|
contact: 'ติดต่อเรา',
|
|
hint: '404',
|
|
},
|
|
en: {
|
|
eyebrow: 'Page not found',
|
|
title: 'This scent trail has faded',
|
|
description: 'The link may have moved, expired, or is not published yet. Head back to the collection or search for the right aroma.',
|
|
home: 'Back home',
|
|
shop: 'Shop products',
|
|
search: 'Search products',
|
|
guide: 'Scent Guide',
|
|
contact: 'Contact',
|
|
hint: '404',
|
|
},
|
|
ja: {
|
|
eyebrow: 'ページが見つかりません',
|
|
title: 'お探しの香りのページは見つかりません',
|
|
description: 'リンクが移動、削除、または未公開の可能性があります。コレクションに戻るか商品を検索してください。',
|
|
home: 'ホームへ戻る',
|
|
shop: '商品を見る',
|
|
search: '商品を検索',
|
|
guide: '香りガイド',
|
|
contact: 'お問い合わせ',
|
|
hint: '404',
|
|
},
|
|
zh: {
|
|
eyebrow: '页面未找到',
|
|
title: '这条香气路径暂时不存在',
|
|
description: '链接可能已移动、删除或尚未发布。你可以返回首页、浏览商品或搜索合适的香氛。',
|
|
home: '返回首页',
|
|
shop: '浏览商品',
|
|
search: '搜索商品',
|
|
guide: '香氛指南',
|
|
contact: '联系我们',
|
|
hint: '404',
|
|
},
|
|
vi: {
|
|
eyebrow: 'Không tìm thấy trang',
|
|
title: 'Đường dẫn hương thơm này không còn tồn tại',
|
|
description: 'Liên kết có thể đã được di chuyển, xóa hoặc chưa xuất bản. Hãy quay lại bộ sưu tập hoặc tìm sản phẩm phù hợp.',
|
|
home: 'Về trang chủ',
|
|
shop: 'Xem sản phẩm',
|
|
search: 'Tìm sản phẩm',
|
|
guide: 'Hướng dẫn mùi hương',
|
|
contact: 'Liên hệ',
|
|
hint: '404',
|
|
},
|
|
ko: {
|
|
eyebrow: '페이지를 찾을 수 없습니다',
|
|
title: '찾으시는 향의 경로가 사라졌습니다',
|
|
description: '링크가 이동되었거나 삭제되었거나 아직 공개되지 않았을 수 있습니다. 컬렉션으로 돌아가거나 상품을 검색해 보세요.',
|
|
home: '홈으로',
|
|
shop: '상품 보기',
|
|
search: '상품 검색',
|
|
guide: '향 가이드',
|
|
contact: '문의하기',
|
|
hint: '404',
|
|
},
|
|
} as const
|
|
|
|
type CopyLang = keyof typeof copy
|
|
|
|
function getCopy(lang: string) {
|
|
return copy[(lang in copy ? lang : 'th') as CopyLang]
|
|
}
|
|
|
|
type LocalizedNotFoundProps = {
|
|
lang: Locale
|
|
}
|
|
|
|
export default function LocalizedNotFound({ lang }: LocalizedNotFoundProps) {
|
|
const text = getCopy(lang)
|
|
|
|
return (
|
|
<section className="min-h-[70vh] bg-surface-page px-6 py-16 text-text-main md:py-24">
|
|
<div className="mx-auto grid max-w-6xl items-center gap-12 lg:grid-cols-[1.05fr_0.95fr]">
|
|
<div>
|
|
<div className="ui-panel mb-8 inline-flex items-center gap-3 px-4 py-2">
|
|
<Image src="/favicon.svg" alt="" width={28} height={28} aria-hidden="true" />
|
|
<span className="ui-eyebrow">{text.eyebrow}</span>
|
|
</div>
|
|
|
|
<p className="text-8xl font-black leading-none text-brand-primary/20 md:text-9xl">{text.hint}</p>
|
|
<h1 className="mt-6 max-w-3xl text-4xl font-semibold leading-tight text-text-main md:text-6xl">
|
|
{text.title}
|
|
</h1>
|
|
<p className="mt-6 max-w-2xl text-base leading-8 text-muted-text md:text-lg">
|
|
{text.description}
|
|
</p>
|
|
|
|
<div className="mt-10 flex flex-col gap-3 sm:flex-row">
|
|
<Link
|
|
href={getPathWithLocale('/', lang)}
|
|
className="ui-button-primary px-6 py-3"
|
|
>
|
|
<Home className="h-4 w-4" />
|
|
{text.home}
|
|
</Link>
|
|
<Link
|
|
href={getPathWithLocale('/shop', lang)}
|
|
className="ui-button-brand bg-surface-card text-text-main hover:bg-surface-page hover:text-brand-primary"
|
|
>
|
|
<ShoppingBag className="h-4 w-4" />
|
|
{text.shop}
|
|
</Link>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="ui-panel border border-white/80 bg-surface-card/80 p-6 backdrop-blur md:p-8">
|
|
<div className="rounded-[1.5rem] bg-surface-page p-6">
|
|
<div className="flex items-center gap-3 border-b border-text-main/10 pb-5">
|
|
<div className="flex h-11 w-11 items-center justify-center rounded-full bg-surface-card text-brand-primary shadow-sm">
|
|
<Search className="h-5 w-5" />
|
|
</div>
|
|
<div>
|
|
<p className="text-xs font-bold uppercase tracking-[0.18em] text-muted-text">{text.hint}</p>
|
|
<p className="mt-1 text-sm font-semibold text-text-main">{text.search}</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="mt-6 grid gap-3">
|
|
<Link
|
|
href={getPathWithLocale('/search', lang)}
|
|
className="group flex items-center justify-between rounded-2xl bg-surface-card px-5 py-4 text-sm font-semibold text-text-main transition hover:text-brand-primary"
|
|
>
|
|
<span>{text.search}</span>
|
|
<ArrowRight className="h-4 w-4 transition group-hover:translate-x-1" />
|
|
</Link>
|
|
<Link
|
|
href={getPathWithLocale('/scent-guide', lang)}
|
|
className="group flex items-center justify-between rounded-2xl bg-surface-card px-5 py-4 text-sm font-semibold text-text-main transition hover:text-brand-primary"
|
|
>
|
|
<span>{text.guide}</span>
|
|
<ArrowRight className="h-4 w-4 transition group-hover:translate-x-1" />
|
|
</Link>
|
|
<Link
|
|
href={getPathWithLocale('/contact', lang)}
|
|
className="group flex items-center justify-between rounded-2xl bg-surface-card px-5 py-4 text-sm font-semibold text-text-main transition hover:text-brand-primary"
|
|
>
|
|
<span>{text.contact}</span>
|
|
<ArrowRight className="h-4 w-4 transition group-hover:translate-x-1" />
|
|
</Link>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
)
|
|
}
|