@burdenoff/microfe-workspaces 2026.625.3 → 2026.625.5
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/dist/hooks/useMemberMutations.js +6 -6
- package/dist/hooks/useMemberMutations.js.map +1 -1
- package/dist/pages/ActivityListPage.js +32 -48
- package/dist/pages/ActivityListPage.js.map +1 -1
- package/dist/pages/MembersListPage.js +196 -241
- package/dist/pages/MembersListPage.js.map +1 -1
- package/dist/pages/PendingInvitesPage.js +69 -78
- package/dist/pages/PendingInvitesPage.js.map +1 -1
- package/dist/pages/ProjectDetailPage.js +37 -52
- package/dist/pages/ProjectDetailPage.js.map +1 -1
- package/dist/pages/ProjectMembersPage.js +73 -86
- package/dist/pages/ProjectMembersPage.js.map +1 -1
- package/dist/pages/ProjectsListPage.js +103 -118
- package/dist/pages/ProjectsListPage.js.map +1 -1
- package/dist/pages/WorkspaceDetailPage.js +74 -76
- package/dist/pages/WorkspaceDetailPage.js.map +1 -1
- package/dist/pages/WorkspacesListPage.js +167 -178
- package/dist/pages/WorkspacesListPage.js.map +1 -1
- package/dist/pages/dashboard/widgets/AgentsWidget.js +21 -22
- package/dist/pages/dashboard/widgets/AgentsWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/ProjectsWidget.js +26 -27
- package/dist/pages/dashboard/widgets/ProjectsWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/RecentActivityWidget.js +19 -23
- package/dist/pages/dashboard/widgets/RecentActivityWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/SessionsWidget.js +30 -32
- package/dist/pages/dashboard/widgets/SessionsWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/UpcomingEventsWidget.js +18 -20
- package/dist/pages/dashboard/widgets/UpcomingEventsWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/VibesWidget.js +18 -19
- package/dist/pages/dashboard/widgets/VibesWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/WelcomeWidget.js +14 -12
- package/dist/pages/dashboard/widgets/WelcomeWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/WorkflowStatsWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/WorkspacesWidget.js +20 -21
- package/dist/pages/dashboard/widgets/WorkspacesWidget.js.map +1 -1
- package/package.json +2 -2
|
@@ -15,26 +15,26 @@ import { ProjectMemberPickerDialog as s } from "../components/ProjectMemberPicke
|
|
|
15
15
|
import { useMemo as c, useState as l } from "react";
|
|
16
16
|
import { Activity as u, Archive as d, ArrowLeft as f, Clock as p, FolderKanban as m, MoreVertical as me, UserPlus as he, Users as h } from "lucide-react";
|
|
17
17
|
import { jsx as g, jsxs as _ } from "react/jsx-runtime";
|
|
18
|
-
import { AlertDialog as ge, AlertDialogAction as _e, AlertDialogCancel as ve, AlertDialogContent as ye, AlertDialogDescription as be, AlertDialogFooter as xe, AlertDialogHeader as Se, AlertDialogTitle as Ce, Badge as v, Button as y, CardContent as b, CardHeader as x, CardTitle as S, DropdownMenu as C, DropdownMenuContent as w, DropdownMenuItem as T, DropdownMenuSeparator as E, DropdownMenuTrigger as D, EntityIdModal as O, GlassCard as k,
|
|
19
|
-
import { useNavigate as
|
|
20
|
-
import { useI18n as
|
|
18
|
+
import { AlertDialog as ge, AlertDialogAction as _e, AlertDialogCancel as ve, AlertDialogContent as ye, AlertDialogDescription as be, AlertDialogFooter as xe, AlertDialogHeader as Se, AlertDialogTitle as Ce, Badge as v, Button as y, CardContent as b, CardHeader as x, CardTitle as S, DropdownMenu as C, DropdownMenuContent as w, DropdownMenuItem as T, DropdownMenuSeparator as E, DropdownMenuTrigger as D, EntityIdModal as O, GlassCard as k, IllustratedEmptyState as A, ShowMore as we, Skeleton as j, useEntityIdModal as Te } from "@burdenoff/fe-libs/ui";
|
|
19
|
+
import { useNavigate as Ee, useParams as De } from "react-router-dom";
|
|
20
|
+
import { useI18n as Oe } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
21
21
|
//#region src/pages/ProjectDetailPage.tsx
|
|
22
22
|
function M() {
|
|
23
|
-
let { t: M } =
|
|
23
|
+
let { t: M } = Oe(), N = Te(), { workspaceId: P, projectId: F } = De();
|
|
24
24
|
te("workspaces.project-detail", {
|
|
25
25
|
workspaceId: P,
|
|
26
26
|
projectId: F,
|
|
27
27
|
requireParams: !0
|
|
28
28
|
});
|
|
29
|
-
let I =
|
|
29
|
+
let I = Ee(), { basePath: L = "/workspaces" } = e(), { withCurrentSearch: R } = ee(), { data: z, isLoading: ke, error: Ae } = ie(F || "", P), [je, B] = l(!1), [V, H] = l(!1), { mutate: Me, isPending: U } = oe(P), { mutate: Ne, isPending: W } = le(P), { mutate: Pe, isPending: G } = se(P), { mutateAsync: Fe, isPending: Ie } = ce(P), { mutateAsync: Le, isPending: Re } = ue(P), { mutateAsync: ze, isPending: Be } = de(P), { canViewProject: Ve, canDeleteProject: K, canArchiveProject: q, canListProjectMembers: J, canAddProjectMember: Y, isLoading: He } = re(), { data: Ue } = ae(F || "", P), X = c(() => fe({
|
|
30
30
|
tags: z?.tags ?? [],
|
|
31
31
|
tagAssignments: z?.tagAssignments
|
|
32
|
-
}), [z?.tags, z?.tagAssignments]), { data:
|
|
33
|
-
if (
|
|
32
|
+
}), [z?.tags, z?.tagAssignments]), { data: We } = pe(P), Ge = (We ?? []).filter((e) => e.resourceId === F || e.resourceType?.toLowerCase() === "project").length, Ke = X;
|
|
33
|
+
if (He) return /* @__PURE__ */ _("div", {
|
|
34
34
|
className: "space-y-4 p-6",
|
|
35
35
|
children: [/* @__PURE__ */ g(j, { className: "h-10 w-1/3" }), /* @__PURE__ */ g(j, { className: "h-64" })]
|
|
36
36
|
});
|
|
37
|
-
if (!
|
|
37
|
+
if (!Ve) return /* @__PURE__ */ g("div", {
|
|
38
38
|
className: "flex items-center justify-center min-h-[400px]",
|
|
39
39
|
children: /* @__PURE__ */ _("div", {
|
|
40
40
|
className: "text-center space-y-2",
|
|
@@ -49,14 +49,14 @@ function M() {
|
|
|
49
49
|
});
|
|
50
50
|
let Z = () => {
|
|
51
51
|
I(R(`${L}/${P}/projects`));
|
|
52
|
-
},
|
|
53
|
-
z && (z.archived ?
|
|
52
|
+
}, qe = () => {
|
|
53
|
+
z && (z.archived ? Ne(z.id, { onError: (e) => {
|
|
54
54
|
console.error("Failed to unarchive project:", e);
|
|
55
|
-
} }) :
|
|
55
|
+
} }) : Me(z.id, { onError: (e) => {
|
|
56
56
|
console.error("Failed to archive project:", e);
|
|
57
57
|
} }));
|
|
58
|
-
},
|
|
59
|
-
z && (ne("medium"),
|
|
58
|
+
}, Je = () => {
|
|
59
|
+
z && (ne("medium"), Pe(z.id, {
|
|
60
60
|
onSuccess: () => {
|
|
61
61
|
r("success"), B(!1), I(R(`${L}/${P}/projects`));
|
|
62
62
|
},
|
|
@@ -70,7 +70,7 @@ function M() {
|
|
|
70
70
|
if (!z) return;
|
|
71
71
|
let t = e.map((e) => a(e));
|
|
72
72
|
try {
|
|
73
|
-
await
|
|
73
|
+
await ze({
|
|
74
74
|
id: z.id,
|
|
75
75
|
input: { tags: t }
|
|
76
76
|
});
|
|
@@ -78,7 +78,7 @@ function M() {
|
|
|
78
78
|
r("warning"), console.error("Failed to sync legacy project tag mirror after updating structured project tags:", e);
|
|
79
79
|
}
|
|
80
80
|
};
|
|
81
|
-
return
|
|
81
|
+
return ke ? /* @__PURE__ */ _("div", {
|
|
82
82
|
className: "space-y-4 sm:space-y-6 p-3 sm:p-6",
|
|
83
83
|
children: [
|
|
84
84
|
/* @__PURE__ */ g(j, { className: "h-10 w-32" }),
|
|
@@ -93,39 +93,24 @@ function M() {
|
|
|
93
93
|
}),
|
|
94
94
|
/* @__PURE__ */ g(j, { className: "h-48" })
|
|
95
95
|
]
|
|
96
|
-
}) :
|
|
96
|
+
}) : Ae || !z ? /* @__PURE__ */ _("div", {
|
|
97
97
|
className: "space-y-4 p-6",
|
|
98
98
|
children: [/* @__PURE__ */ _(y, {
|
|
99
99
|
variant: "ghost",
|
|
100
100
|
onClick: Z,
|
|
101
101
|
className: "gap-2",
|
|
102
102
|
children: [/* @__PURE__ */ g(f, { size: 20 }), n(M, "projectDetail.backToProjects", "Back to Projects")]
|
|
103
|
-
}), /* @__PURE__ */
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
}),
|
|
113
|
-
|
|
114
|
-
className: "text-lg font-semibold mb-2",
|
|
115
|
-
children: n(M, "projectDetail.projectNotFound", "Project not found")
|
|
116
|
-
}),
|
|
117
|
-
/* @__PURE__ */ g("p", {
|
|
118
|
-
className: "text-text-secondary max-w-sm mx-auto mb-4",
|
|
119
|
-
children: n(M, "projectDetail.projectNotFoundDescription", "The project you're looking for doesn't exist or you don't have permission to view it.")
|
|
120
|
-
}),
|
|
121
|
-
/* @__PURE__ */ _(y, {
|
|
122
|
-
onClick: Z,
|
|
123
|
-
children: [/* @__PURE__ */ g(f, {
|
|
124
|
-
size: 16,
|
|
125
|
-
className: "mr-2"
|
|
126
|
-
}), n(M, "projectDetail.backToProjects", "Back to Projects")]
|
|
127
|
-
})
|
|
128
|
-
]
|
|
103
|
+
}), /* @__PURE__ */ g(A, {
|
|
104
|
+
illustration: "empty-search",
|
|
105
|
+
title: n(M, "projectDetail.projectNotFound", "Project not found"),
|
|
106
|
+
description: n(M, "projectDetail.projectNotFoundDescription", "The project you're looking for doesn't exist or you don't have permission to view it."),
|
|
107
|
+
action: /* @__PURE__ */ _(y, {
|
|
108
|
+
onClick: Z,
|
|
109
|
+
children: [/* @__PURE__ */ g(f, {
|
|
110
|
+
size: 16,
|
|
111
|
+
className: "mr-2"
|
|
112
|
+
}), n(M, "projectDetail.backToProjects", "Back to Projects")]
|
|
113
|
+
})
|
|
129
114
|
})]
|
|
130
115
|
}) : /* @__PURE__ */ _("div", {
|
|
131
116
|
className: "space-y-4 sm:space-y-6 p-3 sm:p-6",
|
|
@@ -183,7 +168,7 @@ function M() {
|
|
|
183
168
|
align: "end",
|
|
184
169
|
children: [
|
|
185
170
|
q && /* @__PURE__ */ _(T, {
|
|
186
|
-
onClick:
|
|
171
|
+
onClick: qe,
|
|
187
172
|
disabled: U || W,
|
|
188
173
|
children: [/* @__PURE__ */ g(d, {
|
|
189
174
|
size: 16,
|
|
@@ -222,7 +207,7 @@ function M() {
|
|
|
222
207
|
children: [
|
|
223
208
|
/* @__PURE__ */ g("p", {
|
|
224
209
|
className: "text-3xl font-bold tabular-nums",
|
|
225
|
-
children:
|
|
210
|
+
children: Ue ?? 0
|
|
226
211
|
}),
|
|
227
212
|
/* @__PURE__ */ g("p", {
|
|
228
213
|
className: "text-sm text-text-muted",
|
|
@@ -262,7 +247,7 @@ function M() {
|
|
|
262
247
|
})
|
|
263
248
|
}), /* @__PURE__ */ _(b, { children: [/* @__PURE__ */ g("p", {
|
|
264
249
|
className: "text-3xl font-bold tabular-nums",
|
|
265
|
-
children:
|
|
250
|
+
children: Ge
|
|
266
251
|
}), /* @__PURE__ */ g("p", {
|
|
267
252
|
className: "text-sm text-text-muted",
|
|
268
253
|
children: n(M, "projectDetail.recentActivityItems", "Recent activity items")
|
|
@@ -280,10 +265,10 @@ function M() {
|
|
|
280
265
|
entityType: "Project",
|
|
281
266
|
entityId: z.id,
|
|
282
267
|
workspaceId: P,
|
|
283
|
-
tags:
|
|
268
|
+
tags: Ke,
|
|
284
269
|
onAdd: async (e) => {
|
|
285
270
|
if (z) try {
|
|
286
|
-
await
|
|
271
|
+
await Fe({
|
|
287
272
|
entityId: z.id,
|
|
288
273
|
tagId: e.id
|
|
289
274
|
}), await $([...X, a(e)]);
|
|
@@ -295,7 +280,7 @@ function M() {
|
|
|
295
280
|
if (!z) return;
|
|
296
281
|
let t = z.tagAssignments?.find((t) => t.tagId === e)?.id;
|
|
297
282
|
try {
|
|
298
|
-
await
|
|
283
|
+
await Le({
|
|
299
284
|
entityId: z.id,
|
|
300
285
|
tagId: e,
|
|
301
286
|
assignmentId: t
|
|
@@ -304,7 +289,7 @@ function M() {
|
|
|
304
289
|
throw r("error"), e;
|
|
305
290
|
}
|
|
306
291
|
},
|
|
307
|
-
className:
|
|
292
|
+
className: Ie || Re || Be ? "pointer-events-none opacity-75" : void 0
|
|
308
293
|
})]
|
|
309
294
|
})]
|
|
310
295
|
})]
|
|
@@ -395,7 +380,7 @@ function M() {
|
|
|
395
380
|
children: JSON.stringify(z.config, null, 2)
|
|
396
381
|
})]
|
|
397
382
|
}),
|
|
398
|
-
/* @__PURE__ */ g(
|
|
383
|
+
/* @__PURE__ */ g(we, {
|
|
399
384
|
collapsedHeight: 0,
|
|
400
385
|
label: n(M, "projectDetail.quickActions", "Quick Actions"),
|
|
401
386
|
children: /* @__PURE__ */ _("div", {
|
|
@@ -440,13 +425,13 @@ function M() {
|
|
|
440
425
|
})]
|
|
441
426
|
}),
|
|
442
427
|
/* @__PURE__ */ g(ge, {
|
|
443
|
-
open:
|
|
428
|
+
open: je,
|
|
444
429
|
onOpenChange: B,
|
|
445
430
|
children: /* @__PURE__ */ _(ye, { children: [/* @__PURE__ */ _(Se, { children: [/* @__PURE__ */ g(Ce, { children: n(M, "projectDetail.deleteDialogTitle", "Delete Project") }), /* @__PURE__ */ g(be, { children: n(M, "projectDetail.deleteConfirmPrefix", "Are you sure you want to delete \"") + z.name + n(M, "projectDetail.deleteConfirmSuffix", "\"? This action cannot be undone and all project data will be permanently removed.") })] }), /* @__PURE__ */ _(xe, { children: [/* @__PURE__ */ g(ve, {
|
|
446
431
|
disabled: G,
|
|
447
432
|
children: n(M, "projectDetail.cancel", "Cancel")
|
|
448
433
|
}), /* @__PURE__ */ g(_e, {
|
|
449
|
-
onClick:
|
|
434
|
+
onClick: Je,
|
|
450
435
|
disabled: G,
|
|
451
436
|
className: "bg-status-error-bg text-status-error-text hover:bg-status-error-bg/90",
|
|
452
437
|
children: G ? n(M, "projectDetail.deleting", "Deleting...") : n(M, "projectDetail.deleteProject", "Delete Project")
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProjectDetailPage.js","names":[],"sources":["../../src/pages/ProjectDetailPage.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport { useParams, useNavigate } from 'react-router-dom';\nimport {\n ArrowLeft,\n FolderKanban,\n Users,\n UserPlus,\n Activity,\n Archive,\n MoreVertical,\n Clock,\n} from 'lucide-react';\nimport {\n Button,\n ShowMore,\n GlassCard,\n CardHeader,\n CardTitle,\n CardContent,\n Badge,\n Skeleton,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n DropdownMenuSeparator,\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n EntityIdModal,\n useEntityIdModal,\n} from '@burdenoff/fe-libs/ui';\nimport { type TagItem } from '@burdenoff/fe-libs/tag';\nimport { ProjectTagsWidget } from '../components/tags/ProjectTagsWidget';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { tWithFallback } from '../utils/i18n';\nimport { useProject, useProjectMembersCount } from '../hooks/useProjects';\nimport { useWorkspacesContext } from '../providers/WorkspacesProvider';\nimport {\n useArchiveProject,\n useUnarchiveProject,\n useDeleteProject,\n useTagProject,\n useUntagProject,\n useUpdateProject,\n} from '../hooks/useProjectMutations';\nimport { formatDate } from '../utils/formatters';\nimport { nativeImpact, nativeNotify } from '../utils/nativeBridge';\nimport { getProjectDisplayTags, toProjectTag } from '../utils/projectTags';\nimport { getProjectStatusClasses } from '../utils/tokenHelpers';\nimport { useWorkspaceActivity } from '../hooks/useWorkspaceActivity';\nimport { useScopedNavigation } from '../hooks/useScopedNavigation';\nimport { useWorkspacePermissions } from '../hooks/useWorkspacePermissions';\nimport { useWorkspacesPageView } from '../hooks/useWorkspacesPageView';\nimport { ProjectMemberPickerDialog } from '../components/ProjectMemberPickerDialog';\n\nexport function ProjectDetailPage() {\n const { t } = useI18n();\n const idModal = useEntityIdModal();\n\n const { workspaceId, projectId } = useParams<{ workspaceId: string; projectId: string }>();\n useWorkspacesPageView('workspaces.project-detail', {\n workspaceId,\n projectId,\n requireParams: true,\n });\n const navigate = useNavigate();\n const { basePath = '/workspaces' } = useWorkspacesContext();\n const { withCurrentSearch } = useScopedNavigation();\n const { data: project, isLoading, error } = useProject(projectId || '', workspaceId);\n const [showDeleteDialog, setShowDeleteDialog] = useState(false);\n const [showAddMemberDialog, setShowAddMemberDialog] = useState(false);\n\n const { mutate: archiveProject, isPending: isArchiving } = useArchiveProject(workspaceId);\n const { mutate: unarchiveProject, isPending: isUnarchiving } = useUnarchiveProject(workspaceId);\n const { mutate: deleteProject, isPending: isDeleting } = useDeleteProject(workspaceId);\n const { mutateAsync: tagProject, isPending: isTaggingProject } = useTagProject(workspaceId);\n const { mutateAsync: untagProject, isPending: isUntaggingProject } = useUntagProject(workspaceId);\n const { mutateAsync: updateProject, isPending: isUpdatingProject } =\n useUpdateProject(workspaceId);\n const {\n canViewProject,\n canDeleteProject,\n canArchiveProject,\n canListProjectMembers,\n canAddProjectMember,\n isLoading: permissionsLoading,\n } = useWorkspacePermissions();\n const { data: projectMemberCount } = useProjectMembersCount(projectId || '', workspaceId);\n const displayTags = useMemo(\n () =>\n getProjectDisplayTags({\n tags: project?.tags ?? [],\n tagAssignments: project?.tagAssignments,\n }),\n [project?.tags, project?.tagAssignments]\n );\n const { data: workspaceActivity } = useWorkspaceActivity(workspaceId);\n const relatedActivityCount = (workspaceActivity ?? []).filter(\n (item) => item.resourceId === projectId || item.resourceType?.toLowerCase() === 'project'\n ).length;\n const widgetTags: TagItem[] = displayTags;\n\n if (permissionsLoading) {\n return (\n <div className=\"space-y-4 p-6\">\n <Skeleton className=\"h-10 w-1/3\" />\n <Skeleton className=\"h-64\" />\n </div>\n );\n }\n\n if (!canViewProject) {\n return (\n <div className=\"flex items-center justify-center min-h-[400px]\">\n <div className=\"text-center space-y-2\">\n <h2 className=\"text-lg font-semibold\">\n {tWithFallback(t, 'projectDetail.accessDenied', 'Access Denied')}\n </h2>\n <p className=\"text-sm text-text-secondary\">\n {tWithFallback(\n t,\n 'projectDetail.noPermissionToViewProject',\n \"You don't have permission to view this project.\"\n )}\n </p>\n </div>\n </div>\n );\n }\n\n const handleBack = () => {\n navigate(withCurrentSearch(`${basePath}/${workspaceId}/projects`));\n };\n\n const handleArchive = () => {\n if (!project) return;\n if (project.archived) {\n unarchiveProject(project.id, {\n onError: (err) => {\n console.error('Failed to unarchive project:', err);\n },\n });\n } else {\n archiveProject(project.id, {\n onError: (err) => {\n console.error('Failed to archive project:', err);\n },\n });\n }\n };\n\n const handleDelete = () => {\n if (!project) return;\n void nativeImpact('medium');\n deleteProject(project.id, {\n onSuccess: () => {\n void nativeNotify('success');\n setShowDeleteDialog(false);\n navigate(withCurrentSearch(`${basePath}/${workspaceId}/projects`));\n },\n onError: (err) => {\n void nativeNotify('error');\n console.error('Failed to delete project:', err);\n },\n });\n };\n\n const handleViewProjectMembers = () => {\n navigate(withCurrentSearch(`${basePath}/${workspaceId}/projects/${projectId}/members`));\n };\n\n const syncLegacyProjectTags = async (nextTags: TagItem[]) => {\n if (!project) {\n return;\n }\n\n const normalizedNextTags = nextTags.map((tag) => toProjectTag(tag));\n\n try {\n await updateProject({\n id: project.id,\n input: {\n tags: normalizedNextTags,\n },\n });\n } catch (err) {\n void nativeNotify('warning');\n console.error(\n 'Failed to sync legacy project tag mirror after updating structured project tags:',\n err\n );\n }\n };\n\n const handleAddTag = async (tag: TagItem) => {\n if (!project) {\n return;\n }\n\n try {\n await tagProject({\n entityId: project.id,\n tagId: tag.id,\n });\n\n await syncLegacyProjectTags([...displayTags, toProjectTag(tag)]);\n } catch (err) {\n void nativeNotify('error');\n throw err;\n }\n };\n\n const handleRemoveTag = async (tagId: string) => {\n if (!project) {\n return;\n }\n\n const assignmentId = project.tagAssignments?.find(\n (assignment) => assignment.tagId === tagId\n )?.id;\n try {\n await untagProject({\n entityId: project.id,\n tagId,\n assignmentId,\n });\n\n await syncLegacyProjectTags(\n displayTags.filter((tag) => tag.tagId !== tagId && tag.id !== tagId)\n );\n } catch (err) {\n void nativeNotify('error');\n throw err;\n }\n };\n\n if (isLoading) {\n return (\n <div className=\"space-y-4 sm:space-y-6 p-3 sm:p-6\">\n <Skeleton className=\"h-10 w-32\" />\n <Skeleton className=\"h-10 w-1/3\" />\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-4\">\n <Skeleton className=\"h-32\" />\n <Skeleton className=\"h-32\" />\n <Skeleton className=\"h-32\" />\n </div>\n <Skeleton className=\"h-48\" />\n </div>\n );\n }\n\n if (error || !project) {\n return (\n <div className=\"space-y-4 p-6\">\n <Button variant=\"ghost\" onClick={handleBack} className=\"gap-2\">\n <ArrowLeft size={20} />\n {tWithFallback(t, 'projectDetail.backToProjects', 'Back to Projects')}\n </Button>\n <div className=\"text-center py-12\">\n <div className=\"rounded-full bg-bg-sunken p-6 mb-4 inline-block\">\n <FolderKanban size={48} className=\"text-text-secondary\" />\n </div>\n <h3 className=\"text-lg font-semibold mb-2\">\n {tWithFallback(t, 'projectDetail.projectNotFound', 'Project not found')}\n </h3>\n <p className=\"text-text-secondary max-w-sm mx-auto mb-4\">\n {tWithFallback(\n t,\n 'projectDetail.projectNotFoundDescription',\n \"The project you're looking for doesn't exist or you don't have permission to view it.\"\n )}\n </p>\n <Button onClick={handleBack}>\n <ArrowLeft size={16} className=\"mr-2\" />\n {tWithFallback(t, 'projectDetail.backToProjects', 'Back to Projects')}\n </Button>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"space-y-4 sm:space-y-6 p-3 sm:p-6\">\n {/* Header */}\n <div className=\"flex flex-col sm:flex-row sm:items-start sm:justify-between gap-3\">\n <div>\n <Button variant=\"ghost\" onClick={handleBack} className=\"gap-2 mb-2 -ml-2\">\n <ArrowLeft size={20} />\n {tWithFallback(t, 'projectDetail.backToProjects', 'Back to Projects')}\n </Button>\n <div className=\"flex items-center gap-3\">\n <div className=\"p-3 rounded-lg bg-action-primary-bg/10\">\n <FolderKanban className=\"text-primary\" size={28} />\n </div>\n <div>\n <h1 className=\"text-2xl sm:text-3xl font-bold\">{project.name}</h1>\n <p className=\"text-sm text-text-secondary font-mono\">{project.key}</p>\n </div>\n </div>\n <div className=\"flex items-center gap-2 mt-3\">\n <Badge className={`border ${getProjectStatusClasses(project.status)}`}>\n {project.status}\n </Badge>\n {project.archived && (\n <Badge\n variant=\"outline\"\n className=\"border-workspace-archived-border text-workspace-archived-text\"\n >\n <Archive size={12} className=\"mr-1\" />\n {tWithFallback(t, 'projectDetail.archived', 'Archived')}\n </Badge>\n )}\n </div>\n </div>\n <div className=\"flex items-center gap-2\">\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"outline\"\n size=\"icon\"\n aria-label={tWithFallback(\n t,\n 'projectDetail.openProjectActionsAriaLabel',\n 'Open project actions'\n )}\n >\n <MoreVertical size={20} />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n {canArchiveProject && (\n <DropdownMenuItem onClick={handleArchive} disabled={isArchiving || isUnarchiving}>\n <Archive size={16} className=\"mr-2\" />\n {isArchiving || isUnarchiving\n ? tWithFallback(t, 'projectDetail.processing', 'Processing...')\n : project.archived\n ? tWithFallback(t, 'projectDetail.unarchive', 'Unarchive')\n : tWithFallback(t, 'projectDetail.archive', 'Archive')}\n </DropdownMenuItem>\n )}\n {canArchiveProject && canDeleteProject && <DropdownMenuSeparator />}\n {canDeleteProject && (\n <DropdownMenuItem\n onClick={() => setShowDeleteDialog(true)}\n className=\"text-status-error-text\"\n >\n {tWithFallback(t, 'projectDetail.deleteProject', 'Delete Project')}\n </DropdownMenuItem>\n )}\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n </div>\n\n {/* Main + detail rail */}\n <div className=\"grid grid-cols-1 lg:grid-cols-3 gap-4 sm:gap-6\">\n {/* Main column */}\n <div className=\"lg:col-span-2 space-y-4 sm:space-y-6\">\n {/* Stat metrics */}\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <GlassCard treatment=\"metric\">\n <CardHeader className=\"flex flex-row items-center justify-between pb-2\">\n <CardTitle className=\"flex items-center gap-2 text-sm font-medium text-text-secondary\">\n <Users size={18} className=\"text-text-muted\" />\n {tWithFallback(t, 'projectDetail.membersCardTitle', 'Members')}\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <p className=\"text-3xl font-bold tabular-nums\">{projectMemberCount ?? 0}</p>\n <p className=\"text-sm text-text-muted\">\n {tWithFallback(t, 'projectDetail.projectMembers', 'Project members')}\n </p>\n\n {canAddProjectMember || canListProjectMembers ? (\n <div className=\"flex flex-wrap gap-2\">\n {canAddProjectMember ? (\n <Button size=\"sm\" onClick={() => setShowAddMemberDialog(true)}>\n <UserPlus size={16} className=\"mr-2\" />\n {tWithFallback(t, 'projectDetail.addProjectMember', 'Add Member')}\n </Button>\n ) : null}\n\n {canListProjectMembers ? (\n <Button variant=\"outline\" size=\"sm\" onClick={handleViewProjectMembers}>\n <Users size={16} className=\"mr-2\" />\n {tWithFallback(t, 'projectDetail.manageProjectMembers', 'Manage Members')}\n </Button>\n ) : null}\n </div>\n ) : null}\n </CardContent>\n </GlassCard>\n\n <GlassCard treatment=\"metric\">\n <CardHeader className=\"flex flex-row items-center justify-between pb-2\">\n <CardTitle className=\"flex items-center gap-2 text-sm font-medium text-text-secondary\">\n <Activity size={18} className=\"text-text-muted\" />\n {tWithFallback(t, 'projectDetail.activityCardTitle', 'Activity')}\n </CardTitle>\n </CardHeader>\n <CardContent>\n <p className=\"text-3xl font-bold tabular-nums\">{relatedActivityCount}</p>\n <p className=\"text-sm text-text-muted\">\n {tWithFallback(t, 'projectDetail.recentActivityItems', 'Recent activity items')}\n </p>\n </CardContent>\n </GlassCard>\n </div>\n\n <GlassCard treatment=\"plain\" className=\"border-border-seam\">\n <CardHeader>\n <CardTitle>{tWithFallback(t, 'projectDetail.tagsTitle', 'Tags')}</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n <p className=\"text-sm text-text-muted\">\n {tWithFallback(\n t,\n 'projectDetail.tagsDescription',\n 'Use universal tags to classify and filter this project across the workspace.'\n )}\n </p>\n <ProjectTagsWidget\n entityType=\"Project\"\n entityId={project.id}\n workspaceId={workspaceId}\n tags={widgetTags}\n onAdd={handleAddTag}\n onRemove={handleRemoveTag}\n className={\n isTaggingProject || isUntaggingProject || isUpdatingProject\n ? 'pointer-events-none opacity-75'\n : undefined\n }\n />\n </CardContent>\n </GlassCard>\n </div>\n\n {/* Detail rail */}\n <aside className=\"lg:sticky lg:top-6 lg:self-start\">\n {/* Project Information */}\n <GlassCard treatment=\"plain\" className=\"border-border-seam\">\n <CardHeader>\n <CardTitle>\n {tWithFallback(t, 'projectDetail.projectInformation', 'Project Information')}\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div className=\"grid grid-cols-1 gap-4 text-sm\">\n <div className=\"space-y-1\">\n <span className=\"text-text-muted flex items-center gap-2\">\n <FolderKanban size={14} />\n {tWithFallback(t, 'projectDetail.projectId', 'Project ID')}\n </span>\n <button\n type=\"button\"\n onClick={() =>\n idModal.show({\n id: project.id,\n name: project.name,\n type: 'Project',\n details: project.key ? [{ label: 'Key', value: project.key }] : undefined,\n })\n }\n className=\"inline-flex items-center gap-1.5 text-xs font-medium text-text-link hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)] rounded\"\n >\n {tWithFallback(t, 'projectDetail.getId', 'Get ID')}\n </button>\n </div>\n\n <div className=\"space-y-1\">\n <span className=\"text-text-secondary flex items-center gap-2\">\n <FolderKanban size={14} />\n {tWithFallback(t, 'projectDetail.projectKey', 'Project Key')}\n </span>\n <span className=\"font-medium\">{project.key}</span>\n </div>\n\n <div className=\"space-y-1\">\n <span className=\"text-text-secondary flex items-center gap-2\">\n <Clock size={14} />\n {tWithFallback(t, 'projectDetail.created', 'Created')}\n </span>\n <span>{formatDate(project.createdAt)}</span>\n </div>\n\n <div className=\"space-y-1\">\n <span className=\"text-text-secondary flex items-center gap-2\">\n <Clock size={14} />\n {tWithFallback(t, 'projectDetail.lastUpdated', 'Last Updated')}\n </span>\n <span>{formatDate(project.updatedAt)}</span>\n </div>\n\n <div className=\"space-y-1\">\n <span className=\"text-text-secondary flex items-center gap-2\">\n <Users size={14} />\n {tWithFallback(t, 'projectDetail.workspaceId', 'Workspace ID')}\n </span>\n <span className=\"font-mono text-xs block\">{project.workspaceId}</span>\n </div>\n\n <div className=\"space-y-1\">\n <span className=\"text-text-secondary flex items-center gap-2\">\n <Users size={14} />\n {tWithFallback(t, 'projectDetail.creatorId', 'Creator ID')}\n </span>\n <span className=\"font-mono text-xs block\">{project.creatorId}</span>\n </div>\n </div>\n\n {project.config && Object.keys(project.config).length > 0 && (\n <div className=\"pt-4 border-t border-border-seam\">\n <h4 className=\"text-sm font-medium mb-2\">\n {tWithFallback(t, 'projectDetail.configuration', 'Configuration')}\n </h4>\n <pre className=\"text-xs bg-bg-sunken p-3 rounded-lg overflow-auto\">\n {JSON.stringify(project.config, null, 2)}\n </pre>\n </div>\n )}\n\n {/* Quick Actions — progressive disclosure (secondary navigation) */}\n <ShowMore\n collapsedHeight={0}\n label={tWithFallback(t, 'projectDetail.quickActions', 'Quick Actions')}\n >\n <div className=\"flex flex-col gap-2 pt-2\">\n {canListProjectMembers ? (\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"justify-start\"\n onClick={handleViewProjectMembers}\n >\n <Users size={16} className=\"mr-2\" />\n {tWithFallback(t, 'projectDetail.projectMembersPage', 'Project Members')}\n </Button>\n ) : null}\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"justify-start\"\n onClick={() => navigate(withCurrentSearch(`${basePath}/${workspaceId}/members`))}\n >\n <Users size={16} className=\"mr-2\" />\n {tWithFallback(t, 'projectDetail.workspaceMembers', 'Workspace Members')}\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"justify-start\"\n onClick={() => navigate(withCurrentSearch(`${basePath}/${workspaceId}/activity`))}\n >\n <Activity size={16} className=\"mr-2\" />\n {tWithFallback(t, 'projectDetail.workspaceActivity', 'Workspace Activity')}\n </Button>\n </div>\n </ShowMore>\n </CardContent>\n </GlassCard>\n </aside>\n </div>\n\n {/* Delete Confirmation Dialog */}\n <AlertDialog open={showDeleteDialog} onOpenChange={setShowDeleteDialog}>\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>\n {tWithFallback(t, 'projectDetail.deleteDialogTitle', 'Delete Project')}\n </AlertDialogTitle>\n <AlertDialogDescription>\n {tWithFallback(\n t,\n 'projectDetail.deleteConfirmPrefix',\n 'Are you sure you want to delete \"'\n ) +\n project.name +\n tWithFallback(\n t,\n 'projectDetail.deleteConfirmSuffix',\n '\"? This action cannot be undone and all project data will be permanently removed.'\n )}\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel disabled={isDeleting}>\n {tWithFallback(t, 'projectDetail.cancel', 'Cancel')}\n </AlertDialogCancel>\n <AlertDialogAction\n onClick={handleDelete}\n disabled={isDeleting}\n className=\"bg-status-error-bg text-status-error-text hover:bg-status-error-bg/90\"\n >\n {isDeleting\n ? tWithFallback(t, 'projectDetail.deleting', 'Deleting...')\n : tWithFallback(t, 'projectDetail.deleteProject', 'Delete Project')}\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n\n {workspaceId && projectId && showAddMemberDialog ? (\n <ProjectMemberPickerDialog\n open={showAddMemberDialog}\n onOpenChange={setShowAddMemberDialog}\n workspaceId={workspaceId}\n projectId={projectId}\n projectName={project.name}\n />\n ) : null}\n <EntityIdModal control={idModal} />\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ProjectDetailPage.js","names":[],"sources":["../../src/pages/ProjectDetailPage.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport { useParams, useNavigate } from 'react-router-dom';\nimport {\n ArrowLeft,\n FolderKanban,\n Users,\n UserPlus,\n Activity,\n Archive,\n MoreVertical,\n Clock,\n} from 'lucide-react';\nimport {\n Button,\n ShowMore,\n GlassCard,\n CardHeader,\n CardTitle,\n CardContent,\n Badge,\n Skeleton,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n DropdownMenuSeparator,\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n EntityIdModal,\n useEntityIdModal,\n IllustratedEmptyState,\n} from '@burdenoff/fe-libs/ui';\nimport { type TagItem } from '@burdenoff/fe-libs/tag';\nimport { ProjectTagsWidget } from '../components/tags/ProjectTagsWidget';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { tWithFallback } from '../utils/i18n';\nimport { useProject, useProjectMembersCount } from '../hooks/useProjects';\nimport { useWorkspacesContext } from '../providers/WorkspacesProvider';\nimport {\n useArchiveProject,\n useUnarchiveProject,\n useDeleteProject,\n useTagProject,\n useUntagProject,\n useUpdateProject,\n} from '../hooks/useProjectMutations';\nimport { formatDate } from '../utils/formatters';\nimport { nativeImpact, nativeNotify } from '../utils/nativeBridge';\nimport { getProjectDisplayTags, toProjectTag } from '../utils/projectTags';\nimport { getProjectStatusClasses } from '../utils/tokenHelpers';\nimport { useWorkspaceActivity } from '../hooks/useWorkspaceActivity';\nimport { useScopedNavigation } from '../hooks/useScopedNavigation';\nimport { useWorkspacePermissions } from '../hooks/useWorkspacePermissions';\nimport { useWorkspacesPageView } from '../hooks/useWorkspacesPageView';\nimport { ProjectMemberPickerDialog } from '../components/ProjectMemberPickerDialog';\n\nexport function ProjectDetailPage() {\n const { t } = useI18n();\n const idModal = useEntityIdModal();\n\n const { workspaceId, projectId } = useParams<{ workspaceId: string; projectId: string }>();\n useWorkspacesPageView('workspaces.project-detail', {\n workspaceId,\n projectId,\n requireParams: true,\n });\n const navigate = useNavigate();\n const { basePath = '/workspaces' } = useWorkspacesContext();\n const { withCurrentSearch } = useScopedNavigation();\n const { data: project, isLoading, error } = useProject(projectId || '', workspaceId);\n const [showDeleteDialog, setShowDeleteDialog] = useState(false);\n const [showAddMemberDialog, setShowAddMemberDialog] = useState(false);\n\n const { mutate: archiveProject, isPending: isArchiving } = useArchiveProject(workspaceId);\n const { mutate: unarchiveProject, isPending: isUnarchiving } = useUnarchiveProject(workspaceId);\n const { mutate: deleteProject, isPending: isDeleting } = useDeleteProject(workspaceId);\n const { mutateAsync: tagProject, isPending: isTaggingProject } = useTagProject(workspaceId);\n const { mutateAsync: untagProject, isPending: isUntaggingProject } = useUntagProject(workspaceId);\n const { mutateAsync: updateProject, isPending: isUpdatingProject } =\n useUpdateProject(workspaceId);\n const {\n canViewProject,\n canDeleteProject,\n canArchiveProject,\n canListProjectMembers,\n canAddProjectMember,\n isLoading: permissionsLoading,\n } = useWorkspacePermissions();\n const { data: projectMemberCount } = useProjectMembersCount(projectId || '', workspaceId);\n const displayTags = useMemo(\n () =>\n getProjectDisplayTags({\n tags: project?.tags ?? [],\n tagAssignments: project?.tagAssignments,\n }),\n [project?.tags, project?.tagAssignments]\n );\n const { data: workspaceActivity } = useWorkspaceActivity(workspaceId);\n const relatedActivityCount = (workspaceActivity ?? []).filter(\n (item) => item.resourceId === projectId || item.resourceType?.toLowerCase() === 'project'\n ).length;\n const widgetTags: TagItem[] = displayTags;\n\n if (permissionsLoading) {\n return (\n <div className=\"space-y-4 p-6\">\n <Skeleton className=\"h-10 w-1/3\" />\n <Skeleton className=\"h-64\" />\n </div>\n );\n }\n\n if (!canViewProject) {\n return (\n <div className=\"flex items-center justify-center min-h-[400px]\">\n <div className=\"text-center space-y-2\">\n <h2 className=\"text-lg font-semibold\">\n {tWithFallback(t, 'projectDetail.accessDenied', 'Access Denied')}\n </h2>\n <p className=\"text-sm text-text-secondary\">\n {tWithFallback(\n t,\n 'projectDetail.noPermissionToViewProject',\n \"You don't have permission to view this project.\"\n )}\n </p>\n </div>\n </div>\n );\n }\n\n const handleBack = () => {\n navigate(withCurrentSearch(`${basePath}/${workspaceId}/projects`));\n };\n\n const handleArchive = () => {\n if (!project) return;\n if (project.archived) {\n unarchiveProject(project.id, {\n onError: (err) => {\n console.error('Failed to unarchive project:', err);\n },\n });\n } else {\n archiveProject(project.id, {\n onError: (err) => {\n console.error('Failed to archive project:', err);\n },\n });\n }\n };\n\n const handleDelete = () => {\n if (!project) return;\n void nativeImpact('medium');\n deleteProject(project.id, {\n onSuccess: () => {\n void nativeNotify('success');\n setShowDeleteDialog(false);\n navigate(withCurrentSearch(`${basePath}/${workspaceId}/projects`));\n },\n onError: (err) => {\n void nativeNotify('error');\n console.error('Failed to delete project:', err);\n },\n });\n };\n\n const handleViewProjectMembers = () => {\n navigate(withCurrentSearch(`${basePath}/${workspaceId}/projects/${projectId}/members`));\n };\n\n const syncLegacyProjectTags = async (nextTags: TagItem[]) => {\n if (!project) {\n return;\n }\n\n const normalizedNextTags = nextTags.map((tag) => toProjectTag(tag));\n\n try {\n await updateProject({\n id: project.id,\n input: {\n tags: normalizedNextTags,\n },\n });\n } catch (err) {\n void nativeNotify('warning');\n console.error(\n 'Failed to sync legacy project tag mirror after updating structured project tags:',\n err\n );\n }\n };\n\n const handleAddTag = async (tag: TagItem) => {\n if (!project) {\n return;\n }\n\n try {\n await tagProject({\n entityId: project.id,\n tagId: tag.id,\n });\n\n await syncLegacyProjectTags([...displayTags, toProjectTag(tag)]);\n } catch (err) {\n void nativeNotify('error');\n throw err;\n }\n };\n\n const handleRemoveTag = async (tagId: string) => {\n if (!project) {\n return;\n }\n\n const assignmentId = project.tagAssignments?.find(\n (assignment) => assignment.tagId === tagId\n )?.id;\n try {\n await untagProject({\n entityId: project.id,\n tagId,\n assignmentId,\n });\n\n await syncLegacyProjectTags(\n displayTags.filter((tag) => tag.tagId !== tagId && tag.id !== tagId)\n );\n } catch (err) {\n void nativeNotify('error');\n throw err;\n }\n };\n\n if (isLoading) {\n return (\n <div className=\"space-y-4 sm:space-y-6 p-3 sm:p-6\">\n <Skeleton className=\"h-10 w-32\" />\n <Skeleton className=\"h-10 w-1/3\" />\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-4\">\n <Skeleton className=\"h-32\" />\n <Skeleton className=\"h-32\" />\n <Skeleton className=\"h-32\" />\n </div>\n <Skeleton className=\"h-48\" />\n </div>\n );\n }\n\n if (error || !project) {\n return (\n <div className=\"space-y-4 p-6\">\n <Button variant=\"ghost\" onClick={handleBack} className=\"gap-2\">\n <ArrowLeft size={20} />\n {tWithFallback(t, 'projectDetail.backToProjects', 'Back to Projects')}\n </Button>\n <IllustratedEmptyState\n illustration=\"empty-search\"\n title={tWithFallback(t, 'projectDetail.projectNotFound', 'Project not found')}\n description={tWithFallback(\n t,\n 'projectDetail.projectNotFoundDescription',\n \"The project you're looking for doesn't exist or you don't have permission to view it.\"\n )}\n action={\n <Button onClick={handleBack}>\n <ArrowLeft size={16} className=\"mr-2\" />\n {tWithFallback(t, 'projectDetail.backToProjects', 'Back to Projects')}\n </Button>\n }\n />\n </div>\n );\n }\n\n return (\n <div className=\"space-y-4 sm:space-y-6 p-3 sm:p-6\">\n {/* Header */}\n <div className=\"flex flex-col sm:flex-row sm:items-start sm:justify-between gap-3\">\n <div>\n <Button variant=\"ghost\" onClick={handleBack} className=\"gap-2 mb-2 -ml-2\">\n <ArrowLeft size={20} />\n {tWithFallback(t, 'projectDetail.backToProjects', 'Back to Projects')}\n </Button>\n <div className=\"flex items-center gap-3\">\n <div className=\"p-3 rounded-lg bg-action-primary-bg/10\">\n <FolderKanban className=\"text-primary\" size={28} />\n </div>\n <div>\n <h1 className=\"text-2xl sm:text-3xl font-bold\">{project.name}</h1>\n <p className=\"text-sm text-text-secondary font-mono\">{project.key}</p>\n </div>\n </div>\n <div className=\"flex items-center gap-2 mt-3\">\n <Badge className={`border ${getProjectStatusClasses(project.status)}`}>\n {project.status}\n </Badge>\n {project.archived && (\n <Badge\n variant=\"outline\"\n className=\"border-workspace-archived-border text-workspace-archived-text\"\n >\n <Archive size={12} className=\"mr-1\" />\n {tWithFallback(t, 'projectDetail.archived', 'Archived')}\n </Badge>\n )}\n </div>\n </div>\n <div className=\"flex items-center gap-2\">\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"outline\"\n size=\"icon\"\n aria-label={tWithFallback(\n t,\n 'projectDetail.openProjectActionsAriaLabel',\n 'Open project actions'\n )}\n >\n <MoreVertical size={20} />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n {canArchiveProject && (\n <DropdownMenuItem onClick={handleArchive} disabled={isArchiving || isUnarchiving}>\n <Archive size={16} className=\"mr-2\" />\n {isArchiving || isUnarchiving\n ? tWithFallback(t, 'projectDetail.processing', 'Processing...')\n : project.archived\n ? tWithFallback(t, 'projectDetail.unarchive', 'Unarchive')\n : tWithFallback(t, 'projectDetail.archive', 'Archive')}\n </DropdownMenuItem>\n )}\n {canArchiveProject && canDeleteProject && <DropdownMenuSeparator />}\n {canDeleteProject && (\n <DropdownMenuItem\n onClick={() => setShowDeleteDialog(true)}\n className=\"text-status-error-text\"\n >\n {tWithFallback(t, 'projectDetail.deleteProject', 'Delete Project')}\n </DropdownMenuItem>\n )}\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n </div>\n\n {/* Main + detail rail */}\n <div className=\"grid grid-cols-1 lg:grid-cols-3 gap-4 sm:gap-6\">\n {/* Main column */}\n <div className=\"lg:col-span-2 space-y-4 sm:space-y-6\">\n {/* Stat metrics */}\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <GlassCard treatment=\"metric\">\n <CardHeader className=\"flex flex-row items-center justify-between pb-2\">\n <CardTitle className=\"flex items-center gap-2 text-sm font-medium text-text-secondary\">\n <Users size={18} className=\"text-text-muted\" />\n {tWithFallback(t, 'projectDetail.membersCardTitle', 'Members')}\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <p className=\"text-3xl font-bold tabular-nums\">{projectMemberCount ?? 0}</p>\n <p className=\"text-sm text-text-muted\">\n {tWithFallback(t, 'projectDetail.projectMembers', 'Project members')}\n </p>\n\n {canAddProjectMember || canListProjectMembers ? (\n <div className=\"flex flex-wrap gap-2\">\n {canAddProjectMember ? (\n <Button size=\"sm\" onClick={() => setShowAddMemberDialog(true)}>\n <UserPlus size={16} className=\"mr-2\" />\n {tWithFallback(t, 'projectDetail.addProjectMember', 'Add Member')}\n </Button>\n ) : null}\n\n {canListProjectMembers ? (\n <Button variant=\"outline\" size=\"sm\" onClick={handleViewProjectMembers}>\n <Users size={16} className=\"mr-2\" />\n {tWithFallback(t, 'projectDetail.manageProjectMembers', 'Manage Members')}\n </Button>\n ) : null}\n </div>\n ) : null}\n </CardContent>\n </GlassCard>\n\n <GlassCard treatment=\"metric\">\n <CardHeader className=\"flex flex-row items-center justify-between pb-2\">\n <CardTitle className=\"flex items-center gap-2 text-sm font-medium text-text-secondary\">\n <Activity size={18} className=\"text-text-muted\" />\n {tWithFallback(t, 'projectDetail.activityCardTitle', 'Activity')}\n </CardTitle>\n </CardHeader>\n <CardContent>\n <p className=\"text-3xl font-bold tabular-nums\">{relatedActivityCount}</p>\n <p className=\"text-sm text-text-muted\">\n {tWithFallback(t, 'projectDetail.recentActivityItems', 'Recent activity items')}\n </p>\n </CardContent>\n </GlassCard>\n </div>\n\n <GlassCard treatment=\"plain\" className=\"border-border-seam\">\n <CardHeader>\n <CardTitle>{tWithFallback(t, 'projectDetail.tagsTitle', 'Tags')}</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n <p className=\"text-sm text-text-muted\">\n {tWithFallback(\n t,\n 'projectDetail.tagsDescription',\n 'Use universal tags to classify and filter this project across the workspace.'\n )}\n </p>\n <ProjectTagsWidget\n entityType=\"Project\"\n entityId={project.id}\n workspaceId={workspaceId}\n tags={widgetTags}\n onAdd={handleAddTag}\n onRemove={handleRemoveTag}\n className={\n isTaggingProject || isUntaggingProject || isUpdatingProject\n ? 'pointer-events-none opacity-75'\n : undefined\n }\n />\n </CardContent>\n </GlassCard>\n </div>\n\n {/* Detail rail */}\n <aside className=\"lg:sticky lg:top-6 lg:self-start\">\n {/* Project Information */}\n <GlassCard treatment=\"plain\" className=\"border-border-seam\">\n <CardHeader>\n <CardTitle>\n {tWithFallback(t, 'projectDetail.projectInformation', 'Project Information')}\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div className=\"grid grid-cols-1 gap-4 text-sm\">\n <div className=\"space-y-1\">\n <span className=\"text-text-muted flex items-center gap-2\">\n <FolderKanban size={14} />\n {tWithFallback(t, 'projectDetail.projectId', 'Project ID')}\n </span>\n <button\n type=\"button\"\n onClick={() =>\n idModal.show({\n id: project.id,\n name: project.name,\n type: 'Project',\n details: project.key ? [{ label: 'Key', value: project.key }] : undefined,\n })\n }\n className=\"inline-flex items-center gap-1.5 text-xs font-medium text-text-link hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)] rounded\"\n >\n {tWithFallback(t, 'projectDetail.getId', 'Get ID')}\n </button>\n </div>\n\n <div className=\"space-y-1\">\n <span className=\"text-text-secondary flex items-center gap-2\">\n <FolderKanban size={14} />\n {tWithFallback(t, 'projectDetail.projectKey', 'Project Key')}\n </span>\n <span className=\"font-medium\">{project.key}</span>\n </div>\n\n <div className=\"space-y-1\">\n <span className=\"text-text-secondary flex items-center gap-2\">\n <Clock size={14} />\n {tWithFallback(t, 'projectDetail.created', 'Created')}\n </span>\n <span>{formatDate(project.createdAt)}</span>\n </div>\n\n <div className=\"space-y-1\">\n <span className=\"text-text-secondary flex items-center gap-2\">\n <Clock size={14} />\n {tWithFallback(t, 'projectDetail.lastUpdated', 'Last Updated')}\n </span>\n <span>{formatDate(project.updatedAt)}</span>\n </div>\n\n <div className=\"space-y-1\">\n <span className=\"text-text-secondary flex items-center gap-2\">\n <Users size={14} />\n {tWithFallback(t, 'projectDetail.workspaceId', 'Workspace ID')}\n </span>\n <span className=\"font-mono text-xs block\">{project.workspaceId}</span>\n </div>\n\n <div className=\"space-y-1\">\n <span className=\"text-text-secondary flex items-center gap-2\">\n <Users size={14} />\n {tWithFallback(t, 'projectDetail.creatorId', 'Creator ID')}\n </span>\n <span className=\"font-mono text-xs block\">{project.creatorId}</span>\n </div>\n </div>\n\n {project.config && Object.keys(project.config).length > 0 && (\n <div className=\"pt-4 border-t border-border-seam\">\n <h4 className=\"text-sm font-medium mb-2\">\n {tWithFallback(t, 'projectDetail.configuration', 'Configuration')}\n </h4>\n <pre className=\"text-xs bg-bg-sunken p-3 rounded-lg overflow-auto\">\n {JSON.stringify(project.config, null, 2)}\n </pre>\n </div>\n )}\n\n {/* Quick Actions — progressive disclosure (secondary navigation) */}\n <ShowMore\n collapsedHeight={0}\n label={tWithFallback(t, 'projectDetail.quickActions', 'Quick Actions')}\n >\n <div className=\"flex flex-col gap-2 pt-2\">\n {canListProjectMembers ? (\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"justify-start\"\n onClick={handleViewProjectMembers}\n >\n <Users size={16} className=\"mr-2\" />\n {tWithFallback(t, 'projectDetail.projectMembersPage', 'Project Members')}\n </Button>\n ) : null}\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"justify-start\"\n onClick={() =>\n navigate(withCurrentSearch(`${basePath}/${workspaceId}/members`))\n }\n >\n <Users size={16} className=\"mr-2\" />\n {tWithFallback(t, 'projectDetail.workspaceMembers', 'Workspace Members')}\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"justify-start\"\n onClick={() =>\n navigate(withCurrentSearch(`${basePath}/${workspaceId}/activity`))\n }\n >\n <Activity size={16} className=\"mr-2\" />\n {tWithFallback(t, 'projectDetail.workspaceActivity', 'Workspace Activity')}\n </Button>\n </div>\n </ShowMore>\n </CardContent>\n </GlassCard>\n </aside>\n </div>\n\n {/* Delete Confirmation Dialog */}\n <AlertDialog open={showDeleteDialog} onOpenChange={setShowDeleteDialog}>\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>\n {tWithFallback(t, 'projectDetail.deleteDialogTitle', 'Delete Project')}\n </AlertDialogTitle>\n <AlertDialogDescription>\n {tWithFallback(\n t,\n 'projectDetail.deleteConfirmPrefix',\n 'Are you sure you want to delete \"'\n ) +\n project.name +\n tWithFallback(\n t,\n 'projectDetail.deleteConfirmSuffix',\n '\"? This action cannot be undone and all project data will be permanently removed.'\n )}\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel disabled={isDeleting}>\n {tWithFallback(t, 'projectDetail.cancel', 'Cancel')}\n </AlertDialogCancel>\n <AlertDialogAction\n onClick={handleDelete}\n disabled={isDeleting}\n className=\"bg-status-error-bg text-status-error-text hover:bg-status-error-bg/90\"\n >\n {isDeleting\n ? tWithFallback(t, 'projectDetail.deleting', 'Deleting...')\n : tWithFallback(t, 'projectDetail.deleteProject', 'Delete Project')}\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n\n {workspaceId && projectId && showAddMemberDialog ? (\n <ProjectMemberPickerDialog\n open={showAddMemberDialog}\n onOpenChange={setShowAddMemberDialog}\n workspaceId={workspaceId}\n projectId={projectId}\n projectName={project.name}\n />\n ) : null}\n <EntityIdModal control={idModal} />\n </div>\n );\n}\n"],"mappings":"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"}
|