learning
This commit is contained in:
@@ -31,7 +31,7 @@ const ServiceItem: FC<Props> = (props: Props) => {
|
||||
<div className='font-extralight'>{item.description} </div>
|
||||
</div>
|
||||
|
||||
<div className='mt-4'>
|
||||
<div className='mt-4 flex-1 flex items-end'>
|
||||
<Link to={Pages.services.detail + item.id}>
|
||||
<Button
|
||||
className='h-8 w-fit px-5 text-xs text-black bg-description bg-opacity-20 rounded-xl'
|
||||
|
||||
+4
-3
@@ -253,7 +253,8 @@
|
||||
"thank_pay_1": "ضمن تشکر از خرید شما",
|
||||
"thank_pay_2": "مبلغ این صورت حساب پرداخت شده است.",
|
||||
"discount_code": "کد تخفیف",
|
||||
"apply": "اعمال"
|
||||
"apply": "اعمال",
|
||||
"pending": "تایید نشده"
|
||||
},
|
||||
"confrim": {
|
||||
"subject": "حذف",
|
||||
@@ -309,9 +310,9 @@
|
||||
},
|
||||
"setting": {
|
||||
"setting": "تنظیمات",
|
||||
"notification": "پیام و ایمیل",
|
||||
"notification": "نوتیفیکیشن",
|
||||
"password": "رمز عبور",
|
||||
"setting_email_message": "تنظیمات ارسال پیام و ایمیل",
|
||||
"setting_email_message": "تنظیمات نوتیفیکیشن",
|
||||
"notification_announcement": "اعلانات و اطلاعیه ها",
|
||||
"email": "ایمیل",
|
||||
"sms": "پیامک",
|
||||
|
||||
@@ -111,7 +111,7 @@ const BoxNewAccessbility: FC = () => {
|
||||
</div>
|
||||
:
|
||||
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 (
|
||||
<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'>
|
||||
@@ -129,7 +129,7 @@ const BoxNewAccessbility: FC = () => {
|
||||
</div>
|
||||
<div>
|
||||
<ChangeQuikAccess
|
||||
id={item.plan?.service?.id}
|
||||
id={item?.id}
|
||||
value={active}
|
||||
onChange={handleQuikAccess}
|
||||
/>
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
import { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
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 { t } = useTranslation('global')
|
||||
const getLearnings = useGetLearnings('', 5)
|
||||
|
||||
return (
|
||||
<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>
|
||||
{t('home.danak_learning')}
|
||||
</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>
|
||||
<ArrowLeft size={12} color='black' />
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<div className='mt-7'>
|
||||
<div className='flex gap-3'>
|
||||
<div>
|
||||
<img src={CoverImage} alt='danak-learning-1' className='w-36 h-24 object-cover rounded-2xl' />
|
||||
</div>
|
||||
{
|
||||
getLearnings.data?.data?.learnings?.map((item: LearningItemType) => {
|
||||
return (
|
||||
<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='leading-5'>
|
||||
لورم ایپسوم متن ساختگی با تولید سادگی
|
||||
</div>
|
||||
<div className='flex gap-1 text-[11px] mt-3 text-description'>
|
||||
<div>دیزاین ,</div>
|
||||
<div>۲۴ دقیقه</div>
|
||||
</div>
|
||||
<div className='text-description text-[11px] mt-2'>
|
||||
آذر ماه 1403
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='text-xs'>
|
||||
<div className='leading-5'>
|
||||
{item.title}
|
||||
</div>
|
||||
<div className='flex gap-1 text-[11px] mt-3 text-description'>
|
||||
<div>{item.category.name} ,</div>
|
||||
<div>{item.videoDuration} دقیقه</div>
|
||||
</div>
|
||||
<div className='text-description text-[11px] mt-2'>
|
||||
{moment(item.createdAt).format('jYYYY/jMM/jDD')}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import * as api from "../service/LearningService";
|
||||
|
||||
export const useGetLearnings = (search: string) => {
|
||||
export const useGetLearnings = (search: string, limit?: number) => {
|
||||
return useQuery({
|
||||
queryKey: ["learnings", search],
|
||||
queryFn: () => api.getLearnings(search),
|
||||
queryKey: ["learnings", search, limit],
|
||||
queryFn: () => api.getLearnings(search, limit),
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import axios from "../../../config/axios";
|
||||
|
||||
export const getLearnings = async (search: string) => {
|
||||
const { data } = await axios.get(`/learnings?q=${search}`);
|
||||
export const getLearnings = async (search: string, limit?: number) => {
|
||||
const { data } = await axios.get(
|
||||
`/learnings?q=${search}&limit=${limit ? limit : 20}`
|
||||
);
|
||||
return data;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { FC, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
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 { Link } from 'react-router-dom'
|
||||
import { Pages } from '../../config/Pages'
|
||||
@@ -15,7 +15,7 @@ import { Helmet } from 'react-helmet-async'
|
||||
const ReceiptsList: FC = () => {
|
||||
|
||||
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)
|
||||
|
||||
return (
|
||||
@@ -34,19 +34,24 @@ const ReceiptsList: FC = () => {
|
||||
active={activeTab}
|
||||
items={[
|
||||
{
|
||||
icon: <WalletRemove color={activeTab === 'PENDING' ? 'black' : '#8C90A3'} size={22} />,
|
||||
label: t('receip.dont_pay'),
|
||||
icon: <WalletSearch color={activeTab === 'PENDING' ? 'black' : '#8C90A3'} size={22} />,
|
||||
label: t('receip.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} />,
|
||||
label: t('receip.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'),
|
||||
value: 'CANCELED'
|
||||
value: 'CANCELLED'
|
||||
},
|
||||
{
|
||||
icon: <FolderOpen color={activeTab === 'EXPIRED' ? 'black' : '#8C90A3'} size={22} />,
|
||||
@@ -54,7 +59,7 @@ const ReceiptsList: FC = () => {
|
||||
value: 'EXPIRED'
|
||||
},
|
||||
]}
|
||||
onChange={(value) => setActiveTab(value as "PENDING" | "PAID" | "CANCELED" | "EXPIRED")}
|
||||
onChange={(value) => setActiveTab(value as "PENDING" | "PAID" | "CANCELLED" | "EXPIRED")}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,13 +1,54 @@
|
||||
import { FC } from 'react'
|
||||
import { useParams } from 'react-router-dom'
|
||||
import { useGetDetailService } from './hooks/useServiceData'
|
||||
import { useNavigate, useParams } from 'react-router-dom'
|
||||
import { useBuyService, useGetDetailService } from './hooks/useServiceData'
|
||||
import HeaderBuy from './components/HeaderBuy'
|
||||
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 { t } = useTranslation('global')
|
||||
const navigate = useNavigate()
|
||||
const { serviceId, planId } = useParams()
|
||||
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 (
|
||||
<div className='w-full flex gap-6 mt-4'>
|
||||
@@ -17,6 +58,57 @@ const BuyService: FC = () => {
|
||||
:
|
||||
<div className='flex-1 max-w-full'>
|
||||
<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>
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
import { FC, useEffect, useState } from 'react'
|
||||
import Button from '../../../components/Button'
|
||||
import { ArrowRight, TickCircle } from 'iconsax-react'
|
||||
import { ArrowRight } from 'iconsax-react'
|
||||
import { ServiceDetailDataType } from '../types/ServiecTypes'
|
||||
import { NumberFormat } from '../../../config/func'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Input from '../../../components/Input'
|
||||
import Textarea from '../../../components/Textarea'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import { Pages } from '../../../config/Pages'
|
||||
|
||||
@@ -85,48 +82,7 @@ const HeaderBuy: FC<Props> = ({ data, planId }) => {
|
||||
</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>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -70,10 +70,10 @@ export type PlanItemType = {
|
||||
updatedAt: string;
|
||||
};
|
||||
|
||||
export type BuyServiceType = {
|
||||
planId: string;
|
||||
serviceId: string;
|
||||
};
|
||||
// export type BuyServiceType = {
|
||||
// planId: string;
|
||||
// serviceId: string;
|
||||
// };
|
||||
|
||||
export type MyServicesItem = {
|
||||
createdAt: string;
|
||||
@@ -110,3 +110,11 @@ export type MyServicesItem = {
|
||||
status: string;
|
||||
updatedAt: string;
|
||||
};
|
||||
|
||||
export type BuyServiceType = {
|
||||
planId: string;
|
||||
businessName: string;
|
||||
businessPhone: string;
|
||||
description: string;
|
||||
serviceId: string;
|
||||
};
|
||||
|
||||
@@ -52,7 +52,7 @@ const TransactionList: FC = () => {
|
||||
</div>
|
||||
<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' />
|
||||
<div>۳۰٪</div>
|
||||
<div>{getTransactions.data?.data?.totalDepositsPercentChange || 0}٪</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -71,7 +71,7 @@ const TransactionList: FC = () => {
|
||||
</div>
|
||||
<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' />
|
||||
<div>۳۰٪</div>
|
||||
<div>{getTransactions.data?.data?.totalWithdrawalsPercentChange || 0}٪</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -90,7 +90,7 @@ const TransactionList: FC = () => {
|
||||
</div>
|
||||
<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' />
|
||||
<div>۳۰٪</div>
|
||||
<div>{getTransactions.data?.data?.balancePercentChange || 0}٪</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user