feat: implement roadmap generator

pull/5267/head
Arik Chakma 11 months ago
parent 37ffc2cc62
commit 69df6d906b
  1. 2
      package.json
  2. 131
      pnpm-lock.yaml
  3. 53
      src/components/GenerateRoadmap/GenerateRoadmap.css
  4. 80
      src/components/GenerateRoadmap/GenerateRoadmap.tsx
  5. 8
      src/pages/ai/index.astro
  6. 3
      tsconfig.json

@ -46,10 +46,12 @@
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"reactflow": "^11.10.4", "reactflow": "^11.10.4",
"rehype-external-links": "^3.0.0", "rehype-external-links": "^3.0.0",
"remark-parse": "^11.0.0",
"roadmap-renderer": "^1.0.6", "roadmap-renderer": "^1.0.6",
"slugify": "^1.6.6", "slugify": "^1.6.6",
"tailwind-merge": "^2.2.1", "tailwind-merge": "^2.2.1",
"tailwindcss": "^3.4.1", "tailwindcss": "^3.4.1",
"unified": "^11.0.4",
"zustand": "^4.5.1" "zustand": "^4.5.1"
}, },
"devDependencies": { "devDependencies": {

@ -7,7 +7,7 @@ settings:
dependencies: dependencies:
'@astrojs/react': '@astrojs/react':
specifier: ^3.0.10 specifier: ^3.0.10
version: 3.0.10(@types/react-dom@18.2.19)(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0)(vite@5.0.12) version: 3.0.10(@types/react-dom@18.2.19)(@types/react@18.2.59)(react-dom@18.2.0)(react@18.2.0)(vite@5.1.3)
'@astrojs/sitemap': '@astrojs/sitemap':
specifier: ^3.0.5 specifier: ^3.0.5
version: 3.0.5 version: 3.0.5
@ -21,8 +21,8 @@ dependencies:
specifier: ^0.7.1 specifier: ^0.7.1
version: 0.7.1(nanostores@0.9.5)(react@18.2.0) version: 0.7.1(nanostores@0.9.5)(react@18.2.0)
'@types/react': '@types/react':
specifier: ^18.2.55 specifier: ^18.2.56
version: 18.2.55 version: 18.2.59
'@types/react-dom': '@types/react-dom':
specifier: ^18.2.19 specifier: ^18.2.19
version: 18.2.19 version: 18.2.19
@ -45,8 +45,8 @@ dependencies:
specifier: ^3.0.5 specifier: ^3.0.5
version: 3.0.5 version: 3.0.5
lucide-react: lucide-react:
specifier: ^0.331.0 specifier: ^0.334.0
version: 0.331.0(react@18.2.0) version: 0.334.0(react@18.2.0)
nanoid: nanoid:
specifier: ^5.0.5 specifier: ^5.0.5
version: 5.0.5 version: 5.0.5
@ -73,10 +73,13 @@ dependencies:
version: 18.2.0(react@18.2.0) version: 18.2.0(react@18.2.0)
reactflow: reactflow:
specifier: ^11.10.4 specifier: ^11.10.4
version: 11.10.4(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0) version: 11.10.4(@types/react@18.2.59)(react-dom@18.2.0)(react@18.2.0)
rehype-external-links: rehype-external-links:
specifier: ^3.0.0 specifier: ^3.0.0
version: 3.0.0 version: 3.0.0
remark-parse:
specifier: ^11.0.0
version: 11.0.0
roadmap-renderer: roadmap-renderer:
specifier: ^1.0.6 specifier: ^1.0.6
version: 1.0.6 version: 1.0.6
@ -89,9 +92,12 @@ dependencies:
tailwindcss: tailwindcss:
specifier: ^3.4.1 specifier: ^3.4.1
version: 3.4.1 version: 3.4.1
unified:
specifier: ^11.0.4
version: 11.0.4
zustand: zustand:
specifier: ^4.5.0 specifier: ^4.5.1
version: 4.5.0(@types/react@18.2.55)(react@18.2.0) version: 4.5.1(@types/react@18.2.59)(react@18.2.0)
devDependencies: devDependencies:
'@playwright/test': '@playwright/test':
@ -185,7 +191,7 @@ packages:
prismjs: 1.29.0 prismjs: 1.29.0
dev: false dev: false
/@astrojs/react@3.0.10(@types/react-dom@18.2.19)(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0)(vite@5.0.12): /@astrojs/react@3.0.10(@types/react-dom@18.2.19)(@types/react@18.2.59)(react-dom@18.2.0)(react@18.2.0)(vite@5.1.3):
resolution: {integrity: sha512-uGRIwKMAn7tva2vxXMyoVIGxWFr0rjZ8ZWIlkTG/vIpnAjD2nM8Cz6B8j7yzj176jvl6gZ6xTbTVPm09aeK0Yw==} resolution: {integrity: sha512-uGRIwKMAn7tva2vxXMyoVIGxWFr0rjZ8ZWIlkTG/vIpnAjD2nM8Cz6B8j7yzj176jvl6gZ6xTbTVPm09aeK0Yw==}
engines: {node: '>=18.14.1'} engines: {node: '>=18.14.1'}
peerDependencies: peerDependencies:
@ -194,9 +200,9 @@ packages:
react: ^17.0.2 || ^18.0.0 react: ^17.0.2 || ^18.0.0
react-dom: ^17.0.2 || ^18.0.0 react-dom: ^17.0.2 || ^18.0.0
dependencies: dependencies:
'@types/react': 18.2.55 '@types/react': 18.2.59
'@types/react-dom': 18.2.19 '@types/react-dom': 18.2.19
'@vitejs/plugin-react': 4.2.1(vite@5.0.12) '@vitejs/plugin-react': 4.2.1(vite@5.1.3)
react: 18.2.0 react: 18.2.0
react-dom: 18.2.0(react@18.2.0) react-dom: 18.2.0(react@18.2.0)
ultrahtml: 1.5.2 ultrahtml: 1.5.2
@ -1102,39 +1108,39 @@ packages:
config-chain: 1.1.13 config-chain: 1.1.13
dev: false dev: false
/@reactflow/background@11.3.9(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0): /@reactflow/background@11.3.9(@types/react@18.2.59)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-byj/G9pEC8tN0wT/ptcl/LkEP/BBfa33/SvBkqE4XwyofckqF87lKp573qGlisfnsijwAbpDlf81PuFL41So4Q==} resolution: {integrity: sha512-byj/G9pEC8tN0wT/ptcl/LkEP/BBfa33/SvBkqE4XwyofckqF87lKp573qGlisfnsijwAbpDlf81PuFL41So4Q==}
peerDependencies: peerDependencies:
react: '>=17' react: '>=17'
react-dom: '>=17' react-dom: '>=17'
dependencies: dependencies:
'@reactflow/core': 11.10.4(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0) '@reactflow/core': 11.10.4(@types/react@18.2.59)(react-dom@18.2.0)(react@18.2.0)
classcat: 5.0.4 classcat: 5.0.4
react: 18.2.0 react: 18.2.0
react-dom: 18.2.0(react@18.2.0) react-dom: 18.2.0(react@18.2.0)
zustand: 4.5.0(@types/react@18.2.55)(react@18.2.0) zustand: 4.5.1(@types/react@18.2.59)(react@18.2.0)
transitivePeerDependencies: transitivePeerDependencies:
- '@types/react' - '@types/react'
- immer - immer
dev: false dev: false
/@reactflow/controls@11.2.9(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0): /@reactflow/controls@11.2.9(@types/react@18.2.59)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-e8nWplbYfOn83KN1BrxTXS17+enLyFnjZPbyDgHSRLtI5ZGPKF/8iRXV+VXb2LFVzlu4Wh3la/pkxtfP/0aguA==} resolution: {integrity: sha512-e8nWplbYfOn83KN1BrxTXS17+enLyFnjZPbyDgHSRLtI5ZGPKF/8iRXV+VXb2LFVzlu4Wh3la/pkxtfP/0aguA==}
peerDependencies: peerDependencies:
react: '>=17' react: '>=17'
react-dom: '>=17' react-dom: '>=17'
dependencies: dependencies:
'@reactflow/core': 11.10.4(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0) '@reactflow/core': 11.10.4(@types/react@18.2.59)(react-dom@18.2.0)(react@18.2.0)
classcat: 5.0.4 classcat: 5.0.4
react: 18.2.0 react: 18.2.0
react-dom: 18.2.0(react@18.2.0) react-dom: 18.2.0(react@18.2.0)
zustand: 4.5.0(@types/react@18.2.55)(react@18.2.0) zustand: 4.5.1(@types/react@18.2.59)(react@18.2.0)
transitivePeerDependencies: transitivePeerDependencies:
- '@types/react' - '@types/react'
- immer - immer
dev: false dev: false
/@reactflow/core@11.10.4(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0): /@reactflow/core@11.10.4(@types/react@18.2.59)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-j3i9b2fsTX/sBbOm+RmNzYEFWbNx4jGWGuGooh2r1jQaE2eV+TLJgiG/VNOp0q5mBl9f6g1IXs3Gm86S9JfcGw==} resolution: {integrity: sha512-j3i9b2fsTX/sBbOm+RmNzYEFWbNx4jGWGuGooh2r1jQaE2eV+TLJgiG/VNOp0q5mBl9f6g1IXs3Gm86S9JfcGw==}
peerDependencies: peerDependencies:
react: '>=17' react: '>=17'
@ -1150,19 +1156,19 @@ packages:
d3-zoom: 3.0.0 d3-zoom: 3.0.0
react: 18.2.0 react: 18.2.0
react-dom: 18.2.0(react@18.2.0) react-dom: 18.2.0(react@18.2.0)
zustand: 4.5.0(@types/react@18.2.55)(react@18.2.0) zustand: 4.5.1(@types/react@18.2.59)(react@18.2.0)
transitivePeerDependencies: transitivePeerDependencies:
- '@types/react' - '@types/react'
- immer - immer
dev: false dev: false
/@reactflow/minimap@11.7.9(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0): /@reactflow/minimap@11.7.9(@types/react@18.2.59)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-le95jyTtt3TEtJ1qa7tZ5hyM4S7gaEQkW43cixcMOZLu33VAdc2aCpJg/fXcRrrf7moN2Mbl9WIMNXUKsp5ILA==} resolution: {integrity: sha512-le95jyTtt3TEtJ1qa7tZ5hyM4S7gaEQkW43cixcMOZLu33VAdc2aCpJg/fXcRrrf7moN2Mbl9WIMNXUKsp5ILA==}
peerDependencies: peerDependencies:
react: '>=17' react: '>=17'
react-dom: '>=17' react-dom: '>=17'
dependencies: dependencies:
'@reactflow/core': 11.10.4(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0) '@reactflow/core': 11.10.4(@types/react@18.2.59)(react-dom@18.2.0)(react@18.2.0)
'@types/d3-selection': 3.0.10 '@types/d3-selection': 3.0.10
'@types/d3-zoom': 3.0.8 '@types/d3-zoom': 3.0.8
classcat: 5.0.4 classcat: 5.0.4
@ -1170,41 +1176,41 @@ packages:
d3-zoom: 3.0.0 d3-zoom: 3.0.0
react: 18.2.0 react: 18.2.0
react-dom: 18.2.0(react@18.2.0) react-dom: 18.2.0(react@18.2.0)
zustand: 4.5.0(@types/react@18.2.55)(react@18.2.0) zustand: 4.5.1(@types/react@18.2.59)(react@18.2.0)
transitivePeerDependencies: transitivePeerDependencies:
- '@types/react' - '@types/react'
- immer - immer
dev: false dev: false
/@reactflow/node-resizer@2.2.9(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0): /@reactflow/node-resizer@2.2.9(@types/react@18.2.59)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-HfickMm0hPDIHt9qH997nLdgLt0kayQyslKE0RS/GZvZ4UMQJlx/NRRyj5y47Qyg0NnC66KYOQWDM9LLzRTnUg==} resolution: {integrity: sha512-HfickMm0hPDIHt9qH997nLdgLt0kayQyslKE0RS/GZvZ4UMQJlx/NRRyj5y47Qyg0NnC66KYOQWDM9LLzRTnUg==}
peerDependencies: peerDependencies:
react: '>=17' react: '>=17'
react-dom: '>=17' react-dom: '>=17'
dependencies: dependencies:
'@reactflow/core': 11.10.4(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0) '@reactflow/core': 11.10.4(@types/react@18.2.59)(react-dom@18.2.0)(react@18.2.0)
classcat: 5.0.4 classcat: 5.0.4
d3-drag: 3.0.0 d3-drag: 3.0.0
d3-selection: 3.0.0 d3-selection: 3.0.0
react: 18.2.0 react: 18.2.0
react-dom: 18.2.0(react@18.2.0) react-dom: 18.2.0(react@18.2.0)
zustand: 4.5.0(@types/react@18.2.55)(react@18.2.0) zustand: 4.5.1(@types/react@18.2.59)(react@18.2.0)
transitivePeerDependencies: transitivePeerDependencies:
- '@types/react' - '@types/react'
- immer - immer
dev: false dev: false
/@reactflow/node-toolbar@1.3.9(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0): /@reactflow/node-toolbar@1.3.9(@types/react@18.2.59)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-VmgxKmToax4sX1biZ9LXA7cj/TBJ+E5cklLGwquCCVVxh+lxpZGTBF3a5FJGVHiUNBBtFsC8ldcSZIK4cAlQww==} resolution: {integrity: sha512-VmgxKmToax4sX1biZ9LXA7cj/TBJ+E5cklLGwquCCVVxh+lxpZGTBF3a5FJGVHiUNBBtFsC8ldcSZIK4cAlQww==}
peerDependencies: peerDependencies:
react: '>=17' react: '>=17'
react-dom: '>=17' react-dom: '>=17'
dependencies: dependencies:
'@reactflow/core': 11.10.4(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0) '@reactflow/core': 11.10.4(@types/react@18.2.59)(react-dom@18.2.0)(react@18.2.0)
classcat: 5.0.4 classcat: 5.0.4
react: 18.2.0 react: 18.2.0
react-dom: 18.2.0(react@18.2.0) react-dom: 18.2.0(react@18.2.0)
zustand: 4.5.0(@types/react@18.2.55)(react@18.2.0) zustand: 4.5.1(@types/react@18.2.59)(react@18.2.0)
transitivePeerDependencies: transitivePeerDependencies:
- '@types/react' - '@types/react'
- immer - immer
@ -1700,11 +1706,11 @@ packages:
/@types/react-dom@18.2.19: /@types/react-dom@18.2.19:
resolution: {integrity: sha512-aZvQL6uUbIJpjZk4U8JZGbau9KDeAwMfmhyWorxgBkqDIEf6ROjRozcmPIicqsUwPUjbkDfHKgGee1Lq65APcA==} resolution: {integrity: sha512-aZvQL6uUbIJpjZk4U8JZGbau9KDeAwMfmhyWorxgBkqDIEf6ROjRozcmPIicqsUwPUjbkDfHKgGee1Lq65APcA==}
dependencies: dependencies:
'@types/react': 18.2.55 '@types/react': 18.2.59
dev: false dev: false
/@types/react@18.2.55: /@types/react@18.2.59:
resolution: {integrity: sha512-Y2Tz5P4yz23brwm2d7jNon39qoAtMMmalOQv6+fEFt1mT+FcM3D841wDpoUvFXhaYenuROCy3FZYqdTjM7qVyA==} resolution: {integrity: sha512-DE+F6BYEC8VtajY85Qr7mmhTd/79rJKIHCg99MU9SWPB4xvLb6D1za2vYflgZfmPqQVEr6UqJTnLXEwzpVPuOg==}
dependencies: dependencies:
'@types/prop-types': 15.7.11 '@types/prop-types': 15.7.11
'@types/scheduler': 0.16.8 '@types/scheduler': 0.16.8
@ -1733,7 +1739,7 @@ packages:
resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==}
dev: false dev: false
/@vitejs/plugin-react@4.2.1(vite@5.0.12): /@vitejs/plugin-react@4.2.1(vite@5.1.3):
resolution: {integrity: sha512-oojO9IDc4nCUUi8qIR11KoQm0XFFLIwsRBwHRR4d/88IWghn1y6ckz/bJ8GHDCsYEJee8mDzqtJxh15/cisJNQ==} resolution: {integrity: sha512-oojO9IDc4nCUUi8qIR11KoQm0XFFLIwsRBwHRR4d/88IWghn1y6ckz/bJ8GHDCsYEJee8mDzqtJxh15/cisJNQ==}
engines: {node: ^14.18.0 || >=16.0.0} engines: {node: ^14.18.0 || >=16.0.0}
peerDependencies: peerDependencies:
@ -1744,7 +1750,7 @@ packages:
'@babel/plugin-transform-react-jsx-source': 7.23.3(@babel/core@7.23.7) '@babel/plugin-transform-react-jsx-source': 7.23.3(@babel/core@7.23.7)
'@types/babel__core': 7.20.5 '@types/babel__core': 7.20.5
react-refresh: 0.14.0 react-refresh: 0.14.0
vite: 5.0.12 vite: 5.1.3
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
dev: false dev: false
@ -3996,8 +4002,8 @@ packages:
engines: {node: '>=12'} engines: {node: '>=12'}
dev: false dev: false
/lucide-react@0.331.0(react@18.2.0): /lucide-react@0.334.0(react@18.2.0):
resolution: {integrity: sha512-CHFJ0ve9vaZ7bB2VRAl27SlX1ELh6pfNC0jS96qGpPEEzLkLDGq4pDBFU8RhOoRMqsjXqTzLm9U6bZ1OcIHq7Q==} resolution: {integrity: sha512-y0Rv/Xx6qAq4FutZ3L/efl3O9vl6NC/1p0YOg6mBfRbQ4k1JCE2rz0rnV7WC8Moxq1RY99vLATvjcqUegGJTvA==}
peerDependencies: peerDependencies:
react: ^16.5.1 || ^17.0.0 || ^18.0.0 react: ^16.5.1 || ^17.0.0 || ^18.0.0
dependencies: dependencies:
@ -5543,18 +5549,18 @@ packages:
loose-envify: 1.4.0 loose-envify: 1.4.0
dev: false dev: false
/reactflow@11.10.4(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0): /reactflow@11.10.4(@types/react@18.2.59)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-0CApYhtYicXEDg/x2kvUHiUk26Qur8lAtTtiSlptNKuyEuGti6P1y5cS32YGaUoDMoCqkm/m+jcKkfMOvSCVRA==} resolution: {integrity: sha512-0CApYhtYicXEDg/x2kvUHiUk26Qur8lAtTtiSlptNKuyEuGti6P1y5cS32YGaUoDMoCqkm/m+jcKkfMOvSCVRA==}
peerDependencies: peerDependencies:
react: '>=17' react: '>=17'
react-dom: '>=17' react-dom: '>=17'
dependencies: dependencies:
'@reactflow/background': 11.3.9(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0) '@reactflow/background': 11.3.9(@types/react@18.2.59)(react-dom@18.2.0)(react@18.2.0)
'@reactflow/controls': 11.2.9(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0) '@reactflow/controls': 11.2.9(@types/react@18.2.59)(react-dom@18.2.0)(react@18.2.0)
'@reactflow/core': 11.10.4(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0) '@reactflow/core': 11.10.4(@types/react@18.2.59)(react-dom@18.2.0)(react@18.2.0)
'@reactflow/minimap': 11.7.9(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0) '@reactflow/minimap': 11.7.9(@types/react@18.2.59)(react-dom@18.2.0)(react@18.2.0)
'@reactflow/node-resizer': 2.2.9(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0) '@reactflow/node-resizer': 2.2.9(@types/react@18.2.59)(react-dom@18.2.0)(react@18.2.0)
'@reactflow/node-toolbar': 1.3.9(@types/react@18.2.55)(react-dom@18.2.0)(react@18.2.0) '@reactflow/node-toolbar': 1.3.9(@types/react@18.2.59)(react-dom@18.2.0)(react@18.2.0)
react: 18.2.0 react: 18.2.0
react-dom: 18.2.0(react@18.2.0) react-dom: 18.2.0(react@18.2.0)
transitivePeerDependencies: transitivePeerDependencies:
@ -6745,41 +6751,6 @@ packages:
vfile-message: 4.0.2 vfile-message: 4.0.2
dev: false dev: false
/vite@5.0.12:
resolution: {integrity: sha512-4hsnEkG3q0N4Tzf1+t6NdN9dg/L3BM+q8SWgbSPnJvrgH2kgdyzfVJwbR1ic69/4uMJJ/3dqDZZE5/WwqW8U1w==}
engines: {node: ^18.0.0 || >=20.0.0}
hasBin: true
peerDependencies:
'@types/node': ^18.0.0 || >=20.0.0
less: '*'
lightningcss: ^1.21.0
sass: '*'
stylus: '*'
sugarss: '*'
terser: ^5.4.0
peerDependenciesMeta:
'@types/node':
optional: true
less:
optional: true
lightningcss:
optional: true
sass:
optional: true
stylus:
optional: true
sugarss:
optional: true
terser:
optional: true
dependencies:
esbuild: 0.19.11
postcss: 8.4.33
rollup: 4.9.6
optionalDependencies:
fsevents: 2.3.3
dev: false
/vite@5.1.3: /vite@5.1.3:
resolution: {integrity: sha512-UfmUD36DKkqhi/F75RrxvPpry+9+tTkrXfMNZD+SboZqBCMsxKtO52XeGzzuh7ioz+Eo/SYDBbdb0Z7vgcDJew==} resolution: {integrity: sha512-UfmUD36DKkqhi/F75RrxvPpry+9+tTkrXfMNZD+SboZqBCMsxKtO52XeGzzuh7ioz+Eo/SYDBbdb0Z7vgcDJew==}
engines: {node: ^18.0.0 || >=20.0.0} engines: {node: ^18.0.0 || >=20.0.0}
@ -6964,8 +6935,8 @@ packages:
resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==}
dev: false dev: false
/zustand@4.5.0(@types/react@18.2.55)(react@18.2.0): /zustand@4.5.1(@types/react@18.2.59)(react@18.2.0):
resolution: {integrity: sha512-zlVFqS5TQ21nwijjhJlx4f9iGrXSL0o/+Dpy4txAP22miJ8Ti6c1Ol1RLNN98BMib83lmDH/2KmLwaNXpjrO1A==} resolution: {integrity: sha512-XlauQmH64xXSC1qGYNv00ODaQ3B+tNPoy22jv2diYiP4eoDKr9LA+Bh5Bc3gplTrFdb6JVI+N4kc1DZ/tbtfPg==}
engines: {node: '>=12.7.0'} engines: {node: '>=12.7.0'}
peerDependencies: peerDependencies:
'@types/react': '>=16.8' '@types/react': '>=16.8'
@ -6979,7 +6950,7 @@ packages:
react: react:
optional: true optional: true
dependencies: dependencies:
'@types/react': 18.2.55 '@types/react': 18.2.59
react: 18.2.0 react: 18.2.0
use-sync-external-store: 1.2.0(react@18.2.0) use-sync-external-store: 1.2.0(react@18.2.0)
dev: false dev: false

@ -0,0 +1,53 @@
svg text tspan {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-rendering: optimizeSpeed;
}
svg > g[data-type='topic'],
svg > g[data-type='subtopic'],
svg > g > g[data-type='link-item'],
svg > g[data-type='button'] {
cursor: pointer;
}
svg > g[data-type='topic']:hover > rect {
fill: #d6d700;
}
svg > g[data-type='subtopic']:hover > rect {
fill: #f3c950;
}
svg > g[data-type='button']:hover {
opacity: 0.8;
}
svg .done rect {
fill: #cbcbcb !important;
}
svg .done text,
svg .skipped text {
text-decoration: line-through;
}
svg > g[data-type='topic'].learning > rect + text,
svg > g[data-type='topic'].done > rect + text {
fill: black;
}
svg > g[data-type='subtipic'].done > rect + text,
svg > g[data-type='subtipic'].learning > rect + text {
fill: #cbcbcb;
}
svg .learning rect {
fill: #dad1fd !important;
}
svg .learning text {
text-decoration: underline;
}
svg .skipped rect {
fill: #496b69 !important;
}

@ -0,0 +1,80 @@
import { useRef, useState, type FormEvent } from 'react';
import './GenerateRoadmap.css';
import { httpPost } from '../../lib/http';
import { useToast } from '../../hooks/use-toast';
import { generateRoadmapFromJSON } from '../../../editor/utils/roadmap-generator';
import { renderFlowJSON } from '../../../editor/renderer/renderer';
import { replaceChildren } from '../../lib/dom';
export function GenerateRoadmap() {
const roadmapContainerRef = useRef<HTMLDivElement>(null);
const toast = useToast();
const [isLoading, setIsLoading] = useState(false);
const [roadmapName, setRoadmapName] = useState('');
const handleSubmit = async (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
setIsLoading(true);
const { response, error } = await httpPost(
`${import.meta.env.PUBLIC_API_URL}/v1-generate-roadmap`,
{
title: roadmapName,
},
);
if (error || !response) {
setIsLoading(false);
toast.error(error?.message || 'Something went wrong');
return;
}
const { nodes, edges } = generateRoadmapFromJSON(response as any);
const svg = await renderFlowJSON({ nodes, edges });
if (roadmapContainerRef?.current) {
replaceChildren(roadmapContainerRef?.current, svg);
}
setIsLoading(false);
};
return (
<section className="container grid grid-cols-[280px,1fr]">
<form
className="h-full space-y-4 border-r px-4 py-10"
onSubmit={handleSubmit}
>
<div className="flex w-full flex-col">
<label
htmlFor="roadmap-name"
className='text-sm leading-none text-slate-500 after:text-red-400 after:content-["*"]'
>
Roadmap Title
</label>
<input
type="text"
name="roadmap-name"
id="roadmap-name"
className="mt-2 block w-full appearance-none rounded-lg border border-gray-300 px-3 py-2 shadow-sm outline-none placeholder:text-gray-400 focus:ring-2 focus:ring-black focus:ring-offset-1"
required
placeholder="Frontend"
value={roadmapName}
onInput={(e) =>
setRoadmapName((e.target as HTMLInputElement).value)
}
/>
</div>
<button
type="submit"
disabled={isLoading}
className="inline-flex w-full items-center justify-center rounded-lg bg-black p-2 py-3 text-sm font-medium text-white outline-none focus:ring-2 focus:ring-black focus:ring-offset-1 disabled:bg-gray-400"
>
{isLoading ? 'Please wait...' : 'Generate'}
</button>
</form>
<div ref={roadmapContainerRef} className="px-4 py-10" />
</section>
);
}

@ -0,0 +1,8 @@
---
import { GenerateRoadmap } from '../../components/GenerateRoadmap/GenerateRoadmap';
import AccountLayout from '../../layouts/AccountLayout.astro';
---
<AccountLayout title='Roadmap AI'>
<GenerateRoadmap client:load />
</AccountLayout>

@ -4,5 +4,6 @@
"moduleResolution": "node", "moduleResolution": "node",
"jsx": "react-jsx", "jsx": "react-jsx",
"jsxImportSource": "react" "jsxImportSource": "react"
} },
"exclude": ["node_modules", "dist"]
} }
Loading…
Cancel
Save