@burdenoff/microfe-timecampus 2026.820.2 → 2026.825.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.
@@ -1,16 +1,17 @@
1
1
  import { useTimeCampus as e } from "../../providers/TimeCampusProvider.js";
2
2
  import { StatCard as t } from "../../components/StatCard.js";
3
3
  import { LoadingSkeleton as n } from "../../components/LoadingSkeleton.js";
4
- import { ErrorBoundary as r } from "../../components/ErrorBoundary.js";
5
- import { PageLayout as i } from "../../components/PageLayout.js";
6
- import { useState as a } from "react";
7
- import { Activity as o, Flag as s, RefreshCw as c, RotateCcw as l, ShieldAlert as u } from "lucide-react";
8
- import { gql as d } from "@apollo/client";
9
- import { useMutation as f, useQuery as p } from "@apollo/client/react";
10
- import { jsx as m, jsxs as h } from "react/jsx-runtime";
11
- import { GlassCard as g } from "@burdenoff/fe-libs/ui";
4
+ import { useExportTimeCampusUserDataMutation as ee, useOverrideTimeCampusWorkspaceQuotaMutation as te, useRecordTimeCampusImpersonationAuditMutation as r, useRemoveTimeCampusFeatureFlagOverrideMutation as i, useRequestTimeCampusUserDataErasureMutation as a, useSetTimeCampusFeatureFlagOverrideMutation as o, useTimeCampusDataErasureRequestsQuery as s, useTimeCampusImpersonationAuditQuery as ne, useTimeCampusWorkspaceQuotaOverviewQuery as re } from "../../../generated/wspace-operations.js";
5
+ import { ErrorBoundary as c } from "../../components/ErrorBoundary.js";
6
+ import { PageLayout as ie } from "../../components/PageLayout.js";
7
+ import { useState as l } from "react";
8
+ import { Activity as ae, FileDown as u, Flag as d, Gauge as f, RefreshCw as p, RotateCcw as m, ShieldAlert as h, Trash2 as g, UserCog as _, Users as v } from "lucide-react";
9
+ import { gql as y } from "@apollo/client";
10
+ import { useMutation as b, useQuery as x } from "@apollo/client/react";
11
+ import { jsx as S, jsxs as C } from "react/jsx-runtime";
12
+ import { GlassCard as w } from "@burdenoff/fe-libs/ui";
12
13
  //#region src/timecampus/pages/admin/AdminPage.tsx
13
- var _ = d`
14
+ var T = y`
14
15
  query TimeCampusAdminWorkspaceState($workspaceId: ID!) {
15
16
  timeCampusAdminWorkspaceState(workspaceId: $workspaceId) {
16
17
  workspaceId
@@ -28,7 +29,7 @@ var _ = d`
28
29
  generatedAt
29
30
  }
30
31
  }
31
- `, v = d`
32
+ `, E = y`
32
33
  query TimeCampusFeatureFlags($workspaceId: ID!) {
33
34
  timeCampusFeatureFlags(workspaceId: $workspaceId) {
34
35
  workspaceId
@@ -40,196 +41,613 @@ var _ = d`
40
41
  }
41
42
  }
42
43
  }
43
- `, y = d`
44
+ `, D = y`
44
45
  mutation ReprocessTimeCampusTimeline($workspaceId: ID!) {
45
46
  reprocessTimeCampusTimeline(workspaceId: $workspaceId) {
46
47
  success
47
48
  message
48
49
  }
49
50
  }
50
- `, b = d`
51
+ `, O = y`
51
52
  mutation ResetTimeCampusDemoData($workspaceId: ID!) {
52
53
  resetTimeCampusDemoData(workspaceId: $workspaceId) {
53
54
  success
54
55
  message
55
56
  }
56
57
  }
57
- `, x = () => {
58
- let { workspaceId: r = "" } = e(), [d, x] = a(null), { data: S, loading: C, error: w, refetch: T } = p(_, {
59
- variables: { workspaceId: r },
60
- skip: !r
61
- }), { data: E, loading: D, error: O } = p(v, {
62
- variables: { workspaceId: r },
63
- skip: !r
64
- }), [k, { loading: A }] = f(y), [j, { loading: M }] = f(b);
65
- if (!r) return /* @__PURE__ */ h("div", {
58
+ `;
59
+ function k(e) {
60
+ return e == null ? "—" : e.toLocaleString();
61
+ }
62
+ var A = () => {
63
+ let { workspaceId: c = "" } = e(), [y, A] = l(null), [j, M] = l(""), [N, P] = l("timecampus.operations"), [F, I] = l(!0), [L, R] = l("timecampus.projects.count"), [z, B] = l("100"), [V, H] = l("support"), { data: U, loading: W, error: G, refetch: K } = x(T, {
64
+ variables: { workspaceId: c },
65
+ skip: !c
66
+ }), { data: q, loading: J, error: oe } = x(E, {
67
+ variables: { workspaceId: c },
68
+ skip: !c
69
+ }), { data: se, loading: ce, error: le, refetch: ue } = re({
70
+ variables: { workspaceId: c },
71
+ skip: !c
72
+ }), { data: de, loading: fe, error: pe, refetch: me } = s({
73
+ variables: { workspaceId: c },
74
+ skip: !c
75
+ }), { data: he, loading: ge, error: _e, refetch: ve } = ne({
76
+ variables: { workspaceId: c },
77
+ skip: !c
78
+ }), [ye, { loading: be }] = b(D), [xe, { loading: Se }] = b(O), [Ce, { loading: we }] = o(), [Te, { loading: Ee }] = i(), [De, { loading: Oe }] = te(), [ke, { loading: Ae }] = ee(), [je, { loading: Me }] = a(), [Ne, { loading: Pe }] = r();
79
+ if (!c) return /* @__PURE__ */ C("div", {
66
80
  className: "flex min-h-[40vh] items-center justify-center text-text-secondary",
67
- children: [/* @__PURE__ */ m(u, { className: "mr-2 h-5 w-5" }), "Workspace context is required."]
81
+ children: [/* @__PURE__ */ S(h, { className: "mr-2 h-5 w-5" }), "Workspace context is required."]
68
82
  });
69
- let N = S?.timeCampusAdminWorkspaceState, P = E?.timeCampusFeatureFlags?.items ?? [];
70
- return /* @__PURE__ */ h(i, {
83
+ let Y = U?.timeCampusAdminWorkspaceState, Fe = q?.timeCampusFeatureFlags?.items ?? [], X = se?.data?.timeCampusWorkspaceQuotaOverview?.assignments ?? [], Z = de?.data?.timeCampusDataErasureRequests ?? [], Q = he?.data?.timeCampusImpersonationAudit ?? [], Ie = async () => {
84
+ if (!window.confirm("Reprocess timeline categorization for this workspace?")) return;
85
+ let e = await ye({ variables: { workspaceId: c } });
86
+ A(e.data?.reprocessTimeCampusTimeline?.message ?? "Done");
87
+ }, Le = async () => {
88
+ if (!window.confirm("Reset demo data for this workspace? This cannot be undone.")) return;
89
+ let e = await xe({ variables: { workspaceId: c } });
90
+ A(e.data?.resetTimeCampusDemoData?.message ?? "Done"), await K();
91
+ }, Re = async () => {
92
+ let e = await Ce({ variables: { input: {
93
+ workspaceId: c,
94
+ key: N,
95
+ enabled: F
96
+ } } });
97
+ A(e.data ? `Feature flag ${N} set to ${String(F)}` : "Done");
98
+ }, ze = async () => {
99
+ let e = await Te({ variables: {
100
+ workspaceId: c,
101
+ key: N
102
+ } });
103
+ A(`Removed override for ${N}: ${String(e.data)}`);
104
+ }, Be = async () => {
105
+ let e = await De({ variables: { input: {
106
+ workspaceId: c,
107
+ quotaName: L,
108
+ productId: "timecampus",
109
+ limit: z ? Number(z) : null
110
+ } } });
111
+ A(e.data ? `Quota ${L} overridden to ${z || "unlimited"}` : "Done"), await ue();
112
+ }, Ve = async () => {
113
+ if (!j) {
114
+ A("Enter a target user ID");
115
+ return;
116
+ }
117
+ let e = await ke({ variables: { input: {
118
+ workspaceId: c,
119
+ userId: j,
120
+ entityTypes: [
121
+ "timeEntry",
122
+ "project",
123
+ "task",
124
+ "expenseEntry"
125
+ ],
126
+ format: "JSON"
127
+ } } });
128
+ A(e.data ? `Export job ${e.data.exportTimeCampusUserData.id} created` : "Done");
129
+ }, He = async () => {
130
+ if (!j) {
131
+ A("Enter a target user ID");
132
+ return;
133
+ }
134
+ if (!window.confirm(`Request TimeCampus data erasure for user ${j}?`)) return;
135
+ let e = await je({ variables: {
136
+ workspaceId: c,
137
+ userId: j
138
+ } });
139
+ A(e.data ? `Erasure request ${e.data.requestTimeCampusUserDataErasure.id} created` : "Done"), await me();
140
+ }, Ue = async () => {
141
+ if (!j) {
142
+ A("Enter a target user ID");
143
+ return;
144
+ }
145
+ let e = await Ne({ variables: { input: {
146
+ workspaceId: c,
147
+ targetUserId: j,
148
+ reason: V
149
+ } } });
150
+ A(e.data ? `Impersonation session ${e.data.recordTimeCampusImpersonationAudit.id} recorded` : "Done"), await ve();
151
+ }, $ = [
152
+ G,
153
+ oe,
154
+ le,
155
+ pe,
156
+ _e
157
+ ].filter(Boolean);
158
+ return /* @__PURE__ */ C(ie, {
71
159
  title: "TimeCampus Admin",
72
- description: "Workspace state, feature flags, and super-admin maintenance actions.",
160
+ description: "Workspace state, feature flags, quotas, compliance, and super-admin maintenance actions.",
73
161
  children: [
74
- d && /* @__PURE__ */ h("div", {
162
+ y && /* @__PURE__ */ C("div", {
75
163
  className: "mb-4 rounded-md bg-status-info-bg px-4 py-3 text-sm text-status-info-text",
76
- children: [d, /* @__PURE__ */ m("button", {
164
+ children: [y, /* @__PURE__ */ S("button", {
77
165
  type: "button",
78
- onClick: () => x(null),
166
+ onClick: () => A(null),
79
167
  className: "ml-4 underline",
80
168
  children: "Dismiss"
81
169
  })]
82
170
  }),
83
- (w || O) && /* @__PURE__ */ h("div", {
171
+ $.length > 0 && /* @__PURE__ */ C("div", {
84
172
  className: "mb-4 rounded-md bg-status-error-bg px-4 py-3 text-sm text-status-error-text",
85
- children: [
86
- "Failed to load admin data.",
87
- " ",
88
- w?.message ?? O?.message
89
- ]
173
+ children: ["Failed to load admin data. ", $.map((e) => e?.message).join("; ")]
90
174
  }),
91
- /* @__PURE__ */ h("section", {
175
+ /* @__PURE__ */ C("section", {
92
176
  className: "mb-8",
93
- children: [/* @__PURE__ */ h("h2", {
177
+ children: [/* @__PURE__ */ C("h2", {
94
178
  className: "mb-4 flex items-center gap-2 text-lg font-semibold text-text-primary",
95
- children: [/* @__PURE__ */ m(o, { className: "h-5 w-5" }), "Workspace State"]
96
- }), C ? /* @__PURE__ */ m(n, {}) : /* @__PURE__ */ h("div", {
179
+ children: [/* @__PURE__ */ S(ae, { className: "h-5 w-5" }), "Workspace State"]
180
+ }), W ? /* @__PURE__ */ S(n, {}) : /* @__PURE__ */ C("div", {
97
181
  className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4",
98
182
  children: [
99
- /* @__PURE__ */ m(t, {
183
+ /* @__PURE__ */ S(t, {
100
184
  title: "Time Entries",
101
- value: N?.timeEntryCount ?? 0
185
+ value: Y?.timeEntryCount ?? 0
102
186
  }),
103
- /* @__PURE__ */ m(t, {
187
+ /* @__PURE__ */ S(t, {
104
188
  title: "Projects",
105
- value: N?.projectCount ?? 0
189
+ value: Y?.projectCount ?? 0
106
190
  }),
107
- /* @__PURE__ */ m(t, {
191
+ /* @__PURE__ */ S(t, {
108
192
  title: "Tasks",
109
- value: N?.taskCount ?? 0
193
+ value: Y?.taskCount ?? 0
110
194
  }),
111
- /* @__PURE__ */ m(t, {
195
+ /* @__PURE__ */ S(t, {
112
196
  title: "Pomodoro Sessions",
113
- value: N?.pomodoroSessionCount ?? 0
197
+ value: Y?.pomodoroSessionCount ?? 0
114
198
  }),
115
- /* @__PURE__ */ m(t, {
199
+ /* @__PURE__ */ S(t, {
116
200
  title: "Meetings",
117
- value: N?.meetingCount ?? 0
201
+ value: Y?.meetingCount ?? 0
118
202
  }),
119
- /* @__PURE__ */ m(t, {
203
+ /* @__PURE__ */ S(t, {
120
204
  title: "Expenses",
121
- value: N?.expenseCount ?? 0
205
+ value: Y?.expenseCount ?? 0
122
206
  }),
123
- /* @__PURE__ */ m(t, {
207
+ /* @__PURE__ */ S(t, {
124
208
  title: "Invoices",
125
- value: N?.invoiceCount ?? 0
209
+ value: Y?.invoiceCount ?? 0
126
210
  }),
127
- /* @__PURE__ */ m(t, {
211
+ /* @__PURE__ */ S(t, {
128
212
  title: "Pending Approvals",
129
- value: N?.pendingApprovalCount ?? 0
213
+ value: Y?.pendingApprovalCount ?? 0
130
214
  }),
131
- /* @__PURE__ */ m(t, {
215
+ /* @__PURE__ */ S(t, {
132
216
  title: "Location Entries",
133
- value: N?.locationEntryCount ?? 0
217
+ value: Y?.locationEntryCount ?? 0
134
218
  }),
135
- /* @__PURE__ */ m(t, {
219
+ /* @__PURE__ */ S(t, {
136
220
  title: "Focus Scores",
137
- value: N?.focusScoreCount ?? 0
221
+ value: Y?.focusScoreCount ?? 0
138
222
  }),
139
- /* @__PURE__ */ m(t, {
223
+ /* @__PURE__ */ S(t, {
140
224
  title: "App Usage Records",
141
- value: N?.applicationUsageCount ?? 0
225
+ value: Y?.applicationUsageCount ?? 0
142
226
  })
143
227
  ]
144
228
  })]
145
229
  }),
146
- /* @__PURE__ */ h("section", {
230
+ /* @__PURE__ */ C("section", {
147
231
  className: "mb-8",
148
- children: [/* @__PURE__ */ h("h2", {
149
- className: "mb-4 flex items-center gap-2 text-lg font-semibold text-text-primary",
150
- children: [/* @__PURE__ */ m(s, { className: "h-5 w-5" }), "Feature Flags"]
151
- }), D ? /* @__PURE__ */ m(n, {}) : /* @__PURE__ */ m(g, {
152
- className: "overflow-hidden",
153
- children: /* @__PURE__ */ h("table", {
154
- className: "w-full text-sm",
155
- children: [/* @__PURE__ */ m("thead", {
156
- className: "bg-bg-subtle",
157
- children: /* @__PURE__ */ h("tr", { children: [
158
- /* @__PURE__ */ m("th", {
159
- className: "px-4 py-3 text-left font-medium text-text-secondary",
160
- children: "Key"
161
- }),
162
- /* @__PURE__ */ m("th", {
163
- className: "px-4 py-3 text-left font-medium text-text-secondary",
164
- children: "Category"
165
- }),
166
- /* @__PURE__ */ m("th", {
167
- className: "px-4 py-3 text-left font-medium text-text-secondary",
168
- children: "Default"
169
- }),
170
- /* @__PURE__ */ m("th", {
171
- className: "px-4 py-3 text-left font-medium text-text-secondary",
172
- children: "Current"
173
- })
174
- ] })
175
- }), /* @__PURE__ */ m("tbody", { children: P.map((e) => /* @__PURE__ */ h("tr", {
176
- className: "border-t border-border-subtle",
177
- children: [
178
- /* @__PURE__ */ m("td", {
179
- className: "px-4 py-3 font-mono text-text-primary",
180
- children: e.key
181
- }),
182
- /* @__PURE__ */ m("td", {
183
- className: "px-4 py-3 text-text-secondary",
184
- children: e.category
185
- }),
186
- /* @__PURE__ */ m("td", {
187
- className: "px-4 py-3 text-text-secondary",
188
- children: String(e.defaultValue)
189
- }),
190
- /* @__PURE__ */ m("td", {
191
- className: "px-4 py-3",
192
- children: /* @__PURE__ */ m("span", {
193
- className: `inline-flex rounded-full px-2 py-1 text-xs font-medium ${e.value ? "bg-status-success-bg text-status-success-text" : "bg-status-error-bg text-status-error-text"}`,
194
- children: e.value ? "Enabled" : "Disabled"
232
+ children: [
233
+ /* @__PURE__ */ C("h2", {
234
+ className: "mb-4 flex items-center gap-2 text-lg font-semibold text-text-primary",
235
+ children: [/* @__PURE__ */ S(d, { className: "h-5 w-5" }), "Feature Flags"]
236
+ }),
237
+ J ? /* @__PURE__ */ S(n, {}) : /* @__PURE__ */ S(w, {
238
+ className: "mb-4 overflow-hidden",
239
+ children: /* @__PURE__ */ C("table", {
240
+ className: "w-full text-sm",
241
+ children: [/* @__PURE__ */ S("thead", {
242
+ className: "bg-bg-subtle",
243
+ children: /* @__PURE__ */ C("tr", { children: [
244
+ /* @__PURE__ */ S("th", {
245
+ className: "px-4 py-3 text-left font-medium text-text-secondary",
246
+ children: "Key"
247
+ }),
248
+ /* @__PURE__ */ S("th", {
249
+ className: "px-4 py-3 text-left font-medium text-text-secondary",
250
+ children: "Category"
251
+ }),
252
+ /* @__PURE__ */ S("th", {
253
+ className: "px-4 py-3 text-left font-medium text-text-secondary",
254
+ children: "Default"
255
+ }),
256
+ /* @__PURE__ */ S("th", {
257
+ className: "px-4 py-3 text-left font-medium text-text-secondary",
258
+ children: "Current"
195
259
  })
196
- })
197
- ]
198
- }, e.key)) })]
260
+ ] })
261
+ }), /* @__PURE__ */ S("tbody", { children: Fe.map((e) => /* @__PURE__ */ C("tr", {
262
+ className: "border-t border-border-subtle",
263
+ children: [
264
+ /* @__PURE__ */ S("td", {
265
+ className: "px-4 py-3 font-mono text-text-primary",
266
+ children: e.key
267
+ }),
268
+ /* @__PURE__ */ S("td", {
269
+ className: "px-4 py-3 text-text-secondary",
270
+ children: e.category
271
+ }),
272
+ /* @__PURE__ */ S("td", {
273
+ className: "px-4 py-3 text-text-secondary",
274
+ children: String(e.defaultValue)
275
+ }),
276
+ /* @__PURE__ */ S("td", {
277
+ className: "px-4 py-3",
278
+ children: /* @__PURE__ */ S("span", {
279
+ className: `inline-flex rounded-full px-2 py-1 text-xs font-medium ${e.value ? "bg-status-success-bg text-status-success-text" : "bg-status-error-bg text-status-error-text"}`,
280
+ children: e.value ? "Enabled" : "Disabled"
281
+ })
282
+ })
283
+ ]
284
+ }, e.key)) })]
285
+ })
286
+ }),
287
+ /* @__PURE__ */ C(w, {
288
+ className: "flex flex-wrap items-end gap-4 p-4",
289
+ children: [
290
+ /* @__PURE__ */ C("div", {
291
+ className: "flex flex-col gap-1",
292
+ children: [/* @__PURE__ */ S("label", {
293
+ className: "text-xs font-medium text-text-secondary",
294
+ children: "Flag key"
295
+ }), /* @__PURE__ */ S("input", {
296
+ type: "text",
297
+ value: N,
298
+ onChange: (e) => P(e.target.value),
299
+ className: "rounded-md border border-border-subtle bg-bg-subtle px-3 py-2 text-sm text-text-primary"
300
+ })]
301
+ }),
302
+ /* @__PURE__ */ C("div", {
303
+ className: "flex flex-col gap-1",
304
+ children: [/* @__PURE__ */ S("label", {
305
+ className: "text-xs font-medium text-text-secondary",
306
+ children: "Enabled"
307
+ }), /* @__PURE__ */ C("select", {
308
+ value: String(F),
309
+ onChange: (e) => I(e.target.value === "true"),
310
+ className: "rounded-md border border-border-subtle bg-bg-subtle px-3 py-2 text-sm text-text-primary",
311
+ children: [/* @__PURE__ */ S("option", {
312
+ value: "true",
313
+ children: "true"
314
+ }), /* @__PURE__ */ S("option", {
315
+ value: "false",
316
+ children: "false"
317
+ })]
318
+ })]
319
+ }),
320
+ /* @__PURE__ */ C("button", {
321
+ type: "button",
322
+ onClick: Re,
323
+ disabled: we,
324
+ className: "inline-flex items-center gap-2 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90 disabled:opacity-50",
325
+ children: [/* @__PURE__ */ S(d, { className: "h-4 w-4" }), "Set Override"]
326
+ }),
327
+ /* @__PURE__ */ C("button", {
328
+ type: "button",
329
+ onClick: ze,
330
+ disabled: Ee,
331
+ className: "inline-flex items-center gap-2 rounded-md bg-status-error-bg px-4 py-2 text-sm font-medium text-status-error-text hover:bg-status-error-bg/90 disabled:opacity-50",
332
+ children: [/* @__PURE__ */ S(m, { className: "h-4 w-4" }), "Remove Override"]
333
+ })
334
+ ]
199
335
  })
200
- })]
336
+ ]
337
+ }),
338
+ /* @__PURE__ */ C("section", {
339
+ className: "mb-8",
340
+ children: [
341
+ /* @__PURE__ */ C("h2", {
342
+ className: "mb-4 flex items-center gap-2 text-lg font-semibold text-text-primary",
343
+ children: [/* @__PURE__ */ S(f, { className: "h-5 w-5" }), "Workspace Quotas"]
344
+ }),
345
+ ce ? /* @__PURE__ */ S(n, {}) : /* @__PURE__ */ S(w, {
346
+ className: "mb-4 overflow-hidden",
347
+ children: /* @__PURE__ */ C("table", {
348
+ className: "w-full text-sm",
349
+ children: [/* @__PURE__ */ S("thead", {
350
+ className: "bg-bg-subtle",
351
+ children: /* @__PURE__ */ C("tr", { children: [
352
+ /* @__PURE__ */ S("th", {
353
+ className: "px-4 py-3 text-left font-medium text-text-secondary",
354
+ children: "Quota"
355
+ }),
356
+ /* @__PURE__ */ S("th", {
357
+ className: "px-4 py-3 text-left font-medium text-text-secondary",
358
+ children: "Product"
359
+ }),
360
+ /* @__PURE__ */ S("th", {
361
+ className: "px-4 py-3 text-left font-medium text-text-secondary",
362
+ children: "Limit"
363
+ }),
364
+ /* @__PURE__ */ S("th", {
365
+ className: "px-4 py-3 text-left font-medium text-text-secondary",
366
+ children: "Used"
367
+ }),
368
+ /* @__PURE__ */ S("th", {
369
+ className: "px-4 py-3 text-left font-medium text-text-secondary",
370
+ children: "Reset"
371
+ }),
372
+ /* @__PURE__ */ S("th", {
373
+ className: "px-4 py-3 text-left font-medium text-text-secondary",
374
+ children: "Active"
375
+ })
376
+ ] })
377
+ }), /* @__PURE__ */ C("tbody", { children: [X.map((e) => /* @__PURE__ */ C("tr", {
378
+ className: "border-t border-border-subtle",
379
+ children: [
380
+ /* @__PURE__ */ S("td", {
381
+ className: "px-4 py-3 font-mono text-text-primary",
382
+ children: e.quotaName
383
+ }),
384
+ /* @__PURE__ */ S("td", {
385
+ className: "px-4 py-3 text-text-secondary",
386
+ children: e.productId
387
+ }),
388
+ /* @__PURE__ */ S("td", {
389
+ className: "px-4 py-3 text-text-secondary",
390
+ children: e.noLimit ? "Unlimited" : k(e.limit)
391
+ }),
392
+ /* @__PURE__ */ S("td", {
393
+ className: "px-4 py-3 text-text-secondary",
394
+ children: k(e.used)
395
+ }),
396
+ /* @__PURE__ */ S("td", {
397
+ className: "px-4 py-3 text-text-secondary",
398
+ children: e.resetPeriod
399
+ }),
400
+ /* @__PURE__ */ S("td", {
401
+ className: "px-4 py-3 text-text-secondary",
402
+ children: e.isActive ? "Yes" : "No"
403
+ })
404
+ ]
405
+ }, e.id)), X.length === 0 && /* @__PURE__ */ S("tr", { children: /* @__PURE__ */ S("td", {
406
+ colSpan: 6,
407
+ className: "px-4 py-3 text-center text-text-secondary",
408
+ children: "No quota assignments for this workspace."
409
+ }) })] })]
410
+ })
411
+ }),
412
+ /* @__PURE__ */ C(w, {
413
+ className: "flex flex-wrap items-end gap-4 p-4",
414
+ children: [
415
+ /* @__PURE__ */ C("div", {
416
+ className: "flex flex-col gap-1",
417
+ children: [/* @__PURE__ */ S("label", {
418
+ className: "text-xs font-medium text-text-secondary",
419
+ children: "Quota name"
420
+ }), /* @__PURE__ */ S("input", {
421
+ type: "text",
422
+ value: L,
423
+ onChange: (e) => R(e.target.value),
424
+ className: "rounded-md border border-border-subtle bg-bg-subtle px-3 py-2 text-sm text-text-primary"
425
+ })]
426
+ }),
427
+ /* @__PURE__ */ C("div", {
428
+ className: "flex flex-col gap-1",
429
+ children: [/* @__PURE__ */ S("label", {
430
+ className: "text-xs font-medium text-text-secondary",
431
+ children: "Limit (empty = unlimited)"
432
+ }), /* @__PURE__ */ S("input", {
433
+ type: "number",
434
+ value: z,
435
+ onChange: (e) => B(e.target.value),
436
+ className: "rounded-md border border-border-subtle bg-bg-subtle px-3 py-2 text-sm text-text-primary"
437
+ })]
438
+ }),
439
+ /* @__PURE__ */ C("button", {
440
+ type: "button",
441
+ onClick: Be,
442
+ disabled: Oe,
443
+ className: "inline-flex items-center gap-2 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90 disabled:opacity-50",
444
+ children: [/* @__PURE__ */ S(f, { className: "h-4 w-4" }), "Override Quota"]
445
+ })
446
+ ]
447
+ })
448
+ ]
449
+ }),
450
+ /* @__PURE__ */ C("section", {
451
+ className: "mb-8",
452
+ children: [
453
+ /* @__PURE__ */ C("h2", {
454
+ className: "mb-4 flex items-center gap-2 text-lg font-semibold text-text-primary",
455
+ children: [/* @__PURE__ */ S(v, { className: "h-5 w-5" }), "User Data Export / Erasure"]
456
+ }),
457
+ /* @__PURE__ */ C(w, {
458
+ className: "flex flex-wrap items-end gap-4 p-4",
459
+ children: [
460
+ /* @__PURE__ */ C("div", {
461
+ className: "flex flex-col gap-1",
462
+ children: [/* @__PURE__ */ S("label", {
463
+ className: "text-xs font-medium text-text-secondary",
464
+ children: "Target user ID"
465
+ }), /* @__PURE__ */ S("input", {
466
+ type: "text",
467
+ value: j,
468
+ onChange: (e) => M(e.target.value),
469
+ placeholder: "user-uuid",
470
+ className: "rounded-md border border-border-subtle bg-bg-subtle px-3 py-2 text-sm text-text-primary"
471
+ })]
472
+ }),
473
+ /* @__PURE__ */ C("button", {
474
+ type: "button",
475
+ onClick: Ve,
476
+ disabled: Ae,
477
+ className: "inline-flex items-center gap-2 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90 disabled:opacity-50",
478
+ children: [/* @__PURE__ */ S(u, { className: "h-4 w-4" }), "Export User Data"]
479
+ }),
480
+ /* @__PURE__ */ C("button", {
481
+ type: "button",
482
+ onClick: He,
483
+ disabled: Me,
484
+ className: "inline-flex items-center gap-2 rounded-md bg-status-error-bg px-4 py-2 text-sm font-medium text-status-error-text hover:bg-status-error-bg/90 disabled:opacity-50",
485
+ children: [/* @__PURE__ */ S(g, { className: "h-4 w-4" }), "Request Erasure"]
486
+ })
487
+ ]
488
+ }),
489
+ fe ? /* @__PURE__ */ S(n, {}) : /* @__PURE__ */ S(w, {
490
+ className: "mt-4 overflow-hidden",
491
+ children: /* @__PURE__ */ C("table", {
492
+ className: "w-full text-sm",
493
+ children: [/* @__PURE__ */ S("thead", {
494
+ className: "bg-bg-subtle",
495
+ children: /* @__PURE__ */ C("tr", { children: [
496
+ /* @__PURE__ */ S("th", {
497
+ className: "px-4 py-3 text-left font-medium text-text-secondary",
498
+ children: "User"
499
+ }),
500
+ /* @__PURE__ */ S("th", {
501
+ className: "px-4 py-3 text-left font-medium text-text-secondary",
502
+ children: "Status"
503
+ }),
504
+ /* @__PURE__ */ S("th", {
505
+ className: "px-4 py-3 text-left font-medium text-text-secondary",
506
+ children: "Requested By"
507
+ }),
508
+ /* @__PURE__ */ S("th", {
509
+ className: "px-4 py-3 text-left font-medium text-text-secondary",
510
+ children: "Requested At"
511
+ })
512
+ ] })
513
+ }), /* @__PURE__ */ C("tbody", { children: [Z.map((e) => /* @__PURE__ */ C("tr", {
514
+ className: "border-t border-border-subtle",
515
+ children: [
516
+ /* @__PURE__ */ S("td", {
517
+ className: "px-4 py-3 font-mono text-text-primary",
518
+ children: e.userId
519
+ }),
520
+ /* @__PURE__ */ S("td", {
521
+ className: "px-4 py-3 text-text-secondary",
522
+ children: e.status
523
+ }),
524
+ /* @__PURE__ */ S("td", {
525
+ className: "px-4 py-3 text-text-secondary",
526
+ children: e.requestedBy
527
+ }),
528
+ /* @__PURE__ */ S("td", {
529
+ className: "px-4 py-3 text-text-secondary",
530
+ children: new Date(e.requestedAt).toLocaleString()
531
+ })
532
+ ]
533
+ }, e.id)), Z.length === 0 && /* @__PURE__ */ S("tr", { children: /* @__PURE__ */ S("td", {
534
+ colSpan: 4,
535
+ className: "px-4 py-3 text-center text-text-secondary",
536
+ children: "No erasure requests."
537
+ }) })] })]
538
+ })
539
+ })
540
+ ]
541
+ }),
542
+ /* @__PURE__ */ C("section", {
543
+ className: "mb-8",
544
+ children: [
545
+ /* @__PURE__ */ C("h2", {
546
+ className: "mb-4 flex items-center gap-2 text-lg font-semibold text-text-primary",
547
+ children: [/* @__PURE__ */ S(_, { className: "h-5 w-5" }), "Impersonation Audit"]
548
+ }),
549
+ /* @__PURE__ */ C(w, {
550
+ className: "flex flex-wrap items-end gap-4 p-4",
551
+ children: [/* @__PURE__ */ C("div", {
552
+ className: "flex flex-col gap-1",
553
+ children: [/* @__PURE__ */ S("label", {
554
+ className: "text-xs font-medium text-text-secondary",
555
+ children: "Reason"
556
+ }), /* @__PURE__ */ S("input", {
557
+ type: "text",
558
+ value: V,
559
+ onChange: (e) => H(e.target.value),
560
+ className: "rounded-md border border-border-subtle bg-bg-subtle px-3 py-2 text-sm text-text-primary"
561
+ })]
562
+ }), /* @__PURE__ */ C("button", {
563
+ type: "button",
564
+ onClick: Ue,
565
+ disabled: Pe,
566
+ className: "inline-flex items-center gap-2 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90 disabled:opacity-50",
567
+ children: [/* @__PURE__ */ S(_, { className: "h-4 w-4" }), "Record Session"]
568
+ })]
569
+ }),
570
+ ge ? /* @__PURE__ */ S(n, {}) : /* @__PURE__ */ S(w, {
571
+ className: "mt-4 overflow-hidden",
572
+ children: /* @__PURE__ */ C("table", {
573
+ className: "w-full text-sm",
574
+ children: [/* @__PURE__ */ S("thead", {
575
+ className: "bg-bg-subtle",
576
+ children: /* @__PURE__ */ C("tr", { children: [
577
+ /* @__PURE__ */ S("th", {
578
+ className: "px-4 py-3 text-left font-medium text-text-secondary",
579
+ children: "Target User"
580
+ }),
581
+ /* @__PURE__ */ S("th", {
582
+ className: "px-4 py-3 text-left font-medium text-text-secondary",
583
+ children: "Actor"
584
+ }),
585
+ /* @__PURE__ */ S("th", {
586
+ className: "px-4 py-3 text-left font-medium text-text-secondary",
587
+ children: "Reason"
588
+ }),
589
+ /* @__PURE__ */ S("th", {
590
+ className: "px-4 py-3 text-left font-medium text-text-secondary",
591
+ children: "Started At"
592
+ })
593
+ ] })
594
+ }), /* @__PURE__ */ C("tbody", { children: [Q.map((e) => /* @__PURE__ */ C("tr", {
595
+ className: "border-t border-border-subtle",
596
+ children: [
597
+ /* @__PURE__ */ S("td", {
598
+ className: "px-4 py-3 font-mono text-text-primary",
599
+ children: e.targetUserId
600
+ }),
601
+ /* @__PURE__ */ C("td", {
602
+ className: "px-4 py-3 text-text-secondary",
603
+ children: [
604
+ e.actorId,
605
+ " (",
606
+ e.actorType,
607
+ ")"
608
+ ]
609
+ }),
610
+ /* @__PURE__ */ S("td", {
611
+ className: "px-4 py-3 text-text-secondary",
612
+ children: e.reason ?? "—"
613
+ }),
614
+ /* @__PURE__ */ S("td", {
615
+ className: "px-4 py-3 text-text-secondary",
616
+ children: new Date(e.startedAt).toLocaleString()
617
+ })
618
+ ]
619
+ }, e.id)), Q.length === 0 && /* @__PURE__ */ S("tr", { children: /* @__PURE__ */ S("td", {
620
+ colSpan: 4,
621
+ className: "px-4 py-3 text-center text-text-secondary",
622
+ children: "No impersonation sessions recorded."
623
+ }) })] })]
624
+ })
625
+ })
626
+ ]
201
627
  }),
202
- /* @__PURE__ */ h("section", { children: [/* @__PURE__ */ h("h2", {
628
+ /* @__PURE__ */ C("section", { children: [/* @__PURE__ */ C("h2", {
203
629
  className: "mb-4 flex items-center gap-2 text-lg font-semibold text-text-primary",
204
- children: [/* @__PURE__ */ m(c, { className: "h-5 w-5" }), "Maintenance"]
205
- }), /* @__PURE__ */ h(g, {
630
+ children: [/* @__PURE__ */ S(p, { className: "h-5 w-5" }), "Maintenance"]
631
+ }), /* @__PURE__ */ C(w, {
206
632
  className: "flex flex-wrap items-center gap-4 p-4",
207
- children: [/* @__PURE__ */ h("button", {
633
+ children: [/* @__PURE__ */ C("button", {
208
634
  type: "button",
209
- onClick: async () => {
210
- if (!window.confirm("Reprocess timeline categorization for this workspace?")) return;
211
- let e = await k({ variables: { workspaceId: r } });
212
- x(e.data?.reprocessTimeCampusTimeline?.message ?? "Done");
213
- },
214
- disabled: A,
635
+ onClick: Ie,
636
+ disabled: be,
215
637
  className: "inline-flex items-center gap-2 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90 disabled:opacity-50",
216
- children: [/* @__PURE__ */ m(c, { className: "h-4 w-4" }), "Reprocess Timeline"]
217
- }), /* @__PURE__ */ h("button", {
638
+ children: [/* @__PURE__ */ S(p, { className: "h-4 w-4" }), "Reprocess Timeline"]
639
+ }), /* @__PURE__ */ C("button", {
218
640
  type: "button",
219
- onClick: async () => {
220
- if (!window.confirm("Reset demo data for this workspace? This cannot be undone.")) return;
221
- let e = await j({ variables: { workspaceId: r } });
222
- x(e.data?.resetTimeCampusDemoData?.message ?? "Done"), await T();
223
- },
224
- disabled: M,
641
+ onClick: Le,
642
+ disabled: Se,
225
643
  className: "inline-flex items-center gap-2 rounded-md bg-status-error-bg px-4 py-2 text-sm font-medium text-status-error-text hover:bg-status-error-bg/90 disabled:opacity-50",
226
- children: [/* @__PURE__ */ m(l, { className: "h-4 w-4" }), "Reset Demo Data"]
644
+ children: [/* @__PURE__ */ S(m, { className: "h-4 w-4" }), "Reset Demo Data"]
227
645
  })]
228
646
  })] })
229
647
  ]
230
648
  });
231
- }, S = () => /* @__PURE__ */ m(r, { children: /* @__PURE__ */ m(x, {}) });
649
+ }, j = () => /* @__PURE__ */ S(c, { children: /* @__PURE__ */ S(A, {}) });
232
650
  //#endregion
233
- export { S as AdminPage };
651
+ export { j as AdminPage };
234
652
 
235
653
  //# sourceMappingURL=AdminPage.js.map