@burdenoff/microfe-export 2026.1013.2 → 2026.1023.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 +1 @@
1
- {"version":3,"file":"useExportQueries.d.ts","sourceRoot":"","sources":["../../../src/export/hooks/useExportQueries.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useExportQueries.d.ts","sourceRoot":"","sources":["../../../src/export/hooks/useExportQueries.ts"],"names":[],"mappings":"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"}
@@ -2,106 +2,107 @@ import { useExport as e } from "../providers/ExportProvider.js";
2
2
  import { CancelExportJobDocument as t, CreateExportJobDocument as n, CreateExportTemplateDocument as r, DeleteExportJobDocument as i, DeleteExportTemplateDocument as a, ExportJobProgressDocument as o, GetAvailableExportEntitiesDocument as s, GetExportJobDocument as c, GetExportTemplateDocument as l, ListExportJobsDocument as u, ListExportTemplatesDocument as d, RetryExportJobDocument as f } from "../../generated/wspace-operations.js";
3
3
  import { ExportFormat as p, ExportJobStatus as m, ExportScope as h } from "../../generated/wspace-types.js";
4
4
  import { emitExportEvent as g } from "../utils/events.js";
5
- import { useMutation as _, useQuery as v, useSubscription as y } from "@apollo/client/react";
5
+ import { useEffect as _, useRef as v } from "react";
6
+ import { useMutation as y, useQuery as b, useSubscription as x } from "@apollo/client/react";
6
7
  //#region src/export/hooks/useExportQueries.ts
7
- function b(e) {
8
+ function S(e) {
8
9
  return e ?? void 0;
9
10
  }
10
- function x(e) {
11
+ function C(e) {
11
12
  if (e == null) return;
12
13
  let t = typeof e == "number" ? e : Number(e);
13
14
  return Number.isFinite(t) ? t : void 0;
14
15
  }
15
- function S(e) {
16
- return x(e) ?? 0;
16
+ function w(e) {
17
+ return C(e) ?? 0;
17
18
  }
18
- function C(e) {
19
+ function T(e) {
19
20
  return e && typeof e == "object" && !Array.isArray(e) ? e : void 0;
20
21
  }
21
- function w(e) {
22
+ function E(e) {
22
23
  return {
23
24
  hasNextPage: e.hasNextPage,
24
25
  hasPreviousPage: e.hasPreviousPage,
25
- startCursor: b(e.startCursor),
26
- endCursor: b(e.endCursor)
26
+ startCursor: S(e.startCursor),
27
+ endCursor: S(e.endCursor)
27
28
  };
28
29
  }
29
- function T(e) {
30
+ function D(e) {
30
31
  return {
31
32
  id: e.id,
32
- jobId: b(e.jobId),
33
+ jobId: S(e.jobId),
33
34
  partNumber: e.partNumber,
34
35
  fileName: e.fileName,
35
- sizeBytes: S(e.sizeBytes),
36
+ sizeBytes: w(e.sizeBytes),
36
37
  entityTypes: e.entityTypes,
37
- downloadUrl: b(e.downloadUrl),
38
- downloadExpiresAt: b(e.downloadExpiresAt),
39
- checksum: b(e.checksum),
40
- createdAt: b(e.createdAt)
38
+ downloadUrl: S(e.downloadUrl),
39
+ downloadExpiresAt: S(e.downloadExpiresAt),
40
+ checksum: S(e.checksum),
41
+ createdAt: S(e.createdAt)
41
42
  };
42
43
  }
43
- function E(e) {
44
+ function O(e) {
44
45
  return {
45
46
  id: e.id,
46
47
  name: e.name,
47
- description: b(e.description),
48
+ description: S(e.description),
48
49
  status: e.status,
49
50
  progress: e.progress,
50
51
  exportScope: e.exportScope ? e.exportScope : void 0,
51
- organizationId: b(e.organizationId),
52
+ organizationId: S(e.organizationId),
52
53
  targetWorkspaceIds: e.targetWorkspaceIds ?? void 0,
53
54
  entityTypes: e.entityTypes,
54
55
  format: e.format,
55
56
  archiveFormat: e.archiveFormat ?? "ZIP",
56
- totalEntities: x(e.totalEntities),
57
- processedEntities: x(e.processedEntities),
58
- totalSizeBytes: x(e.totalSizeBytes),
59
- parts: e.parts?.map(T) ?? [],
60
- templateId: b(e.templateId),
61
- filters: C(e.entityFilters),
62
- errorMessage: b(e.errorMessage),
63
- startedAt: b(e.startedAt),
64
- completedAt: b(e.completedAt),
65
- expiresAt: b(e.expiresAt),
57
+ totalEntities: C(e.totalEntities),
58
+ processedEntities: C(e.processedEntities),
59
+ totalSizeBytes: C(e.totalSizeBytes),
60
+ parts: e.parts?.map(D) ?? [],
61
+ templateId: S(e.templateId),
62
+ filters: T(e.entityFilters),
63
+ errorMessage: S(e.errorMessage),
64
+ startedAt: S(e.startedAt),
65
+ completedAt: S(e.completedAt),
66
+ expiresAt: S(e.expiresAt),
66
67
  createdBy: e.createdBy,
67
- temporalWorkflowId: b(e.temporalWorkflowId),
68
- workspaceId: b(e.workspaceId),
68
+ temporalWorkflowId: S(e.temporalWorkflowId),
69
+ workspaceId: S(e.workspaceId),
69
70
  createdAt: e.createdAt,
70
71
  updatedAt: e.updatedAt
71
72
  };
72
73
  }
73
- function D(e) {
74
+ function k(e) {
74
75
  return {
75
76
  id: e.id,
76
77
  name: e.name,
77
- description: b(e.description),
78
+ description: S(e.description),
78
79
  entityTypes: e.entityTypes,
79
80
  format: e.format,
80
- filters: C(e.entityFilters),
81
+ filters: T(e.entityFilters),
81
82
  isDefault: e.isDefault,
82
83
  createdBy: e.createdBy,
83
- workspaceId: b(e.workspaceId),
84
+ workspaceId: S(e.workspaceId),
84
85
  createdAt: e.createdAt,
85
86
  updatedAt: e.updatedAt
86
87
  };
87
88
  }
88
- function O(e) {
89
+ function A(e) {
89
90
  return {
90
91
  entityType: e.entityType,
91
92
  displayName: e.displayName,
92
- description: b(e.description),
93
- estimatedSize: b(e.estimatedSize),
93
+ description: S(e.description),
94
+ estimatedSize: S(e.estimatedSize),
94
95
  supportsDateRange: e.supportsDateRange,
95
96
  supportsMediaExport: e.supportsMediaExport,
96
97
  enabled: e.enabled
97
98
  };
98
99
  }
99
- function k(e) {
100
+ function j(e) {
100
101
  if (e === "CSV") return p.Csv;
101
102
  if (e === "JSON") return p.Json;
102
103
  throw Error(`Unsupported export format: ${e}`);
103
104
  }
104
- function A(e) {
105
+ function M(e) {
105
106
  switch (e) {
106
107
  case "CANCELLED": return m.Cancelled;
107
108
  case "COMPLETED": return m.Completed;
@@ -114,7 +115,7 @@ function A(e) {
114
115
  default: throw Error(`Unsupported export status: ${e}`);
115
116
  }
116
117
  }
117
- function j(e) {
118
+ function N(e) {
118
119
  switch (e) {
119
120
  case "INDIVIDUAL": return h.Individual;
120
121
  case "WORKSPACE_ADMIN": return h.WorkspaceAdmin;
@@ -122,12 +123,12 @@ function j(e) {
122
123
  default: throw Error(`Unsupported export scope: ${e}`);
123
124
  }
124
125
  }
125
- function M(t, n) {
126
- let { workspaceId: r } = e(), { data: i, loading: a, error: o, refetch: s } = v(u, {
126
+ function P(t, n) {
127
+ let { workspaceId: r } = e(), { data: i, loading: a, error: o, refetch: s } = b(u, {
127
128
  variables: {
128
129
  filter: t && r ? {
129
- status: t.status && t.status !== "all" ? [A(t.status)] : void 0,
130
- format: t.format && t.format !== "all" ? k(t.format) : void 0,
130
+ status: t.status && t.status !== "all" ? [M(t.status)] : void 0,
131
+ format: t.format && t.format !== "all" ? j(t.format) : void 0,
131
132
  search: t.search ?? void 0
132
133
  } : void 0,
133
134
  pagination: n,
@@ -136,16 +137,16 @@ function M(t, n) {
136
137
  skip: !r
137
138
  });
138
139
  return {
139
- data: i?.listExportJobs.edges.map((e) => E(e.node)) ?? [],
140
+ data: i?.listExportJobs.edges.map((e) => O(e.node)) ?? [],
140
141
  totalCount: i?.listExportJobs.totalCount ?? 0,
141
- pageInfo: i?.listExportJobs.pageInfo ? w(i.listExportJobs.pageInfo) : null,
142
+ pageInfo: i?.listExportJobs.pageInfo ? E(i.listExportJobs.pageInfo) : null,
142
143
  isLoading: a,
143
144
  error: o ?? null,
144
145
  refetch: s
145
146
  };
146
147
  }
147
- function N(t) {
148
- let { workspaceId: n } = e(), { data: r, loading: i, error: a, refetch: o } = v(c, {
148
+ function F(t) {
149
+ let { workspaceId: n } = e(), { data: r, loading: i, error: a, refetch: o } = b(c, {
149
150
  variables: {
150
151
  id: t ?? "",
151
152
  context: { workspaceId: n }
@@ -153,57 +154,77 @@ function N(t) {
153
154
  skip: !t || !n
154
155
  });
155
156
  return {
156
- data: r?.getExportJob ? E(r.getExportJob) : null,
157
+ data: r?.getExportJob ? O(r.getExportJob) : null,
157
158
  isLoading: i,
158
159
  error: a ?? null,
159
160
  refetch: o
160
161
  };
161
162
  }
162
- function P(e) {
163
- let { data: t, loading: n, error: r } = y(o, {
163
+ function I(e) {
164
+ let { data: t, loading: n, error: r } = x(o, {
164
165
  variables: { jobId: e ?? "" },
165
166
  skip: !e
166
167
  });
167
168
  return {
168
- data: t?.exportJobProgress ? E(t.exportJobProgress) : null,
169
+ data: t?.exportJobProgress ? O(t.exportJobProgress) : null,
169
170
  isLoading: n,
170
171
  error: r ?? null
171
172
  };
172
173
  }
173
- function F(t) {
174
- let { workspaceId: n } = e(), r = t ?? n, { data: i, loading: a, error: o, refetch: c, fetchMore: l } = v(s, {
174
+ function L(e, { fetchMoreResult: t }) {
175
+ return t ? { getAvailableExportEntities: {
176
+ ...t.getAvailableExportEntities,
177
+ edges: [...e.getAvailableExportEntities.edges, ...t.getAvailableExportEntities.edges]
178
+ } } : e;
179
+ }
180
+ function R(t) {
181
+ let { workspaceId: n } = e(), r = t ?? n, { data: i, loading: a, error: o, refetch: c, fetchMore: l } = b(s, {
175
182
  variables: {
176
183
  context: { workspaceId: r },
177
184
  pagination: { first: 100 }
178
185
  },
179
186
  skip: !r
180
- }), u = i?.getAvailableExportEntities;
181
- return {
182
- data: u?.edges.map((e) => O(e.node)) ?? [],
187
+ }), u = i?.getAvailableExportEntities, d = u?.edges.map((e) => A(e.node)) ?? [], f = async () => {
188
+ !r || !u?.pageInfo.hasNextPage || await l({
189
+ variables: {
190
+ context: { workspaceId: r },
191
+ pagination: {
192
+ first: 100,
193
+ after: u.pageInfo.endCursor
194
+ }
195
+ },
196
+ updateQuery: L
197
+ });
198
+ }, p = u?.pageInfo.hasNextPage ?? !1, m = u?.pageInfo.endCursor ?? null, h = v(null);
199
+ return _(() => {
200
+ a || !r || !p || !m || h.current !== m && (h.current = m, l({
201
+ variables: {
202
+ context: { workspaceId: r },
203
+ pagination: {
204
+ first: 100,
205
+ after: m
206
+ }
207
+ },
208
+ updateQuery: L
209
+ }));
210
+ }, [
211
+ a,
212
+ r,
213
+ p,
214
+ m,
215
+ l
216
+ ]), {
217
+ data: d,
183
218
  totalCount: u?.totalCount ?? 0,
184
- pageInfo: u?.pageInfo ? w(u.pageInfo) : null,
185
- loadMore: async () => {
186
- !r || !u?.pageInfo.hasNextPage || await l({
187
- variables: {
188
- context: { workspaceId: r },
189
- pagination: {
190
- first: 100,
191
- after: u.pageInfo.endCursor
192
- }
193
- },
194
- updateQuery: (e, { fetchMoreResult: t }) => t ? { getAvailableExportEntities: {
195
- ...t.getAvailableExportEntities,
196
- edges: [...e.getAvailableExportEntities.edges, ...t.getAvailableExportEntities.edges]
197
- } } : e
198
- });
199
- },
219
+ pageInfo: u?.pageInfo ? E(u.pageInfo) : null,
220
+ loadMore: f,
200
221
  error: o ?? null,
201
222
  isLoading: a,
202
223
  refetch: c
203
224
  };
204
225
  }
205
- function I(t) {
206
- let { workspaceId: n } = e(), r = t ?? n, { data: i, loading: a, error: o, refetch: s, fetchMore: c } = v(d, {
226
+ function z(t) {
227
+ let { workspaceId: n } = e(), r = t ?? n, { data: i, loading: a, error: o, refetch: s, fetchMore: c } = b(d, {
207
228
  variables: {
208
229
  context: { workspaceId: r },
209
230
  pagination: { first: 50 }
@@ -211,9 +232,9 @@ function I(t) {
211
232
  skip: !r
212
233
  }), l = i?.listExportTemplates;
213
234
  return {
214
- data: l?.edges.map((e) => D(e.node)) ?? [],
235
+ data: l?.edges.map((e) => k(e.node)) ?? [],
215
236
  totalCount: l?.totalCount ?? 0,
216
- pageInfo: l?.pageInfo ? w(l.pageInfo) : null,
237
+ pageInfo: l?.pageInfo ? E(l.pageInfo) : null,
217
238
  loadMore: async () => {
218
239
  !r || !l?.pageInfo.hasNextPage || await c({
219
240
  variables: {
@@ -234,8 +255,8 @@ function I(t) {
234
255
  refetch: s
235
256
  };
236
257
  }
237
- function L(t) {
238
- let { workspaceId: n } = e(), { data: r, loading: i, error: a } = v(l, {
258
+ function B(t) {
259
+ let { workspaceId: n } = e(), { data: r, loading: i, error: a } = b(l, {
239
260
  variables: {
240
261
  id: t ?? "",
241
262
  context: { workspaceId: n }
@@ -243,17 +264,17 @@ function L(t) {
243
264
  skip: !t || !n
244
265
  });
245
266
  return {
246
- data: r?.getExportTemplate ? D(r.getExportTemplate) : null,
267
+ data: r?.getExportTemplate ? k(r.getExportTemplate) : null,
247
268
  isLoading: i,
248
269
  error: a ?? null
249
270
  };
250
271
  }
251
- function R() {
252
- let t = e(), { workspaceId: r } = t, [i, { loading: a, error: o }] = _(n), s = async (e) => {
272
+ function V() {
273
+ let t = e(), { workspaceId: r } = t, [i, { loading: a, error: o }] = y(n), s = async (e) => {
253
274
  let { filters: n, ...a } = e, o = {
254
275
  ...a,
255
- exportScope: a.exportScope ? j(a.exportScope) : void 0,
256
- format: k(a.format),
276
+ exportScope: a.exportScope ? N(a.exportScope) : void 0,
277
+ format: j(a.format),
257
278
  entityFilters: n
258
279
  }, s = await i({
259
280
  variables: {
@@ -266,7 +287,7 @@ function R() {
266
287
  }]
267
288
  });
268
289
  if (!s.data) throw g(t, "export.api.failed", { operation: "createExportJob" }), Error("Failed to create export job");
269
- return g(t, "export.job.created", { jobId: s.data.createExportJob.id }), E(s.data.createExportJob);
290
+ return g(t, "export.job.created", { jobId: s.data.createExportJob.id }), O(s.data.createExportJob);
270
291
  };
271
292
  return {
272
293
  createJob: s,
@@ -277,8 +298,8 @@ function R() {
277
298
  error: o ?? null
278
299
  };
279
300
  }
280
- function z() {
281
- let n = e(), { workspaceId: r } = n, [i, { loading: a, error: o }] = _(t), s = async (e) => {
301
+ function H() {
302
+ let n = e(), { workspaceId: r } = n, [i, { loading: a, error: o }] = y(t), s = async (e) => {
282
303
  let t = await i({
283
304
  variables: {
284
305
  id: e,
@@ -304,8 +325,8 @@ function z() {
304
325
  error: o ?? null
305
326
  };
306
327
  }
307
- function B() {
308
- let t = e(), { workspaceId: n } = t, [r, { loading: a, error: o }] = _(i), s = async (e) => (await r({
328
+ function U() {
329
+ let t = e(), { workspaceId: n } = t, [r, { loading: a, error: o }] = y(i), s = async (e) => (await r({
309
330
  variables: {
310
331
  id: e,
311
332
  context: { workspaceId: n }
@@ -324,8 +345,8 @@ function B() {
324
345
  error: o ?? null
325
346
  };
326
347
  }
327
- function V() {
328
- let t = e(), { workspaceId: n } = t, [r, { loading: i, error: a }] = _(f);
348
+ function W() {
349
+ let t = e(), { workspaceId: n } = t, [r, { loading: i, error: a }] = y(f);
329
350
  return {
330
351
  retryJob: async (e) => {
331
352
  let i = await r({
@@ -345,20 +366,20 @@ function V() {
345
366
  return g(t, "export.job.retried", {
346
367
  originalJobId: e,
347
368
  jobId: i.data.retryExportJob.id
348
- }), E(i.data.retryExportJob);
369
+ }), O(i.data.retryExportJob);
349
370
  },
350
371
  loading: i,
351
372
  isPending: i,
352
373
  error: a ?? null
353
374
  };
354
375
  }
355
- function H() {
356
- let t = e(), { workspaceId: n } = t, [i, { loading: a, error: o }] = _(r);
376
+ function G() {
377
+ let t = e(), { workspaceId: n } = t, [i, { loading: a, error: o }] = y(r);
357
378
  return {
358
379
  createTemplate: async (e) => {
359
380
  let r = {
360
381
  ...e,
361
- format: k(e.format)
382
+ format: j(e.format)
362
383
  }, a = await i({
363
384
  variables: {
364
385
  context: { workspaceId: n },
@@ -370,15 +391,15 @@ function H() {
370
391
  }]
371
392
  });
372
393
  if (!a.data) throw g(t, "export.api.failed", { operation: "createExportTemplate" }), Error("Failed to create export template");
373
- return g(t, "export.template.created", { templateId: a.data.createExportTemplate.id }), D(a.data.createExportTemplate);
394
+ return g(t, "export.template.created", { templateId: a.data.createExportTemplate.id }), k(a.data.createExportTemplate);
374
395
  },
375
396
  loading: a,
376
397
  isPending: a,
377
398
  error: o ?? null
378
399
  };
379
400
  }
380
- function U() {
381
- let t = e(), { workspaceId: n } = t, [r, { loading: i, error: o }] = _(a);
401
+ function K() {
402
+ let t = e(), { workspaceId: n } = t, [r, { loading: i, error: o }] = y(a);
382
403
  return {
383
404
  deleteTemplate: async (e) => (await r({
384
405
  variables: {
@@ -396,6 +417,6 @@ function U() {
396
417
  };
397
418
  }
398
419
  //#endregion
399
- export { F as useAvailableEntities, z as useCancelExportJob, R as useCreateExportJob, H as useCreateExportTemplate, B as useDeleteExportJob, U as useDeleteExportTemplate, N as useExportJob, P as useExportJobProgress, M as useExportJobs, L as useExportTemplate, I as useExportTemplates, V as useRetryExportJob };
420
+ export { R as useAvailableEntities, H as useCancelExportJob, V as useCreateExportJob, G as useCreateExportTemplate, U as useDeleteExportJob, K as useDeleteExportTemplate, F as useExportJob, I as useExportJobProgress, P as useExportJobs, B as useExportTemplate, z as useExportTemplates, W as useRetryExportJob };
400
421
 
401
422
  //# sourceMappingURL=useExportQueries.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useExportQueries.js","names":[],"sources":["../../../src/export/hooks/useExportQueries.ts"],"sourcesContent":["/**\n * Export Query Hooks\n *\n * Real Apollo Client hooks for all export operations.\n * Keep these documents in sync with src/operations/wspace/export/*.graphql.\n */\n\nimport { useMutation, useQuery, useSubscription } from \"@apollo/client/react\";\nimport {\n CancelExportJobDocument,\n CreateExportJobDocument,\n CreateExportTemplateDocument,\n DeleteExportJobDocument,\n DeleteExportTemplateDocument,\n ExportJobProgressDocument,\n GetAvailableExportEntitiesDocument,\n GetExportJobDocument,\n GetExportTemplateDocument,\n ListExportJobsDocument,\n ListExportTemplatesDocument,\n RetryExportJobDocument,\n type CancelExportJobMutation,\n type CancelExportJobMutationVariables,\n type CreateExportJobMutation,\n type CreateExportJobMutationVariables,\n type CreateExportTemplateMutation,\n type CreateExportTemplateMutationVariables,\n type DeleteExportJobMutation,\n type DeleteExportJobMutationVariables,\n type DeleteExportTemplateMutation,\n type DeleteExportTemplateMutationVariables,\n type ExportJobProgressSubscription,\n type ExportJobProgressSubscriptionVariables,\n type GetAvailableExportEntitiesQuery,\n type GetAvailableExportEntitiesQueryVariables,\n type GetExportJobQuery,\n type GetExportJobQueryVariables,\n type GetExportTemplateQuery,\n type GetExportTemplateQueryVariables,\n type ListExportJobsQuery,\n type ListExportJobsQueryVariables,\n type ListExportTemplatesQuery,\n type ListExportTemplatesQueryVariables,\n type RetryExportJobMutation,\n type RetryExportJobMutationVariables,\n} from \"../../generated/wspace-operations\";\nimport {\n ExportFormat as GqlExportFormat,\n ExportJobStatus as GqlExportJobStatus,\n ExportScope as GqlExportScope,\n type CreateExportJobInput as GqlCreateExportJobInput,\n type CreateExportTemplateInput as GqlCreateExportTemplateInput,\n type ExportJobFilterInput as GqlExportJobFilterInput,\n type ExportPaginationInput as GqlExportPaginationInput,\n} from \"../../generated/wspace-types\";\nimport { useExport } from \"../providers/ExportProvider\";\nimport { emitExportEvent } from \"../utils/events\";\nimport type {\n ExportArchiveFormat,\n ExportFormat,\n ExportJob,\n ExportJobStatus,\n ExportScope,\n ExportTemplate,\n ExportAvailableEntity,\n ExportPart,\n ExportFilter,\n PageInfo,\n} from \"../types\";\n\n// ---------------------------------------------------------------------------\n// Mapping helpers\n// ---------------------------------------------------------------------------\n\ntype Nullable<T> = T | null | undefined;\n\ninterface ExportPartLike {\n id: string;\n jobId?: Nullable<string>;\n partNumber: number;\n fileName: string;\n sizeBytes: number | string;\n entityTypes: string[];\n downloadUrl?: Nullable<string>;\n downloadExpiresAt?: Nullable<string>;\n checksum?: Nullable<string>;\n createdAt?: Nullable<string>;\n}\n\ninterface ExportJobLike {\n id: string;\n name: string;\n description?: Nullable<string>;\n status: string;\n progress: number;\n exportScope?: Nullable<string>;\n organizationId?: Nullable<string>;\n targetWorkspaceIds?: Nullable<string[]>;\n entityTypes: string[];\n format: string;\n archiveFormat?: Nullable<string>;\n totalEntities?: Nullable<number>;\n processedEntities?: Nullable<number>;\n totalSizeBytes?: Nullable<number | string>;\n parts?: Nullable<ExportPartLike[]>;\n templateId?: Nullable<string>;\n entityFilters?: Nullable<Record<string, unknown>>;\n errorMessage?: Nullable<string>;\n startedAt?: Nullable<string>;\n completedAt?: Nullable<string>;\n expiresAt?: Nullable<string>;\n createdBy: string;\n temporalWorkflowId?: Nullable<string>;\n workspaceId?: Nullable<string>;\n createdAt: string;\n updatedAt: string;\n}\n\ninterface ExportTemplateLike {\n id: string;\n name: string;\n description?: Nullable<string>;\n entityTypes: string[];\n format: string;\n entityFilters?: Nullable<Record<string, unknown>>;\n isDefault: boolean;\n workspaceId?: Nullable<string>;\n createdBy: string;\n createdAt: string;\n updatedAt: string;\n}\n\ninterface ExportAvailableEntityLike {\n entityType: string;\n displayName: string;\n description?: Nullable<string>;\n estimatedSize?: Nullable<string>;\n supportsDateRange: boolean;\n supportsMediaExport: boolean;\n enabled: boolean;\n}\n\nfunction optionalString(value: Nullable<string>): string | undefined {\n return value ?? undefined;\n}\n\nfunction optionalNumber(value: Nullable<number | string>): number | undefined {\n if (value == null) return undefined;\n const parsed = typeof value === \"number\" ? value : Number(value);\n return Number.isFinite(parsed) ? parsed : undefined;\n}\n\nfunction numberOrZero(value: Nullable<number | string>): number {\n return optionalNumber(value) ?? 0;\n}\n\nfunction optionalRecord(\n value: Nullable<Record<string, unknown>>,\n): Record<string, unknown> | undefined {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? value\n : undefined;\n}\n\nfunction mapPageInfo(pageInfo: {\n hasNextPage: boolean;\n hasPreviousPage: boolean;\n startCursor?: Nullable<string>;\n endCursor?: Nullable<string>;\n}): PageInfo {\n return {\n hasNextPage: pageInfo.hasNextPage,\n hasPreviousPage: pageInfo.hasPreviousPage,\n startCursor: optionalString(pageInfo.startCursor),\n endCursor: optionalString(pageInfo.endCursor),\n };\n}\n\nfunction mapPart(part: ExportPartLike): ExportPart {\n return {\n id: part.id,\n jobId: optionalString(part.jobId),\n partNumber: part.partNumber,\n fileName: part.fileName,\n sizeBytes: numberOrZero(part.sizeBytes),\n entityTypes: part.entityTypes,\n downloadUrl: optionalString(part.downloadUrl),\n downloadExpiresAt: optionalString(part.downloadExpiresAt),\n checksum: optionalString(part.checksum),\n createdAt: optionalString(part.createdAt),\n };\n}\n\nfunction mapJob(job: ExportJobLike): ExportJob {\n return {\n id: job.id,\n name: job.name,\n description: optionalString(job.description),\n status: job.status as ExportJobStatus,\n progress: job.progress,\n exportScope: job.exportScope ? (job.exportScope as ExportScope) : undefined,\n organizationId: optionalString(job.organizationId),\n targetWorkspaceIds: job.targetWorkspaceIds ?? undefined,\n entityTypes: job.entityTypes,\n format: job.format as ExportFormat,\n archiveFormat: (job.archiveFormat ?? \"ZIP\") as ExportArchiveFormat,\n totalEntities: optionalNumber(job.totalEntities),\n processedEntities: optionalNumber(job.processedEntities),\n totalSizeBytes: optionalNumber(job.totalSizeBytes),\n parts: job.parts?.map(mapPart) ?? [],\n templateId: optionalString(job.templateId),\n filters: optionalRecord(job.entityFilters),\n errorMessage: optionalString(job.errorMessage),\n startedAt: optionalString(job.startedAt),\n completedAt: optionalString(job.completedAt),\n expiresAt: optionalString(job.expiresAt),\n createdBy: job.createdBy,\n temporalWorkflowId: optionalString(job.temporalWorkflowId),\n workspaceId: optionalString(job.workspaceId),\n createdAt: job.createdAt,\n updatedAt: job.updatedAt,\n };\n}\n\nfunction mapTemplate(template: ExportTemplateLike): ExportTemplate {\n return {\n id: template.id,\n name: template.name,\n description: optionalString(template.description),\n entityTypes: template.entityTypes,\n format: template.format as ExportFormat,\n filters: optionalRecord(template.entityFilters),\n isDefault: template.isDefault,\n createdBy: template.createdBy,\n workspaceId: optionalString(template.workspaceId),\n createdAt: template.createdAt,\n updatedAt: template.updatedAt,\n };\n}\n\nfunction mapAvailableEntity(\n entity: ExportAvailableEntityLike,\n): ExportAvailableEntity {\n return {\n entityType: entity.entityType,\n displayName: entity.displayName,\n description: optionalString(entity.description),\n estimatedSize: optionalString(entity.estimatedSize),\n supportsDateRange: entity.supportsDateRange,\n supportsMediaExport: entity.supportsMediaExport,\n enabled: entity.enabled,\n };\n}\n\nfunction toGqlFormat(format: ExportFormat | string): GqlExportFormat {\n if (format === \"CSV\") return GqlExportFormat.Csv;\n if (format === \"JSON\") return GqlExportFormat.Json;\n throw new Error(`Unsupported export format: ${format}`);\n}\n\nfunction toGqlStatus(status: ExportJobStatus | string): GqlExportJobStatus {\n switch (status) {\n case \"CANCELLED\":\n return GqlExportJobStatus.Cancelled;\n case \"COMPLETED\":\n return GqlExportJobStatus.Completed;\n case \"CREATED\":\n return GqlExportJobStatus.Created;\n case \"DELETED\":\n return GqlExportJobStatus.Deleted;\n case \"EXPIRED\":\n return GqlExportJobStatus.Expired;\n case \"FAILED\":\n return GqlExportJobStatus.Failed;\n case \"QUEUED\":\n return GqlExportJobStatus.Queued;\n case \"RUNNING\":\n return GqlExportJobStatus.Running;\n default:\n throw new Error(`Unsupported export status: ${status}`);\n }\n}\n\nfunction toGqlScope(scope: ExportScope | string): GqlExportScope {\n switch (scope) {\n case \"INDIVIDUAL\":\n return GqlExportScope.Individual;\n case \"WORKSPACE_ADMIN\":\n return GqlExportScope.WorkspaceAdmin;\n case \"ORG_ADMIN\":\n return GqlExportScope.OrgAdmin;\n default:\n throw new Error(`Unsupported export scope: ${scope}`);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Query Hooks\n// ---------------------------------------------------------------------------\n\n/**\n * Input for creating an export job\n */\nexport interface CreateExportJobInput {\n name: string;\n description?: string;\n exportScope?: ExportScope;\n organizationId?: string;\n entityTypes: string[];\n format: ExportFormat;\n filters?: Record<string, unknown>;\n templateId?: string;\n dateRangeStart?: string | null;\n dateRangeEnd?: string | null;\n}\n\n/**\n * Input for creating an export template\n */\nexport interface CreateExportTemplateInput {\n name: string;\n description?: string;\n entityTypes: string[];\n format: ExportFormat;\n}\n\n/**\n * Filter input for listing export jobs\n */\nexport interface ExportJobFilterInput {\n status?: ExportJobStatus[];\n format?: ExportFormat;\n entityTypes?: string[];\n search?: string;\n dateFrom?: string;\n dateTo?: string;\n}\n\n/**\n * Pagination input for export job list\n */\nexport interface ExportPaginationInput {\n first?: number;\n after?: string;\n last?: number;\n before?: string;\n}\n\n/**\n * Hook to fetch a paginated list of export jobs\n */\nexport function useExportJobs(\n filter?: Partial<ExportFilter>,\n pagination?: ExportPaginationInput,\n) {\n const { workspaceId } = useExport();\n\n // Build the backend filter from the UI filter shape\n const backendFilter: GqlExportJobFilterInput | undefined =\n filter && workspaceId\n ? {\n status:\n filter.status && filter.status !== \"all\"\n ? [toGqlStatus(filter.status)]\n : undefined,\n format:\n filter.format && filter.format !== \"all\"\n ? toGqlFormat(filter.format)\n : undefined,\n search: filter.search ?? undefined,\n }\n : undefined;\n\n const { data, loading, error, refetch } = useQuery<\n ListExportJobsQuery,\n ListExportJobsQueryVariables\n >(ListExportJobsDocument, {\n variables: {\n filter: backendFilter,\n pagination: pagination as GqlExportPaginationInput | undefined,\n context: { workspaceId },\n },\n skip: !workspaceId,\n });\n\n const jobs = data?.listExportJobs.edges.map((e) => mapJob(e.node)) ?? [];\n const totalCount = data?.listExportJobs.totalCount ?? 0;\n const pageInfo = data?.listExportJobs.pageInfo\n ? mapPageInfo(data.listExportJobs.pageInfo)\n : null;\n\n return {\n data: jobs,\n totalCount,\n pageInfo,\n isLoading: loading,\n error: error ?? null,\n refetch,\n };\n}\n\n/**\n * Hook to fetch a single export job by ID.\n */\nexport function useExportJob(jobId: string | undefined) {\n const { workspaceId } = useExport();\n\n const { data, loading, error, refetch } = useQuery<\n GetExportJobQuery,\n GetExportJobQueryVariables\n >(GetExportJobDocument, {\n variables: { id: jobId ?? \"\", context: { workspaceId } },\n skip: !jobId || !workspaceId,\n });\n\n const job = data?.getExportJob ? mapJob(data.getExportJob) : null;\n\n return {\n data: job,\n isLoading: loading,\n error: error ?? null,\n refetch,\n };\n}\n\n/**\n * Hook to subscribe to live progress updates for an export job.\n */\nexport function useExportJobProgress(jobId: string | undefined) {\n const { data, loading, error } = useSubscription<\n ExportJobProgressSubscription,\n ExportJobProgressSubscriptionVariables\n >(ExportJobProgressDocument, {\n variables: { jobId: jobId ?? \"\" },\n skip: !jobId,\n });\n\n return {\n data: data?.exportJobProgress ? mapJob(data.exportJobProgress) : null,\n isLoading: loading,\n error: error ?? null,\n };\n}\n\n/**\n * Hook to fetch available entity types for export in a workspace\n */\nexport function useAvailableEntities(overrideWorkspaceId?: string) {\n const { workspaceId: ctxWorkspaceId } = useExport();\n const workspaceId = overrideWorkspaceId ?? ctxWorkspaceId;\n\n const { data, loading, error, refetch, fetchMore } = useQuery<\n GetAvailableExportEntitiesQuery,\n GetAvailableExportEntitiesQueryVariables\n >(GetAvailableExportEntitiesDocument, {\n variables: {\n context: { workspaceId },\n pagination: { first: 100 },\n },\n skip: !workspaceId,\n });\n\n const connection = data?.getAvailableExportEntities;\n const entities =\n connection?.edges.map((edge) => mapAvailableEntity(edge.node)) ?? [];\n\n const loadMore = async () => {\n if (!workspaceId || !connection?.pageInfo.hasNextPage) return;\n await fetchMore({\n variables: {\n context: { workspaceId },\n pagination: { first: 100, after: connection.pageInfo.endCursor },\n },\n updateQuery: (previous, { fetchMoreResult }) => {\n if (!fetchMoreResult) return previous;\n return {\n getAvailableExportEntities: {\n ...fetchMoreResult.getAvailableExportEntities,\n edges: [\n ...previous.getAvailableExportEntities.edges,\n ...fetchMoreResult.getAvailableExportEntities.edges,\n ],\n },\n };\n },\n });\n };\n\n return {\n data: entities,\n totalCount: connection?.totalCount ?? 0,\n pageInfo: connection?.pageInfo ? mapPageInfo(connection.pageInfo) : null,\n loadMore,\n error: error ?? null,\n isLoading: loading,\n refetch,\n };\n}\n\n/**\n * Hook to fetch all export templates for the current workspace\n */\nexport function useExportTemplates(overrideWorkspaceId?: string) {\n const { workspaceId: ctxWorkspaceId } = useExport();\n const workspaceId = overrideWorkspaceId ?? ctxWorkspaceId;\n\n const { data, loading, error, refetch, fetchMore } = useQuery<\n ListExportTemplatesQuery,\n ListExportTemplatesQueryVariables\n >(ListExportTemplatesDocument, {\n variables: {\n context: { workspaceId },\n pagination: { first: 50 },\n },\n skip: !workspaceId,\n });\n\n const connection = data?.listExportTemplates;\n const templates =\n connection?.edges.map((edge) => mapTemplate(edge.node)) ?? [];\n\n const loadMore = async () => {\n if (!workspaceId || !connection?.pageInfo.hasNextPage) return;\n await fetchMore({\n variables: {\n context: { workspaceId },\n pagination: { first: 50, after: connection.pageInfo.endCursor },\n },\n updateQuery: (previous, { fetchMoreResult }) => {\n if (!fetchMoreResult) return previous;\n return {\n listExportTemplates: {\n ...fetchMoreResult.listExportTemplates,\n edges: [\n ...previous.listExportTemplates.edges,\n ...fetchMoreResult.listExportTemplates.edges,\n ],\n },\n };\n },\n });\n };\n\n return {\n data: templates,\n totalCount: connection?.totalCount ?? 0,\n pageInfo: connection?.pageInfo ? mapPageInfo(connection.pageInfo) : null,\n loadMore,\n isLoading: loading,\n error: error ?? null,\n refetch,\n };\n}\n\n/**\n * Hook to fetch a single export template by ID\n */\nexport function useExportTemplate(templateId: string | undefined) {\n const { workspaceId } = useExport();\n\n const { data, loading, error } = useQuery<\n GetExportTemplateQuery,\n GetExportTemplateQueryVariables\n >(GetExportTemplateDocument, {\n variables: { id: templateId ?? \"\", context: { workspaceId } },\n skip: !templateId || !workspaceId,\n });\n\n return {\n data: data?.getExportTemplate ? mapTemplate(data.getExportTemplate) : null,\n isLoading: loading,\n error: error ?? null,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Mutation Hooks\n// ---------------------------------------------------------------------------\n\n/**\n * Hook to create a new export job\n */\nexport function useCreateExportJob() {\n const exportContext = useExport();\n const { workspaceId } = exportContext;\n const [mutate, { loading, error }] = useMutation<\n CreateExportJobMutation,\n CreateExportJobMutationVariables\n >(CreateExportJobDocument);\n\n const createJob = async (input: CreateExportJobInput): Promise<ExportJob> => {\n const { filters, ...restInput } = input;\n const gqlInput: GqlCreateExportJobInput = {\n ...restInput,\n exportScope: restInput.exportScope\n ? toGqlScope(restInput.exportScope)\n : undefined,\n format: toGqlFormat(restInput.format),\n entityFilters: filters,\n };\n\n const result = await mutate({\n variables: {\n context: { workspaceId },\n input: gqlInput,\n },\n refetchQueries: [\n {\n query: ListExportJobsDocument,\n variables: { context: { workspaceId } },\n },\n ],\n });\n if (!result.data) {\n emitExportEvent(exportContext, \"export.api.failed\", {\n operation: \"createExportJob\",\n });\n throw new Error(\"Failed to create export job\");\n }\n emitExportEvent(exportContext, \"export.job.created\", {\n jobId: result.data.createExportJob.id,\n });\n return mapJob(result.data.createExportJob);\n };\n\n return {\n createJob,\n // Keep legacy names for existing callers\n mutate: createJob,\n mutateAsync: createJob,\n loading,\n isPending: loading,\n error: error ?? null,\n };\n}\n\n/**\n * Hook to cancel an export job\n */\nexport function useCancelExportJob() {\n const exportContext = useExport();\n const { workspaceId } = exportContext;\n const [mutate, { loading, error }] = useMutation<\n CancelExportJobMutation,\n CancelExportJobMutationVariables\n >(CancelExportJobDocument);\n\n const cancelJob = async (id: string) => {\n const result = await mutate({\n variables: {\n id,\n context: { workspaceId },\n },\n refetchQueries: [\n {\n query: ListExportJobsDocument,\n variables: { context: { workspaceId } },\n },\n ],\n });\n if (!result.data) {\n emitExportEvent(exportContext, \"export.api.failed\", {\n operation: \"cancelExportJob\",\n jobId: id,\n });\n throw new Error(\"Failed to cancel export job\");\n }\n emitExportEvent(exportContext, \"export.job.cancelled\", { jobId: id });\n return result.data.cancelExportJob;\n };\n\n return {\n cancelJob,\n mutate: cancelJob,\n mutateAsync: cancelJob,\n loading,\n isPending: loading,\n error: error ?? null,\n };\n}\n\n/**\n * Hook to delete an export job\n */\nexport function useDeleteExportJob() {\n const exportContext = useExport();\n const { workspaceId } = exportContext;\n const [mutate, { loading, error }] = useMutation<\n DeleteExportJobMutation,\n DeleteExportJobMutationVariables\n >(DeleteExportJobDocument);\n\n const deleteJob = async (id: string): Promise<boolean> => {\n await mutate({\n variables: {\n id,\n context: { workspaceId },\n },\n refetchQueries: [\n {\n query: ListExportJobsDocument,\n variables: { context: { workspaceId } },\n },\n ],\n });\n emitExportEvent(exportContext, \"export.job.deleted\", { jobId: id });\n return true;\n };\n\n return {\n deleteJob,\n mutate: deleteJob,\n mutateAsync: deleteJob,\n loading,\n isPending: loading,\n error: error ?? null,\n };\n}\n\n/**\n * Hook to retry a failed export job\n */\nexport function useRetryExportJob() {\n const exportContext = useExport();\n const { workspaceId } = exportContext;\n const [mutate, { loading, error }] = useMutation<\n RetryExportJobMutation,\n RetryExportJobMutationVariables\n >(RetryExportJobDocument);\n\n const retryJob = async (id: string): Promise<ExportJob> => {\n const result = await mutate({\n variables: { id, context: { workspaceId } },\n refetchQueries: [\n {\n query: ListExportJobsDocument,\n variables: { context: { workspaceId } },\n },\n ],\n });\n if (!result.data) {\n emitExportEvent(exportContext, \"export.api.failed\", {\n operation: \"retryExportJob\",\n jobId: id,\n });\n throw new Error(\"Failed to retry export job\");\n }\n emitExportEvent(exportContext, \"export.job.retried\", {\n originalJobId: id,\n jobId: result.data.retryExportJob.id,\n });\n return mapJob(result.data.retryExportJob);\n };\n\n return {\n retryJob,\n loading,\n isPending: loading,\n error: error ?? null,\n };\n}\n\n/**\n * Hook to create a new export template\n */\nexport function useCreateExportTemplate() {\n const exportContext = useExport();\n const { workspaceId } = exportContext;\n const [mutate, { loading, error }] = useMutation<\n CreateExportTemplateMutation,\n CreateExportTemplateMutationVariables\n >(CreateExportTemplateDocument);\n\n const createTemplate = async (\n input: CreateExportTemplateInput,\n ): Promise<ExportTemplate> => {\n const gqlInput: GqlCreateExportTemplateInput = {\n ...input,\n format: toGqlFormat(input.format),\n };\n\n const result = await mutate({\n variables: {\n context: { workspaceId },\n input: gqlInput,\n },\n refetchQueries: [\n {\n query: ListExportTemplatesDocument,\n variables: { context: { workspaceId } },\n },\n ],\n });\n if (!result.data) {\n emitExportEvent(exportContext, \"export.api.failed\", {\n operation: \"createExportTemplate\",\n });\n throw new Error(\"Failed to create export template\");\n }\n emitExportEvent(exportContext, \"export.template.created\", {\n templateId: result.data.createExportTemplate.id,\n });\n return mapTemplate(result.data.createExportTemplate);\n };\n\n return {\n createTemplate,\n loading,\n isPending: loading,\n error: error ?? null,\n };\n}\n\n/**\n * Hook to delete an export template\n */\nexport function useDeleteExportTemplate() {\n const exportContext = useExport();\n const { workspaceId } = exportContext;\n const [mutate, { loading, error }] = useMutation<\n DeleteExportTemplateMutation,\n DeleteExportTemplateMutationVariables\n >(DeleteExportTemplateDocument);\n\n const deleteTemplate = async (id: string): Promise<boolean> => {\n await mutate({\n variables: {\n id,\n context: { workspaceId },\n },\n refetchQueries: [\n {\n query: ListExportTemplatesDocument,\n variables: { context: { workspaceId } },\n },\n ],\n });\n emitExportEvent(exportContext, \"export.template.deleted\", {\n templateId: id,\n });\n return true;\n };\n\n return {\n deleteTemplate,\n loading,\n isPending: loading,\n error: error ?? null,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"useExportQueries.js","names":[],"sources":["../../../src/export/hooks/useExportQueries.ts"],"sourcesContent":["/**\n * Export Query Hooks\n *\n * Real Apollo Client hooks for all export operations.\n * Keep these documents in sync with src/operations/wspace/export/*.graphql.\n */\n\nimport { useEffect, useRef } from \"react\";\nimport { useMutation, useQuery, useSubscription } from \"@apollo/client/react\";\nimport {\n CancelExportJobDocument,\n CreateExportJobDocument,\n CreateExportTemplateDocument,\n DeleteExportJobDocument,\n DeleteExportTemplateDocument,\n ExportJobProgressDocument,\n GetAvailableExportEntitiesDocument,\n GetExportJobDocument,\n GetExportTemplateDocument,\n ListExportJobsDocument,\n ListExportTemplatesDocument,\n RetryExportJobDocument,\n type CancelExportJobMutation,\n type CancelExportJobMutationVariables,\n type CreateExportJobMutation,\n type CreateExportJobMutationVariables,\n type CreateExportTemplateMutation,\n type CreateExportTemplateMutationVariables,\n type DeleteExportJobMutation,\n type DeleteExportJobMutationVariables,\n type DeleteExportTemplateMutation,\n type DeleteExportTemplateMutationVariables,\n type ExportJobProgressSubscription,\n type ExportJobProgressSubscriptionVariables,\n type GetAvailableExportEntitiesQuery,\n type GetAvailableExportEntitiesQueryVariables,\n type GetExportJobQuery,\n type GetExportJobQueryVariables,\n type GetExportTemplateQuery,\n type GetExportTemplateQueryVariables,\n type ListExportJobsQuery,\n type ListExportJobsQueryVariables,\n type ListExportTemplatesQuery,\n type ListExportTemplatesQueryVariables,\n type RetryExportJobMutation,\n type RetryExportJobMutationVariables,\n} from \"../../generated/wspace-operations\";\nimport {\n ExportFormat as GqlExportFormat,\n ExportJobStatus as GqlExportJobStatus,\n ExportScope as GqlExportScope,\n type CreateExportJobInput as GqlCreateExportJobInput,\n type CreateExportTemplateInput as GqlCreateExportTemplateInput,\n type ExportJobFilterInput as GqlExportJobFilterInput,\n type ExportPaginationInput as GqlExportPaginationInput,\n} from \"../../generated/wspace-types\";\nimport { useExport } from \"../providers/ExportProvider\";\nimport { emitExportEvent } from \"../utils/events\";\nimport type {\n ExportArchiveFormat,\n ExportFormat,\n ExportJob,\n ExportJobStatus,\n ExportScope,\n ExportTemplate,\n ExportAvailableEntity,\n ExportPart,\n ExportFilter,\n PageInfo,\n} from \"../types\";\n\n// ---------------------------------------------------------------------------\n// Mapping helpers\n// ---------------------------------------------------------------------------\n\ntype Nullable<T> = T | null | undefined;\n\ninterface ExportPartLike {\n id: string;\n jobId?: Nullable<string>;\n partNumber: number;\n fileName: string;\n sizeBytes: number | string;\n entityTypes: string[];\n downloadUrl?: Nullable<string>;\n downloadExpiresAt?: Nullable<string>;\n checksum?: Nullable<string>;\n createdAt?: Nullable<string>;\n}\n\ninterface ExportJobLike {\n id: string;\n name: string;\n description?: Nullable<string>;\n status: string;\n progress: number;\n exportScope?: Nullable<string>;\n organizationId?: Nullable<string>;\n targetWorkspaceIds?: Nullable<string[]>;\n entityTypes: string[];\n format: string;\n archiveFormat?: Nullable<string>;\n totalEntities?: Nullable<number>;\n processedEntities?: Nullable<number>;\n totalSizeBytes?: Nullable<number | string>;\n parts?: Nullable<ExportPartLike[]>;\n templateId?: Nullable<string>;\n entityFilters?: Nullable<Record<string, unknown>>;\n errorMessage?: Nullable<string>;\n startedAt?: Nullable<string>;\n completedAt?: Nullable<string>;\n expiresAt?: Nullable<string>;\n createdBy: string;\n temporalWorkflowId?: Nullable<string>;\n workspaceId?: Nullable<string>;\n createdAt: string;\n updatedAt: string;\n}\n\ninterface ExportTemplateLike {\n id: string;\n name: string;\n description?: Nullable<string>;\n entityTypes: string[];\n format: string;\n entityFilters?: Nullable<Record<string, unknown>>;\n isDefault: boolean;\n workspaceId?: Nullable<string>;\n createdBy: string;\n createdAt: string;\n updatedAt: string;\n}\n\ninterface ExportAvailableEntityLike {\n entityType: string;\n displayName: string;\n description?: Nullable<string>;\n estimatedSize?: Nullable<string>;\n supportsDateRange: boolean;\n supportsMediaExport: boolean;\n enabled: boolean;\n}\n\nfunction optionalString(value: Nullable<string>): string | undefined {\n return value ?? undefined;\n}\n\nfunction optionalNumber(value: Nullable<number | string>): number | undefined {\n if (value == null) return undefined;\n const parsed = typeof value === \"number\" ? value : Number(value);\n return Number.isFinite(parsed) ? parsed : undefined;\n}\n\nfunction numberOrZero(value: Nullable<number | string>): number {\n return optionalNumber(value) ?? 0;\n}\n\nfunction optionalRecord(\n value: Nullable<Record<string, unknown>>,\n): Record<string, unknown> | undefined {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? value\n : undefined;\n}\n\nfunction mapPageInfo(pageInfo: {\n hasNextPage: boolean;\n hasPreviousPage: boolean;\n startCursor?: Nullable<string>;\n endCursor?: Nullable<string>;\n}): PageInfo {\n return {\n hasNextPage: pageInfo.hasNextPage,\n hasPreviousPage: pageInfo.hasPreviousPage,\n startCursor: optionalString(pageInfo.startCursor),\n endCursor: optionalString(pageInfo.endCursor),\n };\n}\n\nfunction mapPart(part: ExportPartLike): ExportPart {\n return {\n id: part.id,\n jobId: optionalString(part.jobId),\n partNumber: part.partNumber,\n fileName: part.fileName,\n sizeBytes: numberOrZero(part.sizeBytes),\n entityTypes: part.entityTypes,\n downloadUrl: optionalString(part.downloadUrl),\n downloadExpiresAt: optionalString(part.downloadExpiresAt),\n checksum: optionalString(part.checksum),\n createdAt: optionalString(part.createdAt),\n };\n}\n\nfunction mapJob(job: ExportJobLike): ExportJob {\n return {\n id: job.id,\n name: job.name,\n description: optionalString(job.description),\n status: job.status as ExportJobStatus,\n progress: job.progress,\n exportScope: job.exportScope ? (job.exportScope as ExportScope) : undefined,\n organizationId: optionalString(job.organizationId),\n targetWorkspaceIds: job.targetWorkspaceIds ?? undefined,\n entityTypes: job.entityTypes,\n format: job.format as ExportFormat,\n archiveFormat: (job.archiveFormat ?? \"ZIP\") as ExportArchiveFormat,\n totalEntities: optionalNumber(job.totalEntities),\n processedEntities: optionalNumber(job.processedEntities),\n totalSizeBytes: optionalNumber(job.totalSizeBytes),\n parts: job.parts?.map(mapPart) ?? [],\n templateId: optionalString(job.templateId),\n filters: optionalRecord(job.entityFilters),\n errorMessage: optionalString(job.errorMessage),\n startedAt: optionalString(job.startedAt),\n completedAt: optionalString(job.completedAt),\n expiresAt: optionalString(job.expiresAt),\n createdBy: job.createdBy,\n temporalWorkflowId: optionalString(job.temporalWorkflowId),\n workspaceId: optionalString(job.workspaceId),\n createdAt: job.createdAt,\n updatedAt: job.updatedAt,\n };\n}\n\nfunction mapTemplate(template: ExportTemplateLike): ExportTemplate {\n return {\n id: template.id,\n name: template.name,\n description: optionalString(template.description),\n entityTypes: template.entityTypes,\n format: template.format as ExportFormat,\n filters: optionalRecord(template.entityFilters),\n isDefault: template.isDefault,\n createdBy: template.createdBy,\n workspaceId: optionalString(template.workspaceId),\n createdAt: template.createdAt,\n updatedAt: template.updatedAt,\n };\n}\n\nfunction mapAvailableEntity(\n entity: ExportAvailableEntityLike,\n): ExportAvailableEntity {\n return {\n entityType: entity.entityType,\n displayName: entity.displayName,\n description: optionalString(entity.description),\n estimatedSize: optionalString(entity.estimatedSize),\n supportsDateRange: entity.supportsDateRange,\n supportsMediaExport: entity.supportsMediaExport,\n enabled: entity.enabled,\n };\n}\n\nfunction toGqlFormat(format: ExportFormat | string): GqlExportFormat {\n if (format === \"CSV\") return GqlExportFormat.Csv;\n if (format === \"JSON\") return GqlExportFormat.Json;\n throw new Error(`Unsupported export format: ${format}`);\n}\n\nfunction toGqlStatus(status: ExportJobStatus | string): GqlExportJobStatus {\n switch (status) {\n case \"CANCELLED\":\n return GqlExportJobStatus.Cancelled;\n case \"COMPLETED\":\n return GqlExportJobStatus.Completed;\n case \"CREATED\":\n return GqlExportJobStatus.Created;\n case \"DELETED\":\n return GqlExportJobStatus.Deleted;\n case \"EXPIRED\":\n return GqlExportJobStatus.Expired;\n case \"FAILED\":\n return GqlExportJobStatus.Failed;\n case \"QUEUED\":\n return GqlExportJobStatus.Queued;\n case \"RUNNING\":\n return GqlExportJobStatus.Running;\n default:\n throw new Error(`Unsupported export status: ${status}`);\n }\n}\n\nfunction toGqlScope(scope: ExportScope | string): GqlExportScope {\n switch (scope) {\n case \"INDIVIDUAL\":\n return GqlExportScope.Individual;\n case \"WORKSPACE_ADMIN\":\n return GqlExportScope.WorkspaceAdmin;\n case \"ORG_ADMIN\":\n return GqlExportScope.OrgAdmin;\n default:\n throw new Error(`Unsupported export scope: ${scope}`);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Query Hooks\n// ---------------------------------------------------------------------------\n\n/**\n * Input for creating an export job\n */\nexport interface CreateExportJobInput {\n name: string;\n description?: string;\n exportScope?: ExportScope;\n organizationId?: string;\n entityTypes: string[];\n format: ExportFormat;\n filters?: Record<string, unknown>;\n templateId?: string;\n dateRangeStart?: string | null;\n dateRangeEnd?: string | null;\n}\n\n/**\n * Input for creating an export template\n */\nexport interface CreateExportTemplateInput {\n name: string;\n description?: string;\n entityTypes: string[];\n format: ExportFormat;\n}\n\n/**\n * Filter input for listing export jobs\n */\nexport interface ExportJobFilterInput {\n status?: ExportJobStatus[];\n format?: ExportFormat;\n entityTypes?: string[];\n search?: string;\n dateFrom?: string;\n dateTo?: string;\n}\n\n/**\n * Pagination input for export job list\n */\nexport interface ExportPaginationInput {\n first?: number;\n after?: string;\n last?: number;\n before?: string;\n}\n\n/**\n * Hook to fetch a paginated list of export jobs\n */\nexport function useExportJobs(\n filter?: Partial<ExportFilter>,\n pagination?: ExportPaginationInput,\n) {\n const { workspaceId } = useExport();\n\n // Build the backend filter from the UI filter shape\n const backendFilter: GqlExportJobFilterInput | undefined =\n filter && workspaceId\n ? {\n status:\n filter.status && filter.status !== \"all\"\n ? [toGqlStatus(filter.status)]\n : undefined,\n format:\n filter.format && filter.format !== \"all\"\n ? toGqlFormat(filter.format)\n : undefined,\n search: filter.search ?? undefined,\n }\n : undefined;\n\n const { data, loading, error, refetch } = useQuery<\n ListExportJobsQuery,\n ListExportJobsQueryVariables\n >(ListExportJobsDocument, {\n variables: {\n filter: backendFilter,\n pagination: pagination as GqlExportPaginationInput | undefined,\n context: { workspaceId },\n },\n skip: !workspaceId,\n });\n\n const jobs = data?.listExportJobs.edges.map((e) => mapJob(e.node)) ?? [];\n const totalCount = data?.listExportJobs.totalCount ?? 0;\n const pageInfo = data?.listExportJobs.pageInfo\n ? mapPageInfo(data.listExportJobs.pageInfo)\n : null;\n\n return {\n data: jobs,\n totalCount,\n pageInfo,\n isLoading: loading,\n error: error ?? null,\n refetch,\n };\n}\n\n/**\n * Hook to fetch a single export job by ID.\n */\nexport function useExportJob(jobId: string | undefined) {\n const { workspaceId } = useExport();\n\n const { data, loading, error, refetch } = useQuery<\n GetExportJobQuery,\n GetExportJobQueryVariables\n >(GetExportJobDocument, {\n variables: { id: jobId ?? \"\", context: { workspaceId } },\n skip: !jobId || !workspaceId,\n });\n\n const job = data?.getExportJob ? mapJob(data.getExportJob) : null;\n\n return {\n data: job,\n isLoading: loading,\n error: error ?? null,\n refetch,\n };\n}\n\n/**\n * Hook to subscribe to live progress updates for an export job.\n */\nexport function useExportJobProgress(jobId: string | undefined) {\n const { data, loading, error } = useSubscription<\n ExportJobProgressSubscription,\n ExportJobProgressSubscriptionVariables\n >(ExportJobProgressDocument, {\n variables: { jobId: jobId ?? \"\" },\n skip: !jobId,\n });\n\n return {\n data: data?.exportJobProgress ? mapJob(data.exportJobProgress) : null,\n isLoading: loading,\n error: error ?? null,\n };\n}\n\n/** Apollo `updateQuery` for the catalog: append a fetched page's edges. */\nfunction appendEntityPage(\n previous: GetAvailableExportEntitiesQuery,\n { fetchMoreResult }: { fetchMoreResult?: GetAvailableExportEntitiesQuery },\n): GetAvailableExportEntitiesQuery {\n if (!fetchMoreResult) return previous;\n return {\n getAvailableExportEntities: {\n ...fetchMoreResult.getAvailableExportEntities,\n edges: [\n ...previous.getAvailableExportEntities.edges,\n ...fetchMoreResult.getAvailableExportEntities.edges,\n ],\n },\n };\n}\n\n/**\n * Hook to fetch available entity types for export in a workspace\n */\nexport function useAvailableEntities(overrideWorkspaceId?: string) {\n const { workspaceId: ctxWorkspaceId } = useExport();\n const workspaceId = overrideWorkspaceId ?? ctxWorkspaceId;\n\n const { data, loading, error, refetch, fetchMore } = useQuery<\n GetAvailableExportEntitiesQuery,\n GetAvailableExportEntitiesQueryVariables\n >(GetAvailableExportEntitiesDocument, {\n variables: {\n context: { workspaceId },\n pagination: { first: 100 },\n },\n skip: !workspaceId,\n });\n\n const connection = data?.getAvailableExportEntities;\n const entities =\n connection?.edges.map((edge) => mapAvailableEntity(edge.node)) ?? [];\n\n const loadMore = async () => {\n if (!workspaceId || !connection?.pageInfo.hasNextPage) return;\n await fetchMore({\n variables: {\n context: { workspaceId },\n pagination: { first: 100, after: connection.pageInfo.endCursor },\n },\n updateQuery: appendEntityPage,\n });\n };\n\n // The entity picker and the template editor need the whole catalog (well\n // over one 100-entry page: entities are sorted by display name, so products\n // late in the alphabet, e.g. VibeControls, were never shown). Fetch the\n // remaining pages, once per cursor.\n const hasNextPage = connection?.pageInfo.hasNextPage ?? false;\n const endCursor = connection?.pageInfo.endCursor ?? null;\n const requestedCursor = useRef<string | null>(null);\n useEffect(() => {\n if (loading || !workspaceId || !hasNextPage || !endCursor) return;\n if (requestedCursor.current === endCursor) return;\n requestedCursor.current = endCursor;\n void fetchMore({\n variables: {\n context: { workspaceId },\n pagination: { first: 100, after: endCursor },\n },\n updateQuery: appendEntityPage,\n });\n }, [loading, workspaceId, hasNextPage, endCursor, fetchMore]);\n\n return {\n data: entities,\n totalCount: connection?.totalCount ?? 0,\n pageInfo: connection?.pageInfo ? mapPageInfo(connection.pageInfo) : null,\n loadMore,\n error: error ?? null,\n isLoading: loading,\n refetch,\n };\n}\n\n/**\n * Hook to fetch all export templates for the current workspace\n */\nexport function useExportTemplates(overrideWorkspaceId?: string) {\n const { workspaceId: ctxWorkspaceId } = useExport();\n const workspaceId = overrideWorkspaceId ?? ctxWorkspaceId;\n\n const { data, loading, error, refetch, fetchMore } = useQuery<\n ListExportTemplatesQuery,\n ListExportTemplatesQueryVariables\n >(ListExportTemplatesDocument, {\n variables: {\n context: { workspaceId },\n pagination: { first: 50 },\n },\n skip: !workspaceId,\n });\n\n const connection = data?.listExportTemplates;\n const templates =\n connection?.edges.map((edge) => mapTemplate(edge.node)) ?? [];\n\n const loadMore = async () => {\n if (!workspaceId || !connection?.pageInfo.hasNextPage) return;\n await fetchMore({\n variables: {\n context: { workspaceId },\n pagination: { first: 50, after: connection.pageInfo.endCursor },\n },\n updateQuery: (previous, { fetchMoreResult }) => {\n if (!fetchMoreResult) return previous;\n return {\n listExportTemplates: {\n ...fetchMoreResult.listExportTemplates,\n edges: [\n ...previous.listExportTemplates.edges,\n ...fetchMoreResult.listExportTemplates.edges,\n ],\n },\n };\n },\n });\n };\n\n return {\n data: templates,\n totalCount: connection?.totalCount ?? 0,\n pageInfo: connection?.pageInfo ? mapPageInfo(connection.pageInfo) : null,\n loadMore,\n isLoading: loading,\n error: error ?? null,\n refetch,\n };\n}\n\n/**\n * Hook to fetch a single export template by ID\n */\nexport function useExportTemplate(templateId: string | undefined) {\n const { workspaceId } = useExport();\n\n const { data, loading, error } = useQuery<\n GetExportTemplateQuery,\n GetExportTemplateQueryVariables\n >(GetExportTemplateDocument, {\n variables: { id: templateId ?? \"\", context: { workspaceId } },\n skip: !templateId || !workspaceId,\n });\n\n return {\n data: data?.getExportTemplate ? mapTemplate(data.getExportTemplate) : null,\n isLoading: loading,\n error: error ?? null,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Mutation Hooks\n// ---------------------------------------------------------------------------\n\n/**\n * Hook to create a new export job\n */\nexport function useCreateExportJob() {\n const exportContext = useExport();\n const { workspaceId } = exportContext;\n const [mutate, { loading, error }] = useMutation<\n CreateExportJobMutation,\n CreateExportJobMutationVariables\n >(CreateExportJobDocument);\n\n const createJob = async (input: CreateExportJobInput): Promise<ExportJob> => {\n const { filters, ...restInput } = input;\n const gqlInput: GqlCreateExportJobInput = {\n ...restInput,\n exportScope: restInput.exportScope\n ? toGqlScope(restInput.exportScope)\n : undefined,\n format: toGqlFormat(restInput.format),\n entityFilters: filters,\n };\n\n const result = await mutate({\n variables: {\n context: { workspaceId },\n input: gqlInput,\n },\n refetchQueries: [\n {\n query: ListExportJobsDocument,\n variables: { context: { workspaceId } },\n },\n ],\n });\n if (!result.data) {\n emitExportEvent(exportContext, \"export.api.failed\", {\n operation: \"createExportJob\",\n });\n throw new Error(\"Failed to create export job\");\n }\n emitExportEvent(exportContext, \"export.job.created\", {\n jobId: result.data.createExportJob.id,\n });\n return mapJob(result.data.createExportJob);\n };\n\n return {\n createJob,\n // Keep legacy names for existing callers\n mutate: createJob,\n mutateAsync: createJob,\n loading,\n isPending: loading,\n error: error ?? null,\n };\n}\n\n/**\n * Hook to cancel an export job\n */\nexport function useCancelExportJob() {\n const exportContext = useExport();\n const { workspaceId } = exportContext;\n const [mutate, { loading, error }] = useMutation<\n CancelExportJobMutation,\n CancelExportJobMutationVariables\n >(CancelExportJobDocument);\n\n const cancelJob = async (id: string) => {\n const result = await mutate({\n variables: {\n id,\n context: { workspaceId },\n },\n refetchQueries: [\n {\n query: ListExportJobsDocument,\n variables: { context: { workspaceId } },\n },\n ],\n });\n if (!result.data) {\n emitExportEvent(exportContext, \"export.api.failed\", {\n operation: \"cancelExportJob\",\n jobId: id,\n });\n throw new Error(\"Failed to cancel export job\");\n }\n emitExportEvent(exportContext, \"export.job.cancelled\", { jobId: id });\n return result.data.cancelExportJob;\n };\n\n return {\n cancelJob,\n mutate: cancelJob,\n mutateAsync: cancelJob,\n loading,\n isPending: loading,\n error: error ?? null,\n };\n}\n\n/**\n * Hook to delete an export job\n */\nexport function useDeleteExportJob() {\n const exportContext = useExport();\n const { workspaceId } = exportContext;\n const [mutate, { loading, error }] = useMutation<\n DeleteExportJobMutation,\n DeleteExportJobMutationVariables\n >(DeleteExportJobDocument);\n\n const deleteJob = async (id: string): Promise<boolean> => {\n await mutate({\n variables: {\n id,\n context: { workspaceId },\n },\n refetchQueries: [\n {\n query: ListExportJobsDocument,\n variables: { context: { workspaceId } },\n },\n ],\n });\n emitExportEvent(exportContext, \"export.job.deleted\", { jobId: id });\n return true;\n };\n\n return {\n deleteJob,\n mutate: deleteJob,\n mutateAsync: deleteJob,\n loading,\n isPending: loading,\n error: error ?? null,\n };\n}\n\n/**\n * Hook to retry a failed export job\n */\nexport function useRetryExportJob() {\n const exportContext = useExport();\n const { workspaceId } = exportContext;\n const [mutate, { loading, error }] = useMutation<\n RetryExportJobMutation,\n RetryExportJobMutationVariables\n >(RetryExportJobDocument);\n\n const retryJob = async (id: string): Promise<ExportJob> => {\n const result = await mutate({\n variables: { id, context: { workspaceId } },\n refetchQueries: [\n {\n query: ListExportJobsDocument,\n variables: { context: { workspaceId } },\n },\n ],\n });\n if (!result.data) {\n emitExportEvent(exportContext, \"export.api.failed\", {\n operation: \"retryExportJob\",\n jobId: id,\n });\n throw new Error(\"Failed to retry export job\");\n }\n emitExportEvent(exportContext, \"export.job.retried\", {\n originalJobId: id,\n jobId: result.data.retryExportJob.id,\n });\n return mapJob(result.data.retryExportJob);\n };\n\n return {\n retryJob,\n loading,\n isPending: loading,\n error: error ?? null,\n };\n}\n\n/**\n * Hook to create a new export template\n */\nexport function useCreateExportTemplate() {\n const exportContext = useExport();\n const { workspaceId } = exportContext;\n const [mutate, { loading, error }] = useMutation<\n CreateExportTemplateMutation,\n CreateExportTemplateMutationVariables\n >(CreateExportTemplateDocument);\n\n const createTemplate = async (\n input: CreateExportTemplateInput,\n ): Promise<ExportTemplate> => {\n const gqlInput: GqlCreateExportTemplateInput = {\n ...input,\n format: toGqlFormat(input.format),\n };\n\n const result = await mutate({\n variables: {\n context: { workspaceId },\n input: gqlInput,\n },\n refetchQueries: [\n {\n query: ListExportTemplatesDocument,\n variables: { context: { workspaceId } },\n },\n ],\n });\n if (!result.data) {\n emitExportEvent(exportContext, \"export.api.failed\", {\n operation: \"createExportTemplate\",\n });\n throw new Error(\"Failed to create export template\");\n }\n emitExportEvent(exportContext, \"export.template.created\", {\n templateId: result.data.createExportTemplate.id,\n });\n return mapTemplate(result.data.createExportTemplate);\n };\n\n return {\n createTemplate,\n loading,\n isPending: loading,\n error: error ?? null,\n };\n}\n\n/**\n * Hook to delete an export template\n */\nexport function useDeleteExportTemplate() {\n const exportContext = useExport();\n const { workspaceId } = exportContext;\n const [mutate, { loading, error }] = useMutation<\n DeleteExportTemplateMutation,\n DeleteExportTemplateMutationVariables\n >(DeleteExportTemplateDocument);\n\n const deleteTemplate = async (id: string): Promise<boolean> => {\n await mutate({\n variables: {\n id,\n context: { workspaceId },\n },\n refetchQueries: [\n {\n query: ListExportTemplatesDocument,\n variables: { context: { workspaceId } },\n },\n ],\n });\n emitExportEvent(exportContext, \"export.template.deleted\", {\n templateId: id,\n });\n return true;\n };\n\n return {\n deleteTemplate,\n loading,\n isPending: loading,\n error: error ?? null,\n };\n}\n"],"mappings":"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"}
@@ -273,7 +273,7 @@ function w() {
273
273
  type: "button",
274
274
  onClick: (t) => ne(t, e.id),
275
275
  className: "p-1.5 rounded-md text-text-secondary hover:text-status-error-text hover:bg-status-error-bg/10 transition-colors",
276
- "aria-label": E("export.templates.card.deleteAriaLabel", "Delete {name}", { name: e.name }),
276
+ "aria-label": E("export.templates.card.deleteAriaLabel", "Delete {{name}}", { name: e.name }),
277
277
  children: /* @__PURE__ */ v(_, { size: 14 })
278
278
  }), /* @__PURE__ */ v(te, {
279
279
  size: 18,
@@ -293,7 +293,7 @@ function w() {
293
293
  children: e
294
294
  }, e)), e.entityTypes.length > 6 && /* @__PURE__ */ v("span", {
295
295
  className: "inline-flex px-2 py-0.5 rounded text-xs font-medium bg-bg-sunken text-text-secondary",
296
- children: E("export.templates.card.moreEntities", "+{count} more", { count: e.entityTypes.length - 6 })
296
+ children: E("export.templates.card.moreEntities", "+{{count}} more", { count: e.entityTypes.length - 6 })
297
297
  })]
298
298
  })]
299
299
  })]
@@ -1 +1 @@
1
- {"version":3,"file":"ExportTemplatesPage.js","names":[],"sources":["../../../src/export/pages/ExportTemplatesPage.tsx"],"sourcesContent":["import { useState, useMemo } from \"react\";\nimport {\n Search,\n X,\n FileBox,\n Plus,\n ChevronRight,\n Sparkles,\n Loader2,\n} from \"lucide-react\";\nimport {\n CTAOverflowMenu,\n IllustratedEmptyState,\n PagePurpose,\n} from \"@burdenoff/fe-libs/ui\";\nimport { useExport } from \"../providers/ExportProvider\";\nimport {\n useExportTemplates,\n useDeleteExportTemplate,\n useCreateExportTemplate,\n useAvailableEntities,\n} from \"../hooks/useExportQueries\";\nimport { PageLayout } from \"../components/PageLayout\";\nimport { getFormatDisplayName } from \"../constants/enums\";\nimport { useTr } from \"../hooks/useTr\";\nimport { cn } from \"../utils/cn\";\nimport type { ExportFormat } from \"../types\";\nimport { nativeImpact, nativeNotify } from \"../../utils/nativeBridge\";\n\n/**\n * Helper to join paths correctly\n */\nconst joinPath = (base: string, path: string): string => {\n const cleanBase = base.endsWith(\"/\") ? base.slice(0, -1) : base;\n const cleanPath = path.startsWith(\"/\") ? path : `/${path}`;\n return cleanBase + cleanPath;\n};\n\n/**\n * Export Templates Page\n * Template management list for reusable export configurations\n */\nexport function ExportTemplatesPage() {\n const { basePath = \"/\", navigate } = useExport();\n const tr = useTr();\n const { data: templates, isLoading } = useExportTemplates();\n const { deleteTemplate } = useDeleteExportTemplate();\n const { createTemplate, isPending: creating } = useCreateExportTemplate();\n const { data: availableEntities } = useAvailableEntities();\n\n const [searchQuery, setSearchQuery] = useState(\"\");\n const [showCreateForm, setShowCreateForm] = useState(false);\n const [newTemplateName, setNewTemplateName] = useState(\"\");\n const [newTemplateDescription, setNewTemplateDescription] = useState(\"\");\n const [newTemplateEntityTypes, setNewTemplateEntityTypes] = useState<\n string[]\n >([]);\n const [newTemplateFormat, setNewTemplateFormat] =\n useState<ExportFormat>(\"CSV\");\n const [createError, setCreateError] = useState<string | null>(null);\n const [templatePendingDelete, setTemplatePendingDelete] = useState<\n string | null\n >(null);\n\n const handleOpenCreate = () => {\n setNewTemplateName(\"\");\n setNewTemplateDescription(\"\");\n setNewTemplateEntityTypes([]);\n setNewTemplateFormat(\"CSV\");\n setCreateError(null);\n setShowCreateForm(true);\n };\n\n const handleCreateTemplate = async () => {\n if (!newTemplateName.trim()) {\n setCreateError(\n tr(\n \"export.templates.form.errors.nameRequired\",\n \"Template name is required.\",\n ),\n );\n return;\n }\n if (newTemplateEntityTypes.length === 0) {\n setCreateError(\n tr(\n \"export.templates.form.errors.entityRequired\",\n \"Select at least one entity type.\",\n ),\n );\n return;\n }\n setCreateError(null);\n try {\n await createTemplate({\n name: newTemplateName.trim(),\n description: newTemplateDescription.trim() || undefined,\n entityTypes: newTemplateEntityTypes,\n format: newTemplateFormat,\n });\n setShowCreateForm(false);\n } catch (err) {\n setCreateError(\n err instanceof Error\n ? err.message\n : tr(\n \"export.templates.form.errors.createFailed\",\n \"Failed to create template.\",\n ),\n );\n }\n };\n\n const toggleEntity = (entityType: string) => {\n setNewTemplateEntityTypes((prev) =>\n prev.includes(entityType)\n ? prev.filter((e) => e !== entityType)\n : [...prev, entityType],\n );\n };\n\n // Client-side search filter\n const filteredTemplates = useMemo(() => {\n if (!searchQuery) return templates;\n const q = searchQuery.toLowerCase();\n return templates.filter(\n (t) =>\n t.name.toLowerCase().includes(q) ||\n t.entityTypes.some((e) => e.toLowerCase().includes(q)),\n );\n }, [templates, searchQuery]);\n\n const handleTemplateClick = (templateId: string) => {\n navigate?.(joinPath(basePath, `templates/${templateId}`));\n };\n\n const handleDeleteTemplate = async (\n e: React.MouseEvent,\n templateId: string,\n ) => {\n e.stopPropagation();\n nativeImpact(\"medium\");\n setTemplatePendingDelete(templateId);\n };\n\n const confirmDeleteTemplate = async () => {\n if (!templatePendingDelete) return;\n try {\n await deleteTemplate(templatePendingDelete);\n nativeNotify(\"success\");\n } catch {\n nativeNotify(\"error\");\n }\n setTemplatePendingDelete(null);\n };\n\n return (\n <PageLayout\n title={tr(\"export.templates.title\", \"Export Templates\")}\n subtitle={tr(\n \"export.templates.subtitle\",\n \"Reusable export configurations for common data exports\",\n )}\n icon={<FileBox size={24} />}\n headerActions={\n <CTAOverflowMenu\n primary={{\n label: tr(\"export.templates.actions.newTemplate\", \"New Template\"),\n icon: <Plus size={16} />,\n onSelect: handleOpenCreate,\n }}\n actions={[\n {\n label: tr(\"export.templates.actions.newExport\", \"New Export\"),\n icon: <Plus size={16} />,\n onSelect: () => navigate?.(joinPath(basePath, \"new\")),\n },\n ]}\n />\n }\n headerContent={\n <span className=\"inline-flex items-center gap-1.5 px-2.5 py-0.5 rounded-full text-xs font-medium bg-bg-sunken text-text-secondary\">\n <Sparkles size={12} />\n {tr(\n \"export.templates.summary.available\",\n \"{{count}} template{{suffix}} available\",\n {\n count: filteredTemplates.length,\n suffix: filteredTemplates.length !== 1 ? \"s\" : \"\",\n },\n )}\n </span>\n }\n >\n {/* Page purpose — why templates exist */}\n <PagePurpose icon={<FileBox size={16} />}>\n {tr(\n \"export.templates.purpose\",\n \"Templates save an export setup — the entity types and format you regularly need — so you don't rebuild it each time. Create one here, then start a new export from it in a single click. Handy for recurring backups, periodic audits, or any export you run more than once.\",\n )}\n </PagePurpose>\n\n {/* Create Template Form */}\n {showCreateForm && (\n <div className=\"border border-primary/30 rounded-xl p-6 bg-accent-wash space-y-4\">\n <div className=\"flex items-center justify-between\">\n <h3 className=\"font-semibold text-lg\">\n {tr(\"export.templates.form.title\", \"New Template\")}\n </h3>\n <button\n type=\"button\"\n onClick={() => setShowCreateForm(false)}\n className=\"p-1.5 rounded-md hover:bg-accent\"\n >\n <X size={16} />\n </button>\n </div>\n {createError && (\n <p className=\"text-sm text-status-error-text bg-status-error-bg/10 rounded-lg px-3 py-2\">\n {createError}\n </p>\n )}\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-4\">\n <div className=\"space-y-1\">\n <label className=\"text-sm font-medium\">\n {tr(\"export.templates.form.fields.name\", \"Name\")} *\n </label>\n <input\n type=\"text\"\n aria-label={tr(\"export.templates.form.fields.name\", \"Name\")}\n placeholder={tr(\n \"export.templates.form.fields.namePlaceholder\",\n \"e.g. Weekly Tags Export\",\n )}\n value={newTemplateName}\n onChange={(e) => setNewTemplateName(e.target.value)}\n className=\"w-full px-3 py-2 border-2 border-border-subtle rounded-lg bg-bg-surface focus:outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary transition-all\"\n />\n </div>\n <div className=\"space-y-1\">\n <label className=\"text-sm font-medium\">\n {tr(\"export.templates.form.fields.format\", \"Format\")} *\n </label>\n <select\n value={newTemplateFormat}\n onChange={(e) =>\n setNewTemplateFormat(e.target.value as ExportFormat)\n }\n className=\"w-full px-3 py-2 border-2 border-border-subtle rounded-lg bg-bg-surface focus:outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary transition-all scheme-normal dark:scheme-dark [&_option]:bg-bg-surface [&_option]:text-text-primary\"\n >\n <option value=\"CSV\">{tr(\"export.format.csv\", \"CSV\")}</option>\n <option value=\"JSON\">{tr(\"export.format.json\", \"JSON\")}</option>\n </select>\n </div>\n </div>\n <div className=\"space-y-1\">\n <label className=\"text-sm font-medium\">\n {tr(\"export.templates.form.fields.description\", \"Description\")}\n </label>\n <input\n type=\"text\"\n aria-label={tr(\n \"export.templates.form.fields.description\",\n \"Description\",\n )}\n placeholder={tr(\n \"export.templates.form.fields.descriptionPlaceholder\",\n \"Optional description\",\n )}\n value={newTemplateDescription}\n onChange={(e) => setNewTemplateDescription(e.target.value)}\n className=\"w-full px-3 py-2 border-2 border-border-subtle rounded-lg bg-bg-surface focus:outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary transition-all\"\n />\n </div>\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium\">\n {tr(\"export.templates.form.fields.entityTypes\", \"Entity Types\")} *{\" \"}\n <span className=\"text-text-secondary font-normal\">\n {tr(\n \"export.templates.form.fields.entityTypesHint\",\n \"(select at least one)\",\n )}\n </span>\n </label>\n <div className=\"flex flex-wrap gap-2\">\n {availableEntities.map((entity) => (\n <button\n key={entity.entityType}\n type=\"button\"\n onClick={() => toggleEntity(entity.entityType)}\n className={cn(\n \"px-3 py-1.5 rounded-lg text-sm font-medium border-2 transition-all\",\n newTemplateEntityTypes.includes(entity.entityType)\n ? \"border-primary bg-action-primary-bg/10 text-primary\"\n : \"border-border-subtle bg-bg-surface hover:border-primary/50\",\n )}\n >\n {entity.displayName}\n </button>\n ))}\n </div>\n </div>\n <div className=\"flex gap-3 pt-2\">\n <button\n type=\"button\"\n onClick={handleCreateTemplate}\n disabled={creating}\n className=\"inline-flex items-center gap-2 px-5 py-2.5 bg-action-primary-bg text-action-primary-text rounded-lg hover:bg-action-primary-bg/90 transition-colors font-medium disabled:opacity-50\"\n >\n {creating ? (\n <Loader2 size={16} className=\"animate-spin\" />\n ) : (\n <Plus size={16} />\n )}\n {tr(\"export.templates.form.actions.create\", \"Create Template\")}\n </button>\n <button\n type=\"button\"\n onClick={() => setShowCreateForm(false)}\n className=\"px-5 py-2.5 border-2 border-border-subtle rounded-lg hover:bg-accent transition-colors font-medium\"\n >\n {tr(\"export.templates.form.actions.cancel\", \"Cancel\")}\n </button>\n </div>\n </div>\n )}\n {/* Search */}\n <div className=\"relative group\">\n <Search\n size={18}\n className=\"absolute left-3 top-1/2 -translate-y-1/2 text-text-secondary group-focus-within:text-primary transition-colors\"\n />\n <input\n type=\"text\"\n aria-label={tr(\n \"export.templates.search.placeholder\",\n \"Search templates\",\n )}\n placeholder={tr(\n \"export.templates.search.placeholder\",\n \"Search templates...\",\n )}\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n className=\"w-full pl-[3.25rem] pr-4 py-2.5 border-2 border-border-subtle rounded-lg bg-bg-surface focus:outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary transition-all duration-200\"\n />\n {searchQuery && (\n <button\n type=\"button\"\n onClick={() => setSearchQuery(\"\")}\n className=\"absolute right-3 top-1/2 -translate-y-1/2 p-1 rounded-md text-text-secondary hover:text-text-primary hover:bg-accent\"\n >\n <X size={16} />\n </button>\n )}\n </div>\n\n {/* Loading */}\n {isLoading && (\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-4\">\n {[...Array(4)].map((_, i) => (\n <div key={i} className=\"border border-border-seam rounded-xl p-5\">\n <div className=\"h-5 w-40 bg-bg-sunken rounded mb-3 animate-vc-shimmer\" />\n <div className=\"h-3 w-full bg-bg-sunken rounded mb-2 animate-vc-shimmer\" />\n <div className=\"flex gap-2 mt-4\">\n <div className=\"h-5 w-16 bg-bg-sunken rounded-full animate-vc-shimmer\" />\n <div className=\"h-5 w-16 bg-bg-sunken rounded-full animate-vc-shimmer\" />\n </div>\n </div>\n ))}\n </div>\n )}\n\n {/* Templates Grid */}\n {!isLoading ? (\n filteredTemplates.length > 0 ? (\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-4\">\n {filteredTemplates.map((template, index) => (\n <div\n key={template.id}\n role=\"button\"\n tabIndex={0}\n onClick={() => handleTemplateClick(template.id)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n handleTemplateClick(template.id);\n }\n }}\n className={cn(\n \"text-left group cursor-pointer border border-border-seam rounded-xl overflow-hidden bg-bg-surface\",\n \"hover:border-primary/40 shadow-[var(--shadow-pop)] transition-colors duration-200\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40\",\n \"animate-in fade-in-0\",\n )}\n style={{ animationDelay: `${index * 50}ms` }}\n >\n {/* Header */}\n <div className=\"p-4 border-b bg-bg-sunken/30\">\n <div className=\"flex items-start justify-between\">\n <div className=\"flex items-center gap-3\">\n <div className=\"p-2 rounded-lg bg-action-primary-bg/10\">\n <FileBox size={20} className=\"text-primary\" />\n </div>\n <div>\n <h3 className=\"font-semibold\">{template.name}</h3>\n <p className=\"text-xs text-text-secondary\">\n {getFormatDisplayName(template.format)}\n {template.isDefault && (\n <span className=\"ml-1.5 inline-flex items-center px-1.5 py-0.5 rounded text-xs bg-action-primary-bg/10 text-primary font-medium\">\n {tr(\"export.templates.card.default\", \"Default\")}\n </span>\n )}\n </p>\n </div>\n </div>\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n onClick={(e) => handleDeleteTemplate(e, template.id)}\n className=\"p-1.5 rounded-md text-text-secondary hover:text-status-error-text hover:bg-status-error-bg/10 transition-colors\"\n aria-label={tr(\n \"export.templates.card.deleteAriaLabel\",\n \"Delete {name}\",\n { name: template.name },\n )}\n >\n <X size={14} />\n </button>\n <ChevronRight\n size={18}\n className=\"text-text-secondary group-hover:text-primary transition-colors mt-1\"\n />\n </div>\n </div>\n </div>\n\n {/* Body */}\n <div className=\"p-4\">\n {template.description && (\n <p className=\"text-sm text-text-secondary mb-3 line-clamp-2\">\n {template.description}\n </p>\n )}\n <div className=\"flex flex-wrap gap-1.5 overflow-hidden\">\n {template.entityTypes.slice(0, 6).map((entity) => (\n <span\n key={entity}\n className=\"inline-flex px-2 py-0.5 rounded text-xs font-medium bg-bg-sunken text-text-secondary max-w-full truncate\"\n >\n {entity}\n </span>\n ))}\n {template.entityTypes.length > 6 && (\n <span className=\"inline-flex px-2 py-0.5 rounded text-xs font-medium bg-bg-sunken text-text-secondary\">\n {tr(\n \"export.templates.card.moreEntities\",\n \"+{count} more\",\n {\n count: template.entityTypes.length - 6,\n },\n )}\n </span>\n )}\n </div>\n </div>\n </div>\n ))}\n </div>\n ) : (\n <IllustratedEmptyState\n illustration={searchQuery ? \"empty-search\" : \"empty-data\"}\n title={\n searchQuery\n ? tr(\n \"export.templates.empty.filtered.title\",\n \"No matching templates\",\n )\n : tr(\"export.templates.empty.title\", \"No templates yet\")\n }\n description={\n searchQuery\n ? tr(\n \"export.templates.empty.filtered.description\",\n \"Try adjusting your search to find what you are looking for.\",\n )\n : tr(\n \"export.templates.empty.description\",\n \"Create a template to save reusable export configurations.\",\n )\n }\n action={\n searchQuery ? (\n <button\n type=\"button\"\n onClick={() => setSearchQuery(\"\")}\n className=\"inline-flex items-center gap-2 px-4 py-2 border-2 border-border-subtle rounded-lg hover:bg-accent transition-colors font-medium\"\n >\n <X size={16} />\n {tr(\n \"export.templates.empty.filtered.actions.clear\",\n \"Clear Search\",\n )}\n </button>\n ) : (\n <button\n type=\"button\"\n onClick={handleOpenCreate}\n className=\"inline-flex items-center gap-2 px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-lg hover:bg-action-primary-bg/90 transition-colors font-medium\"\n >\n <Plus size={16} />\n {tr(\n \"export.templates.empty.actions.newTemplate\",\n \"New Template\",\n )}\n </button>\n )\n }\n />\n )\n ) : null}\n {templatePendingDelete && (\n <div\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"template-list-delete-title\"\n className=\"fixed inset-0 z-50 flex items-center justify-center bg-bg-surface/80 backdrop-blur-sm p-4\"\n >\n <div className=\"w-full max-w-md rounded-xl border-2 border-border-subtle bg-bg-surface p-6 shadow-xl\">\n <h2 id=\"template-list-delete-title\" className=\"text-lg font-bold\">\n {tr(\"export.templates.delete.title\", \"Delete template?\")}\n </h2>\n <p className=\"mt-2 text-sm text-text-secondary\">\n {tr(\n \"export.templates.delete.description\",\n \"This removes the saved export configuration. Existing export jobs are not deleted.\",\n )}\n </p>\n <div className=\"mt-6 flex flex-col-reverse sm:flex-row sm:justify-end gap-3\">\n <button\n type=\"button\"\n onClick={() => setTemplatePendingDelete(null)}\n className=\"px-4 py-2 rounded-lg border-2 border-border-subtle hover:bg-accent transition-colors font-medium\"\n >\n {tr(\"export.templates.delete.cancel\", \"Keep Template\")}\n </button>\n <button\n type=\"button\"\n onClick={confirmDeleteTemplate}\n className=\"px-4 py-2 rounded-lg bg-status-error-bg text-status-error-text hover:bg-status-error-bg/90 transition-colors font-medium\"\n >\n {tr(\"export.templates.delete.confirmAction\", \"Delete Template\")}\n </button>\n </div>\n </div>\n </div>\n )}\n </PageLayout>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ExportTemplatesPage.js","names":[],"sources":["../../../src/export/pages/ExportTemplatesPage.tsx"],"sourcesContent":["import { useState, useMemo } from \"react\";\nimport {\n Search,\n X,\n FileBox,\n Plus,\n ChevronRight,\n Sparkles,\n Loader2,\n} from \"lucide-react\";\nimport {\n CTAOverflowMenu,\n IllustratedEmptyState,\n PagePurpose,\n} from \"@burdenoff/fe-libs/ui\";\nimport { useExport } from \"../providers/ExportProvider\";\nimport {\n useExportTemplates,\n useDeleteExportTemplate,\n useCreateExportTemplate,\n useAvailableEntities,\n} from \"../hooks/useExportQueries\";\nimport { PageLayout } from \"../components/PageLayout\";\nimport { getFormatDisplayName } from \"../constants/enums\";\nimport { useTr } from \"../hooks/useTr\";\nimport { cn } from \"../utils/cn\";\nimport type { ExportFormat } from \"../types\";\nimport { nativeImpact, nativeNotify } from \"../../utils/nativeBridge\";\n\n/**\n * Helper to join paths correctly\n */\nconst joinPath = (base: string, path: string): string => {\n const cleanBase = base.endsWith(\"/\") ? base.slice(0, -1) : base;\n const cleanPath = path.startsWith(\"/\") ? path : `/${path}`;\n return cleanBase + cleanPath;\n};\n\n/**\n * Export Templates Page\n * Template management list for reusable export configurations\n */\nexport function ExportTemplatesPage() {\n const { basePath = \"/\", navigate } = useExport();\n const tr = useTr();\n const { data: templates, isLoading } = useExportTemplates();\n const { deleteTemplate } = useDeleteExportTemplate();\n const { createTemplate, isPending: creating } = useCreateExportTemplate();\n const { data: availableEntities } = useAvailableEntities();\n\n const [searchQuery, setSearchQuery] = useState(\"\");\n const [showCreateForm, setShowCreateForm] = useState(false);\n const [newTemplateName, setNewTemplateName] = useState(\"\");\n const [newTemplateDescription, setNewTemplateDescription] = useState(\"\");\n const [newTemplateEntityTypes, setNewTemplateEntityTypes] = useState<\n string[]\n >([]);\n const [newTemplateFormat, setNewTemplateFormat] =\n useState<ExportFormat>(\"CSV\");\n const [createError, setCreateError] = useState<string | null>(null);\n const [templatePendingDelete, setTemplatePendingDelete] = useState<\n string | null\n >(null);\n\n const handleOpenCreate = () => {\n setNewTemplateName(\"\");\n setNewTemplateDescription(\"\");\n setNewTemplateEntityTypes([]);\n setNewTemplateFormat(\"CSV\");\n setCreateError(null);\n setShowCreateForm(true);\n };\n\n const handleCreateTemplate = async () => {\n if (!newTemplateName.trim()) {\n setCreateError(\n tr(\n \"export.templates.form.errors.nameRequired\",\n \"Template name is required.\",\n ),\n );\n return;\n }\n if (newTemplateEntityTypes.length === 0) {\n setCreateError(\n tr(\n \"export.templates.form.errors.entityRequired\",\n \"Select at least one entity type.\",\n ),\n );\n return;\n }\n setCreateError(null);\n try {\n await createTemplate({\n name: newTemplateName.trim(),\n description: newTemplateDescription.trim() || undefined,\n entityTypes: newTemplateEntityTypes,\n format: newTemplateFormat,\n });\n setShowCreateForm(false);\n } catch (err) {\n setCreateError(\n err instanceof Error\n ? err.message\n : tr(\n \"export.templates.form.errors.createFailed\",\n \"Failed to create template.\",\n ),\n );\n }\n };\n\n const toggleEntity = (entityType: string) => {\n setNewTemplateEntityTypes((prev) =>\n prev.includes(entityType)\n ? prev.filter((e) => e !== entityType)\n : [...prev, entityType],\n );\n };\n\n // Client-side search filter\n const filteredTemplates = useMemo(() => {\n if (!searchQuery) return templates;\n const q = searchQuery.toLowerCase();\n return templates.filter(\n (t) =>\n t.name.toLowerCase().includes(q) ||\n t.entityTypes.some((e) => e.toLowerCase().includes(q)),\n );\n }, [templates, searchQuery]);\n\n const handleTemplateClick = (templateId: string) => {\n navigate?.(joinPath(basePath, `templates/${templateId}`));\n };\n\n const handleDeleteTemplate = async (\n e: React.MouseEvent,\n templateId: string,\n ) => {\n e.stopPropagation();\n nativeImpact(\"medium\");\n setTemplatePendingDelete(templateId);\n };\n\n const confirmDeleteTemplate = async () => {\n if (!templatePendingDelete) return;\n try {\n await deleteTemplate(templatePendingDelete);\n nativeNotify(\"success\");\n } catch {\n nativeNotify(\"error\");\n }\n setTemplatePendingDelete(null);\n };\n\n return (\n <PageLayout\n title={tr(\"export.templates.title\", \"Export Templates\")}\n subtitle={tr(\n \"export.templates.subtitle\",\n \"Reusable export configurations for common data exports\",\n )}\n icon={<FileBox size={24} />}\n headerActions={\n <CTAOverflowMenu\n primary={{\n label: tr(\"export.templates.actions.newTemplate\", \"New Template\"),\n icon: <Plus size={16} />,\n onSelect: handleOpenCreate,\n }}\n actions={[\n {\n label: tr(\"export.templates.actions.newExport\", \"New Export\"),\n icon: <Plus size={16} />,\n onSelect: () => navigate?.(joinPath(basePath, \"new\")),\n },\n ]}\n />\n }\n headerContent={\n <span className=\"inline-flex items-center gap-1.5 px-2.5 py-0.5 rounded-full text-xs font-medium bg-bg-sunken text-text-secondary\">\n <Sparkles size={12} />\n {tr(\n \"export.templates.summary.available\",\n \"{{count}} template{{suffix}} available\",\n {\n count: filteredTemplates.length,\n suffix: filteredTemplates.length !== 1 ? \"s\" : \"\",\n },\n )}\n </span>\n }\n >\n {/* Page purpose — why templates exist */}\n <PagePurpose icon={<FileBox size={16} />}>\n {tr(\n \"export.templates.purpose\",\n \"Templates save an export setup — the entity types and format you regularly need — so you don't rebuild it each time. Create one here, then start a new export from it in a single click. Handy for recurring backups, periodic audits, or any export you run more than once.\",\n )}\n </PagePurpose>\n\n {/* Create Template Form */}\n {showCreateForm && (\n <div className=\"border border-primary/30 rounded-xl p-6 bg-accent-wash space-y-4\">\n <div className=\"flex items-center justify-between\">\n <h3 className=\"font-semibold text-lg\">\n {tr(\"export.templates.form.title\", \"New Template\")}\n </h3>\n <button\n type=\"button\"\n onClick={() => setShowCreateForm(false)}\n className=\"p-1.5 rounded-md hover:bg-accent\"\n >\n <X size={16} />\n </button>\n </div>\n {createError && (\n <p className=\"text-sm text-status-error-text bg-status-error-bg/10 rounded-lg px-3 py-2\">\n {createError}\n </p>\n )}\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-4\">\n <div className=\"space-y-1\">\n <label className=\"text-sm font-medium\">\n {tr(\"export.templates.form.fields.name\", \"Name\")} *\n </label>\n <input\n type=\"text\"\n aria-label={tr(\"export.templates.form.fields.name\", \"Name\")}\n placeholder={tr(\n \"export.templates.form.fields.namePlaceholder\",\n \"e.g. Weekly Tags Export\",\n )}\n value={newTemplateName}\n onChange={(e) => setNewTemplateName(e.target.value)}\n className=\"w-full px-3 py-2 border-2 border-border-subtle rounded-lg bg-bg-surface focus:outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary transition-all\"\n />\n </div>\n <div className=\"space-y-1\">\n <label className=\"text-sm font-medium\">\n {tr(\"export.templates.form.fields.format\", \"Format\")} *\n </label>\n <select\n value={newTemplateFormat}\n onChange={(e) =>\n setNewTemplateFormat(e.target.value as ExportFormat)\n }\n className=\"w-full px-3 py-2 border-2 border-border-subtle rounded-lg bg-bg-surface focus:outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary transition-all scheme-normal dark:scheme-dark [&_option]:bg-bg-surface [&_option]:text-text-primary\"\n >\n <option value=\"CSV\">{tr(\"export.format.csv\", \"CSV\")}</option>\n <option value=\"JSON\">{tr(\"export.format.json\", \"JSON\")}</option>\n </select>\n </div>\n </div>\n <div className=\"space-y-1\">\n <label className=\"text-sm font-medium\">\n {tr(\"export.templates.form.fields.description\", \"Description\")}\n </label>\n <input\n type=\"text\"\n aria-label={tr(\n \"export.templates.form.fields.description\",\n \"Description\",\n )}\n placeholder={tr(\n \"export.templates.form.fields.descriptionPlaceholder\",\n \"Optional description\",\n )}\n value={newTemplateDescription}\n onChange={(e) => setNewTemplateDescription(e.target.value)}\n className=\"w-full px-3 py-2 border-2 border-border-subtle rounded-lg bg-bg-surface focus:outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary transition-all\"\n />\n </div>\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium\">\n {tr(\"export.templates.form.fields.entityTypes\", \"Entity Types\")} *{\" \"}\n <span className=\"text-text-secondary font-normal\">\n {tr(\n \"export.templates.form.fields.entityTypesHint\",\n \"(select at least one)\",\n )}\n </span>\n </label>\n <div className=\"flex flex-wrap gap-2\">\n {availableEntities.map((entity) => (\n <button\n key={entity.entityType}\n type=\"button\"\n onClick={() => toggleEntity(entity.entityType)}\n className={cn(\n \"px-3 py-1.5 rounded-lg text-sm font-medium border-2 transition-all\",\n newTemplateEntityTypes.includes(entity.entityType)\n ? \"border-primary bg-action-primary-bg/10 text-primary\"\n : \"border-border-subtle bg-bg-surface hover:border-primary/50\",\n )}\n >\n {entity.displayName}\n </button>\n ))}\n </div>\n </div>\n <div className=\"flex gap-3 pt-2\">\n <button\n type=\"button\"\n onClick={handleCreateTemplate}\n disabled={creating}\n className=\"inline-flex items-center gap-2 px-5 py-2.5 bg-action-primary-bg text-action-primary-text rounded-lg hover:bg-action-primary-bg/90 transition-colors font-medium disabled:opacity-50\"\n >\n {creating ? (\n <Loader2 size={16} className=\"animate-spin\" />\n ) : (\n <Plus size={16} />\n )}\n {tr(\"export.templates.form.actions.create\", \"Create Template\")}\n </button>\n <button\n type=\"button\"\n onClick={() => setShowCreateForm(false)}\n className=\"px-5 py-2.5 border-2 border-border-subtle rounded-lg hover:bg-accent transition-colors font-medium\"\n >\n {tr(\"export.templates.form.actions.cancel\", \"Cancel\")}\n </button>\n </div>\n </div>\n )}\n {/* Search */}\n <div className=\"relative group\">\n <Search\n size={18}\n className=\"absolute left-3 top-1/2 -translate-y-1/2 text-text-secondary group-focus-within:text-primary transition-colors\"\n />\n <input\n type=\"text\"\n aria-label={tr(\n \"export.templates.search.placeholder\",\n \"Search templates\",\n )}\n placeholder={tr(\n \"export.templates.search.placeholder\",\n \"Search templates...\",\n )}\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n className=\"w-full pl-[3.25rem] pr-4 py-2.5 border-2 border-border-subtle rounded-lg bg-bg-surface focus:outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary transition-all duration-200\"\n />\n {searchQuery && (\n <button\n type=\"button\"\n onClick={() => setSearchQuery(\"\")}\n className=\"absolute right-3 top-1/2 -translate-y-1/2 p-1 rounded-md text-text-secondary hover:text-text-primary hover:bg-accent\"\n >\n <X size={16} />\n </button>\n )}\n </div>\n\n {/* Loading */}\n {isLoading && (\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-4\">\n {[...Array(4)].map((_, i) => (\n <div key={i} className=\"border border-border-seam rounded-xl p-5\">\n <div className=\"h-5 w-40 bg-bg-sunken rounded mb-3 animate-vc-shimmer\" />\n <div className=\"h-3 w-full bg-bg-sunken rounded mb-2 animate-vc-shimmer\" />\n <div className=\"flex gap-2 mt-4\">\n <div className=\"h-5 w-16 bg-bg-sunken rounded-full animate-vc-shimmer\" />\n <div className=\"h-5 w-16 bg-bg-sunken rounded-full animate-vc-shimmer\" />\n </div>\n </div>\n ))}\n </div>\n )}\n\n {/* Templates Grid */}\n {!isLoading ? (\n filteredTemplates.length > 0 ? (\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-4\">\n {filteredTemplates.map((template, index) => (\n <div\n key={template.id}\n role=\"button\"\n tabIndex={0}\n onClick={() => handleTemplateClick(template.id)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n handleTemplateClick(template.id);\n }\n }}\n className={cn(\n \"text-left group cursor-pointer border border-border-seam rounded-xl overflow-hidden bg-bg-surface\",\n \"hover:border-primary/40 shadow-[var(--shadow-pop)] transition-colors duration-200\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40\",\n \"animate-in fade-in-0\",\n )}\n style={{ animationDelay: `${index * 50}ms` }}\n >\n {/* Header */}\n <div className=\"p-4 border-b bg-bg-sunken/30\">\n <div className=\"flex items-start justify-between\">\n <div className=\"flex items-center gap-3\">\n <div className=\"p-2 rounded-lg bg-action-primary-bg/10\">\n <FileBox size={20} className=\"text-primary\" />\n </div>\n <div>\n <h3 className=\"font-semibold\">{template.name}</h3>\n <p className=\"text-xs text-text-secondary\">\n {getFormatDisplayName(template.format)}\n {template.isDefault && (\n <span className=\"ml-1.5 inline-flex items-center px-1.5 py-0.5 rounded text-xs bg-action-primary-bg/10 text-primary font-medium\">\n {tr(\"export.templates.card.default\", \"Default\")}\n </span>\n )}\n </p>\n </div>\n </div>\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n onClick={(e) => handleDeleteTemplate(e, template.id)}\n className=\"p-1.5 rounded-md text-text-secondary hover:text-status-error-text hover:bg-status-error-bg/10 transition-colors\"\n aria-label={tr(\n \"export.templates.card.deleteAriaLabel\",\n \"Delete {{name}}\",\n { name: template.name },\n )}\n >\n <X size={14} />\n </button>\n <ChevronRight\n size={18}\n className=\"text-text-secondary group-hover:text-primary transition-colors mt-1\"\n />\n </div>\n </div>\n </div>\n\n {/* Body */}\n <div className=\"p-4\">\n {template.description && (\n <p className=\"text-sm text-text-secondary mb-3 line-clamp-2\">\n {template.description}\n </p>\n )}\n <div className=\"flex flex-wrap gap-1.5 overflow-hidden\">\n {template.entityTypes.slice(0, 6).map((entity) => (\n <span\n key={entity}\n className=\"inline-flex px-2 py-0.5 rounded text-xs font-medium bg-bg-sunken text-text-secondary max-w-full truncate\"\n >\n {entity}\n </span>\n ))}\n {template.entityTypes.length > 6 && (\n <span className=\"inline-flex px-2 py-0.5 rounded text-xs font-medium bg-bg-sunken text-text-secondary\">\n {tr(\n \"export.templates.card.moreEntities\",\n \"+{{count}} more\",\n {\n count: template.entityTypes.length - 6,\n },\n )}\n </span>\n )}\n </div>\n </div>\n </div>\n ))}\n </div>\n ) : (\n <IllustratedEmptyState\n illustration={searchQuery ? \"empty-search\" : \"empty-data\"}\n title={\n searchQuery\n ? tr(\n \"export.templates.empty.filtered.title\",\n \"No matching templates\",\n )\n : tr(\"export.templates.empty.title\", \"No templates yet\")\n }\n description={\n searchQuery\n ? tr(\n \"export.templates.empty.filtered.description\",\n \"Try adjusting your search to find what you are looking for.\",\n )\n : tr(\n \"export.templates.empty.description\",\n \"Create a template to save reusable export configurations.\",\n )\n }\n action={\n searchQuery ? (\n <button\n type=\"button\"\n onClick={() => setSearchQuery(\"\")}\n className=\"inline-flex items-center gap-2 px-4 py-2 border-2 border-border-subtle rounded-lg hover:bg-accent transition-colors font-medium\"\n >\n <X size={16} />\n {tr(\n \"export.templates.empty.filtered.actions.clear\",\n \"Clear Search\",\n )}\n </button>\n ) : (\n <button\n type=\"button\"\n onClick={handleOpenCreate}\n className=\"inline-flex items-center gap-2 px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-lg hover:bg-action-primary-bg/90 transition-colors font-medium\"\n >\n <Plus size={16} />\n {tr(\n \"export.templates.empty.actions.newTemplate\",\n \"New Template\",\n )}\n </button>\n )\n }\n />\n )\n ) : null}\n {templatePendingDelete && (\n <div\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"template-list-delete-title\"\n className=\"fixed inset-0 z-50 flex items-center justify-center bg-bg-surface/80 backdrop-blur-sm p-4\"\n >\n <div className=\"w-full max-w-md rounded-xl border-2 border-border-subtle bg-bg-surface p-6 shadow-xl\">\n <h2 id=\"template-list-delete-title\" className=\"text-lg font-bold\">\n {tr(\"export.templates.delete.title\", \"Delete template?\")}\n </h2>\n <p className=\"mt-2 text-sm text-text-secondary\">\n {tr(\n \"export.templates.delete.description\",\n \"This removes the saved export configuration. Existing export jobs are not deleted.\",\n )}\n </p>\n <div className=\"mt-6 flex flex-col-reverse sm:flex-row sm:justify-end gap-3\">\n <button\n type=\"button\"\n onClick={() => setTemplatePendingDelete(null)}\n className=\"px-4 py-2 rounded-lg border-2 border-border-subtle hover:bg-accent transition-colors font-medium\"\n >\n {tr(\"export.templates.delete.cancel\", \"Keep Template\")}\n </button>\n <button\n type=\"button\"\n onClick={confirmDeleteTemplate}\n className=\"px-4 py-2 rounded-lg bg-status-error-bg text-status-error-text hover:bg-status-error-bg/90 transition-colors font-medium\"\n >\n {tr(\"export.templates.delete.confirmAction\", \"Delete Template\")}\n </button>\n </div>\n </div>\n </div>\n )}\n </PageLayout>\n );\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/microfe-export",
3
- "version": "2026.1013.2",
3
+ "version": "2026.1023.1",
4
4
  "description": "Burdenoff Export Microfrontend - Data export management interface",
5
5
  "type": "module",
6
6
  "files": [