@burdenoff/microfe-devportal 2026.713.8 → 2026.713.9

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":"AdminDevportalRoot.js","names":[],"sources":["../../src/devportal/AdminDevportalRoot.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useEffect } from \"react\";\nimport { ShieldCheck, ClipboardList, BadgeCheck } from \"lucide-react\";\nimport { ErrorBoundary } from \"@burdenoff/fe-libs/shared/components\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport { FeatureFlagProvider } from \"@burdenoff/fe-libs/shared/feature-flags\";\nimport { DevportalProvider } from \"./providers/DevportalProvider\";\nimport type { NavItem, DevportalRootProps } from \"./types\";\nimport { AdminDevportalRoutes } from \"./AdminDevportalRoutes\";\n\n/**\n * AdminDevportalRoot\n *\n * Admin-only root for the Developer Portal microfrontend, intended to be\n * mounted exclusively in `admin-app`. Exposes the platform-admin review\n * queue (and any future super-admin-only devportal surfaces).\n *\n * Mirrors the AdminOrganizationRoot pattern: same `DevportalRootProps` shape\n * so hosts can swap between user and admin roots without adapter code; nav\n * items registered with `admin-devportal-*` IDs and grouped under\n * `globalconsole`.\n */\nexport const AdminDevportalRoot: FC<DevportalRootProps> = (props) => {\n const {\n registerNavItems,\n registerFooterItems,\n basePath = \"/developer-portal\",\n } = props;\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n };\n\n const 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 useEffect(() => {\n if (!registerNavItems) return;\n\n const navItems: NavItem[] = [\n {\n id: \"admin-devportal\",\n label: tr(\"devportal.developerPortal\", \"Developer Portal\"),\n path: basePath,\n icon: <ShieldCheck size={20} />,\n order: 70,\n group: \"globalconsole\",\n children: [\n {\n id: \"admin-devportal-reviews\",\n label: tr(\"devportal.appReviewQueue\", \"App Review Queue\"),\n path: joinPath(basePath, \"/reviews\"),\n icon: <ClipboardList size={16} />,\n order: 10,\n },\n {\n id: \"admin-devportal-verifications\",\n label: tr(\"devportal.verificationRequests\", \"Verification Requests\"),\n path: joinPath(basePath, \"/verifications\"),\n icon: <BadgeCheck size={16} />,\n order: 20,\n },\n ],\n },\n ];\n\n const cleanup = registerNavItems(navItems);\n return cleanup;\n }, [registerNavItems, basePath, t]);\n\n useEffect(() => {\n if (!registerFooterItems) return;\n\n const footerItems = [\n {\n id: \"admin-devportal-version\",\n label: tr(\n \"devportal.adminDeveloperPortalReady\",\n \"Admin Developer Portal Ready\",\n ),\n type: \"status\" as const,\n order: 30,\n section: \"left\" as const,\n },\n ];\n\n const cleanup = registerFooterItems(footerItems);\n return cleanup;\n }, [registerFooterItems, t]);\n\n return (\n <ErrorBoundary\n fallback={\n <div className=\"p-6 text-center text-text-secondary\">\n Something went wrong loading this module. Please refresh the page.\n </div>\n }\n >\n <FeatureFlagProvider\n workspaceId={null}\n gateway=\"global\"\n defaultEnabled={true}\n >\n <DevportalProvider {...props} basePath={basePath}>\n <AdminDevportalRoutes />\n </DevportalProvider>\n </FeatureFlagProvider>\n </ErrorBoundary>\n );\n};\n"],"mappings":";;;;;;;;;AAsBA,IAAa,KAA8C,MAAU;CACnE,IAAM,EACJ,qBACA,wBACA,cAAW,wBACT,GACE,EAAE,SAAM,GAAS,EACjB,KAAM,GAAa,MAA6B;EACpD,IAAM,IAAQ,EAAE,EAAI;AACpB,SAAO,MAAU,IAAM,IAAW;IAG9B,KAAY,GAAc,OACZ,EAAK,SAAS,IAAI,GAAG,EAAK,MAAM,GAAG,GAAG,GAAG,MACzC,EAAK,WAAW,IAAI,GAAG,IAAO,IAAI;AA0DtD,QAtDA,QAAgB;AACT,QA8BL,QADgB,EA3BY,CAC1B;GACE,IAAI;GACJ,OAAO,EAAG,6BAA6B,mBAAmB;GAC1D,MAAM;GACN,MAAM,kBAAC,GAAD,EAAa,MAAM,IAAM,CAAA;GAC/B,OAAO;GACP,OAAO;GACP,UAAU,CACR;IACE,IAAI;IACJ,OAAO,EAAG,4BAA4B,mBAAmB;IACzD,MAAM,EAAS,GAAU,WAAW;IACpC,MAAM,kBAAC,GAAD,EAAe,MAAM,IAAM,CAAA;IACjC,OAAO;IACR,EACD;IACE,IAAI;IACJ,OAAO,EAAG,kCAAkC,wBAAwB;IACpE,MAAM,EAAS,GAAU,iBAAiB;IAC1C,MAAM,kBAAC,GAAD,EAAY,MAAM,IAAM,CAAA;IAC9B,OAAO;IACR,CACF;GACF,CACF,CAEyC;IAEzC;EAAC;EAAkB;EAAU;EAAE,CAAC,EAEnC,QAAgB;AACT,QAgBL,QADgB,EAbI,CAClB;GACE,IAAI;GACJ,OAAO,EACL,uCACA,+BACD;GACD,MAAM;GACN,OAAO;GACP,SAAS;GACV,CACF,CAE+C;IAE/C,CAAC,GAAqB,EAAE,CAAC,EAG1B,kBAAC,GAAD;EACE,UACE,kBAAC,OAAD;GAAK,WAAU;aAAsC;GAE/C,CAAA;YAGR,kBAAC,GAAD;GACE,aAAa;GACb,SAAQ;GACR,gBAAgB;aAEhB,kBAAC,GAAD;IAAmB,GAAI;IAAiB;cACtC,kBAAC,GAAD,EAAwB,CAAA;IACN,CAAA;GACA,CAAA;EACR,CAAA"}
1
+ {"version":3,"file":"AdminDevportalRoot.js","names":[],"sources":["../../src/devportal/AdminDevportalRoot.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useEffect } from \"react\";\nimport { ShieldCheck, ClipboardList, BadgeCheck } from \"lucide-react\";\nimport { ErrorBoundary } from \"@burdenoff/fe-libs/shared/components\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport { FeatureFlagProvider } from \"@burdenoff/fe-libs/shared/feature-flags\";\nimport { DevportalProvider } from \"./providers/DevportalProvider\";\nimport type { NavItem, DevportalRootProps } from \"./types\";\nimport { AdminDevportalRoutes } from \"./AdminDevportalRoutes\";\n\n/**\n * AdminDevportalRoot\n *\n * Admin-only root for the Developer Portal microfrontend, intended to be\n * mounted exclusively in `admin-app`. Exposes the platform-admin review\n * queue (and any future super-admin-only devportal surfaces).\n *\n * Mirrors the AdminOrganizationRoot pattern: same `DevportalRootProps` shape\n * so hosts can swap between user and admin roots without adapter code; nav\n * items registered with `admin-devportal-*` IDs and grouped under\n * `globalconsole`.\n */\nexport const AdminDevportalRoot: FC<DevportalRootProps> = (props) => {\n const {\n registerNavItems,\n registerFooterItems,\n basePath = \"/developer-portal\",\n } = props;\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n };\n\n const 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 useEffect(() => {\n if (!registerNavItems) return;\n\n const navItems: NavItem[] = [\n {\n id: \"admin-devportal\",\n label: tr(\"devportal.developerPortal\", \"Developer Portal\"),\n path: basePath,\n icon: <ShieldCheck size={20} />,\n order: 70,\n group: \"globalconsole\",\n children: [\n {\n id: \"admin-devportal-reviews\",\n label: tr(\"devportal.appReviewQueue\", \"App Review Queue\"),\n path: joinPath(basePath, \"/reviews\"),\n icon: <ClipboardList size={16} />,\n order: 10,\n },\n {\n id: \"admin-devportal-verifications\",\n label: tr(\n \"devportal.verificationRequests\",\n \"Verification Requests\",\n ),\n path: joinPath(basePath, \"/verifications\"),\n icon: <BadgeCheck size={16} />,\n order: 20,\n },\n ],\n },\n ];\n\n const cleanup = registerNavItems(navItems);\n return cleanup;\n }, [registerNavItems, basePath, t]);\n\n useEffect(() => {\n if (!registerFooterItems) return;\n\n const footerItems = [\n {\n id: \"admin-devportal-version\",\n label: tr(\n \"devportal.adminDeveloperPortalReady\",\n \"Admin Developer Portal Ready\",\n ),\n type: \"status\" as const,\n order: 30,\n section: \"left\" as const,\n },\n ];\n\n const cleanup = registerFooterItems(footerItems);\n return cleanup;\n }, [registerFooterItems, t]);\n\n return (\n <ErrorBoundary\n fallback={\n <div className=\"p-6 text-center text-text-secondary\">\n Something went wrong loading this module. Please refresh the page.\n </div>\n }\n >\n <FeatureFlagProvider\n workspaceId={null}\n gateway=\"global\"\n defaultEnabled={true}\n >\n <DevportalProvider {...props} basePath={basePath}>\n <AdminDevportalRoutes />\n </DevportalProvider>\n </FeatureFlagProvider>\n </ErrorBoundary>\n );\n};\n"],"mappings":";;;;;;;;;AAsBA,IAAa,KAA8C,MAAU;CACnE,IAAM,EACJ,qBACA,wBACA,cAAW,wBACT,GACE,EAAE,SAAM,GAAS,EACjB,KAAM,GAAa,MAA6B;EACpD,IAAM,IAAQ,EAAE,EAAI;AACpB,SAAO,MAAU,IAAM,IAAW;IAG9B,KAAY,GAAc,OACZ,EAAK,SAAS,IAAI,GAAG,EAAK,MAAM,GAAG,GAAG,GAAG,MACzC,EAAK,WAAW,IAAI,GAAG,IAAO,IAAI;AA6DtD,QAzDA,QAAgB;AACT,QAiCL,QADgB,EA9BY,CAC1B;GACE,IAAI;GACJ,OAAO,EAAG,6BAA6B,mBAAmB;GAC1D,MAAM;GACN,MAAM,kBAAC,GAAD,EAAa,MAAM,IAAM,CAAA;GAC/B,OAAO;GACP,OAAO;GACP,UAAU,CACR;IACE,IAAI;IACJ,OAAO,EAAG,4BAA4B,mBAAmB;IACzD,MAAM,EAAS,GAAU,WAAW;IACpC,MAAM,kBAAC,GAAD,EAAe,MAAM,IAAM,CAAA;IACjC,OAAO;IACR,EACD;IACE,IAAI;IACJ,OAAO,EACL,kCACA,wBACD;IACD,MAAM,EAAS,GAAU,iBAAiB;IAC1C,MAAM,kBAAC,GAAD,EAAY,MAAM,IAAM,CAAA;IAC9B,OAAO;IACR,CACF;GACF,CACF,CAEyC;IAEzC;EAAC;EAAkB;EAAU;EAAE,CAAC,EAEnC,QAAgB;AACT,QAgBL,QADgB,EAbI,CAClB;GACE,IAAI;GACJ,OAAO,EACL,uCACA,+BACD;GACD,MAAM;GACN,OAAO;GACP,SAAS;GACV,CACF,CAE+C;IAE/C,CAAC,GAAqB,EAAE,CAAC,EAG1B,kBAAC,GAAD;EACE,UACE,kBAAC,OAAD;GAAK,WAAU;aAAsC;GAE/C,CAAA;YAGR,kBAAC,GAAD;GACE,aAAa;GACb,SAAQ;GACR,gBAAgB;aAEhB,kBAAC,GAAD;IAAmB,GAAI;IAAiB;cACtC,kBAAC,GAAD,EAAwB,CAAA;IACN,CAAA;GACA,CAAA;EACR,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"AdminDevportalRoutes.js","names":[],"sources":["../../src/devportal/AdminDevportalRoutes.tsx"],"sourcesContent":["import { Suspense, lazy } from \"react\";\nimport { Routes, Route, Navigate } from \"react-router-dom\";\nimport { LoadingState } from \"./components/LoadingState\";\n\nconst AdminReviewPage = lazy(() =>\n import(\"./pages/AdminReviewPage\").then((m) => ({\n default: m.AdminReviewPage,\n })),\n);\nconst AdminOrganizationVerificationPage = lazy(() =>\n import(\"./pages/AdminOrganizationVerificationPage\").then((m) => ({\n default: m.AdminOrganizationVerificationPage,\n })),\n);\n\n/**\n * Admin Developer Portal Routes\n *\n * Surfaces strictly intended for platform administrators (super_admin / admin).\n * Mounted exclusively in `admin-app`; never in user-facing shells.\n */\nfunction InnerAdminRoutes() {\n return (\n <Routes>\n <Route index element={<Navigate to=\"reviews\" replace />} />\n <Route path=\"reviews\" element={<AdminReviewPage />} />\n <Route path=\"verifications\" element={<AdminOrganizationVerificationPage />} />\n <Route path=\"*\" element={<Navigate to=\"reviews\" replace />} />\n </Routes>\n );\n}\n\nexport function AdminDevportalRoutes() {\n return (\n <Suspense fallback={<LoadingState message=\"Loading page...\" />}>\n <Routes>\n <Route path=\"/*\" element={<InnerAdminRoutes />} />\n </Routes>\n </Suspense>\n );\n}\n"],"mappings":";;;;;AAIA,IAAM,IAAkB,QACtB,OAAO,8BAA2B,MAAM,OAAO,EAC7C,SAAS,EAAE,iBACZ,EAAE,CACJ,EACK,IAAoC,QACxC,OAAO,gDAA6C,MAAM,OAAO,EAC/D,SAAS,EAAE,mCACZ,EAAE,CACJ;AAQD,SAAS,IAAmB;AAC1B,QACE,kBAAC,GAAD,EAAA,UAAA;EACE,kBAAC,GAAD;GAAO,OAAA;GAAM,SAAS,kBAAC,GAAD;IAAU,IAAG;IAAU,SAAA;IAAU,CAAA;GAAI,CAAA;EAC3D,kBAAC,GAAD;GAAO,MAAK;GAAU,SAAS,kBAAC,GAAD,EAAmB,CAAA;GAAI,CAAA;EACtD,kBAAC,GAAD;GAAO,MAAK;GAAgB,SAAS,kBAAC,GAAD,EAAqC,CAAA;GAAI,CAAA;EAC9E,kBAAC,GAAD;GAAO,MAAK;GAAI,SAAS,kBAAC,GAAD;IAAU,IAAG;IAAU,SAAA;IAAU,CAAA;GAAI,CAAA;EACvD,EAAA,CAAA;;AAIb,SAAgB,IAAuB;AACrC,QACE,kBAAC,GAAD;EAAU,UAAU,kBAAC,GAAD,EAAc,SAAQ,mBAAoB,CAAA;YAC5D,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;GAAO,MAAK;GAAK,SAAS,kBAAC,GAAD,EAAoB,CAAA;GAAI,CAAA,EAC3C,CAAA;EACA,CAAA"}
1
+ {"version":3,"file":"AdminDevportalRoutes.js","names":[],"sources":["../../src/devportal/AdminDevportalRoutes.tsx"],"sourcesContent":["import { Suspense, lazy } from \"react\";\nimport { Routes, Route, Navigate } from \"react-router-dom\";\nimport { LoadingState } from \"./components/LoadingState\";\n\nconst AdminReviewPage = lazy(() =>\n import(\"./pages/AdminReviewPage\").then((m) => ({\n default: m.AdminReviewPage,\n })),\n);\nconst AdminOrganizationVerificationPage = lazy(() =>\n import(\"./pages/AdminOrganizationVerificationPage\").then((m) => ({\n default: m.AdminOrganizationVerificationPage,\n })),\n);\n\n/**\n * Admin Developer Portal Routes\n *\n * Surfaces strictly intended for platform administrators (super_admin / admin).\n * Mounted exclusively in `admin-app`; never in user-facing shells.\n */\nfunction InnerAdminRoutes() {\n return (\n <Routes>\n <Route index element={<Navigate to=\"reviews\" replace />} />\n <Route path=\"reviews\" element={<AdminReviewPage />} />\n <Route\n path=\"verifications\"\n element={<AdminOrganizationVerificationPage />}\n />\n <Route path=\"*\" element={<Navigate to=\"reviews\" replace />} />\n </Routes>\n );\n}\n\nexport function AdminDevportalRoutes() {\n return (\n <Suspense fallback={<LoadingState message=\"Loading page...\" />}>\n <Routes>\n <Route path=\"/*\" element={<InnerAdminRoutes />} />\n </Routes>\n </Suspense>\n );\n}\n"],"mappings":";;;;;AAIA,IAAM,IAAkB,QACtB,OAAO,8BAA2B,MAAM,OAAO,EAC7C,SAAS,EAAE,iBACZ,EAAE,CACJ,EACK,IAAoC,QACxC,OAAO,gDAA6C,MAAM,OAAO,EAC/D,SAAS,EAAE,mCACZ,EAAE,CACJ;AAQD,SAAS,IAAmB;AAC1B,QACE,kBAAC,GAAD,EAAA,UAAA;EACE,kBAAC,GAAD;GAAO,OAAA;GAAM,SAAS,kBAAC,GAAD;IAAU,IAAG;IAAU,SAAA;IAAU,CAAA;GAAI,CAAA;EAC3D,kBAAC,GAAD;GAAO,MAAK;GAAU,SAAS,kBAAC,GAAD,EAAmB,CAAA;GAAI,CAAA;EACtD,kBAAC,GAAD;GACE,MAAK;GACL,SAAS,kBAAC,GAAD,EAAqC,CAAA;GAC9C,CAAA;EACF,kBAAC,GAAD;GAAO,MAAK;GAAI,SAAS,kBAAC,GAAD;IAAU,IAAG;IAAU,SAAA;IAAU,CAAA;GAAI,CAAA;EACvD,EAAA,CAAA;;AAIb,SAAgB,IAAuB;AACrC,QACE,kBAAC,GAAD;EAAU,UAAU,kBAAC,GAAD,EAAc,SAAQ,mBAAoB,CAAA;YAC5D,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;GAAO,MAAK;GAAK,SAAS,kBAAC,GAAD,EAAoB,CAAA;GAAI,CAAA,EAC3C,CAAA;EACA,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"usePackageUpload.js","names":[],"sources":["../../../src/devportal/hooks/usePackageUpload.ts"],"sourcesContent":["/**\n * usePackageUpload — uploads a zip package to wspace-files-svc and returns a\n * stable downloadUrl to store as ApplicationVersion.packageUrl.\n *\n * Flow (mirrors uploadBlobToFiles in @burdenoff/fe-libs/storage):\n * 1. ensureFolderByPath(\"/DevPortal/Packages\") → folderId\n * 2. initiateUpload → { sessionId, presignedUrl }\n * 3. PUT blob to presignedUrl (progress tracked via XHR)\n * 4. completeUpload → { file.downloadUrl }\n *\n * Uses raw fetch for GraphQL mutations so we can target the workspace gateway\n * without a second ApolloProvider.\n */\nimport { useCallback, useState } from \"react\";\n\nexport interface PackageUploadResult {\n fileId: string;\n downloadUrl: string;\n}\n\nexport interface PackageUploadState {\n uploading: boolean;\n progress: number;\n error: string | null;\n}\n\ntype GqlFetcher = (\n query: string,\n variables: Record<string, unknown>,\n) => Promise<Record<string, unknown>>;\n\nfunction makeFetcher(\n workspacesGatewayUrl: string,\n authToken: string | undefined,\n workspaceId: string | undefined,\n workspaceToken: string | undefined,\n): GqlFetcher {\n return async (query, variables) => {\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n if (authToken) headers[\"Authorization\"] = `Bearer ${authToken}`;\n if (workspaceToken)\n headers[\"X-Workspace-Authorization\"] = `Bearer ${workspaceToken}`;\n if (workspaceId) headers[\"x-workspace-id\"] = workspaceId;\n\n const endpoint = workspacesGatewayUrl.endsWith(\"/graphql\")\n ? workspacesGatewayUrl\n : `${workspacesGatewayUrl}/workspaces/graphql`;\n\n const res = await fetch(endpoint, {\n method: \"POST\",\n headers,\n credentials: \"include\",\n body: JSON.stringify({ query, variables }),\n });\n if (!res.ok) {\n throw new Error(\n `GraphQL request failed: ${res.status} ${res.statusText}`,\n );\n }\n const json = (await res.json()) as {\n data?: Record<string, unknown>;\n errors?: Array<{ message: string }>;\n };\n if (json.errors?.length) {\n throw new Error(json.errors.map((e) => e.message).join(\"; \"));\n }\n return json.data ?? {};\n };\n}\n\nasync function ensureFolder(gql: GqlFetcher, path: string): Promise<string> {\n const data = await gql(\n `mutation DevPortal_EnsureFolder($path: String!) {\n ensureFolderByPath(path: $path) { id }\n }`,\n { path },\n );\n const id = (data.ensureFolderByPath as { id?: string } | undefined)?.id;\n if (!id) throw new Error(\"ensureFolderByPath returned no id\");\n return id;\n}\n\nasync function initiateUpload(\n gql: GqlFetcher,\n file: File,\n folderId: string,\n): Promise<{ sessionId: string; uploadUrl: string }> {\n const ext = file.name.includes(\".\")\n ? file.name.substring(file.name.lastIndexOf(\".\") + 1)\n : \"zip\";\n const data = await gql(\n `mutation DevPortal_InitiateUpload($input: InitiateUploadInput!) {\n initiateUpload(input: $input) {\n uploadUrl\n session { id }\n }\n }`,\n {\n input: {\n fileName: file.name,\n fileSize: String(file.size),\n mimeType: file.type || \"application/zip\",\n extension: ext,\n folderId,\n visibility: \"PUBLIC\",\n },\n },\n );\n const result = data.initiateUpload as\n | { uploadUrl?: string; session?: { id?: string } }\n | undefined;\n const sessionId = result?.session?.id;\n const uploadUrl = result?.uploadUrl;\n if (!sessionId || !uploadUrl) {\n throw new Error(\"initiateUpload did not return sessionId or uploadUrl\");\n }\n return { sessionId, uploadUrl };\n}\n\nasync function putToPresignedUrl(\n file: File,\n uploadUrl: string,\n onProgress: (pct: number) => void,\n): Promise<void> {\n await new Promise<void>((resolve, reject) => {\n const xhr = new XMLHttpRequest();\n xhr.upload.addEventListener(\"progress\", (evt) => {\n if (evt.lengthComputable) {\n onProgress(10 + Math.round((evt.loaded / evt.total) * 80));\n }\n });\n xhr.addEventListener(\"load\", () => {\n if (xhr.status >= 200 && xhr.status < 300) {\n resolve();\n } else {\n reject(new Error(`S3 PUT failed: ${xhr.status}`));\n }\n });\n xhr.addEventListener(\"error\", () =>\n reject(new Error(\"S3 PUT network error\")),\n );\n xhr.addEventListener(\"abort\", () => reject(new Error(\"S3 PUT aborted\")));\n xhr.open(\"PUT\", uploadUrl);\n xhr.setRequestHeader(\"Content-Type\", file.type || \"application/zip\");\n xhr.send(file);\n });\n}\n\nasync function completeUpload(\n gql: GqlFetcher,\n sessionId: string,\n folderId: string,\n fileSize: number,\n): Promise<PackageUploadResult> {\n const data = await gql(\n `mutation DevPortal_CompleteUpload($input: CompleteUploadInput!) {\n completeUpload(input: $input) {\n file { id downloadUrl }\n }\n }`,\n {\n input: {\n sessionId,\n folderId,\n fileSize: String(fileSize),\n },\n },\n );\n const file = (\n data.completeUpload as\n | { file?: { id?: string; downloadUrl?: string } }\n | undefined\n )?.file;\n if (!file?.id || !file.downloadUrl) {\n throw new Error(\"completeUpload did not return file id or downloadUrl\");\n }\n return { fileId: file.id, downloadUrl: file.downloadUrl };\n}\n\nexport function usePackageUpload(\n workspacesGatewayUrl: string | undefined,\n authToken: string | undefined,\n workspaceId: string | undefined,\n getWorkspaceToken: (() => Promise<string | null>) | undefined,\n folderPath = \"/DevPortal/Packages\",\n) {\n const [state, setState] = useState<PackageUploadState>({\n uploading: false,\n progress: 0,\n error: null,\n });\n\n const upload = useCallback(\n async (file: File): Promise<PackageUploadResult> => {\n if (!workspacesGatewayUrl) {\n throw new Error(\n \"workspacesGatewayUrl is not configured. Pass it as a prop to DevportalRoot.\",\n );\n }\n\n const freshToken = getWorkspaceToken\n ? await getWorkspaceToken()\n : undefined;\n const gql = makeFetcher(\n workspacesGatewayUrl,\n authToken,\n workspaceId,\n freshToken ?? undefined,\n );\n\n setState({ uploading: true, progress: 0, error: null });\n try {\n const folderId = await ensureFolder(gql, folderPath);\n setState((s) => ({ ...s, progress: 5 }));\n\n const { sessionId, uploadUrl } = await initiateUpload(\n gql,\n file,\n folderId,\n );\n setState((s) => ({ ...s, progress: 10 }));\n\n await putToPresignedUrl(file, uploadUrl, (pct) =>\n setState((s) => ({ ...s, progress: pct })),\n );\n setState((s) => ({ ...s, progress: 90 }));\n\n const result = await completeUpload(\n gql,\n sessionId,\n folderId,\n file.size,\n );\n setState({ uploading: false, progress: 100, error: null });\n return result;\n } catch (err) {\n const message = err instanceof Error ? err.message : \"Upload failed\";\n setState({ uploading: false, progress: 0, error: message });\n throw err;\n }\n },\n [workspacesGatewayUrl, authToken, workspaceId, getWorkspaceToken],\n );\n\n return { upload, ...state };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"usePackageUpload.js","names":[],"sources":["../../../src/devportal/hooks/usePackageUpload.ts"],"sourcesContent":["/**\n * usePackageUpload — uploads a zip package to wspace-files-svc and returns a\n * stable downloadUrl to store as ApplicationVersion.packageUrl.\n *\n * Flow (mirrors uploadBlobToFiles in @burdenoff/fe-libs/storage):\n * 1. ensureFolderByPath(\"/DevPortal/Packages\") → folderId\n * 2. initiateUpload → { sessionId, presignedUrl }\n * 3. PUT blob to presignedUrl (progress tracked via XHR)\n * 4. completeUpload → { file.downloadUrl }\n *\n * Uses raw fetch for GraphQL mutations so we can target the workspace gateway\n * without a second ApolloProvider.\n */\nimport { useCallback, useState } from \"react\";\n\nexport interface PackageUploadResult {\n fileId: string;\n downloadUrl: string;\n}\n\nexport interface PackageUploadState {\n uploading: boolean;\n progress: number;\n error: string | null;\n}\n\ntype GqlFetcher = (\n query: string,\n variables: Record<string, unknown>,\n) => Promise<Record<string, unknown>>;\n\nfunction makeFetcher(\n workspacesGatewayUrl: string,\n authToken: string | undefined,\n workspaceId: string | undefined,\n workspaceToken: string | undefined,\n): GqlFetcher {\n return async (query, variables) => {\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n if (authToken) headers[\"Authorization\"] = `Bearer ${authToken}`;\n if (workspaceToken)\n headers[\"X-Workspace-Authorization\"] = `Bearer ${workspaceToken}`;\n if (workspaceId) headers[\"x-workspace-id\"] = workspaceId;\n\n const endpoint = workspacesGatewayUrl.endsWith(\"/graphql\")\n ? workspacesGatewayUrl\n : `${workspacesGatewayUrl}/workspaces/graphql`;\n\n const res = await fetch(endpoint, {\n method: \"POST\",\n headers,\n credentials: \"include\",\n body: JSON.stringify({ query, variables }),\n });\n if (!res.ok) {\n throw new Error(\n `GraphQL request failed: ${res.status} ${res.statusText}`,\n );\n }\n const json = (await res.json()) as {\n data?: Record<string, unknown>;\n errors?: Array<{ message: string }>;\n };\n if (json.errors?.length) {\n throw new Error(json.errors.map((e) => e.message).join(\"; \"));\n }\n return json.data ?? {};\n };\n}\n\nasync function ensureFolder(gql: GqlFetcher, path: string): Promise<string> {\n const data = await gql(\n `mutation DevPortal_EnsureFolder($path: String!) {\n ensureFolderByPath(path: $path) { id }\n }`,\n { path },\n );\n const id = (data.ensureFolderByPath as { id?: string } | undefined)?.id;\n if (!id) throw new Error(\"ensureFolderByPath returned no id\");\n return id;\n}\n\nasync function initiateUpload(\n gql: GqlFetcher,\n file: File,\n folderId: string,\n): Promise<{ sessionId: string; uploadUrl: string }> {\n const ext = file.name.includes(\".\")\n ? file.name.substring(file.name.lastIndexOf(\".\") + 1)\n : \"zip\";\n const data = await gql(\n `mutation DevPortal_InitiateUpload($input: InitiateUploadInput!) {\n initiateUpload(input: $input) {\n uploadUrl\n session { id }\n }\n }`,\n {\n input: {\n fileName: file.name,\n fileSize: String(file.size),\n mimeType: file.type || \"application/zip\",\n extension: ext,\n folderId,\n visibility: \"PUBLIC\",\n },\n },\n );\n const result = data.initiateUpload as\n { uploadUrl?: string; session?: { id?: string } } | undefined;\n const sessionId = result?.session?.id;\n const uploadUrl = result?.uploadUrl;\n if (!sessionId || !uploadUrl) {\n throw new Error(\"initiateUpload did not return sessionId or uploadUrl\");\n }\n return { sessionId, uploadUrl };\n}\n\nasync function putToPresignedUrl(\n file: File,\n uploadUrl: string,\n onProgress: (pct: number) => void,\n): Promise<void> {\n await new Promise<void>((resolve, reject) => {\n const xhr = new XMLHttpRequest();\n xhr.upload.addEventListener(\"progress\", (evt) => {\n if (evt.lengthComputable) {\n onProgress(10 + Math.round((evt.loaded / evt.total) * 80));\n }\n });\n xhr.addEventListener(\"load\", () => {\n if (xhr.status >= 200 && xhr.status < 300) {\n resolve();\n } else {\n reject(new Error(`S3 PUT failed: ${xhr.status}`));\n }\n });\n xhr.addEventListener(\"error\", () =>\n reject(new Error(\"S3 PUT network error\")),\n );\n xhr.addEventListener(\"abort\", () => reject(new Error(\"S3 PUT aborted\")));\n xhr.open(\"PUT\", uploadUrl);\n xhr.setRequestHeader(\"Content-Type\", file.type || \"application/zip\");\n xhr.send(file);\n });\n}\n\nasync function completeUpload(\n gql: GqlFetcher,\n sessionId: string,\n folderId: string,\n fileSize: number,\n): Promise<PackageUploadResult> {\n const data = await gql(\n `mutation DevPortal_CompleteUpload($input: CompleteUploadInput!) {\n completeUpload(input: $input) {\n file { id downloadUrl }\n }\n }`,\n {\n input: {\n sessionId,\n folderId,\n fileSize: String(fileSize),\n },\n },\n );\n const file = (\n data.completeUpload as\n { file?: { id?: string; downloadUrl?: string } } | undefined\n )?.file;\n if (!file?.id || !file.downloadUrl) {\n throw new Error(\"completeUpload did not return file id or downloadUrl\");\n }\n return { fileId: file.id, downloadUrl: file.downloadUrl };\n}\n\nexport function usePackageUpload(\n workspacesGatewayUrl: string | undefined,\n authToken: string | undefined,\n workspaceId: string | undefined,\n getWorkspaceToken: (() => Promise<string | null>) | undefined,\n folderPath = \"/DevPortal/Packages\",\n) {\n const [state, setState] = useState<PackageUploadState>({\n uploading: false,\n progress: 0,\n error: null,\n });\n\n const upload = useCallback(\n async (file: File): Promise<PackageUploadResult> => {\n if (!workspacesGatewayUrl) {\n throw new Error(\n \"workspacesGatewayUrl is not configured. Pass it as a prop to DevportalRoot.\",\n );\n }\n\n const freshToken = getWorkspaceToken\n ? await getWorkspaceToken()\n : undefined;\n const gql = makeFetcher(\n workspacesGatewayUrl,\n authToken,\n workspaceId,\n freshToken ?? undefined,\n );\n\n setState({ uploading: true, progress: 0, error: null });\n try {\n const folderId = await ensureFolder(gql, folderPath);\n setState((s) => ({ ...s, progress: 5 }));\n\n const { sessionId, uploadUrl } = await initiateUpload(\n gql,\n file,\n folderId,\n );\n setState((s) => ({ ...s, progress: 10 }));\n\n await putToPresignedUrl(file, uploadUrl, (pct) =>\n setState((s) => ({ ...s, progress: pct })),\n );\n setState((s) => ({ ...s, progress: 90 }));\n\n const result = await completeUpload(\n gql,\n sessionId,\n folderId,\n file.size,\n );\n setState({ uploading: false, progress: 100, error: null });\n return result;\n } catch (err) {\n const message = err instanceof Error ? err.message : \"Upload failed\";\n setState({ uploading: false, progress: 0, error: message });\n throw err;\n }\n },\n [workspacesGatewayUrl, authToken, workspaceId, getWorkspaceToken],\n );\n\n return { upload, ...state };\n}\n"],"mappings":"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"}
@@ -98,7 +98,11 @@ var h = "\n query PendingDeveloperOrganizationVerifications($limit: Int, $offse
98
98
  className: "text-sm text-text-secondary",
99
99
  children: [
100
100
  /* @__PURE__ */ p("div", { children: ["Method: ", N.verificationMethod || "manual"] }),
101
- /* @__PURE__ */ p("div", { children: ["Requested: ", N.verificationRequestedAt ? new Date(N.verificationRequestedAt).toLocaleString() : "-"] }),
101
+ /* @__PURE__ */ p("div", { children: [
102
+ "Requested:",
103
+ " ",
104
+ N.verificationRequestedAt ? new Date(N.verificationRequestedAt).toLocaleString() : "-"
105
+ ] }),
102
106
  N.contactEmail && /* @__PURE__ */ p("div", { children: ["Contact email: ", N.contactEmail] }),
103
107
  N.supportEmail && /* @__PURE__ */ p("div", { children: ["Support email: ", N.supportEmail] }),
104
108
  N.websiteUrl && /* @__PURE__ */ p("div", { children: ["Website: ", N.websiteUrl] }),
@@ -1 +1 @@
1
- {"version":3,"file":"AdminOrganizationVerificationPage.js","names":[],"sources":["../../../src/devportal/pages/AdminOrganizationVerificationPage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport { CheckCircle, Loader2, ShieldAlert, XCircle } from \"lucide-react\";\n\nimport { graphqlFetch } from \"@burdenoff/fe-libs/shared/graphql\";\nimport { EmptyState } from \"../components/EmptyState\";\nimport { TextareaField } from \"../components/FormField\";\nimport { DataTable } from \"../components/DataTable\";\nimport { PageLayout, PageSection } from \"../components/PageLayout\";\n\nconst PENDING_QUERY = `\n query PendingDeveloperOrganizationVerifications($limit: Int, $offset: Int) {\n pendingDeveloperOrganizationVerifications(limit: $limit, offset: $offset) {\n totalCount\n edges {\n node {\n id\n name\n slug\n contactEmail\n supportEmail\n websiteUrl\n legalEntityName\n legalEntityType\n taxId\n taxCountry\n verificationMethod\n verificationRequestedAt\n verificationRequestNotes\n verificationEvidenceUrl\n verificationDomain\n }\n }\n }\n }\n`;\n\nconst APPROVE_MUTATION = `\n mutation ApproveDeveloperOrganizationVerification($id: ID!, $notes: String) {\n approveDeveloperOrganizationVerification(id: $id, notes: $notes) {\n id\n }\n }\n`;\n\nconst REJECT_MUTATION = `\n mutation RejectDeveloperOrganizationVerification(\n $id: ID!\n $reason: String!\n $notes: String\n ) {\n rejectDeveloperOrganizationVerification(id: $id, reason: $reason, notes: $notes) {\n id\n }\n }\n`;\n\ninterface Row {\n id: string;\n name: string;\n slug: string;\n contactEmail?: string | null;\n supportEmail?: string | null;\n websiteUrl?: string | null;\n legalEntityName?: string | null;\n legalEntityType?: string | null;\n taxId?: string | null;\n taxCountry?: string | null;\n verificationMethod?: string | null;\n verificationRequestedAt?: string | null;\n verificationRequestNotes?: string | null;\n verificationEvidenceUrl?: string | null;\n verificationDomain?: string | null;\n}\n\nexport const AdminOrganizationVerificationPage: FC = () => {\n const [rows, setRows] = useState<Row[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [selectedId, setSelectedId] = useState<string | null>(null);\n const [notes, setNotes] = useState(\"\");\n const [reason, setReason] = useState(\"\");\n const [saving, setSaving] = useState(false);\n\n const load = async () => {\n setLoading(true);\n setError(null);\n try {\n const result = await graphqlFetch<{\n pendingDeveloperOrganizationVerifications: {\n edges: Array<{ node: Row }>;\n };\n }>({\n gateway: \"global\",\n query: PENDING_QUERY,\n variables: { limit: 50, offset: 0 },\n });\n setRows(\n result.data?.pendingDeveloperOrganizationVerifications?.edges?.map(\n (edge) => edge.node,\n ) ?? [],\n );\n } catch (err) {\n setError(err instanceof Error ? err.message : \"Failed to load verification requests\");\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n void load();\n }, []);\n\n const selected = useMemo(() => rows.find((row) => row.id === selectedId) ?? null, [rows, selectedId]);\n\n return (\n <PageLayout\n title=\"Organization Verification Requests\"\n description=\"Review pending organization verification requests, inspect the submitted evidence, and approve or reject them.\"\n >\n <PageSection title=\"Pending Requests\">\n {loading ? (\n <div className=\"flex items-center justify-center py-12\">\n <Loader2 className=\"h-8 w-8 animate-spin text-text-secondary\" />\n </div>\n ) : error ? (\n <EmptyState\n icon={<ShieldAlert size={32} className=\"text-status-error-text\" />}\n title=\"Unable to load verification requests\"\n description={error}\n />\n ) : rows.length === 0 ? (\n <EmptyState\n icon={<CheckCircle size={32} className=\"text-status-success-text\" />}\n title=\"No pending verification requests\"\n description=\"Organization verification requests will appear here once developers submit them.\"\n />\n ) : (\n <DataTable\n data={rows}\n keyField=\"id\"\n columns={[\n { key: \"name\", header: \"Organization\", render: (row) => row.name },\n { key: \"method\", header: \"Method\", render: (row) => row.verificationMethod || \"manual\" },\n {\n key: \"requested\",\n header: \"Requested\",\n render: (row) => row.verificationRequestedAt ? new Date(row.verificationRequestedAt).toLocaleString() : \"-\",\n },\n {\n key: \"details\",\n header: \"Details\",\n render: (row) => row.verificationDomain || row.verificationEvidenceUrl || row.verificationRequestNotes || row.legalEntityName || \"-\",\n },\n {\n key: \"actions\",\n header: \"Actions\",\n render: (row) => (\n <button\n type=\"button\"\n onClick={() => {\n setSelectedId(row.id);\n setNotes(\"\");\n setReason(\"\");\n }}\n className=\"rounded-md border border-border-subtle px-3 py-1 text-xs font-medium hover:bg-bg-sunken\"\n >\n Review\n </button>\n ),\n },\n ]}\n />\n )}\n </PageSection>\n\n {selected && (\n <PageSection title={`Review · ${selected.name}`}>\n <div className=\"space-y-4 rounded-lg border border-border-subtle p-4\">\n <div className=\"text-sm text-text-secondary\">\n <div>Method: {selected.verificationMethod || \"manual\"}</div>\n <div>Requested: {selected.verificationRequestedAt ? new Date(selected.verificationRequestedAt).toLocaleString() : \"-\"}</div>\n {selected.contactEmail && <div>Contact email: {selected.contactEmail}</div>}\n {selected.supportEmail && <div>Support email: {selected.supportEmail}</div>}\n {selected.websiteUrl && <div>Website: {selected.websiteUrl}</div>}\n {selected.legalEntityName && <div>Legal entity: {selected.legalEntityName}</div>}\n {selected.legalEntityType && <div>Entity type: {selected.legalEntityType}</div>}\n {selected.taxId && <div>Tax ID: {selected.taxId}</div>}\n {selected.taxCountry && <div>Tax country: {selected.taxCountry}</div>}\n {selected.verificationDomain && <div>Domain: {selected.verificationDomain}</div>}\n {selected.verificationEvidenceUrl && <div>Evidence: {selected.verificationEvidenceUrl}</div>}\n {selected.verificationRequestNotes && <div>Notes: {selected.verificationRequestNotes}</div>}\n </div>\n\n <TextareaField label=\"Reviewer notes\" value={notes} onChange={(e) => setNotes(e.target.value)} placeholder=\"What did you verify?\" />\n <TextareaField label=\"Rejection reason\" value={reason} onChange={(e) => setReason(e.target.value)} placeholder=\"Why are you rejecting this request?\" />\n\n <div className=\"flex gap-3\">\n <button\n type=\"button\"\n disabled={saving}\n onClick={async () => {\n setSaving(true);\n await graphqlFetch({\n gateway: \"global\",\n query: APPROVE_MUTATION,\n variables: { id: selected.id, notes: notes || null },\n });\n setSaving(false);\n setSelectedId(null);\n await load();\n }}\n className=\"inline-flex items-center gap-2 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text disabled:opacity-50\"\n >\n <CheckCircle size={14} /> Approve\n </button>\n <button\n type=\"button\"\n disabled={saving || !reason.trim()}\n onClick={async () => {\n setSaving(true);\n await graphqlFetch({\n gateway: \"global\",\n query: REJECT_MUTATION,\n variables: { id: selected.id, reason, notes: notes || null },\n });\n setSaving(false);\n setSelectedId(null);\n await load();\n }}\n className=\"inline-flex items-center gap-2 rounded-md border border-status-error-border px-4 py-2 text-sm font-medium text-status-error-text disabled:opacity-50\"\n >\n <XCircle size={14} /> Reject\n </button>\n </div>\n </div>\n </PageSection>\n )}\n </PageLayout>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"AdminOrganizationVerificationPage.js","names":[],"sources":["../../../src/devportal/pages/AdminOrganizationVerificationPage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport { CheckCircle, Loader2, ShieldAlert, XCircle } from \"lucide-react\";\n\nimport { graphqlFetch } from \"@burdenoff/fe-libs/shared/graphql\";\nimport { EmptyState } from \"../components/EmptyState\";\nimport { TextareaField } from \"../components/FormField\";\nimport { DataTable } from \"../components/DataTable\";\nimport { PageLayout, PageSection } from \"../components/PageLayout\";\n\nconst PENDING_QUERY = `\n query PendingDeveloperOrganizationVerifications($limit: Int, $offset: Int) {\n pendingDeveloperOrganizationVerifications(limit: $limit, offset: $offset) {\n totalCount\n edges {\n node {\n id\n name\n slug\n contactEmail\n supportEmail\n websiteUrl\n legalEntityName\n legalEntityType\n taxId\n taxCountry\n verificationMethod\n verificationRequestedAt\n verificationRequestNotes\n verificationEvidenceUrl\n verificationDomain\n }\n }\n }\n }\n`;\n\nconst APPROVE_MUTATION = `\n mutation ApproveDeveloperOrganizationVerification($id: ID!, $notes: String) {\n approveDeveloperOrganizationVerification(id: $id, notes: $notes) {\n id\n }\n }\n`;\n\nconst REJECT_MUTATION = `\n mutation RejectDeveloperOrganizationVerification(\n $id: ID!\n $reason: String!\n $notes: String\n ) {\n rejectDeveloperOrganizationVerification(id: $id, reason: $reason, notes: $notes) {\n id\n }\n }\n`;\n\ninterface Row {\n id: string;\n name: string;\n slug: string;\n contactEmail?: string | null;\n supportEmail?: string | null;\n websiteUrl?: string | null;\n legalEntityName?: string | null;\n legalEntityType?: string | null;\n taxId?: string | null;\n taxCountry?: string | null;\n verificationMethod?: string | null;\n verificationRequestedAt?: string | null;\n verificationRequestNotes?: string | null;\n verificationEvidenceUrl?: string | null;\n verificationDomain?: string | null;\n}\n\nexport const AdminOrganizationVerificationPage: FC = () => {\n const [rows, setRows] = useState<Row[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [selectedId, setSelectedId] = useState<string | null>(null);\n const [notes, setNotes] = useState(\"\");\n const [reason, setReason] = useState(\"\");\n const [saving, setSaving] = useState(false);\n\n const load = async () => {\n setLoading(true);\n setError(null);\n try {\n const result = await graphqlFetch<{\n pendingDeveloperOrganizationVerifications: {\n edges: Array<{ node: Row }>;\n };\n }>({\n gateway: \"global\",\n query: PENDING_QUERY,\n variables: { limit: 50, offset: 0 },\n });\n setRows(\n result.data?.pendingDeveloperOrganizationVerifications?.edges?.map(\n (edge) => edge.node,\n ) ?? [],\n );\n } catch (err) {\n setError(\n err instanceof Error\n ? err.message\n : \"Failed to load verification requests\",\n );\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n void load();\n }, []);\n\n const selected = useMemo(\n () => rows.find((row) => row.id === selectedId) ?? null,\n [rows, selectedId],\n );\n\n return (\n <PageLayout\n title=\"Organization Verification Requests\"\n description=\"Review pending organization verification requests, inspect the submitted evidence, and approve or reject them.\"\n >\n <PageSection title=\"Pending Requests\">\n {loading ? (\n <div className=\"flex items-center justify-center py-12\">\n <Loader2 className=\"h-8 w-8 animate-spin text-text-secondary\" />\n </div>\n ) : error ? (\n <EmptyState\n icon={<ShieldAlert size={32} className=\"text-status-error-text\" />}\n title=\"Unable to load verification requests\"\n description={error}\n />\n ) : rows.length === 0 ? (\n <EmptyState\n icon={\n <CheckCircle size={32} className=\"text-status-success-text\" />\n }\n title=\"No pending verification requests\"\n description=\"Organization verification requests will appear here once developers submit them.\"\n />\n ) : (\n <DataTable\n data={rows}\n keyField=\"id\"\n columns={[\n {\n key: \"name\",\n header: \"Organization\",\n render: (row) => row.name,\n },\n {\n key: \"method\",\n header: \"Method\",\n render: (row) => row.verificationMethod || \"manual\",\n },\n {\n key: \"requested\",\n header: \"Requested\",\n render: (row) =>\n row.verificationRequestedAt\n ? new Date(row.verificationRequestedAt).toLocaleString()\n : \"-\",\n },\n {\n key: \"details\",\n header: \"Details\",\n render: (row) =>\n row.verificationDomain ||\n row.verificationEvidenceUrl ||\n row.verificationRequestNotes ||\n row.legalEntityName ||\n \"-\",\n },\n {\n key: \"actions\",\n header: \"Actions\",\n render: (row) => (\n <button\n type=\"button\"\n onClick={() => {\n setSelectedId(row.id);\n setNotes(\"\");\n setReason(\"\");\n }}\n className=\"rounded-md border border-border-subtle px-3 py-1 text-xs font-medium hover:bg-bg-sunken\"\n >\n Review\n </button>\n ),\n },\n ]}\n />\n )}\n </PageSection>\n\n {selected && (\n <PageSection title={`Review · ${selected.name}`}>\n <div className=\"space-y-4 rounded-lg border border-border-subtle p-4\">\n <div className=\"text-sm text-text-secondary\">\n <div>Method: {selected.verificationMethod || \"manual\"}</div>\n <div>\n Requested:{\" \"}\n {selected.verificationRequestedAt\n ? new Date(selected.verificationRequestedAt).toLocaleString()\n : \"-\"}\n </div>\n {selected.contactEmail && (\n <div>Contact email: {selected.contactEmail}</div>\n )}\n {selected.supportEmail && (\n <div>Support email: {selected.supportEmail}</div>\n )}\n {selected.websiteUrl && <div>Website: {selected.websiteUrl}</div>}\n {selected.legalEntityName && (\n <div>Legal entity: {selected.legalEntityName}</div>\n )}\n {selected.legalEntityType && (\n <div>Entity type: {selected.legalEntityType}</div>\n )}\n {selected.taxId && <div>Tax ID: {selected.taxId}</div>}\n {selected.taxCountry && (\n <div>Tax country: {selected.taxCountry}</div>\n )}\n {selected.verificationDomain && (\n <div>Domain: {selected.verificationDomain}</div>\n )}\n {selected.verificationEvidenceUrl && (\n <div>Evidence: {selected.verificationEvidenceUrl}</div>\n )}\n {selected.verificationRequestNotes && (\n <div>Notes: {selected.verificationRequestNotes}</div>\n )}\n </div>\n\n <TextareaField\n label=\"Reviewer notes\"\n value={notes}\n onChange={(e) => setNotes(e.target.value)}\n placeholder=\"What did you verify?\"\n />\n <TextareaField\n label=\"Rejection reason\"\n value={reason}\n onChange={(e) => setReason(e.target.value)}\n placeholder=\"Why are you rejecting this request?\"\n />\n\n <div className=\"flex gap-3\">\n <button\n type=\"button\"\n disabled={saving}\n onClick={async () => {\n setSaving(true);\n await graphqlFetch({\n gateway: \"global\",\n query: APPROVE_MUTATION,\n variables: { id: selected.id, notes: notes || null },\n });\n setSaving(false);\n setSelectedId(null);\n await load();\n }}\n className=\"inline-flex items-center gap-2 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text disabled:opacity-50\"\n >\n <CheckCircle size={14} /> Approve\n </button>\n <button\n type=\"button\"\n disabled={saving || !reason.trim()}\n onClick={async () => {\n setSaving(true);\n await graphqlFetch({\n gateway: \"global\",\n query: REJECT_MUTATION,\n variables: {\n id: selected.id,\n reason,\n notes: notes || null,\n },\n });\n setSaving(false);\n setSelectedId(null);\n await load();\n }}\n className=\"inline-flex items-center gap-2 rounded-md border border-status-error-border px-4 py-2 text-sm font-medium text-status-error-text disabled:opacity-50\"\n >\n <XCircle size={14} /> Reject\n </button>\n </div>\n </div>\n </PageSection>\n )}\n </PageLayout>\n );\n};\n"],"mappings":"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"}