api attachment

This commit is contained in:
hamid zarghami
2025-08-20 12:09:10 +03:30
parent dda986d06d
commit d4eda49cd3
10 changed files with 561 additions and 34 deletions
+1
View File
@@ -0,0 +1 @@
VITE_API_BASE_URL = 'https://api.danakcorp.com'
+307
View File
@@ -9,6 +9,8 @@
"version": "0.0.0",
"dependencies": {
"@tailwindcss/vite": "^4.1.12",
"@tanstack/react-query": "^5.85.5",
"axios": "^1.11.0",
"iconsax-reactjs": "^0.0.8",
"react": "^19.1.1",
"react-dom": "^19.1.1",
@@ -1585,6 +1587,32 @@
"vite": "^5.2.0 || ^6 || ^7"
}
},
"node_modules/@tanstack/query-core": {
"version": "5.85.5",
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.85.5.tgz",
"integrity": "sha512-KO0WTob4JEApv69iYp1eGvfMSUkgw//IpMnq+//cORBzXf0smyRwPLrUvEe5qtAEGjwZTXrjxg+oJNP/C00t6w==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
}
},
"node_modules/@tanstack/react-query": {
"version": "5.85.5",
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.85.5.tgz",
"integrity": "sha512-/X4EFNcnPiSs8wM2v+b6DqS5mmGeuJQvxBglmDxl6ZQb5V26ouD2SJYAcC3VjbNwqhY2zjxVD15rDA5nGbMn3A==",
"license": "MIT",
"dependencies": {
"@tanstack/query-core": "5.85.5"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
},
"peerDependencies": {
"react": "^18 || ^19"
}
},
"node_modules/@types/babel__core": {
"version": "7.20.5",
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
@@ -2018,6 +2046,23 @@
"dev": true,
"license": "Python-2.0"
},
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
"license": "MIT"
},
"node_modules/axios": {
"version": "1.11.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.11.0.tgz",
"integrity": "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==",
"license": "MIT",
"dependencies": {
"follow-redirects": "^1.15.6",
"form-data": "^4.0.4",
"proxy-from-env": "^1.1.0"
}
},
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
@@ -2082,6 +2127,19 @@
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
}
},
"node_modules/call-bind-apply-helpers": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"function-bind": "^1.1.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/callsites": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
@@ -2159,6 +2217,18 @@
"dev": true,
"license": "MIT"
},
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"license": "MIT",
"dependencies": {
"delayed-stream": "~1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@@ -2229,6 +2299,15 @@
"dev": true,
"license": "MIT"
},
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
"license": "MIT",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/detect-libc": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz",
@@ -2238,6 +2317,20 @@
"node": ">=8"
}
},
"node_modules/dunder-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.1",
"es-errors": "^1.3.0",
"gopd": "^1.2.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/electron-to-chromium": {
"version": "1.5.207",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.207.tgz",
@@ -2258,6 +2351,51 @@
"node": ">=10.13.0"
}
},
"node_modules/es-define-property": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-errors": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-object-atoms": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-set-tostringtag": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"get-intrinsic": "^1.2.6",
"has-tostringtag": "^1.0.2",
"hasown": "^2.0.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/esbuild": {
"version": "0.25.9",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz",
@@ -2625,6 +2763,42 @@
"dev": true,
"license": "ISC"
},
"node_modules/follow-redirects": {
"version": "1.15.11",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
"integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/RubenVerborgh"
}
],
"license": "MIT",
"engines": {
"node": ">=4.0"
},
"peerDependenciesMeta": {
"debug": {
"optional": true
}
}
},
"node_modules/form-data": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
"integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
"license": "MIT",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"es-set-tostringtag": "^2.1.0",
"hasown": "^2.0.2",
"mime-types": "^2.1.12"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/fsevents": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
@@ -2639,6 +2813,15 @@
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/function-bind": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/gensync": {
"version": "1.0.0-beta.2",
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
@@ -2649,6 +2832,43 @@
"node": ">=6.9.0"
}
},
"node_modules/get-intrinsic": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.2",
"es-define-property": "^1.0.1",
"es-errors": "^1.3.0",
"es-object-atoms": "^1.1.1",
"function-bind": "^1.1.2",
"get-proto": "^1.0.1",
"gopd": "^1.2.0",
"has-symbols": "^1.1.0",
"hasown": "^2.0.2",
"math-intrinsics": "^1.1.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/get-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
"license": "MIT",
"dependencies": {
"dunder-proto": "^1.0.1",
"es-object-atoms": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/glob-parent": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
@@ -2675,6 +2895,18 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/gopd": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/graceful-fs": {
"version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
@@ -2698,6 +2930,45 @@
"node": ">=8"
}
},
"node_modules/has-symbols": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-tostringtag": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
"license": "MIT",
"dependencies": {
"has-symbols": "^1.0.3"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/hasown": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
"license": "MIT",
"dependencies": {
"function-bind": "^1.1.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/iconsax-reactjs": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/iconsax-reactjs/-/iconsax-reactjs-0.0.8.tgz",
@@ -3154,6 +3425,15 @@
"@jridgewell/sourcemap-codec": "^1.5.0"
}
},
"node_modules/math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/merge2": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
@@ -3178,6 +3458,27 @@
"node": ">=8.6"
}
},
"node_modules/mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/mime-types": {
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"license": "MIT",
"dependencies": {
"mime-db": "1.52.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
@@ -3406,6 +3707,12 @@
"node": ">= 0.8.0"
}
},
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
"license": "MIT"
},
"node_modules/punycode": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+2
View File
@@ -11,6 +11,8 @@
},
"dependencies": {
"@tailwindcss/vite": "^4.1.12",
"@tanstack/react-query": "^5.85.5",
"axios": "^1.11.0",
"iconsax-reactjs": "^0.0.8",
"react": "^19.1.1",
"react-dom": "^19.1.1",
+8 -3
View File
@@ -2,13 +2,18 @@ import { type FC } from 'react'
import './assets/fonts/irancell/style.css'
import { BrowserRouter, Route, Routes } from 'react-router-dom'
import Home from './Pages/Home/Home'
import { QueryClientProvider } from '@tanstack/react-query'
import { QueryClient } from '@tanstack/react-query'
const queryClient = new QueryClient()
const App: FC = () => {
return (
<BrowserRouter>
<Routes>
<Route path='/:id' element={<Home />} />
</Routes>
<QueryClientProvider client={queryClient}>
<Routes>
<Route path='/:id' element={<Home />} />
</Routes>
</QueryClientProvider>
</BrowserRouter>
)
}
+60 -5
View File
@@ -1,26 +1,81 @@
import { type FC } from 'react'
import Sidebar from './components/Sidebar'
import { MessageQuestion } from 'iconsax-reactjs'
import HelpItem from './components/HelpItem'
import { useParams } from 'react-router-dom'
import { useGetHelp } from './hooks/useHomeData'
interface Guide {
id: string;
title: string;
description: string;
content: string;
order: number;
isActive: boolean;
service: {
id: string;
name: string;
title: string;
description: string;
slug: string;
};
}
interface HelpItemData {
stepNumber: number;
title: string;
description: string;
content?: string;
id: string;
}
const Home: FC = () => {
const { id } = useParams()
const { data } = useGetHelp(id || '')
// اگر داده‌ای وجود ندارد، از داده‌های پیش‌فرض استفاده کن
const guides: Guide[] = data?.data?.guides || []
const service = guides[0]?.service
const helpItems: HelpItemData[] = guides.length > 0 ? guides.map((guide: Guide, index: number) => ({
stepNumber: index + 1,
title: guide.title,
description: guide.description,
content: guide.content,
id: guide.id
})) : [];
return (
<div className='p-8 flex gap-8'>
<Sidebar />
<Sidebar guides={guides} service={service} />
<div className='w-[280px]'></div>
<div className='flex-1'>
<div className='flex gap-3 items-center'>
<div className='flex gap-3 items-center mb-8'>
<MessageQuestion variant='Bold' size={40} color='#0038FF' />
<div>
<div className='font-bold'>
شروع سریع
شروع سریع با {service?.name}
</div>
<div className='text-sm mt-3'>
این راهنما شما را با قابلیتهای اصلی سیستم آشنا میکند تا بتوانید ارتباطات سازمانی خود را به شکلی سریع، امن و منظم مدیریت کنید. تنها در چند گام، آماده استفاده کامل از دیمیل خواهید بود.
<div className='text-sm mt-3 text-gray-600 max-w-2xl'>
{service?.description}
</div>
</div>
</div>
<div className='space-y-6'>
{helpItems.map((item: HelpItemData) => (
<HelpItem
key={item.stepNumber}
stepNumber={item.stepNumber}
title={item.title}
description={item.description}
content={item.content}
id={item.id}
/>
))}
</div>
</div>
</div>
)
+44 -6
View File
@@ -1,9 +1,47 @@
import { type FC } from 'react'
import React from 'react';
const HelpItem: FC = () => {
return (
<div>HelpItem</div>
)
interface HelpItemProps {
stepNumber: number;
title: string;
description: string;
content?: string;
id: string;
}
export default HelpItem
const HelpItem: React.FC<HelpItemProps> = ({ stepNumber, title, description, content, id }) => {
const backgroundColors = [
'bg-blue-400',
'bg-green-400',
'bg-purple-400',
'bg-pink-400',
'bg-indigo-400',
'bg-teal-400',
'bg-orange-400',
'bg-red-400',
'bg-yellow-400',
'bg-cyan-400'
];
const randomColor = backgroundColors[stepNumber % backgroundColors.length];
return (
<div id={id} className="bg-white rounded-2xl p-6">
<div className="flex items-center gap-3 mb-3">
<div className={`${randomColor} text-white rounded-full pt-1 size-10 font-bold flex items-center justify-center`}>
{stepNumber}
</div>
<h3 className="">{title}</h3>
</div>
<p className="text-sm mb-3">
{description}
</p>
{content && (
<div className="text-sm text-gray-600 leading-relaxed">
<div dangerouslySetInnerHTML={{ __html: content }} />
</div>
)}
</div>
);
};
export default HelpItem;
+105 -20
View File
@@ -1,29 +1,114 @@
import { type FC } from 'react'
import { type FC, useState, useEffect } from 'react'
interface Service {
id: string;
name: string;
title: string;
description: string;
slug: string;
}
interface Guide {
id: string;
title: string;
description: string;
content: string;
order: number;
isActive: boolean;
}
interface SidebarProps {
guides: Guide[];
service?: Service;
}
const Sidebar: FC<SidebarProps> = ({ guides }) => {
const [activeGuideId, setActiveGuideId] = useState<string>('')
useEffect(() => {
const handleScroll = () => {
const guideElements = guides.map(guide => ({
id: guide.id,
element: document.getElementById(guide.id)
}))
let foundActive = false
for (const guide of guideElements) {
if (guide.element) {
const rect = guide.element.getBoundingClientRect()
// اگر element در viewport باشد
if (rect.top <= 150 && rect.bottom >= 150) {
setActiveGuideId(guide.id)
foundActive = true
break
}
}
}
// اگر هیچ element فعالی پیدا نشد، آخرین element را فعال کن
if (!foundActive && guideElements.length > 0) {
const lastGuide = guideElements[guideElements.length - 1]
if (lastGuide.element) {
const rect = lastGuide.element.getBoundingClientRect()
if (rect.top < 150) {
setActiveGuideId(lastGuide.id)
}
}
}
}
window.addEventListener('scroll', handleScroll)
// اجرای اولیه
setTimeout(handleScroll, 100)
return () => {
window.removeEventListener('scroll', handleScroll)
}
}, [guides])
const handleGuideClick = (guideId: string) => {
const element = document.getElementById(guideId)
if (element) {
// اسکرول به element با offset برای header
const offsetTop = element.offsetTop - 100
window.scrollTo({
top: offsetTop,
behavior: 'smooth'
})
// تنظیم active state
setActiveGuideId(guideId)
}
}
const Sidebar: FC = () => {
return (
<div className='bg-white top-8 bottom-8 fixed p-8 w-[280px] rounded-4xl right-8'>
<div className='bg-white top-8 bottom-8 fixed p-8 w-[280px] rounded-4xl right-8 flex flex-col'>
<div className='font-bold'>
لیست محتوا
</div>
<div className='mt-10 flex flex-col gap-8'>
<div className={`border-r-[3px] border-[#A8ABBF] pr-4`}>
<div className='text-sm font-bold'>
خوشآمدگویی
</div>
<div className='mt-3 text-[#616474] text-sm'>
معرفی کلی دیمیل
</div>
</div>
<div className={`border-r-[3px] border-[#A8ABBF] pr-4`}>
<div className='text-sm font-bold'>
خوشآمدگویی
</div>
<div className='mt-3 text-[#616474] text-sm'>
معرفی کلی دیمیل
</div>
</div>
<div className='mt-10 flex flex-col gap-8 overflow-y-auto flex-1 pr-2'>
{guides.length > 0 ? (
guides.map((guide) => (
<div
key={guide.id}
className={`border-r-[3px] pr-4 cursor-pointer transition-all duration-300 ${activeGuideId === guide.id
? 'border-black'
: 'border-[#A8ABBF]'
}`}
onClick={() => handleGuideClick(guide.id)}
>
<div className='text-sm font-bold'>
{guide.title}
</div>
<div className='mt-3 text-[#616474] text-sm'>
{guide.description}
</div>
</div>
))
) : null}
</div>
</div>
)
+10
View File
@@ -0,0 +1,10 @@
import { useQuery } from "@tanstack/react-query";
import { getHelp } from "../service/Service";
export const useGetHelp = (id: string) => {
return useQuery({
queryKey: ["help", id],
queryFn: () => getHelp(id),
enabled: !!id,
});
};
+6
View File
@@ -0,0 +1,6 @@
import axios from "../../../config/axios";
export const getHelp = async (id: string) => {
const { data } = await axios.get(`/danak-services/${id}/guides`);
return data;
};
+18
View File
@@ -0,0 +1,18 @@
import axios from "axios";
const axiosInstance = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL,
});
axiosInstance.interceptors.response.use(
(response) => response,
(error) => {
return Promise.reject(error);
}
);
axiosInstance.interceptors.request.use(async function (config) {
return config;
});
export default axiosInstance;