This commit is contained in:
hamid zarghami
2025-02-26 14:57:11 +03:30
parent e3466bc951
commit 7a4e8ecaa5
29 changed files with 350 additions and 39 deletions
+1 -1
View File
@@ -5,7 +5,7 @@
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" /> <link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>Vite + React + TS</title> <title>کنسول داناک</title>
</head> </head>
<body> <body>
+48 -1
View File
@@ -20,6 +20,7 @@
"react": "^19.0.0", "react": "^19.0.0",
"react-dom": "^19.0.0", "react-dom": "^19.0.0",
"react-dropzone": "^14.3.5", "react-dropzone": "^14.3.5",
"react-helmet-async": "^2.0.5",
"react-i18next": "^15.2.0", "react-i18next": "^15.2.0",
"react-infinite-scroll-component": "^6.1.0", "react-infinite-scroll-component": "^6.1.0",
"react-loading": "^2.0.3", "react-loading": "^2.0.3",
@@ -39,6 +40,7 @@
"@types/moment-jalaali": "^0.7.9", "@types/moment-jalaali": "^0.7.9",
"@types/react": "^18.3.17", "@types/react": "^18.3.17",
"@types/react-dom": "^18.3.5", "@types/react-dom": "^18.3.5",
"@types/react-helmet": "^6.1.11",
"@types/swiper": "^5.4.3", "@types/swiper": "^5.4.3",
"@vitejs/plugin-react": "^4.3.4", "@vitejs/plugin-react": "^4.3.4",
"autoprefixer": "^10.4.20", "autoprefixer": "^10.4.20",
@@ -1881,6 +1883,16 @@
"@types/react": "^18.0.0" "@types/react": "^18.0.0"
} }
}, },
"node_modules/@types/react-helmet": {
"version": "6.1.11",
"resolved": "https://registry.npmjs.org/@types/react-helmet/-/react-helmet-6.1.11.tgz",
"integrity": "sha512-0QcdGLddTERotCXo3VFlUSWO3ztraw8nZ6e3zJSgG7apwV5xt+pJUS8ewPBqT4NYB1optGLprNQzFleIY84u/g==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/react": "*"
}
},
"node_modules/@types/swiper": { "node_modules/@types/swiper": {
"version": "5.4.3", "version": "5.4.3",
"resolved": "https://registry.npmjs.org/@types/swiper/-/swiper-5.4.3.tgz", "resolved": "https://registry.npmjs.org/@types/swiper/-/swiper-5.4.3.tgz",
@@ -3411,6 +3423,15 @@
"node": ">=0.8.19" "node": ">=0.8.19"
} }
}, },
"node_modules/invariant": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
"integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
"license": "MIT",
"dependencies": {
"loose-envify": "^1.0.0"
}
},
"node_modules/is-binary-path": { "node_modules/is-binary-path": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
@@ -4371,6 +4392,26 @@
"integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==", "integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/react-helmet-async": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-2.0.5.tgz",
"integrity": "sha512-rYUYHeus+i27MvFE+Jaa4WsyBKGkL6qVgbJvSBoX8mbsWoABJXdEO0bZyi0F6i+4f0NuIb8AvqPMj3iXFHkMwg==",
"license": "Apache-2.0",
"dependencies": {
"invariant": "^2.2.4",
"react-fast-compare": "^3.2.2",
"shallowequal": "^1.1.0"
},
"peerDependencies": {
"react": "^16.6.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/react-helmet-async/node_modules/react-fast-compare": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz",
"integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==",
"license": "MIT"
},
"node_modules/react-i18next": { "node_modules/react-i18next": {
"version": "15.2.0", "version": "15.2.0",
"resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-15.2.0.tgz", "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-15.2.0.tgz",
@@ -4683,6 +4724,12 @@
"integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==", "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/shallowequal": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz",
"integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==",
"license": "MIT"
},
"node_modules/shebang-command": { "node_modules/shebang-command": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@@ -5102,7 +5149,7 @@
"version": "5.6.3", "version": "5.6.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz",
"integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==",
"devOptional": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"bin": { "bin": {
"tsc": "bin/tsc", "tsc": "bin/tsc",
+2
View File
@@ -22,6 +22,7 @@
"react": "^19.0.0", "react": "^19.0.0",
"react-dom": "^19.0.0", "react-dom": "^19.0.0",
"react-dropzone": "^14.3.5", "react-dropzone": "^14.3.5",
"react-helmet-async": "^2.0.5",
"react-i18next": "^15.2.0", "react-i18next": "^15.2.0",
"react-infinite-scroll-component": "^6.1.0", "react-infinite-scroll-component": "^6.1.0",
"react-loading": "^2.0.3", "react-loading": "^2.0.3",
@@ -41,6 +42,7 @@
"@types/moment-jalaali": "^0.7.9", "@types/moment-jalaali": "^0.7.9",
"@types/react": "^18.3.17", "@types/react": "^18.3.17",
"@types/react-dom": "^18.3.5", "@types/react-dom": "^18.3.5",
"@types/react-helmet": "^6.1.11",
"@types/swiper": "^5.4.3", "@types/swiper": "^5.4.3",
"@vitejs/plugin-react": "^4.3.4", "@vitejs/plugin-react": "^4.3.4",
"autoprefixer": "^10.4.20", "autoprefixer": "^10.4.20",
+6
View File
@@ -14,6 +14,7 @@ import MainRouter from './router/Main'
import AuthRouter from './router/Auth' import AuthRouter from './router/Auth'
import { Pages } from './config/Pages' import { Pages } from './config/Pages'
import useConvertNumbers from './hooks/useConvertNumbers'; import useConvertNumbers from './hooks/useConvertNumbers';
import { Helmet, HelmetProvider } from 'react-helmet-async';
i18next.init({ i18next.init({
interpolation: { escapeValue: false }, interpolation: { escapeValue: false },
@@ -66,6 +67,10 @@ const App: FC = () => {
<BrowserRouter> <BrowserRouter>
<QueryClientProvider client={queryClient}> <QueryClientProvider client={queryClient}>
<I18nextProvider i18n={i18next}> <I18nextProvider i18n={i18next}>
<HelmetProvider>
<Helmet>
<title>کنسول داناک</title>
</Helmet>
{ {
isLogin === 'checking' ? isLogin === 'checking' ?
null null
@@ -75,6 +80,7 @@ const App: FC = () => {
: :
<AuthRouter /> <AuthRouter />
} }
</HelmetProvider>
<ToastContainer /> <ToastContainer />
</I18nextProvider> </I18nextProvider>
</QueryClientProvider> </QueryClientProvider>
+1
View File
@@ -9,6 +9,7 @@ export const Pages = {
mine: "/services", mine: "/services",
other: "/other-service", other: "/other-service",
detail: "/services/detail/", detail: "/services/detail/",
buy: "/other-service/buy/",
}, },
transactions: "/transactions", transactions: "/transactions",
receipts: { receipts: {
+8 -1
View File
@@ -122,7 +122,14 @@
"your_comment": "نظر شما", "your_comment": "نظر شما",
"write_your_comment": "نظر خود را راجع به این سرویس بنویسید", "write_your_comment": "نظر خود را راجع به این سرویس بنویسید",
"users_comments": "نظرات کاربران", "users_comments": "نظرات کاربران",
"detail": "جزییات بیشتر" "detail": "جزییات بیشتر",
"back": "بازگشت",
"info_business": "اطلاعات کسب و کار",
"enter_info_business": "اطلاعت کسب و کار خود را با دقت وارد کنید.",
"business_name": "نام کسب و کار",
"phone_business": "شماره تماس کسب و کار",
"short_description": "توضیح کوتاه",
"confrim_and_invoice": "تایید و صدور صورت حساب"
}, },
"loading": "در حال بارگذاری", "loading": "در حال بارگذاری",
"footer": { "footer": {
+2 -3
View File
@@ -1,11 +1,10 @@
import { StrictMode } from 'react' // import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client' import { createRoot } from 'react-dom/client'
import './assets/fonts/irancell/style.css' import './assets/fonts/irancell/style.css'
import './index.css' import './index.css'
import App from './App.tsx' import App from './App.tsx'
createRoot(document.getElementById('root')!).render( createRoot(document.getElementById('root')!).render(
<StrictMode>
<App /> <App />
</StrictMode>, ,
) )
+6
View File
@@ -5,6 +5,7 @@ import { useNavigate, useParams } from 'react-router-dom'
import { ArrowLeft2 } from 'iconsax-react' import { ArrowLeft2 } from 'iconsax-react'
import { useGetAnnoncementDetail } from './hooks/useAnnoncementData' import { useGetAnnoncementDetail } from './hooks/useAnnoncementData'
import PageLoading from '../../components/PageLoading' import PageLoading from '../../components/PageLoading'
import { Helmet } from 'react-helmet-async'
const AnnouncementDetail: FC = () => { const AnnouncementDetail: FC = () => {
@@ -15,6 +16,11 @@ const AnnouncementDetail: FC = () => {
return ( return (
<div className='mt-4'> <div className='mt-4'>
<Helmet>
<title>
داناک | اطلاعیه
</title>
</Helmet>
<div className='flex justify-between'> <div className='flex justify-between'>
<div> <div>
{t('announcement.text_announcement')} {t('announcement.text_announcement')}
+6
View File
@@ -9,6 +9,7 @@ import { useGetAnnoncement } from './hooks/useAnnoncementData'
import PageLoading from '../../components/PageLoading' import PageLoading from '../../components/PageLoading'
import { AnnoncementItemType } from './types/AnnoncementTypes' import { AnnoncementItemType } from './types/AnnoncementTypes'
import moment from 'moment-jalaali' import moment from 'moment-jalaali'
import { Helmet } from 'react-helmet-async'
const AnnouncementtList: FC = () => { const AnnouncementtList: FC = () => {
@@ -28,6 +29,11 @@ const AnnouncementtList: FC = () => {
return ( return (
<div className='mt-4 text-sm'> <div className='mt-4 text-sm'>
<Helmet>
<title>
داناک | اطلاعیه ها
</title>
</Helmet>
<div className='text-base'> <div className='text-base'>
{t('announcement.announcements')} {t('announcement.announcements')}
</div> </div>
+6
View File
@@ -12,6 +12,7 @@ import * as Yup from 'yup'
import { toast } from 'react-toastify' import { toast } from 'react-toastify'
import { ErrorType } from '../../helpers/types' import { ErrorType } from '../../helpers/types'
import { useCreateCriticisms } from './hooks/useCriticismsData' import { useCreateCriticisms } from './hooks/useCriticismsData'
import { Helmet } from 'react-helmet-async'
const AddCriticisms: FC = () => { const AddCriticisms: FC = () => {
@@ -66,6 +67,11 @@ const AddCriticisms: FC = () => {
return ( return (
<div className='mt-4 text-sm'> <div className='mt-4 text-sm'>
<Helmet>
<title>
داناک | انتقادات
</title>
</Helmet>
<div> <div>
{t('criticisms.criticisms')} {t('criticisms.criticisms')}
</div> </div>
+3 -1
View File
@@ -59,8 +59,10 @@ const Legal: FC = () => {
useEffect(() => { useEffect(() => {
if (getFinancialInfo.data?.data?.user?.legalUser) { if (getFinancialInfo.data?.data?.user?.legalUser || getFinancialInfo.data?.data?.user?.realUser) {
setIsReadOnly(true) setIsReadOnly(true)
}
if (getFinancialInfo.data?.data?.user?.legalUser) {
const data = getFinancialInfo.data.data?.user const data = getFinancialInfo.data.data?.user
formik.setValues({ formik.setValues({
address: data?.address.address, address: data?.address.address,
@@ -55,6 +55,10 @@ const Personal: FC = () => {
useEffect(() => { useEffect(() => {
if (getFinancialInfo.data?.data?.user?.legalUser || getFinancialInfo.data?.data?.user?.realUser) {
setIsReadOnly(true)
}
if (getFinancialInfo.data?.data?.user?.realUser) { if (getFinancialInfo.data?.data?.user?.realUser) {
const data = getFinancialInfo.data?.data?.user const data = getFinancialInfo.data?.data?.user
setIsReadOnly(true) setIsReadOnly(true)
+4
View File
@@ -14,6 +14,7 @@ import { useGetQuikAccess } from './hooks/useHomeData'
import { QuikAccessItemType } from './types/HomeTypes' import { QuikAccessItemType } from './types/HomeTypes'
import ServiceItem from '../../components/ServiceItem' import ServiceItem from '../../components/ServiceItem'
import PageLoading from '../../components/PageLoading' import PageLoading from '../../components/PageLoading'
import { Helmet } from 'react-helmet-async';
const Home: FC = () => { const Home: FC = () => {
@@ -24,6 +25,9 @@ const Home: FC = () => {
return ( return (
<Fragment> <Fragment>
<Helmet>
<title>داناک | پیشخوان</title>
</Helmet>
{ {
getAds.isPending || getQuikAccess.isPending ? getAds.isPending || getQuikAccess.isPending ?
<div className='mt-5'> <div className='mt-5'>
+6
View File
@@ -5,6 +5,7 @@ import PageLoading from '../../components/PageLoading'
import DanakLearning from '../home/components/DanakLearning' import DanakLearning from '../home/components/DanakLearning'
import { Calendar2, Clock, Element3 } from 'iconsax-react' import { Calendar2, Clock, Element3 } from 'iconsax-react'
import moment from 'moment-jalaali' import moment from 'moment-jalaali'
import { Helmet } from 'react-helmet-async'
const LearningDetail: FC = () => { const LearningDetail: FC = () => {
@@ -13,6 +14,11 @@ const LearningDetail: FC = () => {
return ( return (
<div className='mt-4'> <div className='mt-4'>
<Helmet>
<title>
داناک | آموزش
</title>
</Helmet>
{ {
getLearningDetail.isPending ? getLearningDetail.isPending ?
<PageLoading /> <PageLoading />
+6
View File
@@ -8,6 +8,7 @@ import { LearningItemType } from './types/LearningTypes'
import moment from 'moment-jalaali' import moment from 'moment-jalaali'
import { Link } from 'react-router-dom' import { Link } from 'react-router-dom'
import { Pages } from '../../config/Pages' import { Pages } from '../../config/Pages'
import { Helmet } from 'react-helmet-async'
const LearningList: FC = () => { const LearningList: FC = () => {
@@ -17,6 +18,11 @@ const LearningList: FC = () => {
return ( return (
<div className='w-full flex gap-6 mt-4'> <div className='w-full flex gap-6 mt-4'>
<Helmet>
<title>
داناک | آموزش
</title>
</Helmet>
<div className='flex-1'> <div className='flex-1'>
<div> <div>
{t('learning.learning')} {t('learning.learning')}
+6
View File
@@ -15,6 +15,7 @@ import Button from '../../components/Button'
import ApproveInvoice from './components/ApproveInvoice' import ApproveInvoice from './components/ApproveInvoice'
import PayInvoice from './components/PayInvoice' import PayInvoice from './components/PayInvoice'
import Input from '../../components/Input' import Input from '../../components/Input'
import { Helmet } from 'react-helmet-async'
const ReceiptsDetail: FC = () => { const ReceiptsDetail: FC = () => {
@@ -25,6 +26,11 @@ const ReceiptsDetail: FC = () => {
return ( return (
<div className='mt-4'> <div className='mt-4'>
<Helmet>
<title>
داناک | صورتحساب
</title>
</Helmet>
<div className='flex xl:flex-row flex-col gap-4 items-center'> <div className='flex xl:flex-row flex-col gap-4 items-center'>
<div className='flex gap-6 items-center'> <div className='flex gap-6 items-center'>
<div className='whitespace-nowrap'>{t('receip.detail_account')}</div> <div className='whitespace-nowrap'>{t('receip.detail_account')}</div>
+6
View File
@@ -10,6 +10,7 @@ import PageLoading from '../../components/PageLoading'
import { NumberFormat } from '../../config/func' import { NumberFormat } from '../../config/func'
import { ReceiptItemType } from './types/ReceiptTypes' import { ReceiptItemType } from './types/ReceiptTypes'
import moment from 'moment-jalaali' import moment from 'moment-jalaali'
import { Helmet } from 'react-helmet-async'
const ReceiptsList: FC = () => { const ReceiptsList: FC = () => {
@@ -19,6 +20,11 @@ const ReceiptsList: FC = () => {
return ( return (
<div className='mt-4'> <div className='mt-4'>
<Helmet>
<title>
داناک | صورتحساب ها
</title>
</Helmet>
<div> <div>
{t('receip.receip_list')} {t('receip.receip_list')}
</div> </div>
+27
View File
@@ -0,0 +1,27 @@
import { FC } from 'react'
import { useParams } from 'react-router-dom'
import { useGetDetailService } from './hooks/useServiceData'
import ServiceHeader from './components/ServiceHeader'
import HeaderBuy from './components/HeaderBuy'
import PageLoading from '../../components/PageLoading'
const BuyService: FC = () => {
const { serviceId, planId } = useParams()
const getDetailService = useGetDetailService(serviceId ? serviceId : '')
return (
<div className='w-full flex gap-6 mt-4'>
{
getDetailService.isPending ?
<PageLoading />
:
<div className='flex-1 max-w-full'>
<HeaderBuy planId={planId} data={getDetailService?.data?.data?.danakService} />
</div>
}
</div>
)
}
export default BuyService
-6
View File
@@ -111,12 +111,6 @@ const DetailService: FC = () => {
/> />
</div> </div>
<div className='mt-6'>
<Input
label={t('service.fullName')}
placeholder={t('service.enter_your_name')}
/>
</div>
<div className='mt-6'> <div className='mt-6'>
<Input <Input
label={t('service.title')} label={t('service.title')}
+6
View File
@@ -9,6 +9,7 @@ import { useGetMyServices } from './hooks/useServiceData'
import { MyServicesItem } from './types/ServiecTypes' 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'
const MyServices: FC = () => { const MyServices: FC = () => {
@@ -19,6 +20,11 @@ const MyServices: FC = () => {
return ( return (
<div className='w-full flex gap-6 mt-4'> <div className='w-full flex gap-6 mt-4'>
<Helmet>
<title>
داناک | سرویس های من
</title>
</Helmet>
<div className='flex-1'> <div className='flex-1'>
<div> <div>
{t('service.my_service')} {t('service.my_service')}
+5
View File
@@ -10,6 +10,7 @@ import ServiceItem from '../../components/ServiceItem'
import OtherServicesComponent from './components/OtherServices' import OtherServicesComponent from './components/OtherServices'
import { useGetAds } from '../ads/hooks/useAdsData' import { useGetAds } from '../ads/hooks/useAdsData'
import { AdsDisplayLocation, AdsItemType } from '../ads/types/AdsTypes' import { AdsDisplayLocation, AdsItemType } from '../ads/types/AdsTypes'
import { Helmet } from 'react-helmet-async'
const OtherServices: FC = () => { const OtherServices: FC = () => {
@@ -22,6 +23,10 @@ const OtherServices: FC = () => {
return ( return (
<div className='w-full flex gap-6'> <div className='w-full flex gap-6'>
<Helmet>
<title>داناک | لیست سرویس ها
</title>
</Helmet>
<div className='flex-1'> <div className='flex-1'>
{ {
getSuggestedServices.isPending || getAdsLeft.isPending ? getSuggestedServices.isPending || getAdsLeft.isPending ?
+134
View File
@@ -0,0 +1,134 @@
import { FC, useEffect, useState } from 'react'
import Button from '../../../components/Button'
import { ArrowRight, TickCircle } 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'
type Props = {
data: ServiceDetailDataType,
planId?: string
}
const HeaderBuy: FC<Props> = ({ data, planId }) => {
const navigate = useNavigate()
const { t } = useTranslation('global')
const [planSelected] = useState<string>(planId ? planId : '')
const [price, setPrice] = useState<number>(data?.subscriptionPlans[0]?.price)
const [finalPrice, setFinalPrice] = useState<number>(0)
const [planText, setPlanText] = useState<string>('')
useEffect(() => {
const plan = data?.subscriptionPlans.find((item) => item.id === planSelected)
setPlanText(plan.name)
setFinalPrice(plan.finalPrice)
setPrice(plan?.price)
}, [data])
return (
<div>
<div className='p-6 bg-white rounded-3xl'>
<div className='flex justify-between items-center'>
<div onClick={() => navigate(Pages.services.detail + data.id)} className='flex cursor-pointer gap-1.5'>
<ArrowRight className='size-4' color='#888888' />
<div className='text-xs text-description'>
{t('service.back')}
</div>
</div>
<div className='h-8 bg-[#EAEDF5] px-9 text-xs pt-[9px] rounded-full items-center'>
{planText}
</div>
</div>
<div className='w-full items-end mt-6 flex xl:flex-row flex-col xl:justify-between'>
<div className='flex xl:gap-8 gap-4'>
<div className='xl:size-[70px] size-[50px] rounded-xl'>
<img src={data?.icon} className='w-full h-full rounded-xl' />
</div>
<div>
<div>
{data?.name}
</div>
<div className='text-xs xl:mt-3 mt-1.5 text-[#4E505A]'>
{data?.title}
</div>
<p className='text-description mt-1 text-[11px]'>
{data?.description}
</p>
</div>
</div>
<div className='flex flex-col justify-between xl:items-end'>
<div className='flex gap-4 mt-5 xl:mt-0 items-center justify-between xl:justify-normal'>
<div className='text-xs whitespace-nowrap flex gap-1 items-center'>
<div className='flex gap-2'>
{
finalPrice !== price &&
<div className='line-through text-xs text-description'>
{NumberFormat(Number(price))}
</div>
}
<div>{NumberFormat(Number(finalPrice))}</div>
</div>
</div>
</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>
)
}
export default HeaderBuy
@@ -8,12 +8,12 @@ import { PlanItemType, ServiceDetailDataType } from '../types/ServiecTypes'
import { NumberFormat } from '../../../config/func' import { NumberFormat } from '../../../config/func'
import { useBuyService } from '../hooks/useServiceData' import { useBuyService } from '../hooks/useServiceData'
import { toast } from 'react-toastify' import { toast } from 'react-toastify'
import { useNavigate } from 'react-router-dom' import { Link, useNavigate } from 'react-router-dom'
import { Pages } from '../../../config/Pages' import { Pages } from '../../../config/Pages'
import { ErrorType } from '../../../helpers/types' import { ErrorType } from '../../../helpers/types'
type Props = { type Props = {
data: ServiceDetailDataType data: ServiceDetailDataType,
} }
const ServiceHeader: FC<Props> = (props: Props) => { const ServiceHeader: FC<Props> = (props: Props) => {
@@ -52,7 +52,7 @@ const ServiceHeader: FC<Props> = (props: Props) => {
return ( return (
<div className='w-full p-6 bg-white rounded-3xl flex xl:flex-row flex-col xl:justify-between'> <div className='w-full p-6 bg-white rounded-3xl flex xl:flex-row flex-col items-end xl:justify-between'>
<div className='flex xl:gap-8 gap-4'> <div className='flex xl:gap-8 gap-4'>
<div className='xl:size-[70px] size-[50px] rounded-xl'> <div className='xl:size-[70px] size-[50px] rounded-xl'>
<img src={data?.icon} className='w-full h-full rounded-xl' /> <img src={data?.icon} className='w-full h-full rounded-xl' />
@@ -95,9 +95,6 @@ const ServiceHeader: FC<Props> = (props: Props) => {
selected={planSelected} selected={planSelected}
/> />
</div> </div>
<div className='size-9 hidden bg-description rounded-xl xl:flex justify-center items-center'>
<img src={ShareIcon} className='w-4' />
</div>
<div className='flex gap-4 mt-5 xl:mt-0 items-center justify-between xl:justify-normal'> <div className='flex gap-4 mt-5 xl:mt-0 items-center justify-between xl:justify-normal'>
<div className='text-xs whitespace-nowrap flex gap-1 items-center'> <div className='text-xs whitespace-nowrap flex gap-1 items-center'>
<div className='flex gap-2'> <div className='flex gap-2'>
@@ -111,8 +108,9 @@ const ServiceHeader: FC<Props> = (props: Props) => {
</div> </div>
<span>{planText}</span> <span>{planText}</span>
</div> </div>
<Link to={Pages.services.buy + `${data.id}/${planSelected}`}>
<Button <Button
onClick={handleBuy} // onClick={handleBuy}
isLoading={buyService.isPending} isLoading={buyService.isPending}
className='bg-description xl:max-w-full max-w-[100px] text-xs h-8 bg-opacity-20 text-black px-4' className='bg-description xl:max-w-full max-w-[100px] text-xs h-8 bg-opacity-20 text-black px-4'
> >
@@ -123,6 +121,7 @@ const ServiceHeader: FC<Props> = (props: Props) => {
<ArrowLeft className='size-4' color='black' /> <ArrowLeft className='size-4' color='black' />
</div> </div>
</Button> </Button>
</Link>
</div> </div>
</div> </div>
</div> </div>
+6
View File
@@ -7,6 +7,7 @@ import PageLoading from '../../components/PageLoading'
import Email from './components/Email' import Email from './components/Email'
import Sms from './components/Sms' import Sms from './components/Sms'
import ChangePassword from './components/ChangePassword' import ChangePassword from './components/ChangePassword'
import { Helmet } from 'react-helmet-async'
const Setting: FC = () => { const Setting: FC = () => {
@@ -16,6 +17,11 @@ const Setting: FC = () => {
return ( return (
<div className='mt-4'> <div className='mt-4'>
<Helmet>
<title>
داناک| تنظیمات
</title>
</Helmet>
<div> <div>
{t('setting.setting')} {t('setting.setting')}
</div> </div>
+6
View File
@@ -18,6 +18,7 @@ import { useNavigate } from 'react-router-dom'
import { Pages } from '../../config/Pages' import { Pages } from '../../config/Pages'
import { useGetMyServices } from '../service/hooks/useServiceData' import { useGetMyServices } from '../service/hooks/useServiceData'
import { MyServicesItem } from '../service/types/ServiecTypes' import { MyServicesItem } from '../service/types/ServiecTypes'
import { Helmet } from 'react-helmet-async'
const CreateTicket: FC = () => { const CreateTicket: FC = () => {
@@ -81,6 +82,11 @@ const CreateTicket: FC = () => {
return ( return (
<div className='mt-4 pb-12'> <div className='mt-4 pb-12'>
<Helmet>
<title>
داناک | ایجاد تیکت
</title>
</Helmet>
<div> <div>
{t('ticket.new_ticket')} {t('ticket.new_ticket')}
</div> </div>
+6
View File
@@ -16,6 +16,7 @@ import { toast } from 'react-toastify'
import { ErrorType } from '../../helpers/types' import { ErrorType } from '../../helpers/types'
import { clx } from '../../helpers/utils' import { clx } from '../../helpers/utils'
import { Pages } from '../../config/Pages' import { Pages } from '../../config/Pages'
import { Helmet } from 'react-helmet-async'
const TicketDetail: FC = () => { const TicketDetail: FC = () => {
@@ -86,6 +87,11 @@ const TicketDetail: FC = () => {
return ( return (
<div className='mt-4'> <div className='mt-4'>
<Helmet>
<title>
داناک | تیکت
</title>
</Helmet>
<div className='flex gap-1'> <div className='flex gap-1'>
<div>{t('ticket.ticket_number')}</div> <div>{t('ticket.ticket_number')}</div>
</div> </div>
+6
View File
@@ -8,6 +8,7 @@ import { Link } from 'react-router-dom'
import { Pages } from '../../config/Pages' import { Pages } from '../../config/Pages'
import { useGetTickets } from './hooks/useTicketData' import { useGetTickets } from './hooks/useTicketData'
import moment from 'moment-jalaali' import moment from 'moment-jalaali'
import { Helmet } from 'react-helmet-async'
const TicketList: FC = () => { const TicketList: FC = () => {
@@ -17,6 +18,11 @@ const TicketList: FC = () => {
return ( return (
<div className='mt-4'> <div className='mt-4'>
<Helmet>
<title>
داناک | تیکت ها
</title>
</Helmet>
<div className='flex justify-between items-center'> <div className='flex justify-between items-center'>
<div> <div>
{t('ticket.tickets')} {t('ticket.tickets')}
+6
View File
@@ -10,6 +10,7 @@ import { NumberFormat } from '../../config/func'
import Pagination from '../../components/Pagination' import Pagination from '../../components/Pagination'
import BoxSekeleton from './skeleton/BoxSekeleton' import BoxSekeleton from './skeleton/BoxSekeleton'
import DefaultTableSkeleton from '../../components/DefaultTableSkeleton' import DefaultTableSkeleton from '../../components/DefaultTableSkeleton'
import { Helmet } from 'react-helmet-async'
const TransactionList: FC = () => { const TransactionList: FC = () => {
@@ -19,6 +20,11 @@ const TransactionList: FC = () => {
return ( return (
<div className='mt-4'> <div className='mt-4'>
<Helmet>
<title>
داناک | تراکنش ها
</title>
</Helmet>
<div> <div>
{t('transaction.transaction')} {t('transaction.transaction')}
</div> </div>
+2
View File
@@ -28,6 +28,7 @@ import Financial from '../pages/financial/Financial'
import CallBack from '../pages/wallet/CallBack' import CallBack from '../pages/wallet/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'
const MainRouter: FC = () => { const MainRouter: FC = () => {
return ( return (
@@ -42,6 +43,7 @@ const MainRouter: FC = () => {
<Route path={Pages.services.mine} element={<MyServices />} /> <Route path={Pages.services.mine} element={<MyServices />} />
<Route path={Pages.services.other} element={<OtherServices />} /> <Route path={Pages.services.other} element={<OtherServices />} />
<Route path={Pages.services.detail + ':id'} element={<DetailService />} /> <Route path={Pages.services.detail + ':id'} element={<DetailService />} />
<Route path={Pages.services.buy + ':serviceId/:planId'} element={<BuyService />} />
<Route path={Pages.ticket.list} element={<TicketList />} /> <Route path={Pages.ticket.list} element={<TicketList />} />
<Route path={Pages.ticket.create} element={<CreateTicket />} /> <Route path={Pages.ticket.create} element={<CreateTicket />} />
<Route path={Pages.ticket.detail + ':id'} element={<TicketDetail />} /> <Route path={Pages.ticket.detail + ':id'} element={<TicketDetail />} />