feat: add product category components and services
- Implemented ProductCategoryCard component for displaying product categories with icons, titles, and counts. - Created ProductCategoryCardInProducts component for rendering product categories in a product context. - Defined TypeScript interfaces for product category props. - Added ProductCard component for individual product display with image and title. - Established Axios instance for API calls with request and response interceptors. - Developed services for fetching product categories and category details from the API.
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
import { cookies } from 'next/headers';
|
||||
import { productCategories } from '../data';
|
||||
|
||||
export async function GET(
|
||||
request: Request,
|
||||
{ params }: { params: { id: string } },
|
||||
) {
|
||||
const cookieStore = await cookies();
|
||||
const lang = cookieStore.get('lang')?.value || 'en';
|
||||
|
||||
const category = productCategories.find((cat) => cat.id === params.id);
|
||||
|
||||
if (!category) {
|
||||
return NextResponse.json({ error: 'Not found' }, { status: 404 });
|
||||
}
|
||||
|
||||
const titleData =
|
||||
lang === 'fa' && category.fa_title ? category.fa_title : category.title;
|
||||
const priceTypeTitleData =
|
||||
lang === 'fa' && category.fa_priceTypeTitle
|
||||
? category.fa_priceTypeTitle
|
||||
: category.priceTypeTitle;
|
||||
const bestForTitleData =
|
||||
lang === 'fa' && category.fa_bestForTitle
|
||||
? category.fa_bestForTitle
|
||||
: category.bestForTitle;
|
||||
|
||||
return NextResponse.json({
|
||||
data: {
|
||||
id: category.id,
|
||||
icon: category.icon,
|
||||
typesCount: category.typesCount,
|
||||
title: titleData,
|
||||
priceTypeTitle: priceTypeTitleData,
|
||||
bestForTitle: bestForTitleData,
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
export const productCategories = [
|
||||
{
|
||||
id: '1',
|
||||
title: 'Ghazaghi',
|
||||
fa_title: 'قزاقی',
|
||||
icon: 'categoryGhazaghi',
|
||||
typesCount: 22,
|
||||
priceTypeTitle: 'Economy',
|
||||
fa_priceTypeTitle: 'اقتصادی',
|
||||
bestForTitle: 'Best For Interior Part',
|
||||
fa_bestForTitle: 'Best For Interior Part',
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
title: 'Ghermez',
|
||||
fa_title: 'قرمز',
|
||||
icon: 'categoryGhermez',
|
||||
typesCount: 12,
|
||||
priceTypeTitle: 'Luxury',
|
||||
fa_priceTypeTitle: 'لاکچری',
|
||||
bestForTitle: 'Best For Exterior Part',
|
||||
fa_bestForTitle: 'Best For Exterior Part',
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
title: 'oryZard',
|
||||
fa_title: 'زرد',
|
||||
icon: 'categoryZard',
|
||||
typesCount: 11,
|
||||
priceTypeTitle: 'Economy',
|
||||
fa_priceTypeTitle: 'اقتصادی',
|
||||
bestForTitle: 'Best For Facing',
|
||||
fa_bestForTitle: 'Best For Facing',
|
||||
},
|
||||
{
|
||||
id: '40',
|
||||
title: 'Semirom',
|
||||
fa_title: 'سمیرم',
|
||||
icon: 'categorySemirom',
|
||||
typesCount: 40,
|
||||
priceTypeTitle: 'Economy',
|
||||
fa_priceTypeTitle: 'اقتصادی',
|
||||
bestForTitle: 'Best For Building',
|
||||
fa_bestForTitle: 'Best For Building',
|
||||
},
|
||||
] as APIProductCategoryEntity[];
|
||||
|
||||
interface APIProductCategoryEntity {
|
||||
id: string;
|
||||
title: string;
|
||||
fa_title?: string;
|
||||
icon: string;
|
||||
typesCount: number;
|
||||
priceTypeTitle: string;
|
||||
fa_priceTypeTitle?: string;
|
||||
bestForTitle: string;
|
||||
fa_bestForTitle?: string;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
import { cookies } from 'next/headers';
|
||||
import { productCategories } from './data';
|
||||
|
||||
export async function GET(request: Request) {
|
||||
let data = productCategories;
|
||||
|
||||
const cookieStore = cookies();
|
||||
const lang = (await cookieStore).get('lang')?.value || 'fa';
|
||||
|
||||
if (lang === 'fa') {
|
||||
data = productCategories.map(
|
||||
({
|
||||
id,
|
||||
title,
|
||||
fa_title,
|
||||
icon,
|
||||
typesCount,
|
||||
priceTypeTitle,
|
||||
fa_priceTypeTitle,
|
||||
bestForTitle,
|
||||
fa_bestForTitle,
|
||||
}) => {
|
||||
const titleData = lang === 'fa' && fa_title ? fa_title : title;
|
||||
const priceTypeTitleData =
|
||||
lang === 'fa' && fa_priceTypeTitle
|
||||
? fa_priceTypeTitle
|
||||
: priceTypeTitle;
|
||||
const bestForTitleData =
|
||||
lang === 'fa' && fa_bestForTitle ? fa_bestForTitle : bestForTitle;
|
||||
return {
|
||||
id,
|
||||
icon,
|
||||
typesCount,
|
||||
title: titleData,
|
||||
priceTypeTitle: priceTypeTitleData,
|
||||
bestForTitle: bestForTitleData,
|
||||
};
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return NextResponse.json({ data: productCategories });
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
import { cookies } from 'next/headers';
|
||||
import { productCategories } from '../product_categories/data';
|
||||
|
||||
export async function GET(request: Request) {
|
||||
const data = productCategories.find(
|
||||
(productCategory) => productCategory.id === request.url.split('/').pop(),
|
||||
);
|
||||
|
||||
const cookieStore = cookies();
|
||||
const lang = (await cookieStore).get('lang')?.value || 'fa';
|
||||
|
||||
// if (lang === 'fa') {
|
||||
// data = productCategories.find(
|
||||
// ({
|
||||
// id,
|
||||
// title,
|
||||
// fa_title,
|
||||
// icon,
|
||||
// typesCount,
|
||||
// priceTypeTitle,
|
||||
// fa_priceTypeTitle,
|
||||
// bestForTitle,
|
||||
// fa_bestForTitle,
|
||||
// }) => {
|
||||
// const titleData = lang === 'fa' && fa_title ? fa_title : title;
|
||||
// const priceTypeTitleData =
|
||||
// lang === 'fa' && fa_priceTypeTitle
|
||||
// ? fa_priceTypeTitle
|
||||
// : priceTypeTitle;
|
||||
// const bestForTitleData =
|
||||
// lang === 'fa' && fa_bestForTitle ? fa_bestForTitle : bestForTitle;
|
||||
// return {data}
|
||||
// }
|
||||
|
||||
return NextResponse.json({ data });
|
||||
}
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const data = await request.json();
|
||||
return NextResponse.json({ message: 'Received POST request', data });
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
import images from '@/assets/images/images';
|
||||
import InnerPageBanner from '@/components/layout/innerPages/banner';
|
||||
import ProductCard from '@/components/pages/products/ProductCard';
|
||||
import { getProductCategoryById } from '@/services/products';
|
||||
|
||||
export default async function ProductPage({
|
||||
params,
|
||||
}: {
|
||||
params: { product_category_id: string };
|
||||
}) {
|
||||
const { product_category_id: productCategoryId } = params;
|
||||
|
||||
const productCategory = await getProductCategoryById(productCategoryId);
|
||||
|
||||
const product = {
|
||||
title: 'Product title',
|
||||
size: 'W 18 * L10',
|
||||
imageSrc: images.product1.src,
|
||||
};
|
||||
const products = Array.from({ length: 10 }, () => product);
|
||||
return (
|
||||
<main className="">
|
||||
<InnerPageBanner
|
||||
title={productCategory.title}
|
||||
imageSrc={images.homeProductBack.src}
|
||||
/>
|
||||
<div className="container mx-auto my-24">
|
||||
<div className="grid grid-cols-4 gap-3">
|
||||
{products.map((product, index) => (
|
||||
<ProductCard {...product} key={index} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
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 { t } from '@/locales/translates';
|
||||
import { getProductCategories } from '@/services/products';
|
||||
|
||||
export default async function ProductsPage() {
|
||||
const productCategories: IProductCategoryCardProps[] =
|
||||
await getProductCategories();
|
||||
|
||||
return (
|
||||
<main>
|
||||
<InnerPageBanner
|
||||
title={t('pages_projects_title') as string}
|
||||
imageSrc={images.aboutBanner.src}
|
||||
/>
|
||||
<div className="container mx-auto my-24">
|
||||
<div className="grid w-full grid-cols-4 gap-4">
|
||||
{productCategories.map((category) => (
|
||||
<ProductsCategoryCard key={category.id} {...category} />
|
||||
))}
|
||||
</div>
|
||||
<div className="mt-20">
|
||||
<h2 className="mb-4 text-2xl font-semibold text-gray-500">
|
||||
{t('pages_products_content_title') as string}
|
||||
</h2>
|
||||
<p className="text-base font-light text-gray-400">
|
||||
{t('pages_products_content_description') as string}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
import images from '@/assets/images/images';
|
||||
import InnerPageBanner from '@/components/layout/innerPages/banner';
|
||||
import ProductsCategoryCard from '@/components/pages/products/ProductCategoryCard';
|
||||
import type { IProductCategoryCardProps } from '@/components/pages/products/productCategoryCard.d';
|
||||
import { t } from '@/locales/translates';
|
||||
|
||||
export default function ProductsPage() {
|
||||
const productCategories = [
|
||||
{
|
||||
id: '1',
|
||||
title: t('com_products_category_Ghazaghi_title') as string,
|
||||
icon: 'categoryGhazaghi',
|
||||
typesCount: 22,
|
||||
priceTypeTitle: 'Economy',
|
||||
bestForTitle: 'Best For Interior Part',
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
title: t('com_products_category_Ghermez_title') as string,
|
||||
icon: 'categoryGhermez',
|
||||
typesCount: 12,
|
||||
priceTypeTitle: 'Luxury',
|
||||
bestForTitle: 'Best For Exterior Part',
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
title: t('com_products_category_Zard_title') as string,
|
||||
icon: 'categoryZard',
|
||||
typesCount: 11,
|
||||
priceTypeTitle: 'Economy',
|
||||
bestForTitle: 'Best For Facing',
|
||||
},
|
||||
{
|
||||
id: '40',
|
||||
title: t('com_products_category_Semirom_title') as string,
|
||||
icon: 'categorySemirom',
|
||||
typesCount: 40,
|
||||
priceTypeTitle: 'Economy',
|
||||
bestForTitle: 'Best For Building',
|
||||
},
|
||||
] as IProductCategoryCardProps[];
|
||||
return (
|
||||
<main>
|
||||
<InnerPageBanner
|
||||
title={t('pages_projects_title') as string}
|
||||
imageSrc={images.aboutBanner.src}
|
||||
/>
|
||||
<div className="container my-24 grid grid-cols-4 gap-4">
|
||||
{productCategories.map((category) => (
|
||||
<ProductsCategoryCard key={category.id} {...category} />
|
||||
))}
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user