part 1
This commit is contained in:
@@ -12,6 +12,7 @@ import { IApiErrorRepsonse } from './types/error.types'
|
||||
import MainRouter from './router/Main'
|
||||
import AuthRouter from './router/Auth'
|
||||
import { Pages } from './config/Pages'
|
||||
import useConvertNumbers from './hooks/useConvertNumbers';
|
||||
|
||||
i18next.init({
|
||||
interpolation: { escapeValue: false },
|
||||
@@ -43,6 +44,7 @@ const queryClient = new QueryClient({
|
||||
const App: FC = () => {
|
||||
|
||||
// useNumberFont()
|
||||
useConvertNumbers()
|
||||
|
||||
const [isLogin, setIsLogin] = useState<'checking' | 'isLogin' | 'isNotLogin'>('checking')
|
||||
useEffect(() => {
|
||||
|
||||
@@ -27,7 +27,7 @@ const DefaulModal: FC<Props> = (props: Props) => {
|
||||
props.open && (
|
||||
<Fragment>
|
||||
<div style={{ maxWidth: props.width }} className='xl:justify-center xl:items-center items-end flex overflow-x-hidden overflow-y-auto fixed inset-0 z-[60] h-auto top-0 bottom-0 m-auto outline-none focus:outline-none xl:max-w-xl mx-auto'>
|
||||
<div className='relative xl:h-full h-[80%] bottom-0 left-0 flex xl:items-center sm:h-auto w-full xl:my-6 xl:p-2'>
|
||||
<div className='relative xl:h-full max-h-[80%] bottom-0 left-0 flex xl:items-center sm:h-auto w-full xl:my-6 xl:p-2'>
|
||||
<div className='border-0 h-auto p-5 lg:min-w-full overflow-y-auto rounded-3xl rounded-b-none xl:rounded-b-3xl relative flex flex-col w-full modalGlass2 outline-none focus:outline-none'>
|
||||
|
||||
|
||||
|
||||
@@ -27,9 +27,6 @@ const ServiceItem: FC<Props> = (props: Props) => {
|
||||
</div>
|
||||
<div className='mt-4 text-xs'>
|
||||
<div className='font-extralight'>{item.description} </div>
|
||||
<p dangerouslySetInnerHTML={{ __html: item.metaDescription }} className='text-description mt-2'>
|
||||
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className='mt-4'>
|
||||
@@ -38,7 +35,7 @@ const ServiceItem: FC<Props> = (props: Props) => {
|
||||
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>
|
||||
<div>{t('service.detail')}</div>
|
||||
<ArrowLeft color='black' size={16} />
|
||||
</div>
|
||||
</Button>
|
||||
|
||||
@@ -9,7 +9,7 @@ const ServiceSection: FC<Props> = (props: Props) => {
|
||||
const { item } = props
|
||||
return (
|
||||
<div className='flex gap-4'>
|
||||
<div className='size-10 rounded-xl'>
|
||||
<div className='size-10 min-w-10 rounded-xl'>
|
||||
<img src={item.icon} alt={item.name} className='w-full h-full' />
|
||||
</div>
|
||||
<div>
|
||||
|
||||
@@ -28,6 +28,7 @@ export const Pages = {
|
||||
learning: "/learning",
|
||||
setting: "/setting",
|
||||
wallet: "/wallet",
|
||||
callback: "/wallet/callback/",
|
||||
profile: "/profile",
|
||||
discounts: "/discounts",
|
||||
financial: "/financial",
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import { useEffect } from "react";
|
||||
|
||||
const toPersianDigits = (text: string): string => {
|
||||
return text.replace(/\d/g, (d) => "۰۱۲۳۴۵۶۷۸۹"[parseInt(d, 10)]);
|
||||
};
|
||||
|
||||
const convertNumbersInDOM = (node: Node): void => {
|
||||
if (node.nodeType === Node.TEXT_NODE) {
|
||||
node.nodeValue = toPersianDigits(node.nodeValue || "");
|
||||
} else if (node.nodeType === Node.ELEMENT_NODE) {
|
||||
node.childNodes.forEach(convertNumbersInDOM);
|
||||
}
|
||||
};
|
||||
|
||||
const useConvertNumbers = (): void => {
|
||||
useEffect(() => {
|
||||
const observer = new MutationObserver((mutations) => {
|
||||
mutations.forEach((mutation) => {
|
||||
if (mutation.type === "childList") {
|
||||
mutation.addedNodes.forEach(convertNumbersInDOM);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
observer.observe(document.body, { childList: true, subtree: true });
|
||||
|
||||
// اجرای اولیه روی کل صفحه
|
||||
convertNumbersInDOM(document.body);
|
||||
|
||||
return () => observer.disconnect();
|
||||
}, []);
|
||||
};
|
||||
|
||||
export default useConvertNumbers;
|
||||
+21
-5
@@ -39,7 +39,9 @@
|
||||
"login_with_otp": "ورود با رمز عبور یکبار مصرف",
|
||||
"otp_sent": "کد تایید ارسال شد",
|
||||
"mobile_number": "شماره موبایل",
|
||||
"enter_mobile_number": "شماره موبایل خود را وارد کنید"
|
||||
"enter_mobile_number": "شماره موبایل خود را وارد کنید",
|
||||
"try_again": "ارسال مجدد",
|
||||
"toast_resend_code": "کد جدیدی برای شما ارسال شد"
|
||||
},
|
||||
"errors": {
|
||||
"required": "این فیلد اجباری می باشد",
|
||||
@@ -85,13 +87,17 @@
|
||||
"add_access": "دسترسی سریع تازه ایجاد کنید.",
|
||||
"danak_learning": "آموزش داناک",
|
||||
"see_all": "دیدن همه",
|
||||
"create_new_access": "ایجاد دسترسی سریع"
|
||||
"create_new_access": "ایجاد دسترسی سریع",
|
||||
"receip": "صورتحساب پرداخت نشده دارید",
|
||||
"balance": "موجودی",
|
||||
"cannot_find_service": "سرویسی پیدا نشد",
|
||||
"not_active_service": "شما هنوز سرویس فعالی ندارید"
|
||||
},
|
||||
"all": "همه",
|
||||
"service": {
|
||||
"my_service": "سرویس های من",
|
||||
"search": "جستجو در سرویس ها",
|
||||
"active_menu": "منو فعال",
|
||||
"active_menu": "سرویس فعال",
|
||||
"selected_danak": "انتخاب داناک",
|
||||
"buy": "خرید",
|
||||
"other_services": "سایر سرویس ها",
|
||||
@@ -115,7 +121,8 @@
|
||||
"enter_title_comment": "عنوان نظر خود را وارد کنید",
|
||||
"your_comment": "نظر شما",
|
||||
"write_your_comment": "نظر خود را راجع به این سرویس بنویسید",
|
||||
"users_comments": "نظرات کاربران"
|
||||
"users_comments": "نظرات کاربران",
|
||||
"detail": "جزییات بیشتر"
|
||||
},
|
||||
"loading": "در حال بارگذاری",
|
||||
"footer": {
|
||||
@@ -173,6 +180,7 @@
|
||||
},
|
||||
"date": "تاریخ",
|
||||
"receip": {
|
||||
"receip": "صورتحساب",
|
||||
"receip_list": "لیست صورتحساب ها",
|
||||
"dont_pay": "پرداخت نشده",
|
||||
"dont_confrim": "تایید نشده",
|
||||
@@ -400,5 +408,13 @@
|
||||
},
|
||||
"man": "مرد",
|
||||
"woman": "زن",
|
||||
"success": "عملیات با موفقیت انجام شد"
|
||||
"success": "عملیات با موفقیت انجام شد",
|
||||
"callback": {
|
||||
"title_success": "پرداخت موفق بود!",
|
||||
"desc_success": "پرداخت شما با موفقیت انجام شد. از خرید شما متشکریم!",
|
||||
"order_number": "شماره سفارش",
|
||||
"amount": "مبلغ پرداختی",
|
||||
"date": "تاریخ",
|
||||
"back": "بازگشت"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import OTPInput from 'react-otp-input'
|
||||
import { useCountDown } from '../../../hooks/useCountDown'
|
||||
// import ArrowLeftIcon from '../../../assets/images/arrow-left.svg'
|
||||
import { Pages } from '../../../config/Pages'
|
||||
import { useOtpVerify } from '../hooks/useAuthData'
|
||||
import { useLoginWithOtp, useOtpVerify } from '../hooks/useAuthData'
|
||||
import { ErrorType } from '../../../helpers/types'
|
||||
import { toast } from 'react-toastify'
|
||||
|
||||
@@ -17,8 +17,9 @@ const LoginStep2: FC = () => {
|
||||
|
||||
const { t } = useTranslation('global')
|
||||
const { phone, setStepLogin } = useAuthStore()
|
||||
const { value } = useCountDown(2, true)
|
||||
const { value, reset } = useCountDown(2, true)
|
||||
const otpVerify = useOtpVerify()
|
||||
const loginWithOtp = useLoginWithOtp()
|
||||
|
||||
const formik = useFormik<OtpVerifyType>({
|
||||
initialValues: {
|
||||
@@ -69,6 +70,18 @@ const LoginStep2: FC = () => {
|
||||
return () => ac.abort();
|
||||
}, []);
|
||||
|
||||
const reSend = () => {
|
||||
loginWithOtp.mutate({ phone: phone }, {
|
||||
onSuccess: () => {
|
||||
reset()
|
||||
toast.success(t('auth.toast_resend_code'))
|
||||
},
|
||||
onError: (error: ErrorType) => {
|
||||
toast.error(error.response?.data?.error.message[0])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className='mt-5'>
|
||||
@@ -103,6 +116,7 @@ const LoginStep2: FC = () => {
|
||||
renderInput={(props) =>
|
||||
<input
|
||||
{...props}
|
||||
type='tel'
|
||||
autoComplete="one-time-code"
|
||||
inputMode="numeric"
|
||||
className='w-full h-[50px] flex-1 mx-2 bg-white border rounded-2.5' />
|
||||
@@ -116,10 +130,21 @@ const LoginStep2: FC = () => {
|
||||
}
|
||||
|
||||
<div className='flex mt-4 justify-end'>
|
||||
<div className='flex gap-1 text-description text-xs'>
|
||||
<div>{value}</div>
|
||||
<div>{t('auth.counter_otp')}</div>
|
||||
</div>
|
||||
{
|
||||
value !== '00:00' ?
|
||||
<div className='flex gap-1 text-description text-xs'>
|
||||
<div>{value}</div>
|
||||
<div>{t('auth.counter_otp')}</div>
|
||||
</div>
|
||||
:
|
||||
<div onClick={reSend} className='flex cursor-pointer gap-1 pl-2 text-black text-sm'>
|
||||
<div className=''>
|
||||
{t('auth.try_again')}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
}
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -26,7 +26,7 @@ const Financial: FC = () => {
|
||||
},
|
||||
{
|
||||
icon: <ProfileCircle color={activeTab === 'personal' ? 'black' : '#8C90A3'} size={22} />,
|
||||
label: t('financial.legal'),
|
||||
label: t('financial.personal'),
|
||||
value: 'personal'
|
||||
},
|
||||
]}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { ArrowLeft, Element3, Messages3, NotificationStatus, Teacher } from 'iconsax-react'
|
||||
import { ArrowLeft, Element3, Messages3, NotificationStatus, Receipt21 } from 'iconsax-react'
|
||||
import ItemDashboard from './components/ItemDashboard'
|
||||
import TitleLine from '../../components/TitleLine'
|
||||
import AccessbilityImage from '../../assets/images/accessbility.jpg'
|
||||
@@ -73,6 +73,14 @@ const Home: FC = () => {
|
||||
description={t('home.unread_messages')}
|
||||
/>
|
||||
|
||||
<ItemDashboard
|
||||
title={t('receip.receip')}
|
||||
icon={<Receipt21 size={20} color='black' />}
|
||||
color='#0047FF'
|
||||
count={4}
|
||||
description={t('home.receip')}
|
||||
/>
|
||||
|
||||
<ItemDashboard
|
||||
title={t('home.announcement')}
|
||||
icon={<NotificationStatus size={20} color='black' />}
|
||||
@@ -81,14 +89,6 @@ const Home: FC = () => {
|
||||
description={t('home.unread_announcement')}
|
||||
/>
|
||||
|
||||
<ItemDashboard
|
||||
title={t('home.learnings')}
|
||||
icon={<Teacher size={20} color='black' />}
|
||||
color='#0047FF'
|
||||
count={4}
|
||||
description={t('home.learning')}
|
||||
/>
|
||||
|
||||
</div>
|
||||
|
||||
<div className='w-full mt-8'>
|
||||
|
||||
@@ -3,13 +3,17 @@ import { FC, useState } from 'react'
|
||||
import DefaulModal from '../../../components/DefaulModal'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Input from '../../../components/Input'
|
||||
import Select from '../../../components/Select'
|
||||
import SwitchComponent from '../../../components/Switch'
|
||||
import { useGetMyServices } from '../../service/hooks/useServiceData'
|
||||
import { MyServicesItem } from '../../service/types/ServiecTypes'
|
||||
import PageLoading from '../../../components/PageLoading'
|
||||
|
||||
const BoxNewAccessbility: FC = () => {
|
||||
|
||||
const [search, setSearch] = useState<string>('')
|
||||
const [open, setOpen] = useState<boolean>(false)
|
||||
const { t } = useTranslation('global')
|
||||
const getMyservices = useGetMyServices(search)
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -63,80 +67,58 @@ const BoxNewAccessbility: FC = () => {
|
||||
<Input
|
||||
variant='search'
|
||||
className='bg-opacity-25 bg-white'
|
||||
onChangeSearchFinal={setSearch}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Select
|
||||
items={[
|
||||
{ value: '1', label: '1' },
|
||||
{ value: '2', label: '2' },
|
||||
{ value: '3', label: '3' },
|
||||
]}
|
||||
placeholder={t('all')}
|
||||
className='bg-opacity-25 bg-white w-[100px]'
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='mt-6 flex flex-wrap gap-6'>
|
||||
<div 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='size-10 rounded-xl bg-red-300'></div>
|
||||
<div>
|
||||
<div className='text-sm'>
|
||||
دی منو
|
||||
</div>
|
||||
<div className='text-xs text-description'>
|
||||
منو رستوران
|
||||
</div>
|
||||
</div>
|
||||
{
|
||||
getMyservices.isPending ?
|
||||
<div className='mt-6'>
|
||||
<PageLoading />
|
||||
</div>
|
||||
<div>
|
||||
<SwitchComponent
|
||||
active
|
||||
onChange={() => { }}
|
||||
/>
|
||||
:
|
||||
<div className='mt-6 flex flex-wrap gap-6'>
|
||||
{
|
||||
getMyservices.data?.data?.subscriptions?.length === 0 ?
|
||||
<div className='text-center w-full mt-4'>
|
||||
{
|
||||
search === '' ?
|
||||
t('home.not_active_service')
|
||||
:
|
||||
t('home.cannot_find_service')
|
||||
}
|
||||
</div>
|
||||
:
|
||||
getMyservices.data?.data?.subscriptions?.map((item: MyServicesItem) => {
|
||||
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'>
|
||||
<div className='size-10 rounded-xl overflow-hidden'>
|
||||
<img src={item.plan?.service?.icon} className='size-full' />
|
||||
</div>
|
||||
<div>
|
||||
<div className='text-sm'>
|
||||
{item.plan.service?.name}
|
||||
</div>
|
||||
<div className='text-xs text-description'>
|
||||
{item.plan.service?.title}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<SwitchComponent
|
||||
active
|
||||
onChange={() => { }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
}
|
||||
<div className='flex-1 min-w-[40%]'></div>
|
||||
</div>
|
||||
</div>
|
||||
<div 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='size-10 rounded-xl bg-blue-300'></div>
|
||||
<div>
|
||||
<div className='text-sm'>
|
||||
دی منو
|
||||
</div>
|
||||
<div className='text-xs text-description'>
|
||||
منو رستوران
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<SwitchComponent
|
||||
active
|
||||
onChange={() => { }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div 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='size-10 rounded-xl bg-green-300'></div>
|
||||
<div>
|
||||
<div className='text-sm'>
|
||||
دی منو
|
||||
</div>
|
||||
<div className='text-xs text-description'>
|
||||
منو رستوران
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<SwitchComponent
|
||||
active
|
||||
onChange={() => { }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className='flex-1 min-w-[40%]'></div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</DefaulModal>
|
||||
</>
|
||||
|
||||
@@ -210,7 +210,7 @@ const DetailService: FC = () => {
|
||||
|
||||
{
|
||||
getAdsLeft.isSuccess && getAdsLeft.data.data.ads[0] &&
|
||||
<a href={getAdsLeft.data?.data?.ads[0].link} target='_blank' className='bg-white w-sidebar h-fit hidden xl:block rounded-3xl overflow-hidden relative'>
|
||||
<a href={getAdsLeft.data?.data?.ads[0].link} target='_blank' className='bg-white w-sidebar h-fit hidden xl:block rounded-3xl overflow-hidden sticky top-4'>
|
||||
<img
|
||||
src={getAdsLeft.data.data.ads[0].imageUrl}
|
||||
className='w-full backdrop-blur-[100px] h-[550px] object-cover'
|
||||
|
||||
@@ -89,7 +89,7 @@ const MyServices: FC = () => {
|
||||
|
||||
{
|
||||
getAdsLeft.isSuccess && getAdsLeft.data.data.ads[0] &&
|
||||
<a href={getAdsLeft.data?.data?.ads[0].link} target='_blank' className='bg-white w-sidebar h-fit hidden xl:block rounded-3xl overflow-hidden relative'>
|
||||
<a href={getAdsLeft.data?.data?.ads[0].link} target='_blank' className='bg-white w-sidebar h-fit hidden xl:block rounded-3xl overflow-hidden sticky top-0'>
|
||||
<img
|
||||
src={getAdsLeft.data.data.ads[0].imageUrl}
|
||||
className='w-full backdrop-blur-[100px] h-[550px] object-cover'
|
||||
|
||||
@@ -96,7 +96,7 @@ const OtherServices: FC = () => {
|
||||
</div>
|
||||
{
|
||||
getAdsLeft.isSuccess && getAdsLeft.data.data.ads[0] &&
|
||||
<a href={getAdsLeft.data?.data?.ads[0].link} target='_blank' className='bg-white w-sidebar h-fit hidden xl:block rounded-3xl overflow-hidden relative'>
|
||||
<a href={getAdsLeft.data?.data?.ads[0].link} target='_blank' className='bg-white w-sidebar h-fit hidden xl:block rounded-3xl overflow-hidden sticky top-0'>
|
||||
<img
|
||||
src={getAdsLeft.data.data.ads[0].imageUrl}
|
||||
className='w-full backdrop-blur-[100px] h-[550px] object-cover'
|
||||
|
||||
@@ -68,7 +68,7 @@ const OtherServicesComponent: FC = () => {
|
||||
getServices.data?.data?.category?.danakServices?.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'>
|
||||
<div className='flex gap-2 justify-between items-center'>
|
||||
<ServiceSection
|
||||
item={item}
|
||||
/>
|
||||
@@ -77,7 +77,7 @@ const OtherServicesComponent: FC = () => {
|
||||
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>
|
||||
<div className='whitespace-nowrap'>{t('service.detail')}</div>
|
||||
<ArrowLeft color='black' size={16} />
|
||||
</div>
|
||||
</Button>
|
||||
|
||||
@@ -88,7 +88,6 @@ const TicketDetail: FC = () => {
|
||||
<div className='mt-4'>
|
||||
<div className='flex gap-1'>
|
||||
<div>{t('ticket.ticket_number')}</div>
|
||||
<div>12312</div>
|
||||
</div>
|
||||
{
|
||||
getMessages.isPending ?
|
||||
@@ -115,7 +114,7 @@ const TicketDetail: FC = () => {
|
||||
|
||||
{
|
||||
getMessages.data?.data?.messages.map((item: any) => {
|
||||
if (item?.author?.role?.name === 'user') {
|
||||
if (item?.author?.roles[0]?.name === 'user') {
|
||||
return (
|
||||
<div key={item.id} className='mt-6 xl:text-sm text-xs bg-[#F6F7FA] p-6 rounded-3xl rounded-tr-none xl:max-w-[70%] max-w-[90%]'>
|
||||
<div className='leading-7'>
|
||||
@@ -154,8 +153,8 @@ const TicketDetail: FC = () => {
|
||||
<div className='leading-7 mt-4'>
|
||||
{item.content}
|
||||
</div>
|
||||
<div className='flex justify-end mt-6 text-xs text-description'>
|
||||
10:07 | 1403/09/30
|
||||
<div className='flex dltr end mt-6 text-xs text-description'>
|
||||
{moment(item.createdAt).format('jYYYY-jMM-jDD HH:mm')}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import moment from 'moment-jalaali'
|
||||
const TicketList: FC = () => {
|
||||
|
||||
const { t } = useTranslation('global')
|
||||
const [activeTab, setActiveTab] = useState<'ANSWERED' | 'PENDING' | 'CLOSED'>('ANSWERED')
|
||||
const [activeTab, setActiveTab] = useState<'ANSWERED' | 'PENDING' | 'CLOSED'>('PENDING')
|
||||
const getTickets = useGetTickets(activeTab)
|
||||
|
||||
return (
|
||||
@@ -40,16 +40,16 @@ const TicketList: FC = () => {
|
||||
<Tabs
|
||||
active={activeTab}
|
||||
items={[
|
||||
{
|
||||
icon: <MessageTick color={activeTab === 'ANSWERED' ? 'black' : '#8C90A3'} size={22} />,
|
||||
label: t('ticket.answered'),
|
||||
value: 'ANSWERED'
|
||||
},
|
||||
{
|
||||
icon: <MessageTime color={activeTab === 'PENDING' ? 'black' : '#8C90A3'} size={22} />,
|
||||
label: t('ticket.checking'),
|
||||
value: 'PENDING'
|
||||
},
|
||||
{
|
||||
icon: <MessageTick color={activeTab === 'ANSWERED' ? 'black' : '#8C90A3'} size={22} />,
|
||||
label: t('ticket.answered'),
|
||||
value: 'ANSWERED'
|
||||
},
|
||||
// {
|
||||
// icon: <Message2 color={activeTab === 'wating' ? 'black' : '#8C90A3'} size={22} />,
|
||||
// label: t('ticket.wait_answered'),
|
||||
|
||||
@@ -56,7 +56,16 @@ export const useAddMessageTicket = (id: string) => {
|
||||
};
|
||||
|
||||
export const useCloseTicket = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: (id: string) => api.closeTicket(id),
|
||||
onSuccess: () => {
|
||||
queryClient.refetchQueries({
|
||||
queryKey: ["tickets"],
|
||||
});
|
||||
queryClient.refetchQueries({
|
||||
queryKey: ["ticket-messages"],
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
@@ -105,7 +105,7 @@ const TransactionList: FC = () => {
|
||||
<tr key={item.id}>
|
||||
<Td text={item.numericId + ''} />
|
||||
<Td text={item.description} />
|
||||
<Td text={item.amount} />
|
||||
<Td text={NumberFormat(+item.amount)} />
|
||||
<Td text={moment(item.createdAt).format('jYYYY-jMM-jDD')} />
|
||||
<Td text={''}>
|
||||
<Detail />
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
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
|
||||
@@ -11,6 +11,7 @@ import { DepositTransferType } from '../types/WalletTypes'
|
||||
import * as Yup from 'yup'
|
||||
import { useSingleUpload } from '../../ticket/hooks/useTicketData'
|
||||
import { toast } from 'react-toastify'
|
||||
import { ErrorType } from '../../../helpers/types'
|
||||
|
||||
const CardtoCard: FC = () => {
|
||||
|
||||
@@ -42,6 +43,9 @@ const CardtoCard: FC = () => {
|
||||
formik.resetForm()
|
||||
setFile(undefined)
|
||||
toast.success(t('wallet.successful_transfer'))
|
||||
},
|
||||
onError: (error: ErrorType) => {
|
||||
toast.error(error.response?.data?.error.message[0])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import { DepositTransferType } from '../types/WalletTypes'
|
||||
import * as Yup from 'yup'
|
||||
import { useSingleUpload } from '../../ticket/hooks/useTicketData'
|
||||
import { toast } from 'react-toastify'
|
||||
import { ErrorType } from '../../../helpers/types'
|
||||
|
||||
const CardtoCard: FC = () => {
|
||||
|
||||
@@ -43,6 +44,9 @@ const CardtoCard: FC = () => {
|
||||
setFile(undefined)
|
||||
toast.success(t('wallet.successful_transfer'))
|
||||
window.location.reload()
|
||||
},
|
||||
onError: (error: ErrorType) => {
|
||||
toast.error(error.response?.data?.error.message[0])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
+3
-1
@@ -25,6 +25,7 @@ import TicketList from '../pages/ticket/TicketList'
|
||||
import CreateTicket from '../pages/ticket/CreateTicket'
|
||||
import TicketDetail from '../pages/ticket/Detail'
|
||||
import Financial from '../pages/financial/Financial'
|
||||
import CallBack from '../pages/wallet/CallBack'
|
||||
|
||||
const MainRouter: FC = () => {
|
||||
return (
|
||||
@@ -33,7 +34,7 @@ const MainRouter: FC = () => {
|
||||
<Header />
|
||||
<div className='flex-1 xl:ms-[269px] mt-[68px] xl:mt-[81px]'>
|
||||
<div className={`overflow-auto w-[${window.innerWidth}] max-h-[calc(100vh-113px)]`}>
|
||||
<div>
|
||||
<div className='pb-16'>
|
||||
<Routes>
|
||||
<Route path={Pages.dashboard} element={<Home />} />
|
||||
<Route path={Pages.services.mine} element={<MyServices />} />
|
||||
@@ -51,6 +52,7 @@ const MainRouter: FC = () => {
|
||||
<Route path={Pages.learning} element={<LearningList />} />
|
||||
<Route path={Pages.setting} element={<Setting />} />
|
||||
<Route path={Pages.wallet} element={<Wallet />} />
|
||||
<Route path={Pages.callback + ':id'} element={<CallBack />} />
|
||||
<Route path={Pages.profile} element={<Profile />} />
|
||||
<Route path={Pages.financial} element={<Financial />} />
|
||||
</Routes>
|
||||
|
||||
+29
-8
@@ -10,6 +10,8 @@ import { useSharedStore } from './store/sharedStore'
|
||||
import { useGetProfile } from '../pages/profile/hooks/useProfileData'
|
||||
import { Popover, PopoverButton, PopoverPanel } from '@headlessui/react'
|
||||
import SideBarItem from './SideBarItem'
|
||||
import { useGetWalletBalance } from '../pages/wallet/hooks/useWalletData'
|
||||
import { NumberFormat } from '../config/func'
|
||||
|
||||
const Header: FC = () => {
|
||||
|
||||
@@ -18,6 +20,7 @@ const Header: FC = () => {
|
||||
const { t } = useTranslation('global')
|
||||
const { setOpenSidebar, openSidebar } = useSharedStore()
|
||||
const { data } = useGetProfile()
|
||||
const getWalletBalance = useGetWalletBalance()
|
||||
|
||||
useEffect(() => {
|
||||
setPopoverKey((prevKey) => prevKey + 1);
|
||||
@@ -40,9 +43,19 @@ const Header: FC = () => {
|
||||
<Link to={Pages.services.other}>
|
||||
<Element3 color='black' className='xl:size-[18px] size-[17px]' />
|
||||
</Link>
|
||||
<Link to={Pages.wallet}>
|
||||
<Link className='xl:hidden' to={Pages.wallet}>
|
||||
<Wallet className='xl:size-[18px] size-[17px]' color='black' />
|
||||
</Link>
|
||||
<Link className='hidden xl:block' to={Pages.wallet}>
|
||||
<div className='flex items-center h-8 pl-2 rounded-full bg-[#EEF0F7]'>
|
||||
<div className='px-3 text-xs'>
|
||||
{NumberFormat(getWalletBalance.data?.data?.balance) + ' ' + t('toman')}
|
||||
</div>
|
||||
<div className='size-[26px] flex justify-center items-center bg-white rounded-xl'>
|
||||
<Wallet className='xl:size-[18px] size-[17px]' color='black' />
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
<Notifications />
|
||||
{
|
||||
data && (
|
||||
@@ -80,13 +93,21 @@ const Header: FC = () => {
|
||||
</div>
|
||||
|
||||
<div className='pb-6 px-6 border-b border-[#EAEDF5]'>
|
||||
<SideBarItem
|
||||
icon={<Wallet size={20} color='black' />}
|
||||
title={t('header.wallet')}
|
||||
link={Pages.wallet}
|
||||
isActive
|
||||
isWithoutLine
|
||||
/>
|
||||
<div className='flex justify-between items-center'>
|
||||
<SideBarItem
|
||||
icon={<Wallet size={20} color='black' />}
|
||||
title={t('header.wallet')}
|
||||
link={Pages.wallet}
|
||||
isActive
|
||||
isWithoutLine
|
||||
/>
|
||||
<div className='flex items-center mt-4 h-8 pl-2 rounded-full bg-[#EEF0F7]'>
|
||||
<div className='ps-3'>{t('home.balance')}</div>
|
||||
<div className='px-3 text-xs'>
|
||||
{NumberFormat(getWalletBalance.data?.data?.balance) + ' ' + t('toman')}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<SideBarItem
|
||||
icon={<Card color={'black'} size={20} />}
|
||||
|
||||
Reference in New Issue
Block a user