other services

This commit is contained in:
hamid zarghami
2025-02-12 13:17:19 +03:30
parent 71d3d5c393
commit 8b7abf5dd4
9 changed files with 316 additions and 199 deletions
+85 -181
View File
@@ -1,206 +1,110 @@
import { Carousel } from '@material-tailwind/react'
import { FC } from 'react'
import { FC, Fragment } from 'react'
import { useTranslation } from 'react-i18next'
import BannerImage from '../../assets/images/banner2.jpeg'
import RobotImage from '../../assets/images/robot.jpeg'
import { ArrowLeft } from 'iconsax-react'
import TitleLine from '../../components/TitleLine'
import Button from '../../components/Button'
import ServiceSection from '../../components/ServiceSection'
import { Link } from 'react-router-dom'
import { Pages } from '../../config/Pages'
import { useGetSuggestedServices } from './hooks/useServiceData'
import PageLoading from '../../components/PageLoading'
import { ItemServiceType } from './types/ServiecTypes'
import ServiceItem from '../../components/ServiceItem'
import OtherServicesComponent from './components/OtherServices'
const OtherServices: FC = () => {
const { t } = useTranslation('global')
const getSuggestedServices = useGetSuggestedServices()
return (
<div className='w-full flex gap-6'>
<div className='flex-1'>
<Carousel autoplay className="rounded-xl h-fit dltr" placeholder="" onPointerEnterCapture={() => { }} onPointerLeaveCapture={() => { }} >
<div className='relative drtl'>
<img src={BannerImage} className='w-full max-h-[300px] h-full object-cover rounded-3xl' />
<div className='absolute bg-black bg-opacity-20 size-full top-0 right-0 py-6 px-8 flex flex-col justify-between'>
<button className="px-8 w-fit py-1.5 bg-white bg-opacity-10 text-white text-sm rounded-full shadow-md ">
{t('home.new')}
</button>
{
getSuggestedServices.isPending ?
<PageLoading />
:
<Fragment>
<Carousel autoplay className="rounded-xl h-fit dltr" placeholder="" onPointerEnterCapture={() => { }} onPointerLeaveCapture={() => { }} >
<div className='relative drtl'>
<img src={BannerImage} className='w-full max-h-[300px] h-full object-cover rounded-3xl' />
<div className='absolute bg-black bg-opacity-20 size-full top-0 right-0 py-6 px-8 flex flex-col justify-between'>
<button className="px-8 w-fit py-1.5 bg-white bg-opacity-10 text-white text-sm rounded-full shadow-md ">
{t('home.new')}
</button>
<div className='max-w-[340px] font-medium text-white text-lg leading-10'>
<div>
سفارش نرمافزار اختصاصی: سرمایه‌ای برای آینده یا فقط هزینهای برای امروز؟
</div>
<div className='mt-3 text-border text-xs'>
۸ دقیقه مطالعه
</div>
<button className='mt-3 px-4 h-9 flex gap-2 items-center text-xs rounded-2.5 bg-black text-white'>
<div>
{t('home.study')}
</div>
<ArrowLeft size={14} color='white' />
</button>
</div>
</div>
</div>
<div className='relative drtl'>
<img src={BannerImage} className='w-full max-h-[300px] object-cover rounded-3xl' />
<div className='absolute bg-black bg-opacity-20 size-full top-0 right-0 py-6 px-8 flex flex-col justify-between'>
<button className="px-8 w-fit py-1.5 bg-white bg-opacity-10 text-white text-sm rounded-full shadow-md ">
{t('home.new')}
</button>
<div className='max-w-[340px] font-medium text-white text-lg leading-10'>
<div>
سفارش نرمافزار اختصاصی: سرمایه‌ای برای آینده یا فقط هزینهای برای امروز؟
</div>
<div className='mt-3 text-border text-xs'>
۸ دقیقه مطالعه
</div>
<button className='mt-3 px-4 h-9 flex gap-2 items-center text-xs rounded-2.5 bg-black text-white'>
<div>
{t('home.study')}
</div>
<ArrowLeft size={14} color='white' />
</button>
</div>
</div>
</div>
</Carousel>
<div className='w-full mt-8'>
<TitleLine title={t('service.selected_danak')} />
</div>
<div className='flex flex-wrap xl:gap-6 gap-4 items-center mt-8'>
<div className='flex-1 min-w-[45%] xl:min-w-[30%] bg-white rounded-3xl xl:p-6 p-4'>
<div className='flex gap-2 items-center'>
<div className='xl:size-[50px] size-10 bg-[#FF7B00] rounded-xl'></div>
<div className='xl:text-base text-sm'>
دی منو
</div>
</div>
<div className='mt-4 text-xs'>
<div className='font-extralight'>منو رستوران </div>
<p className='text-description mt-2'>
دی منو، راهی ساده و هوشمند برای مدیریت منو شما!
</p>
</div>
<div className='mt-4'>
<Link to={Pages.services.detail + '1'}>
<Button
className='h-8 w-fit px-5 text-xs text-black bg-description bg-opacity-20 rounded-xl'
>
<div className='flex gap-2'>
<div>{t('service.buy')}</div>
<ArrowLeft color='black' size={16} />
</div>
</Button>
</Link>
</div>
</div>
<div className='flex-1 min-w-[40%] xl:min-w-[30%] bg-white rounded-3xl xl:p-6 p-4'>
<div className='flex gap-2 items-center'>
<div className='xl:size-[50px] size-10 bg-[#FF7B00] rounded-xl'></div>
<div className='xl:text-base text-sm'>
دی منو
</div>
</div>
<div className='mt-4 text-xs'>
<div className='font-extralight'>منو رستوران </div>
<p className='text-description mt-2'>
دی منو، راهی ساده و هوشمند برای مدیریت منو شما!
</p>
</div>
<div className='mt-4'>
<Link to={Pages.services.detail + '1'}>
<Button
className='h-8 w-fit px-5 text-xs text-black bg-description bg-opacity-20 rounded-xl'
>
<div className='flex gap-2'>
<div>{t('service.buy')}</div>
<ArrowLeft color='black' size={16} />
</div>
</Button>
</Link>
</div>
</div>
<div className='flex-1 min-w-[40%] xl:min-w-[30%] bg-white rounded-3xl xl:p-6 p-4'>
<div className='flex gap-2 items-center'>
<div className='xl:size-[50px] size-10 bg-[#FF7B00] rounded-xl'></div>
<div className='xl:text-base text-sm'>
دی منو
</div>
</div>
<div className='mt-4 text-xs'>
<div className='font-extralight'>منو رستوران </div>
<p className='text-description mt-2'>
دی منو، راهی ساده و هوشمند برای مدیریت منو شما!
</p>
</div>
<div className='mt-4'>
<Link to={Pages.services.detail + '1'}>
<Button
className='h-8 w-fit px-5 text-xs text-black bg-description bg-opacity-20 rounded-xl'
>
<div className='flex gap-2'>
<div>{t('service.buy')}</div>
<ArrowLeft color='black' size={16} />
</div>
</Button>
</Link>
</div>
</div>
<div className='flex-1 min-w-[40%] xl:min-w-[30%] xl:p-6 p-4'></div>
</div>
<div className='w-full xl:-mt-7 mt-8'>
<TitleLine title={t('service.other_services')} />
</div>
<div className='flex w-full gap-6 items-center'>
<div className='flex w-full flex-wrap xl:gap-6 gap-4 items-center mt-8'>
<div className='flex-1 min-w-full xl:min-w-0 bg-white rounded-3xl py-4 px-6'>
<div className='flex justify-between items-center'>
<ServiceSection
/>
<Link to={Pages.services.detail + '1'}>
<Button
className='h-8 w-fit px-2 text-xs text-black bg-description bg-opacity-20 rounded-xl'
>
<div className='flex gap-2'>
<div>{t('service.buy')}</div>
<ArrowLeft color='black' size={16} />
<div className='max-w-[340px] font-medium text-white text-lg leading-10'>
<div>
سفارش نرمافزار اختصاصی: سرمایه‌ای برای آینده یا فقط هزینهای برای امروز؟
</div>
<div className='mt-3 text-border text-xs'>
۸ دقیقه مطالعه
</div>
<button className='mt-3 px-4 h-9 flex gap-2 items-center text-xs rounded-2.5 bg-black text-white'>
<div>
{t('home.study')}
</div>
<ArrowLeft size={14} color='white' />
</button>
</div>
</Button>
</Link>
</div>
</div>
</div>
<div className='relative drtl'>
<img src={BannerImage} className='w-full max-h-[300px] object-cover rounded-3xl' />
<div className='absolute bg-black bg-opacity-20 size-full top-0 right-0 py-6 px-8 flex flex-col justify-between'>
<button className="px-8 w-fit py-1.5 bg-white bg-opacity-10 text-white text-sm rounded-full shadow-md ">
{t('home.new')}
</button>
</div>
<div className='flex-1 min-w-full xl:min-w-0 bg-white rounded-3xl py-4 px-6'>
<div className='flex justify-between items-center'>
<ServiceSection
/>
<Link to={Pages.services.detail + '1'}>
<Button
className='h-8 w-fit px-2 text-xs text-black bg-description bg-opacity-20 rounded-xl'
>
<div className='flex gap-2'>
<div>{t('service.buy')}</div>
<ArrowLeft color='black' size={16} />
<div className='max-w-[340px] font-medium text-white text-lg leading-10'>
<div>
سفارش نرمافزار اختصاصی: سرمایه‌ای برای آینده یا فقط هزینهای برای امروز؟
</div>
<div className='mt-3 text-border text-xs'>
۸ دقیقه مطالعه
</div>
<button className='mt-3 px-4 h-9 flex gap-2 items-center text-xs rounded-2.5 bg-black text-white'>
<div>
{t('home.study')}
</div>
<ArrowLeft size={14} color='white' />
</button>
</div>
</Button>
</Link>
</div>
</div>
</Carousel>
<div className='w-full mt-8'>
<TitleLine title={t('service.selected_danak')} />
</div>
</div>
</div>
<div className='flex flex-wrap xl:gap-6 gap-4 items-center mt-8'>
{
getSuggestedServices.data?.data?.danakServices?.map((item: ItemServiceType) => (
<ServiceItem
key={item.id}
item={item}
/>
))
}
<div className='flex-1 min-w-[40%] xl:min-w-[30%] xl:p-6 p-4'></div>
</div>
</div>
<div className='h-16 xl:hidden'></div>
<OtherServicesComponent />
<div className='h-16 xl:hidden'></div>
</Fragment>
}
</div>
@@ -0,0 +1,93 @@
import { FC, useEffect, useState } from 'react'
import TitleLine from '../../../components/TitleLine'
import { useTranslation } from 'react-i18next'
import { useGetCategoriesPublic, useGetServicesByCategory } from '../hooks/useServiceData'
import { SwiperSlide, Swiper } from 'swiper/react'
import { CategoryItemType, ItemServiceType } from '../types/ServiecTypes'
import { clx } from '../../../helpers/utils'
import ServiceSection from '../../../components/ServiceSection'
import { Link } from 'react-router-dom'
import Button from '../../../components/Button'
import { ArrowLeft } from 'iconsax-react'
import { Pages } from '../../../config/Pages'
const OtherServicesComponent: FC = () => {
const { t } = useTranslation('global')
const [categoryId, setCategoryId] = useState<string>('')
const getCategory = useGetCategoriesPublic()
const getServices = useGetServicesByCategory(categoryId)
useEffect(() => {
if (getCategory.data) {
setCategoryId(getCategory?.data?.data?.categories[0]?.id)
}
}, [getCategory.data])
return (
<div>
<div className='w-full mt-8'>
<TitleLine title={t('service.other_services')} />
</div>
<div className='mt-6'>
<Swiper
className='w-full'
spaceBetween={15} // فاصله پیش‌فرض بین اسلایدها
slidesPerView='auto'
>
{
getCategory.data?.data?.categories?.map((item: CategoryItemType) => {
return (
<SwiperSlide key={item.id} className='max-w-[158px]'>
<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'
)}>
<img src={item.icon} className='size-5 rounded-full object-cover' />
<div className='text-sm'>{item.title}</div>
</div>
</SwiperSlide>
)
})
}
</Swiper>
</div>
<div className='flex w-full gap-6 items-center'>
<div className='flex w-full flex-wrap xl:gap-6 gap-4 items-center mt-8'>
{
getServices.data?.data?.category?.danakService?.map((item: ItemServiceType) => {
return (
<div className='flex-1 min-w-full xl:min-w-0 bg-white rounded-3xl py-4 px-6'>
<div className='flex justify-between items-center'>
<ServiceSection
item={item}
/>
<Link to={Pages.services.detail + item.id}>
<Button
className='h-8 w-fit px-2 text-xs text-black bg-description bg-opacity-20 rounded-xl'
>
<div className='flex gap-2'>
<div>{t('service.buy')}</div>
<ArrowLeft color='black' size={16} />
</div>
</Button>
</Link>
</div>
</div>
)
})
}
</div>
</div>
</div>
)
}
export default OtherServicesComponent
+24
View File
@@ -0,0 +1,24 @@
import { useQuery } from "@tanstack/react-query";
import * as api from "../service/ServiceService";
export const useGetSuggestedServices = () => {
return useQuery({
queryKey: ["suggested-services"],
queryFn: () => api.getServiceSuggestedDanak(),
});
};
export const useGetCategoriesPublic = () => {
return useQuery({
queryKey: ["categories-public"],
queryFn: () => api.getCategoriesPublic(),
});
};
export const useGetServicesByCategory = (categoryId: string) => {
return useQuery({
queryKey: ["services-category", categoryId],
queryFn: () => api.getServicesByCategory(categoryId),
enabled: !!categoryId,
});
};
@@ -0,0 +1,16 @@
import axios from "../../../config/axios";
export const getServiceSuggestedDanak = async () => {
const { data } = await axios.get(`/danak-services/suggested`);
return data;
};
export const getCategoriesPublic = async () => {
const { data } = await axios.get(`/danak-services/categories/public`);
return data;
};
export const getServicesByCategory = async (categoryId: string) => {
const { data } = await axios.get(
`/danak-services/categories/${categoryId}/services`
);
return data;
};
+27
View File
@@ -0,0 +1,27 @@
export type ItemServiceType = {
author: string;
createDate: string;
createdAt: string;
description: string;
icon: string;
id: string;
isActive: boolean;
isDanakSuggest: boolean;
link: string;
metaDescription: string;
name: string;
serviceLanguage: string;
softwareLanguage: string;
updatedAt: string;
userCount: number;
};
export type CategoryItemType = {
createdAt: string;
icon: string;
id: string;
isActive: boolean;
parentId: string | null;
title: string;
updatedAt: string;
};