diff --git a/package-lock.json b/package-lock.json
index dbe6129..427c4b2 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11,6 +11,7 @@
"@headlessui/react": "^2.2.0",
"@material-tailwind/react": "^2.1.10",
"@tanstack/react-query": "^5.62.8",
+ "draft-js": "^0.11.7",
"formik": "^2.4.6",
"i18next": "^24.2.0",
"iconsax-react": "^0.0.8",
@@ -1852,6 +1853,18 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@types/node": {
+ "version": "22.10.7",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.7.tgz",
+ "integrity": "sha512-V09KvXxFiutGp6B7XkpaDXlNadZxrzajcY50EuoLIpQ6WWYCSvf19lVIazzfIzQvhUN2HjX12spLojTnhuKlGg==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "peer": true,
+ "dependencies": {
+ "undici-types": "~6.20.0"
+ }
+ },
"node_modules/@types/prop-types": {
"version": "15.7.14",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz",
@@ -2240,6 +2253,12 @@
"node": ">=10"
}
},
+ "node_modules/asap": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
+ "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==",
+ "license": "MIT"
+ },
"node_modules/attr-accept": {
"version": "2.2.5",
"resolved": "https://registry.npmjs.org/attr-accept/-/attr-accept-2.2.5.tgz",
@@ -2528,6 +2547,26 @@
"node": ">=18"
}
},
+ "node_modules/core-js": {
+ "version": "3.40.0",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.40.0.tgz",
+ "integrity": "sha512-7vsMc/Lty6AGnn7uFpYT56QesI5D2Y/UkgKounk87OP9Z2H9Z8kj6jzcSGAxFmUtDOS0ntK6lbQz+Nsa0Jj6mQ==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/core-js"
+ }
+ },
+ "node_modules/cross-fetch": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz",
+ "integrity": "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==",
+ "license": "MIT",
+ "dependencies": {
+ "node-fetch": "^2.7.0"
+ }
+ },
"node_modules/cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
@@ -2610,6 +2649,21 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/draft-js": {
+ "version": "0.11.7",
+ "resolved": "https://registry.npmjs.org/draft-js/-/draft-js-0.11.7.tgz",
+ "integrity": "sha512-ne7yFfN4sEL82QPQEn80xnADR8/Q6ALVworbC5UOSzOvjffmYfFsr3xSZtxbIirti14R7Y33EZC5rivpLgIbsg==",
+ "license": "MIT",
+ "dependencies": {
+ "fbjs": "^2.0.0",
+ "immutable": "~3.7.4",
+ "object-assign": "^4.1.1"
+ },
+ "peerDependencies": {
+ "react": ">=0.14.0",
+ "react-dom": ">=0.14.0"
+ }
+ },
"node_modules/eastasianwidth": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
@@ -2944,6 +2998,28 @@
"reusify": "^1.0.4"
}
},
+ "node_modules/fbjs": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-2.0.0.tgz",
+ "integrity": "sha512-8XA8ny9ifxrAWlyhAbexXcs3rRMtxWcs3M0lctLfB49jRDHiaxj+Mo0XxbwE7nKZYzgCFoq64FS+WFd4IycPPQ==",
+ "license": "MIT",
+ "dependencies": {
+ "core-js": "^3.6.4",
+ "cross-fetch": "^3.0.4",
+ "fbjs-css-vars": "^1.0.0",
+ "loose-envify": "^1.0.0",
+ "object-assign": "^4.1.0",
+ "promise": "^7.1.1",
+ "setimmediate": "^1.0.5",
+ "ua-parser-js": "^0.7.18"
+ }
+ },
+ "node_modules/fbjs-css-vars": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz",
+ "integrity": "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==",
+ "license": "MIT"
+ },
"node_modules/file-entry-cache": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
@@ -3325,7 +3401,10 @@
"version": "3.7.6",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-3.7.6.tgz",
"integrity": "sha512-AizQPcaofEtO11RZhPPHBOJRdo/20MKQF9mBLnVkBoyHi1/zXK8fzVdnEpSV9gxqtnh6Qomfp3F0xT5qP/vThw==",
+<<<<<<< HEAD
"dev": true,
+=======
+>>>>>>> add-discount-blog
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.8.0"
@@ -3740,6 +3819,26 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/node-fetch": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
+ "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
+ "license": "MIT",
+ "dependencies": {
+ "whatwg-url": "^5.0.0"
+ },
+ "engines": {
+ "node": "4.x || >=6.0.0"
+ },
+ "peerDependencies": {
+ "encoding": "^0.1.0"
+ },
+ "peerDependenciesMeta": {
+ "encoding": {
+ "optional": true
+ }
+ }
+ },
"node_modules/node-releases": {
"version": "2.0.19",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz",
@@ -4125,6 +4224,15 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/promise": {
+ "version": "7.3.1",
+ "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
+ "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
+ "license": "MIT",
+ "dependencies": {
+ "asap": "~2.0.3"
+ }
+ },
"node_modules/prop-types": {
"version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
@@ -4581,6 +4689,12 @@
"integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==",
"license": "MIT"
},
+ "node_modules/setimmediate": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
+ "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==",
+ "license": "MIT"
+ },
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@@ -4930,6 +5044,12 @@
"integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==",
"license": "MIT"
},
+ "node_modules/tr46": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
+ "license": "MIT"
+ },
"node_modules/ts-api-utils": {
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz",
@@ -5024,6 +5144,41 @@
"typescript": ">=4.8.4 <5.8.0"
}
},
+ "node_modules/ua-parser-js": {
+ "version": "0.7.40",
+ "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.40.tgz",
+ "integrity": "sha512-us1E3K+3jJppDBa3Tl0L3MOJiGhe1C6P0+nIvQAFYbxlMAx0h81eOwLmU57xgqToduDDPx3y5QsdjPfDu+FgOQ==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/ua-parser-js"
+ },
+ {
+ "type": "paypal",
+ "url": "https://paypal.me/faisalman"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/faisalman"
+ }
+ ],
+ "license": "MIT",
+ "bin": {
+ "ua-parser-js": "script/cli.js"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "6.20.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
+ "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "peer": true
+ },
"node_modules/update-browserslist-db": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz",
@@ -5153,6 +5308,22 @@
"node": ">=0.10.0"
}
},
+ "node_modules/webidl-conversions": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/whatwg-url": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+ "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
+ "license": "MIT",
+ "dependencies": {
+ "tr46": "~0.0.3",
+ "webidl-conversions": "^3.0.0"
+ }
+ },
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
diff --git a/package.json b/package.json
index 8510f6e..066e8a8 100644
--- a/package.json
+++ b/package.json
@@ -13,6 +13,7 @@
"@headlessui/react": "^2.2.0",
"@material-tailwind/react": "^2.1.10",
"@tanstack/react-query": "^5.62.8",
+ "draft-js": "^0.11.7",
"formik": "^2.4.6",
"i18next": "^24.2.0",
"iconsax-react": "^0.0.8",
diff --git a/src/App.tsx b/src/App.tsx
index 950f6f2..f69517b 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -12,7 +12,6 @@ import { IApiErrorRepsonse } from './types/error.types'
import MainRouter from './router/Main'
import AuthRouter from './router/Auth'
import { Pages } from './config/Pages'
-
i18next.init({
interpolation: { escapeValue: false },
lng: 'fa',
diff --git a/src/components/Editor.jsx b/src/components/Editor.jsx
new file mode 100644
index 0000000..de66f88
--- /dev/null
+++ b/src/components/Editor.jsx
@@ -0,0 +1,30 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import {Editor, EditorState} from 'draft-js';
+
+function MyEditor() {
+ const [editorState, setEditorState] = React.useState(
+ EditorState.createEmpty()
+ );
+
+ const editor = React.useRef(null);
+
+ function focusEditor() {
+ editor.current.focus();
+ }
+
+ React.useEffect(() => {
+ focusEditor()
+ }, []);
+
+ return (
+
+ setEditorState(editorState)}
+ />
+
+ );
+}
+export default MyEditor
\ No newline at end of file
diff --git a/src/config/Pages.ts b/src/config/Pages.ts
index 1700fb3..ac9dc15 100644
--- a/src/config/Pages.ts
+++ b/src/config/Pages.ts
@@ -45,6 +45,7 @@ export const Pages = {
},
discount: {
list: "/discounts/list",
+ create: "/discounts/create"
},
referralCode: {
list: "/referral-code/list",
@@ -54,9 +55,12 @@ export const Pages = {
},
ads: {
list: "/ads/list",
+ create: "/ads/create"
},
blog: {
list: "/blog/list",
+ create: "/blog/create",
+ category: "/blog/category"
},
messages: {
list: "/messages/list",
diff --git a/src/index.css b/src/index.css
index fb404d9..e9202e9 100644
--- a/src/index.css
+++ b/src/index.css
@@ -142,3 +142,6 @@ tbody tr {
.ql-editor {
@apply !text-right;
}
+.ql-toolbar:first-child {
+ display: none !important;
+}
diff --git a/src/langs/fa.json b/src/langs/fa.json
index f9c8255..dc3a02d 100644
--- a/src/langs/fa.json
+++ b/src/langs/fa.json
@@ -206,6 +206,92 @@
},
"status": "وضعیت",
"title": "عنوان",
+ "ads": {
+ "ads": "تبلیغات",
+ "upload": "آپلود",
+ "deactive": "غیرفعال",
+ "submit": "ثبت تبلیغ",
+ "upload_picture": "تصویر نمایش تبلیغ",
+ "to_upload_message": "تصویر مورد نظر را آپلود کنید",
+ "new_ads": "افزودن تبلیغ",
+ "location": "جایگاه",
+ "startDate": "تاریخ شروع نمایش",
+ "endDate": "تاریخ پایان نمایش",
+ "search": "جستجو",
+ "number": "شماره",
+ "title": "عنوان",
+ "date": "تاریخ",
+ "status": "وضعیت",
+ "enter_your_title": "عنوان تبلیغ را وارد کنید",
+ "link": "لینک",
+ "enter_your_link": "لینک تبلیغ را وارد کنید"
+ },
+ "discount": {
+ "list": "لیست تخفیفات",
+ "type": "نوع تخفیف",
+ "price": "مبلغ تخفیف",
+ "title": "عنوان کد",
+ "code": "کد تخفیف",
+ "enter_discount_description": "عنوان کد تخفیف را وارد کنید",
+ "add_new_discount": "افزودن تخفیف",
+ "auto_generate_code": "ساخت کد",
+ "price_or_percent": "درصد / مبلغ تخفیف",
+ "enter_price_or_percent": "درصد / مبلغ تخفیف را وارد کنید",
+ "service": "سرویس",
+ "status": "وضعیت",
+ "number": "شماره",
+ "startDate": "تاریخ شروع",
+ "endDate": "تاریخ پایان",
+ "service_status": "وضعیت سرویس",
+ "availabe_service": "سرویس هایی که شامل تخفیف میشوند",
+ "new_discount": "کد تخفیف جدید",
+ "submit": "ثبت تخفیف",
+ "discount_code": "کد تخفیف",
+ "direct_discount": "تخفیف مستقیم",
+ "fixed_amount": "مبلغ ثابت",
+ "percent": "درصد"
+ },
+ "blog": {
+ "blog": "بلاگ",
+ "category": "دسته بندی",
+ "new_blog": "افزودن بلاگ",
+ "blog_title": "عنوان بلاگ",
+ "blog_Summary": "خلاصه بلاگ",
+ "content": "محتوا",
+ "blog_status": "وضعیت بلاگ",
+ "featured_image": "تصویر شاخص",
+ "tags": "برچسب ها",
+ "tag_hint": "جدا کردن با کاما یا کلید Enter ",
+ "shareDate": "تاریخ انتشار",
+ "enter_your_title": "عنوان بلاگ را وارد کنید",
+ "add_blog": "افزودن بلاگ",
+ "blog_category": "دسته بندی بلاگ",
+ "add_category": "اضافه کردن دسته بندی",
+ "category_status": "وضعیت دسته بندی",
+ "category_title": "عنوان دسته بندی",
+ "parent_category": "دسته بندی مادر",
+ "price": "مبلغ تخفیف",
+ "title": "عنوان کد",
+ "code": "کد تخفیف",
+ "enter_discount_description": "عنوان کد تخفیف را وارد کنید",
+ "add_new_discount": "افزودن تخفیف",
+ "auto_generate_code": "ساخت کد",
+ "price_or_percent": "درصد / مبلغ تخفیف",
+ "enter_price_or_percent": "درصد / مبلغ تخفیف را وارد کنید",
+ "service": "سرویس",
+ "status": "وضعیت",
+ "number": "شماره",
+ "startDate": "تاریخ شروع",
+ "endDate": "تاریخ پایان",
+ "service_status": "وضعیت سرویس",
+ "availabe_service": "سرویس هایی که شامل تخفیف میشوند",
+ "new_discount": "کد تخفیف جدید",
+ "submit": "ثبت بلاگ",
+ "discount_code": "کد تخفیف",
+ "direct_discount": "تخفیف مستقیم",
+ "fixed_amount": "مبلغ ثابت",
+ "percent": "درصد"
+ },
"receip": {
"receips": "صورتحساب ها",
"receip_list": "لیست صورتحساب ها",
diff --git a/src/pages/ads/AdsList.tsx b/src/pages/ads/AdsList.tsx
new file mode 100644
index 0000000..b7a34ba
--- /dev/null
+++ b/src/pages/ads/AdsList.tsx
@@ -0,0 +1,127 @@
+import { FC } from 'react'
+import { useTranslation } from 'react-i18next'
+import Button from '../../components/Button'
+import { Add, Eye } from 'iconsax-react'
+import Td from '../../components/Td'
+import { Link } from 'react-router-dom'
+import { Pages } from '../../config/Pages'
+import SwitchComponent from '../../components/Switch'
+import DatePickerComponent from '../../components/DatePicker'
+import Select from '../../components/Select'
+import Input from '../../components/Input'
+const AddList: FC = () => {
+ const { t } = useTranslation('global')
+ return (
+
+
+
+ {t('ads.ads')}
+
+
+
+
+
+
+
+ {t('ads.new_ads')}
+
+
+
+
+
+
+
+
+
+ { }}
+ placeholder=''
+ defaulValue='1400-01-01'
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ { }}
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ { }}
+ />
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+export default AddList
\ No newline at end of file
diff --git a/src/pages/ads/CreateAds.tsx b/src/pages/ads/CreateAds.tsx
new file mode 100644
index 0000000..bc5b980
--- /dev/null
+++ b/src/pages/ads/CreateAds.tsx
@@ -0,0 +1,108 @@
+import { FC } from 'react'
+import { useTranslation } from 'react-i18next'
+import Input from '../../components/Input'
+import Button from '../../components/Button'
+import SwitchComponent from '../../components/Switch'
+import { TickCircle, TickSquare, Link2 } from 'iconsax-react'
+import DatePickerComponent from '../../components/DatePicker'
+import ImageUploader from './components/ImageUploader'
+const CreateAd: FC = () => {
+ const { t } = useTranslation('global')
+ return (
+
+
+
+ {t('ads.new_ads')}
+
+
+
+
+
+ {t('ads.submit')}
+
+
+
+
+
+
+
+
+
+
+ { }}
+ placeholder=''
+ defaulValue='1400-01-01'
+ />
+ { }}
+ placeholder=''
+ defaulValue='1400-01-01'
+ />
+
+
+
+
+
+
+
+
+
+ وضعیت تبلیغ
+
+
+
+ {t('ads.deactive')}
+
+
{ }}
+ />
+
+
+
{t('ads.location')}
+
+
+
+
+
+
+ لورم ایپسوم
+
+
+
+
+
+
+
+ لورم ایپسوم
+
+
+
+
+
+
+
+ لورم ایپسوم
+
+
+
+
+
+
+
+
+ )
+}
+
+export default CreateAd
\ No newline at end of file
diff --git a/src/pages/ads/components/ImageUploader.tsx b/src/pages/ads/components/ImageUploader.tsx
new file mode 100644
index 0000000..ad623e9
--- /dev/null
+++ b/src/pages/ads/components/ImageUploader.tsx
@@ -0,0 +1,49 @@
+
+import { FC, useCallback, useState } from 'react'
+import { useTranslation } from 'react-i18next'
+import { Image, DocumentUpload } from 'iconsax-react'
+import { useDropzone } from 'react-dropzone'
+
+
+
+const ImageUploader: FC = () => {
+ const { t } = useTranslation('global')
+ const [file, setFile] = useState()
+ const onDrop = useCallback((acceptedFiles: File[]) => {
+ setFile(acceptedFiles[0])
+ }, [])
+ const { getRootProps, getInputProps } = useDropzone({ onDrop })
+
+ return (
+ <>
+ {t('ads.upload_picture')}
+
+
+
+
+ {
+ file ?
+ file.name
+ :
+ t('ads.to_upload_message')
+
+ }
+
+
+
+
+
+ {t('ads.upload')}
+
+
+
+ >
+ )
+}
+export default ImageUploader
\ No newline at end of file
diff --git a/src/pages/blog/BlogCategory.tsx b/src/pages/blog/BlogCategory.tsx
new file mode 100644
index 0000000..5229686
--- /dev/null
+++ b/src/pages/blog/BlogCategory.tsx
@@ -0,0 +1,147 @@
+
+import { FC } from 'react'
+import { useTranslation } from 'react-i18next'
+import Select from '../../components/Select'
+import Input from '../../components/Input'
+import Td from '../../components/Td'
+import SwitchComponent from '../../components/Switch'
+import { TickSquare, More, TickCircle } from 'iconsax-react'
+import "quill/dist/quill.snow.css";
+import Button from '../../components/Button'
+const BlogCategory: FC = () => {
+ const { t } = useTranslation('global')
+ return (
+
+
+
+ {t('blog.blog_category')}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ { }}
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ { }}
+ />
+
+
+
+
+
+
+
+
+
+
+
+
{t('blog.add_category')}
+
+
+ {t('blog.category_status')}
+
+
+
+ {t('ads.deactive')}
+
+
{ }}
+ />
+
+
+
{t('blog.category_title')}
+
+
+
+
{t('blog.parent_category')}
+
+
+
+
+
+
+
+
+ {t('blog.submit')}
+
+
+
+
+
+
+ )
+}
+export default BlogCategory
\ No newline at end of file
diff --git a/src/pages/blog/BlogList.tsx b/src/pages/blog/BlogList.tsx
new file mode 100644
index 0000000..60e46c1
--- /dev/null
+++ b/src/pages/blog/BlogList.tsx
@@ -0,0 +1,147 @@
+import { FC } from 'react'
+import { useTranslation } from 'react-i18next'
+import Button from '../../components/Button'
+import { Add, Eye } from 'iconsax-react'
+import Td from '../../components/Td'
+import { Link } from 'react-router-dom'
+import { Pages } from '../../config/Pages'
+import SwitchComponent from '../../components/Switch'
+import DatePickerComponent from '../../components/DatePicker'
+import Select from '../../components/Select'
+import Input from '../../components/Input'
+const BlogList: FC = () => {
+ const { t } = useTranslation('global')
+ return (
+
+
+
+ {t('blog.blog')}
+
+
+
+
+
+
+
+ {t('blog.new_blog')}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ { }}
+ placeholder=''
+ defaulValue='1400-01-01'
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ { }}
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ { }}
+ />
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+export default BlogList
\ No newline at end of file
diff --git a/src/pages/blog/CreateBlog.tsx b/src/pages/blog/CreateBlog.tsx
new file mode 100644
index 0000000..0b2acba
--- /dev/null
+++ b/src/pages/blog/CreateBlog.tsx
@@ -0,0 +1,118 @@
+
+import { FC, useEffect } from 'react'
+import { useTranslation } from 'react-i18next'
+import Input from '../../components/Input'
+import Button from '../../components/Button'
+import SwitchComponent from '../../components/Switch'
+import { TickCircle, TickSquare } from 'iconsax-react'
+import ImageUploader from './components/ImageUploader'
+import "quill/dist/quill.snow.css";
+import Quill from 'quill';
+const CreateBlog: FC = () => {
+ const { t } = useTranslation('global')
+ useEffect(() => {
+ new Quill('#editor', {
+ theme: 'snow',
+ });
+ new Quill('#editor2', {
+ theme: 'snow',
+ });
+ }, []);
+ return (
+
+
+
+ {t('blog.add_blog')}
+
+
+
+
+
+ {t('blog.submit')}
+
+
+
+
+
+
+
+
+
+
+
{t('blog.blog_Summary')}
+
+
+
{t('blog.content')}
+
+
+
+
+
+
+
+
+ {t('blog.blog_status')}
+
+
+
+ {t('ads.deactive')}
+
+
{ }}
+ />
+
+
+
{t('blog.category')}
+
+
+
+
+
+
+ لورم ایپسوم
+
+
+
+
+
+
+
+ لورم ایپسوم
+
+
+
+
+
+
+
+ لورم ایپسوم
+
+
+
+
+
{t('blog.tags')}
+
+
+
+ {t('blog.tag_hint')}
+
+
+
+
+
+
+
+ )
+}
+
+export default CreateBlog
\ No newline at end of file
diff --git a/src/pages/blog/components/ImageUploader.tsx b/src/pages/blog/components/ImageUploader.tsx
new file mode 100644
index 0000000..998ac91
--- /dev/null
+++ b/src/pages/blog/components/ImageUploader.tsx
@@ -0,0 +1,49 @@
+
+import { FC, useCallback, useState } from 'react'
+import { useTranslation } from 'react-i18next'
+import { Image, DocumentUpload } from 'iconsax-react'
+import { useDropzone } from 'react-dropzone'
+
+
+
+const ImageUploader: FC = () => {
+ const { t } = useTranslation('global')
+ const [file, setFile] = useState()
+ const onDrop = useCallback((acceptedFiles: File[]) => {
+ setFile(acceptedFiles[0])
+ }, [])
+ const { getRootProps, getInputProps } = useDropzone({ onDrop })
+
+ return(
+ <>
+ {t('blog.featured_image')}
+
+
+
+
+ {
+ file ?
+ file.name
+ :
+ t('ads.to_upload_message')
+
+ }
+
+
+
+
+
+ {t('ads.upload')}
+
+
+
+ >
+ )
+}
+export default ImageUploader
\ No newline at end of file
diff --git a/src/pages/discounts/CreateDiscount.tsx b/src/pages/discounts/CreateDiscount.tsx
new file mode 100644
index 0000000..7657150
--- /dev/null
+++ b/src/pages/discounts/CreateDiscount.tsx
@@ -0,0 +1,156 @@
+import { FC } from 'react'
+import { useTranslation } from 'react-i18next'
+import Input from '../../components/Input'
+import Button from '../../components/Button'
+import SwitchComponent from '../../components/Switch'
+import { TickCircle, TickSquare, Refresh } from 'iconsax-react'
+import DatePickerComponent from '../../components/DatePicker'
+import RadioGroup from '../../components/RadioGroup'
+const CreateDiscount: FC = () => {
+ const { t } = useTranslation('global')
+ return (
+
+
+
+ {t('discount.new_discount')}
+
+
+
+
+
+ {t('discount.submit')}
+
+
+
+
+
+
+
+ {t('discount.type')}
+
+ ''}
+ selected={''}
+ />
+
+
+
+
+
+
+
+
+ {t('discount.auto_generate_code')}
+
+
+
+
+
+
+ {t('discount.price')}
+
+ ''}
+ selected={''}
+ />
+
+
+
+
+
+ { }}
+ placeholder=''
+ defaulValue='1400-01-01'
+ />
+ { }}
+ placeholder=''
+ defaulValue='1400-01-01'
+ />
+
+
+
+
+
+ {t('discount.service_status')}
+
+
+
+ {t('ads.deactive')}
+
+
{ }}
+ />
+
+
+
{t('discount.availabe_service')}
+
+
+
+
+
+
+
+ لورم ایپسوم
+
+
+
+
+
+
+
+ لورم ایپسوم
+
+
+
+
+
+
+
+ لورم ایپسوم
+
+
+
+
+
+
+ )
+}
+export default CreateDiscount
\ No newline at end of file
diff --git a/src/pages/discounts/DiscountsList.tsx b/src/pages/discounts/DiscountsList.tsx
new file mode 100644
index 0000000..7b6ac89
--- /dev/null
+++ b/src/pages/discounts/DiscountsList.tsx
@@ -0,0 +1,116 @@
+import { FC } from 'react'
+import { useTranslation } from 'react-i18next'
+import Button from '../../components/Button'
+import { Add, Eye } from 'iconsax-react'
+import Td from '../../components/Td'
+import { Link } from 'react-router-dom'
+import { Pages } from '../../config/Pages'
+import SwitchComponent from '../../components/Switch'
+import Input from '../../components/Input'
+const DiscountList: FC = () => {
+ const { t } = useTranslation('global')
+ return (
+
+
+
+ {t('discount.list')}
+
+
+
+
+
+
+
+ {t('discount.add_new_discount')}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ { }}
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ { }}
+ />
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+export default DiscountList
\ No newline at end of file
diff --git a/src/pages/discounts/components/ImageUploader.tsx b/src/pages/discounts/components/ImageUploader.tsx
new file mode 100644
index 0000000..966c176
--- /dev/null
+++ b/src/pages/discounts/components/ImageUploader.tsx
@@ -0,0 +1,49 @@
+
+import { FC, useCallback, useState } from 'react'
+import { useTranslation } from 'react-i18next'
+import { Image, DocumentUpload } from 'iconsax-react'
+import { useDropzone } from 'react-dropzone'
+
+
+
+const ImageUploader: FC = () => {
+ const { t } = useTranslation('global')
+ const [file, setFile] = useState()
+ const onDrop = useCallback((acceptedFiles: File[]) => {
+ setFile(acceptedFiles[0])
+ }, [])
+ const { getRootProps, getInputProps } = useDropzone({ onDrop })
+
+ return(
+ <>
+ {t('ads.upload_picture')}
+
+
+
+
+ {
+ file ?
+ file.name
+ :
+ t('ads.to_upload_message')
+
+ }
+
+
+
+
+
+ {t('ads.upload')}
+
+
+
+ >
+ )
+}
+export default ImageUploader
\ No newline at end of file
diff --git a/src/router/Main.tsx b/src/router/Main.tsx
index acf0d00..5a2cd9f 100644
--- a/src/router/Main.tsx
+++ b/src/router/Main.tsx
@@ -5,6 +5,13 @@ import { Route, Routes } from 'react-router-dom'
import { Pages } from '../config/Pages'
import Home from '../pages/home/Home'
import MyServices from '../pages/service/MyServices'
+import DiscountsList from '../pages/discounts/DiscountsList'
+import CreateDiscount from '../pages/discounts/CreateDiscount'
+import AdsList from '../pages/ads/AdsList'
+import BlogList from '../pages/blog/BlogList'
+import CreateBlog from '../pages/blog/CreateBlog'
+import BlogCategory from '../pages/blog/BlogCategory'
+import CreateAds from '../pages/ads/CreateAds'
import TicketList from '../pages/ticket/TicketList'
import CreateTicket from '../pages/ticket/CreateTicket'
import TicketDetail from '../pages/ticket/Detail'
@@ -59,6 +66,13 @@ const MainRouter: FC = () => {
} />
} />
} />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
} />
} />
} />