feat: refactor product components and add sitemap support
- Updated product components to use new IPageParams interface for better type safety. - Added next-sitemap configuration and generated sitemap.xml and robots.txt files. - Removed deprecated ProductCard component and its associated types. - Enhanced internationalization support across various pages.
This commit is contained in:
@@ -1,21 +1,23 @@
|
||||
import '@/app/globals.css';
|
||||
import { notFound } from 'next/navigation';
|
||||
import { NextIntlClientProvider } from 'next-intl';
|
||||
import type { ILayoutLocaleParams } from '@/models/layout.d';
|
||||
import type { IPageParams } from '@/models/layout.d';
|
||||
|
||||
// export const metadata: Metadata = {
|
||||
// title: 'Create Next App',
|
||||
// description: 'Generated by create next app',
|
||||
// };
|
||||
|
||||
export default async function RootLayout({
|
||||
export default async function ErrorLayout({
|
||||
children,
|
||||
params,
|
||||
}: Readonly<{
|
||||
children: React.ReactNode;
|
||||
params: ILayoutLocaleParams;
|
||||
params: IPageParams;
|
||||
}>) {
|
||||
const locale = await params.locale;
|
||||
const paramsData = await params;
|
||||
const locale = paramsData.locale;
|
||||
const fontClass = locale === 'fa' ? 'font-fa' : 'font-en';
|
||||
let messages;
|
||||
try {
|
||||
messages = (await import(`../../../messages/${locale}.json`)).default;
|
||||
@@ -25,7 +27,7 @@ export default async function RootLayout({
|
||||
|
||||
return (
|
||||
<html lang={locale} dir={locale === 'fa' ? 'rtl' : 'ltr'}>
|
||||
<body className="min-h-svh w-full overflow-x-hidden">
|
||||
<body className={`min-h-svh w-full overflow-x-hidden ${fontClass}`}>
|
||||
<NextIntlClientProvider locale={locale} messages={messages}>
|
||||
{children}
|
||||
</NextIntlClientProvider>
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
import routeFactory from '@/assets/constants/routeFactory';
|
||||
import images from '@/assets/images/images';
|
||||
import Button from '@/components/uikit/button';
|
||||
import { ILayoutLocaleParams } from '@/models/layout';
|
||||
import { IPageParams } from '@/models/layout';
|
||||
import { getTranslations } from 'next-intl/server';
|
||||
|
||||
export default async function NotFound({
|
||||
params,
|
||||
}: {
|
||||
params: ILayoutLocaleParams;
|
||||
}) {
|
||||
const t = await getTranslations({ locale: params.locale });
|
||||
const routes = routeFactory(t, params.locale);
|
||||
export default async function NotFound({ params }: { params: IPageParams }) {
|
||||
const paramsData = await params;
|
||||
const t = await getTranslations({ locale: paramsData.locale });
|
||||
const routes = routeFactory(t, paramsData.locale);
|
||||
|
||||
return (
|
||||
<div className="container mx-auto flex h-svh flex-col items-center justify-center gap-6">
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
import images from '@/assets/images/images';
|
||||
import InnerPageBanner from '@/components/layout/innerPages/banner';
|
||||
import AboutTopInfo from '@/components/pages/about/TopInfo';
|
||||
import { ILayoutLocaleParams } from '@/models/layout';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { IPageParams } from '@/models/layout';
|
||||
import { setRequestLocale } from 'next-intl/server';
|
||||
import { getTranslations } from 'next-intl/server';
|
||||
|
||||
export default async function AboutUs({
|
||||
params,
|
||||
}: Readonly<{
|
||||
params: ILayoutLocaleParams;
|
||||
params: IPageParams;
|
||||
}>) {
|
||||
const { locale } = await params;
|
||||
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
import images from '@/assets/images/images';
|
||||
import InnerPageBanner from '@/components/layout/innerPages/banner';
|
||||
import PostsGrid from '@/components/pages/blog/PostsGrid';
|
||||
import { ILayoutLocaleParams } from '@/models/layout';
|
||||
import { IPageParams } from '@/models/layout';
|
||||
import { getTranslations } from 'next-intl/server';
|
||||
|
||||
export default async function Blog({
|
||||
params,
|
||||
}: {
|
||||
params: ILayoutLocaleParams;
|
||||
}) {
|
||||
const t = await getTranslations({ locale: params.locale });
|
||||
export default async function Blog({ params }: { params: IPageParams }) {
|
||||
const paramsData = await params;
|
||||
const t = await getTranslations({ locale: paramsData.locale });
|
||||
|
||||
return (
|
||||
<main className="flex flex-col items-center justify-between">
|
||||
|
||||
@@ -5,14 +5,12 @@ import ContactForm from '@/components/pages/contact/ContactMeForm';
|
||||
import TouchUs from '@/components/pages/contact/TouchUs';
|
||||
import Image from 'next/image';
|
||||
import { getTranslations } from 'next-intl/server';
|
||||
import { ILayoutLocaleParams } from '@/models/layout';
|
||||
import { IPageParams } from '@/models/layout';
|
||||
|
||||
export default async function Contact({
|
||||
params,
|
||||
}: {
|
||||
params: ILayoutLocaleParams;
|
||||
}) {
|
||||
const t = await getTranslations({ locale: params.locale });
|
||||
export default async function Contact({ params }: { params: IPageParams }) {
|
||||
const { locale } = await params;
|
||||
|
||||
const t = await getTranslations({ locale });
|
||||
|
||||
return (
|
||||
<main className="flex flex-col items-center justify-between">
|
||||
|
||||
@@ -2,24 +2,18 @@ import Footer from '@/components/layout/footer/Footer';
|
||||
import '@/app/globals.css';
|
||||
import 'leaflet/dist/leaflet.css';
|
||||
import { notFound } from 'next/navigation';
|
||||
// import { cookies } from 'next/headers';
|
||||
import { NextIntlClientProvider } from 'next-intl';
|
||||
import type { ILayoutLocaleParams } from '@/models/layout.d';
|
||||
import { cookies } from 'next/headers';
|
||||
import type { IPageParams } from '@/models/layout.d';
|
||||
|
||||
export default async function RootLayout({
|
||||
children,
|
||||
params,
|
||||
}: Readonly<{
|
||||
children: React.ReactNode;
|
||||
params: ILayoutLocaleParams;
|
||||
params: IPageParams;
|
||||
}>) {
|
||||
const paramsData = await params;
|
||||
const locale = paramsData.locale;
|
||||
// const cookieStore = await cookies();
|
||||
|
||||
// // Set locale cookie on the server
|
||||
// cookieStore.set('locale', locale, { path: '/', httpOnly: false });
|
||||
|
||||
const fontClass = locale === 'fa' ? 'font-fa' : 'font-en';
|
||||
|
||||
|
||||
@@ -2,17 +2,13 @@ import Header from '@/components/layout/header';
|
||||
import AboutTopInfo from '@/components/pages/about/TopInfo';
|
||||
import HomeStorySection from '@/components/pages/home/HomeStorySection';
|
||||
import HomePageProducts from '@/components/pages/home/Products';
|
||||
import { ILayoutLocaleParams } from '@/models/layout';
|
||||
import type { IPageParams } from '@/models/layout.d';
|
||||
import { getTranslations } from 'next-intl/server';
|
||||
|
||||
interface IPageParams {
|
||||
params: ILayoutLocaleParams;
|
||||
}
|
||||
|
||||
export default async function Home({ params }: IPageParams) {
|
||||
export default async function Home({ params }: { params: IPageParams }) {
|
||||
const { locale } = await params;
|
||||
|
||||
const t = await getTranslations({ locale });
|
||||
await getTranslations({ locale });
|
||||
|
||||
return (
|
||||
<main className="flex flex-col items-center justify-between">
|
||||
|
||||
@@ -3,22 +3,20 @@ import images from '@/assets/images/images';
|
||||
import Breadcrumb from '@/components/layout/breadcrumb';
|
||||
import { IBreadcrumbItem } from '@/components/layout/breadcrumb/breadcrumb';
|
||||
import InnerPageBanner from '@/components/layout/innerPages/banner';
|
||||
import Pagination from '@/components/layout/pagination';
|
||||
import ProductCategoryCardInProducts from '@/components/pages/productCategories/ProductCategoryCardInProducts';
|
||||
import ProductCard from '@/components/pages/products/ProductCard';
|
||||
import ProductList from '@/components/pages/products/productList';
|
||||
import { ILayoutLocaleParams } from '@/models/layout';
|
||||
import { IPageParams } from '@/models/layout';
|
||||
import { getProductCategoryById, getProducts } from '@/services/products';
|
||||
import { getTranslations } from 'next-intl/server';
|
||||
|
||||
interface IParams extends ILayoutLocaleParams {
|
||||
interface IParams {
|
||||
product_category_id: string;
|
||||
}
|
||||
|
||||
export default async function ProductPage({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<IParams>;
|
||||
params: IPageParams<IParams>;
|
||||
}) {
|
||||
const { product_category_id: productCategoryId, locale } = await params;
|
||||
const t = await getTranslations({ locale });
|
||||
|
||||
@@ -2,17 +2,17 @@ import images from '@/assets/images/images';
|
||||
import InnerPageBanner from '@/components/layout/innerPages/banner';
|
||||
import ProductsCategoryCard from '@/components/pages/productCategories/ProductCategoryCard';
|
||||
import type { IProductCategoryCardProps } from '@/components/pages/productCategories/productCategoryCard.d';
|
||||
import { ILayoutLocaleParams } from '@/models/layout';
|
||||
import { IPageParams } from '@/models/layout';
|
||||
import { getProductCategories } from '@/services/products';
|
||||
import { getTranslations } from 'next-intl/server';
|
||||
|
||||
export default async function ProductsPage({
|
||||
params,
|
||||
}: {
|
||||
params: ILayoutLocaleParams;
|
||||
params: IPageParams;
|
||||
}) {
|
||||
const awaitedParams = await params;
|
||||
const t = await getTranslations({ locale: awaitedParams.locale });
|
||||
const { locale } = await params;
|
||||
const t = await getTranslations({ locale });
|
||||
const productCategories: IProductCategoryCardProps[] =
|
||||
await getProductCategories();
|
||||
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
import images from '@/assets/images/images';
|
||||
import InnerPageBanner from '@/components/layout/innerPages/banner';
|
||||
import ProjectsGrid from '@/components/pages/project/ProjectGrid';
|
||||
import { ILayoutLocaleParams } from '@/models/layout';
|
||||
import { IPageParams } from '@/models/layout';
|
||||
import { getTranslations } from 'next-intl/server';
|
||||
|
||||
export default async function Projects({
|
||||
params,
|
||||
}: {
|
||||
params: ILayoutLocaleParams;
|
||||
}) {
|
||||
const t = await getTranslations({ locale: params.locale });
|
||||
export default async function Projects({ params }: { params: IPageParams }) {
|
||||
const { locale } = await params;
|
||||
const t = await getTranslations({ locale });
|
||||
|
||||
return (
|
||||
<main className="flex flex-col items-center justify-between">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { productCategories } from '../../data';
|
||||
import type { IProductCardProps } from '@/components/pages/products/productCard.d';
|
||||
import type { IProductCardProps } from '@/components/pages/products/productCard/productCard.d';
|
||||
|
||||
// Helper to generate 50 products for a category
|
||||
export function generateProductsForCategory(
|
||||
|
||||
@@ -7,7 +7,7 @@ export async function GET(request: NextRequest, context: any) {
|
||||
const cookieStore = await cookies();
|
||||
const lang = cookieStore.get('locale')?.value || 'en';
|
||||
|
||||
const params = context.params;
|
||||
const params = await context.params;
|
||||
const category = productCategories.find((cat) => cat.id === params.id);
|
||||
|
||||
if (!category) {
|
||||
|
||||
@@ -4,14 +4,19 @@ import { NextResponse, NextRequest } from 'next/server';
|
||||
import { cookies } from 'next/headers';
|
||||
import { productCategories } from '../data';
|
||||
|
||||
export async function GET(
|
||||
request: NextRequest,
|
||||
context: { params: { id: string } },
|
||||
) {
|
||||
interface IContext {
|
||||
params: {
|
||||
id: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface IParams {}
|
||||
|
||||
export async function GET(request: NextRequest, context: any) {
|
||||
const cookieStore = await cookies();
|
||||
const lang = cookieStore.get('locale')?.value || 'en';
|
||||
|
||||
const params = await context.params;
|
||||
const params = (await context).params;
|
||||
|
||||
const { id } = params;
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
[]
|
||||
@@ -0,0 +1,49 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { writeFile, readFile } from 'fs/promises';
|
||||
import path from 'path';
|
||||
|
||||
const filePath = path.resolve(process.cwd(), 'contactMessages.json');
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const body = await request.json();
|
||||
const { first_name, last_name, phone, email, message } = body;
|
||||
|
||||
if (!first_name || !last_name || !phone || !email || !message) {
|
||||
return NextResponse.json(
|
||||
{ error: 'مقدار تمامی فیلدها را پر کنید' },
|
||||
{ status: 400 },
|
||||
);
|
||||
}
|
||||
|
||||
let messages = [];
|
||||
try {
|
||||
const fileData = await readFile(filePath, 'utf-8');
|
||||
messages = JSON.parse(fileData);
|
||||
} catch {
|
||||
messages = [];
|
||||
}
|
||||
|
||||
const newMessage = {
|
||||
name,
|
||||
email,
|
||||
message,
|
||||
createdAt: new Date().toISOString(),
|
||||
};
|
||||
|
||||
messages.push(newMessage);
|
||||
|
||||
// Write updated messages back to file
|
||||
await writeFile(filePath, JSON.stringify(messages, null, 2), 'utf-8');
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
message: 'Your message has been received.',
|
||||
});
|
||||
} catch (error) {
|
||||
return NextResponse.json(
|
||||
{ error, message: 'مشکلی پیش آمده.' },
|
||||
{ status: 400 },
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user