responsive danak-services

This commit is contained in:
hamid zarghami
2025-04-15 10:22:38 +03:30
parent 6320cc0784
commit 9bba9156a3
14 changed files with 362 additions and 269 deletions
+78
View File
@@ -0,0 +1,78 @@
'use client'
import SectionHeader from '@/components/SectionHeader'
import ServiceItem from '@/components/ServiceItem'
import { clx } from '@/helpers/utils'
import { FC, useState } from 'react'
import { Swiper, SwiperSlide } from 'swiper/react'
import { useGetCategories, useGetServicesByCategory } from './hooks/useProductData'
import Image from 'next/image'
const DanakServices: FC = () => {
const [categoryId, setCategoryId] = useState<string>('')
const { data: categories } = useGetCategories()
const { data } = useGetServicesByCategory(categoryId)
return (
<div className='xl:mt-24 mt-12 max-w-maxWidth mx-auto'>
<SectionHeader
title='سرویس های داناک'
/>
<div className='mt-6'>
<Swiper
className='w-full'
spaceBetween={15}
slidesPerView='auto'
>
<SwiperSlide className='max-w-[158px]'>
<div onClick={() => setCategoryId('')} className={clx(
'h-10 cursor-pointer rounded-full border-2 border-white bg-white/45 flex gap-2 justify-center items-center',
'' === categoryId && 'bg-white'
)}>
<div className='text-sm'>
همه
</div>
</div>
</SwiperSlide>
{
categories?.data?.categories?.map((item) => {
return (
<SwiperSlide className='max-w-[158px]' key={item.id}>
<div onClick={() => setCategoryId(item.id)} className={clx(
'h-10 cursor-pointer rounded-full border-2 border-white bg-white/45 flex gap-2 justify-center items-center',
item.id === categoryId && 'bg-white'
)}>
<div className='size-5 rounded-full overflow-hidden bg-blue-100'>
<Image src={item.icon} alt={item.title} width={20} height={20} />
</div>
<div className='text-sm'>
{item.title}
</div>
</div>
</SwiperSlide>
)
})
}
</Swiper>
</div>
<div className='xl:mt-16 mt-10 flex flex-wrap gap-8'>
{data?.data?.services?.map((item) => {
return (
<div key={item.id} className='xl:min-w-[30%] min-w-[70%] flex-1'>
<ServiceItem
isShort
item={item}
/>
</div>
)
})}
<div className='xl:min-w-[30%] min-w-[70%] flex-1'></div>
<div className='xl:min-w-[30%] min-w-[70%] flex-1'></div>
</div>
</div>
)
}
export default DanakServices
+173
View File
@@ -0,0 +1,173 @@
'use client'
import { ArrowLeft } from 'iconsax-react'
import Image from 'next/image'
import { Swiper, SwiperSlide } from 'swiper/react'
import DanakSuggestedService from '../home/DanakSuggestedService'
import { FC } from 'react'
import DanakServices from './DanakServices'
const Products: FC = () => {
return (
<div className='max-w-maxWidth mx-auto'>
<div className='flex justify-between mt-20 items-center'>
<h1 className='text-2xl font-bold'>
محصولات
</h1>
<div className='max-w-[320px] text-sm leading-6 hidden xl:block text-center xl:text-right'>
لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است
</div>
</div>
<div className='mt-20'>
<Swiper
className='w-full'
spaceBetween={15}
slidesPerView={'auto'}
>
<SwiperSlide className='xl:max-w-[45%] max-w-[90%]'>
<div className='rounded-4xl overflow-hidden relative'>
<Image
src='https://burgeraddict.fr/wp-content/uploads/2024/09/MSG-Smash-Burger-FT-RECIPE0124-d9682401f3554ef683e24311abdf342b.jpg'
alt='product'
width={1080}
height={1080}
className='w-full h-[400px] object-cover'
/>
<div className='absolute bottom-0 left-0 w-full modalGlass3 h-[150px] rounded-b-3xl text-white p-4'>
<div className='flex justify-between items-center'>
<h6 className='text-xs'>
منو دیجیتال رستوران
</h6>
<div className='h-8 bg-black text-white rounded-xl text-sm px-5 flex items-center'>
دسته بندی
</div>
</div>
<div className='mt-6 flex justify-between items-end'>
<div className='flex gap-4'>
<div className='size-14 bg-red-50 rounded-2xl'></div>
<div>
<h2 className='text-xl font-bold'>
دی منو
</h2>
<div className='mt-1'>
<h6 className='text-sm'>
داناک
</h6>
</div>
</div>
</div>
<div className='flex gap-1.5 text-sm items-center'>
<div>جزییات</div>
<ArrowLeft
size={20}
color='white'
/>
</div>
</div>
</div>
</div>
</SwiperSlide>
<SwiperSlide className='xl:max-w-[45%] max-w-[90%]'>
<div className='rounded-4xl overflow-hidden relative'>
<Image
src='https://burgeraddict.fr/wp-content/uploads/2024/09/MSG-Smash-Burger-FT-RECIPE0124-d9682401f3554ef683e24311abdf342b.jpg'
alt='product'
width={1080}
height={1080}
className='w-full h-[400px] object-cover'
/>
<div className='absolute bottom-0 left-0 w-full modalGlass3 h-[150px] rounded-b-3xl text-white p-4'>
<div className='flex justify-between items-center'>
<h6 className='text-xs'>
منو دیجیتال رستوران
</h6>
<div className='h-8 bg-black text-white rounded-xl text-sm px-5 flex items-center'>
دسته بندی
</div>
</div>
<div className='mt-6 flex justify-between items-end'>
<div className='flex gap-4'>
<div className='size-14 bg-red-50 rounded-2xl'></div>
<div>
<h2 className='text-xl font-bold'>
دی منو
</h2>
<div className='mt-1'>
<h6 className='text-sm'>
داناک
</h6>
</div>
</div>
</div>
<div className='flex gap-1.5 text-sm items-center'>
<div>جزییات</div>
<ArrowLeft
size={20}
color='white'
/>
</div>
</div>
</div>
</div>
</SwiperSlide>
<SwiperSlide className='xl:max-w-[45%] max-w-[90%]'>
<div className='rounded-4xl overflow-hidden relative'>
<Image
src='https://burgeraddict.fr/wp-content/uploads/2024/09/MSG-Smash-Burger-FT-RECIPE0124-d9682401f3554ef683e24311abdf342b.jpg'
alt='product'
width={1080}
height={1080}
className='w-full h-[400px] object-cover'
/>
<div className='absolute bottom-0 left-0 w-full modalGlass3 h-[150px] rounded-b-3xl text-white p-4'>
<div className='flex justify-between items-center'>
<h6 className='text-xs'>
منو دیجیتال رستوران
</h6>
<div className='h-8 bg-black text-white rounded-xl text-sm px-5 flex items-center'>
دسته بندی
</div>
</div>
<div className='mt-6 flex justify-between items-end'>
<div className='flex gap-4'>
<div className='size-14 bg-red-50 rounded-2xl'></div>
<div>
<h2 className='text-xl font-bold'>
دی منو
</h2>
<div className='mt-1'>
<h6 className='text-sm'>
داناک
</h6>
</div>
</div>
</div>
<div className='flex gap-1.5 text-sm items-center'>
<div>جزییات</div>
<ArrowLeft
size={20}
color='white'
/>
</div>
</div>
</div>
</div>
</SwiperSlide>
</Swiper>
</div>
<DanakSuggestedService />
<DanakServices />
</div>
)
}
export default Products
+24
View File
@@ -0,0 +1,24 @@
import { useQuery } from "@tanstack/react-query";
import * as api from "../service/ProductService";
export const useGetServicesByCategory = (categoryId?: string) =>
useQuery({
queryKey: ["services", categoryId],
queryFn: () => api.getServicesByCategory(categoryId),
});
export const servicesQueryOptions = {
queryKey: ["services", ""],
queryFn: () => api.getServicesByCategory(undefined),
};
export const useGetCategories = () =>
useQuery({
queryKey: ["service-categories"],
queryFn: () => api.getCategoriesPublic(),
});
export const categoriesQueryOptions = {
queryKey: ["service-categories"],
queryFn: () => api.getCategoriesPublic(),
};
+14 -168
View File
@@ -1,172 +1,18 @@
'use client'
import { ArrowLeft } from 'iconsax-react'
import Image from 'next/image'
import { FC } from 'react'
import { Swiper, SwiperSlide } from 'swiper/react'
import DanakSuggestedService from '../home/DanakSuggestedService'
import DanakServices from '../home/DanakServices'
const Products: FC = () => {
import { NextPage } from 'next'
import { HydrationBoundary } from '@tanstack/react-query'
import { dehydrate } from '@tanstack/react-query'
import { QueryClient } from '@tanstack/react-query'
import { categoriesQueryOptions, servicesQueryOptions } from './hooks/useProductData'
import Products from './Products'
const ProductsPage: NextPage = async () => {
const queryClient = new QueryClient()
await queryClient.prefetchQuery(servicesQueryOptions)
await queryClient.prefetchQuery(categoriesQueryOptions)
return (
<div className='max-w-maxWidth mx-auto'>
<div className='flex justify-between mt-20 items-center'>
<h1 className='text-2xl font-bold'>
محصولات
</h1>
<div className='max-w-[320px] text-sm leading-6 hidden xl:block text-center xl:text-right'>
لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است
</div>
</div>
<div className='mt-20'>
<Swiper
className='w-full'
spaceBetween={15}
slidesPerView={'auto'}
>
<SwiperSlide className='xl:max-w-[45%] max-w-[90%]'>
<div className='rounded-4xl overflow-hidden relative'>
<Image
src='https://burgeraddict.fr/wp-content/uploads/2024/09/MSG-Smash-Burger-FT-RECIPE0124-d9682401f3554ef683e24311abdf342b.jpg'
alt='product'
width={1080}
height={1080}
className='w-full h-[400px] object-cover'
/>
<div className='absolute bottom-0 left-0 w-full modalGlass3 h-[150px] rounded-b-3xl text-white p-4'>
<div className='flex justify-between items-center'>
<h6 className='text-xs'>
منو دیجیتال رستوران
</h6>
<div className='h-8 bg-black text-white rounded-xl text-sm px-5 flex items-center'>
دسته بندی
</div>
</div>
<div className='mt-6 flex justify-between items-end'>
<div className='flex gap-4'>
<div className='size-14 bg-red-50 rounded-2xl'></div>
<div>
<h2 className='text-xl font-bold'>
دی منو
</h2>
<div className='mt-1'>
<h6 className='text-sm'>
داناک
</h6>
</div>
</div>
</div>
<div className='flex gap-1.5 text-sm items-center'>
<div>جزییات</div>
<ArrowLeft
size={20}
color='white'
/>
</div>
</div>
</div>
</div>
</SwiperSlide>
<SwiperSlide className='xl:max-w-[45%] max-w-[90%]'>
<div className='rounded-4xl overflow-hidden relative'>
<Image
src='https://burgeraddict.fr/wp-content/uploads/2024/09/MSG-Smash-Burger-FT-RECIPE0124-d9682401f3554ef683e24311abdf342b.jpg'
alt='product'
width={1080}
height={1080}
className='w-full h-[400px] object-cover'
/>
<div className='absolute bottom-0 left-0 w-full modalGlass3 h-[150px] rounded-b-3xl text-white p-4'>
<div className='flex justify-between items-center'>
<h6 className='text-xs'>
منو دیجیتال رستوران
</h6>
<div className='h-8 bg-black text-white rounded-xl text-sm px-5 flex items-center'>
دسته بندی
</div>
</div>
<div className='mt-6 flex justify-between items-end'>
<div className='flex gap-4'>
<div className='size-14 bg-red-50 rounded-2xl'></div>
<div>
<h2 className='text-xl font-bold'>
دی منو
</h2>
<div className='mt-1'>
<h6 className='text-sm'>
داناک
</h6>
</div>
</div>
</div>
<div className='flex gap-1.5 text-sm items-center'>
<div>جزییات</div>
<ArrowLeft
size={20}
color='white'
/>
</div>
</div>
</div>
</div>
</SwiperSlide>
<SwiperSlide className='xl:max-w-[45%] max-w-[90%]'>
<div className='rounded-4xl overflow-hidden relative'>
<Image
src='https://burgeraddict.fr/wp-content/uploads/2024/09/MSG-Smash-Burger-FT-RECIPE0124-d9682401f3554ef683e24311abdf342b.jpg'
alt='product'
width={1080}
height={1080}
className='w-full h-[400px] object-cover'
/>
<div className='absolute bottom-0 left-0 w-full modalGlass3 h-[150px] rounded-b-3xl text-white p-4'>
<div className='flex justify-between items-center'>
<h6 className='text-xs'>
منو دیجیتال رستوران
</h6>
<div className='h-8 bg-black text-white rounded-xl text-sm px-5 flex items-center'>
دسته بندی
</div>
</div>
<div className='mt-6 flex justify-between items-end'>
<div className='flex gap-4'>
<div className='size-14 bg-red-50 rounded-2xl'></div>
<div>
<h2 className='text-xl font-bold'>
دی منو
</h2>
<div className='mt-1'>
<h6 className='text-sm'>
داناک
</h6>
</div>
</div>
</div>
<div className='flex gap-1.5 text-sm items-center'>
<div>جزییات</div>
<ArrowLeft
size={20}
color='white'
/>
</div>
</div>
</div>
</div>
</SwiperSlide>
</Swiper>
</div>
<DanakSuggestedService />
<DanakServices />
</div>
<HydrationBoundary state={dehydrate(queryClient)}>
<Products />
</HydrationBoundary>
)
}
export default Products
export default ProductsPage
@@ -0,0 +1,20 @@
import axios from "@/config/axios";
import { CategoryResponse, ServiceResponse } from "../types/ProductTypes";
export const getServicesByCategory = async (categoryId?: string) => {
let query = ``;
if (categoryId) {
query = `?categoryId=${categoryId}`;
}
const { data } = await axios.get<ServiceResponse>(
`/danak-services/public${query}`
);
return data;
};
export const getCategoriesPublic = async () => {
const { data } = await axios.get<CategoryResponse>(
`/danak-services/categories/public`
);
return data;
};
+23
View File
@@ -0,0 +1,23 @@
import { DanakSuggestService } from "@/app/home/types/HomeTypes";
import { ApiResponse } from "@/shared/types/SharedTypes";
export type ServiceResponse = ApiResponse<{
services: DanakSuggestService[];
nextPage: boolean;
}>;
export type CategoryResponse = ApiResponse<{
categories: ServiceCategoryType[];
}>;
export type ServiceCategoryType = {
id: string;
createdAt: string;
updatedAt: string;
title: string;
icon: string;
isActive: boolean;
order: number;
parentId: string | null;
deletedAt: string | null;
};