@burdenoff/microfe-workspaces 2026.625.4 → 2026.626.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/hooks/useMemberMutations.js +6 -6
  2. package/dist/hooks/useMemberMutations.js.map +1 -1
  3. package/dist/pages/ActivityListPage.js +94 -90
  4. package/dist/pages/ActivityListPage.js.map +1 -1
  5. package/dist/pages/CreateWorkspacePage.js +68 -63
  6. package/dist/pages/CreateWorkspacePage.js.map +1 -1
  7. package/dist/pages/InviteAcceptancePage.js +101 -96
  8. package/dist/pages/InviteAcceptancePage.js.map +1 -1
  9. package/dist/pages/MembersListPage.js +185 -184
  10. package/dist/pages/MembersListPage.js.map +1 -1
  11. package/dist/pages/PendingInvitesPage.js +70 -68
  12. package/dist/pages/PendingInvitesPage.js.map +1 -1
  13. package/dist/pages/ProjectDetailPage.js +119 -78
  14. package/dist/pages/ProjectDetailPage.js.map +1 -1
  15. package/dist/pages/ProjectMembersPage.js +105 -104
  16. package/dist/pages/ProjectMembersPage.js.map +1 -1
  17. package/dist/pages/ProjectsListPage.js +158 -157
  18. package/dist/pages/ProjectsListPage.js.map +1 -1
  19. package/dist/pages/WorkspaceDetailPage.js +236 -198
  20. package/dist/pages/WorkspaceDetailPage.js.map +1 -1
  21. package/dist/pages/WorkspaceInvitePage.js +341 -300
  22. package/dist/pages/WorkspaceInvitePage.js.map +1 -1
  23. package/dist/pages/WorkspaceSettingsPage.js +87 -85
  24. package/dist/pages/WorkspaceSettingsPage.js.map +1 -1
  25. package/dist/pages/WorkspacesListPage.js +122 -121
  26. package/dist/pages/WorkspacesListPage.js.map +1 -1
  27. package/dist/pages/dashboard/DashboardPage.js +55 -51
  28. package/dist/pages/dashboard/DashboardPage.js.map +1 -1
  29. package/dist/pages/dashboard/widgets/GroupsWidget.js +16 -17
  30. package/dist/pages/dashboard/widgets/GroupsWidget.js.map +1 -1
  31. package/dist/pages/dashboard/widgets/TagCloudWidget.js +18 -19
  32. package/dist/pages/dashboard/widgets/TagCloudWidget.js.map +1 -1
  33. package/dist/pages/dashboard/widgets/WorkflowStatsWidget.js +10 -11
  34. package/dist/pages/dashboard/widgets/WorkflowStatsWidget.js.map +1 -1
  35. package/package.json +2 -2
@@ -8,30 +8,30 @@ import { useUpdateWorkspace as s } from "../hooks/useWorkspaceMutations.js";
8
8
  import { useMemo as c } from "react";
9
9
  import { ArrowLeft as l, Save as u } from "lucide-react";
10
10
  import { jsx as d, jsxs as f } from "react/jsx-runtime";
11
- import { Button as p, CardContent as m, CardHeader as h, CardTitle as g, GlassCard as _, OptionalFields as v } from "@burdenoff/fe-libs/ui";
12
- import { useNavigate as y, useParams as b } from "react-router-dom";
13
- import { AccessDenied as x, PermissionGate as S } from "@burdenoff/fe-libs/shared/components";
14
- import { useI18n as C } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
15
- import { Form as w, FormControl as T, FormField as E, FormItem as D, FormLabel as O, FormMessage as k, Input as A, z as j } from "@burdenoff/fe-libs/form";
16
- import { TagsWidget as M } from "@burdenoff/fe-libs/tag";
11
+ import { Button as p, CardContent as m, CardHeader as h, CardTitle as g, GlassCard as _, OptionalFields as v, PagePurpose as y } from "@burdenoff/fe-libs/ui";
12
+ import { useNavigate as b, useParams as x } from "react-router-dom";
13
+ import { AccessDenied as S, PermissionGate as C } from "@burdenoff/fe-libs/shared/components";
14
+ import { useI18n as w } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
15
+ import { Form as T, FormControl as E, FormField as D, FormItem as O, FormLabel as k, FormMessage as A, Input as j, z as M } from "@burdenoff/fe-libs/form";
16
+ import { TagsWidget as N } from "@burdenoff/fe-libs/tag";
17
17
  //#region src/pages/WorkspaceSettingsPage.tsx
18
- var N = j.object({
19
- name: j.string().min(2).max(100),
20
- contactEmail: j.string().email().optional().or(j.literal("")),
21
- domain: j.string().optional(),
22
- website: j.string().url().optional().or(j.literal(""))
18
+ var P = M.object({
19
+ name: M.string().min(2).max(100),
20
+ contactEmail: M.string().email().optional().or(M.literal("")),
21
+ domain: M.string().optional(),
22
+ website: M.string().url().optional().or(M.literal(""))
23
23
  });
24
- function P() {
25
- let { t: j } = C(), { workspaceId: P } = b();
24
+ function F() {
25
+ let { t: M } = w(), { workspaceId: F } = x();
26
26
  o("workspaces.settings", {
27
- workspaceId: P,
27
+ workspaceId: F,
28
28
  requireParams: !0
29
29
  });
30
- let F = y(), { basePath: I = "/" } = e(), { data: L, isLoading: R } = r(P || ""), { mutate: z, isPending: B } = s(), { data: V, refetch: H } = t({
31
- variables: { input: { workspaceId: P ?? "" } },
32
- skip: !P,
30
+ let I = b(), { basePath: L = "/" } = e(), { data: R, isLoading: z } = r(F || ""), { mutate: B, isPending: V } = s(), { data: H, refetch: U } = t({
31
+ variables: { input: { workspaceId: F ?? "" } },
32
+ skip: !F,
33
33
  fetchPolicy: "cache-and-network"
34
- }), [U, { loading: W }] = n(), G = c(() => (V?.getWorkspaceTags ?? []).flatMap((e) => e.tag ? [{
34
+ }), [W, { loading: G }] = n(), K = c(() => (H?.getWorkspaceTags ?? []).flatMap((e) => e.tag ? [{
35
35
  id: e.tagId,
36
36
  key: e.tag.key,
37
37
  label: e.tag.label,
@@ -42,32 +42,32 @@ function P() {
42
42
  color: e.tag.color ?? null,
43
43
  icon: e.tag.icon ?? null,
44
44
  description: e.tag.description ?? null
45
- }] : []), [V?.getWorkspaceTags]), K = async (e) => {
46
- P && (await U({ variables: { input: {
47
- workspaceId: P,
45
+ }] : []), [H?.getWorkspaceTags]), q = async (e) => {
46
+ F && (await W({ variables: { input: {
47
+ workspaceId: F,
48
48
  tagIds: e.map((e) => e.id)
49
- } } }), await H());
49
+ } } }), await U());
50
50
  };
51
- return R ? /* @__PURE__ */ d("div", {
51
+ return z ? /* @__PURE__ */ d("div", {
52
52
  className: "p-6",
53
- children: a(j, "workspaceSettings.loading", "Loading...")
54
- }) : L ? /* @__PURE__ */ d(S, {
53
+ children: a(M, "workspaceSettings.loading", "Loading...")
54
+ }) : R ? /* @__PURE__ */ d(C, {
55
55
  permission: i.WORKSPACE_UPDATE,
56
56
  fallback: /* @__PURE__ */ f("div", {
57
57
  className: "p-6",
58
58
  children: [/* @__PURE__ */ f(p, {
59
59
  variant: "ghost",
60
- onClick: () => F(`${I}/${P}`),
60
+ onClick: () => I(`${L}/${F}`),
61
61
  className: "gap-2 mb-6 -ml-2",
62
- children: [/* @__PURE__ */ d(l, { size: 20 }), a(j, "workspaceSettings.backToWorkspace", "Back to Workspace")]
63
- }), /* @__PURE__ */ d(x, {
62
+ children: [/* @__PURE__ */ d(l, { size: 20 }), a(M, "workspaceSettings.backToWorkspace", "Back to Workspace")]
63
+ }), /* @__PURE__ */ d(S, {
64
64
  variant: "card",
65
- title: a(j, "workspaceSettings.permissionRequired", "Permission Required"),
66
- description: a(j, "workspaceSettings.permissionRequiredDesc", "You don't have permission to edit workspace settings."),
67
- details: a(j, "workspaceSettings.permissionRequiredDetails", "Required: workspace:update"),
65
+ title: a(M, "workspaceSettings.permissionRequired", "Permission Required"),
66
+ description: a(M, "workspaceSettings.permissionRequiredDesc", "You don't have permission to edit workspace settings."),
67
+ details: a(M, "workspaceSettings.permissionRequiredDetails", "Required: workspace:update"),
68
68
  primaryAction: {
69
- label: a(j, "workspaceSettings.goBack", "Go Back"),
70
- onClick: () => F(`${I}/${P}`)
69
+ label: a(M, "workspaceSettings.goBack", "Go Back"),
70
+ onClick: () => I(`${L}/${F}`)
71
71
  }
72
72
  })]
73
73
  }),
@@ -77,27 +77,29 @@ function P() {
77
77
  /* @__PURE__ */ f("div", { children: [
78
78
  /* @__PURE__ */ f(p, {
79
79
  variant: "ghost",
80
- onClick: () => F(`${I}/${P}`),
80
+ onClick: () => I(`${L}/${F}`),
81
81
  className: "gap-2 mb-2 -ml-2",
82
- children: [/* @__PURE__ */ d(l, { size: 20 }), a(j, "workspaceSettings.backToWorkspace", "Back to Workspace")]
82
+ children: [/* @__PURE__ */ d(l, { size: 20 }), a(M, "workspaceSettings.backToWorkspace", "Back to Workspace")]
83
83
  }),
84
84
  /* @__PURE__ */ d("h1", {
85
85
  className: "text-2xl sm:text-3xl font-bold",
86
- children: a(j, "workspaceSettings.title", "Workspace Settings")
86
+ children: a(M, "workspaceSettings.title", "Workspace Settings")
87
87
  }),
88
88
  /* @__PURE__ */ d("p", {
89
89
  className: "text-text-secondary",
90
- children: a(j, "workspaceSettings.subtitle", "Manage workspace configuration")
90
+ children: a(M, "workspaceSettings.subtitle", "Manage workspace configuration")
91
91
  })
92
92
  ] }),
93
+ /* @__PURE__ */ d(y, { children: a(M, "workspaceSettings.purpose", "This is where you control how the workspace presents itself and how it's organised — its display name, a contact email, an optional custom domain and website, and the tags used to classify and filter it. Update these to keep the workspace's identity accurate as your team grows.") }),
93
94
  /* @__PURE__ */ f(_, {
94
- treatment: "plain",
95
+ treatment: "glass",
96
+ glow: !0,
95
97
  className: "border-border-seam",
96
- children: [/* @__PURE__ */ d(h, { children: /* @__PURE__ */ d(g, { children: a(j, "workspaceSettings.generalSettings", "General Settings") }) }), /* @__PURE__ */ d(m, { children: /* @__PURE__ */ d(w, {
97
- schema: N,
98
+ children: [/* @__PURE__ */ d(h, { children: /* @__PURE__ */ d(g, { children: a(M, "workspaceSettings.generalSettings", "General Settings") }) }), /* @__PURE__ */ d(m, { children: /* @__PURE__ */ d(T, {
99
+ schema: P,
98
100
  onSubmit: (e) => {
99
- P && z({
100
- id: P,
101
+ F && B({
102
+ id: F,
101
103
  input: {
102
104
  ...e,
103
105
  contactEmail: e.contactEmail || void 0,
@@ -105,60 +107,60 @@ function P() {
105
107
  website: e.website || void 0
106
108
  }
107
109
  }, { onSuccess: () => {
108
- F(`${I}/${P}`);
110
+ I(`${L}/${F}`);
109
111
  } });
110
112
  },
111
113
  formOptions: { defaultValues: {
112
- name: L?.name || "",
113
- contactEmail: L?.contactEmail || "",
114
- domain: L?.domain || "",
115
- website: L?.website || ""
114
+ name: R?.name || "",
115
+ contactEmail: R?.contactEmail || "",
116
+ domain: R?.domain || "",
117
+ website: R?.website || ""
116
118
  } },
117
119
  children: (e) => /* @__PURE__ */ f("div", {
118
120
  className: "space-y-4",
119
121
  children: [
120
- /* @__PURE__ */ d(E, {
122
+ /* @__PURE__ */ d(D, {
121
123
  control: e.control,
122
124
  name: "name",
123
- render: ({ field: e }) => /* @__PURE__ */ f(D, { children: [
124
- /* @__PURE__ */ d(O, { children: a(j, "workspaceSettings.workspaceName", "Workspace Name") }),
125
- /* @__PURE__ */ d(T, { children: /* @__PURE__ */ d(A, { ...e }) }),
126
- /* @__PURE__ */ d(k, {})
125
+ render: ({ field: e }) => /* @__PURE__ */ f(O, { children: [
126
+ /* @__PURE__ */ d(k, { children: a(M, "workspaceSettings.workspaceName", "Workspace Name") }),
127
+ /* @__PURE__ */ d(E, { children: /* @__PURE__ */ d(j, { ...e }) }),
128
+ /* @__PURE__ */ d(A, {})
127
129
  ] })
128
130
  }),
129
- /* @__PURE__ */ d(E, {
131
+ /* @__PURE__ */ d(D, {
130
132
  control: e.control,
131
133
  name: "contactEmail",
132
- render: ({ field: e }) => /* @__PURE__ */ f(D, { children: [
133
- /* @__PURE__ */ d(O, { children: a(j, "workspaceSettings.contactEmail", "Contact Email") }),
134
- /* @__PURE__ */ d(T, { children: /* @__PURE__ */ d(A, {
134
+ render: ({ field: e }) => /* @__PURE__ */ f(O, { children: [
135
+ /* @__PURE__ */ d(k, { children: a(M, "workspaceSettings.contactEmail", "Contact Email") }),
136
+ /* @__PURE__ */ d(E, { children: /* @__PURE__ */ d(j, {
135
137
  type: "email",
136
138
  ...e
137
139
  }) }),
138
- /* @__PURE__ */ d(k, {})
140
+ /* @__PURE__ */ d(A, {})
139
141
  ] })
140
142
  }),
141
143
  /* @__PURE__ */ f(v, {
142
- title: a(j, "workspaceSettings.advancedTitle", "Advanced settings"),
143
- description: a(j, "workspaceSettings.advancedDescription", "Custom domain + website. Most workspaces leave these blank."),
144
- children: [/* @__PURE__ */ d(E, {
144
+ title: a(M, "workspaceSettings.advancedTitle", "Advanced settings"),
145
+ description: a(M, "workspaceSettings.advancedDescription", "Custom domain + website. Most workspaces leave these blank."),
146
+ children: [/* @__PURE__ */ d(D, {
145
147
  control: e.control,
146
148
  name: "domain",
147
- render: ({ field: e }) => /* @__PURE__ */ f(D, { children: [
148
- /* @__PURE__ */ d(O, { children: a(j, "workspaceSettings.domain", "Domain") }),
149
- /* @__PURE__ */ d(T, { children: /* @__PURE__ */ d(A, { ...e }) }),
150
- /* @__PURE__ */ d(k, {})
149
+ render: ({ field: e }) => /* @__PURE__ */ f(O, { children: [
150
+ /* @__PURE__ */ d(k, { children: a(M, "workspaceSettings.domain", "Domain") }),
151
+ /* @__PURE__ */ d(E, { children: /* @__PURE__ */ d(j, { ...e }) }),
152
+ /* @__PURE__ */ d(A, {})
151
153
  ] })
152
- }), /* @__PURE__ */ d(E, {
154
+ }), /* @__PURE__ */ d(D, {
153
155
  control: e.control,
154
156
  name: "website",
155
- render: ({ field: e }) => /* @__PURE__ */ f(D, { children: [
156
- /* @__PURE__ */ d(O, { children: a(j, "workspaceSettings.website", "Website") }),
157
- /* @__PURE__ */ d(T, { children: /* @__PURE__ */ d(A, {
157
+ render: ({ field: e }) => /* @__PURE__ */ f(O, { children: [
158
+ /* @__PURE__ */ d(k, { children: a(M, "workspaceSettings.website", "Website") }),
159
+ /* @__PURE__ */ d(E, { children: /* @__PURE__ */ d(j, {
158
160
  type: "url",
159
161
  ...e
160
162
  }) }),
161
- /* @__PURE__ */ d(k, {})
163
+ /* @__PURE__ */ d(A, {})
162
164
  ] })
163
165
  })]
164
166
  }),
@@ -166,37 +168,37 @@ function P() {
166
168
  className: "flex gap-2",
167
169
  children: [/* @__PURE__ */ f(p, {
168
170
  type: "submit",
169
- disabled: B,
171
+ disabled: V,
170
172
  className: "gap-2",
171
- children: [/* @__PURE__ */ d(u, { size: 20 }), B ? a(j, "workspaceSettings.saving", "Saving...") : a(j, "workspaceSettings.saveChanges", "Save Changes")]
173
+ children: [/* @__PURE__ */ d(u, { size: 20 }), V ? a(M, "workspaceSettings.saving", "Saving...") : a(M, "workspaceSettings.saveChanges", "Save Changes")]
172
174
  }), /* @__PURE__ */ d(p, {
173
175
  type: "button",
174
176
  variant: "outline",
175
- onClick: () => F(`${I}/${P}`),
176
- children: a(j, "workspaceSettings.cancel", "Cancel")
177
+ onClick: () => I(`${L}/${F}`),
178
+ children: a(M, "workspaceSettings.cancel", "Cancel")
177
179
  })]
178
180
  })
179
181
  ]
180
182
  })
181
183
  }) })]
182
184
  }),
183
- P && /* @__PURE__ */ f(_, {
185
+ F && /* @__PURE__ */ f(_, {
184
186
  treatment: "plain",
185
187
  className: "border-border-seam",
186
- children: [/* @__PURE__ */ d(h, { children: /* @__PURE__ */ d(g, { children: a(j, "workspaceSettings.tags", "Tags") }) }), /* @__PURE__ */ f(m, {
188
+ children: [/* @__PURE__ */ d(h, { children: /* @__PURE__ */ d(g, { children: a(M, "workspaceSettings.tags", "Tags") }) }), /* @__PURE__ */ f(m, {
187
189
  className: "space-y-3",
188
190
  children: [/* @__PURE__ */ d("p", {
189
191
  className: "text-sm text-text-muted",
190
- children: a(j, "workspaceSettings.tagsDescription", "Use universal tags to classify and filter this workspace.")
191
- }), /* @__PURE__ */ d(M, {
192
+ children: a(M, "workspaceSettings.tagsDescription", "Use universal tags to classify and filter this workspace.")
193
+ }), /* @__PURE__ */ d(N, {
192
194
  entityType: "Workspace",
193
- entityId: P,
194
- workspaceId: P,
195
- tags: G,
196
- onAdd: (e) => K([...G, e]),
197
- onRemove: (e) => K(G.filter((t) => t.id !== e)),
195
+ entityId: F,
196
+ workspaceId: F,
197
+ tags: K,
198
+ onAdd: (e) => q([...K, e]),
199
+ onRemove: (e) => q(K.filter((t) => t.id !== e)),
198
200
  syncGraphNotifications: !1,
199
- className: W ? "pointer-events-none opacity-75" : void 0
201
+ className: G ? "pointer-events-none opacity-75" : void 0
200
202
  })]
201
203
  })]
202
204
  })
@@ -204,10 +206,10 @@ function P() {
204
206
  })
205
207
  }) : /* @__PURE__ */ d("div", {
206
208
  className: "p-6",
207
- children: a(j, "workspaceSettings.notFound", "Workspace not found")
209
+ children: a(M, "workspaceSettings.notFound", "Workspace not found")
208
210
  });
209
211
  }
210
212
  //#endregion
211
- export { P as WorkspaceSettingsPage };
213
+ export { F as WorkspaceSettingsPage };
212
214
 
213
215
  //# sourceMappingURL=WorkspaceSettingsPage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"WorkspaceSettingsPage.js","names":[],"sources":["../../src/pages/WorkspaceSettingsPage.tsx"],"sourcesContent":["import { useMemo } from 'react';\nimport { useParams, useNavigate } from 'react-router-dom';\nimport { ArrowLeft, Save } from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { type TagItem, TagsWidget } from '@burdenoff/fe-libs/tag';\nimport { tWithFallback } from '../utils/i18n';\nimport {\n Button,\n GlassCard,\n CardHeader,\n CardTitle,\n CardContent,\n OptionalFields,\n} from '@burdenoff/fe-libs/ui';\nimport {\n useGetWorkspaceTagsQuery,\n useReplaceWorkspaceTagsMutation,\n type WorkspaceTagAssignmentFieldsFragment,\n} from '../generated/wspace-operations';\nimport {\n Form,\n FormField,\n FormItem,\n FormLabel,\n FormControl,\n FormMessage,\n Input,\n z,\n} from '@burdenoff/fe-libs/form';\nimport { PermissionGate, AccessDenied } from '@burdenoff/fe-libs/shared/components';\nimport { WORKSPACE_PERMISSIONS } from '../constants/permissions';\nimport { useWorkspace } from '../hooks/useWorkspaces';\nimport { useUpdateWorkspace } from '../hooks/useWorkspaceMutations';\nimport { useWorkspacesContext } from '../providers/WorkspacesProvider';\nimport { useWorkspacesPageView } from '../hooks/useWorkspacesPageView';\n\nconst updateWorkspaceSchema = z.object({\n name: z.string().min(2).max(100),\n contactEmail: z.string().email().optional().or(z.literal('')),\n domain: z.string().optional(),\n website: z.string().url().optional().or(z.literal('')),\n});\n\ntype UpdateWorkspaceFormData = z.infer<typeof updateWorkspaceSchema>;\n\nexport function WorkspaceSettingsPage() {\n const { t } = useI18n();\n const { workspaceId } = useParams<{ workspaceId: string }>();\n useWorkspacesPageView('workspaces.settings', { workspaceId, requireParams: true });\n const navigate = useNavigate();\n const { basePath = '/' } = useWorkspacesContext();\n const { data: workspace, isLoading } = useWorkspace(workspaceId || '');\n const { mutate: updateWorkspace, isPending } = useUpdateWorkspace();\n\n // Workspace tags (universal-tags assignments) — backend exposed via\n // wspace-workspace-svc workspace-tags.gql; this UI is the canonical\n // editor for them. Identical pattern to ProjectDetailPage.\n const { data: tagsData, refetch: refetchTags } = useGetWorkspaceTagsQuery({\n variables: { input: { workspaceId: workspaceId ?? '' } },\n skip: !workspaceId,\n fetchPolicy: 'cache-and-network',\n });\n const [replaceWorkspaceTags, { loading: tagsUpdating }] = useReplaceWorkspaceTagsMutation();\n // The widget keys tags by `id` for add/remove. We store the\n // assignment's tagId there so the round-trip back to\n // replaceWorkspaceTags has the right value to send. Display fields\n // come from the embedded `tag: UniversalTag` resolved by the\n // assignment — assignments without a hydrated tag (deleted or\n // unresolved) are dropped so the widget never renders empty badges.\n const widgetTags = useMemo<TagItem[]>(() => {\n const assignments = tagsData?.getWorkspaceTags ?? [];\n return assignments.flatMap((a: WorkspaceTagAssignmentFieldsFragment) => {\n if (!a.tag) return [];\n return [\n {\n id: a.tagId,\n key: a.tag.key,\n label: a.tag.label,\n value: a.tag.value ?? null,\n vocabularyId: a.tag.vocabularyId ?? null,\n parentId: a.tag.parentId ?? null,\n hierarchyPath: a.tag.hierarchyPath ?? null,\n color: a.tag.color ?? null,\n icon: a.tag.icon ?? null,\n description: a.tag.description ?? null,\n } satisfies TagItem,\n ];\n });\n }, [tagsData?.getWorkspaceTags]);\n\n const persistTags = async (next: TagItem[]) => {\n if (!workspaceId) return;\n await replaceWorkspaceTags({\n variables: {\n input: {\n workspaceId,\n tagIds: next.map((t) => t.id),\n },\n },\n });\n await refetchTags();\n };\n\n const handleAddTag = (tag: TagItem) => persistTags([...widgetTags, tag]);\n const handleRemoveTag = (tagId: string) => persistTags(widgetTags.filter((t) => t.id !== tagId));\n\n const handleSubmit = (data: UpdateWorkspaceFormData) => {\n if (!workspaceId) return;\n\n updateWorkspace(\n {\n id: workspaceId,\n input: {\n ...data,\n contactEmail: data.contactEmail || undefined,\n domain: data.domain || undefined,\n website: data.website || undefined,\n },\n },\n {\n onSuccess: () => {\n navigate(`${basePath}/${workspaceId}`);\n },\n }\n );\n };\n\n if (isLoading) {\n return <div className=\"p-6\">{tWithFallback(t, 'workspaceSettings.loading', 'Loading...')}</div>;\n }\n\n if (!workspace) {\n return (\n <div className=\"p-6\">\n {tWithFallback(t, 'workspaceSettings.notFound', 'Workspace not found')}\n </div>\n );\n }\n\n return (\n <PermissionGate\n permission={WORKSPACE_PERMISSIONS.WORKSPACE_UPDATE}\n fallback={\n <div className=\"p-6\">\n <Button\n variant=\"ghost\"\n onClick={() => navigate(`${basePath}/${workspaceId}`)}\n className=\"gap-2 mb-6 -ml-2\"\n >\n <ArrowLeft size={20} />\n {tWithFallback(t, 'workspaceSettings.backToWorkspace', 'Back to Workspace')}\n </Button>\n <AccessDenied\n variant=\"card\"\n title={tWithFallback(t, 'workspaceSettings.permissionRequired', 'Permission Required')}\n description={tWithFallback(\n t,\n 'workspaceSettings.permissionRequiredDesc',\n \"You don't have permission to edit workspace settings.\"\n )}\n details={tWithFallback(\n t,\n 'workspaceSettings.permissionRequiredDetails',\n 'Required: workspace:update'\n )}\n primaryAction={{\n label: tWithFallback(t, 'workspaceSettings.goBack', 'Go Back'),\n onClick: () => navigate(`${basePath}/${workspaceId}`),\n }}\n />\n </div>\n }\n >\n <div className=\"space-y-4 sm:space-y-6 p-3 sm:p-6\">\n <div>\n <Button\n variant=\"ghost\"\n onClick={() => navigate(`${basePath}/${workspaceId}`)}\n className=\"gap-2 mb-2 -ml-2\"\n >\n <ArrowLeft size={20} />\n {tWithFallback(t, 'workspaceSettings.backToWorkspace', 'Back to Workspace')}\n </Button>\n <h1 className=\"text-2xl sm:text-3xl font-bold\">\n {tWithFallback(t, 'workspaceSettings.title', 'Workspace Settings')}\n </h1>\n <p className=\"text-text-secondary\">\n {tWithFallback(t, 'workspaceSettings.subtitle', 'Manage workspace configuration')}\n </p>\n </div>\n\n <GlassCard treatment=\"plain\" className=\"border-border-seam\">\n <CardHeader>\n <CardTitle>\n {tWithFallback(t, 'workspaceSettings.generalSettings', 'General Settings')}\n </CardTitle>\n </CardHeader>\n <CardContent>\n <Form\n schema={updateWorkspaceSchema}\n onSubmit={handleSubmit}\n formOptions={{\n defaultValues: {\n name: workspace?.name || '',\n contactEmail: workspace?.contactEmail || '',\n domain: workspace?.domain || '',\n website: workspace?.website || '',\n },\n }}\n >\n {(form) => (\n <div className=\"space-y-4\">\n <FormField\n control={form.control}\n name=\"name\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>\n {tWithFallback(t, 'workspaceSettings.workspaceName', 'Workspace Name')}\n </FormLabel>\n <FormControl>\n <Input {...field} />\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n\n <FormField\n control={form.control}\n name=\"contactEmail\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>\n {tWithFallback(t, 'workspaceSettings.contactEmail', 'Contact Email')}\n </FormLabel>\n <FormControl>\n <Input type=\"email\" {...field} />\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n\n <OptionalFields\n title={tWithFallback(t, 'workspaceSettings.advancedTitle', 'Advanced settings')}\n description={tWithFallback(\n t,\n 'workspaceSettings.advancedDescription',\n 'Custom domain + website. Most workspaces leave these blank.'\n )}\n >\n <FormField\n control={form.control}\n name=\"domain\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>\n {tWithFallback(t, 'workspaceSettings.domain', 'Domain')}\n </FormLabel>\n <FormControl>\n <Input {...field} />\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n\n <FormField\n control={form.control}\n name=\"website\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>\n {tWithFallback(t, 'workspaceSettings.website', 'Website')}\n </FormLabel>\n <FormControl>\n <Input type=\"url\" {...field} />\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n </OptionalFields>\n\n <div className=\"flex gap-2\">\n <Button type=\"submit\" disabled={isPending} className=\"gap-2\">\n <Save size={20} />\n {isPending\n ? tWithFallback(t, 'workspaceSettings.saving', 'Saving...')\n : tWithFallback(t, 'workspaceSettings.saveChanges', 'Save Changes')}\n </Button>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => navigate(`${basePath}/${workspaceId}`)}\n >\n {tWithFallback(t, 'workspaceSettings.cancel', 'Cancel')}\n </Button>\n </div>\n </div>\n )}\n </Form>\n </CardContent>\n </GlassCard>\n\n {workspaceId && (\n <GlassCard treatment=\"plain\" className=\"border-border-seam\">\n <CardHeader>\n <CardTitle>{tWithFallback(t, 'workspaceSettings.tags', 'Tags')}</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n <p className=\"text-sm text-text-muted\">\n {tWithFallback(\n t,\n 'workspaceSettings.tagsDescription',\n 'Use universal tags to classify and filter this workspace.'\n )}\n </p>\n <TagsWidget\n entityType=\"Workspace\"\n entityId={workspaceId}\n workspaceId={workspaceId}\n tags={widgetTags}\n onAdd={handleAddTag}\n onRemove={handleRemoveTag}\n syncGraphNotifications={false}\n className={tagsUpdating ? 'pointer-events-none opacity-75' : undefined}\n />\n </CardContent>\n </GlassCard>\n )}\n </div>\n </PermissionGate>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAoCA,IAAM,IAAwB,EAAE,OAAO;CACrC,MAAM,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,IAAI;CAChC,cAAc,EAAE,QAAQ,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,EAAE,QAAQ,GAAG,CAAC;CAC7D,QAAQ,EAAE,QAAQ,CAAC,UAAU;CAC7B,SAAS,EAAE,QAAQ,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,EAAE,QAAQ,GAAG,CAAC;CACvD,CAAC;AAIF,SAAgB,IAAwB;CACtC,IAAM,EAAE,SAAM,GAAS,EACjB,EAAE,mBAAgB,GAAoC;AAC5D,GAAsB,uBAAuB;EAAE;EAAa,eAAe;EAAM,CAAC;CAClF,IAAM,IAAW,GAAa,EACxB,EAAE,cAAW,QAAQ,GAAsB,EAC3C,EAAE,MAAM,GAAW,iBAAc,EAAa,KAAe,GAAG,EAChE,EAAE,QAAQ,GAAiB,iBAAc,GAAoB,EAK7D,EAAE,MAAM,GAAU,SAAS,MAAgB,EAAyB;EACxE,WAAW,EAAE,OAAO,EAAE,aAAa,KAAe,IAAI,EAAE;EACxD,MAAM,CAAC;EACP,aAAa;EACd,CAAC,EACI,CAAC,GAAsB,EAAE,SAAS,OAAkB,GAAiC,EAOrF,IAAa,SACG,GAAU,oBAAoB,EAAE,EACjC,SAAS,MACrB,EAAE,MACA,CACL;EACE,IAAI,EAAE;EACN,KAAK,EAAE,IAAI;EACX,OAAO,EAAE,IAAI;EACb,OAAO,EAAE,IAAI,SAAS;EACtB,cAAc,EAAE,IAAI,gBAAgB;EACpC,UAAU,EAAE,IAAI,YAAY;EAC5B,eAAe,EAAE,IAAI,iBAAiB;EACtC,OAAO,EAAE,IAAI,SAAS;EACtB,MAAM,EAAE,IAAI,QAAQ;EACpB,aAAa,EAAE,IAAI,eAAe;EACnC,CACF,GAdkB,EAAE,CAerB,EACD,CAAC,GAAU,iBAAiB,CAAC,EAE1B,IAAc,OAAO,MAAoB;AACxC,QACL,MAAM,EAAqB,EACzB,WAAW,EACT,OAAO;GACL;GACA,QAAQ,EAAK,KAAK,MAAM,EAAE,GAAG;GAC9B,EACF,EACF,CAAC,EACF,MAAM,GAAa;;AAuCrB,QAZI,IACK,kBAAC,OAAD;EAAK,WAAU;YAAO,EAAc,GAAG,6BAA6B,aAAa;EAAO,CAAA,GAG5F,IASH,kBAAC,GAAD;EACE,YAAY,EAAsB;EAClC,UACE,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,GAAD;IACE,SAAQ;IACR,eAAe,EAAS,GAAG,EAAS,GAAG,IAAc;IACrD,WAAU;cAHZ,CAKE,kBAAC,GAAD,EAAW,MAAM,IAAM,CAAA,EACtB,EAAc,GAAG,qCAAqC,oBAAoB,CACpE;OACT,kBAAC,GAAD;IACE,SAAQ;IACR,OAAO,EAAc,GAAG,wCAAwC,sBAAsB;IACtF,aAAa,EACX,GACA,4CACA,wDACD;IACD,SAAS,EACP,GACA,+CACA,6BACD;IACD,eAAe;KACb,OAAO,EAAc,GAAG,4BAA4B,UAAU;KAC9D,eAAe,EAAS,GAAG,EAAS,GAAG,IAAc;KACtD;IACD,CAAA,CACE;;YAGR,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,OAAD,EAAA,UAAA;KACE,kBAAC,GAAD;MACE,SAAQ;MACR,eAAe,EAAS,GAAG,EAAS,GAAG,IAAc;MACrD,WAAU;gBAHZ,CAKE,kBAAC,GAAD,EAAW,MAAM,IAAM,CAAA,EACtB,EAAc,GAAG,qCAAqC,oBAAoB,CACpE;;KACT,kBAAC,MAAD;MAAI,WAAU;gBACX,EAAc,GAAG,2BAA2B,qBAAqB;MAC/D,CAAA;KACL,kBAAC,KAAD;MAAG,WAAU;gBACV,EAAc,GAAG,8BAA8B,iCAAiC;MAC/E,CAAA;KACA,EAAA,CAAA;IAEN,kBAAC,GAAD;KAAW,WAAU;KAAQ,WAAU;eAAvC,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAA,UACG,EAAc,GAAG,qCAAqC,mBAAmB,EAChE,CAAA,EACD,CAAA,EACb,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;MACE,QAAQ;MACR,WA9FU,MAAkC;AACjD,YAEL,EACE;QACE,IAAI;QACJ,OAAO;SACL,GAAG;SACH,cAAc,EAAK,gBAAgB,KAAA;SACnC,QAAQ,EAAK,UAAU,KAAA;SACvB,SAAS,EAAK,WAAW,KAAA;SAC1B;QACF,EACD,EACE,iBAAiB;AACf,UAAS,GAAG,EAAS,GAAG,IAAc;UAEzC,CACF;;MA6ES,aAAa,EACX,eAAe;OACb,MAAM,GAAW,QAAQ;OACzB,cAAc,GAAW,gBAAgB;OACzC,QAAQ,GAAW,UAAU;OAC7B,SAAS,GAAW,WAAW;OAChC,EACF;iBAEC,MACA,kBAAC,OAAD;OAAK,WAAU;iBAAf;QACE,kBAAC,GAAD;SACE,SAAS,EAAK;SACd,MAAK;SACL,SAAS,EAAE,eACT,kBAAC,GAAD,EAAA,UAAA;UACE,kBAAC,GAAD,EAAA,UACG,EAAc,GAAG,mCAAmC,iBAAiB,EAC5D,CAAA;UACZ,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAO,GAAI,GAAS,CAAA,EACR,CAAA;UACd,kBAAC,GAAD,EAAe,CAAA;UACN,EAAA,CAAA;SAEb,CAAA;QAEF,kBAAC,GAAD;SACE,SAAS,EAAK;SACd,MAAK;SACL,SAAS,EAAE,eACT,kBAAC,GAAD,EAAA,UAAA;UACE,kBAAC,GAAD,EAAA,UACG,EAAc,GAAG,kCAAkC,gBAAgB,EAC1D,CAAA;UACZ,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;WAAO,MAAK;WAAQ,GAAI;WAAS,CAAA,EACrB,CAAA;UACd,kBAAC,GAAD,EAAe,CAAA;UACN,EAAA,CAAA;SAEb,CAAA;QAEF,kBAAC,GAAD;SACE,OAAO,EAAc,GAAG,mCAAmC,oBAAoB;SAC/E,aAAa,EACX,GACA,yCACA,8DACD;mBANH,CAQE,kBAAC,GAAD;UACE,SAAS,EAAK;UACd,MAAK;UACL,SAAS,EAAE,eACT,kBAAC,GAAD,EAAA,UAAA;WACE,kBAAC,GAAD,EAAA,UACG,EAAc,GAAG,4BAA4B,SAAS,EAC7C,CAAA;WACZ,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAO,GAAI,GAAS,CAAA,EACR,CAAA;WACd,kBAAC,GAAD,EAAe,CAAA;WACN,EAAA,CAAA;UAEb,CAAA,EAEF,kBAAC,GAAD;UACE,SAAS,EAAK;UACd,MAAK;UACL,SAAS,EAAE,eACT,kBAAC,GAAD,EAAA,UAAA;WACE,kBAAC,GAAD,EAAA,UACG,EAAc,GAAG,6BAA6B,UAAU,EAC/C,CAAA;WACZ,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;YAAO,MAAK;YAAM,GAAI;YAAS,CAAA,EACnB,CAAA;WACd,kBAAC,GAAD,EAAe,CAAA;WACN,EAAA,CAAA;UAEb,CAAA,CACa;;QAEjB,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,GAAD;UAAQ,MAAK;UAAS,UAAU;UAAW,WAAU;oBAArD,CACE,kBAAC,GAAD,EAAM,MAAM,IAAM,CAAA,EACjB,IACG,EAAc,GAAG,4BAA4B,YAAY,GACzD,EAAc,GAAG,iCAAiC,eAAe,CAC9D;aACT,kBAAC,GAAD;UACE,MAAK;UACL,SAAQ;UACR,eAAe,EAAS,GAAG,EAAS,GAAG,IAAc;oBAEpD,EAAc,GAAG,4BAA4B,SAAS;UAChD,CAAA,CACL;;QACF;;MAEH,CAAA,EACK,CAAA,CACJ;;IAEX,KACC,kBAAC,GAAD;KAAW,WAAU;KAAQ,WAAU;eAAvC,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAA,UAAY,EAAc,GAAG,0BAA0B,OAAO,EAAa,CAAA,EAChE,CAAA,EACb,kBAAC,GAAD;MAAa,WAAU;gBAAvB,CACE,kBAAC,KAAD;OAAG,WAAU;iBACV,EACC,GACA,qCACA,4DACD;OACC,CAAA,EACJ,kBAAC,GAAD;OACE,YAAW;OACX,UAAU;OACG;OACb,MAAM;OACN,QA7NQ,MAAiB,EAAY,CAAC,GAAG,GAAY,EAAI,CAAC;OA8N1D,WA7NW,MAAkB,EAAY,EAAW,QAAQ,MAAM,EAAE,OAAO,EAAM,CAAC;OA8NlF,wBAAwB;OACxB,WAAW,IAAe,mCAAmC,KAAA;OAC7D,CAAA,CACU;QACJ;;IAEV;;EACS,CAAA,GAxMf,kBAAC,OAAD;EAAK,WAAU;YACZ,EAAc,GAAG,8BAA8B,sBAAsB;EAClE,CAAA"}
1
+ {"version":3,"file":"WorkspaceSettingsPage.js","names":[],"sources":["../../src/pages/WorkspaceSettingsPage.tsx"],"sourcesContent":["import { useMemo } from 'react';\nimport { useParams, useNavigate } from 'react-router-dom';\nimport { ArrowLeft, Save } from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { type TagItem, TagsWidget } from '@burdenoff/fe-libs/tag';\nimport { tWithFallback } from '../utils/i18n';\nimport {\n Button,\n GlassCard,\n CardHeader,\n CardTitle,\n CardContent,\n OptionalFields,\n PagePurpose,\n} from '@burdenoff/fe-libs/ui';\nimport {\n useGetWorkspaceTagsQuery,\n useReplaceWorkspaceTagsMutation,\n type WorkspaceTagAssignmentFieldsFragment,\n} from '../generated/wspace-operations';\nimport {\n Form,\n FormField,\n FormItem,\n FormLabel,\n FormControl,\n FormMessage,\n Input,\n z,\n} from '@burdenoff/fe-libs/form';\nimport { PermissionGate, AccessDenied } from '@burdenoff/fe-libs/shared/components';\nimport { WORKSPACE_PERMISSIONS } from '../constants/permissions';\nimport { useWorkspace } from '../hooks/useWorkspaces';\nimport { useUpdateWorkspace } from '../hooks/useWorkspaceMutations';\nimport { useWorkspacesContext } from '../providers/WorkspacesProvider';\nimport { useWorkspacesPageView } from '../hooks/useWorkspacesPageView';\n\nconst updateWorkspaceSchema = z.object({\n name: z.string().min(2).max(100),\n contactEmail: z.string().email().optional().or(z.literal('')),\n domain: z.string().optional(),\n website: z.string().url().optional().or(z.literal('')),\n});\n\ntype UpdateWorkspaceFormData = z.infer<typeof updateWorkspaceSchema>;\n\nexport function WorkspaceSettingsPage() {\n const { t } = useI18n();\n const { workspaceId } = useParams<{ workspaceId: string }>();\n useWorkspacesPageView('workspaces.settings', { workspaceId, requireParams: true });\n const navigate = useNavigate();\n const { basePath = '/' } = useWorkspacesContext();\n const { data: workspace, isLoading } = useWorkspace(workspaceId || '');\n const { mutate: updateWorkspace, isPending } = useUpdateWorkspace();\n\n // Workspace tags (universal-tags assignments) — backend exposed via\n // wspace-workspace-svc workspace-tags.gql; this UI is the canonical\n // editor for them. Identical pattern to ProjectDetailPage.\n const { data: tagsData, refetch: refetchTags } = useGetWorkspaceTagsQuery({\n variables: { input: { workspaceId: workspaceId ?? '' } },\n skip: !workspaceId,\n fetchPolicy: 'cache-and-network',\n });\n const [replaceWorkspaceTags, { loading: tagsUpdating }] = useReplaceWorkspaceTagsMutation();\n // The widget keys tags by `id` for add/remove. We store the\n // assignment's tagId there so the round-trip back to\n // replaceWorkspaceTags has the right value to send. Display fields\n // come from the embedded `tag: UniversalTag` resolved by the\n // assignment — assignments without a hydrated tag (deleted or\n // unresolved) are dropped so the widget never renders empty badges.\n const widgetTags = useMemo<TagItem[]>(() => {\n const assignments = tagsData?.getWorkspaceTags ?? [];\n return assignments.flatMap((a: WorkspaceTagAssignmentFieldsFragment) => {\n if (!a.tag) return [];\n return [\n {\n id: a.tagId,\n key: a.tag.key,\n label: a.tag.label,\n value: a.tag.value ?? null,\n vocabularyId: a.tag.vocabularyId ?? null,\n parentId: a.tag.parentId ?? null,\n hierarchyPath: a.tag.hierarchyPath ?? null,\n color: a.tag.color ?? null,\n icon: a.tag.icon ?? null,\n description: a.tag.description ?? null,\n } satisfies TagItem,\n ];\n });\n }, [tagsData?.getWorkspaceTags]);\n\n const persistTags = async (next: TagItem[]) => {\n if (!workspaceId) return;\n await replaceWorkspaceTags({\n variables: {\n input: {\n workspaceId,\n tagIds: next.map((t) => t.id),\n },\n },\n });\n await refetchTags();\n };\n\n const handleAddTag = (tag: TagItem) => persistTags([...widgetTags, tag]);\n const handleRemoveTag = (tagId: string) => persistTags(widgetTags.filter((t) => t.id !== tagId));\n\n const handleSubmit = (data: UpdateWorkspaceFormData) => {\n if (!workspaceId) return;\n\n updateWorkspace(\n {\n id: workspaceId,\n input: {\n ...data,\n contactEmail: data.contactEmail || undefined,\n domain: data.domain || undefined,\n website: data.website || undefined,\n },\n },\n {\n onSuccess: () => {\n navigate(`${basePath}/${workspaceId}`);\n },\n }\n );\n };\n\n if (isLoading) {\n return <div className=\"p-6\">{tWithFallback(t, 'workspaceSettings.loading', 'Loading...')}</div>;\n }\n\n if (!workspace) {\n return (\n <div className=\"p-6\">\n {tWithFallback(t, 'workspaceSettings.notFound', 'Workspace not found')}\n </div>\n );\n }\n\n return (\n <PermissionGate\n permission={WORKSPACE_PERMISSIONS.WORKSPACE_UPDATE}\n fallback={\n <div className=\"p-6\">\n <Button\n variant=\"ghost\"\n onClick={() => navigate(`${basePath}/${workspaceId}`)}\n className=\"gap-2 mb-6 -ml-2\"\n >\n <ArrowLeft size={20} />\n {tWithFallback(t, 'workspaceSettings.backToWorkspace', 'Back to Workspace')}\n </Button>\n <AccessDenied\n variant=\"card\"\n title={tWithFallback(t, 'workspaceSettings.permissionRequired', 'Permission Required')}\n description={tWithFallback(\n t,\n 'workspaceSettings.permissionRequiredDesc',\n \"You don't have permission to edit workspace settings.\"\n )}\n details={tWithFallback(\n t,\n 'workspaceSettings.permissionRequiredDetails',\n 'Required: workspace:update'\n )}\n primaryAction={{\n label: tWithFallback(t, 'workspaceSettings.goBack', 'Go Back'),\n onClick: () => navigate(`${basePath}/${workspaceId}`),\n }}\n />\n </div>\n }\n >\n <div className=\"space-y-4 sm:space-y-6 p-3 sm:p-6\">\n <div>\n <Button\n variant=\"ghost\"\n onClick={() => navigate(`${basePath}/${workspaceId}`)}\n className=\"gap-2 mb-2 -ml-2\"\n >\n <ArrowLeft size={20} />\n {tWithFallback(t, 'workspaceSettings.backToWorkspace', 'Back to Workspace')}\n </Button>\n <h1 className=\"text-2xl sm:text-3xl font-bold\">\n {tWithFallback(t, 'workspaceSettings.title', 'Workspace Settings')}\n </h1>\n <p className=\"text-text-secondary\">\n {tWithFallback(t, 'workspaceSettings.subtitle', 'Manage workspace configuration')}\n </p>\n </div>\n\n <PagePurpose>\n {tWithFallback(\n t,\n 'workspaceSettings.purpose',\n \"This is where you control how the workspace presents itself and how it's organised — its display name, a contact email, an optional custom domain and website, and the tags used to classify and filter it. Update these to keep the workspace's identity accurate as your team grows.\"\n )}\n </PagePurpose>\n\n <GlassCard treatment=\"glass\" glow className=\"border-border-seam\">\n <CardHeader>\n <CardTitle>\n {tWithFallback(t, 'workspaceSettings.generalSettings', 'General Settings')}\n </CardTitle>\n </CardHeader>\n <CardContent>\n <Form\n schema={updateWorkspaceSchema}\n onSubmit={handleSubmit}\n formOptions={{\n defaultValues: {\n name: workspace?.name || '',\n contactEmail: workspace?.contactEmail || '',\n domain: workspace?.domain || '',\n website: workspace?.website || '',\n },\n }}\n >\n {(form) => (\n <div className=\"space-y-4\">\n <FormField\n control={form.control}\n name=\"name\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>\n {tWithFallback(t, 'workspaceSettings.workspaceName', 'Workspace Name')}\n </FormLabel>\n <FormControl>\n <Input {...field} />\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n\n <FormField\n control={form.control}\n name=\"contactEmail\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>\n {tWithFallback(t, 'workspaceSettings.contactEmail', 'Contact Email')}\n </FormLabel>\n <FormControl>\n <Input type=\"email\" {...field} />\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n\n <OptionalFields\n title={tWithFallback(t, 'workspaceSettings.advancedTitle', 'Advanced settings')}\n description={tWithFallback(\n t,\n 'workspaceSettings.advancedDescription',\n 'Custom domain + website. Most workspaces leave these blank.'\n )}\n >\n <FormField\n control={form.control}\n name=\"domain\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>\n {tWithFallback(t, 'workspaceSettings.domain', 'Domain')}\n </FormLabel>\n <FormControl>\n <Input {...field} />\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n\n <FormField\n control={form.control}\n name=\"website\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>\n {tWithFallback(t, 'workspaceSettings.website', 'Website')}\n </FormLabel>\n <FormControl>\n <Input type=\"url\" {...field} />\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n </OptionalFields>\n\n <div className=\"flex gap-2\">\n <Button type=\"submit\" disabled={isPending} className=\"gap-2\">\n <Save size={20} />\n {isPending\n ? tWithFallback(t, 'workspaceSettings.saving', 'Saving...')\n : tWithFallback(t, 'workspaceSettings.saveChanges', 'Save Changes')}\n </Button>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => navigate(`${basePath}/${workspaceId}`)}\n >\n {tWithFallback(t, 'workspaceSettings.cancel', 'Cancel')}\n </Button>\n </div>\n </div>\n )}\n </Form>\n </CardContent>\n </GlassCard>\n\n {workspaceId && (\n <GlassCard treatment=\"plain\" className=\"border-border-seam\">\n <CardHeader>\n <CardTitle>{tWithFallback(t, 'workspaceSettings.tags', 'Tags')}</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n <p className=\"text-sm text-text-muted\">\n {tWithFallback(\n t,\n 'workspaceSettings.tagsDescription',\n 'Use universal tags to classify and filter this workspace.'\n )}\n </p>\n <TagsWidget\n entityType=\"Workspace\"\n entityId={workspaceId}\n workspaceId={workspaceId}\n tags={widgetTags}\n onAdd={handleAddTag}\n onRemove={handleRemoveTag}\n syncGraphNotifications={false}\n className={tagsUpdating ? 'pointer-events-none opacity-75' : undefined}\n />\n </CardContent>\n </GlassCard>\n )}\n </div>\n </PermissionGate>\n );\n}\n"],"mappings":"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"}