blogs
This commit is contained in:
Generated
+144
-2
@@ -11,14 +11,17 @@
|
|||||||
"@tanstack/react-query": "^5.73.3",
|
"@tanstack/react-query": "^5.73.3",
|
||||||
"@tanstack/react-query-devtools": "^5.74.3",
|
"@tanstack/react-query-devtools": "^5.74.3",
|
||||||
"axios": "^1.8.4",
|
"axios": "^1.8.4",
|
||||||
|
"formik": "^2.4.6",
|
||||||
"iconsax-react": "^0.0.8",
|
"iconsax-react": "^0.0.8",
|
||||||
"js-cookie": "^3.0.5",
|
"js-cookie": "^3.0.5",
|
||||||
"next": "15.2.3",
|
"next": "15.2.3",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"react-spinners": "^0.15.0",
|
"react-spinners": "^0.15.0",
|
||||||
|
"react-toastify": "^11.0.5",
|
||||||
"swiper": "^11.2.6",
|
"swiper": "^11.2.6",
|
||||||
"tailwind-merge": "^3.0.2",
|
"tailwind-merge": "^3.0.2",
|
||||||
|
"yup": "^1.6.1",
|
||||||
"zustand": "^5.0.3"
|
"zustand": "^5.0.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -1189,6 +1192,16 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"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": {
|
"node_modules/@types/js-cookie": {
|
||||||
"version": "3.0.6",
|
"version": "3.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-3.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-3.0.6.tgz",
|
||||||
@@ -1224,7 +1237,6 @@
|
|||||||
"version": "19.0.12",
|
"version": "19.0.12",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.0.12.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.0.12.tgz",
|
||||||
"integrity": "sha512-V6Ar115dBDrjbtXSrS+/Oruobc+qVbbUxDFC1RSbRqLt5SYvxxyIDrSC85RWml54g+jfNeEMZhEj7wW07ONQhA==",
|
"integrity": "sha512-V6Ar115dBDrjbtXSrS+/Oruobc+qVbbUxDFC1RSbRqLt5SYvxxyIDrSC85RWml54g+jfNeEMZhEj7wW07ONQhA==",
|
||||||
"devOptional": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"csstype": "^3.0.2"
|
"csstype": "^3.0.2"
|
||||||
@@ -2078,6 +2090,15 @@
|
|||||||
"integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==",
|
"integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==",
|
||||||
"license": "MIT"
|
"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": {
|
"node_modules/color": {
|
||||||
"version": "4.2.3",
|
"version": "4.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
|
||||||
@@ -2161,7 +2182,6 @@
|
|||||||
"version": "3.1.3",
|
"version": "3.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
|
||||||
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
|
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
|
||||||
"devOptional": true,
|
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/damerau-levenshtein": {
|
"node_modules/damerau-levenshtein": {
|
||||||
@@ -2250,6 +2270,15 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"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": {
|
"node_modules/define-data-property": {
|
||||||
"version": "1.1.4",
|
"version": "1.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
|
||||||
@@ -3138,6 +3167,31 @@
|
|||||||
"node": ">= 6"
|
"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": {
|
"node_modules/function-bind": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
||||||
@@ -3406,6 +3460,15 @@
|
|||||||
"node": ">= 0.4"
|
"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": {
|
"node_modules/i": {
|
||||||
"version": "0.3.7",
|
"version": "0.3.7",
|
||||||
"resolved": "https://registry.npmjs.org/i/-/i-0.3.7.tgz",
|
"resolved": "https://registry.npmjs.org/i/-/i-0.3.7.tgz",
|
||||||
@@ -4293,6 +4356,18 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"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": {
|
"node_modules/lodash.merge": {
|
||||||
"version": "4.6.2",
|
"version": "4.6.2",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
|
||||||
@@ -7486,6 +7561,12 @@
|
|||||||
"react-is": "^16.13.1"
|
"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": {
|
"node_modules/proxy-from-env": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||||
@@ -7544,6 +7625,12 @@
|
|||||||
"react": "^19.0.0"
|
"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": {
|
"node_modules/react-is": {
|
||||||
"version": "16.13.1",
|
"version": "16.13.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
"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"
|
"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": {
|
"node_modules/reflect.getprototypeof": {
|
||||||
"version": "1.0.10",
|
"version": "1.0.10",
|
||||||
"resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
|
"resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
|
||||||
@@ -8230,6 +8330,18 @@
|
|||||||
"node": ">=6"
|
"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": {
|
"node_modules/tinyglobby": {
|
||||||
"version": "0.2.12",
|
"version": "0.2.12",
|
||||||
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.12.tgz",
|
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.12.tgz",
|
||||||
@@ -8288,6 +8400,12 @@
|
|||||||
"node": ">=8.0"
|
"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": {
|
"node_modules/ts-api-utils": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz",
|
||||||
@@ -8333,6 +8451,18 @@
|
|||||||
"node": ">= 0.8.0"
|
"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": {
|
"node_modules/typed-array-buffer": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz",
|
"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"
|
"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": {
|
"node_modules/zustand": {
|
||||||
"version": "5.0.3",
|
"version": "5.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.3.tgz",
|
||||||
|
|||||||
@@ -12,14 +12,17 @@
|
|||||||
"@tanstack/react-query": "^5.73.3",
|
"@tanstack/react-query": "^5.73.3",
|
||||||
"@tanstack/react-query-devtools": "^5.74.3",
|
"@tanstack/react-query-devtools": "^5.74.3",
|
||||||
"axios": "^1.8.4",
|
"axios": "^1.8.4",
|
||||||
|
"formik": "^2.4.6",
|
||||||
"iconsax-react": "^0.0.8",
|
"iconsax-react": "^0.0.8",
|
||||||
"js-cookie": "^3.0.5",
|
"js-cookie": "^3.0.5",
|
||||||
"next": "15.2.3",
|
"next": "15.2.3",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"react-spinners": "^0.15.0",
|
"react-spinners": "^0.15.0",
|
||||||
|
"react-toastify": "^11.0.5",
|
||||||
"swiper": "^11.2.6",
|
"swiper": "^11.2.6",
|
||||||
"tailwind-merge": "^3.0.2",
|
"tailwind-merge": "^3.0.2",
|
||||||
|
"yup": "^1.6.1",
|
||||||
"zustand": "^5.0.3"
|
"zustand": "^5.0.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
+12
-77
File diff suppressed because one or more lines are too long
@@ -3,6 +3,7 @@ import Image from 'next/image'
|
|||||||
import { ArrowLeft, Calendar2, Profile } from 'iconsax-react'
|
import { ArrowLeft, Calendar2, Profile } from 'iconsax-react'
|
||||||
import { Blog } from '../types/BlogTypes'
|
import { Blog } from '../types/BlogTypes'
|
||||||
import { toJalaliDate } from '@/config/func'
|
import { toJalaliDate } from '@/config/func'
|
||||||
|
import Link from 'next/link'
|
||||||
|
|
||||||
interface BigBlogItemProps {
|
interface BigBlogItemProps {
|
||||||
item: Blog
|
item: Blog
|
||||||
@@ -38,17 +39,18 @@ const BigBlogItem: FC<BigBlogItemProps> = ({ item }) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p className='mt-3 text-sm leading-5'>
|
<p dangerouslySetInnerHTML={{ __html: item.previewContent }} className='mt-3 text-sm leading-5'>
|
||||||
{item.previewContent}
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div className='mt-3 flex gap-1 text-sm text-[#8C90A3]'>
|
<Link href={`/blogs/${item.id}`}>
|
||||||
<div>ادامه ی مطلب</div>
|
<div className='mt-3 flex gap-1 text-sm text-[#8C90A3]'>
|
||||||
<ArrowLeft
|
<div>ادامه ی مطلب</div>
|
||||||
size={18}
|
<ArrowLeft
|
||||||
color='#8C90A3'
|
size={18}
|
||||||
/>
|
color='#8C90A3'
|
||||||
</div>
|
/>
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -27,8 +27,7 @@ const HeroSection: FC = () => {
|
|||||||
{item.title}
|
{item.title}
|
||||||
</h4>
|
</h4>
|
||||||
|
|
||||||
<p className="text-xs xl:text-sm mt-4 leading-7 truncate xl:text-clip xl:whitespace-normal">
|
<p dangerouslySetInnerHTML={{ __html: item.previewContent }} className="text-xs xl:text-sm mt-4 leading-7 truncate xl:text-clip xl:whitespace-normal">
|
||||||
{item.previewContent}
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { FC } from 'react'
|
import { FC } from 'react'
|
||||||
import MiniBlogItem from './MiniBlogItem'
|
import MiniBlogItem from './MiniBlogItem'
|
||||||
import { useGetBlogCombined } from '../hooks/useBlogsData'
|
import { useGetMostVisitedBlogs } from '../hooks/useBlogsData'
|
||||||
|
|
||||||
const MostVisited: FC = () => {
|
const MostVisited: FC = () => {
|
||||||
const { data } = useGetBlogCombined()
|
const { data } = useGetMostVisitedBlogs()
|
||||||
return (
|
return (
|
||||||
<div className='w-full rounded-4xl bg-white p-4'>
|
<div className='w-full rounded-4xl bg-white p-4'>
|
||||||
<h4>
|
<h4>
|
||||||
@@ -12,7 +12,7 @@ const MostVisited: FC = () => {
|
|||||||
|
|
||||||
<div className='flex flex-col gap-6 mt-7 text-sm'>
|
<div className='flex flex-col gap-6 mt-7 text-sm'>
|
||||||
{
|
{
|
||||||
data?.data?.mostVisitedBlogs?.map((item) => {
|
data?.data?.blogs?.map((item) => {
|
||||||
return <MiniBlogItem key={item.id} item={item} />
|
return <MiniBlogItem key={item.id} item={item} />
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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<Props> = ({ id }) => {
|
||||||
|
|
||||||
|
const { data } = useGetBlogSingle(id)
|
||||||
|
if (!data) return <div></div>
|
||||||
|
return (
|
||||||
|
<div className='mt-24 max-w-maxWidth mx-auto'>
|
||||||
|
<h1 className='text-2xl font-bold'>
|
||||||
|
{data?.data?.blog?.title}
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<div className='mt-10 flex gap-8'>
|
||||||
|
<div className='flex-1 bg-white rounded-4xl p-10'>
|
||||||
|
<div className='flex gap-4'>
|
||||||
|
<div className='flex gap-1'>
|
||||||
|
<div className='size-5 overflow-hidden rounded-full'>
|
||||||
|
<Image
|
||||||
|
src={data?.data?.blog?.category?.iconUrl}
|
||||||
|
alt={data?.data?.blog?.category?.title}
|
||||||
|
width={20}
|
||||||
|
height={20}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<h6 className='text-[#7D818C] text-sm'>{data?.data?.blog?.category?.title}</h6>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='flex gap-1'>
|
||||||
|
<Profile size={20} color='#7D818C' />
|
||||||
|
<h6 className='text-[#7D818C] text-sm'>{data?.data?.blog?.author.firstName} {data?.data?.blog?.author.lastName}</h6>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='flex gap-1'>
|
||||||
|
<Calendar size={20} color='#7D818C' />
|
||||||
|
<h6 className='text-[#7D818C] text-sm'>{toJalaliDate(data?.data?.blog?.createdAt)}</h6>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='mt-6'>
|
||||||
|
<Image
|
||||||
|
src={data?.data?.blog?.imageUrl}
|
||||||
|
alt={data?.data?.blog?.title}
|
||||||
|
width={1000}
|
||||||
|
height={1000}
|
||||||
|
className='w-full rounded-4xl max-h-[400px] object-cover'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p dangerouslySetInnerHTML={{ __html: data?.data?.blog?.content }} className='mt-8 text-sm leading-6'>
|
||||||
|
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className='mt-6 flex gap-4 border-y border-[#E5E5E5] py-4'>
|
||||||
|
<div className='text-sm'>اشتراک گذاری</div>
|
||||||
|
<Image
|
||||||
|
src='/images/instagram.svg'
|
||||||
|
alt='share'
|
||||||
|
width={20}
|
||||||
|
height={20}
|
||||||
|
/>
|
||||||
|
<Image
|
||||||
|
src='/images/instagram.svg'
|
||||||
|
alt='share'
|
||||||
|
width={20}
|
||||||
|
height={20}
|
||||||
|
/>
|
||||||
|
<Image
|
||||||
|
src='/images/instagram.svg'
|
||||||
|
alt='share'
|
||||||
|
width={20}
|
||||||
|
height={20}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='w-[261px]'>
|
||||||
|
<MostVisited />
|
||||||
|
<div className='mt-6'>
|
||||||
|
<ContactUs />
|
||||||
|
</div>
|
||||||
|
<div className='mt-6'>
|
||||||
|
{/* <MostVisited /> */}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SingleBlog
|
||||||
@@ -8,6 +8,12 @@ export const useGetBlogs = () =>
|
|||||||
queryFn: api.getBlogs,
|
queryFn: api.getBlogs,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const useGetMostVisitedBlogs = () =>
|
||||||
|
useQuery({
|
||||||
|
queryKey: ["most-visited-blogs"],
|
||||||
|
queryFn: api.getMostVisitedBlogs,
|
||||||
|
});
|
||||||
|
|
||||||
export const useGetBlogsPinned = () =>
|
export const useGetBlogsPinned = () =>
|
||||||
useQuery({
|
useQuery({
|
||||||
queryKey: ["blogs-pinned"],
|
queryKey: ["blogs-pinned"],
|
||||||
@@ -26,12 +32,28 @@ export const useGetBlogCombined = () =>
|
|||||||
queryFn: api.getCombinedBlogs,
|
queryFn: api.getCombinedBlogs,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const useGetBlogSingle = (id: string) =>
|
||||||
|
useQuery({
|
||||||
|
queryKey: ["blog-single", id],
|
||||||
|
queryFn: () => api.getBlogSingle(id),
|
||||||
|
});
|
||||||
|
|
||||||
// برای server prefetch
|
// برای server prefetch
|
||||||
export const blogsQueryOptions = {
|
export const blogsQueryOptions = {
|
||||||
queryKey: ["blogs"],
|
queryKey: ["blogs"],
|
||||||
queryFn: api.getBlogs,
|
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 = {
|
export const blogsPinnedQueryOptions = {
|
||||||
queryKey: ["blogs-pinned"],
|
queryKey: ["blogs-pinned"],
|
||||||
queryFn: api.getBlogsPinned,
|
queryFn: api.getBlogsPinned,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { HydrationBoundary, dehydrate } from '@tanstack/react-query'
|
import { HydrationBoundary, dehydrate } from '@tanstack/react-query'
|
||||||
import { QueryClient } from '@tanstack/react-query'
|
import { QueryClient } from '@tanstack/react-query'
|
||||||
import BlogList from './components/BlogList'
|
import BlogList from './components/BlogList'
|
||||||
import { blogCategoriesQueryOptions, blogsQueryOptions, blogCombinedQueryOptions } from './hooks/useBlogsData'
|
import { blogCategoriesQueryOptions, blogsQueryOptions, blogCombinedQueryOptions, mostVisitedBlogsQueryOptions } from './hooks/useBlogsData'
|
||||||
|
|
||||||
export const metadata = {
|
export const metadata = {
|
||||||
title: 'مجله داناک | مقالات و آموزشها',
|
title: 'مجله داناک | مقالات و آموزشها',
|
||||||
@@ -14,6 +14,7 @@ export default async function BlogsPage() {
|
|||||||
await queryClient.prefetchQuery(blogsQueryOptions)
|
await queryClient.prefetchQuery(blogsQueryOptions)
|
||||||
await queryClient.prefetchQuery(blogCategoriesQueryOptions)
|
await queryClient.prefetchQuery(blogCategoriesQueryOptions)
|
||||||
await queryClient.prefetchQuery(blogCombinedQueryOptions)
|
await queryClient.prefetchQuery(blogCombinedQueryOptions)
|
||||||
|
await queryClient.prefetchQuery(mostVisitedBlogsQueryOptions)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<HydrationBoundary state={dehydrate(queryClient)}>
|
<HydrationBoundary state={dehydrate(queryClient)}>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import {
|
|||||||
BlogCategoryResponse,
|
BlogCategoryResponse,
|
||||||
BlogCombinedResponse,
|
BlogCombinedResponse,
|
||||||
BlogResponse,
|
BlogResponse,
|
||||||
|
BlogSingleResponse,
|
||||||
} from "../types/BlogTypes";
|
} from "../types/BlogTypes";
|
||||||
|
|
||||||
export const getBlogs = async () => {
|
export const getBlogs = async () => {
|
||||||
@@ -10,6 +11,11 @@ export const getBlogs = async () => {
|
|||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getMostVisitedBlogs = async () => {
|
||||||
|
const { data } = await axios.get<BlogResponse>(`/blogs/most-visited`);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
export const getBlogCategories = async () => {
|
export const getBlogCategories = async () => {
|
||||||
const { data } = await axios.get<BlogCategoryResponse>(
|
const { data } = await axios.get<BlogCategoryResponse>(
|
||||||
`/blogs/categories/public`
|
`/blogs/categories/public`
|
||||||
@@ -26,3 +32,8 @@ export const getCombinedBlogs = async () => {
|
|||||||
const { data } = await axios.get<BlogCombinedResponse>(`/blogs/combined`);
|
const { data } = await axios.get<BlogCombinedResponse>(`/blogs/combined`);
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getBlogSingle = async (id: string) => {
|
||||||
|
const { data } = await axios.get<BlogSingleResponse>(`/blogs/${id}`);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ export interface Blog {
|
|||||||
viewCount: number;
|
viewCount: number;
|
||||||
author: Author;
|
author: Author;
|
||||||
category: Category;
|
category: Category;
|
||||||
|
content: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Pager {
|
export interface Pager {
|
||||||
@@ -57,3 +58,7 @@ export type BlogStoreType = {
|
|||||||
selectedCategory: string;
|
selectedCategory: string;
|
||||||
setSelectedCategory: (category: string) => void;
|
setSelectedCategory: (category: string) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type BlogSingleResponse = ApiResponse<{
|
||||||
|
blog: Blog;
|
||||||
|
}>;
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import { useMutation } from "@tanstack/react-query";
|
||||||
|
import * as api from "../service/ContactService";
|
||||||
|
|
||||||
|
export const useCreateContact = () => {
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: api.createContact,
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -1,11 +1,47 @@
|
|||||||
|
'use client'
|
||||||
import Button from '@/components/Button'
|
import Button from '@/components/Button'
|
||||||
import Input from '@/components/Input'
|
import Input from '@/components/Input'
|
||||||
import Textarea from '@/components/Textarea'
|
import Textarea from '@/components/Textarea'
|
||||||
import { CallCalling, Location, SmsTracking } from 'iconsax-react'
|
import { CallCalling, Location, SmsTracking } from 'iconsax-react'
|
||||||
import { NextPage } from 'next'
|
import { NextPage } from 'next'
|
||||||
import React from 'react'
|
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 Contact: NextPage = () => {
|
||||||
|
|
||||||
|
const createContact = useCreateContact()
|
||||||
|
|
||||||
|
const formik = useFormik<CreateContactType>({
|
||||||
|
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 (
|
return (
|
||||||
<div className='mt-24 max-w-maxWidth mx-auto'>
|
<div className='mt-24 max-w-maxWidth mx-auto'>
|
||||||
<h1 className='text-2xl font-bold'>
|
<h1 className='text-2xl font-bold'>
|
||||||
@@ -62,23 +98,33 @@ const Contact: NextPage = () => {
|
|||||||
<div className='rowTwoInput mt-8'>
|
<div className='rowTwoInput mt-8'>
|
||||||
<Input
|
<Input
|
||||||
placeholder='نام و نام خانوادگی'
|
placeholder='نام و نام خانوادگی'
|
||||||
|
{...formik.getFieldProps('fullName')}
|
||||||
|
error_text={formik.touched.fullName && formik.errors.fullName ? formik.errors.fullName : undefined}
|
||||||
/>
|
/>
|
||||||
<Input
|
<Input
|
||||||
placeholder='نام شرکت '
|
placeholder='نام شرکت '
|
||||||
|
{...formik.getFieldProps('businessName')}
|
||||||
|
error_text={formik.touched.businessName && formik.errors.businessName ? formik.errors.businessName : undefined}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className='rowTwoInput mt-8'>
|
<div className='rowTwoInput mt-8'>
|
||||||
<Input
|
<Input
|
||||||
placeholder='شماره تماس'
|
placeholder='شماره تماس'
|
||||||
|
{...formik.getFieldProps('phone')}
|
||||||
|
error_text={formik.touched.phone && formik.errors.phone ? formik.errors.phone : undefined}
|
||||||
/>
|
/>
|
||||||
<Input
|
<Input
|
||||||
placeholder='ایمیل'
|
placeholder='ایمیل'
|
||||||
|
{...formik.getFieldProps('email')}
|
||||||
|
error_text={formik.touched.email && formik.errors.email ? formik.errors.email : undefined}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='mt-8'>
|
<div className='mt-8'>
|
||||||
<Textarea
|
<Textarea
|
||||||
label='پیام'
|
label='پیام'
|
||||||
|
{...formik.getFieldProps('content')}
|
||||||
|
error_text={formik.touched.content && formik.errors.content ? formik.errors.content : undefined}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -86,6 +132,8 @@ const Contact: NextPage = () => {
|
|||||||
<Button
|
<Button
|
||||||
label='ارسال'
|
label='ارسال'
|
||||||
className='w-fit px-8'
|
className='w-fit px-8'
|
||||||
|
onClick={() => formik.handleSubmit()}
|
||||||
|
isLoading={createContact.isPending}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import axios from "@/config/axios";
|
||||||
|
import { CreateContactType } from "../types/ContactTypes";
|
||||||
|
|
||||||
|
export const createContact = async (params: CreateContactType) => {
|
||||||
|
const { data } = await axios.post("/contact-us", params);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
export type CreateContactType = {
|
||||||
|
fullName: string;
|
||||||
|
email: string;
|
||||||
|
phone: string;
|
||||||
|
businessName: string;
|
||||||
|
content: string;
|
||||||
|
};
|
||||||
@@ -94,3 +94,8 @@ tbody tr {
|
|||||||
.swiper-button-prev {
|
.swiper-button-prev {
|
||||||
color: white !important;
|
color: white !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.Toastify__toast {
|
||||||
|
direction: rtl;
|
||||||
|
font-family: "irancell" !important;
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ const Blog: FC = () => {
|
|||||||
return (
|
return (
|
||||||
<div className='xl:mt-24 mt-14 max-w-maxWidth mx-auto'>
|
<div className='xl:mt-24 mt-14 max-w-maxWidth mx-auto'>
|
||||||
<SectionHeader
|
<SectionHeader
|
||||||
title='بلاگ داناک'
|
title='مجله داناک'
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className='flex xl:flex-row flex-col gap-8 xl:mt-16 mt-10 items-center'>
|
<div className='flex xl:flex-row flex-col gap-8 xl:mt-16 mt-10 items-center'>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { Geist, Geist_Mono } from "next/font/google";
|
|||||||
import "swiper/css";
|
import "swiper/css";
|
||||||
import "./globals.css";
|
import "./globals.css";
|
||||||
import "@/assets/fonts/irancell/style.css";
|
import "@/assets/fonts/irancell/style.css";
|
||||||
|
import { ToastContainer } from 'react-toastify';
|
||||||
import Header from "@/shared/Header";
|
import Header from "@/shared/Header";
|
||||||
import Footer from "@/shared/Footer";
|
import Footer from "@/shared/Footer";
|
||||||
import SideBar from "@/shared/SideBar";
|
import SideBar from "@/shared/SideBar";
|
||||||
@@ -43,6 +44,7 @@ export default function RootLayout({
|
|||||||
<Footer />
|
<Footer />
|
||||||
</div>
|
</div>
|
||||||
<ReactQueryDevtools initialIsOpen={false} />
|
<ReactQueryDevtools initialIsOpen={false} />
|
||||||
|
<ToastContainer />
|
||||||
|
|
||||||
</QueryProvider>
|
</QueryProvider>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
'use client'
|
||||||
|
import { FC } from 'react'
|
||||||
|
import ServiceItem from '@/components/ServiceItem'
|
||||||
|
import { useGetDanakServiceSuggested } from './hooks/useProductData'
|
||||||
|
|
||||||
|
const DanakSuggestedService: FC = () => {
|
||||||
|
|
||||||
|
const { data } = useGetDanakServiceSuggested()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='max-w-maxWidth mx-auto xl:mt-20 mt-12'>
|
||||||
|
<h2 className='xl:text-2xl text-sm font-bold text-center xl:text-right'>
|
||||||
|
سرویس های پیشنهادی داناک
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<div className='xl:mt-14 mt-10 flex xl:flex-row flex-col gap-8'>
|
||||||
|
{
|
||||||
|
data?.data?.danakServices?.map((item) => {
|
||||||
|
return (
|
||||||
|
<ServiceItem key={item.id} item={item} />
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DanakSuggestedService
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
import { ArrowLeft } from 'iconsax-react'
|
import { ArrowLeft } from 'iconsax-react'
|
||||||
import Image from 'next/image'
|
import Image from 'next/image'
|
||||||
import { Swiper, SwiperSlide } from 'swiper/react'
|
import { Swiper, SwiperSlide } from 'swiper/react'
|
||||||
import DanakSuggestedService from '../home/DanakSuggestedService'
|
import DanakSuggestedService from './DanakSuggestedService'
|
||||||
import { FC } from 'react'
|
import { FC } from 'react'
|
||||||
import DanakServices from './DanakServices'
|
import DanakServices from './DanakServices'
|
||||||
|
|
||||||
@@ -7,11 +7,22 @@ export const useGetServicesByCategory = (categoryId?: string) =>
|
|||||||
queryFn: () => api.getServicesByCategory(categoryId),
|
queryFn: () => api.getServicesByCategory(categoryId),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const useGetDanakServiceSuggested = () =>
|
||||||
|
useQuery({
|
||||||
|
queryKey: ["danak-service-suggested"],
|
||||||
|
queryFn: () => api.getDanakServiceSuggested(),
|
||||||
|
});
|
||||||
|
|
||||||
export const servicesQueryOptions = {
|
export const servicesQueryOptions = {
|
||||||
queryKey: ["services", ""],
|
queryKey: ["services", ""],
|
||||||
queryFn: () => api.getServicesByCategory(undefined),
|
queryFn: () => api.getServicesByCategory(undefined),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const danakServiceSuggestedQueryOptions = {
|
||||||
|
queryKey: ["danak-service-suggested"],
|
||||||
|
queryFn: () => api.getDanakServiceSuggested(),
|
||||||
|
};
|
||||||
|
|
||||||
export const useGetCategories = () =>
|
export const useGetCategories = () =>
|
||||||
useQuery({
|
useQuery({
|
||||||
queryKey: ["service-categories"],
|
queryKey: ["service-categories"],
|
||||||
|
|||||||
@@ -2,12 +2,13 @@ import { NextPage } from 'next'
|
|||||||
import { HydrationBoundary } from '@tanstack/react-query'
|
import { HydrationBoundary } from '@tanstack/react-query'
|
||||||
import { dehydrate } from '@tanstack/react-query'
|
import { dehydrate } from '@tanstack/react-query'
|
||||||
import { QueryClient } from '@tanstack/react-query'
|
import { QueryClient } from '@tanstack/react-query'
|
||||||
import { categoriesQueryOptions, servicesQueryOptions } from './hooks/useProductData'
|
import { categoriesQueryOptions, danakServiceSuggestedQueryOptions, servicesQueryOptions } from './hooks/useProductData'
|
||||||
import Products from './Products'
|
import Products from './ProductsPage'
|
||||||
const ProductsPage: NextPage = async () => {
|
const ProductsPage: NextPage = async () => {
|
||||||
const queryClient = new QueryClient()
|
const queryClient = new QueryClient()
|
||||||
await queryClient.prefetchQuery(servicesQueryOptions)
|
await queryClient.prefetchQuery(servicesQueryOptions)
|
||||||
await queryClient.prefetchQuery(categoriesQueryOptions)
|
await queryClient.prefetchQuery(categoriesQueryOptions)
|
||||||
|
await queryClient.prefetchQuery(danakServiceSuggestedQueryOptions)
|
||||||
return (
|
return (
|
||||||
<HydrationBoundary state={dehydrate(queryClient)}>
|
<HydrationBoundary state={dehydrate(queryClient)}>
|
||||||
<Products />
|
<Products />
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
import axios from "@/config/axios";
|
import axios from "@/config/axios";
|
||||||
import { CategoryResponse, ServiceResponse } from "../types/ProductTypes";
|
import {
|
||||||
|
CategoryResponse,
|
||||||
|
DanakServiceSuggestedResponse,
|
||||||
|
ServiceResponse,
|
||||||
|
} from "../types/ProductTypes";
|
||||||
|
|
||||||
export const getServicesByCategory = async (categoryId?: string) => {
|
export const getServicesByCategory = async (categoryId?: string) => {
|
||||||
let query = ``;
|
let query = ``;
|
||||||
@@ -18,3 +22,10 @@ export const getCategoriesPublic = async () => {
|
|||||||
);
|
);
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getDanakServiceSuggested = async () => {
|
||||||
|
const { data } = await axios.get<DanakServiceSuggestedResponse>(
|
||||||
|
`/danak-services/suggested`
|
||||||
|
);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|||||||
@@ -21,3 +21,7 @@ export type ServiceCategoryType = {
|
|||||||
parentId: string | null;
|
parentId: string | null;
|
||||||
deletedAt: string | null;
|
deletedAt: string | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type DanakServiceSuggestedResponse = ApiResponse<{
|
||||||
|
danakServices: DanakSuggestService[];
|
||||||
|
}>;
|
||||||
|
|||||||
@@ -25,8 +25,7 @@ const BlogItem: FC<Props> = ({ item }) => {
|
|||||||
{item.title}
|
{item.title}
|
||||||
</h6>
|
</h6>
|
||||||
|
|
||||||
<p className='mt-4 text-sm'>
|
<p className='mt-4 text-sm' dangerouslySetInnerHTML={{ __html: item.previewContent }}>
|
||||||
{item.previewContent}
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ const SideBar: FC = () => {
|
|||||||
|
|
||||||
<SideBarItem
|
<SideBarItem
|
||||||
icon={<DocumentText variant={isActive('blogs') ? 'Bold' : 'Outline'} color={isActive('blogs') ? 'black' : '#8C90A3'} size={iconSizeSideBar} />}
|
icon={<DocumentText variant={isActive('blogs') ? 'Bold' : 'Outline'} color={isActive('blogs') ? 'black' : '#8C90A3'} size={iconSizeSideBar} />}
|
||||||
title={'بلاگ'}
|
title={'مجله'}
|
||||||
isActive={isActive('blogs')}
|
isActive={isActive('blogs')}
|
||||||
link={'/blogs'}
|
link={'/blogs'}
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user