From afacc7c48822927077dd8dfbf3c5813f85fd267e Mon Sep 17 00:00:00 2001 From: hamid zarghami Date: Tue, 15 Apr 2025 16:37:25 +0330 Subject: [PATCH] blogs --- package-lock.json | 146 +++++++++++++++++- package.json | 3 + src/app/blogs/[id]/page.tsx | 89 ++--------- src/app/blogs/components/BigBlogItem.tsx | 20 +-- src/app/blogs/components/HeroSection.tsx | 3 +- src/app/blogs/components/MostVisited.tsx | 6 +- src/app/blogs/components/SingleBlogPage.tsx | 102 ++++++++++++ src/app/blogs/hooks/useBlogsData.ts | 22 +++ src/app/blogs/page.tsx | 3 +- src/app/blogs/service/BlogService.ts | 11 ++ src/app/blogs/types/BlogTypes.ts | 5 + src/app/contact/hooks/useContactData.ts | 8 + src/app/contact/page.tsx | 50 +++++- src/app/contact/service/ContactService.ts | 7 + src/app/contact/types/ContactTypes.ts | 7 + src/app/globals.css | 5 + src/app/home/Blog.tsx | 2 +- src/app/layout.tsx | 2 + src/app/products/DanakSuggestedService.tsx | 30 ++++ .../{Products.tsx => ProductsPage.tsx} | 2 +- src/app/products/hooks/useProductData.ts | 11 ++ src/app/products/page.tsx | 5 +- src/app/products/service/ProductService.ts | 13 +- src/app/products/types/ProductTypes.ts | 4 + src/components/BlogItem.tsx | 3 +- src/shared/SideBar.tsx | 2 +- 26 files changed, 458 insertions(+), 103 deletions(-) create mode 100644 src/app/blogs/components/SingleBlogPage.tsx create mode 100644 src/app/contact/hooks/useContactData.ts create mode 100644 src/app/contact/service/ContactService.ts create mode 100644 src/app/contact/types/ContactTypes.ts create mode 100644 src/app/products/DanakSuggestedService.tsx rename src/app/products/{Products.tsx => ProductsPage.tsx} (99%) diff --git a/package-lock.json b/package-lock.json index 3c22b09..4ad55fd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,14 +11,17 @@ "@tanstack/react-query": "^5.73.3", "@tanstack/react-query-devtools": "^5.74.3", "axios": "^1.8.4", + "formik": "^2.4.6", "iconsax-react": "^0.0.8", "js-cookie": "^3.0.5", "next": "15.2.3", "react": "^19.0.0", "react-dom": "^19.0.0", "react-spinners": "^0.15.0", + "react-toastify": "^11.0.5", "swiper": "^11.2.6", "tailwind-merge": "^3.0.2", + "yup": "^1.6.1", "zustand": "^5.0.3" }, "devDependencies": { @@ -1189,6 +1192,16 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/hoist-non-react-statics": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.6.tgz", + "integrity": "sha512-lPByRJUer/iN/xa4qpyL0qmL11DqNW81iU/IG1S3uvRUq4oKagz8VCxZjiWkumgt66YT3vOdDgZ0o32sGKtCEw==", + "license": "MIT", + "dependencies": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, "node_modules/@types/js-cookie": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-3.0.6.tgz", @@ -1224,7 +1237,6 @@ "version": "19.0.12", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.0.12.tgz", "integrity": "sha512-V6Ar115dBDrjbtXSrS+/Oruobc+qVbbUxDFC1RSbRqLt5SYvxxyIDrSC85RWml54g+jfNeEMZhEj7wW07ONQhA==", - "devOptional": true, "license": "MIT", "dependencies": { "csstype": "^3.0.2" @@ -2078,6 +2090,15 @@ "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", "license": "MIT" }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/color": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", @@ -2161,7 +2182,6 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "devOptional": true, "license": "MIT" }, "node_modules/damerau-levenshtein": { @@ -2250,6 +2270,15 @@ "dev": true, "license": "MIT" }, + "node_modules/deepmerge": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz", + "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/define-data-property": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", @@ -3138,6 +3167,31 @@ "node": ">= 6" } }, + "node_modules/formik": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/formik/-/formik-2.4.6.tgz", + "integrity": "sha512-A+2EI7U7aG296q2TLGvNapDNTZp1khVt5Vk0Q/fyfSROss0V/V6+txt2aJnwEos44IxTCW/LYAi/zgWzlevj+g==", + "funding": [ + { + "type": "individual", + "url": "https://opencollective.com/formik" + } + ], + "license": "Apache-2.0", + "dependencies": { + "@types/hoist-non-react-statics": "^3.3.1", + "deepmerge": "^2.1.1", + "hoist-non-react-statics": "^3.3.0", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "react-fast-compare": "^2.0.1", + "tiny-warning": "^1.0.2", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -3406,6 +3460,15 @@ "node": ">= 0.4" } }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "license": "BSD-3-Clause", + "dependencies": { + "react-is": "^16.7.0" + } + }, "node_modules/i": { "version": "0.3.7", "resolved": "https://registry.npmjs.org/i/-/i-0.3.7.tgz", @@ -4293,6 +4356,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" + }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "license": "MIT" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -7486,6 +7561,12 @@ "react-is": "^16.13.1" } }, + "node_modules/property-expr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.6.tgz", + "integrity": "sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==", + "license": "MIT" + }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", @@ -7544,6 +7625,12 @@ "react": "^19.0.0" } }, + "node_modules/react-fast-compare": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz", + "integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==", + "license": "MIT" + }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -7560,6 +7647,19 @@ "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, + "node_modules/react-toastify": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-11.0.5.tgz", + "integrity": "sha512-EpqHBGvnSTtHYhCPLxML05NLY2ZX0JURbAdNYa6BUkk+amz4wbKBQvoKQAB0ardvSarUBuY4Q4s1sluAzZwkmA==", + "license": "MIT", + "dependencies": { + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": "^18 || ^19", + "react-dom": "^18 || ^19" + } + }, "node_modules/reflect.getprototypeof": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", @@ -8230,6 +8330,18 @@ "node": ">=6" } }, + "node_modules/tiny-case": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-case/-/tiny-case-1.0.3.tgz", + "integrity": "sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==", + "license": "MIT" + }, + "node_modules/tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==", + "license": "MIT" + }, "node_modules/tinyglobby": { "version": "0.2.12", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.12.tgz", @@ -8288,6 +8400,12 @@ "node": ">=8.0" } }, + "node_modules/toposort": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", + "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==", + "license": "MIT" + }, "node_modules/ts-api-utils": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", @@ -8333,6 +8451,18 @@ "node": ">= 0.8.0" } }, + "node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/typed-array-buffer": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", @@ -8589,6 +8719,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/yup": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/yup/-/yup-1.6.1.tgz", + "integrity": "sha512-JED8pB50qbA4FOkDol0bYF/p60qSEDQqBD0/qeIrUCG1KbPBIQ776fCUNb9ldbPcSTxA69g/47XTo4TqWiuXOA==", + "license": "MIT", + "dependencies": { + "property-expr": "^2.0.5", + "tiny-case": "^1.0.3", + "toposort": "^2.0.2", + "type-fest": "^2.19.0" + } + }, "node_modules/zustand": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.3.tgz", diff --git a/package.json b/package.json index 073a23e..ca06b29 100644 --- a/package.json +++ b/package.json @@ -12,14 +12,17 @@ "@tanstack/react-query": "^5.73.3", "@tanstack/react-query-devtools": "^5.74.3", "axios": "^1.8.4", + "formik": "^2.4.6", "iconsax-react": "^0.0.8", "js-cookie": "^3.0.5", "next": "15.2.3", "react": "^19.0.0", "react-dom": "^19.0.0", "react-spinners": "^0.15.0", + "react-toastify": "^11.0.5", "swiper": "^11.2.6", "tailwind-merge": "^3.0.2", + "yup": "^1.6.1", "zustand": "^5.0.3" }, "devDependencies": { diff --git a/src/app/blogs/[id]/page.tsx b/src/app/blogs/[id]/page.tsx index 97da2e5..5ec3e02 100644 --- a/src/app/blogs/[id]/page.tsx +++ b/src/app/blogs/[id]/page.tsx @@ -1,83 +1,18 @@ -import { Profile, Calendar } from 'iconsax-react' +import { dehydrate, HydrationBoundary, QueryClient } from '@tanstack/react-query' +import { blogSingleQueryOptions, mostVisitedBlogsQueryOptions } from '../hooks/useBlogsData' +import SingleBlogPage from '../components/SingleBlogPage' import { NextPage } from 'next' -import Image from 'next/image' -import MostVisited from '../components/MostVisited' -import ContactUs from '../components/ContactUs' -const SingleBlog: NextPage = () => { +const SingleBlog: NextPage<{ params: { id: string } }> = async ({ params }) => { + + + const queryClient = new QueryClient() + await queryClient.prefetchQuery(blogSingleQueryOptions(params.id)) + await queryClient.prefetchQuery(mostVisitedBlogsQueryOptions) return ( -
-

- سفارش نرم‌افزار اختصاصی: سرمایه‌ای برای آینده یا فقط هزینه‌ای برای امروز؟ -

- -
-
-
-
-
-
دسته بندی
-
- -
- -
نویسنده
-
- -
- -
۱۴۰۳/۱۲/۰۱
-
-
- -
- blog -
- -

- لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ، و با استفاده از طراحان گرافیک است، چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است، و برای شرایط فعلی تکنولوژی مورد نیاز، و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد، کتابهای زیادی در شصت و سه درصد گذشته حال و آینده، شناخت فراوان جامعه و متخصصان را می طلبد، تا با نرم افزارها شناخت بیشتری را برای طراحان رایانه ای علی الخصوص طراحان خلاقی، و فرهنگ پیشرو در زبان فارسی ایجاد کرد، در این صورت می توان امید داشت که تمام و دشواری موجود در ارائه راهکارها، و شرایط سخت تایپ به پایان رسد و زمان مورد نیاز شامل حروفچینی دستاوردهای اصلی، و جوابگوی سوالات پیوسته اهل دنیای موجود طراحی اساسا مورد استفاده قرار گیرد.لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ، و با استفاده از طراحان گرافیک است، چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است، و برای شرایط فعلی تکنولوژی مورد نیاز، و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد، کتابهای زیادی در شصت و سه درصد گذشته حال و آینده، شناخت فراوان جامعه و متخصصان را می طلبد، تا با نرم افزارها شناخت بیشتری را برای طراحان رایانه ای علی الخصوص طراحان خلاقی، و فرهنگ پیشرو در زبان فارسی ایجاد کرد، در این صورت می توان امید داشت که تمام و دشواری موجود در ارائه راهکارها، و شرایط سخت تایپ به پایان رسد و زمان مورد نیاز شامل حروفچینی دستاوردهای اصلی، و جوابگوی سوالات پیوسته اهل دنیای موجود طراحی اساسا مورد استفاده قرار گیرد.لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ، و با استفاده از طراحان گرافیک است، چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است، و برای شرایط فعلی تکنولوژی مورد نیاز، و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد، کتابهای زیادی در شصت و سه درصد گذشته حال و آینده، شناخت فراوان جامعه و متخصصان را می طلبد، تا با نرم افزارها شناخت بیشتری را برای طراحان رایانه ای علی الخصوص طراحان خلاقی، و فرهنگ پیشرو در زبان فارسی ایجاد کرد، در این صورت می توان امید داشت که تمام و دشواری موجود در ارائه راهکارها، و شرایط سخت تایپ به پایان رسد و زمان مورد نیاز شامل حروفچینی دستاوردهای اصلی، و جوابگوی سوالات پیوسته اهل دنیای موجود طراحی اساسا مورد استفاده قرار گیرد.چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است، و برای شرایط فعلی تکنولوژی مورد نیاز، و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد، کتابهای زیادی در شصت و سه درصد گذشته حال و آینده، شناخت فراوان جامعه و متخصصان را می طلبد، تا با نرم افزارها شناخت بیشتری را برای طراحان رایانه ای علی الخصوص طراحان خلاقی، و فرهنگ پیشرو در زبان فارسی ایجاد کرد، در این صورت می توان امید داشت که تمام و دشواری موجود در ارائه راهکارها، و شرایط سخت تایپ به پایان رسد و زمان مورد نیاز شامل حروفچینی دستاوردهای اصلی، و جوابگوی سوالات پیوسته اهل دنیای موجود طراحی اساسا مورد استفاده قرار گیردچاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است، و برای شرایط فعلی تکنولوژی مورد نیاز، و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می باشد، کتابهای زیادی در شصت و سه درصد گذشته حال و آینده، شناخت فراوان جامعه و متخصصان را می طلبد، تا با نرم افزارها شناخت بیشتری را برای طراحان رایانه ای علی الخصوص طراحان خلاقی، و فرهنگ پیشرو در زبان فارسی ایجاد کرد، در این صورت می توان امید داشت که تمام و دشواری موجود در ارائه راهکارها، و شرایط سخت تایپ به پایان رسد و زمان مورد نیاز شامل حروفچینی دستاوردهای اصلی، و جوابگوی سوالات پیوسته اهل دنیای موجود طراحی اساسا مورد استفاده قرار گیرد -

- -
-
اشتراک گذاری
- share - share - share -
-
- -
- -
- -
-
- -
-
-
-
+ + + ) } diff --git a/src/app/blogs/components/BigBlogItem.tsx b/src/app/blogs/components/BigBlogItem.tsx index c421610..96b58f1 100644 --- a/src/app/blogs/components/BigBlogItem.tsx +++ b/src/app/blogs/components/BigBlogItem.tsx @@ -3,6 +3,7 @@ import Image from 'next/image' import { ArrowLeft, Calendar2, Profile } from 'iconsax-react' import { Blog } from '../types/BlogTypes' import { toJalaliDate } from '@/config/func' +import Link from 'next/link' interface BigBlogItemProps { item: Blog @@ -38,17 +39,18 @@ const BigBlogItem: FC = ({ item }) => { -

- {item.previewContent} +

-
-
ادامه ی مطلب
- -
+ +
+
ادامه ی مطلب
+ +
+ ) diff --git a/src/app/blogs/components/HeroSection.tsx b/src/app/blogs/components/HeroSection.tsx index 515371b..974e259 100644 --- a/src/app/blogs/components/HeroSection.tsx +++ b/src/app/blogs/components/HeroSection.tsx @@ -27,8 +27,7 @@ const HeroSection: FC = () => { {item.title} -

- {item.previewContent} +

diff --git a/src/app/blogs/components/MostVisited.tsx b/src/app/blogs/components/MostVisited.tsx index c9cd835..7dbc8f2 100644 --- a/src/app/blogs/components/MostVisited.tsx +++ b/src/app/blogs/components/MostVisited.tsx @@ -1,9 +1,9 @@ import { FC } from 'react' import MiniBlogItem from './MiniBlogItem' -import { useGetBlogCombined } from '../hooks/useBlogsData' +import { useGetMostVisitedBlogs } from '../hooks/useBlogsData' const MostVisited: FC = () => { - const { data } = useGetBlogCombined() + const { data } = useGetMostVisitedBlogs() return (

@@ -12,7 +12,7 @@ const MostVisited: FC = () => {
{ - data?.data?.mostVisitedBlogs?.map((item) => { + data?.data?.blogs?.map((item) => { return }) } diff --git a/src/app/blogs/components/SingleBlogPage.tsx b/src/app/blogs/components/SingleBlogPage.tsx new file mode 100644 index 0000000..67b9b8b --- /dev/null +++ b/src/app/blogs/components/SingleBlogPage.tsx @@ -0,0 +1,102 @@ +'use client' +import { Profile, Calendar } from 'iconsax-react' +import { NextPage } from 'next' +import Image from 'next/image' +// import MostVisited from '../components/MostVisited' +import ContactUs from '../components/ContactUs' +import { useGetBlogSingle } from '../hooks/useBlogsData' +import { toJalaliDate } from '@/config/func' +import MostVisited from './MostVisited' + +type Props = { + id: string +} + +const SingleBlog: NextPage = ({ id }) => { + + const { data } = useGetBlogSingle(id) + if (!data) return
+ return ( +
+

+ {data?.data?.blog?.title} +

+ +
+
+
+
+
+ {data?.data?.blog?.category?.title} +
+
{data?.data?.blog?.category?.title}
+
+ +
+ +
{data?.data?.blog?.author.firstName} {data?.data?.blog?.author.lastName}
+
+ +
+ +
{toJalaliDate(data?.data?.blog?.createdAt)}
+
+
+ +
+ {data?.data?.blog?.title} +
+ +

+ +

+ +
+
اشتراک گذاری
+ share + share + share +
+
+ +
+ +
+ +
+
+ {/* */} +
+
+
+
+ ) +} + +export default SingleBlog \ No newline at end of file diff --git a/src/app/blogs/hooks/useBlogsData.ts b/src/app/blogs/hooks/useBlogsData.ts index 5905755..dbd29e0 100644 --- a/src/app/blogs/hooks/useBlogsData.ts +++ b/src/app/blogs/hooks/useBlogsData.ts @@ -8,6 +8,12 @@ export const useGetBlogs = () => queryFn: api.getBlogs, }); +export const useGetMostVisitedBlogs = () => + useQuery({ + queryKey: ["most-visited-blogs"], + queryFn: api.getMostVisitedBlogs, + }); + export const useGetBlogsPinned = () => useQuery({ queryKey: ["blogs-pinned"], @@ -26,12 +32,28 @@ export const useGetBlogCombined = () => queryFn: api.getCombinedBlogs, }); +export const useGetBlogSingle = (id: string) => + useQuery({ + queryKey: ["blog-single", id], + queryFn: () => api.getBlogSingle(id), + }); + // برای server prefetch export const blogsQueryOptions = { queryKey: ["blogs"], queryFn: api.getBlogs, }; +export const blogSingleQueryOptions = (id: string) => ({ + queryKey: ["blog-single", id], + queryFn: () => api.getBlogSingle(id), +}); + +export const mostVisitedBlogsQueryOptions = { + queryKey: ["most-visited-blogs"], + queryFn: api.getMostVisitedBlogs, +}; + export const blogsPinnedQueryOptions = { queryKey: ["blogs-pinned"], queryFn: api.getBlogsPinned, diff --git a/src/app/blogs/page.tsx b/src/app/blogs/page.tsx index 839d396..12333a6 100644 --- a/src/app/blogs/page.tsx +++ b/src/app/blogs/page.tsx @@ -1,7 +1,7 @@ import { HydrationBoundary, dehydrate } from '@tanstack/react-query' import { QueryClient } from '@tanstack/react-query' import BlogList from './components/BlogList' -import { blogCategoriesQueryOptions, blogsQueryOptions, blogCombinedQueryOptions } from './hooks/useBlogsData' +import { blogCategoriesQueryOptions, blogsQueryOptions, blogCombinedQueryOptions, mostVisitedBlogsQueryOptions } from './hooks/useBlogsData' export const metadata = { title: 'مجله داناک | مقالات و آموزش‌ها', @@ -14,6 +14,7 @@ export default async function BlogsPage() { await queryClient.prefetchQuery(blogsQueryOptions) await queryClient.prefetchQuery(blogCategoriesQueryOptions) await queryClient.prefetchQuery(blogCombinedQueryOptions) + await queryClient.prefetchQuery(mostVisitedBlogsQueryOptions) return ( diff --git a/src/app/blogs/service/BlogService.ts b/src/app/blogs/service/BlogService.ts index 9f6f543..4aec9de 100644 --- a/src/app/blogs/service/BlogService.ts +++ b/src/app/blogs/service/BlogService.ts @@ -3,6 +3,7 @@ import { BlogCategoryResponse, BlogCombinedResponse, BlogResponse, + BlogSingleResponse, } from "../types/BlogTypes"; export const getBlogs = async () => { @@ -10,6 +11,11 @@ export const getBlogs = async () => { return data; }; +export const getMostVisitedBlogs = async () => { + const { data } = await axios.get(`/blogs/most-visited`); + return data; +}; + export const getBlogCategories = async () => { const { data } = await axios.get( `/blogs/categories/public` @@ -26,3 +32,8 @@ export const getCombinedBlogs = async () => { const { data } = await axios.get(`/blogs/combined`); return data; }; + +export const getBlogSingle = async (id: string) => { + const { data } = await axios.get(`/blogs/${id}`); + return data; +}; diff --git a/src/app/blogs/types/BlogTypes.ts b/src/app/blogs/types/BlogTypes.ts index b19961b..7f02751 100644 --- a/src/app/blogs/types/BlogTypes.ts +++ b/src/app/blogs/types/BlogTypes.ts @@ -24,6 +24,7 @@ export interface Blog { viewCount: number; author: Author; category: Category; + content: string; } export interface Pager { @@ -57,3 +58,7 @@ export type BlogStoreType = { selectedCategory: string; setSelectedCategory: (category: string) => void; }; + +export type BlogSingleResponse = ApiResponse<{ + blog: Blog; +}>; diff --git a/src/app/contact/hooks/useContactData.ts b/src/app/contact/hooks/useContactData.ts new file mode 100644 index 0000000..1a71803 --- /dev/null +++ b/src/app/contact/hooks/useContactData.ts @@ -0,0 +1,8 @@ +import { useMutation } from "@tanstack/react-query"; +import * as api from "../service/ContactService"; + +export const useCreateContact = () => { + return useMutation({ + mutationFn: api.createContact, + }); +}; diff --git a/src/app/contact/page.tsx b/src/app/contact/page.tsx index 1d00e07..e697d26 100644 --- a/src/app/contact/page.tsx +++ b/src/app/contact/page.tsx @@ -1,11 +1,47 @@ +'use client' import Button from '@/components/Button' import Input from '@/components/Input' import Textarea from '@/components/Textarea' import { CallCalling, Location, SmsTracking } from 'iconsax-react' import { NextPage } from 'next' import React from 'react' - +import { CreateContactType } from './types/ContactTypes' +import { useFormik } from 'formik' +import * as Yup from 'yup' +import { useCreateContact } from './hooks/useContactData' +import { toast } from 'react-toastify' +import { ErrorType } from '@/helpers/types' const Contact: NextPage = () => { + + const createContact = useCreateContact() + + const formik = useFormik({ + initialValues: { + fullName: '', + email: '', + phone: '', + businessName: '', + content: '', + }, + validationSchema: Yup.object({ + fullName: Yup.string().required('نام وارد کنید'), + email: Yup.string().email('ایمیل معتبر وارد کنید').required('ایمیل وارد کنید'), + phone: Yup.string().required('شماره تماس وارد کنید'), + businessName: Yup.string().required('نام شرکت وارد کنید'), + content: Yup.string().required('پیام وارد کنید'), + }), + onSubmit: (values) => { + createContact.mutate(values, { + onSuccess: () => { + toast.success('پیام شما با موفقیت ثبت شد') + formik.resetForm() + }, + onError: (error: ErrorType) => { + toast.error(error.response?.data?.error.message[0]) + } + }) + }, + }) return (

@@ -62,23 +98,33 @@ const Contact: NextPage = () => {