This commit is contained in:
hamid zarghami
2025-02-28 19:26:32 +03:30
parent e8c26de5e1
commit d986365f56
11 changed files with 168 additions and 92 deletions
+1 -1
View File
@@ -31,7 +31,7 @@ const ServiceItem: FC<Props> = (props: Props) => {
<div className='font-extralight'>{item.description} </div> <div className='font-extralight'>{item.description} </div>
</div> </div>
<div className='mt-4'> <div className='mt-4 flex-1 flex items-end'>
<Link to={Pages.services.detail + item.id}> <Link to={Pages.services.detail + item.id}>
<Button <Button
className='h-8 w-fit px-5 text-xs text-black bg-description bg-opacity-20 rounded-xl' className='h-8 w-fit px-5 text-xs text-black bg-description bg-opacity-20 rounded-xl'
+4 -3
View File
@@ -253,7 +253,8 @@
"thank_pay_1": "ضمن تشکر از خرید شما", "thank_pay_1": "ضمن تشکر از خرید شما",
"thank_pay_2": "مبلغ این صورت حساب پرداخت شده است.", "thank_pay_2": "مبلغ این صورت حساب پرداخت شده است.",
"discount_code": "کد تخفیف", "discount_code": "کد تخفیف",
"apply": "اعمال" "apply": "اعمال",
"pending": "تایید نشده"
}, },
"confrim": { "confrim": {
"subject": "حذف", "subject": "حذف",
@@ -309,9 +310,9 @@
}, },
"setting": { "setting": {
"setting": "تنظیمات", "setting": "تنظیمات",
"notification": "پیام و ایمیل", "notification": "نوتیفیکیشن",
"password": "رمز عبور", "password": "رمز عبور",
"setting_email_message": "تنظیمات ارسال پیام و ایمیل", "setting_email_message": "تنظیمات نوتیفیکیشن",
"notification_announcement": "اعلانات و اطلاعیه ها", "notification_announcement": "اعلانات و اطلاعیه ها",
"email": "ایمیل", "email": "ایمیل",
"sms": "پیامک", "sms": "پیامک",
@@ -111,7 +111,7 @@ const BoxNewAccessbility: FC = () => {
</div> </div>
: :
getMyservices.data?.data?.subscriptions?.map((item: MyServicesItem) => { getMyservices.data?.data?.subscriptions?.map((item: MyServicesItem) => {
const active = getQuikAccess.data?.data?.quickAccesses?.find((o: any) => o.service?.id === item.plan?.service?.id) ? true : false const active = getQuikAccess.data?.data?.quickAccesses?.find((o: any) => o.userSubscription?.id === item?.id) ? true : false
return ( return (
<div key={item.id} className='flex-1 xl:min-w-[40%] min-w-full flex justify-between items-center border-b border-[#8C90A3] border-opacity-30 py-2'> <div key={item.id} className='flex-1 xl:min-w-[40%] min-w-full flex justify-between items-center border-b border-[#8C90A3] border-opacity-30 py-2'>
<div className='flex gap-4'> <div className='flex gap-4'>
@@ -129,7 +129,7 @@ const BoxNewAccessbility: FC = () => {
</div> </div>
<div> <div>
<ChangeQuikAccess <ChangeQuikAccess
id={item.plan?.service?.id} id={item?.id}
value={active} value={active}
onChange={handleQuikAccess} onChange={handleQuikAccess}
/> />
+23 -11
View File
@@ -1,11 +1,16 @@
import { FC } from 'react' import { FC } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { ArrowLeft } from 'iconsax-react' import { ArrowLeft } from 'iconsax-react'
import CoverImage from '../../../assets/images/banner.png' import { useGetLearnings } from '../../learning/hooks/useLearningData'
import { LearningItemType } from '../../learning/types/LearningTypes'
import moment from 'moment-jalaali'
import { Link } from 'react-router-dom'
import { Pages } from '../../../config/Pages'
const DanakLearning: FC = () => { const DanakLearning: FC = () => {
const { t } = useTranslation('global') const { t } = useTranslation('global')
const getLearnings = useGetLearnings('', 5)
return ( return (
<div className='bg-white w-sidebar text-xs hidden 2xl:block h-fit px-5 py-7 rounded-3xl'> <div className='bg-white w-sidebar text-xs hidden 2xl:block h-fit px-5 py-7 rounded-3xl'>
@@ -13,31 +18,38 @@ const DanakLearning: FC = () => {
<div> <div>
{t('home.danak_learning')} {t('home.danak_learning')}
</div> </div>
<div className='flex gap-2 items-center text-[10px]'> <Link to={Pages.learning.list} className='flex gap-2 items-center text-[10px]'>
<div>{t('home.see_all')}</div> <div>{t('home.see_all')}</div>
<ArrowLeft size={12} color='black' /> <ArrowLeft size={12} color='black' />
</div> </Link>
</div> </div>
<div className='mt-7'> <div className='mt-7'>
<div className='flex gap-3'> {
<div> getLearnings.data?.data?.learnings?.map((item: LearningItemType) => {
<img src={CoverImage} alt='danak-learning-1' className='w-36 h-24 object-cover rounded-2xl' /> return (
</div> <div key={item.id} className='flex gap-3'>
<Link to={Pages.learning.detail + item.id}>
<img src={item.coverUrl} alt='danak-learning-1' className='w-36 h-24 object-cover rounded-2xl' />
</Link>
<div className='text-xs'> <div className='text-xs'>
<div className='leading-5'> <div className='leading-5'>
لورم ایپسوم متن ساختگی با تولید سادگی {item.title}
</div> </div>
<div className='flex gap-1 text-[11px] mt-3 text-description'> <div className='flex gap-1 text-[11px] mt-3 text-description'>
<div>دیزاین ,</div> <div>{item.category.name} ,</div>
<div>۲۴ دقیقه</div> <div>{item.videoDuration} دقیقه</div>
</div> </div>
<div className='text-description text-[11px] mt-2'> <div className='text-description text-[11px] mt-2'>
آذر ماه 1403 {moment(item.createdAt).format('jYYYY/jMM/jDD')}
</div> </div>
</div> </div>
</div> </div>
)
}
)
}
</div> </div>
</div> </div>
) )
+3 -3
View File
@@ -1,10 +1,10 @@
import { useQuery } from "@tanstack/react-query"; import { useQuery } from "@tanstack/react-query";
import * as api from "../service/LearningService"; import * as api from "../service/LearningService";
export const useGetLearnings = (search: string) => { export const useGetLearnings = (search: string, limit?: number) => {
return useQuery({ return useQuery({
queryKey: ["learnings", search], queryKey: ["learnings", search, limit],
queryFn: () => api.getLearnings(search), queryFn: () => api.getLearnings(search, limit),
}); });
}; };
@@ -1,7 +1,9 @@
import axios from "../../../config/axios"; import axios from "../../../config/axios";
export const getLearnings = async (search: string) => { export const getLearnings = async (search: string, limit?: number) => {
const { data } = await axios.get(`/learnings?q=${search}`); const { data } = await axios.get(
`/learnings?q=${search}&limit=${limit ? limit : 20}`
);
return data; return data;
}; };
+12 -7
View File
@@ -1,7 +1,7 @@
import { FC, useState } from 'react' import { FC, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import Tabs from '../../components/Tabs' import Tabs from '../../components/Tabs'
import { CloseCircle, Eye, FolderOpen, WalletCheck, WalletRemove } from 'iconsax-react' import { CloseCircle, Eye, FolderOpen, WalletCheck, WalletRemove, WalletSearch } from 'iconsax-react'
import Td from '../../components/Td' import Td from '../../components/Td'
import { Link } from 'react-router-dom' import { Link } from 'react-router-dom'
import { Pages } from '../../config/Pages' import { Pages } from '../../config/Pages'
@@ -15,7 +15,7 @@ import { Helmet } from 'react-helmet-async'
const ReceiptsList: FC = () => { const ReceiptsList: FC = () => {
const { t } = useTranslation('global') const { t } = useTranslation('global')
const [activeTab, setActiveTab] = useState<"PENDING" | "PAID" | "CANCELED" | "EXPIRED">('PENDING') const [activeTab, setActiveTab] = useState<"PENDING" | "WAIT_PAYMENT" | "PAID" | "CANCELLED" | "EXPIRED">('PENDING')
const getInvoices = useGetInvoices(activeTab) const getInvoices = useGetInvoices(activeTab)
return ( return (
@@ -34,19 +34,24 @@ const ReceiptsList: FC = () => {
active={activeTab} active={activeTab}
items={[ items={[
{ {
icon: <WalletRemove color={activeTab === 'PENDING' ? 'black' : '#8C90A3'} size={22} />, icon: <WalletSearch color={activeTab === 'PENDING' ? 'black' : '#8C90A3'} size={22} />,
label: t('receip.dont_pay'), label: t('receip.pending'),
value: 'PENDING' value: 'PENDING'
}, },
{
icon: <WalletRemove color={activeTab === 'WAIT_PAYMENT' ? 'black' : '#8C90A3'} size={22} />,
label: t('receip.dont_pay'),
value: 'WAIT_PAYMENT'
},
{ {
icon: <WalletCheck color={activeTab === 'PAID' ? 'black' : '#8C90A3'} size={22} />, icon: <WalletCheck color={activeTab === 'PAID' ? 'black' : '#8C90A3'} size={22} />,
label: t('receip.paid'), label: t('receip.paid'),
value: 'PAID' value: 'PAID'
}, },
{ {
icon: <CloseCircle color={activeTab === 'CANCELED' ? 'black' : '#8C90A3'} size={22} />, icon: <CloseCircle color={activeTab === 'CANCELLED' ? 'black' : '#8C90A3'} size={22} />,
label: t('receip.canceled'), label: t('receip.canceled'),
value: 'CANCELED' value: 'CANCELLED'
}, },
{ {
icon: <FolderOpen color={activeTab === 'EXPIRED' ? 'black' : '#8C90A3'} size={22} />, icon: <FolderOpen color={activeTab === 'EXPIRED' ? 'black' : '#8C90A3'} size={22} />,
@@ -54,7 +59,7 @@ const ReceiptsList: FC = () => {
value: 'EXPIRED' value: 'EXPIRED'
}, },
]} ]}
onChange={(value) => setActiveTab(value as "PENDING" | "PAID" | "CANCELED" | "EXPIRED")} onChange={(value) => setActiveTab(value as "PENDING" | "PAID" | "CANCELLED" | "EXPIRED")}
/> />
</div> </div>
+94 -2
View File
@@ -1,13 +1,54 @@
import { FC } from 'react' import { FC } from 'react'
import { useParams } from 'react-router-dom' import { useNavigate, useParams } from 'react-router-dom'
import { useGetDetailService } from './hooks/useServiceData' import { useBuyService, useGetDetailService } from './hooks/useServiceData'
import HeaderBuy from './components/HeaderBuy' import HeaderBuy from './components/HeaderBuy'
import PageLoading from '../../components/PageLoading' import PageLoading from '../../components/PageLoading'
import Button from '../../components/Button'
import { TickCircle } from 'iconsax-react'
import Textarea from '../../components/Textarea'
import Input from '../../components/Input'
import { useTranslation } from 'react-i18next'
import { useFormik } from 'formik'
import * as Yup from 'yup'
import { BuyServiceType } from './types/ServiecTypes'
import { toast } from 'react-toastify'
import { ErrorType } from '../../helpers/types'
import { Pages } from '../../config/Pages'
const BuyService: FC = () => { const BuyService: FC = () => {
const { t } = useTranslation('global')
const navigate = useNavigate()
const { serviceId, planId } = useParams() const { serviceId, planId } = useParams()
const getDetailService = useGetDetailService(serviceId ? serviceId : '') const getDetailService = useGetDetailService(serviceId ? serviceId : '')
const buyService = useBuyService()
const formik = useFormik<BuyServiceType>({
initialValues: {
businessName: '',
businessPhone: '',
description: '',
planId: planId ? planId : '',
serviceId: serviceId ? serviceId : ''
},
validationSchema: Yup.object({
businessName: Yup.string().required(t('errors.required')),
businessPhone: Yup.string().required(t('errors.required')),
description: Yup.string().required(t('errors.required')),
planId: Yup.string().required(t('errors.required'))
}),
onSubmit: (values) => {
buyService.mutate(values, {
onSuccess: () => {
toast.success(t('success'))
navigate(Pages.services.mine)
},
onError: (error: ErrorType) => {
toast.error(error.response?.data?.error.message[0])
}
})
}
})
return ( return (
<div className='w-full flex gap-6 mt-4'> <div className='w-full flex gap-6 mt-4'>
@@ -17,6 +58,57 @@ const BuyService: FC = () => {
: :
<div className='flex-1 max-w-full'> <div className='flex-1 max-w-full'>
<HeaderBuy planId={planId} data={getDetailService?.data?.data?.danakService} /> <HeaderBuy planId={planId} data={getDetailService?.data?.data?.danakService} />
<div className='mt-8 p-6 bg-white rounded-3xl flex xl:gap-20 xl:flex-row flex-col gap-10'>
<div>
<div className='text-sm'>
{t('service.info_business')}
</div>
<div className='text-xs text-description mt-2'>
{t('service.enter_info_business')}
</div>
</div>
<div className='flex-1'>
<div>
<Input
label={t('service.business_name')}
{...formik.getFieldProps('businessName')}
error_text={formik.touched.businessName && formik.errors.businessName ? formik.errors.businessName : ''}
/>
</div>
<div className='mt-8'>
<Input
label={t('service.phone_business')}
{...formik.getFieldProps('businessPhone')}
error_text={formik.touched.businessPhone && formik.errors.businessPhone ? formik.errors.businessPhone : ''}
/>
</div>
<div className='mt-8'>
<Textarea
label={t('service.short_description')}
{...formik.getFieldProps('description')}
error_text={formik.touched.description && formik.errors.description ? formik.errors.description : ''}
/>
</div>
<div className='mt-8 flex justify-end'>
<Button
className='xl:w-fit px-5'
onClick={() => formik.handleSubmit()}
isLoading={buyService.isPending}
>
<div className='flex gap-2 items-center'>
<TickCircle size={20} color='white' />
<div>
{t('service.confrim_and_invoice')}
</div>
</div>
</Button>
</div>
</div>
</div>
</div> </div>
} }
</div> </div>
+1 -45
View File
@@ -1,11 +1,8 @@
import { FC, useEffect, useState } from 'react' import { FC, useEffect, useState } from 'react'
import Button from '../../../components/Button' import { ArrowRight } from 'iconsax-react'
import { ArrowRight, TickCircle } from 'iconsax-react'
import { ServiceDetailDataType } from '../types/ServiecTypes' import { ServiceDetailDataType } from '../types/ServiecTypes'
import { NumberFormat } from '../../../config/func' import { NumberFormat } from '../../../config/func'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import Input from '../../../components/Input'
import Textarea from '../../../components/Textarea'
import { useNavigate } from 'react-router-dom' import { useNavigate } from 'react-router-dom'
import { Pages } from '../../../config/Pages' import { Pages } from '../../../config/Pages'
@@ -85,48 +82,7 @@ const HeaderBuy: FC<Props> = ({ data, planId }) => {
</div> </div>
</div> </div>
<div className='mt-8 p-6 bg-white rounded-3xl flex xl:gap-20 xl:flex-row flex-col gap-10'>
<div>
<div className='text-sm'>
{t('service.info_business')}
</div>
<div className='text-xs text-description mt-2'>
{t('service.enter_info_business')}
</div>
</div>
<div className='flex-1'>
<div>
<Input
label={t('service.business_name')}
/>
</div>
<div className='mt-8'>
<Input
label={t('service.phone_business')}
/>
</div>
<div className='mt-8'>
<Textarea
label={t('service.short_description')}
/>
</div>
<div className='mt-8 flex justify-end'>
<Button
className='xl:w-fit px-5'
>
<div className='flex gap-2 items-center'>
<TickCircle size={20} color='white' />
<div>
{t('service.confrim_and_invoice')}
</div>
</div>
</Button>
</div>
</div>
</div>
</div> </div>
) )
} }
+12 -4
View File
@@ -70,10 +70,10 @@ export type PlanItemType = {
updatedAt: string; updatedAt: string;
}; };
export type BuyServiceType = { // export type BuyServiceType = {
planId: string; // planId: string;
serviceId: string; // serviceId: string;
}; // };
export type MyServicesItem = { export type MyServicesItem = {
createdAt: string; createdAt: string;
@@ -110,3 +110,11 @@ export type MyServicesItem = {
status: string; status: string;
updatedAt: string; updatedAt: string;
}; };
export type BuyServiceType = {
planId: string;
businessName: string;
businessPhone: string;
description: string;
serviceId: string;
};
+3 -3
View File
@@ -52,7 +52,7 @@ const TransactionList: FC = () => {
</div> </div>
<div className='flex gap gap-0.5 px-2 py-1 bg-green-100 rounded-lg text-[10px] text-success'> <div className='flex gap gap-0.5 px-2 py-1 bg-green-100 rounded-lg text-[10px] text-success'>
<ArrowRight size={12} color='#00BA4B' className='-rotate-45' /> <ArrowRight size={12} color='#00BA4B' className='-rotate-45' />
<div>۳۰٪</div> <div>{getTransactions.data?.data?.totalDepositsPercentChange || 0}٪</div>
</div> </div>
</div> </div>
</div> </div>
@@ -71,7 +71,7 @@ const TransactionList: FC = () => {
</div> </div>
<div className='flex gap gap-0.5 px-2 py-1 bg-green-100 rounded-lg text-[10px] text-success'> <div className='flex gap gap-0.5 px-2 py-1 bg-green-100 rounded-lg text-[10px] text-success'>
<ArrowRight size={12} color='#00BA4B' className='-rotate-45' /> <ArrowRight size={12} color='#00BA4B' className='-rotate-45' />
<div>۳۰٪</div> <div>{getTransactions.data?.data?.totalWithdrawalsPercentChange || 0}٪</div>
</div> </div>
</div> </div>
</div> </div>
@@ -90,7 +90,7 @@ const TransactionList: FC = () => {
</div> </div>
<div className='flex gap gap-0.5 px-2 py-1 text-red-400 rounded-lg text-[10px] bg-red-100'> <div className='flex gap gap-0.5 px-2 py-1 text-red-400 rounded-lg text-[10px] bg-red-100'>
<ArrowRight size={12} color='red' className='rotate-45' /> <ArrowRight size={12} color='red' className='rotate-45' />
<div>۳۰٪</div> <div>{getTransactions.data?.data?.balancePercentChange || 0}٪</div>
</div> </div>
</div> </div>
</div> </div>