@burdenoff/microfe-export 2026.801.1 → 2026.830.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/dist/export/ExportRoot.d.ts.map +1 -1
  2. package/dist/export/ExportRoot.js +41 -36
  3. package/dist/export/ExportRoot.js.map +1 -1
  4. package/dist/export/ExportRoutes.d.ts.map +1 -1
  5. package/dist/export/ExportRoutes.js +75 -66
  6. package/dist/export/ExportRoutes.js.map +1 -1
  7. package/dist/export/components/ExportProgressBar.d.ts.map +1 -1
  8. package/dist/export/components/ExportProgressBar.js +19 -18
  9. package/dist/export/components/ExportProgressBar.js.map +1 -1
  10. package/dist/export/components/ExportStatusBadge.d.ts.map +1 -1
  11. package/dist/export/components/ExportStatusBadge.js +19 -20
  12. package/dist/export/components/ExportStatusBadge.js.map +1 -1
  13. package/dist/export/hooks/useTr.d.ts +19 -0
  14. package/dist/export/hooks/useTr.d.ts.map +1 -0
  15. package/dist/export/hooks/useTr.js +15 -0
  16. package/dist/export/hooks/useTr.js.map +1 -0
  17. package/dist/export/index.d.ts +1 -0
  18. package/dist/export/index.d.ts.map +1 -1
  19. package/dist/export/index.js +1 -0
  20. package/dist/export/pages/CreateExportPage.d.ts +4 -0
  21. package/dist/export/pages/CreateExportPage.d.ts.map +1 -1
  22. package/dist/export/pages/CreateExportPage.js +271 -283
  23. package/dist/export/pages/CreateExportPage.js.map +1 -1
  24. package/dist/export/pages/ExportDashboardPage.d.ts.map +1 -1
  25. package/dist/export/pages/ExportDashboardPage.js +71 -72
  26. package/dist/export/pages/ExportDashboardPage.js.map +1 -1
  27. package/dist/export/pages/ExportDetailPage.d.ts.map +1 -1
  28. package/dist/export/pages/ExportDetailPage.js +171 -173
  29. package/dist/export/pages/ExportDetailPage.js.map +1 -1
  30. package/dist/export/pages/ExportHistoryPage.d.ts.map +1 -1
  31. package/dist/export/pages/ExportHistoryPage.js +110 -111
  32. package/dist/export/pages/ExportHistoryPage.js.map +1 -1
  33. package/dist/export/pages/ExportLandingPage.d.ts.map +1 -1
  34. package/dist/export/pages/ExportLandingPage.js +28 -27
  35. package/dist/export/pages/ExportLandingPage.js.map +1 -1
  36. package/dist/export/pages/ExportTemplatesPage.d.ts.map +1 -1
  37. package/dist/export/pages/ExportTemplatesPage.js +115 -116
  38. package/dist/export/pages/ExportTemplatesPage.js.map +1 -1
  39. package/dist/export/pages/TemplateDetailPage.d.ts.map +1 -1
  40. package/dist/export/pages/TemplateDetailPage.js +122 -118
  41. package/dist/export/pages/TemplateDetailPage.js.map +1 -1
  42. package/dist/export/utils/i18n.d.ts +18 -2
  43. package/dist/export/utils/i18n.d.ts.map +1 -1
  44. package/dist/export/utils/i18n.js +2 -9
  45. package/dist/export/utils/i18n.js.map +1 -1
  46. package/dist/index.js +2 -1
  47. package/dist/translations/en.d.ts +454 -0
  48. package/dist/translations/en.d.ts.map +1 -0
  49. package/dist/translations/en.js +417 -0
  50. package/dist/translations/en.js.map +1 -0
  51. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"CreateExportPage.js","names":[],"sources":["../../../src/export/pages/CreateExportPage.tsx"],"sourcesContent":["import { useState, useEffect, useRef } from \"react\";\nimport { useSearchParams } from \"react-router\";\nimport { isQuotaExhaustedError } from \"@burdenoff/fe-libs/shared/utils\";\nimport {\n ArrowLeft,\n ArrowRight,\n Download,\n CheckCircle2,\n Loader2,\n FileSpreadsheet,\n FileJson,\n Package,\n CalendarRange,\n User,\n Users,\n Building2,\n Lock,\n} from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport { usePermission } from \"@burdenoff/fe-libs/shared/providers/shell\";\nimport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n EmphasisPanel,\n ShowMore,\n PagePurpose,\n IllustratedEmptyState,\n} from \"@burdenoff/fe-libs/ui\";\nimport { useExport } from \"../providers/ExportProvider\";\nimport {\n useCreateExportJob,\n useAvailableEntities,\n useExportTemplates,\n} from \"../hooks/useExportQueries\";\nimport { getFormatDisplayName } from \"../constants/enums\";\nimport { PageLayout } from \"../components/PageLayout\";\nimport { cn } from \"../utils/cn\";\nimport { isExportEntityDisabled } from \"../utils/disabledModules\";\nimport type {\n ExportAvailableEntity,\n ExportFormat,\n ExportScope,\n} from \"../types\";\nimport { tWithFallback } from \"../utils/i18n\";\n\ntype WizardStep = \"entities\" | \"options\" | \"review\";\n\n// Backend only supports CSV and JSON\nconst SUPPORTED_FORMATS: ExportFormat[] = [\"CSV\", \"JSON\"];\n\nconst FORMAT_ICONS: Record<ExportFormat, typeof FileJson> = {\n CSV: FileSpreadsheet,\n JSON: FileJson,\n};\n\n/**\n * Create Export Page\n * Multi-step form: select entities, configure options, review & start\n */\nconst SCOPE_OPTIONS: Array<{\n value: ExportScope;\n label: string;\n description: string;\n Icon: typeof User;\n}> = [\n {\n value: \"INDIVIDUAL\",\n label: \"My Data Only\",\n description: \"Export data you personally created across selected modules.\",\n Icon: User,\n },\n {\n value: \"WORKSPACE_ADMIN\",\n label: \"All Workspace Data\",\n description:\n \"Export all data in this workspace regardless of who created it. Requires workspace admin access.\",\n Icon: Users,\n },\n {\n value: \"ORG_ADMIN\",\n label: \"All Organization Data\",\n description:\n \"Export data from every workspace in your organization. Requires org-admin access.\",\n Icon: Building2,\n },\n];\n\nexport function CreateExportPage() {\n const { basePath = \"/\", navigate, organizationId } = useExport();\n const { t } = useI18n();\n const tr = (\n key: string,\n fallback: string,\n params?: Record<string, string | number>,\n ) => tWithFallback(t, key, fallback, params);\n const { createJob, isPending } = useCreateExportJob();\n const { data: availableEntities } = useAvailableEntities();\n const { data: templates } = useExportTemplates();\n const [searchParams] = useSearchParams();\n\n // RBAC: Check permissions for admin scopes\n const canExportWorkspaceAdmin = usePermission(\"export:workspace:admin\");\n const canExportOrgAdmin = usePermission(\"export:org:admin\");\n\n const [step, setStep] = useState<WizardStep>(\"entities\");\n const [selectedEntities, setSelectedEntities] = useState<string[]>([]);\n const [exportName, setExportName] = useState(\"\");\n const [selectedFormat, setSelectedFormat] = useState<ExportFormat>(\"CSV\");\n const [selectedScope, setSelectedScope] = useState<ExportScope>(\"INDIVIDUAL\");\n const [selectedTemplateId, setSelectedTemplateId] = useState<\n string | undefined\n >(searchParams.get(\"templateId\") ?? undefined);\n const [dateRangeStart, setDateRangeStart] = useState(\"\");\n const [dateRangeEnd, setDateRangeEnd] = useState(\"\");\n const [error, setError] = useState<string | null>(null);\n const [showQuotaDialog, setShowQuotaDialog] = useState(false);\n\n // Pre-populate form when arriving from \"Use Template\" — apply only once per templateId\n const appliedTemplateRef = useRef<string | null>(null);\n useEffect(() => {\n const paramTemplateId = searchParams.get(\"templateId\");\n if (!paramTemplateId || !templates?.length) return;\n if (appliedTemplateRef.current === paramTemplateId) return;\n const tpl = templates.find((t) => t.id === paramTemplateId);\n if (!tpl) return;\n appliedTemplateRef.current = paramTemplateId;\n setSelectedTemplateId(tpl.id);\n // Skip entity types whose product export is currently disabled.\n setSelectedEntities(\n (tpl.entityTypes ?? []).filter((et) => !isExportEntityDisabled(et)),\n );\n const normalizedFormat = tpl.format?.toUpperCase() as\n ExportFormat | undefined;\n if (normalizedFormat && SUPPORTED_FORMATS.includes(normalizedFormat)) {\n setSelectedFormat(normalizedFormat);\n }\n if (tpl.name) setExportName(tpl.name);\n }, [searchParams, templates]);\n\n const handleBack = () => {\n if (step === \"options\") setStep(\"entities\");\n else if (step === \"review\") setStep(\"options\");\n else navigate?.(basePath);\n };\n\n const handleNext = () => {\n if (step === \"entities\") {\n if (selectedEntities.length === 0) {\n setError(\n tr(\n \"export.create.errors.selectEntity\",\n \"Please select at least one entity type to export\",\n ),\n );\n return;\n }\n setError(null);\n setStep(\"options\");\n } else if (step === \"options\") {\n if (!exportName.trim()) {\n setError(\n tr(\n \"export.create.errors.exportNameRequired\",\n \"Please provide a name for this export\",\n ),\n );\n return;\n }\n setError(null);\n setStep(\"review\");\n }\n };\n\n const handleSubmit = async () => {\n try {\n setError(null);\n await createJob({\n name: exportName,\n entityTypes: selectedEntities,\n format: selectedFormat,\n exportScope: selectedScope,\n organizationId:\n selectedScope === \"ORG_ADMIN\" ? organizationId : undefined,\n templateId: selectedTemplateId,\n dateRangeStart: dateRangeStart\n ? new Date(dateRangeStart).toISOString()\n : null,\n dateRangeEnd: dateRangeEnd\n ? new Date(dateRangeEnd).toISOString()\n : null,\n });\n navigate?.(basePath);\n } catch (err) {\n if (isQuotaExhaustedError(err)) {\n setShowQuotaDialog(true);\n setError(\n tr(\n \"export.create.errors.quotaReached\",\n \"You have reached your export limit for this month.\",\n ),\n );\n return;\n }\n setError(\n err instanceof Error\n ? err.message\n : tr(\"export.create.errors.createFailed\", \"Failed to create export\"),\n );\n }\n };\n\n const toggleEntity = (entityType: string) => {\n // Disabled-product entities can't be selected.\n if (isExportEntityDisabled(entityType)) return;\n setSelectedEntities((prev) =>\n prev.includes(entityType)\n ? prev.filter((e) => e !== entityType)\n : [...prev, entityType],\n );\n };\n\n const getScopeLabel = (scope: ExportScope) => {\n switch (scope) {\n case \"INDIVIDUAL\":\n return tr(\"export.create.scope.individual.label\", \"My Data Only\");\n case \"WORKSPACE_ADMIN\":\n return tr(\n \"export.create.scope.workspaceAdmin.label\",\n \"All Workspace Data\",\n );\n case \"ORG_ADMIN\":\n return tr(\n \"export.create.scope.orgAdmin.label\",\n \"All Organization Data\",\n );\n default:\n return scope;\n }\n };\n\n const getScopeDescription = (scope: ExportScope) => {\n switch (scope) {\n case \"INDIVIDUAL\":\n return tr(\n \"export.create.scope.individual.description\",\n \"Export data you personally created across selected modules.\",\n );\n case \"WORKSPACE_ADMIN\":\n return tr(\n \"export.create.scope.workspaceAdmin.description\",\n \"Export all data in this workspace regardless of who created it. Requires workspace admin access.\",\n );\n case \"ORG_ADMIN\":\n return tr(\n \"export.create.scope.orgAdmin.description\",\n \"Export data from every workspace in your organization. Requires org-admin access.\",\n );\n default:\n return \"\";\n }\n };\n\n const fallbackEntityCopy: Record<\n string,\n { label: string; description: string }\n > = {\n users: {\n label: tr(\"export.create.entities.users.label\", \"Users\"),\n description: tr(\n \"export.create.entities.users.description\",\n \"Workspace members and profiles\",\n ),\n },\n projects: {\n label: tr(\"export.create.entities.projects.label\", \"Projects\"),\n description: tr(\n \"export.create.entities.projects.description\",\n \"Projects and their metadata\",\n ),\n },\n tasks: {\n label: tr(\"export.create.entities.tasks.label\", \"Tasks\"),\n description: tr(\n \"export.create.entities.tasks.description\",\n \"Task items and assignments\",\n ),\n },\n files: {\n label: tr(\"export.create.entities.files.label\", \"Files\"),\n description: tr(\n \"export.create.entities.files.description\",\n \"File metadata and references\",\n ),\n },\n conversations: {\n label: tr(\"export.create.entities.conversations.label\", \"Conversations\"),\n description: tr(\n \"export.create.entities.conversations.description\",\n \"Chat messages and threads\",\n ),\n },\n tags: {\n label: tr(\"export.create.entities.tags.label\", \"Tags\"),\n description: tr(\n \"export.create.entities.tags.description\",\n \"Tags and vocabularies\",\n ),\n },\n activity: {\n label: tr(\"export.create.entities.activity.label\", \"Activity Logs\"),\n description: tr(\n \"export.create.entities.activity.description\",\n \"Audit trail and activity history\",\n ),\n },\n calendar: {\n label: tr(\"export.create.entities.calendar.label\", \"Calendar Events\"),\n description: tr(\n \"export.create.entities.calendar.description\",\n \"Events and bookings\",\n ),\n },\n };\n\n // Entities the backend marks available, split so the ones a user can export\n // show first and disabled-product entities are listed (still visible) below.\n const visibleEntities = availableEntities.filter((e) => e.enabled !== false);\n const availableForExport = visibleEntities.filter(\n (e) => !isExportEntityDisabled(e.entityType),\n );\n const unavailableForExport = visibleEntities.filter((e) =>\n isExportEntityDisabled(e.entityType),\n );\n\n const renderEntityCard = (\n entity: ExportAvailableEntity,\n isDisabled: boolean,\n ) => {\n const isSelected =\n !isDisabled && selectedEntities.includes(entity.entityType);\n return (\n <button\n type=\"button\"\n key={entity.entityType}\n onClick={() => toggleEntity(entity.entityType)}\n disabled={isDisabled}\n aria-disabled={isDisabled}\n title={\n isDisabled\n ? tr(\n \"export.create.select.unavailableHint\",\n \"Export for this product isn't available yet\",\n )\n : undefined\n }\n className={cn(\n \"text-left border-2 rounded-xl p-4 transition-all duration-200\",\n isDisabled\n ? \"border-border-subtle/30 opacity-50 cursor-not-allowed\"\n : isSelected\n ? \"border-primary bg-action-primary-bg/5 shadow-md\"\n : \"border-border-subtle/50 hover:border-primary/30 hover:shadow-sm\",\n )}\n >\n <div className=\"flex items-center justify-between mb-2 gap-2\">\n <h3 className=\"font-semibold\">\n {fallbackEntityCopy[entity.entityType]?.label ?? entity.displayName}\n </h3>\n {isDisabled ? (\n <span className=\"shrink-0 text-xs font-medium px-2 py-0.5 rounded-full bg-bg-sunken text-text-secondary\">\n {tr(\"export.create.select.unavailable\", \"Unavailable\")}\n </span>\n ) : (\n isSelected && <CheckCircle2 size={18} className=\"text-primary\" />\n )}\n </div>\n <p className=\"text-sm text-text-secondary\">\n {fallbackEntityCopy[entity.entityType]?.description ??\n entity.description}\n </p>\n {entity.estimatedSize && (\n <p className=\"text-xs text-text-secondary mt-2\">\n ~{entity.estimatedSize}\n </p>\n )}\n </button>\n );\n };\n\n return (\n <PageLayout showHeader={false}>\n {/* Header */}\n <div className=\"relative overflow-hidden rounded-xl bg-accent-wash border border-border-seam p-6 shadow-[var(--shadow-pop)]\">\n <div className=\"relative z-10 flex items-center gap-4\">\n <button\n type=\"button\"\n onClick={() => navigate?.(basePath)}\n className=\"p-2.5 hover:bg-accent rounded-lg transition-colors duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40\"\n aria-label={tr(\n \"export.create.actions.backToDashboard\",\n \"Back to export dashboard\",\n )}\n >\n <ArrowLeft size={20} />\n </button>\n <div className=\"flex items-center gap-3\">\n <div className=\"p-2.5 rounded-lg bg-action-primary-bg/10 backdrop-blur-sm\">\n <Download size={24} className=\"text-primary\" />\n </div>\n <h1 className=\"text-2xl sm:text-3xl font-bold\">\n {tr(\"export.create.title\", \"New Export\")}\n </h1>\n </div>\n </div>\n </div>\n\n {/* Page purpose — explains the wizard's job in plain language */}\n <PagePurpose icon={<Download size={16} />}>\n {tr(\n \"export.create.purpose\",\n \"Build a one-off export in three steps: pick which data to include, choose a format and scope, then review and start it. The export runs in the background and produces a downloadable ZIP you can grab from History when it finishes.\",\n )}\n </PagePurpose>\n\n {/* Step Indicator */}\n <div className=\"flex items-center gap-2 justify-center flex-wrap\">\n {([\"entities\", \"options\", \"review\"] as WizardStep[]).map((s, i) => (\n <div key={s} className=\"flex items-center gap-2\">\n {i > 0 && <ArrowRight size={18} className=\"text-text-secondary\" />}\n <div\n className={cn(\n \"flex items-center gap-2 px-4 py-2.5 rounded-lg text-sm font-medium border-2 transition-all duration-200\",\n step === s\n ? \"bg-action-primary-bg text-action-primary-text border-primary shadow-[var(--shadow-pop)]\"\n : \"bg-bg-sunken/50 text-text-secondary border-border-seam\",\n )}\n >\n <div className=\"flex items-center justify-center size-6 rounded-full bg-bg-surface/20 font-bold\">\n {i + 1}\n </div>\n <span className=\"hidden sm:inline capitalize\">\n {s === \"entities\"\n ? tr(\"export.create.steps.entities\", \"Select Data\")\n : s === \"options\"\n ? tr(\"export.create.steps.options\", \"Options\")\n : tr(\"export.create.steps.review\", \"Review\")}\n </span>\n </div>\n </div>\n ))}\n </div>\n\n {/* Error */}\n {error && (\n <div className=\"border-2 border-border-default rounded-xl bg-status-error-bg-subtle p-4 text-status-error-text text-sm\">\n {error}\n </div>\n )}\n\n {/* Step 1: Select Entities */}\n {step === \"entities\" && (\n <div className=\"space-y-4\">\n <h2 className=\"text-lg font-bold\">\n {tr(\"export.create.select.title\", \"Select data to export\")}\n </h2>\n <p className=\"text-sm text-text-secondary\">\n {tr(\n \"export.create.select.description\",\n \"Choose which entity types to include in your export.\",\n )}\n </p>\n {visibleEntities.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title={tr(\n \"export.create.select.emptyTitle\",\n \"Nothing to export yet\",\n )}\n description={tr(\n \"export.create.select.empty\",\n \"No exportable entity types are configured for this workspace yet. Once your workspace has data in supported modules, they'll show up here to select.\",\n )}\n />\n ) : (\n <div className=\"space-y-6\">\n {availableForExport.length > 0 && (\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3\">\n {availableForExport.map((entity) =>\n renderEntityCard(entity, false),\n )}\n </div>\n )}\n {unavailableForExport.length > 0 && (\n <div className=\"space-y-3\">\n <div className=\"flex items-center gap-3\">\n <div className=\"h-px flex-1 bg-border/60\" />\n <span className=\"text-xs font-medium uppercase tracking-wide text-text-secondary\">\n {tr(\n \"export.create.select.unavailableSection\",\n \"Not available yet\",\n )}\n </span>\n <div className=\"h-px flex-1 bg-border/60\" />\n </div>\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3\">\n {unavailableForExport.map((entity) =>\n renderEntityCard(entity, true),\n )}\n </div>\n </div>\n )}\n </div>\n )}\n </div>\n )}\n\n {/* Step 2: Configure Options */}\n {step === \"options\" && (\n <div className=\"space-y-6\">\n <div className=\"border border-border-seam rounded-xl p-6 space-y-5 bg-bg-surface\">\n <h2 className=\"text-lg font-bold\">\n {tr(\"export.create.options.title\", \"Export Options\")}\n </h2>\n\n {/* Scope selection */}\n <div>\n <label className=\"block text-sm font-semibold mb-2\">\n {tr(\"export.create.options.scope\", \"Export Scope\")}\n </label>\n <div className=\"grid grid-cols-1 sm:grid-cols-3 gap-3\">\n {SCOPE_OPTIONS.map(({ value, Icon }) => {\n // RBAC: Disable admin scopes if user lacks permission\n const isDisabled =\n (value === \"WORKSPACE_ADMIN\" && !canExportWorkspaceAdmin) ||\n (value === \"ORG_ADMIN\" && !canExportOrgAdmin);\n\n return (\n <button\n key={value}\n type=\"button\"\n onClick={() => !isDisabled && setSelectedScope(value)}\n disabled={isDisabled}\n className={cn(\n \"text-left border-2 rounded-xl p-4 transition-all duration-200\",\n selectedScope === value\n ? \"border-primary bg-action-primary-bg/5 shadow-md\"\n : isDisabled\n ? \"border-border-subtle/30 opacity-50 cursor-not-allowed\"\n : \"border-border-subtle/50 hover:border-primary/30 hover:shadow-sm\",\n )}\n title={\n isDisabled\n ? value === \"WORKSPACE_ADMIN\"\n ? \"Workspace admin access required\"\n : \"Organization admin access required\"\n : undefined\n }\n >\n <div className=\"flex items-center justify-between mb-2\">\n <Icon\n size={18}\n className={\n selectedScope === value\n ? \"text-primary\"\n : isDisabled\n ? \"text-text-secondary/50\"\n : \"text-text-secondary\"\n }\n />\n {selectedScope === value && (\n <CheckCircle2 size={16} className=\"text-primary\" />\n )}\n {isDisabled && (\n <Lock size={14} className=\"text-text-secondary/50\" />\n )}\n </div>\n <p className=\"font-semibold text-sm\">\n {getScopeLabel(value)}\n </p>\n <p className=\"text-xs text-text-secondary mt-1\">\n {getScopeDescription(value)}\n </p>\n </button>\n );\n })}\n </div>\n </div>\n\n {/* Name */}\n <div>\n <label\n htmlFor=\"exportName\"\n className=\"block text-sm font-semibold mb-2\"\n >\n {tr(\"export.create.options.name\", \"Export Name\")}{\" \"}\n <span className=\"text-status-error-text\">*</span>\n </label>\n <input\n type=\"text\"\n id=\"exportName\"\n aria-label={tr(\"export.create.options.name\", \"Export Name\")}\n value={exportName}\n onChange={(e) => setExportName(e.target.value)}\n className=\"w-full px-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 placeholder={tr(\n \"export.create.options.namePlaceholder\",\n \"e.g., Monthly User Export\",\n )}\n />\n </div>\n\n {/* Format — only CSV and JSON are supported */}\n <div>\n <label className=\"block text-sm font-semibold mb-2\">\n {tr(\"export.create.options.outputFormat\", \"Output Format\")}\n </label>\n <div className=\"grid grid-cols-2 gap-3\">\n {SUPPORTED_FORMATS.map((format) => {\n const Icon = FORMAT_ICONS[format];\n return (\n <button\n type=\"button\"\n key={format}\n onClick={() => setSelectedFormat(format)}\n className={cn(\n \"flex items-center gap-3 border-2 rounded-lg p-3 transition-all duration-200\",\n selectedFormat === format\n ? \"border-primary bg-action-primary-bg/5\"\n : \"border-border-subtle/50 hover:border-primary/30\",\n )}\n >\n <Icon\n size={18}\n className={\n selectedFormat === format\n ? \"text-primary\"\n : \"text-text-secondary\"\n }\n />\n <span className=\"font-medium text-sm\">\n {getFormatDisplayName(format)}\n </span>\n </button>\n );\n })}\n </div>\n </div>\n\n {/* Archive format — only ZIP is supported */}\n <div>\n <label className=\"block text-sm font-semibold mb-2\">\n {tr(\"export.create.options.archiveFormat\", \"Archive Format\")}\n </label>\n <div className=\"flex gap-3\">\n <div\n className={cn(\n \"flex items-center gap-2 border-2 rounded-lg px-4 py-2 border-primary bg-action-primary-bg/5\",\n )}\n >\n <Package size={16} className=\"text-primary\" />\n <span className=\"font-medium text-sm\">ZIP</span>\n </div>\n </div>\n <p className=\"text-xs text-text-secondary mt-1.5\">\n {tr(\n \"export.create.options.archiveDescription\",\n \"Exports are packaged as ZIP archives.\",\n )}\n </p>\n </div>\n\n {/* Advanced / optional refinements — progressively disclosed */}\n <ShowMore\n collapsedHeight={0}\n label={tr(\n \"export.create.options.advancedToggle\",\n \"Date range & template\",\n )}\n >\n <div className=\"space-y-5 pt-1\">\n {/* Date range filter */}\n <div>\n <label className=\"block text-sm font-semibold mb-2\">\n <span className=\"inline-flex items-center gap-1.5\">\n <CalendarRange size={15} />\n {tr(\"export.create.options.dateRange\", \"Date Range\")}{\" \"}\n <span className=\"font-normal text-text-secondary\">\n {tr(\"export.create.shared.optional\", \"(optional)\")}\n </span>\n </span>\n </label>\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-3\">\n <div>\n <label\n htmlFor=\"dateFrom\"\n className=\"block text-xs text-text-secondary mb-1\"\n >\n {tr(\"export.create.options.dateFrom\", \"From\")}\n </label>\n <input\n type=\"date\"\n id=\"dateFrom\"\n aria-label={tr(\n \"export.create.options.dateFrom\",\n \"From\",\n )}\n value={dateRangeStart}\n onChange={(e) => setDateRangeStart(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 text-sm\"\n />\n </div>\n <div>\n <label\n htmlFor=\"dateTo\"\n className=\"block text-xs text-text-secondary mb-1\"\n >\n {tr(\"export.create.options.dateTo\", \"To\")}\n </label>\n <input\n type=\"date\"\n id=\"dateTo\"\n aria-label={tr(\"export.create.options.dateTo\", \"To\")}\n value={dateRangeEnd}\n min={dateRangeStart}\n onChange={(e) => setDateRangeEnd(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 text-sm\"\n />\n </div>\n </div>\n <p className=\"text-xs text-text-secondary mt-1.5\">\n {tr(\n \"export.create.options.dateRangeDescription\",\n \"Leave blank to export all data regardless of date.\",\n )}\n </p>\n </div>\n\n {/* Optional: Use a template */}\n <div>\n <label className=\"block text-sm font-semibold mb-2\">\n {tr(\n \"export.create.options.basedOnTemplate\",\n \"Based on Template\",\n )}{\" \"}\n <span className=\"font-normal text-text-secondary\">\n {tr(\"export.create.shared.optional\", \"(optional)\")}\n </span>\n </label>\n {templates.length > 0 ? (\n <select\n value={selectedTemplateId ?? \"\"}\n onChange={(e) =>\n setSelectedTemplateId(e.target.value || undefined)\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\"\n >\n <option value=\"\">\n {tr(\"export.create.options.noTemplate\", \"No template\")}\n </option>\n {templates.map((t) => (\n <option key={t.id} value={t.id}>\n {t.name}\n </option>\n ))}\n </select>\n ) : (\n <p className=\"text-sm text-text-secondary\">\n {tr(\n \"export.create.options.noTemplates\",\n \"No templates yet.\",\n )}{\" \"}\n <button\n type=\"button\"\n onClick={() => navigate?.(basePath + \"/templates\")}\n className=\"text-primary underline-offset-2 hover:underline\"\n >\n {tr(\n \"export.create.options.createTemplateLink\",\n \"Create one\",\n )}\n </button>{\" \"}\n {tr(\n \"export.create.options.reuseTemplateHint\",\n \"to reuse export configurations.\",\n )}\n </p>\n )}\n </div>\n </div>\n </ShowMore>\n </div>\n </div>\n )}\n\n {/* Step 3: Review */}\n {step === \"review\" && (\n <div className=\"space-y-6\">\n <EmphasisPanel className=\"p-6 space-y-4\">\n <h2 className=\"text-lg font-bold flex items-center gap-2\">\n <CheckCircle2 size={20} className=\"text-primary\" />\n {tr(\"export.create.review.title\", \"Review Export\")}\n </h2>\n <dl className=\"space-y-3 text-sm\">\n {[\n {\n label: tr(\"export.create.review.fields.name\", \"Name\"),\n value: exportName,\n },\n {\n label: tr(\"export.create.review.fields.scope\", \"Scope\"),\n value: getScopeLabel(selectedScope),\n },\n {\n label: tr(\n \"export.create.review.fields.entityTypes\",\n \"Entity Types\",\n ),\n value: selectedEntities.join(\", \"),\n },\n {\n label: tr(\"export.create.review.fields.format\", \"Format\"),\n value: getFormatDisplayName(selectedFormat),\n },\n {\n label: tr(\"export.create.review.fields.archive\", \"Archive\"),\n value: \"ZIP\",\n },\n ...(dateRangeStart || dateRangeEnd\n ? [\n {\n label: tr(\n \"export.create.review.fields.dateRange\",\n \"Date Range\",\n ),\n value: [\n dateRangeStart || \"—\",\n dateRangeEnd || \"—\",\n ].join(\" → \"),\n },\n ]\n : []),\n ...(selectedTemplateId\n ? [\n {\n label: tr(\n \"export.create.review.fields.template\",\n \"Template\",\n ),\n value:\n templates.find((t) => t.id === selectedTemplateId)\n ?.name ?? selectedTemplateId,\n },\n ]\n : []),\n ].map(({ label, value }) => (\n <div\n key={label}\n className=\"flex flex-col sm:flex-row sm:justify-between gap-1\"\n >\n <dt className=\"text-text-secondary\">{label}</dt>\n <dd className=\"font-semibold sm:text-right break-words\">\n {value}\n </dd>\n </div>\n ))}\n </dl>\n </EmphasisPanel>\n </div>\n )}\n\n {/* Actions */}\n <div className=\"flex flex-col sm:flex-row gap-3 pt-2\">\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"px-6 py-3 border-2 border-border-subtle/50 rounded-lg hover:bg-accent hover:border-primary/30 transition-all duration-200 font-medium\"\n >\n {step === \"entities\"\n ? tr(\"export.create.actions.cancel\", \"Cancel\")\n : tr(\"export.create.actions.back\", \"Back\")}\n </button>\n {step === \"review\" ? (\n <button\n type=\"button\"\n onClick={handleSubmit}\n disabled={isPending}\n className=\"flex-1 inline-flex items-center justify-center gap-2 px-6 py-3 bg-action-primary-bg text-action-primary-text rounded-lg hover:bg-action-primary-bg/90 transition-all duration-200 font-bold shadow-lg disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n {isPending ? (\n <Loader2 size={18} className=\"animate-spin\" />\n ) : (\n <Download size={18} />\n )}\n {tr(\"export.create.actions.startExport\", \"Start Export\")}\n </button>\n ) : (\n <button\n type=\"button\"\n onClick={handleNext}\n className=\"flex-1 inline-flex items-center justify-center gap-2 px-6 py-3 bg-action-primary-bg text-action-primary-text rounded-lg hover:bg-action-primary-bg/90 transition-all duration-200 font-bold shadow-lg\"\n >\n {tr(\"export.create.actions.next\", \"Next\")}\n <ArrowRight size={18} />\n </button>\n )}\n </div>\n\n <AlertDialog open={showQuotaDialog} onOpenChange={setShowQuotaDialog}>\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>\n {tr(\"export.create.quotaDialog.title\", \"Export Limit Reached\")}\n </AlertDialogTitle>\n <AlertDialogDescription>\n {tr(\n \"export.create.quotaDialog.description\",\n \"You have reached your export limit for this month.\",\n )}\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel>\n {tr(\"export.create.quotaDialog.dismiss\", \"Dismiss\")}\n </AlertDialogCancel>\n <AlertDialogAction\n onClick={() => window.location.assign(\"/billing\")}\n >\n {tr(\"export.create.quotaDialog.viewBilling\", \"View Billing\")}\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"CreateExportPage.js","names":[],"sources":["../../../src/export/pages/CreateExportPage.tsx"],"sourcesContent":["import { useState, useEffect, useRef } from \"react\";\nimport { useSearchParams } from \"react-router\";\nimport { isQuotaExhaustedError } from \"@burdenoff/fe-libs/shared/utils\";\nimport {\n ArrowLeft,\n ArrowRight,\n Download,\n CheckCircle2,\n Loader2,\n FileSpreadsheet,\n FileJson,\n Package,\n CalendarRange,\n User,\n Users,\n Building2,\n Lock,\n} from \"lucide-react\";\nimport { usePermission } from \"@burdenoff/fe-libs/shared/providers/shell\";\nimport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n EmphasisPanel,\n ShowMore,\n PagePurpose,\n IllustratedEmptyState,\n} from \"@burdenoff/fe-libs/ui\";\nimport { useExport } from \"../providers/ExportProvider\";\nimport {\n useCreateExportJob,\n useAvailableEntities,\n useExportTemplates,\n} from \"../hooks/useExportQueries\";\nimport { getFormatDisplayName } from \"../constants/enums\";\nimport { PageLayout } from \"../components/PageLayout\";\nimport { useTr } from \"../hooks/useTr\";\nimport { cn } from \"../utils/cn\";\nimport { isExportEntityDisabled } from \"../utils/disabledModules\";\nimport type {\n ExportAvailableEntity,\n ExportFormat,\n ExportScope,\n} from \"../types\";\n\ntype WizardStep = \"entities\" | \"options\" | \"review\";\n\n// Backend only supports CSV and JSON\nconst SUPPORTED_FORMATS: ExportFormat[] = [\"CSV\", \"JSON\"];\n\nconst FORMAT_ICONS: Record<ExportFormat, typeof FileJson> = {\n CSV: FileSpreadsheet,\n JSON: FileJson,\n};\n\nconst SCOPE_ICONS: Record<ExportScope, typeof User> = {\n INDIVIDUAL: User,\n WORKSPACE_ADMIN: Users,\n ORG_ADMIN: Building2,\n};\n\n/**\n * Create Export Page\n * Multi-step form: select entities, configure options, review & start\n */\n\nexport function CreateExportPage() {\n const { basePath = \"/\", navigate, organizationId } = useExport();\n const tr = useTr();\n const { createJob, isPending } = useCreateExportJob();\n const { data: availableEntities } = useAvailableEntities();\n const { data: templates } = useExportTemplates();\n const [searchParams] = useSearchParams();\n\n // RBAC: Check permissions for admin scopes\n const canExportWorkspaceAdmin = usePermission(\"export:workspace:admin\");\n const canExportOrgAdmin = usePermission(\"export:org:admin\");\n\n const [step, setStep] = useState<WizardStep>(\"entities\");\n const [selectedEntities, setSelectedEntities] = useState<string[]>([]);\n const [exportName, setExportName] = useState(\"\");\n const [selectedFormat, setSelectedFormat] = useState<ExportFormat>(\"CSV\");\n const [selectedScope, setSelectedScope] = useState<ExportScope>(\"INDIVIDUAL\");\n const [selectedTemplateId, setSelectedTemplateId] = useState<\n string | undefined\n >(searchParams.get(\"templateId\") ?? undefined);\n const [dateRangeStart, setDateRangeStart] = useState(\"\");\n const [dateRangeEnd, setDateRangeEnd] = useState(\"\");\n const [error, setError] = useState<string | null>(null);\n const [showQuotaDialog, setShowQuotaDialog] = useState(false);\n\n // Pre-populate form when arriving from \"Use Template\" — apply only once per templateId\n const appliedTemplateRef = useRef<string | null>(null);\n useEffect(() => {\n const paramTemplateId = searchParams.get(\"templateId\");\n if (!paramTemplateId || !templates?.length) return;\n if (appliedTemplateRef.current === paramTemplateId) return;\n const tpl = templates.find((t) => t.id === paramTemplateId);\n if (!tpl) return;\n appliedTemplateRef.current = paramTemplateId;\n setSelectedTemplateId(tpl.id);\n // Skip entity types whose product export is currently disabled.\n setSelectedEntities(\n (tpl.entityTypes ?? []).filter((et) => !isExportEntityDisabled(et)),\n );\n const normalizedFormat = tpl.format?.toUpperCase() as\n ExportFormat | undefined;\n if (normalizedFormat && SUPPORTED_FORMATS.includes(normalizedFormat)) {\n setSelectedFormat(normalizedFormat);\n }\n if (tpl.name) setExportName(tpl.name);\n }, [searchParams, templates]);\n\n const handleBack = () => {\n if (step === \"options\") setStep(\"entities\");\n else if (step === \"review\") setStep(\"options\");\n else navigate?.(basePath);\n };\n\n const handleNext = () => {\n if (step === \"entities\") {\n if (selectedEntities.length === 0) {\n setError(\n tr(\n \"export.create.errors.selectEntity\",\n \"Please select at least one entity type to export\",\n ),\n );\n return;\n }\n setError(null);\n setStep(\"options\");\n } else if (step === \"options\") {\n if (!exportName.trim()) {\n setError(\n tr(\n \"export.create.errors.exportNameRequired\",\n \"Please provide a name for this export\",\n ),\n );\n return;\n }\n setError(null);\n setStep(\"review\");\n }\n };\n\n const handleSubmit = async () => {\n try {\n setError(null);\n await createJob({\n name: exportName,\n entityTypes: selectedEntities,\n format: selectedFormat,\n exportScope: selectedScope,\n organizationId:\n selectedScope === \"ORG_ADMIN\" ? organizationId : undefined,\n templateId: selectedTemplateId,\n dateRangeStart: dateRangeStart\n ? new Date(dateRangeStart).toISOString()\n : null,\n dateRangeEnd: dateRangeEnd\n ? new Date(dateRangeEnd).toISOString()\n : null,\n });\n navigate?.(basePath);\n } catch (err) {\n if (isQuotaExhaustedError(err)) {\n setShowQuotaDialog(true);\n setError(\n tr(\n \"export.create.errors.quotaReached\",\n \"You have reached your export limit for this month.\",\n ),\n );\n return;\n }\n setError(\n err instanceof Error\n ? err.message\n : tr(\"export.create.errors.createFailed\", \"Failed to create export\"),\n );\n }\n };\n\n const toggleEntity = (entityType: string) => {\n // Disabled-product entities can't be selected.\n if (isExportEntityDisabled(entityType)) return;\n setSelectedEntities((prev) =>\n prev.includes(entityType)\n ? prev.filter((e) => e !== entityType)\n : [...prev, entityType],\n );\n };\n\n const getScopeLabel = (scope: ExportScope) => {\n switch (scope) {\n case \"INDIVIDUAL\":\n return tr(\"export.create.scope.individual.label\", \"My Data Only\");\n case \"WORKSPACE_ADMIN\":\n return tr(\n \"export.create.scope.workspaceAdmin.label\",\n \"All Workspace Data\",\n );\n case \"ORG_ADMIN\":\n return tr(\n \"export.create.scope.orgAdmin.label\",\n \"All Organization Data\",\n );\n default:\n return scope;\n }\n };\n\n const getScopeDescription = (scope: ExportScope) => {\n switch (scope) {\n case \"INDIVIDUAL\":\n return tr(\n \"export.create.scope.individual.description\",\n \"Export data you personally created across selected modules.\",\n );\n case \"WORKSPACE_ADMIN\":\n return tr(\n \"export.create.scope.workspaceAdmin.description\",\n \"Export all data in this workspace regardless of who created it. Requires workspace admin access.\",\n );\n case \"ORG_ADMIN\":\n return tr(\n \"export.create.scope.orgAdmin.description\",\n \"Export data from every workspace in your organization. Requires org-admin access.\",\n );\n default:\n return \"\";\n }\n };\n\n const fallbackEntityCopy: Record<\n string,\n { label: string; description: string }\n > = {\n users: {\n label: tr(\"export.create.entities.users.label\", \"Users\"),\n description: tr(\n \"export.create.entities.users.description\",\n \"Workspace members and profiles\",\n ),\n },\n projects: {\n label: tr(\"export.create.entities.projects.label\", \"Projects\"),\n description: tr(\n \"export.create.entities.projects.description\",\n \"Projects and their metadata\",\n ),\n },\n tasks: {\n label: tr(\"export.create.entities.tasks.label\", \"Tasks\"),\n description: tr(\n \"export.create.entities.tasks.description\",\n \"Task items and assignments\",\n ),\n },\n files: {\n label: tr(\"export.create.entities.files.label\", \"Files\"),\n description: tr(\n \"export.create.entities.files.description\",\n \"File metadata and references\",\n ),\n },\n conversations: {\n label: tr(\"export.create.entities.conversations.label\", \"Conversations\"),\n description: tr(\n \"export.create.entities.conversations.description\",\n \"Chat messages and threads\",\n ),\n },\n tags: {\n label: tr(\"export.create.entities.tags.label\", \"Tags\"),\n description: tr(\n \"export.create.entities.tags.description\",\n \"Tags and vocabularies\",\n ),\n },\n activity: {\n label: tr(\"export.create.entities.activity.label\", \"Activity Logs\"),\n description: tr(\n \"export.create.entities.activity.description\",\n \"Audit trail and activity history\",\n ),\n },\n calendar: {\n label: tr(\"export.create.entities.calendar.label\", \"Calendar Events\"),\n description: tr(\n \"export.create.entities.calendar.description\",\n \"Events and bookings\",\n ),\n },\n };\n\n // Entities the backend marks available, split so the ones a user can export\n // show first and disabled-product entities are listed (still visible) below.\n const visibleEntities = availableEntities.filter((e) => e.enabled !== false);\n const availableForExport = visibleEntities.filter(\n (e) => !isExportEntityDisabled(e.entityType),\n );\n const unavailableForExport = visibleEntities.filter((e) =>\n isExportEntityDisabled(e.entityType),\n );\n\n const renderEntityCard = (\n entity: ExportAvailableEntity,\n isDisabled: boolean,\n ) => {\n const isSelected =\n !isDisabled && selectedEntities.includes(entity.entityType);\n return (\n <button\n type=\"button\"\n key={entity.entityType}\n onClick={() => toggleEntity(entity.entityType)}\n disabled={isDisabled}\n aria-disabled={isDisabled}\n title={\n isDisabled\n ? tr(\n \"export.create.select.unavailableHint\",\n \"Export for this product isn't available yet\",\n )\n : undefined\n }\n className={cn(\n \"text-left border-2 rounded-xl p-4 transition-all duration-200\",\n isDisabled\n ? \"border-border-subtle/30 opacity-50 cursor-not-allowed\"\n : isSelected\n ? \"border-primary bg-action-primary-bg/5 shadow-md\"\n : \"border-border-subtle/50 hover:border-primary/30 hover:shadow-sm\",\n )}\n >\n <div className=\"flex items-center justify-between mb-2 gap-2\">\n <h3 className=\"font-semibold\">\n {fallbackEntityCopy[entity.entityType]?.label ?? entity.displayName}\n </h3>\n {isDisabled ? (\n <span className=\"shrink-0 text-xs font-medium px-2 py-0.5 rounded-full bg-bg-sunken text-text-secondary\">\n {tr(\"export.create.select.unavailable\", \"Unavailable\")}\n </span>\n ) : (\n isSelected && <CheckCircle2 size={18} className=\"text-primary\" />\n )}\n </div>\n <p className=\"text-sm text-text-secondary\">\n {fallbackEntityCopy[entity.entityType]?.description ??\n entity.description}\n </p>\n {entity.estimatedSize && (\n <p className=\"text-xs text-text-secondary mt-2\">\n ~{entity.estimatedSize}\n </p>\n )}\n </button>\n );\n };\n\n return (\n <PageLayout showHeader={false}>\n {/* Header */}\n <div className=\"relative overflow-hidden rounded-xl bg-accent-wash border border-border-seam p-6 shadow-[var(--shadow-pop)]\">\n <div className=\"relative z-10 flex items-center gap-4\">\n <button\n type=\"button\"\n onClick={() => navigate?.(basePath)}\n className=\"p-2.5 hover:bg-accent rounded-lg transition-colors duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40\"\n aria-label={tr(\n \"export.create.actions.backToDashboard\",\n \"Back to export dashboard\",\n )}\n >\n <ArrowLeft size={20} />\n </button>\n <div className=\"flex items-center gap-3\">\n <div className=\"p-2.5 rounded-lg bg-action-primary-bg/10 backdrop-blur-sm\">\n <Download size={24} className=\"text-primary\" />\n </div>\n <h1 className=\"text-2xl sm:text-3xl font-bold\">\n {tr(\"export.create.title\", \"New Export\")}\n </h1>\n </div>\n </div>\n </div>\n\n {/* Page purpose — explains the wizard's job in plain language */}\n <PagePurpose icon={<Download size={16} />}>\n {tr(\n \"export.create.purpose\",\n \"Build a one-off export in three steps: pick which data to include, choose a format and scope, then review and start it. The export runs in the background and produces a downloadable ZIP you can grab from History when it finishes.\",\n )}\n </PagePurpose>\n\n {/* Step Indicator */}\n <div className=\"flex items-center gap-2 justify-center flex-wrap\">\n {([\"entities\", \"options\", \"review\"] as WizardStep[]).map((s, i) => (\n <div key={s} className=\"flex items-center gap-2\">\n {i > 0 && <ArrowRight size={18} className=\"text-text-secondary\" />}\n <div\n className={cn(\n \"flex items-center gap-2 px-4 py-2.5 rounded-lg text-sm font-medium border-2 transition-all duration-200\",\n step === s\n ? \"bg-action-primary-bg text-action-primary-text border-primary shadow-[var(--shadow-pop)]\"\n : \"bg-bg-sunken/50 text-text-secondary border-border-seam\",\n )}\n >\n <div className=\"flex items-center justify-center size-6 rounded-full bg-bg-surface/20 font-bold\">\n {i + 1}\n </div>\n <span className=\"hidden sm:inline capitalize\">\n {s === \"entities\"\n ? tr(\"export.create.steps.entities\", \"Select Data\")\n : s === \"options\"\n ? tr(\"export.create.steps.options\", \"Options\")\n : tr(\"export.create.steps.review\", \"Review\")}\n </span>\n </div>\n </div>\n ))}\n </div>\n\n {/* Error */}\n {error && (\n <div className=\"border-2 border-border-default rounded-xl bg-status-error-bg-subtle p-4 text-status-error-text text-sm\">\n {error}\n </div>\n )}\n\n {/* Step 1: Select Entities */}\n {step === \"entities\" && (\n <div className=\"space-y-4\">\n <h2 className=\"text-lg font-bold\">\n {tr(\"export.create.select.title\", \"Select data to export\")}\n </h2>\n <p className=\"text-sm text-text-secondary\">\n {tr(\n \"export.create.select.description\",\n \"Choose which entity types to include in your export.\",\n )}\n </p>\n {visibleEntities.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title={tr(\n \"export.create.select.emptyTitle\",\n \"Nothing to export yet\",\n )}\n description={tr(\n \"export.create.select.empty\",\n \"No exportable entity types are configured for this workspace yet. Once your workspace has data in supported modules, they'll show up here to select.\",\n )}\n />\n ) : (\n <div className=\"space-y-6\">\n {availableForExport.length > 0 && (\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3\">\n {availableForExport.map((entity) =>\n renderEntityCard(entity, false),\n )}\n </div>\n )}\n {unavailableForExport.length > 0 && (\n <div className=\"space-y-3\">\n <div className=\"flex items-center gap-3\">\n <div className=\"h-px flex-1 bg-border/60\" />\n <span className=\"text-xs font-medium uppercase tracking-wide text-text-secondary\">\n {tr(\n \"export.create.select.unavailableSection\",\n \"Not available yet\",\n )}\n </span>\n <div className=\"h-px flex-1 bg-border/60\" />\n </div>\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3\">\n {unavailableForExport.map((entity) =>\n renderEntityCard(entity, true),\n )}\n </div>\n </div>\n )}\n </div>\n )}\n </div>\n )}\n\n {/* Step 2: Configure Options */}\n {step === \"options\" && (\n <div className=\"space-y-6\">\n <div className=\"border border-border-seam rounded-xl p-6 space-y-5 bg-bg-surface\">\n <h2 className=\"text-lg font-bold\">\n {tr(\"export.create.options.title\", \"Export Options\")}\n </h2>\n\n {/* Scope selection */}\n <div>\n <label className=\"block text-sm font-semibold mb-2\">\n {tr(\"export.create.options.scope\", \"Export Scope\")}\n </label>\n <div className=\"grid grid-cols-1 sm:grid-cols-3 gap-3\">\n {(\n [\n \"INDIVIDUAL\",\n \"WORKSPACE_ADMIN\",\n \"ORG_ADMIN\",\n ] as ExportScope[]\n ).map((value) => {\n // RBAC: Disable admin scopes if user lacks permission\n const isDisabled =\n (value === \"WORKSPACE_ADMIN\" && !canExportWorkspaceAdmin) ||\n (value === \"ORG_ADMIN\" && !canExportOrgAdmin);\n const Icon = SCOPE_ICONS[value];\n const disabledTitle =\n value === \"WORKSPACE_ADMIN\"\n ? tr(\n \"export.create.scope.workspaceAdmin.required\",\n \"Workspace admin access required\",\n )\n : tr(\n \"export.create.scope.orgAdmin.required\",\n \"Organization admin access required\",\n );\n\n return (\n <button\n key={value}\n type=\"button\"\n onClick={() => !isDisabled && setSelectedScope(value)}\n disabled={isDisabled}\n className={cn(\n \"text-left border-2 rounded-xl p-4 transition-all duration-200\",\n selectedScope === value\n ? \"border-primary bg-action-primary-bg/5 shadow-md\"\n : isDisabled\n ? \"border-border-subtle/30 opacity-50 cursor-not-allowed\"\n : \"border-border-subtle/50 hover:border-primary/30 hover:shadow-sm\",\n )}\n title={isDisabled ? disabledTitle : undefined}\n >\n <div className=\"flex items-center justify-between mb-2\">\n <Icon\n size={18}\n className={\n selectedScope === value\n ? \"text-primary\"\n : isDisabled\n ? \"text-text-secondary/50\"\n : \"text-text-secondary\"\n }\n />\n {selectedScope === value && (\n <CheckCircle2 size={16} className=\"text-primary\" />\n )}\n {isDisabled && (\n <Lock size={14} className=\"text-text-secondary/50\" />\n )}\n </div>\n <p className=\"font-semibold text-sm\">\n {getScopeLabel(value)}\n </p>\n <p className=\"text-xs text-text-secondary mt-1\">\n {getScopeDescription(value)}\n </p>\n </button>\n );\n })}\n </div>\n </div>\n\n {/* Name */}\n <div>\n <label\n htmlFor=\"exportName\"\n className=\"block text-sm font-semibold mb-2\"\n >\n {tr(\"export.create.options.name\", \"Export Name\")}{\" \"}\n <span className=\"text-status-error-text\">*</span>\n </label>\n <input\n type=\"text\"\n id=\"exportName\"\n aria-label={tr(\"export.create.options.name\", \"Export Name\")}\n value={exportName}\n onChange={(e) => setExportName(e.target.value)}\n className=\"w-full px-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 placeholder={tr(\n \"export.create.options.namePlaceholder\",\n \"e.g., Monthly User Export\",\n )}\n />\n </div>\n\n {/* Format — only CSV and JSON are supported */}\n <div>\n <label className=\"block text-sm font-semibold mb-2\">\n {tr(\"export.create.options.outputFormat\", \"Output Format\")}\n </label>\n <div className=\"grid grid-cols-2 gap-3\">\n {SUPPORTED_FORMATS.map((format) => {\n const Icon = FORMAT_ICONS[format];\n return (\n <button\n type=\"button\"\n key={format}\n onClick={() => setSelectedFormat(format)}\n className={cn(\n \"flex items-center gap-3 border-2 rounded-lg p-3 transition-all duration-200\",\n selectedFormat === format\n ? \"border-primary bg-action-primary-bg/5\"\n : \"border-border-subtle/50 hover:border-primary/30\",\n )}\n >\n <Icon\n size={18}\n className={\n selectedFormat === format\n ? \"text-primary\"\n : \"text-text-secondary\"\n }\n />\n <span className=\"font-medium text-sm\">\n {getFormatDisplayName(format)}\n </span>\n </button>\n );\n })}\n </div>\n </div>\n\n {/* Archive format — only ZIP is supported */}\n <div>\n <label className=\"block text-sm font-semibold mb-2\">\n {tr(\"export.create.options.archiveFormat\", \"Archive Format\")}\n </label>\n <div className=\"flex gap-3\">\n <div\n className={cn(\n \"flex items-center gap-2 border-2 rounded-lg px-4 py-2 border-primary bg-action-primary-bg/5\",\n )}\n >\n <Package size={16} className=\"text-primary\" />\n <span className=\"font-medium text-sm\">\n {tr(\"export.archive.zip\", \"ZIP\")}\n </span>\n </div>\n </div>\n <p className=\"text-xs text-text-secondary mt-1.5\">\n {tr(\n \"export.create.options.archiveDescription\",\n \"Exports are packaged as ZIP archives.\",\n )}\n </p>\n </div>\n\n {/* Advanced / optional refinements — progressively disclosed */}\n <ShowMore\n collapsedHeight={0}\n label={tr(\n \"export.create.options.advancedToggle\",\n \"Date range & template\",\n )}\n >\n <div className=\"space-y-5 pt-1\">\n {/* Date range filter */}\n <div>\n <label className=\"block text-sm font-semibold mb-2\">\n <span className=\"inline-flex items-center gap-1.5\">\n <CalendarRange size={15} />\n {tr(\"export.create.options.dateRange\", \"Date Range\")}{\" \"}\n <span className=\"font-normal text-text-secondary\">\n {tr(\"export.create.shared.optional\", \"(optional)\")}\n </span>\n </span>\n </label>\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-3\">\n <div>\n <label\n htmlFor=\"dateFrom\"\n className=\"block text-xs text-text-secondary mb-1\"\n >\n {tr(\"export.create.options.dateFrom\", \"From\")}\n </label>\n <input\n type=\"date\"\n id=\"dateFrom\"\n aria-label={tr(\n \"export.create.options.dateFrom\",\n \"From\",\n )}\n value={dateRangeStart}\n onChange={(e) => setDateRangeStart(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 text-sm\"\n />\n </div>\n <div>\n <label\n htmlFor=\"dateTo\"\n className=\"block text-xs text-text-secondary mb-1\"\n >\n {tr(\"export.create.options.dateTo\", \"To\")}\n </label>\n <input\n type=\"date\"\n id=\"dateTo\"\n aria-label={tr(\"export.create.options.dateTo\", \"To\")}\n value={dateRangeEnd}\n min={dateRangeStart}\n onChange={(e) => setDateRangeEnd(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 text-sm\"\n />\n </div>\n </div>\n <p className=\"text-xs text-text-secondary mt-1.5\">\n {tr(\n \"export.create.options.dateRangeDescription\",\n \"Leave blank to export all data regardless of date.\",\n )}\n </p>\n </div>\n\n {/* Optional: Use a template */}\n <div>\n <label className=\"block text-sm font-semibold mb-2\">\n {tr(\n \"export.create.options.basedOnTemplate\",\n \"Based on Template\",\n )}{\" \"}\n <span className=\"font-normal text-text-secondary\">\n {tr(\"export.create.shared.optional\", \"(optional)\")}\n </span>\n </label>\n {templates.length > 0 ? (\n <select\n value={selectedTemplateId ?? \"\"}\n onChange={(e) =>\n setSelectedTemplateId(e.target.value || undefined)\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\"\n >\n <option value=\"\">\n {tr(\"export.create.options.noTemplate\", \"No template\")}\n </option>\n {templates.map((t) => (\n <option key={t.id} value={t.id}>\n {t.name}\n </option>\n ))}\n </select>\n ) : (\n <p className=\"text-sm text-text-secondary\">\n {tr(\n \"export.create.options.noTemplates\",\n \"No templates yet.\",\n )}{\" \"}\n <button\n type=\"button\"\n onClick={() => navigate?.(basePath + \"/templates\")}\n className=\"text-primary underline-offset-2 hover:underline\"\n >\n {tr(\n \"export.create.options.createTemplateLink\",\n \"Create one\",\n )}\n </button>{\" \"}\n {tr(\n \"export.create.options.reuseTemplateHint\",\n \"to reuse export configurations.\",\n )}\n </p>\n )}\n </div>\n </div>\n </ShowMore>\n </div>\n </div>\n )}\n\n {/* Step 3: Review */}\n {step === \"review\" && (\n <div className=\"space-y-6\">\n <EmphasisPanel className=\"p-6 space-y-4\">\n <h2 className=\"text-lg font-bold flex items-center gap-2\">\n <CheckCircle2 size={20} className=\"text-primary\" />\n {tr(\"export.create.review.title\", \"Review Export\")}\n </h2>\n <dl className=\"space-y-3 text-sm\">\n {[\n {\n label: tr(\"export.create.review.fields.name\", \"Name\"),\n value: exportName,\n },\n {\n label: tr(\"export.create.review.fields.scope\", \"Scope\"),\n value: getScopeLabel(selectedScope),\n },\n {\n label: tr(\n \"export.create.review.fields.entityTypes\",\n \"Entity Types\",\n ),\n value: selectedEntities.join(\", \"),\n },\n {\n label: tr(\"export.create.review.fields.format\", \"Format\"),\n value: getFormatDisplayName(selectedFormat),\n },\n {\n label: tr(\"export.create.review.fields.archive\", \"Archive\"),\n value: tr(\"export.archive.zip\", \"ZIP\"),\n },\n ...(dateRangeStart || dateRangeEnd\n ? [\n {\n label: tr(\n \"export.create.review.fields.dateRange\",\n \"Date Range\",\n ),\n value: [\n dateRangeStart || \"—\",\n dateRangeEnd || \"—\",\n ].join(\" → \"),\n },\n ]\n : []),\n ...(selectedTemplateId\n ? [\n {\n label: tr(\n \"export.create.review.fields.template\",\n \"Template\",\n ),\n value:\n templates.find((t) => t.id === selectedTemplateId)\n ?.name ?? selectedTemplateId,\n },\n ]\n : []),\n ].map(({ label, value }) => (\n <div\n key={label}\n className=\"flex flex-col sm:flex-row sm:justify-between gap-1\"\n >\n <dt className=\"text-text-secondary\">{label}</dt>\n <dd className=\"font-semibold sm:text-right break-words\">\n {value}\n </dd>\n </div>\n ))}\n </dl>\n </EmphasisPanel>\n </div>\n )}\n\n {/* Actions */}\n <div className=\"flex flex-col sm:flex-row gap-3 pt-2\">\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"px-6 py-3 border-2 border-border-subtle/50 rounded-lg hover:bg-accent hover:border-primary/30 transition-all duration-200 font-medium\"\n >\n {step === \"entities\"\n ? tr(\"export.create.actions.cancel\", \"Cancel\")\n : tr(\"export.create.actions.back\", \"Back\")}\n </button>\n {step === \"review\" ? (\n <button\n type=\"button\"\n onClick={handleSubmit}\n disabled={isPending}\n className=\"flex-1 inline-flex items-center justify-center gap-2 px-6 py-3 bg-action-primary-bg text-action-primary-text rounded-lg hover:bg-action-primary-bg/90 transition-all duration-200 font-bold shadow-lg disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n {isPending ? (\n <Loader2 size={18} className=\"animate-spin\" />\n ) : (\n <Download size={18} />\n )}\n {tr(\"export.create.actions.startExport\", \"Start Export\")}\n </button>\n ) : (\n <button\n type=\"button\"\n onClick={handleNext}\n className=\"flex-1 inline-flex items-center justify-center gap-2 px-6 py-3 bg-action-primary-bg text-action-primary-text rounded-lg hover:bg-action-primary-bg/90 transition-all duration-200 font-bold shadow-lg\"\n >\n {tr(\"export.create.actions.next\", \"Next\")}\n <ArrowRight size={18} />\n </button>\n )}\n </div>\n\n <AlertDialog open={showQuotaDialog} onOpenChange={setShowQuotaDialog}>\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>\n {tr(\"export.create.quotaDialog.title\", \"Export Limit Reached\")}\n </AlertDialogTitle>\n <AlertDialogDescription>\n {tr(\n \"export.create.quotaDialog.description\",\n \"You have reached your export limit for this month.\",\n )}\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel>\n {tr(\"export.create.quotaDialog.dismiss\", \"Dismiss\")}\n </AlertDialogCancel>\n <AlertDialogAction\n onClick={() => window.location.assign(\"/billing\")}\n >\n {tr(\"export.create.quotaDialog.viewBilling\", \"View Billing\")}\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n </PageLayout>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;AAqDA,IAAM,IAAoC,CAAC,OAAO,OAAO,EAEnD,KAAsD;CAC1D,KAAK;CACL,MAAM;CACP,EAEK,IAAgD;CACpD,YAAY;CACZ,iBAAiB;CACjB,WAAW;CACZ;AAOD,SAAgB,IAAmB;CACjC,IAAM,EAAE,cAAW,KAAK,aAAU,sBAAmB,GAAW,EAC1D,IAAK,GAAO,EACZ,EAAE,cAAW,iBAAc,GAAoB,EAC/C,EAAE,MAAM,OAAsB,GAAsB,EACpD,EAAE,MAAM,MAAc,IAAoB,EAC1C,CAAC,KAAgB,GAAiB,EAGlC,IAA0B,EAAc,yBAAyB,EACjE,IAAoB,EAAc,mBAAmB,EAErD,CAAC,GAAM,KAAW,EAAqB,WAAW,EAClD,CAAC,GAAkB,KAAuB,EAAmB,EAAE,CAAC,EAChE,CAAC,GAAY,KAAiB,EAAS,GAAG,EAC1C,CAAC,GAAgB,KAAqB,EAAuB,MAAM,EACnE,CAAC,GAAe,MAAoB,EAAsB,aAAa,EACvE,CAAC,GAAoB,KAAyB,EAElD,EAAa,IAAI,aAAa,IAAI,KAAA,EAAU,EACxC,CAAC,GAAgB,MAAqB,EAAS,GAAG,EAClD,CAAC,GAAc,MAAmB,EAAS,GAAG,EAC9C,CAAC,GAAO,KAAY,EAAwB,KAAK,EACjD,CAAC,IAAiB,KAAsB,EAAS,GAAM,EAGvD,IAAqB,EAAsB,KAAK;AACtD,SAAgB;EACd,IAAM,IAAkB,EAAa,IAAI,aAAa;AAEtD,MADI,CAAC,KAAmB,CAAC,GAAW,UAChC,EAAmB,YAAY,EAAiB;EACpD,IAAM,IAAM,EAAU,MAAM,MAAM,EAAE,OAAO,EAAgB;AAC3D,MAAI,CAAC,EAAK;AAIV,EAHA,EAAmB,UAAU,GAC7B,EAAsB,EAAI,GAAG,EAE7B,GACG,EAAI,eAAe,EAAE,EAAE,QAAQ,MAAO,CAAC,EAAuB,EAAG,CAAC,CACpE;EACD,IAAM,IAAmB,EAAI,QAAQ,aAAa;AAKlD,EAHI,KAAoB,EAAkB,SAAS,EAAiB,IAClE,EAAkB,EAAiB,EAEjC,EAAI,QAAM,EAAc,EAAI,KAAK;IACpC,CAAC,GAAc,EAAU,CAAC;CAE7B,IAAM,WAAmB;AACvB,EAAI,MAAS,YAAW,EAAQ,WAAW,GAClC,MAAS,WAAU,EAAQ,UAAU,GACzC,IAAW,EAAS;IAGrB,WAAmB;AACvB,MAAI,MAAS,YAAY;AACvB,OAAI,EAAiB,WAAW,GAAG;AACjC,MACE,EACE,qCACA,mDACD,CACF;AACD;;AAGF,GADA,EAAS,KAAK,EACd,EAAQ,UAAU;aACT,MAAS,WAAW;AAC7B,OAAI,CAAC,EAAW,MAAM,EAAE;AACtB,MACE,EACE,2CACA,wCACD,CACF;AACD;;AAGF,GADA,EAAS,KAAK,EACd,EAAQ,SAAS;;IAIf,KAAe,YAAY;AAC/B,MAAI;AAiBF,GAhBA,EAAS,KAAK,EACd,MAAM,EAAU;IACd,MAAM;IACN,aAAa;IACb,QAAQ;IACR,aAAa;IACb,gBACE,MAAkB,cAAc,IAAiB,KAAA;IACnD,YAAY;IACZ,gBAAgB,IACZ,IAAI,KAAK,EAAe,CAAC,aAAa,GACtC;IACJ,cAAc,IACV,IAAI,KAAK,EAAa,CAAC,aAAa,GACpC;IACL,CAAC,EACF,IAAW,EAAS;WACb,GAAK;AACZ,OAAI,EAAsB,EAAI,EAAE;AAE9B,IADA,EAAmB,GAAK,EACxB,EACE,EACE,qCACA,qDACD,CACF;AACD;;AAEF,KACE,aAAe,QACX,EAAI,UACJ,EAAG,qCAAqC,0BAA0B,CACvE;;IAIC,MAAgB,MAAuB;AAEvC,IAAuB,EAAW,IACtC,GAAqB,MACnB,EAAK,SAAS,EAAW,GACrB,EAAK,QAAQ,MAAM,MAAM,EAAW,GACpC,CAAC,GAAG,GAAM,EAAW,CAC1B;IAGG,KAAiB,MAAuB;AAC5C,UAAQ,GAAR;GACE,KAAK,aACH,QAAO,EAAG,wCAAwC,eAAe;GACnE,KAAK,kBACH,QAAO,EACL,4CACA,qBACD;GACH,KAAK,YACH,QAAO,EACL,sCACA,wBACD;GACH,QACE,QAAO;;IAIP,MAAuB,MAAuB;AAClD,UAAQ,GAAR;GACE,KAAK,aACH,QAAO,EACL,8CACA,8DACD;GACH,KAAK,kBACH,QAAO,EACL,kDACA,mGACD;GACH,KAAK,YACH,QAAO,EACL,4CACA,oFACD;GACH,QACE,QAAO;;IAIP,IAGF;EACF,OAAO;GACL,OAAO,EAAG,sCAAsC,QAAQ;GACxD,aAAa,EACX,4CACA,iCACD;GACF;EACD,UAAU;GACR,OAAO,EAAG,yCAAyC,WAAW;GAC9D,aAAa,EACX,+CACA,8BACD;GACF;EACD,OAAO;GACL,OAAO,EAAG,sCAAsC,QAAQ;GACxD,aAAa,EACX,4CACA,6BACD;GACF;EACD,OAAO;GACL,OAAO,EAAG,sCAAsC,QAAQ;GACxD,aAAa,EACX,4CACA,+BACD;GACF;EACD,eAAe;GACb,OAAO,EAAG,8CAA8C,gBAAgB;GACxE,aAAa,EACX,oDACA,4BACD;GACF;EACD,MAAM;GACJ,OAAO,EAAG,qCAAqC,OAAO;GACtD,aAAa,EACX,2CACA,wBACD;GACF;EACD,UAAU;GACR,OAAO,EAAG,yCAAyC,gBAAgB;GACnE,aAAa,EACX,+CACA,mCACD;GACF;EACD,UAAU;GACR,OAAO,EAAG,yCAAyC,kBAAkB;GACrE,aAAa,EACX,+CACA,sBACD;GACF;EACF,EAIK,IAAkB,GAAkB,QAAQ,MAAM,EAAE,YAAY,GAAM,EACtE,IAAqB,EAAgB,QACxC,MAAM,CAAC,EAAuB,EAAE,WAAW,CAC7C,EACK,IAAuB,EAAgB,QAAQ,MACnD,EAAuB,EAAE,WAAW,CACrC,EAEK,KACJ,GACA,MACG;EACH,IAAM,IACJ,CAAC,KAAc,EAAiB,SAAS,EAAO,WAAW;AAC7D,SACE,kBAAC,UAAD;GACE,MAAK;GAEL,eAAe,GAAa,EAAO,WAAW;GAC9C,UAAU;GACV,iBAAe;GACf,OACE,IACI,EACE,wCACA,8CACD,GACD,KAAA;GAEN,WAAW,EACT,iEACA,IACI,0DACA,IACE,oDACA,kEACP;aArBH;IAuBE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,MAAD;MAAI,WAAU;gBACX,EAAmB,EAAO,aAAa,SAAS,EAAO;MACrD,CAAA,EACJ,IACC,kBAAC,QAAD;MAAM,WAAU;gBACb,EAAG,oCAAoC,cAAc;MACjD,CAAA,GAEP,KAAc,kBAAC,GAAD;MAAc,MAAM;MAAI,WAAU;MAAiB,CAAA,CAE/D;;IACN,kBAAC,KAAD;KAAG,WAAU;eACV,EAAmB,EAAO,aAAa,eACtC,EAAO;KACP,CAAA;IACH,EAAO,iBACN,kBAAC,KAAD;KAAG,WAAU;eAAb,CAAgD,KAC5C,EAAO,cACP;;IAEC;KA1CF,EAAO,WA0CL;;AAIb,QACE,kBAAC,IAAD;EAAY,YAAY;YAAxB;GAEE,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,UAAD;MACE,MAAK;MACL,eAAe,IAAW,EAAS;MACnC,WAAU;MACV,cAAY,EACV,yCACA,2BACD;gBAED,kBAAC,IAAD,EAAW,MAAM,IAAM,CAAA;MAChB,CAAA,EACT,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,OAAD;OAAK,WAAU;iBACb,kBAAC,GAAD;QAAU,MAAM;QAAI,WAAU;QAAiB,CAAA;OAC3C,CAAA,EACN,kBAAC,MAAD;OAAI,WAAU;iBACX,EAAG,uBAAuB,aAAa;OACrC,CAAA,CACD;QACF;;IACF,CAAA;GAGN,kBAAC,IAAD;IAAa,MAAM,kBAAC,GAAD,EAAU,MAAM,IAAM,CAAA;cACtC,EACC,yBACA,wOACD;IACW,CAAA;GAGd,kBAAC,OAAD;IAAK,WAAU;cACX;KAAC;KAAY;KAAW;KAAS,CAAkB,KAAK,GAAG,MAC3D,kBAAC,OAAD;KAAa,WAAU;eAAvB,CACG,IAAI,KAAK,kBAAC,GAAD;MAAY,MAAM;MAAI,WAAU;MAAwB,CAAA,EAClE,kBAAC,OAAD;MACE,WAAW,EACT,2GACA,MAAS,IACL,4FACA,yDACL;gBANH,CAQE,kBAAC,OAAD;OAAK,WAAU;iBACZ,IAAI;OACD,CAAA,EACN,kBAAC,QAAD;OAAM,WAAU;iBACb,MAAM,aACH,EAAG,gCAAgC,cAAc,GACjD,MAAM,YACJ,EAAG,+BAA+B,UAAU,GAC5C,EAAG,8BAA8B,SAAS;OAC3C,CAAA,CACH;QACF;OArBI,EAqBJ,CACN;IACE,CAAA;GAGL,KACC,kBAAC,OAAD;IAAK,WAAU;cACZ;IACG,CAAA;GAIP,MAAS,cACR,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,MAAD;MAAI,WAAU;gBACX,EAAG,8BAA8B,wBAAwB;MACvD,CAAA;KACL,kBAAC,KAAD;MAAG,WAAU;gBACV,EACC,oCACA,uDACD;MACC,CAAA;KACH,EAAgB,WAAW,IAC1B,kBAAC,IAAD;MACE,cAAa;MACb,OAAO,EACL,mCACA,wBACD;MACD,aAAa,EACX,8BACA,uJACD;MACD,CAAA,GAEF,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACG,EAAmB,SAAS,KAC3B,kBAAC,OAAD;OAAK,WAAU;iBACZ,EAAmB,KAAK,MACvB,EAAiB,GAAQ,GAAM,CAChC;OACG,CAAA,EAEP,EAAqB,SAAS,KAC7B,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,OAAD;QAAK,WAAU;kBAAf;SACE,kBAAC,OAAD,EAAK,WAAU,4BAA6B,CAAA;SAC5C,kBAAC,QAAD;UAAM,WAAU;oBACb,EACC,2CACA,oBACD;UACI,CAAA;SACP,kBAAC,OAAD,EAAK,WAAU,4BAA6B,CAAA;SACxC;WACN,kBAAC,OAAD;QAAK,WAAU;kBACZ,EAAqB,KAAK,MACzB,EAAiB,GAAQ,GAAK,CAC/B;QACG,CAAA,CACF;SAEJ;;KAEJ;;GAIP,MAAS,aACR,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,OAAD;KAAK,WAAU;eAAf;MACE,kBAAC,MAAD;OAAI,WAAU;iBACX,EAAG,+BAA+B,iBAAiB;OACjD,CAAA;MAGL,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;OAAO,WAAU;iBACd,EAAG,+BAA+B,eAAe;OAC5C,CAAA,EACR,kBAAC,OAAD;OAAK,WAAU;iBAEX;QACE;QACA;QACA;QACD,CACD,KAAK,MAAU;QAEf,IAAM,IACH,MAAU,qBAAqB,CAAC,KAChC,MAAU,eAAe,CAAC,GACvB,IAAO,EAAY,IACnB,IACJ,MAAU,oBACN,EACE,+CACA,kCACD,GACD,EACE,yCACA,qCACD;AAEP,eACE,kBAAC,UAAD;SAEE,MAAK;SACL,eAAe,CAAC,KAAc,GAAiB,EAAM;SACrD,UAAU;SACV,WAAW,EACT,iEACA,MAAkB,IACd,oDACA,IACE,0DACA,kEACP;SACD,OAAO,IAAa,IAAgB,KAAA;mBAbtC;UAeE,kBAAC,OAAD;WAAK,WAAU;qBAAf;YACE,kBAAC,GAAD;aACE,MAAM;aACN,WACE,MAAkB,IACd,iBACA,IACE,2BACA;aAER,CAAA;YACD,MAAkB,KACjB,kBAAC,GAAD;aAAc,MAAM;aAAI,WAAU;aAAiB,CAAA;YAEpD,KACC,kBAAC,IAAD;aAAM,MAAM;aAAI,WAAU;aAA2B,CAAA;YAEnD;;UACN,kBAAC,KAAD;WAAG,WAAU;qBACV,EAAc,EAAM;WACnB,CAAA;UACJ,kBAAC,KAAD;WAAG,WAAU;qBACV,GAAoB,EAAM;WACzB,CAAA;UACG;WAtCF,EAsCE;SAEX;OACE,CAAA,CACF,EAAA,CAAA;MAGN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;OACE,SAAQ;OACR,WAAU;iBAFZ;QAIG,EAAG,8BAA8B,cAAc;QAAE;QAClD,kBAAC,QAAD;SAAM,WAAU;mBAAyB;SAAQ,CAAA;QAC3C;UACR,kBAAC,SAAD;OACE,MAAK;OACL,IAAG;OACH,cAAY,EAAG,8BAA8B,cAAc;OAC3D,OAAO;OACP,WAAW,MAAM,EAAc,EAAE,OAAO,MAAM;OAC9C,WAAU;OACV,aAAa,EACX,yCACA,4BACD;OACD,CAAA,CACE,EAAA,CAAA;MAGN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;OAAO,WAAU;iBACd,EAAG,sCAAsC,gBAAgB;OACpD,CAAA,EACR,kBAAC,OAAD;OAAK,WAAU;iBACZ,EAAkB,KAAK,MAAW;QACjC,IAAM,IAAO,GAAa;AAC1B,eACE,kBAAC,UAAD;SACE,MAAK;SAEL,eAAe,EAAkB,EAAO;SACxC,WAAW,EACT,+EACA,MAAmB,IACf,0CACA,kDACL;mBATH,CAWE,kBAAC,GAAD;UACE,MAAM;UACN,WACE,MAAmB,IACf,iBACA;UAEN,CAAA,EACF,kBAAC,QAAD;UAAM,WAAU;oBACb,EAAqB,EAAO;UACxB,CAAA,CACA;WApBF,EAoBE;SAEX;OACE,CAAA,CACF,EAAA,CAAA;MAGN,kBAAC,OAAD,EAAA,UAAA;OACE,kBAAC,SAAD;QAAO,WAAU;kBACd,EAAG,uCAAuC,iBAAiB;QACtD,CAAA;OACR,kBAAC,OAAD;QAAK,WAAU;kBACb,kBAAC,OAAD;SACE,WAAW,EACT,8FACD;mBAHH,CAKE,kBAAC,IAAD;UAAS,MAAM;UAAI,WAAU;UAAiB,CAAA,EAC9C,kBAAC,QAAD;UAAM,WAAU;oBACb,EAAG,sBAAsB,MAAM;UAC3B,CAAA,CACH;;QACF,CAAA;OACN,kBAAC,KAAD;QAAG,WAAU;kBACV,EACC,4CACA,wCACD;QACC,CAAA;OACA,EAAA,CAAA;MAGN,kBAAC,IAAD;OACE,iBAAiB;OACjB,OAAO,EACL,wCACA,wBACD;iBAED,kBAAC,OAAD;QAAK,WAAU;kBAAf,CAEE,kBAAC,OAAD,EAAA,UAAA;SACE,kBAAC,SAAD;UAAO,WAAU;oBACf,kBAAC,QAAD;WAAM,WAAU;qBAAhB;YACE,kBAAC,GAAD,EAAe,MAAM,IAAM,CAAA;YAC1B,EAAG,mCAAmC,aAAa;YAAE;YACtD,kBAAC,QAAD;aAAM,WAAU;uBACb,EAAG,iCAAiC,aAAa;aAC7C,CAAA;YACF;;UACD,CAAA;SACR,kBAAC,OAAD;UAAK,WAAU;oBAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;WACE,SAAQ;WACR,WAAU;qBAET,EAAG,kCAAkC,OAAO;WACvC,CAAA,EACR,kBAAC,SAAD;WACE,MAAK;WACL,IAAG;WACH,cAAY,EACV,kCACA,OACD;WACD,OAAO;WACP,WAAW,MAAM,GAAkB,EAAE,OAAO,MAAM;WAClD,WAAU;WACV,CAAA,CACE,EAAA,CAAA,EACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;WACE,SAAQ;WACR,WAAU;qBAET,EAAG,gCAAgC,KAAK;WACnC,CAAA,EACR,kBAAC,SAAD;WACE,MAAK;WACL,IAAG;WACH,cAAY,EAAG,gCAAgC,KAAK;WACpD,OAAO;WACP,KAAK;WACL,WAAW,MAAM,GAAgB,EAAE,OAAO,MAAM;WAChD,WAAU;WACV,CAAA,CACE,EAAA,CAAA,CACF;;SACN,kBAAC,KAAD;UAAG,WAAU;oBACV,EACC,8CACA,qDACD;UACC,CAAA;SACA,EAAA,CAAA,EAGN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;SAAO,WAAU;mBAAjB;UACG,EACC,yCACA,oBACD;UAAE;UACH,kBAAC,QAAD;WAAM,WAAU;qBACb,EAAG,iCAAiC,aAAa;WAC7C,CAAA;UACD;YACP,EAAU,SAAS,IAClB,kBAAC,UAAD;SACE,OAAO,KAAsB;SAC7B,WAAW,MACT,EAAsB,EAAE,OAAO,SAAS,KAAA,EAAU;SAEpD,WAAU;mBALZ,CAOE,kBAAC,UAAD;UAAQ,OAAM;oBACX,EAAG,oCAAoC,cAAc;UAC/C,CAAA,EACR,EAAU,KAAK,MACd,kBAAC,UAAD;UAAmB,OAAO,EAAE;oBACzB,EAAE;UACI,EAFI,EAAE,GAEN,CACT,CACK;aAET,kBAAC,KAAD;SAAG,WAAU;mBAAb;UACG,EACC,qCACA,oBACD;UAAE;UACH,kBAAC,UAAD;WACE,MAAK;WACL,eAAe,IAAW,IAAW,aAAa;WAClD,WAAU;qBAET,EACC,4CACA,aACD;WACM,CAAA;UAAC;UACT,EACC,2CACA,kCACD;UACC;WAEF,EAAA,CAAA,CACF;;OACG,CAAA;MACP;;IACF,CAAA;GAIP,MAAS,YACR,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,IAAD;KAAe,WAAU;eAAzB,CACE,kBAAC,MAAD;MAAI,WAAU;gBAAd,CACE,kBAAC,GAAD;OAAc,MAAM;OAAI,WAAU;OAAiB,CAAA,EAClD,EAAG,8BAA8B,gBAAgB,CAC/C;SACL,kBAAC,MAAD;MAAI,WAAU;gBACX;OACC;QACE,OAAO,EAAG,oCAAoC,OAAO;QACrD,OAAO;QACR;OACD;QACE,OAAO,EAAG,qCAAqC,QAAQ;QACvD,OAAO,EAAc,EAAc;QACpC;OACD;QACE,OAAO,EACL,2CACA,eACD;QACD,OAAO,EAAiB,KAAK,KAAK;QACnC;OACD;QACE,OAAO,EAAG,sCAAsC,SAAS;QACzD,OAAO,EAAqB,EAAe;QAC5C;OACD;QACE,OAAO,EAAG,uCAAuC,UAAU;QAC3D,OAAO,EAAG,sBAAsB,MAAM;QACvC;OACD,GAAI,KAAkB,IAClB,CACE;QACE,OAAO,EACL,yCACA,aACD;QACD,OAAO,CACL,KAAkB,KAClB,KAAgB,IACjB,CAAC,KAAK,MAAM;QACd,CACF,GACD,EAAE;OACN,GAAI,IACA,CACE;QACE,OAAO,EACL,wCACA,WACD;QACD,OACE,EAAU,MAAM,MAAM,EAAE,OAAO,EAAmB,EAC9C,QAAQ;QACf,CACF,GACD,EAAE;OACP,CAAC,KAAK,EAAE,UAAO,eACd,kBAAC,OAAD;OAEE,WAAU;iBAFZ,CAIE,kBAAC,MAAD;QAAI,WAAU;kBAAuB;QAAW,CAAA,EAChD,kBAAC,MAAD;QAAI,WAAU;kBACX;QACE,CAAA,CACD;SAPC,EAOD,CACN;MACC,CAAA,CACS;;IACZ,CAAA;GAIR,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,UAAD;KACE,MAAK;KACL,SAAS;KACT,WAAU;eAET,MAAS,aACN,EAAG,gCAAgC,SAAS,GAC5C,EAAG,8BAA8B,OAAO;KACrC,CAAA,EACR,MAAS,WACR,kBAAC,UAAD;KACE,MAAK;KACL,SAAS;KACT,UAAU;KACV,WAAU;eAJZ,CAMG,IACC,kBAAC,IAAD;MAAS,MAAM;MAAI,WAAU;MAAiB,CAAA,GAE9C,kBAAC,GAAD,EAAU,MAAM,IAAM,CAAA,EAEvB,EAAG,qCAAqC,eAAe,CACjD;SAET,kBAAC,UAAD;KACE,MAAK;KACL,SAAS;KACT,WAAU;eAHZ,CAKG,EAAG,8BAA8B,OAAO,EACzC,kBAAC,GAAD,EAAY,MAAM,IAAM,CAAA,CACjB;OAEP;;GAEN,kBAAC,IAAD;IAAa,MAAM;IAAiB,cAAc;cAChD,kBAAC,IAAD,EAAA,UAAA,CACE,kBAAC,IAAD,EAAA,UAAA,CACE,kBAAC,IAAD,EAAA,UACG,EAAG,mCAAmC,uBAAuB,EAC7C,CAAA,EACnB,kBAAC,IAAD,EAAA,UACG,EACC,yCACA,qDACD,EACsB,CAAA,CACP,EAAA,CAAA,EACpB,kBAAC,IAAD,EAAA,UAAA,CACE,kBAAC,IAAD,EAAA,UACG,EAAG,qCAAqC,UAAU,EACjC,CAAA,EACpB,kBAAC,IAAD;KACE,eAAe,OAAO,SAAS,OAAO,WAAW;eAEhD,EAAG,yCAAyC,eAAe;KAC1C,CAAA,CACF,EAAA,CAAA,CACD,EAAA,CAAA;IACT,CAAA;GACH"}
@@ -1 +1 @@
1
- {"version":3,"file":"ExportDashboardPage.d.ts","sourceRoot":"","sources":["../../../src/export/pages/ExportDashboardPage.tsx"],"names":[],"mappings":"AAqCA;;;GAGG;AACH,wBAAgB,mBAAmB,gCAkXlC"}
1
+ {"version":3,"file":"ExportDashboardPage.d.ts","sourceRoot":"","sources":["../../../src/export/pages/ExportDashboardPage.tsx"],"names":[],"mappings":"AAoCA;;;GAGG;AACH,wBAAgB,mBAAmB,gCA6WlC"}
@@ -1,64 +1,63 @@
1
1
  import { useExport as e } from "../providers/ExportProvider.js";
2
- import { useExportJobs as t } from "../hooks/useExportQueries.js";
3
- import { cn as n } from "../utils/cn.js";
4
- import { tWithFallback as r } from "../utils/i18n.js";
2
+ import { useTr as t } from "../hooks/useTr.js";
3
+ import { useExportJobs as n } from "../hooks/useExportQueries.js";
4
+ import { cn as r } from "../utils/cn.js";
5
5
  import { ExportStatusBadge as i } from "../components/ExportStatusBadge.js";
6
6
  import { ExportProgressBar as a } from "../components/ExportProgressBar.js";
7
7
  import { PageLayout as o, PageSection as s } from "../components/PageLayout.js";
8
8
  import { Activity as c, ArrowRight as l, CheckCircle2 as u, Clock as d, Download as f, FileBox as p, Plus as m } from "lucide-react";
9
9
  import { jsx as h, jsxs as g } from "react/jsx-runtime";
10
- import { useI18n as _ } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
11
- import { AuroraBackground as v, EmphasisPanel as y, GlassCard as b, GradientText as x, IllustratedEmptyState as S, NextSteps as C, PagePurpose as w } from "@burdenoff/fe-libs/ui";
10
+ import { AuroraBackground as _, EmphasisPanel as v, GlassCard as y, GradientText as b, IllustratedEmptyState as x, NextSteps as S, PagePurpose as C } from "@burdenoff/fe-libs/ui";
12
11
  //#region src/export/pages/ExportDashboardPage.tsx
13
- var T = (e, t) => (e.endsWith("/") ? e.slice(0, -1) : e) + (t.startsWith("/") ? t : `/${t}`);
14
- function E() {
15
- let { basePath: E = "/", navigate: D } = e(), { t: O } = _(), k = (e, t, n) => r(O, e, t, n), { data: A, isLoading: j } = t({}), M = A.slice(0, 5), N = A.filter((e) => e.status === "RUNNING" || e.status === "QUEUED"), P = A.filter((e) => e.status === "COMPLETED"), F = [
12
+ var w = (e, t) => (e.endsWith("/") ? e.slice(0, -1) : e) + (t.startsWith("/") ? t : `/${t}`);
13
+ function T() {
14
+ let { basePath: T = "/", navigate: E } = e(), D = t(), { data: O, isLoading: k } = n({}), A = O.slice(0, 5), j = O.filter((e) => e.status === "RUNNING" || e.status === "QUEUED"), M = O.filter((e) => e.status === "COMPLETED"), N = [
16
15
  {
17
16
  icon: /* @__PURE__ */ h(f, { size: 18 }),
18
- label: k("export.dashboard.metrics.total", "Total Exports"),
19
- value: A.length,
17
+ label: D("export.dashboard.metrics.total", "Total Exports"),
18
+ value: O.length,
20
19
  treatment: "glass",
21
20
  glow: !0
22
21
  },
23
22
  {
24
23
  icon: /* @__PURE__ */ h(c, { size: 18 }),
25
- label: k("export.dashboard.metrics.active", "Active"),
26
- value: N.length,
24
+ label: D("export.dashboard.metrics.active", "Active"),
25
+ value: j.length,
27
26
  treatment: "metric",
28
27
  glow: !1
29
28
  },
30
29
  {
31
30
  icon: /* @__PURE__ */ h(u, { size: 18 }),
32
- label: k("export.dashboard.metrics.completed", "Completed"),
33
- value: P.length,
31
+ label: D("export.dashboard.metrics.completed", "Completed"),
32
+ value: M.length,
34
33
  treatment: "metric",
35
34
  glow: !1
36
35
  }
37
- ], I = (e) => {
38
- D && D(T(E, e));
39
- }, L = [
36
+ ], P = (e) => {
37
+ E && E(w(T, e));
38
+ }, F = [
40
39
  {
41
40
  id: "create",
42
- label: k("export.dashboard.nextSteps.create.label", "Create your first export"),
43
- description: k("export.dashboard.nextSteps.create.description", "Pick the data you want and download it as CSV or JSON."),
41
+ label: D("export.dashboard.nextSteps.create.label", "Create your first export"),
42
+ description: D("export.dashboard.nextSteps.create.description", "Pick the data you want and download it as CSV or JSON."),
44
43
  icon: /* @__PURE__ */ h(m, { size: 16 }),
45
- onClick: () => I("new"),
46
- done: A.length > 0
44
+ onClick: () => P("new"),
45
+ done: O.length > 0
47
46
  },
48
47
  {
49
48
  id: "template",
50
- label: k("export.dashboard.nextSteps.template.label", "Save a reusable template"),
51
- description: k("export.dashboard.nextSteps.template.description", "Store a common export config so repeat exports are one click."),
49
+ label: D("export.dashboard.nextSteps.template.label", "Save a reusable template"),
50
+ description: D("export.dashboard.nextSteps.template.description", "Store a common export config so repeat exports are one click."),
52
51
  icon: /* @__PURE__ */ h(p, { size: 16 }),
53
- onClick: () => I("templates")
52
+ onClick: () => P("templates")
54
53
  },
55
54
  {
56
55
  id: "history",
57
- label: k("export.dashboard.nextSteps.history.label", "Track exports in History"),
58
- description: k("export.dashboard.nextSteps.history.description", "Monitor progress and grab download links for finished jobs."),
56
+ label: D("export.dashboard.nextSteps.history.label", "Track exports in History"),
57
+ description: D("export.dashboard.nextSteps.history.description", "Monitor progress and grab download links for finished jobs."),
59
58
  icon: /* @__PURE__ */ h(d, { size: 16 }),
60
- onClick: () => I("history"),
61
- done: P.length > 0
59
+ onClick: () => P("history"),
60
+ done: M.length > 0
62
61
  }
63
62
  ];
64
63
  return /* @__PURE__ */ g(o, {
@@ -66,7 +65,7 @@ function E() {
66
65
  children: [
67
66
  /* @__PURE__ */ g("header", {
68
67
  className: "relative overflow-hidden rounded-2xl",
69
- children: [/* @__PURE__ */ h(v, { intensity: "subtle" }), /* @__PURE__ */ g("div", {
68
+ children: [/* @__PURE__ */ h(_, { intensity: "subtle" }), /* @__PURE__ */ g("div", {
70
69
  className: "relative flex items-center gap-3 px-2 py-4 sm:py-5",
71
70
  children: [/* @__PURE__ */ h("div", {
72
71
  className: "flex-shrink-0 p-2.5 rounded-xl bg-action-primary-bg/10 text-primary",
@@ -75,26 +74,26 @@ function E() {
75
74
  className: "space-y-1",
76
75
  children: [/* @__PURE__ */ h("h1", {
77
76
  className: "text-2xl sm:text-3xl font-bold tracking-tight text-text-primary",
78
- children: /* @__PURE__ */ h(x, { children: k("export.dashboard.title", "Export") })
77
+ children: /* @__PURE__ */ h(b, { children: D("export.dashboard.title", "Export") })
79
78
  }), /* @__PURE__ */ h("p", {
80
79
  className: "text-sm sm:text-base text-text-secondary max-w-2xl",
81
- children: k("export.dashboard.subtitle", "Export your workspace data in multiple formats")
80
+ children: D("export.dashboard.subtitle", "Export your workspace data in multiple formats")
82
81
  })]
83
82
  })]
84
83
  })]
85
84
  }),
86
- /* @__PURE__ */ h(w, {
85
+ /* @__PURE__ */ h(C, {
87
86
  icon: /* @__PURE__ */ h(f, { size: 16 }),
88
- children: k("export.dashboard.purpose", "Export takes your workspace data — people, projects, files, tags, activity and more — and packages it into downloadable CSV or JSON files. Use it to back up your data, hand it to another tool, run an audit, or take it with you when you leave. Pick what you want, choose a format, and grab the download when it's ready.")
87
+ children: D("export.dashboard.purpose", "Export takes your workspace data — people, projects, files, tags, activity and more — and packages it into downloadable CSV or JSON files. Use it to back up your data, hand it to another tool, run an audit, or take it with you when you leave. Pick what you want, choose a format, and grab the download when it's ready.")
89
88
  }),
90
- /* @__PURE__ */ h(C, {
89
+ /* @__PURE__ */ h(S, {
91
90
  storageKey: "export-dashboard",
92
- title: k("export.dashboard.nextSteps.title", "Get started"),
93
- steps: L
91
+ title: D("export.dashboard.nextSteps.title", "Get started"),
92
+ steps: F
94
93
  }),
95
- !j && A.length > 0 && /* @__PURE__ */ h("div", {
94
+ !k && O.length > 0 && /* @__PURE__ */ h("div", {
96
95
  className: "grid grid-cols-1 sm:grid-cols-3 gap-4",
97
- children: F.map((e) => /* @__PURE__ */ g(b, {
96
+ children: N.map((e) => /* @__PURE__ */ g(y, {
98
97
  treatment: e.treatment,
99
98
  glow: e.glow,
100
99
  className: "p-5 border-border-seam",
@@ -116,39 +115,39 @@ function E() {
116
115
  children: [
117
116
  {
118
117
  icon: /* @__PURE__ */ h(m, { size: 20 }),
119
- label: k("export.dashboard.actions.newExport.label", "New Export"),
120
- description: k("export.dashboard.actions.newExport.description", "Create a new data export"),
118
+ label: D("export.dashboard.actions.newExport.label", "New Export"),
119
+ description: D("export.dashboard.actions.newExport.description", "Create a new data export"),
121
120
  path: "new",
122
121
  color: "bg-action-primary-bg/10 text-primary"
123
122
  },
124
123
  {
125
124
  icon: /* @__PURE__ */ h(d, { size: 20 }),
126
- label: k("export.dashboard.actions.history.label", "History"),
127
- description: k("export.dashboard.actions.history.description", "View past exports"),
125
+ label: D("export.dashboard.actions.history.label", "History"),
126
+ description: D("export.dashboard.actions.history.description", "View past exports"),
128
127
  path: "history",
129
128
  color: "bg-status-info-bg-subtle text-status-info-text"
130
129
  },
131
130
  {
132
131
  icon: /* @__PURE__ */ h(p, { size: 20 }),
133
- label: k("export.dashboard.actions.templates.label", "Templates"),
134
- description: k("export.dashboard.actions.templates.description", "Reusable export configs"),
132
+ label: D("export.dashboard.actions.templates.label", "Templates"),
133
+ description: D("export.dashboard.actions.templates.description", "Reusable export configs"),
135
134
  path: "templates",
136
135
  color: "bg-accent-purple-subtle text-accent-purple"
137
136
  },
138
137
  {
139
138
  icon: /* @__PURE__ */ h(c, { size: 20 }),
140
- label: k("export.dashboard.actions.activeJobs.label", "Active Jobs"),
141
- description: k("export.dashboard.actions.activeJobs.description", "{count} running", { count: N.length }),
139
+ label: D("export.dashboard.actions.activeJobs.label", "Active Jobs"),
140
+ description: D("export.dashboard.actions.activeJobs.description", "{{count}} running", { count: j.length }),
142
141
  path: "history?status=RUNNING",
143
142
  color: "bg-status-success-bg-subtle text-status-success-text"
144
143
  }
145
144
  ].map((e) => /* @__PURE__ */ g("button", {
146
145
  type: "button",
147
- onClick: () => I(e.path),
148
- className: n("group relative overflow-hidden border border-border-seam rounded-xl p-5", "bg-bg-surface shadow-[var(--shadow-pop)]", "hover:border-primary/40 transition-colors duration-200", "text-left focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40"),
146
+ onClick: () => P(e.path),
147
+ className: r("group relative overflow-hidden border border-border-seam rounded-xl p-5", "bg-bg-surface shadow-[var(--shadow-pop)]", "hover:border-primary/40 transition-colors duration-200", "text-left focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40"),
149
148
  children: [
150
149
  /* @__PURE__ */ h("div", {
151
- className: n("p-2.5 rounded-lg w-fit mb-3", e.color),
150
+ className: r("p-2.5 rounded-lg w-fit mb-3", e.color),
152
151
  children: e.icon
153
152
  }),
154
153
  /* @__PURE__ */ h("h3", {
@@ -166,24 +165,24 @@ function E() {
166
165
  ]
167
166
  }, e.path + e.label))
168
167
  }),
169
- N.length > 0 && /* @__PURE__ */ g(y, {
168
+ j.length > 0 && /* @__PURE__ */ g(v, {
170
169
  "data-tour": "export-dashboard-active-section",
171
170
  className: "p-5 sm:p-6",
172
171
  children: [/* @__PURE__ */ g("div", {
173
172
  className: "mb-4",
174
173
  children: [/* @__PURE__ */ h("h2", {
175
174
  className: "text-lg font-semibold text-text-primary",
176
- children: k("export.dashboard.active.title", "Active Exports")
175
+ children: D("export.dashboard.active.title", "Active Exports")
177
176
  }), /* @__PURE__ */ h("p", {
178
177
  className: "text-sm text-text-secondary",
179
- children: k("export.dashboard.active.description", "Currently running export jobs")
178
+ children: D("export.dashboard.active.description", "Currently running export jobs")
180
179
  })]
181
180
  }), /* @__PURE__ */ h("div", {
182
181
  className: "space-y-3",
183
- children: N.map((e) => /* @__PURE__ */ g("button", {
182
+ children: j.map((e) => /* @__PURE__ */ g("button", {
184
183
  type: "button",
185
- onClick: () => I(e.id),
186
- className: n("w-full text-left border border-border-seam rounded-xl p-4 bg-bg-surface/70", "hover:border-primary/40 transition-colors duration-200", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40"),
184
+ onClick: () => P(e.id),
185
+ className: r("w-full text-left border border-border-seam rounded-xl p-4 bg-bg-surface/70", "hover:border-primary/40 transition-colors duration-200", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40"),
187
186
  children: [/* @__PURE__ */ g("div", {
188
187
  className: "flex items-center justify-between mb-2",
189
188
  children: [/* @__PURE__ */ h("h4", {
@@ -199,15 +198,15 @@ function E() {
199
198
  }),
200
199
  /* @__PURE__ */ h(s, {
201
200
  "data-tour": "export-dashboard-recent-section",
202
- title: k("export.dashboard.recent.title", "Recent Exports"),
203
- description: k("export.dashboard.recent.description", "Your latest export jobs"),
204
- actions: M.length > 0 ? /* @__PURE__ */ h("button", {
201
+ title: D("export.dashboard.recent.title", "Recent Exports"),
202
+ description: D("export.dashboard.recent.description", "Your latest export jobs"),
203
+ actions: A.length > 0 ? /* @__PURE__ */ h("button", {
205
204
  type: "button",
206
- onClick: () => I("history"),
205
+ onClick: () => P("history"),
207
206
  className: "text-sm text-primary hover:underline font-medium",
208
- children: k("export.dashboard.recent.actions.viewAll", "View All")
207
+ children: D("export.dashboard.recent.actions.viewAll", "View All")
209
208
  }) : void 0,
210
- children: j ? /* @__PURE__ */ h("div", {
209
+ children: k ? /* @__PURE__ */ h("div", {
211
210
  className: "space-y-3",
212
211
  children: [...[
213
212
  ,
@@ -220,12 +219,12 @@ function E() {
220
219
  children: [/* @__PURE__ */ h("div", { className: "h-4 w-48 bg-bg-sunken rounded animate-vc-shimmer" }), /* @__PURE__ */ h("div", { className: "h-5 w-20 bg-bg-sunken rounded-full animate-vc-shimmer" })]
221
220
  }), /* @__PURE__ */ h("div", { className: "h-3 w-32 bg-bg-sunken rounded mt-2 animate-vc-shimmer" })]
222
221
  }, t))
223
- }) : M.length > 0 ? /* @__PURE__ */ h("div", {
222
+ }) : A.length > 0 ? /* @__PURE__ */ h("div", {
224
223
  className: "space-y-3",
225
- children: M.map((e, t) => /* @__PURE__ */ h("button", {
224
+ children: A.map((e, t) => /* @__PURE__ */ h("button", {
226
225
  type: "button",
227
- onClick: () => I(e.id),
228
- className: n("w-full text-left border border-border-seam rounded-xl p-4 bg-bg-surface", "hover:border-primary/40 transition-colors duration-200", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40", "animate-in fade-in-0"),
226
+ onClick: () => P(e.id),
227
+ className: r("w-full text-left border border-border-seam rounded-xl p-4 bg-bg-surface", "hover:border-primary/40 transition-colors duration-200", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40", "animate-in fade-in-0"),
229
228
  style: { animationDelay: `${t * 50}ms` },
230
229
  children: /* @__PURE__ */ g("div", {
231
230
  className: "flex items-start sm:items-center justify-between gap-3",
@@ -240,7 +239,7 @@ function E() {
240
239
  e.entityTypes.join(", "),
241
240
  " · ",
242
241
  e.format,
243
- e.totalEntities != null && ` · ${k("export.dashboard.recent.entitiesCount", "{count} entities", { count: e.totalEntities.toLocaleString() })}`
242
+ e.totalEntities != null && ` · ${D("export.dashboard.recent.entitiesCount", "{{count}} entities", { count: e.totalEntities.toLocaleString() })}`
244
243
  ]
245
244
  })]
246
245
  }), /* @__PURE__ */ g("div", {
@@ -252,15 +251,15 @@ function E() {
252
251
  })]
253
252
  })
254
253
  }, e.id))
255
- }) : /* @__PURE__ */ h(S, {
254
+ }) : /* @__PURE__ */ h(x, {
256
255
  illustration: "empty-files",
257
- title: k("export.dashboard.empty.title", "No exports yet"),
258
- description: k("export.dashboard.empty.description", "Create your first export to start downloading your workspace data."),
256
+ title: D("export.dashboard.empty.title", "No exports yet"),
257
+ description: D("export.dashboard.empty.description", "Create your first export to start downloading your workspace data."),
259
258
  action: /* @__PURE__ */ g("button", {
260
259
  type: "button",
261
- onClick: () => I("new"),
260
+ onClick: () => P("new"),
262
261
  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",
263
- children: [/* @__PURE__ */ h(m, { size: 16 }), k("export.dashboard.empty.actions.createFirst", "Create First Export")]
262
+ children: [/* @__PURE__ */ h(m, { size: 16 }), D("export.dashboard.empty.actions.createFirst", "Create First Export")]
264
263
  })
265
264
  })
266
265
  })
@@ -268,6 +267,6 @@ function E() {
268
267
  });
269
268
  }
270
269
  //#endregion
271
- export { E as ExportDashboardPage };
270
+ export { T as ExportDashboardPage };
272
271
 
273
272
  //# sourceMappingURL=ExportDashboardPage.js.map