beads-kanban-ui 0.1.0 → 0.1.1
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.
- package/README.md +16 -222
- package/package.json +18 -55
- package/.designs/beads-kanban-ui-bj0.md +0 -73
- package/.designs/beads-kanban-ui-qxq.md +0 -144
- package/.designs/epic-support.md +0 -282
- package/.env.local.example +0 -2
- package/.eslintrc.json +0 -3
- package/.gitattributes +0 -3
- package/.github/workflows/release.yml +0 -123
- package/.history/README_20260121193710.md +0 -227
- package/.history/README_20260121193918.md +0 -227
- package/.history/README_20260121193921.md +0 -227
- package/.history/README_20260121193933.md +0 -227
- package/.history/README_20260121193934.md +0 -227
- package/.history/README_20260121193944.md +0 -227
- package/.history/README_20260121193953.md +0 -227
- package/.history/src/app/page_20260121133429.tsx +0 -134
- package/.history/src/app/page_20260121133928.tsx +0 -134
- package/.history/src/app/page_20260121144850.tsx +0 -138
- package/.history/src/app/page_20260121144854.tsx +0 -138
- package/.history/src/app/page_20260121144858.tsx +0 -138
- package/.history/src/app/page_20260121144902.tsx +0 -138
- package/.history/src/app/page_20260121144906.tsx +0 -138
- package/.history/src/app/page_20260121144911.tsx +0 -138
- package/.history/src/app/page_20260121144928.tsx +0 -138
- package/.playwright-mcp/.playwright-mcp/morphing-dialog-wheel-scroll-fix.png +0 -0
- package/.playwright-mcp/beams-test.png +0 -0
- package/.playwright-mcp/card-verification.png +0 -0
- package/.playwright-mcp/design-doc-dialog-fix-verification.png +0 -0
- package/.playwright-mcp/dialog-width-test.png +0 -0
- package/.playwright-mcp/homepage.png +0 -0
- package/.playwright-mcp/morphing-dialog-expanded.png +0 -0
- package/.playwright-mcp/morphing-dialog-fixes-final.png +0 -0
- package/.playwright-mcp/morphing-dialog-open.png +0 -0
- package/.playwright-mcp/page-2026-01-21T14-08-31-529Z.png +0 -0
- package/.playwright-mcp/page-2026-01-21T14-09-23-431Z.png +0 -0
- package/.playwright-mcp/page-2026-01-21T14-10-28-773Z.png +0 -0
- package/.playwright-mcp/page-2026-01-21T14-10-47-432Z.png +0 -0
- package/.playwright-mcp/page-2026-01-21T14-11-12-350Z.png +0 -0
- package/.playwright-mcp/screenshot-after-click.png +0 -0
- package/.playwright-mcp/screenshot-after-dialog-click.png +0 -0
- package/.playwright-mcp/sheet-restored-after-dialog-close.png +0 -0
- package/.playwright-mcp/test-1-sheet-open-with-overlay.png +0 -0
- package/.playwright-mcp/test-2-morphing-dialog-with-overlay.png +0 -0
- package/.playwright-mcp/test-3-sheet-open-dark-overlay.png +0 -0
- package/.playwright-mcp/test-4-morphing-dialog-with-dark-overlay.png +0 -0
- package/.playwright-mcp/test-5-morphing-dialog-scrolled.png +0 -0
- package/.playwright-mcp/test-6-sheet-restored-after-dialog-close.png +0 -0
- package/.playwright-mcp/wheel-scroll-fixed.png +0 -0
- package/Screenshots/bead-detail.png +0 -0
- package/Screenshots/dashboard.png +0 -0
- package/Screenshots/kanban-board.png +0 -0
- package/components.json +0 -27
- package/logo/logo.svg +0 -1
- package/next.config.js +0 -9
- package/npm/README.md +0 -37
- package/npm/package.json +0 -20
- package/postcss.config.js +0 -6
- package/public/logo.svg +0 -1
- package/restart.sh +0 -5
- package/server/Cargo.lock +0 -1685
- package/server/Cargo.toml +0 -24
- package/server/src/db.rs +0 -570
- package/server/src/main.rs +0 -141
- package/server/src/routes/beads.rs +0 -413
- package/server/src/routes/cli.rs +0 -150
- package/server/src/routes/fs.rs +0 -360
- package/server/src/routes/git.rs +0 -169
- package/server/src/routes/mod.rs +0 -107
- package/server/src/routes/projects.rs +0 -177
- package/server/src/routes/watch.rs +0 -211
- package/src/app/globals.css +0 -101
- package/src/app/layout.tsx +0 -36
- package/src/app/page.tsx +0 -348
- package/src/app/project/kanban-board.tsx +0 -356
- package/src/app/project/page.tsx +0 -18
- package/src/app/settings/page.tsx +0 -224
- package/src/components/Beams.css +0 -5
- package/src/components/Beams.jsx +0 -307
- package/src/components/Galaxy.css +0 -5
- package/src/components/Galaxy.jsx +0 -333
- package/src/components/activity-timeline.tsx +0 -172
- package/src/components/add-project-dialog.tsx +0 -219
- package/src/components/bead-card.tsx +0 -196
- package/src/components/bead-detail.tsx +0 -306
- package/src/components/color-picker.tsx +0 -101
- package/src/components/comment-input.tsx +0 -155
- package/src/components/comment-list.tsx +0 -147
- package/src/components/dependency-badge.tsx +0 -106
- package/src/components/design-doc-dialog.tsx +0 -58
- package/src/components/design-doc-preview.tsx +0 -97
- package/src/components/design-doc-viewer.tsx +0 -199
- package/src/components/editable-project-name.tsx +0 -178
- package/src/components/epic-card.tsx +0 -263
- package/src/components/folder-browser.tsx +0 -273
- package/src/components/footer.tsx +0 -27
- package/src/components/kanban/default.tsx +0 -184
- package/src/components/kanban-column.tsx +0 -167
- package/src/components/project-card.tsx +0 -191
- package/src/components/quick-filter-bar.tsx +0 -279
- package/src/components/scan-directory-dialog.tsx +0 -368
- package/src/components/status-donut.tsx +0 -197
- package/src/components/subtask-list.tsx +0 -128
- package/src/components/tag-picker.tsx +0 -252
- package/src/components/ui/.gitkeep +0 -0
- package/src/components/ui/alert-dialog.tsx +0 -141
- package/src/components/ui/avatar.tsx +0 -67
- package/src/components/ui/badge.tsx +0 -230
- package/src/components/ui/button.tsx +0 -433
- package/src/components/ui/card/index.tsx +0 -24
- package/src/components/ui/card/roiui-card.module.css +0 -197
- package/src/components/ui/card/roiui-card.tsx +0 -154
- package/src/components/ui/card/shadcn-card.tsx +0 -76
- package/src/components/ui/chart.tsx +0 -369
- package/src/components/ui/dialog.tsx +0 -122
- package/src/components/ui/dropdown-menu.tsx +0 -201
- package/src/components/ui/input.tsx +0 -22
- package/src/components/ui/kanban.tsx +0 -522
- package/src/components/ui/morphing-dialog.tsx +0 -457
- package/src/components/ui/popover.tsx +0 -33
- package/src/components/ui/progress.tsx +0 -28
- package/src/components/ui/scroll-area.tsx +0 -48
- package/src/components/ui/select.tsx +0 -159
- package/src/components/ui/separator.tsx +0 -31
- package/src/components/ui/sheet.tsx +0 -142
- package/src/components/ui/skeleton.tsx +0 -15
- package/src/components/ui/toast.tsx +0 -129
- package/src/components/ui/toaster.tsx +0 -35
- package/src/components/ui/tooltip.tsx +0 -30
- package/src/hooks/.gitkeep +0 -0
- package/src/hooks/use-bead-filters.ts +0 -261
- package/src/hooks/use-beads.ts +0 -162
- package/src/hooks/use-branch-statuses.ts +0 -161
- package/src/hooks/use-epics.ts +0 -173
- package/src/hooks/use-file-watcher.ts +0 -111
- package/src/hooks/use-keyboard-navigation.ts +0 -282
- package/src/hooks/use-project.ts +0 -61
- package/src/hooks/use-projects.ts +0 -93
- package/src/hooks/use-toast.ts +0 -194
- package/src/hooks/useClickOutside.tsx +0 -26
- package/src/lib/.gitkeep +0 -0
- package/src/lib/api.ts +0 -186
- package/src/lib/beads-parser.ts +0 -252
- package/src/lib/cli.ts +0 -193
- package/src/lib/db.ts +0 -145
- package/src/lib/design-doc.ts +0 -74
- package/src/lib/epic-parser.ts +0 -242
- package/src/lib/git.ts +0 -102
- package/src/lib/utils.ts +0 -12
- package/src/types/index.ts +0 -107
- package/tailwind.config.ts +0 -85
- package/tsconfig.json +0 -26
- /package/{npm/bin → bin}/cli.js +0 -0
- /package/{npm/scripts → scripts}/postinstall.js +0 -0
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import { useState } from "react";
|
|
4
|
-
import Link from "next/link";
|
|
5
|
-
import dynamic from "next/dynamic";
|
|
6
|
-
import { Settings } from "lucide-react";
|
|
7
|
-
import { ProjectCard } from "@/components/project-card";
|
|
8
|
-
import { AddProjectDialog } from "@/components/add-project-dialog";
|
|
9
|
-
import { useProjects } from "@/hooks/use-projects";
|
|
10
|
-
import { Skeleton } from "@/components/ui/skeleton";
|
|
11
|
-
import "@/components/Beams.css";
|
|
12
|
-
|
|
13
|
-
// Dynamic import with SSR disabled for Three.js canvas component
|
|
14
|
-
const Beams = dynamic(() => import("@/components/Beams"), { ssr: false });
|
|
15
|
-
|
|
16
|
-
export default function ProjectsPage() {
|
|
17
|
-
const [isAddDialogOpen, setIsAddDialogOpen] = useState(false);
|
|
18
|
-
const { projects, isLoading, error, addProject, updateProjectTags } = useProjects();
|
|
19
|
-
|
|
20
|
-
const handleAddProject = async (input: { name: string; path: string }) => {
|
|
21
|
-
await addProject(input);
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
return (
|
|
25
|
-
<div className="dark relative min-h-screen">
|
|
26
|
-
{/* Beams Background - fixed, full-screen, z-0 */}
|
|
27
|
-
<div className="fixed inset-0 z-0">
|
|
28
|
-
<Beams
|
|
29
|
-
beamWidth={8}
|
|
30
|
-
beamHeight={14}
|
|
31
|
-
beamNumber={20}
|
|
32
|
-
lightColor="#f0c7ff"
|
|
33
|
-
speed={2}
|
|
34
|
-
noiseIntensity={1.75}
|
|
35
|
-
scale={0.2}
|
|
36
|
-
rotation={30}
|
|
37
|
-
/>
|
|
38
|
-
</div>
|
|
39
|
-
|
|
40
|
-
{/* Settings Icon - fixed top-right, z-20 */}
|
|
41
|
-
<Link
|
|
42
|
-
href="/settings"
|
|
43
|
-
aria-label="Settings"
|
|
44
|
-
className="fixed right-6 top-6 z-20 rounded-md p-2 text-zinc-400 hover:bg-zinc-800/50 hover:text-zinc-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-zinc-400 focus-visible:ring-offset-2 focus-visible:ring-offset-transparent"
|
|
45
|
-
>
|
|
46
|
-
<Settings className="h-5 w-5" aria-hidden="true" />
|
|
47
|
-
</Link>
|
|
48
|
-
|
|
49
|
-
{/* Main Content */}
|
|
50
|
-
<main className="relative z-10 flex flex-col items-center px-6 py-16">
|
|
51
|
-
{/* Centered Heading with Space Grotesk */}
|
|
52
|
-
<h1 className="mb-12 text-center text-balance font-heading text-4xl font-bold tracking-tight text-white sm:text-5xl">
|
|
53
|
-
Manage Your Beads Projects
|
|
54
|
-
</h1>
|
|
55
|
-
|
|
56
|
-
<div className="w-full max-w-[1200px]">
|
|
57
|
-
{isLoading ? (
|
|
58
|
-
<div role="status" aria-label="Loading projects" className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
|
59
|
-
{[1, 2, 3].map((i) => (
|
|
60
|
-
<div key={i} className="rounded-xl border bg-card/70 p-4 backdrop-blur-md">
|
|
61
|
-
<div className="mb-3 flex gap-1.5">
|
|
62
|
-
<Skeleton className="h-5 w-16" />
|
|
63
|
-
<Skeleton className="h-5 w-12" />
|
|
64
|
-
</div>
|
|
65
|
-
<Skeleton className="h-5 w-40" />
|
|
66
|
-
<Skeleton className="mt-2 h-4 w-48" />
|
|
67
|
-
<Skeleton className="mt-4 h-4 w-32" />
|
|
68
|
-
<Skeleton className="mt-2 h-3 w-28" />
|
|
69
|
-
</div>
|
|
70
|
-
))}
|
|
71
|
-
</div>
|
|
72
|
-
) : error ? (
|
|
73
|
-
<div className="rounded-lg border border-red-800/50 bg-red-950/70 p-6 text-center backdrop-blur-md">
|
|
74
|
-
<p className="text-red-400">Error loading projects: {error.message}</p>
|
|
75
|
-
<p className="mt-2 text-sm text-red-500">
|
|
76
|
-
Make sure the Tauri backend is running.
|
|
77
|
-
</p>
|
|
78
|
-
</div>
|
|
79
|
-
) : projects.length === 0 ? (
|
|
80
|
-
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
|
81
|
-
<div className="rounded-lg border border-dashed border-zinc-700 bg-card/70 p-6 text-center text-zinc-400 backdrop-blur-md">
|
|
82
|
-
<p>No projects yet</p>
|
|
83
|
-
<p className="mt-1 text-sm text-zinc-500">Click the button below to add a project</p>
|
|
84
|
-
</div>
|
|
85
|
-
</div>
|
|
86
|
-
) : (
|
|
87
|
-
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
|
88
|
-
{projects.map((project) => (
|
|
89
|
-
<ProjectCard
|
|
90
|
-
key={project.id}
|
|
91
|
-
id={project.id}
|
|
92
|
-
name={project.name}
|
|
93
|
-
path={project.path}
|
|
94
|
-
tags={project.tags}
|
|
95
|
-
onTagsChange={(tags) => updateProjectTags(project.id, tags)}
|
|
96
|
-
/>
|
|
97
|
-
))}
|
|
98
|
-
</div>
|
|
99
|
-
)}
|
|
100
|
-
</div>
|
|
101
|
-
</main>
|
|
102
|
-
|
|
103
|
-
{/* FAB - Add Project, z-20 */}
|
|
104
|
-
<button
|
|
105
|
-
onClick={() => setIsAddDialogOpen(true)}
|
|
106
|
-
className="fixed bottom-6 right-6 z-20 flex h-14 w-14 items-center justify-center rounded-full bg-zinc-100 text-zinc-900 shadow-lg hover:bg-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-zinc-100 focus-visible:ring-offset-2 focus-visible:ring-offset-transparent"
|
|
107
|
-
aria-label="Add Project"
|
|
108
|
-
>
|
|
109
|
-
<svg
|
|
110
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
111
|
-
width="24"
|
|
112
|
-
height="24"
|
|
113
|
-
viewBox="0 0 24 24"
|
|
114
|
-
fill="none"
|
|
115
|
-
stroke="currentColor"
|
|
116
|
-
strokeWidth="2"
|
|
117
|
-
strokeLinecap="round"
|
|
118
|
-
strokeLinejoin="round"
|
|
119
|
-
aria-hidden="true"
|
|
120
|
-
>
|
|
121
|
-
<path d="M5 12h14" />
|
|
122
|
-
<path d="M12 5v14" />
|
|
123
|
-
</svg>
|
|
124
|
-
</button>
|
|
125
|
-
|
|
126
|
-
{/* Add Project Dialog */}
|
|
127
|
-
<AddProjectDialog
|
|
128
|
-
open={isAddDialogOpen}
|
|
129
|
-
onOpenChange={setIsAddDialogOpen}
|
|
130
|
-
onAddProject={handleAddProject}
|
|
131
|
-
/>
|
|
132
|
-
</div>
|
|
133
|
-
);
|
|
134
|
-
}
|
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import { useState } from "react";
|
|
4
|
-
import Link from "next/link";
|
|
5
|
-
import dynamic from "next/dynamic";
|
|
6
|
-
import { Settings } from "lucide-react";
|
|
7
|
-
import { ProjectCard } from "@/components/project-card";
|
|
8
|
-
import { AddProjectDialog } from "@/components/add-project-dialog";
|
|
9
|
-
import { useProjects } from "@/hooks/use-projects";
|
|
10
|
-
import { Skeleton } from "@/components/ui/skeleton";
|
|
11
|
-
import "@/components/Beams.css";
|
|
12
|
-
|
|
13
|
-
// Dynamic import with SSR disabled for Three.js canvas component
|
|
14
|
-
const Beams = dynamic(() => import("@/components/Beams"), { ssr: false });
|
|
15
|
-
|
|
16
|
-
export default function ProjectsPage() {
|
|
17
|
-
const [isAddDialogOpen, setIsAddDialogOpen] = useState(false);
|
|
18
|
-
const { projects, isLoading, error, addProject, updateProjectTags } = useProjects();
|
|
19
|
-
|
|
20
|
-
const handleAddProject = async (input: { name: string; path: string }) => {
|
|
21
|
-
await addProject(input);
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
return (
|
|
25
|
-
<div className="dark relative min-h-screen">
|
|
26
|
-
{/* Beams Background - fixed, full-screen, z-0 */}
|
|
27
|
-
<div className="fixed inset-0 z-0">
|
|
28
|
-
<Beams
|
|
29
|
-
beamWidth={8}
|
|
30
|
-
beamHeight={14}
|
|
31
|
-
beamNumber={20}
|
|
32
|
-
lightColor="#ffffff"
|
|
33
|
-
speed={2}
|
|
34
|
-
noiseIntensity={1.75}
|
|
35
|
-
scale={0.2}
|
|
36
|
-
rotation={30}
|
|
37
|
-
/>
|
|
38
|
-
</div>
|
|
39
|
-
|
|
40
|
-
{/* Settings Icon - fixed top-right, z-20 */}
|
|
41
|
-
<Link
|
|
42
|
-
href="/settings"
|
|
43
|
-
aria-label="Settings"
|
|
44
|
-
className="fixed right-6 top-6 z-20 rounded-md p-2 text-zinc-400 hover:bg-zinc-800/50 hover:text-zinc-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-zinc-400 focus-visible:ring-offset-2 focus-visible:ring-offset-transparent"
|
|
45
|
-
>
|
|
46
|
-
<Settings className="h-5 w-5" aria-hidden="true" />
|
|
47
|
-
</Link>
|
|
48
|
-
|
|
49
|
-
{/* Main Content */}
|
|
50
|
-
<main className="relative z-10 flex flex-col items-center px-6 py-16">
|
|
51
|
-
{/* Centered Heading with Space Grotesk */}
|
|
52
|
-
<h1 className="mb-12 text-center text-balance font-heading text-4xl font-bold tracking-tight text-white sm:text-5xl">
|
|
53
|
-
Manage Your Beads Projects
|
|
54
|
-
</h1>
|
|
55
|
-
|
|
56
|
-
<div className="w-full max-w-[1200px]">
|
|
57
|
-
{isLoading ? (
|
|
58
|
-
<div role="status" aria-label="Loading projects" className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
|
59
|
-
{[1, 2, 3].map((i) => (
|
|
60
|
-
<div key={i} className="rounded-xl border bg-card/70 p-4 backdrop-blur-md">
|
|
61
|
-
<div className="mb-3 flex gap-1.5">
|
|
62
|
-
<Skeleton className="h-5 w-16" />
|
|
63
|
-
<Skeleton className="h-5 w-12" />
|
|
64
|
-
</div>
|
|
65
|
-
<Skeleton className="h-5 w-40" />
|
|
66
|
-
<Skeleton className="mt-2 h-4 w-48" />
|
|
67
|
-
<Skeleton className="mt-4 h-4 w-32" />
|
|
68
|
-
<Skeleton className="mt-2 h-3 w-28" />
|
|
69
|
-
</div>
|
|
70
|
-
))}
|
|
71
|
-
</div>
|
|
72
|
-
) : error ? (
|
|
73
|
-
<div className="rounded-lg border border-red-800/50 bg-red-950/70 p-6 text-center backdrop-blur-md">
|
|
74
|
-
<p className="text-red-400">Error loading projects: {error.message}</p>
|
|
75
|
-
<p className="mt-2 text-sm text-red-500">
|
|
76
|
-
Make sure the Tauri backend is running.
|
|
77
|
-
</p>
|
|
78
|
-
</div>
|
|
79
|
-
) : projects.length === 0 ? (
|
|
80
|
-
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
|
81
|
-
<div className="rounded-lg border border-dashed border-zinc-700 bg-card/70 p-6 text-center text-zinc-400 backdrop-blur-md">
|
|
82
|
-
<p>No projects yet</p>
|
|
83
|
-
<p className="mt-1 text-sm text-zinc-500">Click the button below to add a project</p>
|
|
84
|
-
</div>
|
|
85
|
-
</div>
|
|
86
|
-
) : (
|
|
87
|
-
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
|
88
|
-
{projects.map((project) => (
|
|
89
|
-
<ProjectCard
|
|
90
|
-
key={project.id}
|
|
91
|
-
id={project.id}
|
|
92
|
-
name={project.name}
|
|
93
|
-
path={project.path}
|
|
94
|
-
tags={project.tags}
|
|
95
|
-
onTagsChange={(tags) => updateProjectTags(project.id, tags)}
|
|
96
|
-
/>
|
|
97
|
-
))}
|
|
98
|
-
</div>
|
|
99
|
-
)}
|
|
100
|
-
</div>
|
|
101
|
-
</main>
|
|
102
|
-
|
|
103
|
-
{/* FAB - Add Project, z-20 */}
|
|
104
|
-
<button
|
|
105
|
-
onClick={() => setIsAddDialogOpen(true)}
|
|
106
|
-
className="fixed bottom-6 right-6 z-20 flex h-14 w-14 items-center justify-center rounded-full bg-zinc-100 text-zinc-900 shadow-lg hover:bg-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-zinc-100 focus-visible:ring-offset-2 focus-visible:ring-offset-transparent"
|
|
107
|
-
aria-label="Add Project"
|
|
108
|
-
>
|
|
109
|
-
<svg
|
|
110
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
111
|
-
width="24"
|
|
112
|
-
height="24"
|
|
113
|
-
viewBox="0 0 24 24"
|
|
114
|
-
fill="none"
|
|
115
|
-
stroke="currentColor"
|
|
116
|
-
strokeWidth="2"
|
|
117
|
-
strokeLinecap="round"
|
|
118
|
-
strokeLinejoin="round"
|
|
119
|
-
aria-hidden="true"
|
|
120
|
-
>
|
|
121
|
-
<path d="M5 12h14" />
|
|
122
|
-
<path d="M12 5v14" />
|
|
123
|
-
</svg>
|
|
124
|
-
</button>
|
|
125
|
-
|
|
126
|
-
{/* Add Project Dialog */}
|
|
127
|
-
<AddProjectDialog
|
|
128
|
-
open={isAddDialogOpen}
|
|
129
|
-
onOpenChange={setIsAddDialogOpen}
|
|
130
|
-
onAddProject={handleAddProject}
|
|
131
|
-
/>
|
|
132
|
-
</div>
|
|
133
|
-
);
|
|
134
|
-
}
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import { useState } from "react";
|
|
4
|
-
import Link from "next/link";
|
|
5
|
-
import dynamic from "next/dynamic";
|
|
6
|
-
import { Settings } from "lucide-react";
|
|
7
|
-
import { ProjectCard } from "@/components/project-card";
|
|
8
|
-
import { AddProjectDialog } from "@/components/add-project-dialog";
|
|
9
|
-
import { useProjects } from "@/hooks/use-projects";
|
|
10
|
-
import { Skeleton } from "@/components/ui/skeleton";
|
|
11
|
-
|
|
12
|
-
// Dynamic import with SSR disabled for WebGL canvas component
|
|
13
|
-
const RippleGrid = dynamic(() => import("@/components/RippleGrid"), { ssr: false });
|
|
14
|
-
|
|
15
|
-
export default function ProjectsPage() {
|
|
16
|
-
const [isAddDialogOpen, setIsAddDialogOpen] = useState(false);
|
|
17
|
-
const { projects, isLoading, error, addProject, updateProjectTags } = useProjects();
|
|
18
|
-
|
|
19
|
-
const handleAddProject = async (input: { name: string; path: string }) => {
|
|
20
|
-
await addProject(input);
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
return (
|
|
24
|
-
<div className="dark relative min-h-screen bg-[#0d0b14]">
|
|
25
|
-
{/* RippleGrid Background - fixed, full-screen, z-0 */}
|
|
26
|
-
<div className="fixed inset-0 z-0 overflow-hidden">
|
|
27
|
-
<RippleGrid
|
|
28
|
-
gridColor="#302a4c"
|
|
29
|
-
rippleIntensity={0.02}
|
|
30
|
-
gridSize={10}
|
|
31
|
-
gridThickness={33}
|
|
32
|
-
fadeDistance={2.7}
|
|
33
|
-
vignetteStrength={3.5}
|
|
34
|
-
glowIntensity={0.5}
|
|
35
|
-
opacity={1}
|
|
36
|
-
gridRotation={0}
|
|
37
|
-
mouseInteractionRadius={0.8}
|
|
38
|
-
mouseInteraction={false}
|
|
39
|
-
enableRainbow={false}
|
|
40
|
-
/>
|
|
41
|
-
</div>
|
|
42
|
-
|
|
43
|
-
{/* Settings Icon - fixed top-right, z-20 */}
|
|
44
|
-
<Link
|
|
45
|
-
href="/settings"
|
|
46
|
-
aria-label="Settings"
|
|
47
|
-
className="fixed right-6 top-6 z-20 rounded-md p-2 text-zinc-400 hover:bg-zinc-800/50 hover:text-zinc-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-zinc-400 focus-visible:ring-offset-2 focus-visible:ring-offset-transparent"
|
|
48
|
-
>
|
|
49
|
-
<Settings className="h-5 w-5" aria-hidden="true" />
|
|
50
|
-
</Link>
|
|
51
|
-
|
|
52
|
-
{/* Main Content */}
|
|
53
|
-
<main className="relative z-10 flex flex-col items-center px-6 py-16">
|
|
54
|
-
{/* Centered Heading with Space Grotesk */}
|
|
55
|
-
<h1 className="mb-12 text-center text-balance font-heading text-4xl font-bold tracking-tight text-white sm:text-5xl">
|
|
56
|
-
Manage Your Beads Projects
|
|
57
|
-
</h1>
|
|
58
|
-
|
|
59
|
-
<div className="w-full max-w-[1200px]">
|
|
60
|
-
{isLoading ? (
|
|
61
|
-
<div role="status" aria-label="Loading projects" className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
|
62
|
-
{[1, 2, 3].map((i) => (
|
|
63
|
-
<div key={i} className="rounded-xl border bg-card/70 p-4 backdrop-blur-md">
|
|
64
|
-
<div className="mb-3 flex gap-1.5">
|
|
65
|
-
<Skeleton className="h-5 w-16" />
|
|
66
|
-
<Skeleton className="h-5 w-12" />
|
|
67
|
-
</div>
|
|
68
|
-
<Skeleton className="h-5 w-40" />
|
|
69
|
-
<Skeleton className="mt-2 h-4 w-48" />
|
|
70
|
-
<Skeleton className="mt-4 h-4 w-32" />
|
|
71
|
-
<Skeleton className="mt-2 h-3 w-28" />
|
|
72
|
-
</div>
|
|
73
|
-
))}
|
|
74
|
-
</div>
|
|
75
|
-
) : error ? (
|
|
76
|
-
<div className="rounded-lg border border-red-800/50 bg-red-950/70 p-6 text-center backdrop-blur-md">
|
|
77
|
-
<p className="text-red-400">Error loading projects: {error.message}</p>
|
|
78
|
-
<p className="mt-2 text-sm text-red-500">
|
|
79
|
-
Make sure the Tauri backend is running.
|
|
80
|
-
</p>
|
|
81
|
-
</div>
|
|
82
|
-
) : projects.length === 0 ? (
|
|
83
|
-
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
|
84
|
-
<div className="rounded-lg border border-dashed border-zinc-700 bg-card/70 p-6 text-center text-zinc-400 backdrop-blur-md">
|
|
85
|
-
<p>No projects yet</p>
|
|
86
|
-
<p className="mt-1 text-sm text-zinc-500">Click the button below to add a project</p>
|
|
87
|
-
</div>
|
|
88
|
-
</div>
|
|
89
|
-
) : (
|
|
90
|
-
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
|
91
|
-
{projects.map((project) => (
|
|
92
|
-
<ProjectCard
|
|
93
|
-
key={project.id}
|
|
94
|
-
id={project.id}
|
|
95
|
-
name={project.name}
|
|
96
|
-
path={project.path}
|
|
97
|
-
tags={project.tags}
|
|
98
|
-
beadCounts={project.beadCounts}
|
|
99
|
-
onTagsChange={(tags) => updateProjectTags(project.id, tags)}
|
|
100
|
-
/>
|
|
101
|
-
))}
|
|
102
|
-
</div>
|
|
103
|
-
)}
|
|
104
|
-
</div>
|
|
105
|
-
</main>
|
|
106
|
-
|
|
107
|
-
{/* FAB - Add Project, z-20 */}
|
|
108
|
-
<button
|
|
109
|
-
onClick={() => setIsAddDialogOpen(true)}
|
|
110
|
-
className="fixed bottom-6 right-6 z-20 flex h-14 w-14 items-center justify-center rounded-full bg-zinc-100 text-zinc-900 shadow-lg hover:bg-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-zinc-100 focus-visible:ring-offset-2 focus-visible:ring-offset-transparent"
|
|
111
|
-
aria-label="Add Project"
|
|
112
|
-
>
|
|
113
|
-
<svg
|
|
114
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
115
|
-
width="24"
|
|
116
|
-
height="24"
|
|
117
|
-
viewBox="0 0 24 24"
|
|
118
|
-
fill="none"
|
|
119
|
-
stroke="currentColor"
|
|
120
|
-
strokeWidth="2"
|
|
121
|
-
strokeLinecap="round"
|
|
122
|
-
strokeLinejoin="round"
|
|
123
|
-
aria-hidden="true"
|
|
124
|
-
>
|
|
125
|
-
<path d="M5 12h14" />
|
|
126
|
-
<path d="M12 5v14" />
|
|
127
|
-
</svg>
|
|
128
|
-
</button>
|
|
129
|
-
|
|
130
|
-
{/* Add Project Dialog */}
|
|
131
|
-
<AddProjectDialog
|
|
132
|
-
open={isAddDialogOpen}
|
|
133
|
-
onOpenChange={setIsAddDialogOpen}
|
|
134
|
-
onAddProject={handleAddProject}
|
|
135
|
-
/>
|
|
136
|
-
</div>
|
|
137
|
-
);
|
|
138
|
-
}
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import { useState } from "react";
|
|
4
|
-
import Link from "next/link";
|
|
5
|
-
import dynamic from "next/dynamic";
|
|
6
|
-
import { Settings } from "lucide-react";
|
|
7
|
-
import { ProjectCard } from "@/components/project-card";
|
|
8
|
-
import { AddProjectDialog } from "@/components/add-project-dialog";
|
|
9
|
-
import { useProjects } from "@/hooks/use-projects";
|
|
10
|
-
import { Skeleton } from "@/components/ui/skeleton";
|
|
11
|
-
|
|
12
|
-
// Dynamic import with SSR disabled for WebGL canvas component
|
|
13
|
-
const RippleGrid = dynamic(() => import("@/components/RippleGrid"), { ssr: false });
|
|
14
|
-
|
|
15
|
-
export default function ProjectsPage() {
|
|
16
|
-
const [isAddDialogOpen, setIsAddDialogOpen] = useState(false);
|
|
17
|
-
const { projects, isLoading, error, addProject, updateProjectTags } = useProjects();
|
|
18
|
-
|
|
19
|
-
const handleAddProject = async (input: { name: string; path: string }) => {
|
|
20
|
-
await addProject(input);
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
return (
|
|
24
|
-
<div className="dark relative min-h-screen bg-[#0d0b14]">
|
|
25
|
-
{/* RippleGrid Background - fixed, full-screen, z-0 */}
|
|
26
|
-
<div className="fixed inset-0 z-0 overflow-hidden">
|
|
27
|
-
<RippleGrid
|
|
28
|
-
gridColor="#302a4c"
|
|
29
|
-
rippleIntensity={0.02}
|
|
30
|
-
gridSize={15}
|
|
31
|
-
gridThickness={33}
|
|
32
|
-
fadeDistance={2.7}
|
|
33
|
-
vignetteStrength={3.5}
|
|
34
|
-
glowIntensity={0.5}
|
|
35
|
-
opacity={1}
|
|
36
|
-
gridRotation={0}
|
|
37
|
-
mouseInteractionRadius={0.8}
|
|
38
|
-
mouseInteraction={false}
|
|
39
|
-
enableRainbow={false}
|
|
40
|
-
/>
|
|
41
|
-
</div>
|
|
42
|
-
|
|
43
|
-
{/* Settings Icon - fixed top-right, z-20 */}
|
|
44
|
-
<Link
|
|
45
|
-
href="/settings"
|
|
46
|
-
aria-label="Settings"
|
|
47
|
-
className="fixed right-6 top-6 z-20 rounded-md p-2 text-zinc-400 hover:bg-zinc-800/50 hover:text-zinc-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-zinc-400 focus-visible:ring-offset-2 focus-visible:ring-offset-transparent"
|
|
48
|
-
>
|
|
49
|
-
<Settings className="h-5 w-5" aria-hidden="true" />
|
|
50
|
-
</Link>
|
|
51
|
-
|
|
52
|
-
{/* Main Content */}
|
|
53
|
-
<main className="relative z-10 flex flex-col items-center px-6 py-16">
|
|
54
|
-
{/* Centered Heading with Space Grotesk */}
|
|
55
|
-
<h1 className="mb-12 text-center text-balance font-heading text-4xl font-bold tracking-tight text-white sm:text-5xl">
|
|
56
|
-
Manage Your Beads Projects
|
|
57
|
-
</h1>
|
|
58
|
-
|
|
59
|
-
<div className="w-full max-w-[1200px]">
|
|
60
|
-
{isLoading ? (
|
|
61
|
-
<div role="status" aria-label="Loading projects" className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
|
62
|
-
{[1, 2, 3].map((i) => (
|
|
63
|
-
<div key={i} className="rounded-xl border bg-card/70 p-4 backdrop-blur-md">
|
|
64
|
-
<div className="mb-3 flex gap-1.5">
|
|
65
|
-
<Skeleton className="h-5 w-16" />
|
|
66
|
-
<Skeleton className="h-5 w-12" />
|
|
67
|
-
</div>
|
|
68
|
-
<Skeleton className="h-5 w-40" />
|
|
69
|
-
<Skeleton className="mt-2 h-4 w-48" />
|
|
70
|
-
<Skeleton className="mt-4 h-4 w-32" />
|
|
71
|
-
<Skeleton className="mt-2 h-3 w-28" />
|
|
72
|
-
</div>
|
|
73
|
-
))}
|
|
74
|
-
</div>
|
|
75
|
-
) : error ? (
|
|
76
|
-
<div className="rounded-lg border border-red-800/50 bg-red-950/70 p-6 text-center backdrop-blur-md">
|
|
77
|
-
<p className="text-red-400">Error loading projects: {error.message}</p>
|
|
78
|
-
<p className="mt-2 text-sm text-red-500">
|
|
79
|
-
Make sure the Tauri backend is running.
|
|
80
|
-
</p>
|
|
81
|
-
</div>
|
|
82
|
-
) : projects.length === 0 ? (
|
|
83
|
-
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
|
84
|
-
<div className="rounded-lg border border-dashed border-zinc-700 bg-card/70 p-6 text-center text-zinc-400 backdrop-blur-md">
|
|
85
|
-
<p>No projects yet</p>
|
|
86
|
-
<p className="mt-1 text-sm text-zinc-500">Click the button below to add a project</p>
|
|
87
|
-
</div>
|
|
88
|
-
</div>
|
|
89
|
-
) : (
|
|
90
|
-
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
|
91
|
-
{projects.map((project) => (
|
|
92
|
-
<ProjectCard
|
|
93
|
-
key={project.id}
|
|
94
|
-
id={project.id}
|
|
95
|
-
name={project.name}
|
|
96
|
-
path={project.path}
|
|
97
|
-
tags={project.tags}
|
|
98
|
-
beadCounts={project.beadCounts}
|
|
99
|
-
onTagsChange={(tags) => updateProjectTags(project.id, tags)}
|
|
100
|
-
/>
|
|
101
|
-
))}
|
|
102
|
-
</div>
|
|
103
|
-
)}
|
|
104
|
-
</div>
|
|
105
|
-
</main>
|
|
106
|
-
|
|
107
|
-
{/* FAB - Add Project, z-20 */}
|
|
108
|
-
<button
|
|
109
|
-
onClick={() => setIsAddDialogOpen(true)}
|
|
110
|
-
className="fixed bottom-6 right-6 z-20 flex h-14 w-14 items-center justify-center rounded-full bg-zinc-100 text-zinc-900 shadow-lg hover:bg-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-zinc-100 focus-visible:ring-offset-2 focus-visible:ring-offset-transparent"
|
|
111
|
-
aria-label="Add Project"
|
|
112
|
-
>
|
|
113
|
-
<svg
|
|
114
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
115
|
-
width="24"
|
|
116
|
-
height="24"
|
|
117
|
-
viewBox="0 0 24 24"
|
|
118
|
-
fill="none"
|
|
119
|
-
stroke="currentColor"
|
|
120
|
-
strokeWidth="2"
|
|
121
|
-
strokeLinecap="round"
|
|
122
|
-
strokeLinejoin="round"
|
|
123
|
-
aria-hidden="true"
|
|
124
|
-
>
|
|
125
|
-
<path d="M5 12h14" />
|
|
126
|
-
<path d="M12 5v14" />
|
|
127
|
-
</svg>
|
|
128
|
-
</button>
|
|
129
|
-
|
|
130
|
-
{/* Add Project Dialog */}
|
|
131
|
-
<AddProjectDialog
|
|
132
|
-
open={isAddDialogOpen}
|
|
133
|
-
onOpenChange={setIsAddDialogOpen}
|
|
134
|
-
onAddProject={handleAddProject}
|
|
135
|
-
/>
|
|
136
|
-
</div>
|
|
137
|
-
);
|
|
138
|
-
}
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import { useState } from "react";
|
|
4
|
-
import Link from "next/link";
|
|
5
|
-
import dynamic from "next/dynamic";
|
|
6
|
-
import { Settings } from "lucide-react";
|
|
7
|
-
import { ProjectCard } from "@/components/project-card";
|
|
8
|
-
import { AddProjectDialog } from "@/components/add-project-dialog";
|
|
9
|
-
import { useProjects } from "@/hooks/use-projects";
|
|
10
|
-
import { Skeleton } from "@/components/ui/skeleton";
|
|
11
|
-
|
|
12
|
-
// Dynamic import with SSR disabled for WebGL canvas component
|
|
13
|
-
const RippleGrid = dynamic(() => import("@/components/RippleGrid"), { ssr: false });
|
|
14
|
-
|
|
15
|
-
export default function ProjectsPage() {
|
|
16
|
-
const [isAddDialogOpen, setIsAddDialogOpen] = useState(false);
|
|
17
|
-
const { projects, isLoading, error, addProject, updateProjectTags } = useProjects();
|
|
18
|
-
|
|
19
|
-
const handleAddProject = async (input: { name: string; path: string }) => {
|
|
20
|
-
await addProject(input);
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
return (
|
|
24
|
-
<div className="dark relative min-h-screen bg-[#0d0b14]">
|
|
25
|
-
{/* RippleGrid Background - fixed, full-screen, z-0 */}
|
|
26
|
-
<div className="fixed inset-0 z-0 overflow-hidden">
|
|
27
|
-
<RippleGrid
|
|
28
|
-
gridColor="#302a4c"
|
|
29
|
-
rippleIntensity={0.02}
|
|
30
|
-
gridSize={15}
|
|
31
|
-
gridThickness={15}
|
|
32
|
-
fadeDistance={2.7}
|
|
33
|
-
vignetteStrength={3.5}
|
|
34
|
-
glowIntensity={0.5}
|
|
35
|
-
opacity={1}
|
|
36
|
-
gridRotation={0}
|
|
37
|
-
mouseInteractionRadius={0.8}
|
|
38
|
-
mouseInteraction={false}
|
|
39
|
-
enableRainbow={false}
|
|
40
|
-
/>
|
|
41
|
-
</div>
|
|
42
|
-
|
|
43
|
-
{/* Settings Icon - fixed top-right, z-20 */}
|
|
44
|
-
<Link
|
|
45
|
-
href="/settings"
|
|
46
|
-
aria-label="Settings"
|
|
47
|
-
className="fixed right-6 top-6 z-20 rounded-md p-2 text-zinc-400 hover:bg-zinc-800/50 hover:text-zinc-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-zinc-400 focus-visible:ring-offset-2 focus-visible:ring-offset-transparent"
|
|
48
|
-
>
|
|
49
|
-
<Settings className="h-5 w-5" aria-hidden="true" />
|
|
50
|
-
</Link>
|
|
51
|
-
|
|
52
|
-
{/* Main Content */}
|
|
53
|
-
<main className="relative z-10 flex flex-col items-center px-6 py-16">
|
|
54
|
-
{/* Centered Heading with Space Grotesk */}
|
|
55
|
-
<h1 className="mb-12 text-center text-balance font-heading text-4xl font-bold tracking-tight text-white sm:text-5xl">
|
|
56
|
-
Manage Your Beads Projects
|
|
57
|
-
</h1>
|
|
58
|
-
|
|
59
|
-
<div className="w-full max-w-[1200px]">
|
|
60
|
-
{isLoading ? (
|
|
61
|
-
<div role="status" aria-label="Loading projects" className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
|
62
|
-
{[1, 2, 3].map((i) => (
|
|
63
|
-
<div key={i} className="rounded-xl border bg-card/70 p-4 backdrop-blur-md">
|
|
64
|
-
<div className="mb-3 flex gap-1.5">
|
|
65
|
-
<Skeleton className="h-5 w-16" />
|
|
66
|
-
<Skeleton className="h-5 w-12" />
|
|
67
|
-
</div>
|
|
68
|
-
<Skeleton className="h-5 w-40" />
|
|
69
|
-
<Skeleton className="mt-2 h-4 w-48" />
|
|
70
|
-
<Skeleton className="mt-4 h-4 w-32" />
|
|
71
|
-
<Skeleton className="mt-2 h-3 w-28" />
|
|
72
|
-
</div>
|
|
73
|
-
))}
|
|
74
|
-
</div>
|
|
75
|
-
) : error ? (
|
|
76
|
-
<div className="rounded-lg border border-red-800/50 bg-red-950/70 p-6 text-center backdrop-blur-md">
|
|
77
|
-
<p className="text-red-400">Error loading projects: {error.message}</p>
|
|
78
|
-
<p className="mt-2 text-sm text-red-500">
|
|
79
|
-
Make sure the Tauri backend is running.
|
|
80
|
-
</p>
|
|
81
|
-
</div>
|
|
82
|
-
) : projects.length === 0 ? (
|
|
83
|
-
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
|
84
|
-
<div className="rounded-lg border border-dashed border-zinc-700 bg-card/70 p-6 text-center text-zinc-400 backdrop-blur-md">
|
|
85
|
-
<p>No projects yet</p>
|
|
86
|
-
<p className="mt-1 text-sm text-zinc-500">Click the button below to add a project</p>
|
|
87
|
-
</div>
|
|
88
|
-
</div>
|
|
89
|
-
) : (
|
|
90
|
-
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
|
91
|
-
{projects.map((project) => (
|
|
92
|
-
<ProjectCard
|
|
93
|
-
key={project.id}
|
|
94
|
-
id={project.id}
|
|
95
|
-
name={project.name}
|
|
96
|
-
path={project.path}
|
|
97
|
-
tags={project.tags}
|
|
98
|
-
beadCounts={project.beadCounts}
|
|
99
|
-
onTagsChange={(tags) => updateProjectTags(project.id, tags)}
|
|
100
|
-
/>
|
|
101
|
-
))}
|
|
102
|
-
</div>
|
|
103
|
-
)}
|
|
104
|
-
</div>
|
|
105
|
-
</main>
|
|
106
|
-
|
|
107
|
-
{/* FAB - Add Project, z-20 */}
|
|
108
|
-
<button
|
|
109
|
-
onClick={() => setIsAddDialogOpen(true)}
|
|
110
|
-
className="fixed bottom-6 right-6 z-20 flex h-14 w-14 items-center justify-center rounded-full bg-zinc-100 text-zinc-900 shadow-lg hover:bg-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-zinc-100 focus-visible:ring-offset-2 focus-visible:ring-offset-transparent"
|
|
111
|
-
aria-label="Add Project"
|
|
112
|
-
>
|
|
113
|
-
<svg
|
|
114
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
115
|
-
width="24"
|
|
116
|
-
height="24"
|
|
117
|
-
viewBox="0 0 24 24"
|
|
118
|
-
fill="none"
|
|
119
|
-
stroke="currentColor"
|
|
120
|
-
strokeWidth="2"
|
|
121
|
-
strokeLinecap="round"
|
|
122
|
-
strokeLinejoin="round"
|
|
123
|
-
aria-hidden="true"
|
|
124
|
-
>
|
|
125
|
-
<path d="M5 12h14" />
|
|
126
|
-
<path d="M12 5v14" />
|
|
127
|
-
</svg>
|
|
128
|
-
</button>
|
|
129
|
-
|
|
130
|
-
{/* Add Project Dialog */}
|
|
131
|
-
<AddProjectDialog
|
|
132
|
-
open={isAddDialogOpen}
|
|
133
|
-
onOpenChange={setIsAddDialogOpen}
|
|
134
|
-
onAddProject={handleAddProject}
|
|
135
|
-
/>
|
|
136
|
-
</div>
|
|
137
|
-
);
|
|
138
|
-
}
|