@locusai/web 0.1.7 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (346) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/next.config.js +15 -2
  3. package/package.json +26 -3
  4. package/src/app/(auth)/invite/page.tsx +109 -0
  5. package/src/app/(auth)/layout.tsx +19 -0
  6. package/src/app/(auth)/login/page.tsx +65 -0
  7. package/src/app/(auth)/onboarding/workspace/page.tsx +46 -0
  8. package/src/app/(auth)/register/page.tsx +165 -0
  9. package/src/app/(dashboard)/activity/page.tsx +7 -0
  10. package/src/app/(dashboard)/backlog/page.tsx +195 -0
  11. package/src/app/(dashboard)/board/page.tsx +141 -0
  12. package/src/app/(dashboard)/layout.tsx +32 -0
  13. package/src/app/(dashboard)/page.tsx +14 -0
  14. package/src/app/(dashboard)/settings/page.tsx +161 -0
  15. package/src/app/(dashboard)/settings/team/page.tsx +75 -0
  16. package/src/app/globals.css +259 -0
  17. package/src/app/layout.tsx +10 -20
  18. package/src/app/providers.tsx +26 -3
  19. package/src/components/AuthLayoutUI.tsx +53 -0
  20. package/src/components/BoardFilter.tsx +75 -74
  21. package/src/components/CreateModal/CreateModal.tsx +142 -0
  22. package/src/components/CreateModal/index.ts +1 -0
  23. package/src/components/Editor.tsx +279 -0
  24. package/src/components/Header.tsx +99 -12
  25. package/src/components/PageLayout.tsx +69 -0
  26. package/src/components/PropertyItem.tsx +55 -9
  27. package/src/components/Sidebar.tsx +280 -36
  28. package/src/components/SprintCreateModal.tsx +84 -0
  29. package/src/components/TaskCard.tsx +196 -78
  30. package/src/components/TaskCreateModal.tsx +181 -178
  31. package/src/components/TaskPanel.tsx +140 -692
  32. package/src/components/WorkspaceCreateModal.tsx +97 -0
  33. package/src/components/WorkspaceProtected.tsx +91 -0
  34. package/src/components/auth/InviteSteps.tsx +220 -0
  35. package/src/components/auth/LoginSteps.tsx +86 -0
  36. package/src/components/auth/RegisterSteps.tsx +371 -0
  37. package/src/components/auth/index.ts +3 -0
  38. package/src/components/backlog/BacklogList.tsx +92 -0
  39. package/src/components/backlog/BacklogSection.tsx +137 -0
  40. package/src/components/backlog/CompletedSprintItem.tsx +95 -0
  41. package/src/components/backlog/CompletedSprintsSection.tsx +77 -0
  42. package/src/components/backlog/SprintSection.tsx +155 -0
  43. package/src/components/backlog/constants.ts +26 -0
  44. package/src/components/board/BoardColumn.tsx +97 -0
  45. package/src/components/board/BoardContent.tsx +84 -0
  46. package/src/components/board/BoardEmptyState.tsx +82 -0
  47. package/src/components/board/BoardHeader.tsx +47 -0
  48. package/src/components/board/SprintMindmap.tsx +65 -0
  49. package/src/components/board/constants.ts +40 -0
  50. package/src/components/board/index.ts +5 -0
  51. package/src/components/common/ErrorState.tsx +124 -0
  52. package/src/components/common/LoadingState.tsx +83 -0
  53. package/src/components/common/index.ts +40 -0
  54. package/src/components/dashboard/ActivityFeed.tsx +77 -0
  55. package/src/components/dashboard/ActivityItem.tsx +207 -0
  56. package/src/components/dashboard/QuickActions.tsx +50 -0
  57. package/src/components/dashboard/StatCard.tsx +79 -0
  58. package/src/components/dnd/index.tsx +51 -0
  59. package/src/components/docs/DocsEditorArea.tsx +87 -0
  60. package/src/components/docs/DocsHeaderActions.tsx +121 -0
  61. package/src/components/docs/DocsSidebar.tsx +351 -0
  62. package/src/components/index.ts +7 -0
  63. package/src/components/onboarding/StepProgress.tsx +21 -0
  64. package/src/components/onboarding/index.ts +1 -0
  65. package/src/components/settings/ApiKeyConfirmationModal.tsx +81 -0
  66. package/src/components/settings/ApiKeyCreatedModal.tsx +96 -0
  67. package/src/components/settings/ApiKeysList.tsx +143 -0
  68. package/src/components/settings/ApiKeysSettings.tsx +144 -0
  69. package/src/components/settings/InviteMemberModal.tsx +106 -0
  70. package/src/components/settings/ProjectSetupGuide.tsx +147 -0
  71. package/src/components/settings/SettingItem.tsx +32 -0
  72. package/src/components/settings/SettingSection.tsx +50 -0
  73. package/src/components/settings/TeamInvitationsList.tsx +90 -0
  74. package/src/components/settings/TeamMembersList.tsx +95 -0
  75. package/src/components/settings/index.ts +8 -0
  76. package/src/components/task-panel/TaskActivity.tsx +127 -0
  77. package/src/components/task-panel/TaskChecklist.tsx +142 -0
  78. package/src/components/task-panel/TaskDescription.tsx +201 -0
  79. package/src/components/task-panel/TaskDocs.tsx +137 -0
  80. package/src/components/task-panel/TaskHeader.tsx +125 -0
  81. package/src/components/task-panel/TaskProperties.tsx +111 -0
  82. package/src/components/task-panel/index.ts +12 -0
  83. package/src/components/typography/EmptyStateText.tsx +59 -0
  84. package/src/components/typography/MetadataText.tsx +65 -0
  85. package/src/components/typography/SecondaryText.tsx +60 -0
  86. package/src/components/typography/SectionLabel.tsx +60 -0
  87. package/src/components/typography/index.ts +14 -0
  88. package/src/components/typography-scales.tsx +218 -0
  89. package/src/components/ui/Avatar.tsx +123 -0
  90. package/src/components/ui/Badge.tsx +69 -2
  91. package/src/components/ui/Button.tsx +71 -30
  92. package/src/components/ui/Checkbox.tsx +34 -0
  93. package/src/components/ui/Dropdown.tsx +67 -1
  94. package/src/components/ui/EmptyState.tsx +129 -0
  95. package/src/components/ui/Input.tsx +53 -6
  96. package/src/components/ui/Modal.tsx +45 -12
  97. package/src/components/ui/OtpInput.tsx +148 -0
  98. package/src/components/ui/Skeleton.tsx +36 -0
  99. package/src/components/ui/Spinner.tsx +112 -0
  100. package/src/components/ui/Textarea.tsx +28 -3
  101. package/src/components/ui/Toast.tsx +99 -0
  102. package/src/components/ui/Toggle.tsx +63 -0
  103. package/src/components/ui/constants.ts +108 -0
  104. package/src/components/ui/index.ts +7 -0
  105. package/src/context/AuthContext.tsx +140 -0
  106. package/src/context/index.ts +1 -0
  107. package/src/hooks/backlog/index.ts +13 -0
  108. package/src/hooks/backlog/useBacklogActions.ts +144 -0
  109. package/src/hooks/backlog/useBacklogComposite.ts +73 -0
  110. package/src/hooks/backlog/useBacklogData.ts +74 -0
  111. package/src/hooks/backlog/useBacklogDragDrop.ts +118 -0
  112. package/src/hooks/backlog/useBacklogUI.ts +74 -0
  113. package/src/hooks/index.ts +22 -0
  114. package/src/hooks/task-panel/index.ts +13 -0
  115. package/src/hooks/task-panel/useTaskActions.ts +200 -0
  116. package/src/hooks/task-panel/useTaskComputedValues.ts +30 -0
  117. package/src/hooks/task-panel/useTaskData.ts +78 -0
  118. package/src/hooks/task-panel/useTaskPanelComposite.ts +161 -0
  119. package/src/hooks/task-panel/useTaskUIState.ts +80 -0
  120. package/src/hooks/useAuthLayoutLogic.ts +43 -0
  121. package/src/hooks/useAuthenticatedUser.ts +36 -0
  122. package/src/hooks/useAuthenticatedUserWithOrg.ts +41 -0
  123. package/src/hooks/useBacklog.ts +303 -0
  124. package/src/hooks/useBoard.ts +230 -0
  125. package/src/hooks/useDashboardLayout.ts +49 -0
  126. package/src/hooks/useDocs.ts +279 -0
  127. package/src/hooks/useDocsQuery.ts +99 -0
  128. package/src/hooks/useDocsSidebarState.ts +104 -0
  129. package/src/hooks/useFormState.ts +40 -0
  130. package/src/hooks/useGlobalKeydowns.ts +52 -0
  131. package/src/hooks/useInviteForm.ts +122 -0
  132. package/src/hooks/useLoginForm.ts +84 -0
  133. package/src/hooks/useMutationWithToast.ts +56 -0
  134. package/src/hooks/useOrganizationQuery.ts +55 -0
  135. package/src/hooks/useRegisterForm.ts +216 -0
  136. package/src/hooks/useSprintsQuery.ts +38 -0
  137. package/src/hooks/useTaskDescription.ts +102 -0
  138. package/src/hooks/useTaskPanel.ts +341 -0
  139. package/src/hooks/useTasksQuery.ts +39 -0
  140. package/src/hooks/useTeamManagement.ts +92 -0
  141. package/src/hooks/useWorkspaceCreateForm.ts +70 -0
  142. package/src/hooks/useWorkspaceId.ts +29 -0
  143. package/src/lib/api-client.ts +40 -23
  144. package/src/lib/config.ts +25 -0
  145. package/src/lib/constants.ts +83 -0
  146. package/src/lib/options.ts +96 -0
  147. package/src/lib/query-keys.ts +91 -0
  148. package/src/lib/typography.ts +103 -0
  149. package/src/lib/utils.ts +4 -0
  150. package/src/lib/validation.ts +192 -0
  151. package/src/services/index.ts +7 -3
  152. package/src/services/notifications.ts +80 -0
  153. package/src/utils/env.utils.ts +15 -0
  154. package/src/views/ActivityView.tsx +123 -0
  155. package/src/views/Dashboard.tsx +126 -0
  156. package/src/views/Docs.tsx +98 -612
  157. package/tsconfig.tsbuildinfo +1 -1
  158. package/.next/BUILD_ID +0 -1
  159. package/.next/app-build-manifest.json +0 -55
  160. package/.next/app-path-routes-manifest.json +0 -8
  161. package/.next/build-manifest.json +0 -33
  162. package/.next/cache/.previewinfo +0 -1
  163. package/.next/cache/.rscinfo +0 -1
  164. package/.next/cache/.tsbuildinfo +0 -1
  165. package/.next/cache/config.json +0 -7
  166. package/.next/cache/webpack/client-production/0.pack +0 -0
  167. package/.next/cache/webpack/client-production/index.pack +0 -0
  168. package/.next/cache/webpack/edge-server-production/0.pack +0 -0
  169. package/.next/cache/webpack/edge-server-production/index.pack +0 -0
  170. package/.next/cache/webpack/server-production/0.pack +0 -0
  171. package/.next/cache/webpack/server-production/index.pack +0 -0
  172. package/.next/diagnostics/build-diagnostics.json +0 -6
  173. package/.next/diagnostics/framework.json +0 -1
  174. package/.next/export-detail.json +0 -5
  175. package/.next/export-marker.json +0 -6
  176. package/.next/images-manifest.json +0 -57
  177. package/.next/next-minimal-server.js.nft.json +0 -1
  178. package/.next/next-server.js.nft.json +0 -1
  179. package/.next/package.json +0 -1
  180. package/.next/prerender-manifest.json +0 -137
  181. package/.next/react-loadable-manifest.json +0 -32
  182. package/.next/required-server-files.json +0 -324
  183. package/.next/routes-manifest.json +0 -77
  184. package/.next/server/app/_not-found/page.js +0 -2
  185. package/.next/server/app/_not-found/page.js.nft.json +0 -1
  186. package/.next/server/app/_not-found/page_client-reference-manifest.js +0 -1
  187. package/.next/server/app/_not-found.html +0 -1
  188. package/.next/server/app/_not-found.meta +0 -8
  189. package/.next/server/app/_not-found.rsc +0 -21
  190. package/.next/server/app/backlog/page.js +0 -2
  191. package/.next/server/app/backlog/page.js.nft.json +0 -1
  192. package/.next/server/app/backlog/page_client-reference-manifest.js +0 -1
  193. package/.next/server/app/backlog.html +0 -1
  194. package/.next/server/app/backlog.meta +0 -7
  195. package/.next/server/app/backlog.rsc +0 -25
  196. package/.next/server/app/docs/page.js +0 -97
  197. package/.next/server/app/docs/page.js.nft.json +0 -1
  198. package/.next/server/app/docs/page_client-reference-manifest.js +0 -1
  199. package/.next/server/app/docs.html +0 -1
  200. package/.next/server/app/docs.meta +0 -7
  201. package/.next/server/app/docs.rsc +0 -26
  202. package/.next/server/app/favicon.ico/route.js +0 -1
  203. package/.next/server/app/favicon.ico/route.js.nft.json +0 -1
  204. package/.next/server/app/favicon.ico.body +0 -0
  205. package/.next/server/app/favicon.ico.meta +0 -1
  206. package/.next/server/app/index.html +0 -1
  207. package/.next/server/app/index.meta +0 -7
  208. package/.next/server/app/index.rsc +0 -25
  209. package/.next/server/app/page.js +0 -2
  210. package/.next/server/app/page.js.nft.json +0 -1
  211. package/.next/server/app/page_client-reference-manifest.js +0 -1
  212. package/.next/server/app/settings/page.js +0 -2
  213. package/.next/server/app/settings/page.js.nft.json +0 -1
  214. package/.next/server/app/settings/page_client-reference-manifest.js +0 -1
  215. package/.next/server/app/settings.html +0 -1
  216. package/.next/server/app/settings.meta +0 -7
  217. package/.next/server/app/settings.rsc +0 -25
  218. package/.next/server/app-paths-manifest.json +0 -8
  219. package/.next/server/chunks/496.js +0 -6
  220. package/.next/server/chunks/585.js +0 -1
  221. package/.next/server/chunks/665.js +0 -1
  222. package/.next/server/chunks/699.js +0 -22
  223. package/.next/server/chunks/852.js +0 -7
  224. package/.next/server/functions-config-manifest.json +0 -4
  225. package/.next/server/interception-route-rewrite-manifest.js +0 -1
  226. package/.next/server/middleware-build-manifest.js +0 -1
  227. package/.next/server/middleware-manifest.json +0 -6
  228. package/.next/server/middleware-react-loadable-manifest.js +0 -1
  229. package/.next/server/next-font-manifest.js +0 -1
  230. package/.next/server/next-font-manifest.json +0 -1
  231. package/.next/server/pages/404.html +0 -1
  232. package/.next/server/pages/500.html +0 -1
  233. package/.next/server/pages/_app.js +0 -1
  234. package/.next/server/pages/_app.js.nft.json +0 -1
  235. package/.next/server/pages/_document.js +0 -1
  236. package/.next/server/pages/_document.js.nft.json +0 -1
  237. package/.next/server/pages/_error.js +0 -19
  238. package/.next/server/pages/_error.js.nft.json +0 -1
  239. package/.next/server/pages-manifest.json +0 -6
  240. package/.next/server/server-reference-manifest.js +0 -1
  241. package/.next/server/server-reference-manifest.json +0 -1
  242. package/.next/server/webpack-runtime.js +0 -1
  243. package/.next/static/D0NXe04ZCLNDckV_quc8g/_buildManifest.js +0 -1
  244. package/.next/static/D0NXe04ZCLNDckV_quc8g/_ssgManifest.js +0 -1
  245. package/.next/static/chunks/138.b98511c56423f8bb.js +0 -1
  246. package/.next/static/chunks/146-34259952c594a3b0.js +0 -1
  247. package/.next/static/chunks/337-d3bb75304d130513.js +0 -1
  248. package/.next/static/chunks/477.1a6ecfe53375bd9c.js +0 -1
  249. package/.next/static/chunks/487-1808785ba665f784.js +0 -1
  250. package/.next/static/chunks/544.a9569941cc886e9d.js +0 -1
  251. package/.next/static/chunks/87c73c54-1f4741035a95c140.js +0 -1
  252. package/.next/static/chunks/902-d6926825a9fe8784.js +0 -1
  253. package/.next/static/chunks/955-c8f8f6235ae8f8c6.js +0 -1
  254. package/.next/static/chunks/996.e0a334e6ae90900e.js +0 -1
  255. package/.next/static/chunks/app/_not-found/page-44b1804abb44a34d.js +0 -1
  256. package/.next/static/chunks/app/backlog/page-dce1450769bfae8f.js +0 -1
  257. package/.next/static/chunks/app/docs/page-1efee819f25492cb.js +0 -1
  258. package/.next/static/chunks/app/layout-05f504c042b9f7ee.js +0 -1
  259. package/.next/static/chunks/app/page-3fd91aaaa4776ced.js +0 -1
  260. package/.next/static/chunks/app/settings/page-84e16c9638d657e4.js +0 -1
  261. package/.next/static/chunks/framework-152a1bc8c81c7458.js +0 -1
  262. package/.next/static/chunks/main-843ab130fc1be309.js +0 -1
  263. package/.next/static/chunks/main-app-123e879c5a937a00.js +0 -1
  264. package/.next/static/chunks/pages/_app-a050a8e6e4fb04cf.js +0 -1
  265. package/.next/static/chunks/pages/_error-3e422ffd891594de.js +0 -1
  266. package/.next/static/chunks/polyfills-42372ed130431b0a.js +0 -1
  267. package/.next/static/chunks/webpack-99a10a055b5bb9c4.js +0 -1
  268. package/.next/static/css/13e8617b72f9d3aa.css +0 -1
  269. package/.next/static/css/8aea088cdc4338f0.css +0 -1
  270. package/.next/static/css/b301ab0424111664.css +0 -1
  271. package/.next/static/media/24c15609eaa28576-s.woff2 +0 -0
  272. package/.next/static/media/2c07349e02a7b712-s.woff2 +0 -0
  273. package/.next/static/media/456105d6ea6d39e0-s.woff2 +0 -0
  274. package/.next/static/media/47cbc4e2adbc5db9-s.p.woff2 +0 -0
  275. package/.next/static/media/4f77bef990aad698-s.woff2 +0 -0
  276. package/.next/static/media/627d916fd739a539-s.woff2 +0 -0
  277. package/.next/static/media/63b255f18bea0ca9-s.woff2 +0 -0
  278. package/.next/static/media/70bd82ac89b4fa42-s.woff2 +0 -0
  279. package/.next/static/media/84602850c8fd81c3-s.woff2 +0 -0
  280. package/.next/trace +0 -46
  281. package/.next/types/app/backlog/page.ts +0 -84
  282. package/.next/types/app/docs/page.ts +0 -84
  283. package/.next/types/app/layout.ts +0 -84
  284. package/.next/types/app/page.ts +0 -84
  285. package/.next/types/app/settings/page.ts +0 -84
  286. package/.next/types/cache-life.d.ts +0 -141
  287. package/.next/types/package.json +0 -1
  288. package/next-env.d.ts +0 -5
  289. package/out/404.html +0 -1
  290. package/out/_next/static/D0NXe04ZCLNDckV_quc8g/_buildManifest.js +0 -1
  291. package/out/_next/static/D0NXe04ZCLNDckV_quc8g/_ssgManifest.js +0 -1
  292. package/out/_next/static/chunks/138.b98511c56423f8bb.js +0 -1
  293. package/out/_next/static/chunks/146-34259952c594a3b0.js +0 -1
  294. package/out/_next/static/chunks/337-d3bb75304d130513.js +0 -1
  295. package/out/_next/static/chunks/477.1a6ecfe53375bd9c.js +0 -1
  296. package/out/_next/static/chunks/487-1808785ba665f784.js +0 -1
  297. package/out/_next/static/chunks/544.a9569941cc886e9d.js +0 -1
  298. package/out/_next/static/chunks/87c73c54-1f4741035a95c140.js +0 -1
  299. package/out/_next/static/chunks/902-d6926825a9fe8784.js +0 -1
  300. package/out/_next/static/chunks/955-c8f8f6235ae8f8c6.js +0 -1
  301. package/out/_next/static/chunks/996.e0a334e6ae90900e.js +0 -1
  302. package/out/_next/static/chunks/app/_not-found/page-44b1804abb44a34d.js +0 -1
  303. package/out/_next/static/chunks/app/backlog/page-dce1450769bfae8f.js +0 -1
  304. package/out/_next/static/chunks/app/docs/page-1efee819f25492cb.js +0 -1
  305. package/out/_next/static/chunks/app/layout-05f504c042b9f7ee.js +0 -1
  306. package/out/_next/static/chunks/app/page-3fd91aaaa4776ced.js +0 -1
  307. package/out/_next/static/chunks/app/settings/page-84e16c9638d657e4.js +0 -1
  308. package/out/_next/static/chunks/framework-152a1bc8c81c7458.js +0 -1
  309. package/out/_next/static/chunks/main-843ab130fc1be309.js +0 -1
  310. package/out/_next/static/chunks/main-app-123e879c5a937a00.js +0 -1
  311. package/out/_next/static/chunks/pages/_app-a050a8e6e4fb04cf.js +0 -1
  312. package/out/_next/static/chunks/pages/_error-3e422ffd891594de.js +0 -1
  313. package/out/_next/static/chunks/polyfills-42372ed130431b0a.js +0 -1
  314. package/out/_next/static/chunks/webpack-99a10a055b5bb9c4.js +0 -1
  315. package/out/_next/static/css/13e8617b72f9d3aa.css +0 -1
  316. package/out/_next/static/css/8aea088cdc4338f0.css +0 -1
  317. package/out/_next/static/css/b301ab0424111664.css +0 -1
  318. package/out/_next/static/media/24c15609eaa28576-s.woff2 +0 -0
  319. package/out/_next/static/media/2c07349e02a7b712-s.woff2 +0 -0
  320. package/out/_next/static/media/456105d6ea6d39e0-s.woff2 +0 -0
  321. package/out/_next/static/media/47cbc4e2adbc5db9-s.p.woff2 +0 -0
  322. package/out/_next/static/media/4f77bef990aad698-s.woff2 +0 -0
  323. package/out/_next/static/media/627d916fd739a539-s.woff2 +0 -0
  324. package/out/_next/static/media/63b255f18bea0ca9-s.woff2 +0 -0
  325. package/out/_next/static/media/70bd82ac89b4fa42-s.woff2 +0 -0
  326. package/out/_next/static/media/84602850c8fd81c3-s.woff2 +0 -0
  327. package/out/backlog.html +0 -1
  328. package/out/backlog.txt +0 -25
  329. package/out/docs.html +0 -1
  330. package/out/docs.txt +0 -26
  331. package/out/favicon.ico +0 -0
  332. package/out/index.html +0 -1
  333. package/out/index.txt +0 -25
  334. package/out/logo.png +0 -0
  335. package/out/settings.html +0 -1
  336. package/out/settings.txt +0 -25
  337. package/src/app/backlog/page.tsx +0 -19
  338. package/src/app/page.tsx +0 -16
  339. package/src/app/settings/page.tsx +0 -194
  340. package/src/hooks/useTasks.ts +0 -119
  341. package/src/services/doc.service.ts +0 -27
  342. package/src/services/sprint.service.ts +0 -24
  343. package/src/services/task.service.ts +0 -75
  344. package/src/views/Backlog.tsx +0 -691
  345. package/src/views/Board.tsx +0 -306
  346. /package/src/app/{docs → (dashboard)/docs}/page.tsx +0 -0
@@ -1,194 +0,0 @@
1
- "use client";
2
-
3
- import {
4
- Bell,
5
- Globe,
6
- Moon,
7
- Palette,
8
- Shield,
9
- Sun,
10
- User,
11
- Zap,
12
- } from "lucide-react";
13
- import { useState } from "react";
14
- import { Button } from "@/components/ui";
15
-
16
- interface SettingItemProps {
17
- icon: React.ReactNode;
18
- title: string;
19
- description: string;
20
- children: React.ReactNode;
21
- }
22
-
23
- function SettingItem({ icon, title, description, children }: SettingItemProps) {
24
- return (
25
- <div className="flex items-start justify-between p-4 rounded-xl hover:bg-secondary/30 transition-colors">
26
- <div className="flex gap-4">
27
- <div className="w-10 h-10 rounded-xl bg-secondary flex items-center justify-center text-muted-foreground shrink-0">
28
- {icon}
29
- </div>
30
- <div>
31
- <h4 className="font-medium text-foreground">{title}</h4>
32
- <p className="text-sm text-muted-foreground mt-0.5">{description}</p>
33
- </div>
34
- </div>
35
- <div className="shrink-0">{children}</div>
36
- </div>
37
- );
38
- }
39
-
40
- function Toggle({
41
- checked,
42
- onChange,
43
- }: {
44
- checked: boolean;
45
- onChange: (checked: boolean) => void;
46
- }) {
47
- return (
48
- <button
49
- type="button"
50
- role="switch"
51
- aria-checked={checked}
52
- onClick={() => onChange(!checked)}
53
- className={`relative inline-flex h-6 w-11 shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 ${
54
- checked ? "bg-primary" : "bg-secondary"
55
- }`}
56
- >
57
- <span
58
- className={`pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow-lg ring-0 transition ${
59
- checked ? "translate-x-5" : "translate-x-0"
60
- }`}
61
- />
62
- </button>
63
- );
64
- }
65
-
66
- export default function SettingsPage() {
67
- const [darkMode, setDarkMode] = useState(true);
68
- const [notifications, setNotifications] = useState(true);
69
- const [autoRefresh, setAutoRefresh] = useState(true);
70
- const [compactMode, setCompactMode] = useState(false);
71
-
72
- return (
73
- <div className="max-w-3xl">
74
- <div className="mb-8">
75
- <h1 className="text-2xl font-bold tracking-tight text-foreground">
76
- Settings
77
- </h1>
78
- <p className="text-muted-foreground mt-1">
79
- Manage your workspace preferences and configuration.
80
- </p>
81
- </div>
82
-
83
- {/* Appearance Section */}
84
- <div className="mb-8">
85
- <h3 className="text-xs font-bold uppercase tracking-widest text-muted-foreground mb-4 px-4">
86
- Appearance
87
- </h3>
88
- <div className="bg-card border border-border/50 rounded-2xl overflow-hidden divide-y divide-border/50">
89
- <SettingItem
90
- icon={darkMode ? <Moon size={18} /> : <Sun size={18} />}
91
- title="Dark Mode"
92
- description="Toggle between light and dark theme"
93
- >
94
- <Toggle checked={darkMode} onChange={setDarkMode} />
95
- </SettingItem>
96
- <SettingItem
97
- icon={<Palette size={18} />}
98
- title="Accent Color"
99
- description="Choose your preferred accent color"
100
- >
101
- <div className="flex gap-2">
102
- {["#6366f1", "#8b5cf6", "#06b6d4", "#10b981", "#f59e0b"].map(
103
- (color) => (
104
- <button
105
- key={color}
106
- className="w-6 h-6 rounded-full border-2 border-transparent hover:border-foreground/30 transition-colors"
107
- style={{ backgroundColor: color }}
108
- />
109
- )
110
- )}
111
- </div>
112
- </SettingItem>
113
- <SettingItem
114
- icon={<Zap size={18} />}
115
- title="Compact Mode"
116
- description="Reduce spacing for more content visibility"
117
- >
118
- <Toggle checked={compactMode} onChange={setCompactMode} />
119
- </SettingItem>
120
- </div>
121
- </div>
122
-
123
- {/* Notifications Section */}
124
- <div className="mb-8">
125
- <h3 className="text-xs font-bold uppercase tracking-widest text-muted-foreground mb-4 px-4">
126
- Notifications
127
- </h3>
128
- <div className="bg-card border border-border/50 rounded-2xl overflow-hidden divide-y divide-border/50">
129
- <SettingItem
130
- icon={<Bell size={18} />}
131
- title="Push Notifications"
132
- description="Receive notifications for task updates"
133
- >
134
- <Toggle checked={notifications} onChange={setNotifications} />
135
- </SettingItem>
136
- <SettingItem
137
- icon={<Globe size={18} />}
138
- title="Auto Refresh"
139
- description="Automatically refresh board data"
140
- >
141
- <Toggle checked={autoRefresh} onChange={setAutoRefresh} />
142
- </SettingItem>
143
- </div>
144
- </div>
145
-
146
- {/* Account Section */}
147
- <div className="mb-8">
148
- <h3 className="text-xs font-bold uppercase tracking-widest text-muted-foreground mb-4 px-4">
149
- Account
150
- </h3>
151
- <div className="bg-card border border-border/50 rounded-2xl overflow-hidden divide-y divide-border/50">
152
- <SettingItem
153
- icon={<User size={18} />}
154
- title="Profile"
155
- description="Update your personal information"
156
- >
157
- <Button variant="secondary" size="sm">
158
- Edit
159
- </Button>
160
- </SettingItem>
161
- <SettingItem
162
- icon={<Shield size={18} />}
163
- title="Security"
164
- description="Manage authentication settings"
165
- >
166
- <Button variant="secondary" size="sm">
167
- Configure
168
- </Button>
169
- </SettingItem>
170
- </div>
171
- </div>
172
-
173
- {/* Danger Zone */}
174
- <div>
175
- <h3 className="text-xs font-bold uppercase tracking-widest text-destructive mb-4 px-4">
176
- Danger Zone
177
- </h3>
178
- <div className="bg-destructive/5 border border-destructive/20 rounded-2xl p-6">
179
- <div className="flex items-center justify-between">
180
- <div>
181
- <h4 className="font-medium text-foreground">Reset Workspace</h4>
182
- <p className="text-sm text-muted-foreground mt-0.5">
183
- Delete all tasks, documents, and settings
184
- </p>
185
- </div>
186
- <Button variant="danger" size="sm">
187
- Reset
188
- </Button>
189
- </div>
190
- </div>
191
- </div>
192
- </div>
193
- );
194
- }
@@ -1,119 +0,0 @@
1
- "use client";
2
-
3
- import { AssigneeRole, TaskPriority, TaskStatus } from "@locusai/shared";
4
- import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
5
- import { useCallback, useMemo, useState } from "react";
6
-
7
- import { taskService } from "@/services";
8
-
9
- export function useTasks() {
10
- const queryClient = useQueryClient();
11
-
12
- const {
13
- data: tasks = [],
14
- isLoading: loading,
15
- error: queryError,
16
- refetch: refreshTasks,
17
- } = useQuery({
18
- queryKey: ["tasks"],
19
- queryFn: () => taskService.getAll(),
20
- refetchInterval: 15000,
21
- });
22
-
23
- const error = queryError ? (queryError as Error).message : null;
24
-
25
- // Filter state
26
- const [searchQuery, setSearchQuery] = useState("");
27
- const [priorityFilter, setPriorityFilter] = useState<TaskPriority | "ALL">(
28
- "ALL"
29
- );
30
- const [assigneeFilter, setAssigneeFilter] = useState<AssigneeRole | "ALL">(
31
- "ALL"
32
- );
33
-
34
- const hasActiveFilters = useMemo(
35
- () =>
36
- searchQuery !== "" ||
37
- priorityFilter !== "ALL" ||
38
- assigneeFilter !== "ALL",
39
- [searchQuery, priorityFilter, assigneeFilter]
40
- );
41
-
42
- const updateMutation = useMutation({
43
- mutationFn: ({ taskId, status }: { taskId: number; status: TaskStatus }) =>
44
- taskService.update(taskId, { status }),
45
- onSuccess: () => {
46
- queryClient.invalidateQueries({ queryKey: ["tasks"] });
47
- },
48
- });
49
-
50
- const deleteMutation = useMutation({
51
- mutationFn: (taskId: number) => taskService.delete(taskId),
52
- onSuccess: () => {
53
- queryClient.invalidateQueries({ queryKey: ["tasks"] });
54
- },
55
- });
56
-
57
- const clearFilters = useCallback(() => {
58
- setSearchQuery("");
59
- setPriorityFilter("ALL");
60
- setAssigneeFilter("ALL");
61
- }, []);
62
-
63
- const filteredTasks = useMemo(() => {
64
- return tasks.filter((task) => {
65
- if (searchQuery) {
66
- const query = searchQuery.toLowerCase();
67
- if (!task.title.toLowerCase().includes(query)) {
68
- return false;
69
- }
70
- }
71
- if (priorityFilter !== "ALL" && task.priority !== priorityFilter) {
72
- return false;
73
- }
74
- if (assigneeFilter !== "ALL" && task.assigneeRole !== assigneeFilter) {
75
- return false;
76
- }
77
- return true;
78
- });
79
- }, [tasks, searchQuery, priorityFilter, assigneeFilter]);
80
-
81
- const getTasksByStatus = useCallback(
82
- (status: TaskStatus) => {
83
- return filteredTasks.filter((t) => t.status === status);
84
- },
85
- [filteredTasks]
86
- );
87
-
88
- const updateTaskStatus = useCallback(
89
- async (taskId: number, status: TaskStatus) => {
90
- await updateMutation.mutateAsync({ taskId, status });
91
- },
92
- [updateMutation]
93
- );
94
-
95
- const deleteTask = useCallback(
96
- async (taskId: number) => {
97
- await deleteMutation.mutateAsync(taskId);
98
- },
99
- [deleteMutation]
100
- );
101
-
102
- return {
103
- tasks,
104
- loading,
105
- error,
106
- searchQuery,
107
- setSearchQuery,
108
- priorityFilter,
109
- setPriorityFilter,
110
- assigneeFilter,
111
- setAssigneeFilter,
112
- hasActiveFilters,
113
- clearFilters,
114
- getTasksByStatus,
115
- updateTaskStatus,
116
- deleteTask,
117
- refreshTasks,
118
- };
119
- }
@@ -1,27 +0,0 @@
1
- import apiClient from "@/lib/api-client";
2
-
3
- export interface DocNode {
4
- type: "file" | "directory";
5
- name: string;
6
- path: string;
7
- children?: DocNode[];
8
- }
9
-
10
- export const docService = {
11
- getTree: async () => {
12
- const response = await apiClient.get<DocNode[]>("/docs/tree");
13
- return response.data;
14
- },
15
-
16
- read: async (path: string) => {
17
- const response = await apiClient.get<{ content: string }>(
18
- `/docs/read?path=${encodeURIComponent(path)}`
19
- );
20
- return response.data;
21
- },
22
-
23
- write: async (path: string, content: string) => {
24
- const response = await apiClient.post("/docs/write", { path, content });
25
- return response.data;
26
- },
27
- };
@@ -1,24 +0,0 @@
1
- import { type Sprint } from "@locusai/shared";
2
- import apiClient from "@/lib/api-client";
3
-
4
- export const sprintService = {
5
- getAll: async () => {
6
- const res = await apiClient.get<Sprint[]>("/sprints");
7
- return res.data;
8
- },
9
-
10
- create: async (data: Partial<Sprint>) => {
11
- const res = await apiClient.post<{ id: number }>("/sprints", data);
12
- return res.data;
13
- },
14
-
15
- update: async (id: number, data: Partial<Sprint>) => {
16
- const res = await apiClient.patch(`/sprints/${id}`, data);
17
- return res.data;
18
- },
19
-
20
- delete: async (id: number) => {
21
- const res = await apiClient.delete(`/sprints/${id}`);
22
- return res.data;
23
- },
24
- };
@@ -1,75 +0,0 @@
1
- import { AssigneeRole, Task, TaskPriority, TaskStatus } from "@locusai/shared";
2
- import apiClient from "@/lib/api-client";
3
-
4
- export interface CreateTaskDto {
5
- title: string;
6
- description?: string;
7
- status: TaskStatus;
8
- priority: TaskPriority;
9
- labels?: string[];
10
- assigneeRole?: AssigneeRole;
11
- sprintId?: number | null;
12
- }
13
-
14
- export interface UpdateTaskDto {
15
- title?: string;
16
- description?: string;
17
- status?: TaskStatus;
18
- priority?: TaskPriority;
19
- labels?: string[];
20
- assigneeRole?: AssigneeRole;
21
- acceptanceCriteria?: { id: string; text: string; done: boolean }[];
22
- sprintId?: number | null;
23
- }
24
-
25
- export const taskService = {
26
- getAll: async () => {
27
- const response = await apiClient.get<Task[]>("/tasks");
28
- return response.data;
29
- },
30
-
31
- getById: async (id: number) => {
32
- const response = await apiClient.get<Task>(`/tasks/${id}`);
33
- return response.data;
34
- },
35
-
36
- create: async (data: CreateTaskDto) => {
37
- const response = await apiClient.post<Task>("/tasks", data);
38
- return response.data;
39
- },
40
-
41
- update: async (id: number, data: UpdateTaskDto) => {
42
- const response = await apiClient.patch<Task>(`/tasks/${id}`, data);
43
- return response.data;
44
- },
45
-
46
- delete: async (id: number) => {
47
- await apiClient.delete(`/tasks/${id}`);
48
- },
49
-
50
- addComment: async (id: number, data: { author: string; text: string }) => {
51
- const response = await apiClient.post<Task>(`/tasks/${id}/comment`, data);
52
- return response.data;
53
- },
54
-
55
- runCi: async (id: number, preset: string) => {
56
- const response = await apiClient.post<{ summary: string }>("/ci/run", {
57
- taskId: id,
58
- preset,
59
- });
60
- return response.data;
61
- },
62
-
63
- lock: async (id: number, agentId: string, ttlSeconds: number) => {
64
- const response = await apiClient.post(`/tasks/${id}/lock`, {
65
- agentId,
66
- ttlSeconds,
67
- });
68
- return response.data;
69
- },
70
-
71
- unlock: async (id: number, agentId: string) => {
72
- const response = await apiClient.post(`/tasks/${id}/unlock`, { agentId });
73
- return response.data;
74
- },
75
- };