@burdenoff/microfe-devportal 2026.1113.1 → 2026.1113.3

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 (55) hide show
  1. package/dist/devportal/DevportalRoot.js +65 -119
  2. package/dist/devportal/DevportalRoot.js.map +1 -1
  3. package/dist/devportal/components/AppCard.js +4 -4
  4. package/dist/devportal/components/DeveloperSettingsHub.d.ts +6 -0
  5. package/dist/devportal/components/DeveloperSettingsHub.js +59 -0
  6. package/dist/devportal/components/DeveloperSettingsHub.js.map +1 -0
  7. package/dist/devportal/components/SectionNav.d.ts +1 -1
  8. package/dist/devportal/components/SectionNav.js +60 -36
  9. package/dist/devportal/components/SectionNav.js.map +1 -1
  10. package/dist/devportal/pages/AnalyticsDashboardPage.js +186 -179
  11. package/dist/devportal/pages/AnalyticsDashboardPage.js.map +1 -1
  12. package/dist/devportal/pages/ApiKeysPage.js +113 -111
  13. package/dist/devportal/pages/ApiKeysPage.js.map +1 -1
  14. package/dist/devportal/pages/AppLogsPage.js +80 -84
  15. package/dist/devportal/pages/AppLogsPage.js.map +1 -1
  16. package/dist/devportal/pages/ApplicationDetailPage.js +529 -504
  17. package/dist/devportal/pages/ApplicationDetailPage.js.map +1 -1
  18. package/dist/devportal/pages/ApplicationsPage.js +68 -67
  19. package/dist/devportal/pages/ApplicationsPage.js.map +1 -1
  20. package/dist/devportal/pages/CreateApiKeyPage.js +163 -166
  21. package/dist/devportal/pages/CreateApiKeyPage.js.map +1 -1
  22. package/dist/devportal/pages/CreateOAuthClientPage.js +134 -130
  23. package/dist/devportal/pages/CreateOAuthClientPage.js.map +1 -1
  24. package/dist/devportal/pages/DelegationsPage.js +11 -11
  25. package/dist/devportal/pages/DocumentationPage.js +100 -94
  26. package/dist/devportal/pages/DocumentationPage.js.map +1 -1
  27. package/dist/devportal/pages/EditApplicationPage.js +379 -377
  28. package/dist/devportal/pages/EditApplicationPage.js.map +1 -1
  29. package/dist/devportal/pages/InvitationDecisionPage.js +83 -79
  30. package/dist/devportal/pages/InvitationDecisionPage.js.map +1 -1
  31. package/dist/devportal/pages/OAuthClientDetailPage.js +76 -76
  32. package/dist/devportal/pages/OAuthClientDetailPage.js.map +1 -1
  33. package/dist/devportal/pages/OAuthClientsPage.js +126 -124
  34. package/dist/devportal/pages/OAuthClientsPage.js.map +1 -1
  35. package/dist/devportal/pages/OrganizationDetailPage.js +19 -19
  36. package/dist/devportal/pages/OrganizationMembersPage.js +223 -204
  37. package/dist/devportal/pages/OrganizationMembersPage.js.map +1 -1
  38. package/dist/devportal/pages/ResourcesPage.d.ts +6 -0
  39. package/dist/devportal/pages/ResourcesPage.js +171 -155
  40. package/dist/devportal/pages/ResourcesPage.js.map +1 -1
  41. package/dist/devportal/pages/SellerDashboardPage.js +13 -13
  42. package/dist/devportal/pages/SellerItemsPage.js +4 -4
  43. package/dist/devportal/pages/SettingsPage.js +330 -315
  44. package/dist/devportal/pages/SettingsPage.js.map +1 -1
  45. package/dist/devportal/pages/SetupPage.js +5 -5
  46. package/dist/devportal/pages/WebhookDetailPage.js +6 -6
  47. package/dist/devportal/pages/WebhooksPage.js +39 -39
  48. package/dist/devportal/pages/WebhooksPage.js.map +1 -1
  49. package/dist/devportal/utils/appDetailTabs.d.ts +73 -0
  50. package/dist/devportal/utils/appDetailTabs.js +62 -0
  51. package/dist/devportal/utils/appDetailTabs.js.map +1 -0
  52. package/dist/devportal/utils/developerNav.d.ts +39 -0
  53. package/dist/devportal/utils/developerNav.js +304 -0
  54. package/dist/devportal/utils/developerNav.js.map +1 -0
  55. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"SettingsPage.js","names":["EmptyState","EmptyState$1","formatDate","value","neverLabel","parsed","SettingsPage","useDevportal","tr","useTr","useGetDeveloperPortalSettingsOverviewQuery","handleNavigate","basePath","path","title","description","loading","data","PageLayout","Loader2","error","AlertCircle","getErrorMessage","profile","organizations","org","apiKeys","totalApiKeyCount","latestApiKey","totalRevenue","sum","organization","PageSection","EmphasisPanel","UserCircle2","VerifiedBadge","Settings","KeyRound","Workflow","Building2","ExternalLink","Webhook","Shield","Mail"],"sources":["../../../src/devportal/pages/SettingsPage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport {\n Building2,\n ExternalLink,\n KeyRound,\n Mail,\n Settings,\n Shield,\n UserCircle2,\n Webhook,\n Workflow,\n Loader2,\n AlertCircle,\n} from \"lucide-react\";\nimport { EmphasisPanel } from \"@burdenoff/fe-libs/ui\";\nimport { PageLayout, PageSection } from \"../components/PageLayout\";\nimport { EmptyState } from \"../components/EmptyState\";\nimport { VerifiedBadge } from \"../components/StatusBadge\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport {\n getErrorMessage,\n useGetDeveloperPortalSettingsOverviewQuery,\n} from \"../hooks\";\nimport { useTr } from \"../utils/i18n\";\n\nconst formatDate = (\n value: string | null | undefined,\n neverLabel: string,\n): string => {\n if (!value) return neverLabel;\n\n const parsed = new Date(value);\n if (Number.isNaN(parsed.getTime())) return neverLabel;\n\n return parsed.toLocaleDateString();\n};\n\nexport const SettingsPage: FC = () => {\n const { navigate, basePath } = useDevportal();\n const tr = useTr();\n const { data, loading, error } = useGetDeveloperPortalSettingsOverviewQuery({\n fetchPolicy: \"cache-and-network\",\n });\n\n const handleNavigate = (path: string) => {\n navigate?.(`${basePath}${path}`);\n };\n\n const neverLabel = tr(\"devportal.settings.never\", \"Never\");\n const title = tr(\"devportal.settings.title\", \"Settings\");\n const description = tr(\n \"devportal.settings.description\",\n \"Review your developer portal account, credentials, and support options\",\n );\n\n if (loading && !data) {\n return (\n <PageLayout title={title} description={description}>\n <div\n className=\"flex items-center justify-center py-16 text-text-secondary\"\n role=\"status\"\n aria-live=\"polite\"\n aria-label={tr(\"devportal.common.loading\", \"Loading\")}\n >\n <Loader2 className=\"h-8 w-8 animate-spin\" />\n </div>\n </PageLayout>\n );\n }\n\n if (error) {\n return (\n <PageLayout title={title} description={description}>\n <EmptyState\n icon={<AlertCircle size={32} className=\"text-status-error-text\" />}\n title={tr(\"devportal.settings.errorTitle\", \"Unable to load settings\")}\n description={getErrorMessage(error)}\n />\n </PageLayout>\n );\n }\n\n const profile = data?.myDeveloperProfile;\n // This overview is scoped to the regular (digital) devportal — exclude\n // PHYSICAL orgs so seller-portal orgs don't inflate the \"Developer\n // organizations\" count/revenue shown here. See DeveloperOrgKind (BOFF-7285).\n type SettingsOrganization = NonNullable<\n typeof data\n >[\"myDeveloperOrganizations\"][number];\n const organizations = (data?.myDeveloperOrganizations ?? []).filter(\n (org: SettingsOrganization) => org.kind !== \"PHYSICAL\",\n );\n const apiKeys = data?.myApiKeys?.apiKeys ?? [];\n const totalApiKeyCount = data?.myApiKeys?.totalCount ?? apiKeys.length;\n const latestApiKey = apiKeys[0];\n const totalRevenue = organizations.reduce(\n (sum: number, organization: (typeof organizations)[number]) =>\n sum + (organization.totalRevenue ?? 0),\n 0,\n );\n\n return (\n <PageLayout\n title={title}\n description={description}\n purpose={tr(\n \"devportal.settings.purpose\",\n \"A quick health-check of your developer account — your profile, how many API keys and organizations you have, and where to get support. Use it to spot missing setup before it blocks publishing or billing.\",\n )}\n >\n <div className=\"grid gap-6 xl:grid-cols-[minmax(0,2fr)_minmax(320px,1fr)]\">\n <div className=\"space-y-6\">\n <PageSection title={tr(\"devportal.settings.profile\", \"Profile\")}>\n <EmphasisPanel>\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between\">\n <div className=\"space-y-2\">\n <div className=\"flex items-center gap-2\">\n <UserCircle2\n className=\"h-5 w-5 text-primary\"\n aria-hidden=\"true\"\n />\n <h2 className=\"text-lg font-semibold\">\n {tr(\n \"devportal.settings.developerProfile\",\n \"Developer profile\",\n )}\n </h2>\n {profile?.isVerified && <VerifiedBadge verified />}\n </div>\n <p className=\"text-sm text-text-secondary\">\n {profile?.companyName ||\n tr(\n \"devportal.settings.noCompanyName\",\n \"No company name set yet\",\n )}\n </p>\n {profile?.bio && (\n <p className=\"max-w-2xl text-sm text-text-secondary\">\n {profile.bio}\n </p>\n )}\n <div className=\"flex flex-wrap gap-2 pt-1 text-xs text-text-secondary\">\n <span className=\"rounded-full bg-bg-sunken px-2.5 py-1\">\n {profile?.applicationCount ?? 0}{\" \"}\n {tr(\n \"devportal.settings.publishedAssetsTracked\",\n \"published assets tracked\",\n )}\n </span>\n <span className=\"rounded-full bg-bg-sunken px-2.5 py-1\">\n {profile?.totalInstalls ?? 0}{\" \"}\n {tr(\"devportal.settings.installs\", \"installs\")}\n </span>\n <span className=\"rounded-full bg-bg-sunken px-2.5 py-1\">\n {tr(\"devportal.settings.emailUpdates\", \"Email updates\")}{\" \"}\n {profile?.emailNotifications\n ? tr(\"devportal.common.enabled\", \"enabled\")\n : tr(\"devportal.common.disabled\", \"disabled\")}\n </span>\n </div>\n </div>\n <button\n type=\"button\"\n onClick={() => handleNavigate(\"/publisher/profile\")}\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 hover:bg-action-primary-bg/90 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n >\n <Settings size={16} aria-hidden=\"true\" />\n {tr(\"devportal.settings.manageProfile\", \"Manage profile\")}\n </button>\n </div>\n </EmphasisPanel>\n </PageSection>\n\n <div className=\"grid gap-6 lg:grid-cols-2\">\n <PageSection\n title={tr(\"devportal.settings.credentials\", \"Credentials\")}\n >\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6\">\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <button\n type=\"button\"\n onClick={() => handleNavigate(\"/api-keys\")}\n className=\"rounded-card border border-border-seam bg-bg-surface p-4 text-left transition-colors hover:bg-accent focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n >\n <div className=\"flex items-center gap-2 text-primary\">\n <KeyRound size={16} aria-hidden=\"true\" />\n <span className=\"font-medium\">\n {tr(\"devportal.apiKeys\", \"API Keys\")}\n </span>\n </div>\n <p className=\"mt-2 text-2xl font-semibold\">\n {totalApiKeyCount}\n </p>\n <p className=\"mt-1 text-sm text-text-secondary\">\n {latestApiKey\n ? `${tr(\"devportal.settings.lastUsed\", \"Last used\")} ${formatDate(latestApiKey.lastUsedAt, neverLabel)}`\n : tr(\n \"devportal.settings.noApiKeys\",\n \"No API keys created yet\",\n )}\n </p>\n </button>\n\n <button\n type=\"button\"\n onClick={() => handleNavigate(\"/oauth\")}\n className=\"rounded-card border border-border-seam bg-bg-surface p-4 text-left transition-colors hover:bg-accent focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n >\n <div className=\"flex items-center gap-2 text-primary\">\n <Workflow size={16} aria-hidden=\"true\" />\n <span className=\"font-medium\">\n {tr(\"devportal.settings.oauthApps\", \"OAuth Apps\")}\n </span>\n </div>\n <p className=\"mt-2 text-2xl font-semibold\">\n {tr(\"devportal.common.open\", \"Open\")}\n </p>\n <p className=\"mt-1 text-sm text-text-secondary\">\n {tr(\n \"devportal.settings.oauthDescription\",\n \"Manage OAuth clients on the dedicated credentials page.\",\n )}\n </p>\n </button>\n </div>\n </div>\n </PageSection>\n\n <PageSection\n title={tr(\"devportal.settings.organizations\", \"Organizations\")}\n >\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6\">\n <div className=\"flex items-center gap-2 text-primary\">\n <Building2 size={16} aria-hidden=\"true\" />\n <span className=\"font-medium\">\n {tr(\n \"devportal.settings.developerOrganizations\",\n \"Developer organizations\",\n )}\n </span>\n </div>\n <p className=\"mt-2 text-2xl font-semibold\">\n {organizations.length}\n </p>\n <p className=\"mt-1 text-sm text-text-secondary\">\n ${totalRevenue.toLocaleString()}{\" \"}\n {tr(\n \"devportal.settings.lifetimeRevenue\",\n \"lifetime revenue across all teams\",\n )}\n </p>\n <button\n type=\"button\"\n onClick={() => handleNavigate(\"/organizations\")}\n className=\"mt-4 inline-flex items-center gap-2 rounded-md border px-4 py-2 text-sm font-medium hover:bg-accent focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n >\n {tr(\n \"devportal.settings.viewOrganizations\",\n \"View organizations\",\n )}\n <ExternalLink size={14} aria-hidden=\"true\" />\n </button>\n </div>\n </PageSection>\n </div>\n\n <PageSection\n title={tr(\n \"devportal.settings.deliveryAutomation\",\n \"Delivery & automation\",\n )}\n >\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6\">\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between\">\n <div>\n <div className=\"flex items-center gap-2 text-primary\">\n <Webhook size={16} aria-hidden=\"true\" />\n <span className=\"font-medium\">\n {tr(\n \"devportal.settings.webhookOperations\",\n \"Webhook operations\",\n )}\n </span>\n </div>\n <p className=\"mt-2 text-sm text-text-secondary\">\n {tr(\n \"devportal.settings.webhookOperationsDescription\",\n \"Configure application webhooks from each application detail page. Delivery history and retry status are available per app.\",\n )}\n </p>\n </div>\n <button\n type=\"button\"\n onClick={() => handleNavigate(\"/webhooks\")}\n className=\"inline-flex items-center gap-2 rounded-md border px-4 py-2 text-sm font-medium hover:bg-accent focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n >\n {tr(\"devportal.settings.openWebhooks\", \"Open webhooks\")}\n <ExternalLink size={14} aria-hidden=\"true\" />\n </button>\n </div>\n </div>\n </PageSection>\n </div>\n\n <div className=\"space-y-6\">\n <PageSection\n title={tr(\n \"devportal.settings.securitySupport\",\n \"Security & support\",\n )}\n >\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6\">\n <div className=\"flex items-center gap-2 text-primary\">\n <Shield size={16} aria-hidden=\"true\" />\n <span className=\"font-medium\">\n {tr(\"devportal.settings.securityPosture\", \"Security posture\")}\n </span>\n </div>\n <ul className=\"mt-4 space-y-3 text-sm text-text-secondary\">\n <li className=\"rounded-md bg-bg-sunken px-3 py-2\">\n {tr(\n \"devportal.settings.securityNote1\",\n \"API keys and OAuth apps are managed through the public global gateway.\",\n )}\n </li>\n <li className=\"rounded-md bg-bg-sunken px-3 py-2\">\n {tr(\n \"devportal.settings.securityNote2\",\n \"Webhook testing and delivery history are available per application.\",\n )}\n </li>\n <li className=\"rounded-md bg-bg-sunken px-3 py-2\">\n {tr(\n \"devportal.settings.securityNote3\",\n \"Profile verification status is reflected directly from your developer profile.\",\n )}\n </li>\n </ul>\n </div>\n </PageSection>\n\n <PageSection\n title={tr(\n \"devportal.settings.recentCredentialActivity\",\n \"Recent credential activity\",\n )}\n >\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6\">\n {latestApiKey ? (\n <div className=\"space-y-4 text-sm\">\n <div className=\"flex items-center justify-between gap-3\">\n <div>\n <p className=\"font-medium\">{latestApiKey.name}</p>\n <p className=\"text-text-secondary\">\n {latestApiKey.prefix}\n </p>\n </div>\n <span className=\"inline-flex items-center rounded-full bg-status-success-bg-subtle px-2.5 py-1 text-xs font-medium text-status-success-text\">\n {tr(\"devportal.common.active\", \"Active\")}\n </span>\n </div>\n <dl className=\"grid gap-3 text-text-secondary\">\n <div className=\"flex items-center justify-between gap-3\">\n <dt>{tr(\"devportal.common.created\", \"Created\")}</dt>\n <dd>{formatDate(latestApiKey.createdAt, neverLabel)}</dd>\n </div>\n <div className=\"flex items-center justify-between gap-3\">\n <dt>{tr(\"devportal.common.expires\", \"Expires\")}</dt>\n <dd>{formatDate(latestApiKey.expiresAt, neverLabel)}</dd>\n </div>\n <div className=\"flex items-center justify-between gap-3\">\n <dt>{tr(\"devportal.settings.lastUsed\", \"Last used\")}</dt>\n <dd>{formatDate(latestApiKey.lastUsedAt, neverLabel)}</dd>\n </div>\n </dl>\n </div>\n ) : (\n <EmptyState\n illustration=\"empty-notifications\"\n icon={<KeyRound size={24} />}\n title={tr(\n \"devportal.settings.noCredentialActivity\",\n \"No credential activity yet\",\n )}\n description={tr(\n \"devportal.settings.noCredentialActivityDescription\",\n \"Create an API key or OAuth app to manage credentials from here.\",\n )}\n />\n )}\n </div>\n </PageSection>\n\n <PageSection\n title={tr(\"devportal.settings.accountActions\", \"Account actions\")}\n >\n <div className=\"rounded-lg border border-status-warning-border bg-status-warning-bg-subtle p-6\">\n <h2 className=\"font-semibold text-status-warning-text\">\n {tr(\n \"devportal.settings.needHelpTitle\",\n \"Need help with account changes?\",\n )}\n </h2>\n <p className=\"mt-2 text-sm text-status-warning-text\">\n {tr(\n \"devportal.settings.needHelpDescription\",\n \"Destructive account operations are handled through support so the team can verify ownership and preserve billing history, audit trails, and marketplace assets.\",\n )}\n </p>\n <a\n href=\"mailto:support@burdenoff.com?subject=Developer%20portal%20account%20support\"\n className=\"mt-4 inline-flex items-center gap-2 rounded-md border border-status-warning-border bg-bg-surface px-4 py-2 text-sm font-medium text-text-primary hover:bg-accent focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n >\n <Mail size={16} aria-hidden=\"true\" />\n {tr(\"devportal.settings.contactSupport\", \"Contact support\")}\n </a>\n </div>\n </PageSection>\n </div>\n </div>\n </PageLayout>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"SettingsPage.js","names":["_Fragment","EmptyState","EmptyState$1","formatDate","value","neverLabel","parsed","HealthCheckFold","tr","useTr","fold","OptionalFields","Fragment","SettingsPage","useDevportal","isFluidgrids","useIsFluidgridsVariant","useGetDeveloperPortalSettingsOverviewQuery","handleNavigate","basePath","path","title","description","hub","DeveloperSettingsHub","loading","data","PageLayout","Loader2","error","AlertCircle","getErrorMessage","profile","organizations","org","apiKeys","totalApiKeyCount","latestApiKey","totalRevenue","sum","organization","PageSection","EmphasisPanel","UserCircle2","VerifiedBadge","Settings","KeyRound","Workflow","Building2","ExternalLink","Webhook","Shield","Mail"],"sources":["../../../src/devportal/pages/SettingsPage.tsx"],"sourcesContent":["import type { FC, ReactNode } from \"react\";\nimport {\n Building2,\n ExternalLink,\n KeyRound,\n Mail,\n Settings,\n Shield,\n UserCircle2,\n Webhook,\n Workflow,\n Loader2,\n AlertCircle,\n} from \"lucide-react\";\nimport { EmphasisPanel, OptionalFields } from \"@burdenoff/fe-libs/ui\";\nimport { PageLayout, PageSection } from \"../components/PageLayout\";\nimport { EmptyState } from \"../components/EmptyState\";\nimport { VerifiedBadge } from \"../components/StatusBadge\";\nimport { DeveloperSettingsHub } from \"../components/DeveloperSettingsHub\";\nimport {\n useDevportal,\n useIsFluidgridsVariant,\n} from \"../providers/DevportalProvider\";\nimport {\n getErrorMessage,\n useGetDeveloperPortalSettingsOverviewQuery,\n} from \"../hooks\";\nimport { useTr } from \"../utils/i18n\";\n\nconst formatDate = (\n value: string | null | undefined,\n neverLabel: string,\n): string => {\n if (!value) return neverLabel;\n\n const parsed = new Date(value);\n if (Number.isNaN(parsed.getTime())) return neverLabel;\n\n return parsed.toLocaleDateString();\n};\n\n/** FluidGrids: the health check sits one click deeper, remembered once opened. */\nconst HealthCheckFold: FC<{ fold: boolean; children: ReactNode }> = ({\n fold,\n children,\n}) => {\n const tr = useTr();\n if (!fold) return <>{children}</>;\n return (\n <OptionalFields\n storageKey=\"devportal.settings.healthCheck\"\n title={tr(\"devportal.developerSettings.healthTitle\", \"Account check\")}\n description={tr(\n \"devportal.developerSettings.healthDescription\",\n \"Your developer profile, credentials, organizations and support options.\",\n )}\n >\n {children}\n </OptionalFields>\n );\n};\n\nexport const SettingsPage: FC = () => {\n const { navigate, basePath } = useDevportal();\n const tr = useTr();\n const isFluidgrids = useIsFluidgridsVariant();\n const { data, loading, error } = useGetDeveloperPortalSettingsOverviewQuery({\n fetchPolicy: \"cache-and-network\",\n });\n\n const handleNavigate = (path: string) => {\n navigate?.(`${basePath}${path}`);\n };\n\n const neverLabel = tr(\"devportal.settings.never\", \"Never\");\n // FluidGrids: this page is the Developer settings hub (links first, the\n // account health check one click deeper). Other apps keep the old page.\n const title = isFluidgrids\n ? tr(\"devportal.developerSettings.title\", \"Developer settings\")\n : tr(\"devportal.settings.title\", \"Settings\");\n const description = isFluidgrids\n ? tr(\n \"devportal.developerSettings.description\",\n \"API keys, OAuth apps, webhooks, apps acting for you, app logs, analytics and docs in one place\",\n )\n : tr(\n \"devportal.settings.description\",\n \"Review your developer portal account, credentials, and support options\",\n );\n const hub = isFluidgrids ? (\n <div className=\"mb-6\">\n <DeveloperSettingsHub />\n </div>\n ) : null;\n\n if (loading && !data) {\n return (\n <PageLayout title={title} description={description}>\n {hub}\n <div\n className=\"flex items-center justify-center py-16 text-text-secondary\"\n role=\"status\"\n aria-live=\"polite\"\n aria-label={tr(\"devportal.common.loading\", \"Loading\")}\n >\n <Loader2 className=\"h-8 w-8 animate-spin\" />\n </div>\n </PageLayout>\n );\n }\n\n if (error) {\n return (\n <PageLayout title={title} description={description}>\n {hub}\n <EmptyState\n icon={<AlertCircle size={32} className=\"text-status-error-text\" />}\n title={tr(\"devportal.settings.errorTitle\", \"Unable to load settings\")}\n description={getErrorMessage(error)}\n />\n </PageLayout>\n );\n }\n\n const profile = data?.myDeveloperProfile;\n // This overview is scoped to the regular (digital) devportal — exclude\n // PHYSICAL orgs so seller-portal orgs don't inflate the \"Developer\n // organizations\" count/revenue shown here. See DeveloperOrgKind (BOFF-7285).\n type SettingsOrganization = NonNullable<\n typeof data\n >[\"myDeveloperOrganizations\"][number];\n const organizations = (data?.myDeveloperOrganizations ?? []).filter(\n (org: SettingsOrganization) => org.kind !== \"PHYSICAL\",\n );\n const apiKeys = data?.myApiKeys?.apiKeys ?? [];\n const totalApiKeyCount = data?.myApiKeys?.totalCount ?? apiKeys.length;\n const latestApiKey = apiKeys[0];\n const totalRevenue = organizations.reduce(\n (sum: number, organization: (typeof organizations)[number]) =>\n sum + (organization.totalRevenue ?? 0),\n 0,\n );\n\n return (\n <PageLayout\n title={title}\n description={description}\n purpose={tr(\n \"devportal.settings.purpose\",\n \"A quick health-check of your developer account — your profile, how many API keys and organizations you have, and where to get support. Use it to spot missing setup before it blocks publishing or billing.\",\n )}\n >\n {hub}\n <HealthCheckFold fold={isFluidgrids}>\n <div className=\"grid gap-6 xl:grid-cols-[minmax(0,2fr)_minmax(320px,1fr)]\">\n <div className=\"space-y-6\">\n <PageSection title={tr(\"devportal.settings.profile\", \"Profile\")}>\n <EmphasisPanel>\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between\">\n <div className=\"space-y-2\">\n <div className=\"flex items-center gap-2\">\n <UserCircle2\n className=\"h-5 w-5 text-primary\"\n aria-hidden=\"true\"\n />\n <h2 className=\"text-lg font-semibold\">\n {tr(\n \"devportal.settings.developerProfile\",\n \"Developer profile\",\n )}\n </h2>\n {profile?.isVerified && <VerifiedBadge verified />}\n </div>\n <p className=\"text-sm text-text-secondary\">\n {profile?.companyName ||\n tr(\n \"devportal.settings.noCompanyName\",\n \"No company name set yet\",\n )}\n </p>\n {profile?.bio && (\n <p className=\"max-w-2xl text-sm text-text-secondary\">\n {profile.bio}\n </p>\n )}\n <div className=\"flex flex-wrap gap-2 pt-1 text-xs text-text-secondary\">\n <span className=\"rounded-full bg-bg-sunken px-2.5 py-1\">\n {profile?.applicationCount ?? 0}{\" \"}\n {tr(\n \"devportal.settings.publishedAssetsTracked\",\n \"published assets tracked\",\n )}\n </span>\n <span className=\"rounded-full bg-bg-sunken px-2.5 py-1\">\n {profile?.totalInstalls ?? 0}{\" \"}\n {tr(\"devportal.settings.installs\", \"installs\")}\n </span>\n <span className=\"rounded-full bg-bg-sunken px-2.5 py-1\">\n {tr(\"devportal.settings.emailUpdates\", \"Email updates\")}{\" \"}\n {profile?.emailNotifications\n ? tr(\"devportal.common.enabled\", \"enabled\")\n : tr(\"devportal.common.disabled\", \"disabled\")}\n </span>\n </div>\n </div>\n <button\n type=\"button\"\n onClick={() => handleNavigate(\"/publisher/profile\")}\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 hover:bg-action-primary-bg/90 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n >\n <Settings size={16} aria-hidden=\"true\" />\n {tr(\"devportal.settings.manageProfile\", \"Manage profile\")}\n </button>\n </div>\n </EmphasisPanel>\n </PageSection>\n\n <div className=\"grid gap-6 lg:grid-cols-2\">\n <PageSection\n title={tr(\"devportal.settings.credentials\", \"Credentials\")}\n >\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6\">\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <button\n type=\"button\"\n onClick={() => handleNavigate(\"/api-keys\")}\n className=\"rounded-card border border-border-seam bg-bg-surface p-4 text-left transition-colors hover:bg-accent focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n >\n <div className=\"flex items-center gap-2 text-primary\">\n <KeyRound size={16} aria-hidden=\"true\" />\n <span className=\"font-medium\">\n {tr(\"devportal.apiKeys\", \"API Keys\")}\n </span>\n </div>\n <p className=\"mt-2 text-2xl font-semibold\">\n {totalApiKeyCount}\n </p>\n <p className=\"mt-1 text-sm text-text-secondary\">\n {latestApiKey\n ? `${tr(\"devportal.settings.lastUsed\", \"Last used\")} ${formatDate(latestApiKey.lastUsedAt, neverLabel)}`\n : tr(\n \"devportal.settings.noApiKeys\",\n \"No API keys created yet\",\n )}\n </p>\n </button>\n\n <button\n type=\"button\"\n onClick={() => handleNavigate(\"/oauth\")}\n className=\"rounded-card border border-border-seam bg-bg-surface p-4 text-left transition-colors hover:bg-accent focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n >\n <div className=\"flex items-center gap-2 text-primary\">\n <Workflow size={16} aria-hidden=\"true\" />\n <span className=\"font-medium\">\n {tr(\"devportal.settings.oauthApps\", \"OAuth Apps\")}\n </span>\n </div>\n <p className=\"mt-2 text-2xl font-semibold\">\n {tr(\"devportal.common.open\", \"Open\")}\n </p>\n <p className=\"mt-1 text-sm text-text-secondary\">\n {tr(\n \"devportal.settings.oauthDescription\",\n \"Manage OAuth clients on the dedicated credentials page.\",\n )}\n </p>\n </button>\n </div>\n </div>\n </PageSection>\n\n <PageSection\n title={tr(\"devportal.settings.organizations\", \"Organizations\")}\n >\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6\">\n <div className=\"flex items-center gap-2 text-primary\">\n <Building2 size={16} aria-hidden=\"true\" />\n <span className=\"font-medium\">\n {tr(\n \"devportal.settings.developerOrganizations\",\n \"Developer organizations\",\n )}\n </span>\n </div>\n <p className=\"mt-2 text-2xl font-semibold\">\n {organizations.length}\n </p>\n <p className=\"mt-1 text-sm text-text-secondary\">\n ${totalRevenue.toLocaleString()}{\" \"}\n {tr(\n \"devportal.settings.lifetimeRevenue\",\n \"lifetime revenue across all teams\",\n )}\n </p>\n <button\n type=\"button\"\n onClick={() => handleNavigate(\"/organizations\")}\n className=\"mt-4 inline-flex items-center gap-2 rounded-md border px-4 py-2 text-sm font-medium hover:bg-accent focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n >\n {tr(\n \"devportal.settings.viewOrganizations\",\n \"View organizations\",\n )}\n <ExternalLink size={14} aria-hidden=\"true\" />\n </button>\n </div>\n </PageSection>\n </div>\n\n <PageSection\n title={tr(\n \"devportal.settings.deliveryAutomation\",\n \"Delivery & automation\",\n )}\n >\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6\">\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between\">\n <div>\n <div className=\"flex items-center gap-2 text-primary\">\n <Webhook size={16} aria-hidden=\"true\" />\n <span className=\"font-medium\">\n {tr(\n \"devportal.settings.webhookOperations\",\n \"Webhook operations\",\n )}\n </span>\n </div>\n <p className=\"mt-2 text-sm text-text-secondary\">\n {tr(\n \"devportal.settings.webhookOperationsDescription\",\n \"Configure application webhooks from each application detail page. Delivery history and retry status are available per app.\",\n )}\n </p>\n </div>\n <button\n type=\"button\"\n onClick={() => handleNavigate(\"/webhooks\")}\n className=\"inline-flex items-center gap-2 rounded-md border px-4 py-2 text-sm font-medium hover:bg-accent focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n >\n {tr(\"devportal.settings.openWebhooks\", \"Open webhooks\")}\n <ExternalLink size={14} aria-hidden=\"true\" />\n </button>\n </div>\n </div>\n </PageSection>\n </div>\n\n <div className=\"space-y-6\">\n <PageSection\n title={tr(\n \"devportal.settings.securitySupport\",\n \"Security & support\",\n )}\n >\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6\">\n <div className=\"flex items-center gap-2 text-primary\">\n <Shield size={16} aria-hidden=\"true\" />\n <span className=\"font-medium\">\n {tr(\n \"devportal.settings.securityPosture\",\n \"Security posture\",\n )}\n </span>\n </div>\n <ul className=\"mt-4 space-y-3 text-sm text-text-secondary\">\n <li className=\"rounded-md bg-bg-sunken px-3 py-2\">\n {tr(\n \"devportal.settings.securityNote1\",\n \"API keys and OAuth apps are managed through the public global gateway.\",\n )}\n </li>\n <li className=\"rounded-md bg-bg-sunken px-3 py-2\">\n {tr(\n \"devportal.settings.securityNote2\",\n \"Webhook testing and delivery history are available per application.\",\n )}\n </li>\n <li className=\"rounded-md bg-bg-sunken px-3 py-2\">\n {tr(\n \"devportal.settings.securityNote3\",\n \"Profile verification status is reflected directly from your developer profile.\",\n )}\n </li>\n </ul>\n </div>\n </PageSection>\n\n <PageSection\n title={tr(\n \"devportal.settings.recentCredentialActivity\",\n \"Recent credential activity\",\n )}\n >\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6\">\n {latestApiKey ? (\n <div className=\"space-y-4 text-sm\">\n <div className=\"flex items-center justify-between gap-3\">\n <div>\n <p className=\"font-medium\">{latestApiKey.name}</p>\n <p className=\"text-text-secondary\">\n {latestApiKey.prefix}\n </p>\n </div>\n <span className=\"inline-flex items-center rounded-full bg-status-success-bg-subtle px-2.5 py-1 text-xs font-medium text-status-success-text\">\n {tr(\"devportal.common.active\", \"Active\")}\n </span>\n </div>\n <dl className=\"grid gap-3 text-text-secondary\">\n <div className=\"flex items-center justify-between gap-3\">\n <dt>{tr(\"devportal.common.created\", \"Created\")}</dt>\n <dd>\n {formatDate(latestApiKey.createdAt, neverLabel)}\n </dd>\n </div>\n <div className=\"flex items-center justify-between gap-3\">\n <dt>{tr(\"devportal.common.expires\", \"Expires\")}</dt>\n <dd>\n {formatDate(latestApiKey.expiresAt, neverLabel)}\n </dd>\n </div>\n <div className=\"flex items-center justify-between gap-3\">\n <dt>\n {tr(\"devportal.settings.lastUsed\", \"Last used\")}\n </dt>\n <dd>\n {formatDate(latestApiKey.lastUsedAt, neverLabel)}\n </dd>\n </div>\n </dl>\n </div>\n ) : (\n <EmptyState\n illustration=\"empty-notifications\"\n icon={<KeyRound size={24} />}\n title={tr(\n \"devportal.settings.noCredentialActivity\",\n \"No credential activity yet\",\n )}\n description={tr(\n \"devportal.settings.noCredentialActivityDescription\",\n \"Create an API key or OAuth app to manage credentials from here.\",\n )}\n />\n )}\n </div>\n </PageSection>\n\n <PageSection\n title={tr(\"devportal.settings.accountActions\", \"Account actions\")}\n >\n <div className=\"rounded-lg border border-status-warning-border bg-status-warning-bg-subtle p-6\">\n <h2 className=\"font-semibold text-status-warning-text\">\n {tr(\n \"devportal.settings.needHelpTitle\",\n \"Need help with account changes?\",\n )}\n </h2>\n <p className=\"mt-2 text-sm text-status-warning-text\">\n {tr(\n \"devportal.settings.needHelpDescription\",\n \"Destructive account operations are handled through support so the team can verify ownership and preserve billing history, audit trails, and marketplace assets.\",\n )}\n </p>\n <a\n href=\"mailto:support@burdenoff.com?subject=Developer%20portal%20account%20support\"\n className=\"mt-4 inline-flex items-center gap-2 rounded-md border border-status-warning-border bg-bg-surface px-4 py-2 text-sm font-medium text-text-primary hover:bg-accent focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n >\n <Mail size={16} aria-hidden=\"true\" />\n {tr(\"devportal.settings.contactSupport\", \"Contact support\")}\n </a>\n </div>\n </PageSection>\n </div>\n </div>\n </HealthCheckFold>\n </PageLayout>\n );\n};\n"],"mappings":"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"}
@@ -11,8 +11,8 @@ import { ELIGIBILITY_RULES as c, reviewRequirementsFor as oe } from "../utils/de
11
11
  import { useState as l } from "react";
12
12
  import { AppWindow as u, ArrowRight as se, BookOpen as ce, Box as le, Building2 as d, Check as f, ChevronRight as p, GitFork as ue, Key as de, ListChecks as m, Puzzle as h, Rocket as g, ShieldCheck as _ } from "lucide-react";
13
13
  import { jsx as v, jsxs as y } from "react/jsx-runtime";
14
- import { useI18n as fe } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
15
- import { Illustration as pe, PagePurpose as me } from "@burdenoff/fe-libs/ui";
14
+ import { Illustration as fe, PagePurpose as pe } from "@burdenoff/fe-libs/ui";
15
+ import { useI18n as me } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
16
16
  // src/devportal/pages/SetupPage.tsx
17
17
  function b(e) {
18
18
  return e.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
@@ -61,7 +61,7 @@ var S = [
61
61
  })
62
62
  });
63
63
  }, C = () => {
64
- let { navigate: a, basePath: c, currentUser: _ } = i(), { t: S } = fe(), C = ee(), E = (e, t) => {
64
+ let { navigate: a, basePath: c, currentUser: _ } = i(), { t: S } = me(), C = ee(), E = (e, t) => {
65
65
  let n = S(e);
66
66
  return n === e ? t : n;
67
67
  }, D = (e) => a?.(`${c}${e}`), [O, k] = l("org"), [A, _e] = l(null), [j, ve] = l(null), [ye, be] = l(null), [M, xe] = l(""), [N, P] = l(""), [F, Se] = l(""), [I, L] = l({}), [R, Ce] = l(!1), [z, B] = l(null), [we, { loading: Te }] = ie(), [Ee, { loading: De }] = re(), V = Te || De, [Oe] = ne(), ke = () => {
@@ -170,11 +170,11 @@ var S = [
170
170
  }),
171
171
  O === "org" && /* @__PURE__ */ y("div", {
172
172
  className: "mb-8 flex flex-col items-center gap-3 text-center",
173
- children: [/* @__PURE__ */ v(pe, {
173
+ children: [/* @__PURE__ */ v(fe, {
174
174
  name: "onboarding",
175
175
  alt: E("devportal.setup.illustrationAlt", "Getting started with the developer portal"),
176
176
  size: "md"
177
- }), /* @__PURE__ */ v(me, {
177
+ }), /* @__PURE__ */ v(pe, {
178
178
  className: "justify-center",
179
179
  children: E("devportal.setup.purposeWithReview", "Three quick steps to start building: create the organization that owns your apps, register your first app, then submit it for review. Your developer profile is created with your organization. You can change everything later.")
180
180
  })]
@@ -17,11 +17,11 @@ import { useEffect as v, useMemo as ae, useState as y } from "react";
17
17
  import { AlertCircle as oe, CheckCircle as b, Clock as se, ExternalLink as ce, Loader2 as le, Pause as x, Play as S, Send as C, Trash2 as ue, Webhook as de, XCircle as fe } from "lucide-react";
18
18
  import { useParams as w } from "react-router";
19
19
  import { jsx as T, jsxs as E } from "react/jsx-runtime";
20
- import { useI18n as D } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
21
- import { CTAOverflowMenu as O, EmphasisPanel as k, NextSteps as A } from "@burdenoff/fe-libs/ui";
20
+ import { CTAOverflowMenu as D, EmphasisPanel as O, NextSteps as k } from "@burdenoff/fe-libs/ui";
21
+ import { useI18n as A } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
22
22
  // src/devportal/pages/WebhookDetailPage.tsx
23
23
  var j = (t) => t ? e(new Date(t), "MMM d, yyyy HH:mm:ss") : "Never", M = () => {
24
- let { appId: M, webhookId: N } = w(), { navigate: P, basePath: F } = p(), { t: I } = D(), L = (e, t) => {
24
+ let { appId: M, webhookId: N } = w(), { navigate: P, basePath: F } = p(), { t: I } = A(), L = (e, t) => {
25
25
  let n = I(e);
26
26
  return n === e ? t : n;
27
27
  }, { allowed: R } = _(g.WEBHOOK_UPDATE), { allowed: z } = _(g.WEBHOOK_DELETE), [B, V] = y(!1), [pe, H] = y(!1), [U, W] = y(null), [me, G] = y(!1), { data: K } = ee({
@@ -106,7 +106,7 @@ var j = (t) => t ? e(new Date(t), "MMM d, yyyy HH:mm:ss") : "Never", M = () => {
106
106
  purpose: L("devportal.webhookDetailPurpose", "This endpoint receives the events you subscribed to, signed with your secret. Check the delivery history to confirm your server is responding with 2xx, send a test event, and pause it if your endpoint is down so deliveries are not lost to repeated failures."),
107
107
  backLink: `/apps/${Q}/webhooks`,
108
108
  backLabel: L("devportal.backToWebhooks", "Back to Webhooks"),
109
- actions: /* @__PURE__ */ T(O, {
109
+ actions: /* @__PURE__ */ T(D, {
110
110
  primary: {
111
111
  label: L("devportal.test", "Test"),
112
112
  icon: /* @__PURE__ */ T(C, { size: 16 }),
@@ -128,7 +128,7 @@ var j = (t) => t ? e(new Date(t), "MMM d, yyyy HH:mm:ss") : "Never", M = () => {
128
128
  }]
129
129
  }),
130
130
  children: [
131
- /* @__PURE__ */ T(k, { children: /* @__PURE__ */ E(c, {
131
+ /* @__PURE__ */ T(O, { children: /* @__PURE__ */ E(c, {
132
132
  columns: 4,
133
133
  children: [
134
134
  /* @__PURE__ */ T(s, {
@@ -153,7 +153,7 @@ var j = (t) => t ? e(new Date(t), "MMM d, yyyy HH:mm:ss") : "Never", M = () => {
153
153
  })
154
154
  ]
155
155
  }) }),
156
- /* @__PURE__ */ T(A, {
156
+ /* @__PURE__ */ T(k, {
157
157
  storageKey: `devportal-webhook-${X.id}`,
158
158
  steps: [{
159
159
  id: "test",
@@ -4,22 +4,22 @@ import { StatusBadge as n } from "../components/StatusBadge.js";
4
4
  import { useGetApplicationQuery as r, useGetApplicationsQuery as i, useGetWebhooksQuery as a } from "../../generated/global-operations.js";
5
5
  import { getErrorMessage as o } from "../hooks/useGraphQL.js";
6
6
  import { EmptyState as s } from "../components/EmptyState.js";
7
- import { AppListItem as c } from "../components/AppCard.js";
7
+ import { AppListItem as ee } from "../components/AppCard.js";
8
8
  import "../components/index.js";
9
- import { useDevportal as l } from "../providers/DevportalProvider.js";
10
- import { PermissionGuard as u } from "../components/PermissionGuard.js";
11
- import { DEVPORTAL_PERMISSIONS as d } from "../constants/permissions.js";
12
- import { useDevportalPermission as ee } from "../hooks/usePermission.js";
9
+ import { useDevportal as c } from "../providers/DevportalProvider.js";
10
+ import { PermissionGuard as l } from "../components/PermissionGuard.js";
11
+ import { DEVPORTAL_PERMISSIONS as u } from "../constants/permissions.js";
12
+ import { useDevportalPermission as d } from "../hooks/usePermission.js";
13
13
  import { cn as f } from "../utils/cn.js";
14
14
  import "../hooks/index.js";
15
- import { useEffect as te, useState as p } from "react";
16
- import { AlertCircle as m, AlertTriangle as h, AppWindow as ne, CheckCircle as g, Loader2 as _, PauseCircle as v, Plus as y, Search as b, Webhook as x, XCircle as S } from "lucide-react";
15
+ import { useEffect as p, useState as m } from "react";
16
+ import { AlertCircle as h, AlertTriangle as te, AppWindow as ne, CheckCircle as g, Loader2 as _, PauseCircle as v, Plus as y, Search as b, Webhook as x, XCircle as S } from "lucide-react";
17
17
  import { useParams as C } from "react-router";
18
18
  import { jsx as w, jsxs as T } from "react/jsx-runtime";
19
- import { useI18n as re } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
20
19
  import { EmphasisPanel as E, GlassCard as D } from "@burdenoff/fe-libs/ui";
20
+ import { useI18n as O } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
21
21
  // src/devportal/pages/WebhooksPage.tsx
22
- function O(e) {
22
+ function k(e) {
23
23
  return {
24
24
  id: e.id,
25
25
  applicationId: e.applicationId,
@@ -43,31 +43,31 @@ function O(e) {
43
43
  updatedAt: e.updatedAt
44
44
  };
45
45
  }
46
- var k = () => {
47
- let { appId: k } = C(), { navigate: j, basePath: ie, activeOrgId: M } = l(), { t: ae } = re(), N = (e, t) => {
46
+ var A = () => {
47
+ let { appId: A } = C(), { navigate: re, basePath: ie, activeOrgId: M } = c(), { t: ae } = O(), N = (e, t) => {
48
48
  let n = ae(e);
49
49
  return n === e ? t : n;
50
- }, P = ee(d.WEBHOOK_CREATE), [F, I] = p(""), [L, R] = p(""), { data: z } = r({
51
- variables: { id: k ?? "" },
52
- skip: !k,
50
+ }, P = d(u.WEBHOOK_CREATE), [F, I] = m(""), [L, R] = m(""), { data: z } = r({
51
+ variables: { id: A ?? "" },
52
+ skip: !A,
53
53
  fetchPolicy: "cache-first"
54
54
  });
55
- te(() => {
55
+ p(() => {
56
56
  let e = z?.application?.name;
57
- if (!k || !e) return;
57
+ if (!A || !e) return;
58
58
  let t = window.__breadcrumbRegistry;
59
- return t?.register(k, e), () => t?.unregister(k);
60
- }, [k, z?.application?.name]);
59
+ return t?.register(A, e), () => t?.unregister(A);
60
+ }, [A, z?.application?.name]);
61
61
  let { data: B, loading: V, error: H, refetch: U } = i({
62
62
  variables: { limit: 100 },
63
- skip: !!k,
63
+ skip: !!A,
64
64
  fetchPolicy: "cache-and-network"
65
65
  }), { data: W, loading: G, error: K, refetch: q } = a({
66
- variables: { applicationId: k || "" },
67
- skip: !k,
66
+ variables: { applicationId: A || "" },
67
+ skip: !A,
68
68
  fetchPolicy: "cache-and-network"
69
- }), J = W?.webhooks?.map(O) ?? [], Y = B?.applications?.edges?.map((e) => e.node) ?? [], X = M ? Y.filter((e) => e.developerOrganizationId === M) : Y, Z = (e) => {
70
- j?.(`${ie}${e}`);
69
+ }), J = W?.webhooks?.map(k) ?? [], Y = B?.applications?.edges?.map((e) => e.node) ?? [], X = M ? Y.filter((e) => e.developerOrganizationId === M) : Y, Z = (e) => {
70
+ re?.(`${ie}${e}`);
71
71
  }, Q = J.filter((e) => {
72
72
  let t = !F || e.name.toLowerCase().includes(F.toLowerCase()) || e.url.toLowerCase().includes(F.toLowerCase()), n = !L || e.status === L;
73
73
  return t && n;
@@ -85,7 +85,7 @@ var k = () => {
85
85
  size: 16,
86
86
  className: "text-status-error-text"
87
87
  });
88
- case "DISABLED": return /* @__PURE__ */ w(h, {
88
+ case "DISABLED": return /* @__PURE__ */ w(te, {
89
89
  size: 16,
90
90
  className: "text-text-tertiary"
91
91
  });
@@ -95,13 +95,13 @@ var k = () => {
95
95
  let t = e.successCount + e.failureCount;
96
96
  return t === 0 ? 100 : Math.round(e.successCount / t * 100);
97
97
  };
98
- if (!k) {
98
+ if (!A) {
99
99
  let t = X.filter((e) => {
100
100
  if (!F) return !0;
101
101
  let t = F.toLowerCase();
102
102
  return e.name.toLowerCase().includes(t) || (e.slug ?? "").toLowerCase().includes(t);
103
103
  });
104
- return /* @__PURE__ */ w(u, {
104
+ return /* @__PURE__ */ w(l, {
105
105
  authOnly: !0,
106
106
  children: /* @__PURE__ */ w(e, {
107
107
  title: N("devportal.webhooks", "Webhooks"),
@@ -136,7 +136,7 @@ var k = () => {
136
136
  }) : H ? /* @__PURE__ */ T("div", {
137
137
  className: "rounded-lg border border-status-error-border/50 bg-status-error-bg/10 p-6 text-center",
138
138
  children: [
139
- /* @__PURE__ */ w(m, { className: "mx-auto h-8 w-8 text-status-error-text" }),
139
+ /* @__PURE__ */ w(h, { className: "mx-auto h-8 w-8 text-status-error-text" }),
140
140
  /* @__PURE__ */ w("h3", {
141
141
  className: "mt-2 font-medium text-status-error-text",
142
142
  children: "Failed to load applications"
@@ -153,7 +153,7 @@ var k = () => {
153
153
  ]
154
154
  }) : t.length > 0 ? /* @__PURE__ */ w("div", {
155
155
  className: "space-y-2",
156
- children: t.map((e) => /* @__PURE__ */ w(c, {
156
+ children: t.map((e) => /* @__PURE__ */ w(ee, {
157
157
  app: e,
158
158
  onClick: () => Z(`/apps/${e.id}/webhooks`)
159
159
  }, e.id))
@@ -176,7 +176,7 @@ var k = () => {
176
176
  if (G && !W) return /* @__PURE__ */ w(e, {
177
177
  title: N("devportal.webhooks", "Webhooks"),
178
178
  description: N("devportal.manageWebhooksApp", "Manage webhooks for this application"),
179
- backLink: `/apps/${k}`,
179
+ backLink: `/apps/${A}`,
180
180
  backLabel: N("devportal.backToApplication", "Back to Application"),
181
181
  children: /* @__PURE__ */ T("div", {
182
182
  className: "flex items-center justify-center py-12",
@@ -189,12 +189,12 @@ var k = () => {
189
189
  if (K) return /* @__PURE__ */ w(e, {
190
190
  title: N("devportal.webhooks", "Webhooks"),
191
191
  description: N("devportal.manageWebhooksApp", "Manage webhooks for this application"),
192
- backLink: `/apps/${k}`,
192
+ backLink: `/apps/${A}`,
193
193
  backLabel: N("devportal.backToApplication", "Back to Application"),
194
194
  children: /* @__PURE__ */ T("div", {
195
195
  className: "rounded-lg border border-status-error-border/50 bg-status-error-bg/10 p-6 text-center",
196
196
  children: [
197
- /* @__PURE__ */ w(m, { className: "mx-auto h-8 w-8 text-status-error-text" }),
197
+ /* @__PURE__ */ w(h, { className: "mx-auto h-8 w-8 text-status-error-text" }),
198
198
  /* @__PURE__ */ w("h3", {
199
199
  className: "mt-2 font-medium text-status-error-text",
200
200
  children: N("devportal.failedToLoadWebhooks", "Failed to load webhooks")
@@ -307,7 +307,7 @@ var k = () => {
307
307
  header: "Last Triggered",
308
308
  render: (e) => /* @__PURE__ */ w("span", {
309
309
  className: "text-sm text-text-secondary",
310
- children: e.lastTriggeredAt ? A(e.lastTriggeredAt) : "Never"
310
+ children: e.lastTriggeredAt ? j(e.lastTriggeredAt) : "Never"
311
311
  })
312
312
  }
313
313
  ], $ = {
@@ -316,16 +316,16 @@ var k = () => {
316
316
  failed: J.filter((e) => e.status === "FAILED").length,
317
317
  paused: J.filter((e) => e.status === "PAUSED").length
318
318
  };
319
- return /* @__PURE__ */ w(u, {
319
+ return /* @__PURE__ */ w(l, {
320
320
  authOnly: !0,
321
321
  children: /* @__PURE__ */ T(e, {
322
322
  title: N("devportal.webhooks", "Webhooks"),
323
323
  description: N("devportal.manageWebhooksApp", "Manage webhooks for this application"),
324
324
  purpose: N("devportal.webhooksAppPurpose", "These webhooks deliver this application's events to your endpoints. Add a URL, choose which events to subscribe to, and send a test delivery to confirm your server receives and verifies the signed payload."),
325
- backLink: `/apps/${k}`,
325
+ backLink: `/apps/${A}`,
326
326
  backLabel: N("devportal.backToApplication", "Back to Application"),
327
327
  actions: /* @__PURE__ */ T("button", {
328
- onClick: () => Z(`/apps/${k}/webhooks/new`),
328
+ onClick: () => Z(`/apps/${A}/webhooks/new`),
329
329
  disabled: !P.allowed,
330
330
  "aria-disabled": !P.allowed,
331
331
  title: P.allowed ? void 0 : N("devportal.common.noPermission", "You do not have permission to perform this action"),
@@ -455,13 +455,13 @@ var k = () => {
455
455
  data: Q,
456
456
  columns: ce,
457
457
  keyField: "id",
458
- onRowClick: (e) => Z(`/apps/${k}/webhooks/${e.id}`)
458
+ onRowClick: (e) => Z(`/apps/${A}/webhooks/${e.id}`)
459
459
  }) : /* @__PURE__ */ w(s, {
460
460
  illustration: "empty-notifications",
461
461
  title: N("devportal.noWebhooksFound", "No webhooks found"),
462
462
  description: F || L ? N("devportal.tryAdjustingFilters", "Try adjusting your filters") : N("devportal.createFirstWebhook", "Create your first webhook to receive real-time event notifications"),
463
463
  action: !F && !L ? /* @__PURE__ */ T("button", {
464
- onClick: () => Z(`/apps/${k}/webhooks/new`),
464
+ onClick: () => Z(`/apps/${A}/webhooks/new`),
465
465
  className: "inline-flex items-center gap-2 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90",
466
466
  children: [/* @__PURE__ */ w(y, { size: 16 }), N("devportal.createWebhook", "Create Webhook")]
467
467
  }) : void 0
@@ -470,10 +470,10 @@ var k = () => {
470
470
  })
471
471
  });
472
472
  };
473
- function A(e) {
473
+ function j(e) {
474
474
  let t = new Date(e), n = (/* @__PURE__ */ new Date()).getTime() - t.getTime(), r = Math.floor(n / 6e4), i = Math.floor(r / 60), a = Math.floor(i / 24);
475
475
  return r < 1 ? "Just now" : r < 60 ? `${r}m ago` : i < 24 ? `${i}h ago` : a < 7 ? `${a}d ago` : t.toLocaleDateString();
476
476
  }
477
- export { k as WebhooksPage };
477
+ export { A as WebhooksPage };
478
478
 
479
479
  //# sourceMappingURL=WebhooksPage.js.map