@burdenoff/microfe-workspaces 2026.625.2 → 2026.625.4

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 (33) hide show
  1. package/dist/pages/ActivityListPage.js +32 -48
  2. package/dist/pages/ActivityListPage.js.map +1 -1
  3. package/dist/pages/MembersListPage.js +196 -241
  4. package/dist/pages/MembersListPage.js.map +1 -1
  5. package/dist/pages/PendingInvitesPage.js +69 -78
  6. package/dist/pages/PendingInvitesPage.js.map +1 -1
  7. package/dist/pages/ProjectDetailPage.js +37 -52
  8. package/dist/pages/ProjectDetailPage.js.map +1 -1
  9. package/dist/pages/ProjectMembersPage.js +74 -87
  10. package/dist/pages/ProjectMembersPage.js.map +1 -1
  11. package/dist/pages/ProjectsListPage.js +103 -118
  12. package/dist/pages/ProjectsListPage.js.map +1 -1
  13. package/dist/pages/WorkspaceDetailPage.js +74 -76
  14. package/dist/pages/WorkspaceDetailPage.js.map +1 -1
  15. package/dist/pages/WorkspacesListPage.js +167 -178
  16. package/dist/pages/WorkspacesListPage.js.map +1 -1
  17. package/dist/pages/dashboard/widgets/AgentsWidget.js +21 -22
  18. package/dist/pages/dashboard/widgets/AgentsWidget.js.map +1 -1
  19. package/dist/pages/dashboard/widgets/ProjectsWidget.js +26 -27
  20. package/dist/pages/dashboard/widgets/ProjectsWidget.js.map +1 -1
  21. package/dist/pages/dashboard/widgets/RecentActivityWidget.js +19 -23
  22. package/dist/pages/dashboard/widgets/RecentActivityWidget.js.map +1 -1
  23. package/dist/pages/dashboard/widgets/SessionsWidget.js +30 -32
  24. package/dist/pages/dashboard/widgets/SessionsWidget.js.map +1 -1
  25. package/dist/pages/dashboard/widgets/UpcomingEventsWidget.js +18 -20
  26. package/dist/pages/dashboard/widgets/UpcomingEventsWidget.js.map +1 -1
  27. package/dist/pages/dashboard/widgets/VibesWidget.js +18 -19
  28. package/dist/pages/dashboard/widgets/VibesWidget.js.map +1 -1
  29. package/dist/pages/dashboard/widgets/WelcomeWidget.js +14 -12
  30. package/dist/pages/dashboard/widgets/WelcomeWidget.js.map +1 -1
  31. package/dist/pages/dashboard/widgets/WorkspacesWidget.js +20 -21
  32. package/dist/pages/dashboard/widgets/WorkspacesWidget.js.map +1 -1
  33. 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, ShowMore as A, Skeleton as j, useEntityIdModal as we } from "@burdenoff/fe-libs/ui";
19
- import { useNavigate as Te, useParams as Ee } from "react-router-dom";
20
- import { useI18n as De } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
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 } = De(), N = we(), { workspaceId: P, projectId: F } = Ee();
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 = Te(), { basePath: L = "/workspaces" } = e(), { withCurrentSearch: R } = ee(), { data: z, isLoading: Oe, error: ke } = ie(F || "", P), [Ae, B] = l(!1), [V, H] = l(!1), { mutate: je, isPending: U } = oe(P), { mutate: Me, isPending: W } = le(P), { mutate: Ne, isPending: G } = se(P), { mutateAsync: Pe, isPending: Fe } = ce(P), { mutateAsync: Ie, isPending: Le } = ue(P), { mutateAsync: Re, isPending: ze } = de(P), { canViewProject: Be, canDeleteProject: K, canArchiveProject: q, canListProjectMembers: J, canAddProjectMember: Y, isLoading: Ve } = re(), { data: He } = ae(F || "", P), X = c(() => fe({
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: Ue } = pe(P), We = (Ue ?? []).filter((e) => e.resourceId === F || e.resourceType?.toLowerCase() === "project").length, Ge = X;
33
- if (Ve) return /* @__PURE__ */ _("div", {
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 (!Be) return /* @__PURE__ */ g("div", {
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
- }, Ke = () => {
53
- z && (z.archived ? Me(z.id, { onError: (e) => {
52
+ }, qe = () => {
53
+ z && (z.archived ? Ne(z.id, { onError: (e) => {
54
54
  console.error("Failed to unarchive project:", e);
55
- } }) : je(z.id, { onError: (e) => {
55
+ } }) : Me(z.id, { onError: (e) => {
56
56
  console.error("Failed to archive project:", e);
57
57
  } }));
58
- }, qe = () => {
59
- z && (ne("medium"), Ne(z.id, {
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 Re({
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 Oe ? /* @__PURE__ */ _("div", {
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
- }) : ke || !z ? /* @__PURE__ */ _("div", {
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__ */ _("div", {
104
- className: "text-center py-12",
105
- children: [
106
- /* @__PURE__ */ g("div", {
107
- className: "rounded-full bg-bg-sunken p-6 mb-4 inline-block",
108
- children: /* @__PURE__ */ g(m, {
109
- size: 48,
110
- className: "text-text-secondary"
111
- })
112
- }),
113
- /* @__PURE__ */ g("h3", {
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: Ke,
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: He ?? 0
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: We
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: Ge,
268
+ tags: Ke,
284
269
  onAdd: async (e) => {
285
270
  if (z) try {
286
- await Pe({
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 Ie({
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: Fe || Le || ze ? "pointer-events-none opacity-75" : void 0
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(A, {
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: Ae,
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: qe,
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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"}