call back and service item skeleton
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
VITE_TOKEN_NAME = 'dsc_token'
|
VITE_TOKEN_NAME = 'dsc_token'
|
||||||
VITE_REFRESH_TOKEN_NAME = 'dsc_refresh_token'
|
VITE_REFRESH_TOKEN_NAME = 'dsc_refresh_token'
|
||||||
VITE_BASE_URL = 'https://api.danakcorp.com'
|
VITE_BASE_URL = 'https://api.danakcorp.com'
|
||||||
# VITE_BASE_URL = 'http://192.168.0.223:3500'
|
# VITE_BASE_URL = 'http://192.168.1.124:4000'
|
||||||
+1
-1
@@ -32,7 +32,7 @@ export const Pages = {
|
|||||||
},
|
},
|
||||||
setting: "/setting",
|
setting: "/setting",
|
||||||
wallet: "/wallet",
|
wallet: "/wallet",
|
||||||
callback: "/wallet/callback/",
|
callback: "/payment",
|
||||||
profile: "/profile",
|
profile: "/profile",
|
||||||
discounts: "/discounts",
|
discounts: "/discounts",
|
||||||
financial: "/financial",
|
financial: "/financial",
|
||||||
|
|||||||
+7
-2
@@ -382,7 +382,8 @@
|
|||||||
"username_save_success": "نام کاربری با موفقیت ذخیره شد",
|
"username_save_success": "نام کاربری با موفقیت ذخیره شد",
|
||||||
"image_uploaded_successfully": "تصویر با موفقیت آپلود شد",
|
"image_uploaded_successfully": "تصویر با موفقیت آپلود شد",
|
||||||
"confrim_email": "تایید ایمیل",
|
"confrim_email": "تایید ایمیل",
|
||||||
"confrim": "تایید صورتحساب "
|
"confrim": "تایید صورتحساب ",
|
||||||
|
"link_email": "یک لینک برای تایید ایمیل برای شما ارسال شد."
|
||||||
},
|
},
|
||||||
"email": "ایمیل",
|
"email": "ایمیل",
|
||||||
"save": "ذخیره",
|
"save": "ذخیره",
|
||||||
@@ -428,7 +429,11 @@
|
|||||||
"order_number": "شماره سفارش",
|
"order_number": "شماره سفارش",
|
||||||
"amount": "مبلغ پرداختی",
|
"amount": "مبلغ پرداختی",
|
||||||
"date": "تاریخ",
|
"date": "تاریخ",
|
||||||
"back": "بازگشت"
|
"back": "بازگشت",
|
||||||
|
"failed": "پرداخت ناموفق!",
|
||||||
|
"desc_failed": "متأسفیم! پرداخت شما انجام نشد. لطفاً دوباره تلاش کنید یا روش پرداخت دیگری انتخاب کنید.",
|
||||||
|
"pending": "وضعیت پرداخت نامشخص است!",
|
||||||
|
"desc_pending": "اگر مبلغی از حساب شما کسر شده ولی سفارش شما بعد از ۷۲ ساعت تأیید نشد، لطفاً با پشتیبانی تماس بگیرید."
|
||||||
},
|
},
|
||||||
"discount": {
|
"discount": {
|
||||||
"number": "شماره",
|
"number": "شماره",
|
||||||
|
|||||||
@@ -0,0 +1,102 @@
|
|||||||
|
import { CloseCircle, InfoCircle, TickCircle } from 'iconsax-react'
|
||||||
|
import { FC } from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import { NumberFormat } from '../../config/func'
|
||||||
|
import Button from '../../components/Button'
|
||||||
|
import { useSearchParams } from "react-router-dom";
|
||||||
|
import moment from 'moment-jalaali'
|
||||||
|
|
||||||
|
const CallBack: FC = () => {
|
||||||
|
|
||||||
|
const [searchParams] = useSearchParams();
|
||||||
|
const { t } = useTranslation('global')
|
||||||
|
|
||||||
|
const params = {
|
||||||
|
status: searchParams.get('status') as 'PENDING' | 'FAILED' | 'COMPLETED',
|
||||||
|
id: searchParams.get('id'),
|
||||||
|
date: searchParams.get('date'),
|
||||||
|
amount: searchParams.get('amount'),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='flex mt-10 flex-col justify-center items-center flex-1 h-full'>
|
||||||
|
{
|
||||||
|
params.status === 'COMPLETED' ?
|
||||||
|
<TickCircle
|
||||||
|
size={64}
|
||||||
|
color={'#00712D'}
|
||||||
|
/>
|
||||||
|
:
|
||||||
|
params.status === 'FAILED' ?
|
||||||
|
<CloseCircle
|
||||||
|
size={64}
|
||||||
|
color='#D52903'
|
||||||
|
/>
|
||||||
|
:
|
||||||
|
<InfoCircle
|
||||||
|
size={64}
|
||||||
|
color='#FFA800'
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
|
||||||
|
<div className='mt-7 text-xl'>
|
||||||
|
{
|
||||||
|
params.status === 'COMPLETED' ?
|
||||||
|
t('callback.title_success')
|
||||||
|
:
|
||||||
|
params.status === 'FAILED' ?
|
||||||
|
t('callback.failed')
|
||||||
|
:
|
||||||
|
t('callback.pending')
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='mt-7'>
|
||||||
|
{
|
||||||
|
params.status === 'COMPLETED' ?
|
||||||
|
t('callback.desc_success')
|
||||||
|
:
|
||||||
|
params.status === 'FAILED' ?
|
||||||
|
t('callback.desc_failed')
|
||||||
|
:
|
||||||
|
t('callback.desc_pending')
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='mt-16 xl:min-w-[560px] bg-[#FBFBFD] p-8 text-sm'>
|
||||||
|
<div className='flex justify-between'>
|
||||||
|
<div>
|
||||||
|
{t('callback.order_number')}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{params.id}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className='flex justify-between mt-6'>
|
||||||
|
<div>
|
||||||
|
{t('callback.amount')}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{NumberFormat(Number(params.amount)) + ' ' + t('toman')}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className='flex justify-between mt-6'>
|
||||||
|
<div>
|
||||||
|
{t('callback.date')}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{moment(params.date).format('jYYYY/jMM/jDD')}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
label={t('callback.back')}
|
||||||
|
className='xl:max-w-[560px] mt-8'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CallBack
|
||||||
@@ -26,7 +26,7 @@ const Email: FC<Props> = (props: Props) => {
|
|||||||
const handleShowModal = () => {
|
const handleShowModal = () => {
|
||||||
updateEmail.mutate({ email: email }, {
|
updateEmail.mutate({ email: email }, {
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
setShowModal(true)
|
toast.success(t('profile.link_email'))
|
||||||
},
|
},
|
||||||
onError: (error: ErrorType) => {
|
onError: (error: ErrorType) => {
|
||||||
toast.error(error.response?.data?.error.message[0])
|
toast.error(error.response?.data?.error.message[0])
|
||||||
|
|||||||
@@ -23,12 +23,12 @@ export const updateProfile = async (params: UpdateProfileType) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const updateEmail = async (params: UpdateEmailType) => {
|
export const updateEmail = async (params: UpdateEmailType) => {
|
||||||
const { data } = await axios.patch(`/users/update-email`, params);
|
const { data } = await axios.patch(`/users/change-email`, params);
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const updatePhone = async (params: UpdatePhoneType) => {
|
export const updatePhone = async (params: UpdatePhoneType) => {
|
||||||
const { data } = await axios.patch(`/users/update-phone`, params);
|
const { data } = await axios.patch(`/users/change-phone`, params);
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { MyServicesItem } from './types/ServiecTypes'
|
|||||||
import { useGetAds } from '../ads/hooks/useAdsData'
|
import { useGetAds } from '../ads/hooks/useAdsData'
|
||||||
import { AdsDisplayLocation } from '../ads/types/AdsTypes'
|
import { AdsDisplayLocation } from '../ads/types/AdsTypes'
|
||||||
import { Helmet } from 'react-helmet-async'
|
import { Helmet } from 'react-helmet-async'
|
||||||
|
import ServiceItemSkeleton from './components/ServiceItemSkeleton'
|
||||||
|
|
||||||
const MyServices: FC = () => {
|
const MyServices: FC = () => {
|
||||||
|
|
||||||
@@ -53,40 +54,42 @@ const MyServices: FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='flex items-stretch flex-wrap xl:gap-6 gap-4 xl:items-center mt-8'>
|
<div className='flex items-stretch flex-wrap xl:gap-6 gap-4 xl:items-center mt-8'>
|
||||||
|
|
||||||
{
|
{
|
||||||
getServices.data?.data?.subscriptions?.map((item: MyServicesItem) => {
|
getServices.isPending ?
|
||||||
return (
|
Array.from({ length: 4 }).map((_, index) => <ServiceItemSkeleton key={index} />)
|
||||||
<Link key={item.id} to={Pages.services.detail + item.id} className='flex-1 min-w-[40%] xl:min-w-[20%] bg-white rounded-3xl p-6'>
|
:
|
||||||
<ServiceSection
|
getServices.data?.data?.subscriptions?.map((item: MyServicesItem) => {
|
||||||
item={{
|
return (
|
||||||
author: item.plan.service.author,
|
<Link key={item.id} to={Pages.services.detail + item.id} className='flex-1 min-w-[40%] xl:min-w-[20%] bg-white rounded-3xl p-6'>
|
||||||
createDate: item.plan?.service?.createDate,
|
<ServiceSection
|
||||||
createdAt: item.createdAt,
|
item={{
|
||||||
description: item.plan?.service?.title,
|
author: item.plan.service.author,
|
||||||
icon: item.plan?.service.icon,
|
createDate: item.plan?.service?.createDate,
|
||||||
id: item.plan.service.id,
|
createdAt: item.createdAt,
|
||||||
isActive: item.plan.isActive,
|
description: item.plan?.service?.title,
|
||||||
isDanakSuggest: item.plan.service.isDanakSuggest,
|
icon: item.plan?.service.icon,
|
||||||
link: item.plan.service.link,
|
id: item.plan.service.id,
|
||||||
metaDescription: item.plan.service.metaDescription,
|
isActive: item.plan.isActive,
|
||||||
name: item.plan.service.name,
|
isDanakSuggest: item.plan.service.isDanakSuggest,
|
||||||
serviceLanguage: item.plan.service.serviceLanguage,
|
link: item.plan.service.link,
|
||||||
softwareLanguage: item.plan.service.softwareLanguage,
|
metaDescription: item.plan.service.metaDescription,
|
||||||
updatedAt: item.plan.service.updatedAt,
|
name: item.plan.service.name,
|
||||||
userCount: item.plan.service?.userCount
|
serviceLanguage: item.plan.service.serviceLanguage,
|
||||||
}}
|
softwareLanguage: item.plan.service.softwareLanguage,
|
||||||
/>
|
updatedAt: item.plan.service.updatedAt,
|
||||||
<div className='mt-6 flex gap-1 items-center'>
|
userCount: item.plan.service?.userCount
|
||||||
<StatusCircle
|
}}
|
||||||
color='#00BA4B'
|
|
||||||
/>
|
/>
|
||||||
<div className='text-xs text-description'>1 {t('service.active_menu')}</div>
|
<div className='mt-6 flex gap-1 items-center'>
|
||||||
</div>
|
<StatusCircle
|
||||||
|
color='#00BA4B'
|
||||||
|
/>
|
||||||
|
<div className='text-xs text-description'>1 {t('service.active_menu')}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</Link>
|
</Link>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import { FC } from 'react'
|
||||||
|
import Skeleton from 'react-loading-skeleton'
|
||||||
|
|
||||||
|
const ServiceItemSkeleton: FC = () => {
|
||||||
|
return (
|
||||||
|
<Skeleton
|
||||||
|
containerClassName='flex-1 min-w-[40%] xl:min-w-[20%]'
|
||||||
|
className='min-h-[128px] !rounded-3xl '
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ServiceItemSkeleton
|
||||||
@@ -11,5 +11,5 @@ export const updateSettings = async (params: UpdateSettingType) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const changePassword = async (params: ChangePasswordType) => {
|
export const changePassword = async (params: ChangePasswordType) => {
|
||||||
await axios.patch(`/auth/password`, params);
|
await axios.patch(`/auth/change-password`, params);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,61 +0,0 @@
|
|||||||
import { TickCircle } from 'iconsax-react'
|
|
||||||
import { FC } from 'react'
|
|
||||||
import { useTranslation } from 'react-i18next'
|
|
||||||
import { NumberFormat } from '../../config/func'
|
|
||||||
import Button from '../../components/Button'
|
|
||||||
|
|
||||||
const CallBack: FC = () => {
|
|
||||||
|
|
||||||
const { t } = useTranslation('global')
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className='flex mt-10 flex-col justify-center items-center flex-1 h-full'>
|
|
||||||
<TickCircle
|
|
||||||
size={64}
|
|
||||||
color='#00712D'
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div className='mt-7 text-xl'>
|
|
||||||
{t('callback.title_success')}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className='mt-7'>
|
|
||||||
{t('callback.desc_success')}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className='mt-16 xl:min-w-[560px] bg-[#FBFBFD] p-8 text-sm'>
|
|
||||||
<div className='flex justify-between'>
|
|
||||||
<div>
|
|
||||||
{t('callback.order_number')}
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
#1234
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className='flex justify-between mt-6'>
|
|
||||||
<div>
|
|
||||||
{t('callback.amount')}
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
{NumberFormat(200000) + ' ' + t('toman')}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className='flex justify-between mt-6'>
|
|
||||||
<div>
|
|
||||||
{t('callback.date')}
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
۲۹ بهمن ۱۴۰۳
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
label={t('callback.back')}
|
|
||||||
className='xl:max-w-[560px] mt-8'
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default CallBack
|
|
||||||
+2
-2
@@ -25,7 +25,7 @@ import TicketList from '../pages/ticket/TicketList'
|
|||||||
import CreateTicket from '../pages/ticket/CreateTicket'
|
import CreateTicket from '../pages/ticket/CreateTicket'
|
||||||
import TicketDetail from '../pages/ticket/Detail'
|
import TicketDetail from '../pages/ticket/Detail'
|
||||||
import Financial from '../pages/financial/Financial'
|
import Financial from '../pages/financial/Financial'
|
||||||
import CallBack from '../pages/wallet/CallBack'
|
import CallBack from '../pages/payment/CallBack'
|
||||||
import MyDiscountList from '../pages/discounts/List'
|
import MyDiscountList from '../pages/discounts/List'
|
||||||
import LearningDetail from '../pages/learning/Detail'
|
import LearningDetail from '../pages/learning/Detail'
|
||||||
import BuyService from '../pages/service/BuyService'
|
import BuyService from '../pages/service/BuyService'
|
||||||
@@ -57,7 +57,7 @@ const MainRouter: FC = () => {
|
|||||||
<Route path={Pages.learning.detail + ':id'} element={<LearningDetail />} />
|
<Route path={Pages.learning.detail + ':id'} element={<LearningDetail />} />
|
||||||
<Route path={Pages.setting} element={<Setting />} />
|
<Route path={Pages.setting} element={<Setting />} />
|
||||||
<Route path={Pages.wallet} element={<Wallet />} />
|
<Route path={Pages.wallet} element={<Wallet />} />
|
||||||
<Route path={Pages.callback + ':id'} element={<CallBack />} />
|
<Route path={Pages.callback} element={<CallBack />} />
|
||||||
<Route path={Pages.profile} element={<Profile />} />
|
<Route path={Pages.profile} element={<Profile />} />
|
||||||
<Route path={Pages.financial} element={<Financial />} />
|
<Route path={Pages.financial} element={<Financial />} />
|
||||||
<Route path={Pages.discounts} element={<MyDiscountList />} />
|
<Route path={Pages.discounts} element={<MyDiscountList />} />
|
||||||
|
|||||||
Reference in New Issue
Block a user