Files
sanihome/src/app/layout.tsx
T
amirhosein.ashourlooandClaude Sonnet 5 66f92b634e Add customer auth, real cart/checkout, store-items pages, comments, contact form
- Real in-site login/register (password + SMS OTP) against Meshkee's
  /auth API, with self-healing access-token refresh (15 min lifetime) and
  an in-flight-refresh guard so AuthContext and CartContext don't race
  each other into a failed concurrent refresh.
- Real cart: header cart button/badge, a cart popup, and a working
  "add to cart" on both product cards (where a specific variant id is
  known) and the product/store-item detail buy-box (always resolves a
  purchasable variant, even for single-SKU products with no selectable
  variation).
- /checkout: address + cash/bank-transfer payment, posts to the real
  checkout API and creates an order; refreshes the cart afterward so the
  header badge doesn't go stale.
- New /store-items and /store-items/[id] pages (variant-level browsing,
  separate from the product-level /products catalog), cross-referencing
  the parent product for images/description/technical-info.
- Product gallery: click-to-open fullscreen lightbox alongside the
  existing hover-zoom.
- Comments tab wired to the real comments API, gated to logged-in users
  (a product decision — the API itself doesn't require auth) with a
  login prompt otherwise.
- Similar-products row on product/store-item detail pages.
- Contact page wired to the real contact-submissions API, with a toast
  and inline confirmation on success, and the form resetting.
- CONTEXT.md: a maintained architecture/conventions doc for this repo,
  now auto-loaded via CLAUDE.md, covering the Meshkee integration quirks
  and UI conventions established across this project.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-06 08:06:30 +03:30

59 lines
1.8 KiB
TypeScript

import type { Metadata } from "next";
import { Syne } from "next/font/google";
import localFont from "next/font/local";
import "./globals.css";
import { TopBar } from "@/components/home/TopBar";
import { Header } from "@/components/home/Header";
import { Footer } from "@/components/home/Footer";
import { Providers } from "@/context/Providers";
import { getBusinessInfo, getCategories, getCategoryTree } from "@/lib/meshkee";
// Body text — headings use the bold weight instead, see globals.css.
const iranyekan = localFont({
variable: "--font-iranyekan",
src: "../../public/fonts/iranyekanweblightfanum.woff",
weight: "400",
});
const iranyekanBold = localFont({
variable: "--font-iranyekan-bold",
src: "../../public/fonts/iranyekanwebboldfanum.woff",
weight: "700",
});
const syne = Syne({
variable: "--font-syne",
subsets: ["latin"],
weight: ["600", "700", "800"],
});
export const metadata: Metadata = {
title: "سانی‌هوم | فروشگاه لوازم خانگی",
description: "فروشگاه آنلاین لوازم خانگی — یخچال، لباسشویی، تلویزیون و بیشتر",
};
export default async function RootLayout({ children }: LayoutProps<"/">) {
const [categoryTree, categories, businessInfo] = await Promise.all([
getCategoryTree(),
getCategories(),
getBusinessInfo(),
]);
return (
<html
lang="fa"
dir="rtl"
className={`${iranyekan.variable} ${iranyekanBold.variable} ${syne.variable} h-full antialiased`}
>
<body className="min-h-full flex flex-col">
<Providers businessId={businessInfo?.id ?? "1"}>
<TopBar />
<Header categoryTree={categoryTree} categories={categories} />
<main>{children}</main>
<Footer businessInfo={businessInfo} categories={categories} />
</Providers>
</body>
</html>
);
}