@burdenoff/microfe-devportal 2026.715.2 → 2026.715.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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ApplicationDetailPage.js","names":[],"sources":["../../../src/devportal/pages/ApplicationDetailPage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useState, useMemo, useCallback, useEffect, useRef } from \"react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport { useParams, useNavigate } from \"react-router-dom\";\nimport {\n AppWindow,\n Key,\n Webhook,\n BarChart3,\n Plus,\n ExternalLink,\n MoreHorizontal,\n Loader2,\n AlertCircle,\n CheckCircle,\n Clock,\n Shield,\n RefreshCw,\n Edit,\n XCircle,\n Power,\n Users,\n Store,\n FlaskConical,\n Upload,\n Info,\n X,\n SendHorizontal,\n Package,\n ChevronRight,\n Check,\n CircleDollarSign,\n TrendingUp,\n Wallet,\n Gift,\n Lock,\n Link,\n Copy,\n} from \"lucide-react\";\nimport {\n CTAOverflowMenu,\n EmphasisPanel,\n GlassCard,\n type CTAAction,\n} from \"@burdenoff/fe-libs/ui\";\nimport { PageLayout, PageSection } from \"../components/PageLayout\";\nimport {\n InputField,\n TextareaField,\n SelectField,\n} from \"../components/FormField\";\nimport {\n StatusBadge,\n VerifiedBadge,\n FeaturedBadge,\n} from \"../components/StatusBadge\";\nimport { DataTable, DetailList } from \"../components/DataTable\";\nimport { NewSecretAlert } from \"../components/SecretDisplay\";\nimport { EmptyState } from \"../components/EmptyState\";\nimport { LoadingState } from \"../components/LoadingState\";\nimport { ConfirmDialog } from \"../components/ConfirmDialog\";\nimport { SelectionCheckbox } from \"../components/SelectionCheckbox\";\nimport { GrantDelegationModal } from \"../components/GrantDelegationModal\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport { usePackageUpload } from \"../hooks/usePackageUpload\";\nimport { nativeNotify } from \"../../utils/nativeBridge\";\nimport { DEVPORTAL_PERMISSIONS } from \"../constants/permissions\";\nimport { useDevportalPermission } from \"../hooks/usePermission\";\nimport type {\n Application,\n Webhook as WebhookType,\n ApplicationAnalytics,\n AppUserDelegation,\n DelegationStatus,\n} from \"../types\";\nimport { cn } from \"../utils/cn\";\nimport { APP_TYPE_LABELS } from \"../utils/constants\";\nimport {\n useGetApplicationQuery,\n useGetWebhooksQuery,\n useGetApplicationAnalyticsQuery,\n useGetApplicationVersionsQuery,\n type GetApplicationVersionsQuery,\n useCurrentUserDelegationsQuery,\n useDeactivateAppMutation,\n useRotateAppSecretMutation,\n useRevokeDelegationMutation,\n useUpdateApplicationMutation,\n useInstallApplicationMutation,\n useUninstallApplicationMutation,\n useGetWorkspaceInstallationQuery,\n useSubmitApplicationMutation,\n usePublishApplicationVersionMutation,\n useGetOrganizationQuery,\n type ApplicationScopeFieldsFragment,\n useShareWorkflowMutation,\n useUnshareWorkflowMutation,\n} from \"../../generated/global-operations\";\n\n// =============================================================================\n// HELPERS\n// =============================================================================\n\n/** Safely map GraphQL response to Application type */\nfunction mapToApplication(\n data: NonNullable<\n ReturnType<typeof useGetApplicationQuery>[\"data\"]\n >[\"application\"],\n): Application | null {\n if (!data) return null;\n return {\n id: data.id,\n name: data.name,\n slug: data.slug,\n shortDescription: data.shortDescription || undefined,\n description: data.description || undefined,\n appType: data.appType,\n status: data.status,\n visibility: data.visibility,\n tenantId: data.tenantId,\n developerId: data.developerId,\n developerOrganizationId: data.developerOrganizationId || undefined,\n category: data.category || undefined,\n tags: data.tags || [],\n keywords: data.keywords || [],\n iconUrl: data.iconUrl || undefined,\n bannerUrl: data.bannerUrl || undefined,\n screenshots: Array.isArray(data.screenshots) ? data.screenshots : undefined,\n videoUrl: data.videoUrl || undefined,\n websiteUrl: data.websiteUrl || undefined,\n documentationUrl: data.documentationUrl || undefined,\n supportUrl: data.supportUrl || undefined,\n privacyPolicyUrl: data.privacyPolicyUrl || undefined,\n termsOfServiceUrl: data.termsOfServiceUrl || undefined,\n githubUrl: data.githubUrl || undefined,\n pricingType: data.pricingType || undefined,\n pricingDetails: data.pricingDetails ?? undefined,\n manifest: data.manifest ?? undefined,\n installCount: data.installCount,\n activeInstallCount: data.activeInstallCount,\n averageRating: data.averageRating ?? undefined,\n reviewCount: data.reviewCount,\n submittedAt: data.submittedAt || undefined,\n publishedAt: data.publishedAt || undefined,\n lastReviewedAt: data.lastReviewedAt || undefined,\n reviewStatus: data.reviewStatus,\n isFeatured: data.isFeatured,\n isVerified: data.isVerified,\n requiresApproval: data.requiresApproval,\n appId: data.appId || undefined,\n scopes: data.scopes?.map((s: ApplicationScopeFieldsFragment) => ({\n id: s.id,\n applicationId: s.applicationId,\n scope: s.scope,\n description: s.description || undefined,\n isRequired: s.isRequired,\n createdAt: s.createdAt,\n })),\n createdAt: data.createdAt,\n updatedAt: data.updatedAt,\n };\n}\n\n/**\n * Note: OAuth client and API key mappers removed.\n * OAuth apps and API keys are now managed centrally via auth-svc\n * (see /oauth and /api-keys routes).\n */\n\n/** Map GraphQL webhook response to local Webhook type */\nfunction mapToWebhook(\n gqlWebhook: NonNullable<\n ReturnType<typeof useGetWebhooksQuery>[\"data\"]\n >[\"webhooks\"][number],\n): WebhookType {\n return {\n id: gqlWebhook.id,\n applicationId: gqlWebhook.applicationId,\n name: gqlWebhook.name,\n description: gqlWebhook.description || undefined,\n url: gqlWebhook.url,\n secret: gqlWebhook.secret,\n events: gqlWebhook.events,\n isActive: gqlWebhook.isActive,\n status: gqlWebhook.status,\n maxRetries: gqlWebhook.maxRetries,\n retryDelay: gqlWebhook.retryDelay,\n retryEnabled: gqlWebhook.retryEnabled,\n lastTriggeredAt: gqlWebhook.lastTriggeredAt || undefined,\n lastSuccessAt: gqlWebhook.lastSuccessAt || undefined,\n lastFailureAt: gqlWebhook.lastFailureAt || undefined,\n lastFailureReason: gqlWebhook.lastFailureReason || undefined,\n failureCount: gqlWebhook.failureCount,\n successCount: gqlWebhook.successCount,\n createdAt: gqlWebhook.createdAt,\n updatedAt: gqlWebhook.updatedAt,\n };\n}\n\n/** Map GraphQL analytics response to local ApplicationAnalytics type */\nfunction mapToAnalytics(\n gqlAnalytics: NonNullable<\n ReturnType<typeof useGetApplicationAnalyticsQuery>[\"data\"]\n >[\"applicationAnalytics\"][number],\n): ApplicationAnalytics {\n return {\n id: gqlAnalytics.id,\n applicationId: gqlAnalytics.applicationId,\n date: gqlAnalytics.date,\n period: gqlAnalytics.period,\n apiCalls: gqlAnalytics.apiCalls,\n errors: gqlAnalytics.errors,\n sessions: gqlAnalytics.sessions,\n activeUsers: gqlAnalytics.activeUsers,\n newUsers: gqlAnalytics.newUsers,\n avgResponseTime: gqlAnalytics.avgResponseTime ?? undefined,\n avgSessionDuration: gqlAnalytics.avgSessionDuration ?? undefined,\n createdAt: gqlAnalytics.createdAt,\n };\n}\n\n/** Map GraphQL delegation response to local AppUserDelegation type */\nfunction mapToDelegation(\n gqlDelegation: NonNullable<\n ReturnType<typeof useCurrentUserDelegationsQuery>[\"data\"]\n >[\"currentUserDelegations\"][number],\n): AppUserDelegation {\n return {\n id: gqlDelegation.id,\n appId: gqlDelegation.appId,\n app: {\n id: gqlDelegation.app.id,\n name: gqlDelegation.app.name,\n description: gqlDelegation.app.description || undefined,\n type: gqlDelegation.app.type,\n status: gqlDelegation.app.status,\n },\n userId: gqlDelegation.userId,\n scopes: gqlDelegation.scopes,\n workspaceIds: gqlDelegation.workspaceIds ?? [],\n status: gqlDelegation.status as DelegationStatus,\n grantedAt: gqlDelegation.grantedAt,\n grantedBy: gqlDelegation.grantedBy,\n expiresAt: gqlDelegation.expiresAt || undefined,\n revokedAt: gqlDelegation.revokedAt || undefined,\n revokedBy: gqlDelegation.revokedBy || undefined,\n };\n}\n\n// =============================================================================\n// TAB DEFINITIONS\n// =============================================================================\n\ntype TabId =\n | \"overview\"\n | \"permissions\"\n | \"webhooks\"\n | \"delegations\"\n | \"analytics\"\n | \"playground\"\n | \"store-listing\"\n | \"versions\"\n | \"pricing\"\n | \"oauth\"\n | \"api-keys\";\n\nconst tabs: Array<{ id: TabId; label: string; icon: FC<{ size?: number }> }> = [\n { id: \"overview\", label: \"Overview\", icon: AppWindow },\n { id: \"analytics\", label: \"Analytics\", icon: BarChart3 },\n { id: \"store-listing\", label: \"Store Listing\", icon: Store },\n { id: \"versions\", label: \"Versions\", icon: Package },\n { id: \"pricing\", label: \"Pricing\", icon: CircleDollarSign },\n { id: \"permissions\", label: \"Permissions\", icon: Shield },\n { id: \"webhooks\", label: \"Webhooks\", icon: Webhook },\n { id: \"delegations\", label: \"Delegations\", icon: Users },\n { id: \"playground\", label: \"API Playground\", icon: ExternalLink },\n { id: \"oauth\", label: \"OAuth\", icon: Lock },\n { id: \"api-keys\", label: \"API Keys\", icon: Key },\n];\n\n// =============================================================================\n// DELEGATION STATUS HELPERS\n// =============================================================================\n\nconst DELEGATION_STATUS_STYLES: Record<DelegationStatus, string> = {\n ACTIVE: \"bg-status-success-bg-subtle text-status-success-text\",\n REVOKED: \"bg-status-error-bg-subtle text-status-error-text\",\n EXPIRED: \"bg-bg-sunken text-text-secondary\",\n};\n\n// =============================================================================\n// TAB LOADING SPINNER\n// =============================================================================\n\nconst TabLoadingSpinner: FC<{ message?: string }> = ({\n message = \"Loading...\",\n}) => (\n <div className=\"flex items-center justify-center gap-3 py-12\">\n <Loader2 size={20} className=\"animate-spin text-text-secondary\" />\n <p className=\"text-sm text-text-secondary\">{message}</p>\n </div>\n);\n\nconst TabErrorState: FC<{ message: string }> = ({ message }) => (\n <div className=\"flex flex-col items-center justify-center gap-2 py-12 text-center\">\n <AlertCircle size={32} className=\"text-status-error-text\" />\n <p className=\"text-sm text-text-secondary\">{message}</p>\n </div>\n);\n\n// =============================================================================\n// MAIN PAGE COMPONENT\n// =============================================================================\n\n/**\n * Application detail page with tabbed navigation\n */\nexport const ApplicationDetailPage: FC = () => {\n const { navigate, basePath, workspaceId } = useDevportal();\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 const { allowed: canUpdate } = useDevportalPermission(\n DEVPORTAL_PERMISSIONS.APP_UPDATE,\n );\n const { allowed: canDelete } = useDevportalPermission(\n DEVPORTAL_PERMISSIONS.APP_DELETE,\n );\n const { appId } = useParams<{ appId: string }>();\n const [activeTab, setActiveTab] = useState<TabId>(\"overview\");\n\n // ---- Dialogs ----\n const [showRotateSecretDialog, setShowRotateSecretDialog] = useState(false);\n const [showDeactivateDialog, setShowDeactivateDialog] = useState(false);\n const [newSecret, setNewSecret] = useState<string | null>(null);\n const [showDelegationModal, setShowDelegationModal] = useState(false);\n\n // ---- Application query ----\n const { data, loading, error, refetch } = useGetApplicationQuery({\n variables: { id: appId! },\n skip: !appId,\n });\n\n // ---- Mutations ----\n const [rotateAppSecret, { loading: rotateLoading }] =\n useRotateAppSecretMutation();\n const [deactivateApp, { loading: deactivateLoading }] =\n useDeactivateAppMutation();\n const [submitApplication, { loading: isSubmitting }] =\n useSubmitApplicationMutation();\n const [publishApplicationVersion] = usePublishApplicationVersionMutation();\n const [installApplication, { loading: installLoading }] =\n useInstallApplicationMutation();\n const [uninstallApplication, { loading: uninstallLoading }] =\n useUninstallApplicationMutation();\n const [shareWorkflow, { loading: shareLoading }] = useShareWorkflowMutation();\n const [unshareWorkflow, { loading: unshareLoading }] =\n useUnshareWorkflowMutation();\n const [linkCopied, setLinkCopied] = useState(false);\n\n // ---- Workspace installation status ----\n const { data: installationData, refetch: refetchInstallation } =\n useGetWorkspaceInstallationQuery({\n variables: {\n applicationId: appId,\n workspaceId: workspaceId ?? undefined,\n },\n skip: !workspaceId || !appId,\n fetchPolicy: \"cache-and-network\",\n });\n const activeInstallation =\n installationData?.appInstallations?.edges?.[0]?.node ?? null;\n\n // ---- Developer org (for platformFeeRate + billingAccountId) ----\n const { data: orgData } = useGetOrganizationQuery({\n variables: { id: data?.application?.developerOrganizationId ?? \"\" },\n skip: !data?.application?.developerOrganizationId,\n fetchPolicy: \"cache-first\",\n });\n\n const handleNavigate = useCallback(\n (path: string) => {\n navigate?.(`${basePath}${path}`);\n },\n [navigate, basePath],\n );\n\n // ---- Rotate Secret ----\n const handleRotateSecret = useCallback(async () => {\n const authAppId = data?.application?.appId;\n if (!authAppId) return;\n try {\n const result = await rotateAppSecret({ variables: { id: authAppId } });\n const secret = result.data?.rotateAppSecret.clientSecret;\n if (secret) {\n setNewSecret(secret);\n }\n setShowRotateSecretDialog(false);\n } catch {\n // Error is displayed via Apollo error state\n }\n }, [data?.application?.appId, rotateAppSecret]);\n\n // ---- Deactivate App ----\n const handleDeactivateApp = useCallback(async () => {\n if (!appId) return;\n try {\n await deactivateApp({ variables: { id: appId } });\n setShowDeactivateDialog(false);\n handleNavigate(\"/apps\");\n } catch {\n // Error is displayed via Apollo error state\n }\n }, [appId, deactivateApp, handleNavigate]);\n\n // ---- Test in Workspace ----\n const handleTestInWorkspace = useCallback(async () => {\n if (!appId || !workspaceId) return;\n try {\n await installApplication({\n variables: {\n input: {\n applicationId: appId,\n scope: \"WORKSPACE\" as const,\n workspaceId,\n autoUpdate: false,\n },\n },\n });\n void refetchInstallation();\n void nativeNotify(\"success\");\n } catch (err) {\n console.error(\"[DevPortal] Test in Workspace failed:\", err);\n void nativeNotify(\"error\");\n }\n }, [appId, workspaceId, installApplication, refetchInstallation]);\n\n // ---- Uninstall from Workspace ----\n const handleUninstall = useCallback(\n async (installationId: string) => {\n try {\n await uninstallApplication({ variables: { id: installationId } });\n void refetchInstallation();\n void nativeNotify(\"success\");\n } catch {\n void nativeNotify(\"error\");\n }\n },\n [uninstallApplication, refetchInstallation],\n );\n\n // ---- Submit for Review ----\n // Must stay before early returns (Rules of Hooks).\n const handleSubmitForReview = useCallback(async () => {\n if (!appId) return;\n try {\n // Auto-publish all draft versions so they go into review together with the app.\n const draftVersions = (data?.application?.versions?.edges ?? [])\n .map((e: { node: { id: string; status: string } }) => e.node)\n .filter((v: { id: string; status: string }) => v.status === \"draft\");\n for (const v of draftVersions) {\n await publishApplicationVersion({ variables: { id: v.id } });\n }\n await submitApplication({ variables: { id: appId } });\n void nativeNotify(\"success\");\n } catch (err) {\n console.error(\"[DevPortal] Submit failed:\", err);\n void nativeNotify(\"error\");\n } finally {\n void refetch();\n }\n }, [\n appId,\n data?.application?.versions?.edges,\n publishApplicationVersion,\n submitApplication,\n refetch,\n ]);\n\n // ---- Loading / Error / Not Found ----\n // Only show full-page loading on initial load (no cached data yet).\n // With cache-and-network, Apollo sets loading:true on background refetches even\n // when data is already in cache — guarding on !data prevents StoreListingTab\n // (and other tab panels) from unmounting and losing their local form state.\n if (loading && !data) {\n return (\n <LoadingState\n message={tr(\"devportal.loadingApplication\", \"Loading application...\")}\n />\n );\n }\n\n if (error) {\n return (\n <PageLayout\n title={tr(\"devportal.error\", \"Error\")}\n backLink={`${basePath}/apps`}\n backLabel={tr(\"devportal.backToApplications\", \"Back to Applications\")}\n >\n <div className=\"flex flex-col items-center justify-center py-12 text-center\">\n <AlertCircle size={48} className=\"text-status-error-text mb-4\" />\n <h3 className=\"text-lg font-semibold mb-2\">\n {tr(\n \"devportal.failedToLoadApplication\",\n \"Failed to load application\",\n )}\n </h3>\n <p className=\"text-sm text-text-secondary\">{error.message}</p>\n </div>\n </PageLayout>\n );\n }\n\n const app = mapToApplication(data?.application);\n\n if (!app) {\n return (\n <PageLayout\n title={tr(\"devportal.notFound\", \"Not Found\")}\n backLink={`${basePath}/apps`}\n backLabel={tr(\"devportal.backToApplications\", \"Back to Applications\")}\n >\n <EmptyState\n illustration=\"empty-generic\"\n icon={<AppWindow size={48} />}\n title={tr(\"devportal.applicationNotFound\", \"Application not found\")}\n description={tr(\n \"devportal.applicationNotFoundDescription\",\n \"The application you're looking for doesn't exist or you don't have access to it.\",\n )}\n />\n </PageLayout>\n );\n }\n\n const isPackageApp = app.appType === \"NODE\" || app.appType === \"WORKFLOW\";\n const isIntegrationApp = app.appType === \"API_INTEGRATION\";\n const versionCount = data?.application?.versions?.totalCount ?? 0;\n const isPaidApp = app.pricingType === \"PAID\";\n const devOrg = orgData?.developerOrganization;\n const platformFeeRate = devOrg?.platformFeeRate ?? 0.3;\n const billingAccountLinked = !!devOrg?.billingAccountId;\n\n // Pricing is \"done\" when the developer has explicitly chosen FREE or set a PAID price in credits\n const pricingDetailsRaw = (app.pricingDetails ?? {}) as Record<\n string,\n unknown\n >;\n const pricingDone =\n app.pricingType === \"FREE\" ||\n (app.pricingType === \"PAID\" &&\n typeof pricingDetailsRaw.price === \"number\" &&\n (pricingDetailsRaw.price as number) > 0);\n\n // Readiness: store listing + icon + version (pkg/integration) + billing acct (paid) + pricing chosen\n const isReadyToSubmit =\n !!app.description?.trim() &&\n !!app.category &&\n !!app.iconUrl &&\n (app.visibility === \"PUBLIC\" || app.visibility === \"UNLISTED\") &&\n ((!isPackageApp && !isIntegrationApp) || versionCount > 0) &&\n (!isPaidApp || billingAccountLinked) &&\n pricingDone;\n\n const canSubmit =\n isReadyToSubmit && app.status !== \"PUBLISHED\" && app.status !== \"SUBMITTED\";\n\n const headerActions: CTAAction[] = [\n ...(!isPackageApp\n ? [\n {\n label: tr(\"devportal.rotateSecret\", \"Rotate Secret\"),\n icon: <RefreshCw size={16} />,\n disabled: !app.appId,\n onSelect: () => setShowRotateSecretDialog(true),\n },\n ]\n : []),\n ...(!isPackageApp\n ? activeInstallation\n ? [\n {\n label: tr(\n \"devportal.uninstallFromWorkspace\",\n \"Uninstall from Workspace\",\n ),\n icon: <XCircle size={16} />,\n disabled: uninstallLoading || !workspaceId,\n onSelect: () => void handleUninstall(activeInstallation.id),\n },\n ]\n : [\n {\n label: tr(\"devportal.testInWorkspace\", \"Test in Workspace\"),\n icon: <FlaskConical size={16} />,\n disabled: installLoading || !workspaceId,\n onSelect: () => void handleTestInWorkspace(),\n },\n ]\n : []),\n {\n label: tr(\"devportal.deactivate\", \"Deactivate\"),\n icon: <Power size={16} />,\n intent: \"destructive\" as const,\n disabled: !canDelete,\n onSelect: () => setShowDeactivateDialog(true),\n },\n ];\n\n return (\n <PageLayout\n title={app.name}\n description={app.shortDescription}\n purpose={tr(\n \"devportal.appDetailPurpose\",\n \"Everything about this application in one place — its credentials, the permissions and webhooks it uses, its analytics, and its store listing. Use the tabs to configure each area, then edit or publish when it is ready.\",\n )}\n backLink={`${basePath}/apps`}\n backLabel={tr(\"devportal.backToApplications\", \"Back to Applications\")}\n actions={\n <div className=\"flex items-center gap-2\">\n {app.status === \"SUBMITTED\" ? (\n <div className=\"flex items-center gap-1.5 rounded-full border border-status-warning-bg bg-status-warning-bg-subtle px-3 py-1.5 text-xs font-medium text-status-warning-text\">\n <Clock size={13} />\n {tr(\"devportal.underReview\", \"Under Review\")}\n </div>\n ) : app.status !== \"PUBLISHED\" ? (\n <button\n type=\"button\"\n onClick={() => void handleSubmitForReview()}\n disabled={!canSubmit || isSubmitting}\n title={\n !isReadyToSubmit\n ? [\n !app.description?.trim() && \"Add full description\",\n !app.category && \"Select a category\",\n !app.iconUrl && \"Upload an app icon\",\n app.visibility === \"PRIVATE\" &&\n \"Set visibility to Public/Unlisted\",\n isPackageApp &&\n versionCount === 0 &&\n \"Upload at least one version\",\n !pricingDone &&\n \"Set pricing (choose Free or Paid in the Pricing tab)\",\n isPaidApp &&\n !billingAccountLinked &&\n \"Link a billing account to receive payments\",\n ]\n .filter(Boolean)\n .join(\" · \")\n : undefined\n }\n className={cn(\n \"inline-flex items-center gap-2 rounded-md px-5 py-2 text-sm font-medium whitespace-nowrap transition-colors\",\n canSubmit && !isSubmitting\n ? \"bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg/90 cursor-pointer\"\n : \"cursor-not-allowed bg-bg-muted text-text-tertiary ring-1 ring-border-subtle\",\n )}\n >\n {isSubmitting ? (\n <>\n <Loader2 size={15} className=\"animate-spin\" />\n {tr(\"devportal.submitting\", \"Submitting…\")}\n </>\n ) : (\n <>\n <SendHorizontal size={15} />\n {tr(\"devportal.submitForReview\", \"Submit for Review\")}\n </>\n )}\n </button>\n ) : null}\n <CTAOverflowMenu\n primary={{\n label: tr(\"devportal.editApp\", \"Edit App\"),\n icon: <Edit size={16} />,\n disabled: !canUpdate,\n onSelect: () => handleNavigate(`/apps/${app.id}/edit`),\n }}\n actions={headerActions}\n />\n </div>\n }\n >\n {/* New Secret Alert (shown after rotation) */}\n {newSecret && (\n <NewSecretAlert\n title={tr(\n \"devportal.newAppSecretGenerated\",\n \"New App Secret Generated\",\n )}\n secret={newSecret}\n description={tr(\n \"devportal.appSecretRotatedDescription\",\n \"Your app secret has been rotated. The old secret is no longer valid.\",\n )}\n onDismiss={() => setNewSecret(null)}\n />\n )}\n\n {/* Status badges */}\n <div className=\"flex flex-wrap items-center gap-2\">\n <StatusBadge status={app.status} type=\"app\" />\n <StatusBadge status={app.visibility} type=\"app\" />\n {app.isVerified && <VerifiedBadge verified />}\n {app.isFeatured && <FeaturedBadge />}\n <span className=\"text-sm text-text-secondary\">\n {APP_TYPE_LABELS[app.appType] || app.appType}\n </span>\n </div>\n\n {/* Share as public link — AUTOMATION apps only */}\n {app.appType === \"AUTOMATION\" && (\n <div className=\"rounded-lg border border-border-subtle bg-bg-elevated p-4\">\n <div className=\"flex items-start justify-between gap-4\">\n <div className=\"flex items-start gap-3\">\n <div className=\"mt-0.5 flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full bg-action-primary-bg-subtle\">\n <Link size={15} className=\"text-action-primary-text\" />\n </div>\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {tr(\n \"devportal.shareWorkflow.title\",\n \"Share as Public Link\",\n )}\n </p>\n <p className=\"mt-0.5 text-xs text-text-secondary\">\n {app.visibility === \"UNLISTED\"\n ? tr(\n \"devportal.shareWorkflow.activeDesc\",\n \"Anyone with the link can preview and copy this workflow into their FluidGrids workspace.\",\n )\n : tr(\n \"devportal.shareWorkflow.inactiveDesc\",\n \"Generate a public link anyone can use to copy this workflow into their own FluidGrids workspace — no store review needed.\",\n )}\n </p>\n {app.visibility === \"UNLISTED\" && appId && (\n <div className=\"mt-2 flex items-center gap-2\">\n <code className=\"rounded bg-bg-canvas px-2 py-1 text-xs text-text-secondary\">\n {`${window.location.protocol}//${window.location.host.replace(/^app\\./, \"app.fluidgrids.com\").replace(/localhost:\\d+/, \"app.fluidgrids.com\")}/shared/${appId}`}\n </code>\n <button\n type=\"button\"\n className=\"flex items-center gap-1 rounded px-2 py-1 text-xs text-action-primary-text hover:bg-action-primary-bg-subtle transition-colors\"\n onClick={() => {\n const url = `${window.location.protocol}//${window.location.host}/shared/${appId}`;\n void navigator.clipboard.writeText(url).then(() => {\n setLinkCopied(true);\n setTimeout(() => setLinkCopied(false), 2000);\n });\n }}\n >\n {linkCopied ? (\n <Check size={12} />\n ) : (\n <Copy size={12} />\n )}\n {linkCopied\n ? tr(\"devportal.copied\", \"Copied!\")\n : tr(\"devportal.copyLink\", \"Copy Link\")}\n </button>\n </div>\n )}\n </div>\n </div>\n <button\n type=\"button\"\n disabled={shareLoading || unshareLoading || !app.manifest}\n title={\n !app.manifest\n ? tr(\n \"devportal.shareWorkflow.noManifestHint\",\n \"Add a workflow manifest before sharing\",\n )\n : undefined\n }\n onClick={() => {\n if (app.visibility === \"UNLISTED\") {\n void unshareWorkflow({ variables: { id: appId! } }).then(\n () => void refetch(),\n );\n } else {\n void shareWorkflow({ variables: { id: appId! } }).then(\n () => void refetch(),\n );\n }\n }}\n className={`flex-shrink-0 rounded-full px-3 py-1.5 text-xs font-medium transition-colors ${\n app.visibility === \"UNLISTED\"\n ? \"border border-status-error-bg text-status-error-text hover:bg-status-error-bg-subtle\"\n : \"bg-action-primary-bg text-text-on-action hover:opacity-90 disabled:opacity-50\"\n }`}\n >\n {shareLoading || unshareLoading ? (\n <Loader2 size={12} className=\"animate-spin\" />\n ) : app.visibility === \"UNLISTED\" ? (\n tr(\"devportal.shareWorkflow.stopSharing\", \"Stop Sharing\")\n ) : (\n tr(\"devportal.shareWorkflow.share\", \"Share Link\")\n )}\n </button>\n </div>\n </div>\n )}\n\n {/* Review status banner */}\n {app.status === \"SUBMITTED\" && (\n <div className=\"flex items-start gap-3 rounded-lg border border-border-subtle bg-status-warning-bg-subtle p-4\">\n <Clock\n size={18}\n className=\"text-status-warning-text mt-0.5 flex-shrink-0\"\n />\n <div className=\"text-sm\">\n <p className=\"font-medium text-status-warning-text\">\n {tr(\"devportal.underReview\", \"Under Review\")}\n </p>\n <p className=\"mt-0.5 text-text-secondary\">\n {tr(\n \"devportal.underReviewDesc\",\n \"Your submission is being reviewed by our team. You'll be notified of the outcome.\",\n )}\n {app.submittedAt && (\n <span className=\"ml-1\">\n Submitted {new Date(app.submittedAt).toLocaleDateString()}.\n </span>\n )}\n </p>\n </div>\n </div>\n )}\n {app.status === \"REJECTED\" && (\n <div className=\"flex items-start gap-3 rounded-lg border border-status-error-bg bg-status-error-bg-subtle p-4\">\n <XCircle\n size={18}\n className=\"text-status-error-text mt-0.5 flex-shrink-0\"\n />\n <div className=\"text-sm\">\n <p className=\"font-medium text-status-error-text\">\n {tr(\"devportal.reviewRejected\", \"Review Rejected\")}\n </p>\n <p className=\"mt-0.5 text-text-secondary\">\n {app.reviewNotes ||\n tr(\n \"devportal.reviewRejectedDesc\",\n \"Your submission was not approved. Please review the feedback, update your app, and re-submit.\",\n )}\n </p>\n <button\n type=\"button\"\n onClick={() => handleNavigate(`/apps/${app.id}/edit`)}\n className=\"mt-2 inline-flex items-center gap-1 text-xs font-medium text-primary underline\"\n >\n {tr(\"devportal.editAndResubmit\", \"Edit app and re-submit →\")}\n </button>\n </div>\n </div>\n )}\n {app.status === \"PUBLISHED\" && (\n <div className=\"flex items-start gap-3 rounded-lg border border-status-success-bg bg-status-success-bg-subtle p-4\">\n <CheckCircle\n size={18}\n className=\"text-status-success-text mt-0.5 flex-shrink-0\"\n />\n <div className=\"text-sm\">\n <p className=\"font-medium text-status-success-text\">\n {tr(\"devportal.liveInStore\", \"Live in the Store\")}\n </p>\n <p className=\"mt-0.5 text-text-secondary\">\n {tr(\n \"devportal.liveInStoreDesc\",\n \"Your app is published and visible to users in the marketplace.\",\n )}\n </p>\n </div>\n </div>\n )}\n\n {/* Setup wizard — shown when the app is in DRAFT or REJECTED and not yet ready */}\n {(app.status === \"DRAFT\" || app.status === \"REJECTED\") &&\n !isReadyToSubmit &&\n (() => {\n const storeDone =\n !!app.description?.trim() &&\n !!app.category &&\n !!app.iconUrl &&\n (app.visibility === \"PUBLIC\" || app.visibility === \"UNLISTED\");\n const versionsDone =\n (!isPackageApp && !isIntegrationApp) || versionCount > 0;\n const storeHints = [\n !app.description?.trim() && \"Add a full description\",\n !app.category && \"Select a category\",\n !app.iconUrl && \"Upload an app icon\",\n app.visibility === \"PRIVATE\" &&\n \"Set visibility to Public or Unlisted\",\n ].filter(Boolean) as string[];\n\n const wizardSteps = [\n {\n id: \"store\",\n label: tr(\n \"devportal.setupStoreListingStep\",\n \"Complete Store Listing\",\n ),\n hint: storeDone\n ? tr(\"devportal.done\", \"Done\")\n : storeHints.join(\" · \"),\n done: storeDone,\n onClick: () => setActiveTab(\"store-listing\"),\n },\n ...(isPackageApp\n ? [\n {\n id: \"version\",\n label: tr(\"devportal.setupVersionStep\", \"Upload a Version\"),\n hint: versionsDone\n ? tr(\"devportal.done\", \"Done\")\n : tr(\n \"devportal.uploadVersionHint\",\n \"Upload your ZIP bundle and manifest\",\n ),\n done: versionsDone,\n onClick: () => setActiveTab(\"versions\"),\n },\n ]\n : []),\n ...(isIntegrationApp\n ? [\n {\n id: \"version\",\n label: tr(\n \"devportal.setupIntegrationVersionStep\",\n \"Publish a Version\",\n ),\n hint: versionsDone\n ? tr(\"devportal.done\", \"Done\")\n : tr(\n \"devportal.integrationVersionHint\",\n \"Define required scopes and publish your first API version\",\n ),\n done: versionsDone,\n onClick: () => setActiveTab(\"versions\"),\n },\n {\n id: \"webhooks\",\n label: tr(\n \"devportal.setupWebhooksStep\",\n \"Configure Webhooks\",\n ),\n hint: tr(\n \"devportal.webhooksOptionalHint\",\n \"Set up endpoints to receive platform events (optional)\",\n ),\n done: false,\n onClick: () => setActiveTab(\"webhooks\"),\n },\n ]\n : []),\n {\n id: \"pricing\",\n label: tr(\"devportal.setupPricingStep\", \"Set Pricing\"),\n hint: pricingDone\n ? tr(\"devportal.done\", \"Done\")\n : tr(\n \"devportal.pricingHint\",\n \"Choose Free or set a credit price in the Pricing tab\",\n ),\n done: pricingDone,\n onClick: () => setActiveTab(\"pricing\"),\n },\n ...(isPaidApp\n ? [\n {\n id: \"billing\",\n label: tr(\n \"devportal.setupBillingStep\",\n \"Link Billing Account\",\n ),\n hint: billingAccountLinked\n ? tr(\"devportal.done\", \"Done\")\n : tr(\n \"devportal.billingAccountHint\",\n \"Link a billing account to receive payouts — required for paid apps\",\n ),\n done: billingAccountLinked,\n onClick: () => setActiveTab(\"pricing\"),\n },\n ]\n : []),\n {\n id: \"submit\",\n label: tr(\"devportal.submitForReview\", \"Submit for Review\"),\n hint: isReadyToSubmit\n ? tr(\n \"devportal.readyToSubmit\",\n \"Ready — click Submit for Review above\",\n )\n : !app.description?.trim()\n ? tr(\n \"devportal.hintMissingDescription\",\n \"Add a full description on the Store Listing tab\",\n )\n : !app.category\n ? tr(\n \"devportal.hintMissingCategory\",\n \"Select a category on the Store Listing tab\",\n )\n : !app.iconUrl\n ? tr(\n \"devportal.hintMissingIcon\",\n \"Upload an app icon on the Store Listing tab\",\n )\n : app.visibility === \"PRIVATE\"\n ? tr(\n \"devportal.hintPrivateVisibility\",\n \"Set visibility to Public or Unlisted\",\n )\n : (isPackageApp || isIntegrationApp) &&\n versionCount === 0\n ? tr(\n \"devportal.hintMissingVersion\",\n \"Upload at least one version\",\n )\n : !pricingDone\n ? tr(\n \"devportal.hintMissingPricing\",\n \"Choose Free or set a credit price in the Pricing tab\",\n )\n : isPaidApp && !billingAccountLinked\n ? tr(\n \"devportal.hintMissingBilling\",\n \"Link a billing account in the Pricing tab to receive payouts\",\n )\n : tr(\n \"devportal.completeStepsFirst\",\n \"Complete the steps above first\",\n ),\n done: false,\n onClick: undefined as (() => void) | undefined,\n },\n ];\n const completedCount = wizardSteps.filter((s) => s.done).length;\n\n return (\n <div className=\"rounded-xl border border-border-subtle bg-bg-surface shadow-sm\">\n <div className=\"flex items-center justify-between border-b border-border-subtle px-5 py-4\">\n <div className=\"flex items-center gap-3\">\n <div className=\"flex h-8 w-8 items-center justify-center rounded-full bg-action-primary-bg/10\">\n <Store size={16} className=\"text-primary\" />\n </div>\n <div>\n <p className=\"text-sm font-semibold text-text-primary\">\n {tr(\"devportal.completeSetup\", \"Complete your app setup\")}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {completedCount} of{\" \"}\n {wizardSteps.filter((s) => s.id !== \"submit\").length}{\" \"}\n {tr(\"devportal.stepsDone\", \"steps complete\")}\n </p>\n </div>\n </div>\n </div>\n <div className=\"divide-y divide-border-subtle\">\n {wizardSteps.map((step, idx) => (\n <button\n key={step.id}\n type=\"button\"\n onClick={step.onClick}\n disabled={!step.onClick}\n className={cn(\n \"w-full flex items-center gap-4 px-5 py-4 text-left transition-colors\",\n step.onClick\n ? \"hover:bg-bg-sunken/40 cursor-pointer\"\n : \"cursor-default opacity-60\",\n )}\n >\n <div\n className={cn(\n \"flex h-7 w-7 flex-shrink-0 items-center justify-center rounded-full text-xs font-bold\",\n step.done\n ? \"bg-status-success-bg text-status-success-text\"\n : \"border-2 border-border-subtle bg-bg-sunken text-text-secondary\",\n )}\n >\n {step.done ? <Check size={13} /> : idx + 1}\n </div>\n <div className=\"flex-1 min-w-0\">\n <p\n className={cn(\n \"text-sm font-medium\",\n step.done\n ? \"text-text-secondary line-through\"\n : \"text-text-primary\",\n )}\n >\n {step.label}\n </p>\n {step.hint && !step.done && (\n <p className=\"mt-0.5 text-xs text-text-secondary truncate\">\n {step.hint}\n </p>\n )}\n </div>\n {step.onClick && !step.done && (\n <ChevronRight\n size={16}\n className=\"flex-shrink-0 text-text-secondary\"\n />\n )}\n </button>\n ))}\n </div>\n </div>\n );\n })()}\n\n {/* Tabs */}\n <div className=\"border-b\">\n <nav\n className=\"-mb-px flex gap-4 overflow-x-auto\"\n role=\"tablist\"\n aria-label={tr(\n \"devportal.applicationSections\",\n \"Application sections\",\n )}\n >\n {tabs\n .filter((tab) => {\n // Package apps (NODE/WORKFLOW): hide integration-only tabs\n if (\n isPackageApp &&\n (tab.id === \"permissions\" ||\n tab.id === \"webhooks\" ||\n tab.id === \"delegations\" ||\n tab.id === \"playground\" ||\n tab.id === \"oauth\" ||\n tab.id === \"api-keys\")\n ) {\n return false;\n }\n // Non-package apps: hide versions tab unless it's an integration app\n if (!isPackageApp && !isIntegrationApp && tab.id === \"versions\") {\n return false;\n }\n // OAuth and API Keys only for integration apps\n if (\n !isIntegrationApp &&\n (tab.id === \"oauth\" || tab.id === \"api-keys\")\n ) {\n return false;\n }\n return true;\n })\n .map((tab) => {\n const Icon = tab.icon;\n return (\n <button\n key={tab.id}\n id={`application-tab-${tab.id}`}\n role=\"tab\"\n aria-selected={activeTab === tab.id}\n aria-controls={`application-panel-${tab.id}`}\n onClick={() => setActiveTab(tab.id)}\n className={cn(\n \"flex items-center gap-2 border-b-2 px-1 py-3 text-sm font-medium transition-colors\",\n activeTab === tab.id\n ? \"border-primary text-primary\"\n : \"border-transparent text-text-secondary hover:text-text-primary hover:border-muted-foreground\",\n )}\n >\n <Icon size={16} />\n {tab.label}\n </button>\n );\n })}\n </nav>\n </div>\n\n {/* Tab content */}\n <div\n className=\"mt-6\"\n id={`application-panel-${activeTab}`}\n role=\"tabpanel\"\n aria-labelledby={`application-tab-${activeTab}`}\n tabIndex={0}\n >\n {activeTab === \"overview\" && <OverviewTab app={app} />}\n {activeTab === \"permissions\" && (\n <PermissionsTab\n app={app}\n versionScopes={\n (data?.application?.versions?.edges?.[0]?.node?.requiredScopes ??\n []) as string[]\n }\n locked={\n app.status === \"PUBLISHED\" ||\n app.status === \"APPROVED\" ||\n app.status === \"ACTIVE\"\n }\n onNavigateToVersions={() => setActiveTab(\"versions\")}\n />\n )}\n {activeTab === \"webhooks\" && (\n <WebhooksTabConnected appId={app.id} onNavigate={handleNavigate} />\n )}\n {activeTab === \"delegations\" && (\n <DelegationsTabConnected\n authAppId={app.appId || undefined}\n appName={app.name}\n onGrantDelegation={() => setShowDelegationModal(true)}\n onNavigate={handleNavigate}\n />\n )}\n {activeTab === \"analytics\" && <AnalyticsTabConnected appId={app.id} />}\n {activeTab === \"playground\" && <ApiPlaygroundTab app={app} />}\n {activeTab === \"oauth\" && (\n <OAuthTabConnected appId={app.id} onNavigate={handleNavigate} />\n )}\n {activeTab === \"api-keys\" && (\n <ApiKeysTabConnected appId={app.id} onNavigate={handleNavigate} />\n )}\n {activeTab === \"store-listing\" && (\n <StoreListingTab\n app={app}\n versionCount={data?.application?.versions?.totalCount ?? 0}\n isPackageApp={isPackageApp}\n pricingDone={pricingDone}\n onNavigateToVersions={\n isPackageApp || isIntegrationApp\n ? () => setActiveTab(\"versions\")\n : undefined\n }\n onNavigateToPricing={() => setActiveTab(\"pricing\")}\n onNavigateToSubmission={() =>\n handleNavigate(`/apps/${app.id}/store-submission`)\n }\n />\n )}\n {activeTab === \"pricing\" && (\n <PricingTab\n app={app}\n platformFeeRate={platformFeeRate}\n billingAccountLinked={billingAccountLinked}\n onNavigateToRevenue={() => handleNavigate(\"/revenue\")}\n isReadyToSubmit={isReadyToSubmit}\n />\n )}\n {activeTab === \"versions\" && (\n <VersionsTabConnected\n appId={app.id}\n onNavigate={handleNavigate}\n pricingDone={pricingDone}\n onNavigateToPricing={() => setActiveTab(\"pricing\")}\n />\n )}\n </div>\n\n {/* Rotate Secret Confirmation */}\n <ConfirmDialog\n open={showRotateSecretDialog}\n onOpenChange={setShowRotateSecretDialog}\n onConfirm={handleRotateSecret}\n title={tr(\"devportal.rotateAppSecret\", \"Rotate App Secret\")}\n description={tr(\n \"devportal.rotateAppSecretDescription\",\n \"This will generate a new client secret and invalidate the current one. All existing integrations using the old secret will stop working immediately.\",\n )}\n confirmLabel={tr(\"devportal.rotateSecret\", \"Rotate Secret\")}\n cancelLabel={tr(\"devportal.cancel\", \"Cancel\")}\n variant=\"warning\"\n loading={rotateLoading}\n />\n\n {/* Deactivate App Confirmation */}\n <ConfirmDialog\n open={showDeactivateDialog}\n onOpenChange={setShowDeactivateDialog}\n onConfirm={handleDeactivateApp}\n title={tr(\"devportal.deactivateApplication\", \"Deactivate Application\")}\n description={tr(\n \"devportal.deactivateApplicationDescription\",\n \"This will deactivate the application. All OAuth clients, API keys, and webhooks associated with this app will stop functioning. This action can be reversed by reactivating the app.\",\n )}\n confirmLabel={tr(\"devportal.deactivate\", \"Deactivate\")}\n cancelLabel={tr(\"devportal.cancel\", \"Cancel\")}\n variant=\"destructive\"\n loading={deactivateLoading}\n />\n\n {/* Grant Delegation Modal */}\n <GrantDelegationModal\n open={showDelegationModal}\n onOpenChange={setShowDelegationModal}\n appId={app.appId || \"\"}\n appName={app.name}\n appScopes={app.scopes?.map((s) => s.scope) ?? []}\n onSuccess={() => {\n setShowDelegationModal(false);\n }}\n />\n </PageLayout>\n );\n};\n\n// =============================================================================\n// CONNECTED TAB WRAPPERS (data-fetching layer)\n// =============================================================================\n\n/**\n * OAuth tab — now links to centralized OAuth apps page (auth-svc).\n * Previously fetched devportal-svc OAuthClients per application.\n */\nconst OAuthTabConnected: FC<{\n appId: string;\n onNavigate: (path: string) => void;\n}> = ({ onNavigate }) => {\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 return (\n <div className=\"space-y-4 py-4 text-center\">\n <Shield className=\"mx-auto h-10 w-10 text-text-secondary\" />\n <h3 className=\"font-medium\">{tr(\"devportal.oauthApps\", \"OAuth Apps\")}</h3>\n <p className=\"text-sm text-text-secondary\">\n {tr(\n \"devportal.oauthAppsManagedCentrally\",\n \"OAuth apps are now managed centrally. Visit the OAuth Apps page to create and manage your apps.\",\n )}\n </p>\n <button\n onClick={() => onNavigate(\"/oauth\")}\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 transition-colors\"\n >\n <ExternalLink size={16} />\n {tr(\"devportal.manageOAuthApps\", \"Manage OAuth Apps\")}\n </button>\n </div>\n );\n};\n\n/**\n * API Keys tab — now links to centralized API keys page (auth-svc).\n * Previously fetched devportal-svc ApiKeys per application.\n */\nconst ApiKeysTabConnected: FC<{\n appId: string;\n onNavigate: (path: string) => void;\n}> = ({ onNavigate }) => {\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 return (\n <div className=\"space-y-4 py-4 text-center\">\n <Key className=\"mx-auto h-10 w-10 text-text-secondary\" />\n <h3 className=\"font-medium\">{tr(\"devportal.apiKeys\", \"API Keys\")}</h3>\n <p className=\"text-sm text-text-secondary\">\n {tr(\n \"devportal.apiKeysManagedCentrally\",\n \"API keys are now managed centrally. Visit the API Keys page to generate and manage your keys.\",\n )}\n </p>\n <button\n onClick={() => onNavigate(\"/api-keys\")}\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 transition-colors\"\n >\n <ExternalLink size={16} />\n {tr(\"devportal.manageApiKeys\", \"Manage API Keys\")}\n </button>\n </div>\n );\n};\n\n// =============================================================================\n// PRICING TAB\n// =============================================================================\n\n// 1 platform credit = $0.01 USD (matches the default rateUSD fallback in CreditsProvider)\nconst CREDIT_RATE_USD = 0.01;\nconst creditsToUsd = (credits: number) => credits * CREDIT_RATE_USD;\nconst usdToCredits = (usd: number) => Math.round(usd / CREDIT_RATE_USD);\n\nconst PricingTab: FC<{\n app: Application;\n platformFeeRate: number;\n billingAccountLinked: boolean;\n onNavigateToRevenue?: () => void;\n isReadyToSubmit?: boolean;\n}> = ({\n app,\n platformFeeRate,\n billingAccountLinked,\n onNavigateToRevenue,\n isReadyToSubmit = false,\n}) => {\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 pricingDetails = (app.pricingDetails ?? {}) as Record<string, unknown>;\n const [formData, setFormData] = useState({\n pricingType: app.pricingType ?? \"FREE\",\n // stored as credits in pricingDetails.price; older data may store USD — treat <1000 as USD legacy\n price:\n typeof pricingDetails.price === \"number\"\n ? String(pricingDetails.price)\n : \"\",\n });\n const [isSaving, setIsSaving] = useState(false);\n const [updateApplication] = useUpdateApplicationMutation();\n\n const appRef = useRef(app);\n appRef.current = app;\n useEffect(() => {\n const pd = (appRef.current.pricingDetails ?? {}) as Record<string, unknown>;\n setFormData({\n pricingType: appRef.current.pricingType ?? \"FREE\",\n price: typeof pd.price === \"number\" ? String(pd.price) : \"\",\n });\n }, [app.id]);\n\n const handleChange = (field: \"pricingType\" | \"price\", value: string) => {\n setFormData((prev) => ({ ...prev, [field]: value }));\n };\n\n const handleSave = async () => {\n setIsSaving(true);\n try {\n const existingDetails = (app.pricingDetails ?? {}) as Record<\n string,\n unknown\n >;\n const pricingDetailsUpdate: Record<string, unknown> = {\n ...existingDetails,\n };\n if (formData.pricingType !== \"FREE\") {\n const parsedCredits = parseInt(formData.price, 10);\n if (!isNaN(parsedCredits) && parsedCredits > 0) {\n pricingDetailsUpdate.price = parsedCredits;\n // always store currency as credits unit identifier\n pricingDetailsUpdate.currency = \"CREDITS\";\n }\n } else {\n delete pricingDetailsUpdate.price;\n delete pricingDetailsUpdate.currency;\n }\n await updateApplication({\n variables: {\n id: app.id,\n input: {\n pricingType: formData.pricingType || null,\n pricingDetails:\n Object.keys(pricingDetailsUpdate).length > 0\n ? pricingDetailsUpdate\n : null,\n },\n },\n });\n void nativeNotify(\"success\");\n } catch {\n void nativeNotify(\"error\");\n } finally {\n setIsSaving(false);\n }\n };\n\n const showPriceFields = formData.pricingType !== \"FREE\";\n const parsedCredits = parseInt(formData.price, 10);\n const hasValidPrice =\n showPriceFields && !isNaN(parsedCredits) && parsedCredits > 0;\n const priceUsd = hasValidPrice ? creditsToUsd(parsedCredits) : 0;\n const feeCredits = hasValidPrice\n ? Math.round(parsedCredits * platformFeeRate)\n : 0;\n const feeUsd = creditsToUsd(feeCredits);\n const payoutCredits = hasValidPrice ? parsedCredits - feeCredits : 0;\n const payoutUsd = creditsToUsd(payoutCredits);\n const fmtUsd = (n: number) =>\n \"$\" +\n n.toLocaleString(\"en-US\", {\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n });\n const fmtCredits = (n: number) => n.toLocaleString(\"en-US\") + \" cr\";\n\n return (\n <div className=\"space-y-8\">\n {/* ── Credits explained ── */}\n <div className=\"flex items-start gap-3 rounded-lg border border-border-subtle bg-bg-sunken px-4 py-3\">\n <CircleDollarSign size={16} className=\"mt-0.5 shrink-0 text-primary\" />\n <p className=\"text-sm text-text-secondary\">\n <span className=\"font-medium text-text-primary\">\n Platform credits\n </span>{\" \"}\n are the currency of the Burdenoff marketplace.{\" \"}\n <span className=\"font-medium\">\n 1 credit = {fmtUsd(CREDIT_RATE_USD)} USD.\n </span>{\" \"}\n Buyers purchase credits and spend them on apps. You earn credits on\n every sale and can withdraw them as cash via your billing account.\n </p>\n </div>\n\n {/* ── How monetization works ── */}\n <div className=\"space-y-3\">\n <div>\n <h2 className=\"text-lg font-semibold\">\n {tr(\"devportal.howMonetizationWorks\", \"How App Monetization Works\")}\n </h2>\n <p className=\"mt-1 text-sm text-text-secondary\">\n {tr(\n \"devportal.monetizationDesc\",\n \"Earn revenue when users install or purchase your app. Here's exactly how the money flows.\",\n )}\n </p>\n </div>\n <div className=\"grid gap-4 sm:grid-cols-3\">\n {/* Revenue share */}\n <div className=\"rounded-xl border border-border-subtle bg-bg-surface p-5 space-y-3\">\n <div className=\"flex h-9 w-9 items-center justify-center rounded-lg bg-status-success-bg-subtle\">\n <TrendingUp size={18} className=\"text-status-success-text\" />\n </div>\n <div>\n <p className=\"font-semibold\">\n {(100 - platformFeeRate * 100).toFixed(0)}% revenue share\n </p>\n <p className=\"mt-1 text-sm text-text-secondary\">\n You keep{\" \"}\n <span className=\"font-medium text-status-success-text\">\n {(100 - platformFeeRate * 100).toFixed(0)}%\n </span>{\" \"}\n of every sale in credits. The platform retains a{\" \"}\n <span className=\"font-medium\">\n {(platformFeeRate * 100).toFixed(0)}%\n </span>{\" \"}\n fee to cover infrastructure, payments processing, and\n marketplace operations.\n </p>\n </div>\n </div>\n {/* Payouts */}\n <div className=\"rounded-xl border border-border-subtle bg-bg-surface p-5 space-y-3\">\n <div className=\"flex h-9 w-9 items-center justify-center rounded-lg bg-action-primary-bg/10\">\n <Wallet size={18} className=\"text-primary\" />\n </div>\n <div>\n <p className=\"font-semibold\">Credits → cash via billing</p>\n <p className=\"mt-1 text-sm text-text-secondary\">\n Every sale instantly deposits your earned credits into your\n linked billing account. You can spend them on platform services\n or request a cash withdrawal. Track everything on the{\" \"}\n {onNavigateToRevenue ? (\n <button\n type=\"button\"\n onClick={onNavigateToRevenue}\n className=\"font-medium text-primary underline-offset-2 hover:underline\"\n >\n Revenue page\n </button>\n ) : (\n <span className=\"font-medium text-primary\">Revenue page</span>\n )}\n .\n </p>\n </div>\n </div>\n {/* Marketplace reach */}\n <div className=\"rounded-xl border border-border-subtle bg-bg-surface p-5 space-y-3\">\n <div className=\"flex h-9 w-9 items-center justify-center rounded-lg bg-status-warning-bg-subtle\">\n <Gift size={18} className=\"text-status-warning-text\" />\n </div>\n <div>\n <p className=\"font-semibold\">Reach the full marketplace</p>\n <p className=\"mt-1 text-sm text-text-secondary\">\n Any user with platform credits can discover and install your app\n directly from the marketplace. Free apps maximise reach; paid\n apps let you monetise your work.\n </p>\n </div>\n </div>\n </div>\n </div>\n\n {/* ── Set your price ── */}\n <div className=\"space-y-4\">\n <div>\n <h3 className=\"text-base font-semibold\">\n {tr(\"devportal.setPricingTitle\", \"Set Your Price\")}\n </h3>\n <p className=\"mt-0.5 text-sm text-text-secondary\">\n Choose <strong>Free</strong> to maximise installs, or{\" \"}\n <strong>Paid</strong> to earn credits on every install. Paid apps\n require a linked billing account before publishing.\n </p>\n </div>\n\n {/* Pricing type toggle */}\n <div className=\"flex flex-wrap gap-2\">\n {PRICING_TYPE_OPTIONS.map((opt) => (\n <button\n key={opt.value}\n type=\"button\"\n onClick={() => handleChange(\"pricingType\", opt.value)}\n className={cn(\n \"rounded-md border px-4 py-2 text-sm font-medium transition-colors\",\n formData.pricingType === opt.value\n ? \"bg-action-primary-bg text-action-primary-text border-primary\"\n : \"hover:bg-bg-sunken border-border-subtle\",\n )}\n >\n {opt.label}\n </button>\n ))}\n </div>\n\n {showPriceFields && (\n <div className=\"space-y-4\">\n {/* Credits price input */}\n <div className=\"max-w-xs\">\n <label className=\"mb-1.5 block text-sm font-medium\">\n Listing price{\" \"}\n <span className=\"text-text-tertiary font-normal\">\n (credits)\n </span>\n </label>\n <div className=\"relative flex items-center\">\n <input\n type=\"number\"\n min={1}\n step={1}\n value={formData.price}\n onChange={(e) => handleChange(\"price\", e.target.value)}\n placeholder=\"e.g. 1000\"\n className=\"w-full rounded-md border border-border-subtle bg-bg-input px-3 py-2 pr-20 text-sm focus:outline-none focus:ring-2 focus:ring-primary/50\"\n />\n <span className=\"pointer-events-none absolute right-3 text-xs text-text-tertiary\">\n credits\n </span>\n </div>\n {hasValidPrice && (\n <p className=\"mt-1.5 text-xs text-text-secondary\">\n ≈ {fmtUsd(priceUsd)} USD at the current credit rate (1 cr ={\" \"}\n {fmtUsd(CREDIT_RATE_USD)})\n </p>\n )}\n <p className=\"mt-1 text-xs text-text-tertiary\">\n {tr(\n \"devportal.priceHint\",\n \"Set the number of credits a buyer spends to install your app\",\n )}\n </p>\n </div>\n\n {/* Quick USD → credits helper */}\n <div className=\"flex items-center gap-2 text-xs text-text-secondary\">\n <span>Quick convert:</span>\n {[5, 10, 25, 50].map((usd) => (\n <button\n key={usd}\n type=\"button\"\n onClick={() =>\n handleChange(\"price\", String(usdToCredits(usd)))\n }\n className=\"rounded border border-border-subtle px-2 py-0.5 hover:bg-bg-sunken transition-colors\"\n >\n ${usd} = {usdToCredits(usd).toLocaleString()} cr\n </button>\n ))}\n </div>\n\n {/* Live revenue breakdown */}\n {hasValidPrice && (\n <div className=\"rounded-lg border border-border-subtle bg-bg-sunken p-4 space-y-3\">\n <p className=\"text-xs font-semibold uppercase tracking-wide text-text-secondary\">\n {tr(\n \"devportal.revenueBreakdown\",\n \"Revenue Breakdown per Sale\",\n )}\n </p>\n <div className=\"space-y-2 text-sm\">\n <div className=\"flex items-center justify-between\">\n <span className=\"text-text-secondary\">Buyer pays</span>\n <span className=\"font-medium tabular-nums\">\n {fmtCredits(parsedCredits)}{\" \"}\n <span className=\"text-text-tertiary text-xs\">\n ({fmtUsd(priceUsd)})\n </span>\n </span>\n </div>\n <div className=\"flex items-center justify-between text-status-error-text\">\n <span>\n Platform fee{\" \"}\n <span className=\"opacity-70\">\n ({(platformFeeRate * 100).toFixed(0)}%)\n </span>\n </span>\n <span className=\"tabular-nums\">\n − {fmtCredits(feeCredits)}{\" \"}\n <span className=\"text-xs opacity-70\">\n ({fmtUsd(feeUsd)})\n </span>\n </span>\n </div>\n <div className=\"flex items-center justify-between border-t border-border-subtle pt-2 font-semibold text-status-success-text\">\n <span>You earn</span>\n <span className=\"tabular-nums\">\n {fmtCredits(payoutCredits)}{\" \"}\n <span className=\"text-sm font-normal\">\n ≈ {fmtUsd(payoutUsd)}\n </span>\n </span>\n </div>\n </div>\n <p className=\"text-xs text-text-tertiary\">\n Credits are deposited to your billing account on each sale.\n Cash withdrawal is subject to platform terms and minimum\n payout thresholds.\n </p>\n </div>\n )}\n\n {/* Billing account warning */}\n {!billingAccountLinked && (\n <div className=\"flex items-start gap-3 rounded-lg border border-status-warning-bg bg-status-warning-bg-subtle p-4\">\n <AlertCircle\n size={16}\n className=\"mt-0.5 shrink-0 text-status-warning-text\"\n />\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm font-medium text-status-warning-text\">\n {tr(\n \"devportal.billingAccountRequired\",\n \"Billing account required to publish\",\n )}\n </p>\n <p className=\"mt-0.5 text-xs text-text-secondary\">\n Paid apps must have a billing account linked to your\n developer organization before you can submit for review.\n This is where your earned credits and cash withdrawals will\n be managed.\n </p>\n {onNavigateToRevenue && (\n <button\n type=\"button\"\n onClick={onNavigateToRevenue}\n className=\"mt-2 text-xs font-medium text-primary hover:underline underline-offset-2\"\n >\n {tr(\n \"devportal.goToRevenueBilling\",\n \"Go to Revenue & Billing →\",\n )}\n </button>\n )}\n </div>\n </div>\n )}\n </div>\n )}\n </div>\n\n {/* ── Terms & Conditions ── */}\n <div className=\"rounded-xl border border-border-subtle bg-bg-surface p-5 space-y-3\">\n <h3 className=\"text-sm font-semibold\">\n {tr(\"devportal.termsTitle\", \"Developer & Marketplace Terms\")}\n </h3>\n <ul className=\"space-y-2 text-sm text-text-secondary\">\n <li className=\"flex items-start gap-2\">\n <Check\n size={14}\n className=\"mt-0.5 shrink-0 text-status-success-text\"\n />\n <span>\n By publishing to the marketplace you agree to the{\" \"}\n <a\n href=\"/legal/developer-terms\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-primary underline-offset-2 hover:underline\"\n >\n Developer Program Agreement\n </a>\n .\n </span>\n </li>\n <li className=\"flex items-start gap-2\">\n <Check\n size={14}\n className=\"mt-0.5 shrink-0 text-status-success-text\"\n />\n <span>\n All prices are in platform credits. The USD equivalent is\n indicative only and may vary with the current credit rate.\n </span>\n </li>\n <li className=\"flex items-start gap-2\">\n <Check\n size={14}\n className=\"mt-0.5 shrink-0 text-status-success-text\"\n />\n <span>\n Earnings are credited to your billing account per-sale. Cash\n withdrawals are subject to a minimum threshold and applicable\n taxes in your jurisdiction.\n </span>\n </li>\n <li className=\"flex items-start gap-2\">\n <Check\n size={14}\n className=\"mt-0.5 shrink-0 text-status-success-text\"\n />\n <span>\n The platform reserves the right to adjust the credit rate, fee\n structure, or payout schedule with 30 days notice. See the{\" \"}\n <a\n href=\"/legal/marketplace-terms\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-primary underline-offset-2 hover:underline\"\n >\n Marketplace Terms\n </a>{\" \"}\n for full details.\n </span>\n </li>\n </ul>\n </div>\n\n {/* ── Save + all-set banner ── */}\n <div className=\"border-t border-border-subtle pt-6 space-y-4\">\n <button\n type=\"button\"\n onClick={() => void handleSave()}\n disabled={isSaving}\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 transition-colors disabled:opacity-50\"\n >\n {isSaving ? (\n <>\n <Loader2 size={16} className=\"animate-spin\" />\n {tr(\"devportal.saving\", \"Saving…\")}\n </>\n ) : (\n <>\n <CircleDollarSign size={16} />\n {tr(\"devportal.savePricing\", \"Save Pricing\")}\n </>\n )}\n </button>\n {/* All-set banner — shown when every pre-publish check passes */}\n {isReadyToSubmit && (\n <div className=\"flex items-start gap-3 rounded-lg border border-status-success-bg bg-status-success-bg-subtle px-4 py-3\">\n <Check\n size={16}\n className=\"mt-0.5 shrink-0 text-status-success-text\"\n />\n <div>\n <p className=\"text-sm font-medium text-status-success-text\">\n {tr(\"devportal.allSetToSubmit\", \"You're all set!\")}\n </p>\n <p className=\"mt-0.5 text-xs text-text-secondary\">\n {tr(\n \"devportal.allSetDesc\",\n \"Store listing, versions, and pricing are complete. Head to the top of the page and click Submit for Review.\",\n )}\n </p>\n </div>\n </div>\n )}\n </div>\n </div>\n );\n};\n\n/** Versions tab — inline list of application versions with link to the full management page */\nconst VersionsTabConnected: FC<{\n appId: string;\n onNavigate: (path: string) => void;\n pricingDone?: boolean;\n onNavigateToPricing?: () => void;\n}> = ({ appId, onNavigate, pricingDone = false, onNavigateToPricing }) => {\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 const { data, loading, error } = useGetApplicationVersionsQuery({\n variables: { applicationId: appId },\n fetchPolicy: \"cache-and-network\",\n });\n\n if (loading)\n return (\n <TabLoadingSpinner\n message={tr(\"devportal.loadingVersions\", \"Loading versions…\")}\n />\n );\n if (error) return <TabErrorState message={error.message} />;\n\n type VersionEdge = NonNullable<\n GetApplicationVersionsQuery[\"application\"]\n >[\"versions\"][\"edges\"][number];\n const edges: VersionEdge[] = data?.application?.versions?.edges ?? [];\n const versions = edges.map((e) => e.node);\n\n return (\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between\">\n <p className=\"text-sm text-text-secondary\">\n {versions.length}{\" \"}\n {versions.length !== 1\n ? tr(\"devportal.versions\", \"versions\")\n : tr(\"devportal.version\", \"version\")}\n </p>\n <button\n onClick={() => onNavigate(`/apps/${appId}/versions`)}\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 transition-colors\"\n >\n <Upload size={16} />\n {tr(\"devportal.uploadVersion\", \"Upload Version\")}\n </button>\n </div>\n\n {versions.length > 0 ? (\n <div className=\"overflow-hidden rounded-lg border border-border-subtle\">\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"border-b border-border-subtle bg-bg-sunken/50\">\n <th className=\"px-4 py-3 text-left font-medium text-text-secondary\">\n {tr(\"devportal.version\", \"Version\")}\n </th>\n <th className=\"px-4 py-3 text-left font-medium text-text-secondary\">\n {tr(\"devportal.status\", \"Status\")}\n </th>\n <th className=\"px-4 py-3 text-left font-medium text-text-secondary\">\n {tr(\"devportal.released\", \"Released\")}\n </th>\n <th className=\"px-4 py-3 text-left font-medium text-text-secondary\">\n {tr(\"devportal.flags\", \"Flags\")}\n </th>\n </tr>\n </thead>\n <tbody className=\"divide-y divide-border-subtle\">\n {versions.map((v) => (\n <>\n <tr\n key={v.id}\n className=\"hover:bg-bg-sunken/30 transition-colors\"\n >\n <td className=\"px-4 py-3 font-mono font-medium\">\n {v.version}\n </td>\n <td className=\"px-4 py-3\">\n <span\n className={cn(\n \"inline-flex rounded-full px-2 py-0.5 text-xs font-medium\",\n v.status === \"published\"\n ? \"bg-status-success-bg-subtle text-status-success-text\"\n : v.status === \"pending_review\"\n ? \"bg-status-info-bg-subtle text-status-info-text\"\n : v.status === \"rejected\"\n ? \"bg-status-error-bg-subtle text-status-error-text\"\n : v.status === \"deprecated\"\n ? \"bg-bg-sunken text-text-secondary\"\n : \"bg-status-warning-bg-subtle text-status-warning-text\",\n )}\n >\n {v.status === \"pending_review\" ? \"In Review\" : v.status}\n </span>\n </td>\n <td className=\"px-4 py-3 text-text-secondary\">\n {v.publishedAt\n ? new Date(v.publishedAt).toLocaleDateString()\n : new Date(v.createdAt).toLocaleDateString()}\n </td>\n <td className=\"px-4 py-3\">\n <div className=\"flex gap-1.5\">\n {v.isLatest && (\n <span className=\"rounded-full bg-action-primary-bg/10 px-2 py-0.5 text-xs text-primary font-medium\">\n latest\n </span>\n )}\n {v.isStable && (\n <span className=\"rounded-full bg-status-success-bg-subtle px-2 py-0.5 text-xs text-status-success-text font-medium\">\n stable\n </span>\n )}\n </div>\n </td>\n </tr>\n {v.status === \"rejected\" && v.reviewNotes && (\n <tr\n key={`${v.id}-notes`}\n className=\"bg-status-error-bg-subtle/40\"\n >\n <td colSpan={4} className=\"px-4 py-2\">\n <p className=\"text-xs text-status-error-text\">\n <span className=\"font-semibold\">\n Review feedback:{\" \"}\n </span>\n {v.reviewNotes}\n </p>\n </td>\n </tr>\n )}\n {v.status === \"pending_review\" && (\n <tr\n key={`${v.id}-review`}\n className=\"bg-status-info-bg-subtle/30\"\n >\n <td colSpan={4} className=\"px-4 py-2\">\n <p className=\"text-xs text-status-info-text\">\n Submitted for platform review — you will be notified\n once approved or if changes are needed.\n </p>\n </td>\n </tr>\n )}\n </>\n ))}\n </tbody>\n </table>\n </div>\n ) : (\n <EmptyState\n illustration=\"empty-generic\"\n icon={<Package size={32} />}\n title={tr(\"devportal.noVersions\", \"No versions yet\")}\n description={tr(\n \"devportal.noVersionsDescription\",\n \"Upload your first version to make this item available for review and distribution.\",\n )}\n action={\n <button\n onClick={() => onNavigate(`/apps/${appId}/versions`)}\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\"\n >\n <Upload size={16} />\n {tr(\"devportal.uploadVersion\", \"Upload Version\")}\n </button>\n }\n />\n )}\n {/* Next-step hint: guide to pricing — only once a version actually exists */}\n {versions.length > 0 && !pricingDone && onNavigateToPricing && (\n <div className=\"mt-4 flex items-center gap-3 rounded-lg border border-border-subtle bg-bg-sunken px-4 py-3\">\n <CircleDollarSign size={16} className=\"shrink-0 text-primary\" />\n <p className=\"flex-1 text-sm text-text-secondary\">\n {tr(\n \"devportal.versionsNextPricing\",\n \"You've got versions covered. Now set your pricing before you can submit.\",\n )}\n </p>\n <button\n type=\"button\"\n onClick={onNavigateToPricing}\n className=\"inline-flex items-center gap-1 text-sm font-medium text-primary hover:underline underline-offset-2 whitespace-nowrap\"\n >\n {tr(\"devportal.nextSetPricing\", \"Set Pricing\")}\n <ChevronRight size={15} />\n </button>\n </div>\n )}\n </div>\n );\n};\n\n/** Webhooks tab with real data from useGetWebhooksQuery */\nconst WebhooksTabConnected: FC<{\n appId: string;\n onNavigate: (path: string) => void;\n}> = ({ appId, onNavigate }) => {\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 const { data, loading, error } = useGetWebhooksQuery({\n variables: { applicationId: appId },\n });\n\n if (loading)\n return (\n <TabLoadingSpinner\n message={tr(\"devportal.loadingWebhooks\", \"Loading webhooks...\")}\n />\n );\n if (error) return <TabErrorState message={error.message} />;\n\n const webhooks = (data?.webhooks ?? []).map(mapToWebhook);\n\n return (\n <WebhooksTab appId={appId} webhooks={webhooks} onNavigate={onNavigate} />\n );\n};\n\n/** Delegations tab with real data from useCurrentUserDelegationsQuery */\nconst DelegationsTabConnected: FC<{\n authAppId?: string;\n appName: string;\n onGrantDelegation: () => void;\n onNavigate: (path: string) => void;\n}> = ({ authAppId, appName, onGrantDelegation, onNavigate }) => {\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 const { data, loading, error, refetch } = useCurrentUserDelegationsQuery();\n const [revokeDelegation] = useRevokeDelegationMutation();\n const [revokeConfirmIds, setRevokeConfirmIds] = useState<string[]>([]);\n const [revokeLoading, setRevokeLoading] = useState(false);\n const [selectedDelegationIds, setSelectedDelegationIds] = useState<\n Set<string>\n >(new Set());\n const [successMessage, setSuccessMessage] = useState<string | null>(null);\n\n const appDelegations = useMemo((): AppUserDelegation[] => {\n if (!data?.currentUserDelegations?.delegations) return [];\n return data.currentUserDelegations.delegations\n .filter((d: { appId: string }) => d.appId === authAppId)\n .map(mapToDelegation);\n }, [authAppId, data]);\n\n const activeAppDelegations = useMemo(\n () => appDelegations.filter((delegation) => delegation.status === \"ACTIVE\"),\n [appDelegations],\n );\n const selectedActiveDelegations = useMemo(\n () =>\n activeAppDelegations.filter((delegation) =>\n selectedDelegationIds.has(delegation.id),\n ),\n [activeAppDelegations, selectedDelegationIds],\n );\n const allVisibleSelected =\n activeAppDelegations.length > 0 &&\n activeAppDelegations.every((delegation) =>\n selectedDelegationIds.has(delegation.id),\n );\n const partiallySelected =\n activeAppDelegations.some((delegation) =>\n selectedDelegationIds.has(delegation.id),\n ) && !allVisibleSelected;\n\n const toggleDelegationSelection = useCallback(\n (delegationId: string, checked: boolean) => {\n setSelectedDelegationIds((prev) => {\n const next = new Set(prev);\n if (checked) {\n next.add(delegationId);\n } else {\n next.delete(delegationId);\n }\n return next;\n });\n },\n [],\n );\n\n const toggleAllVisibleDelegations = useCallback(\n (checked: boolean) => {\n setSelectedDelegationIds((prev) => {\n const next = new Set(prev);\n activeAppDelegations.forEach((delegation) => {\n if (checked) {\n next.add(delegation.id);\n } else {\n next.delete(delegation.id);\n }\n });\n return next;\n });\n },\n [activeAppDelegations],\n );\n\n const clearSelection = useCallback(() => {\n setSelectedDelegationIds(new Set());\n }, []);\n\n const handleRevoke = useCallback(\n async (delegationIds: string[]) => {\n setRevokeLoading(true);\n try {\n const results = await Promise.allSettled(\n delegationIds.map((delegationId) =>\n revokeDelegation({ variables: { id: delegationId } }),\n ),\n );\n const succeeded = results.filter(\n (result: PromiseSettledResult<unknown>) =>\n result.status === \"fulfilled\",\n ).length;\n const failed = results.length - succeeded;\n setSuccessMessage(\n `Revoked ${succeeded} delegation${succeeded === 1 ? \"\" : \"s\"}${failed > 0 ? ` • ${failed} failed` : \"\"}`,\n );\n setSelectedDelegationIds((prev) => {\n const next = new Set(prev);\n delegationIds.forEach((delegationId) => next.delete(delegationId));\n return next;\n });\n setRevokeConfirmIds([]);\n refetch();\n } catch {\n // Error handled by Apollo\n } finally {\n setRevokeLoading(false);\n }\n },\n [revokeDelegation, refetch],\n );\n\n if (!authAppId) {\n return (\n <EmptyState\n illustration=\"empty-generic\"\n icon={<Shield size={32} />}\n title={tr(\"devportal.linkAuthAppFirst\", \"Link an auth app first\")}\n description={tr(\n \"devportal.linkAuthAppFirstDescription\",\n \"Delegations are managed through auth apps. Create or link an auth app before granting app-as-user access.\",\n )}\n action={\n <button\n onClick={() => onNavigate(\"/oauth\")}\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\"\n >\n <ExternalLink size={16} />\n {tr(\"devportal.manageOAuthApps\", \"Manage OAuth Apps\")}\n </button>\n }\n />\n );\n }\n\n if (loading)\n return (\n <TabLoadingSpinner\n message={tr(\"devportal.loadingDelegations\", \"Loading delegations...\")}\n />\n );\n if (error) return <TabErrorState message={error.message} />;\n\n return (\n <>\n {successMessage && (\n <div className=\"rounded-lg border border-border-subtle bg-status-success-bg-subtle p-3 text-sm text-status-success-text\">\n <div className=\"flex items-center justify-between gap-3\">\n <span>{successMessage}</span>\n <button\n onClick={() => setSuccessMessage(null)}\n className=\"text-status-success-text hover:text-status-success-text\"\n >\n {tr(\"devportal.dismiss\", \"Dismiss\")}\n </button>\n </div>\n </div>\n )}\n\n <DelegationsTab\n appName={appName}\n delegations={appDelegations}\n onGrantDelegation={onGrantDelegation}\n onRevokeDelegation={(id) => setRevokeConfirmIds([id])}\n selectedDelegationIds={selectedDelegationIds}\n onToggleSelectDelegation={toggleDelegationSelection}\n onToggleAllDelegations={toggleAllVisibleDelegations}\n onClearSelection={clearSelection}\n onRevokeSelected={() =>\n setRevokeConfirmIds(\n selectedActiveDelegations.map((delegation) => delegation.id),\n )\n }\n allVisibleSelected={allVisibleSelected}\n partiallySelected={partiallySelected}\n />\n\n <ConfirmDialog\n open={revokeConfirmIds.length > 0}\n onOpenChange={(open) => {\n if (!open) setRevokeConfirmIds([]);\n }}\n onConfirm={() => {\n if (revokeConfirmIds.length > 0) {\n handleRevoke(revokeConfirmIds);\n }\n }}\n title={\n revokeConfirmIds.length > 1\n ? tr(\"devportal.revokeDelegations\", \"Revoke Delegations\")\n : tr(\"devportal.revokeDelegation\", \"Revoke Delegation\")\n }\n description={\n revokeConfirmIds.length > 1\n ? tr(\n \"devportal.revokeMultipleDelegationsDescription\",\n `This will immediately revoke ${revokeConfirmIds.length} selected delegations.`,\n )\n : tr(\n \"devportal.revokeDelegationDescription\",\n \"This will immediately revoke the delegation. The app will no longer be able to act on your behalf with the selected permissions.\",\n )\n }\n confirmLabel={tr(\"devportal.revoke\", \"Revoke\")}\n cancelLabel={tr(\"devportal.cancel\", \"Cancel\")}\n variant=\"destructive\"\n loading={revokeLoading}\n />\n </>\n );\n};\n\n/** Analytics tab with real data from useGetApplicationAnalyticsQuery */\nconst AnalyticsTabConnected: FC<{ appId: string }> = ({ appId }) => {\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 const now = useMemo(() => new Date(), []);\n const thirtyDaysAgo = useMemo(() => {\n const d = new Date(now);\n d.setDate(d.getDate() - 30);\n return d;\n }, [now]);\n\n const { data, loading, error } = useGetApplicationAnalyticsQuery({\n variables: {\n applicationId: appId,\n period: \"daily\",\n startDate: thirtyDaysAgo.toISOString(),\n endDate: now.toISOString(),\n },\n });\n\n if (loading)\n return (\n <TabLoadingSpinner\n message={tr(\"devportal.loadingAnalytics\", \"Loading analytics...\")}\n />\n );\n if (error) return <TabErrorState message={error.message} />;\n\n const analytics = (data?.applicationAnalytics ?? []).map(mapToAnalytics);\n\n return <AnalyticsTab analytics={analytics} />;\n};\n\n// =============================================================================\n// OVERVIEW TAB\n// =============================================================================\n\nconst OverviewTab: FC<{ app: Application }> = ({ app }) => {\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 return (\n <div className=\"grid gap-6 lg:grid-cols-3\">\n <div className=\"lg:col-span-2 space-y-6\">\n {/* Stats — primary emphasis zone */}\n <EmphasisPanel>\n <div className=\"grid gap-4 sm:grid-cols-4\">\n <StatCard\n label={tr(\"devportal.totalInstalls\", \"Total Installs\")}\n value={app.installCount.toLocaleString()}\n />\n <StatCard\n label={tr(\"devportal.activeInstalls\", \"Active Installs\")}\n value={app.activeInstallCount.toLocaleString()}\n />\n <StatCard\n label={tr(\"devportal.averageRating\", \"Average Rating\")}\n value={\n app.averageRating\n ? `${app.averageRating.toFixed(1)} ★`\n : tr(\"devportal.notAvailable\", \"N/A\")\n }\n />\n <StatCard\n label={tr(\"devportal.reviews\", \"Reviews\")}\n value={app.reviewCount.toString()}\n />\n </div>\n </EmphasisPanel>\n\n {/* Description */}\n <PageSection title={tr(\"devportal.description\", \"Description\")}>\n <div className=\"prose prose-sm max-w-none\">\n <pre className=\"whitespace-pre-wrap font-sans text-sm text-text-primary bg-transparent p-0 m-0\">\n {app.description ||\n tr(\n \"devportal.noDescriptionProvided\",\n \"No description provided.\",\n )}\n </pre>\n </div>\n </PageSection>\n\n {/* Tags & Keywords */}\n <PageSection title={tr(\"devportal.tagsAndKeywords\", \"Tags & Keywords\")}>\n <div className=\"space-y-3\">\n {app.tags.length > 0 && (\n <div>\n <p className=\"text-xs text-text-secondary mb-2\">\n {tr(\"devportal.tags\", \"Tags\")}\n </p>\n <div className=\"flex flex-wrap gap-2\">\n {app.tags.map((tag) => (\n <span\n key={tag}\n className=\"rounded-full bg-action-primary-bg/10 px-3 py-1 text-xs font-medium text-primary\"\n >\n {tag}\n </span>\n ))}\n </div>\n </div>\n )}\n {app.keywords.length > 0 && (\n <div>\n <p className=\"text-xs text-text-secondary mb-2\">\n {tr(\"devportal.keywords\", \"Keywords\")}\n </p>\n <div className=\"flex flex-wrap gap-2\">\n {app.keywords.map((keyword) => (\n <span\n key={keyword}\n className=\"rounded-full bg-bg-sunken px-3 py-1 text-xs\"\n >\n {keyword}\n </span>\n ))}\n </div>\n </div>\n )}\n </div>\n </PageSection>\n </div>\n\n {/* Sidebar */}\n <div className=\"space-y-6\">\n <PageSection title={tr(\"devportal.details\", \"Details\")}>\n <DetailList\n items={[\n {\n label: tr(\"devportal.appId\", \"App ID\"),\n value: <code className=\"text-xs\">{app.id}</code>,\n },\n { label: tr(\"devportal.slug\", \"Slug\"), value: app.slug },\n {\n label: tr(\"devportal.category\", \"Category\"),\n value:\n app.category ||\n tr(\"devportal.uncategorized\", \"Uncategorized\"),\n },\n {\n label: tr(\"devportal.pricing\", \"Pricing\"),\n value: (() => {\n if (app.pricingType === \"PAID\") {\n const pd = (app.pricingDetails ?? {}) as Record<\n string,\n unknown\n >;\n const price =\n typeof pd.price === \"number\" ? pd.price : null;\n const currency =\n typeof pd.currency === \"string\" ? pd.currency : \"USD\";\n return price != null\n ? `PAID — ${price} ${currency}`\n : \"PAID\";\n }\n return app.pricingType || tr(\"devportal.free\", \"Free\");\n })(),\n },\n {\n label: tr(\"devportal.created\", \"Created\"),\n value: new Date(app.createdAt).toLocaleDateString(),\n },\n {\n label: tr(\"devportal.updated\", \"Updated\"),\n value: new Date(app.updatedAt).toLocaleDateString(),\n },\n {\n label: tr(\"devportal.published\", \"Published\"),\n value: app.publishedAt\n ? new Date(app.publishedAt).toLocaleDateString()\n : tr(\"devportal.notPublished\", \"Not published\"),\n },\n ]}\n />\n </PageSection>\n\n <PageSection title={tr(\"devportal.links\", \"Links\")}>\n <div className=\"space-y-2\">\n {app.websiteUrl && (\n <LinkItem\n label={tr(\"devportal.website\", \"Website\")}\n url={app.websiteUrl}\n />\n )}\n {app.documentationUrl && (\n <LinkItem\n label={tr(\"devportal.documentation\", \"Documentation\")}\n url={app.documentationUrl}\n />\n )}\n {app.supportUrl && (\n <LinkItem\n label={tr(\"devportal.support\", \"Support\")}\n url={app.supportUrl}\n />\n )}\n {app.githubUrl && (\n <LinkItem\n label={tr(\"devportal.github\", \"GitHub\")}\n url={app.githubUrl}\n />\n )}\n {app.privacyPolicyUrl && (\n <LinkItem\n label={tr(\"devportal.privacyPolicy\", \"Privacy Policy\")}\n url={app.privacyPolicyUrl}\n />\n )}\n {app.termsOfServiceUrl && (\n <LinkItem\n label={tr(\"devportal.termsOfService\", \"Terms of Service\")}\n url={app.termsOfServiceUrl}\n />\n )}\n </div>\n </PageSection>\n </div>\n </div>\n );\n};\n\n// =============================================================================\n// OAUTH TAB\n// =============================================================================\n\n/**\n * Note: OAuthTab and ApiKeysTab presentation components removed.\n * OAuth apps and API keys are now managed centrally via auth-svc.\n * The connected wrappers above link to the /oauth and /api-keys pages.\n */\n\n// =============================================================================\n// WEBHOOKS TAB\n// =============================================================================\n\nconst WebhooksTab: FC<{\n appId: string;\n webhooks: WebhookType[];\n onNavigate: (path: string) => void;\n}> = ({ appId, webhooks, onNavigate }) => {\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 return (\n <div className=\"space-y-6\">\n <div className=\"flex items-center justify-between\">\n <p className=\"text-sm text-text-secondary\">\n {webhooks.length}{\" \"}\n {webhooks.length !== 1\n ? tr(\"devportal.webhooks\", \"webhooks\")\n : tr(\"devportal.webhook\", \"webhook\")}{\" \"}\n {tr(\"devportal.configured\", \"configured\")}\n </p>\n <button\n onClick={() => onNavigate(`/apps/${appId}/webhooks/new`)}\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 transition-colors\"\n >\n <Plus size={16} />\n {tr(\"devportal.addWebhook\", \"Add Webhook\")}\n </button>\n </div>\n\n {webhooks.length > 0 ? (\n <div className=\"space-y-4\">\n {webhooks.map((webhook) => (\n <div\n key={webhook.id}\n className=\"rounded-card border border-border-seam bg-bg-surface p-4 space-y-4 shadow-[var(--shadow-pop)]\"\n >\n <div className=\"flex items-start justify-between\">\n <div>\n <div className=\"flex items-center gap-2\">\n <h3 className=\"font-medium\">{webhook.name}</h3>\n <StatusBadge status={webhook.status} type=\"webhook\" />\n </div>\n {webhook.description && (\n <p className=\"text-sm text-text-secondary mt-1\">\n {webhook.description}\n </p>\n )}\n </div>\n <button\n onClick={() =>\n onNavigate(`/apps/${appId}/webhooks/${webhook.id}`)\n }\n className=\"rounded-md p-1 hover:bg-bg-sunken\"\n >\n <MoreHorizontal size={20} />\n </button>\n </div>\n\n <div>\n <p className=\"text-xs text-text-secondary mb-1\">\n {tr(\"devportal.endpointUrl\", \"Endpoint URL\")}\n </p>\n <code className=\"text-sm bg-bg-sunken px-2 py-1 rounded block truncate\">\n {webhook.url}\n </code>\n </div>\n\n <div>\n <p className=\"text-xs text-text-secondary mb-2\">\n {tr(\"devportal.events\", \"Events\")}\n </p>\n <div className=\"flex flex-wrap gap-2\">\n {webhook.events.map((event) => (\n <span\n key={event}\n className=\"rounded-full bg-bg-sunken px-2 py-0.5 text-xs\"\n >\n {event}\n </span>\n ))}\n </div>\n </div>\n\n <div className=\"grid gap-4 sm:grid-cols-4 text-sm\">\n <div>\n <p className=\"text-xs text-text-secondary\">\n {tr(\"devportal.success\", \"Success\")}\n </p>\n <p className=\"font-medium text-status-success-text\">\n {webhook.successCount.toLocaleString()}\n </p>\n </div>\n <div>\n <p className=\"text-xs text-text-secondary\">\n {tr(\"devportal.failed\", \"Failed\")}\n </p>\n <p className=\"font-medium text-status-error-text\">\n {webhook.failureCount.toLocaleString()}\n </p>\n </div>\n <div>\n <p className=\"text-xs text-text-secondary\">\n {tr(\"devportal.successRate\", \"Success Rate\")}\n </p>\n <p className=\"font-medium\">\n {webhook.successCount + webhook.failureCount > 0\n ? (\n (webhook.successCount /\n (webhook.successCount + webhook.failureCount)) *\n 100\n ).toFixed(1)\n : \"0.0\"}\n %\n </p>\n </div>\n <div>\n <p className=\"text-xs text-text-secondary\">\n {tr(\"devportal.lastTriggered\", \"Last Triggered\")}\n </p>\n <p className=\"font-medium\">\n {webhook.lastTriggeredAt\n ? new Date(webhook.lastTriggeredAt).toLocaleString()\n : tr(\"devportal.never\", \"Never\")}\n </p>\n </div>\n </div>\n </div>\n ))}\n </div>\n ) : (\n <EmptyState\n illustration=\"empty-notifications\"\n icon={<Webhook size={32} />}\n title={tr(\"devportal.noWebhooks\", \"No webhooks\")}\n description={tr(\n \"devportal.noWebhooksDescription\",\n \"Add a webhook to receive event notifications\",\n )}\n action={\n <button\n onClick={() => onNavigate(`/apps/${appId}/webhooks/new`)}\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\"\n >\n <Plus size={16} />\n {tr(\"devportal.addWebhook\", \"Add Webhook\")}\n </button>\n }\n />\n )}\n </div>\n );\n};\n\n// =============================================================================\n// DELEGATIONS TAB\n// =============================================================================\n\nconst DelegationsTab: FC<{\n appName: string;\n delegations: AppUserDelegation[];\n onGrantDelegation: () => void;\n onRevokeDelegation: (id: string) => void;\n selectedDelegationIds: Set<string>;\n onToggleSelectDelegation: (id: string, checked: boolean) => void;\n onToggleAllDelegations: (checked: boolean) => void;\n onClearSelection: () => void;\n onRevokeSelected: () => void;\n allVisibleSelected: boolean;\n partiallySelected: boolean;\n}> = ({\n appName,\n delegations,\n onGrantDelegation,\n onRevokeDelegation,\n selectedDelegationIds,\n onToggleSelectDelegation,\n onToggleAllDelegations,\n onClearSelection,\n onRevokeSelected,\n allVisibleSelected,\n partiallySelected,\n}) => {\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 const activeDelegations = delegations.filter((d) => d.status === \"ACTIVE\");\n const inactiveDelegations = delegations.filter((d) => d.status !== \"ACTIVE\");\n\n return (\n <div className=\"space-y-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <p className=\"text-sm text-text-secondary\">\n {delegations.length}{\" \"}\n {delegations.length !== 1\n ? tr(\"devportal.delegations\", \"delegations\")\n : tr(\"devportal.delegation\", \"delegation\")}{\" \"}\n {tr(\"devportal.for\", \"for\")} {appName}\n </p>\n {activeDelegations.length > 0 && (\n <p className=\"text-xs text-text-secondary mt-0.5\">\n {activeDelegations.length} {tr(\"devportal.active\", \"active\")},{\" \"}\n {inactiveDelegations.length}{\" \"}\n {tr(\"devportal.revokedExpired\", \"revoked/expired\")}\n </p>\n )}\n </div>\n <button\n onClick={onGrantDelegation}\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 transition-colors\"\n >\n <Plus size={16} />\n {tr(\"devportal.grantDelegation\", \"Grant Delegation\")}\n </button>\n </div>\n\n {activeDelegations.length > 0 && (\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-4\">\n <div className=\"flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <div className=\"flex items-center gap-2\">\n <SelectionCheckbox\n checked={allVisibleSelected}\n indeterminate={partiallySelected}\n onChange={onToggleAllDelegations}\n ariaLabel={tr(\n \"devportal.selectAllActiveDelegations\",\n \"Select all active app delegations\",\n )}\n />\n <span className=\"text-sm font-medium\">\n {tr(\"devportal.selectAllActive\", \"Select all active\")}\n </span>\n </div>\n {selectedDelegationIds.size > 0 && (\n <button\n onClick={onClearSelection}\n className=\"text-sm text-text-secondary hover:text-text-primary\"\n >\n {tr(\"devportal.clearSelection\", \"Clear selection\")}\n </button>\n )}\n </div>\n\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"rounded-full bg-bg-sunken px-3 py-1 text-sm font-medium text-text-secondary\">\n {selectedDelegationIds.size}{\" \"}\n {tr(\"devportal.selected\", \"selected\")}\n </span>\n <button\n onClick={onRevokeSelected}\n disabled={selectedDelegationIds.size === 0}\n className=\"rounded-md border border-status-error-bg px-3 py-2 text-sm font-medium text-status-error-text hover:bg-status-error-bg-subtle disabled:cursor-not-allowed disabled:opacity-50\"\n >\n {tr(\"devportal.revokeSelected\", \"Revoke Selected\")}\n {selectedDelegationIds.size > 0\n ? ` (${selectedDelegationIds.size})`\n : \"\"}\n </button>\n </div>\n </div>\n </div>\n )}\n\n {delegations.length > 0 ? (\n <div className=\"space-y-4\">\n {delegations.map((delegation) => (\n <div\n key={delegation.id}\n className=\"rounded-card border border-border-seam bg-bg-surface p-4 space-y-4 shadow-[var(--shadow-pop)]\"\n >\n <div className=\"flex items-start justify-between\">\n <div className=\"flex items-start gap-3\">\n {delegation.status === \"ACTIVE\" && (\n <div onClick={(event) => event.stopPropagation()}>\n <SelectionCheckbox\n checked={selectedDelegationIds.has(delegation.id)}\n onChange={(checked) =>\n onToggleSelectDelegation(delegation.id, checked)\n }\n ariaLabel={`Select delegation ${delegation.id}`}\n className=\"mt-1\"\n />\n </div>\n )}\n <div>\n <div className=\"flex items-center gap-2\">\n <h3 className=\"font-medium\">\n Delegation #{delegation.id.slice(0, 8)}\n </h3>\n <span\n className={cn(\n \"rounded-full px-2 py-0.5 text-xs font-medium\",\n DELEGATION_STATUS_STYLES[delegation.status],\n )}\n >\n {delegation.status}\n </span>\n </div>\n <p className=\"text-sm text-text-secondary mt-1\">\n {tr(\"devportal.granted\", \"Granted\")}{\" \"}\n {new Date(delegation.grantedAt).toLocaleDateString()}{\" \"}\n {tr(\"devportal.by\", \"by\")}{\" \"}\n {delegation.grantedBy === delegation.userId\n ? tr(\"devportal.you\", \"you\")\n : delegation.grantedBy.slice(0, 8)}\n </p>\n </div>\n </div>\n {delegation.status === \"ACTIVE\" && (\n <button\n onClick={() => onRevokeDelegation(delegation.id)}\n className=\"inline-flex items-center gap-1.5 rounded-md border border-border-subtle px-3 py-1.5 text-xs font-medium text-status-error-text hover:bg-status-error-bg-subtle transition-colors\"\n >\n <XCircle size={14} />\n {tr(\"devportal.revoke\", \"Revoke\")}\n </button>\n )}\n </div>\n\n {/* Scopes */}\n <div>\n <p className=\"text-xs text-text-secondary mb-2\">\n {tr(\"devportal.grantedScopes\", \"Granted Scopes\")}\n </p>\n <div className=\"flex flex-wrap gap-2\">\n {delegation.scopes.map((scope) => (\n <span\n key={scope}\n className=\"rounded-full bg-status-success-bg-subtle px-2 py-0.5 text-xs text-status-success-text\"\n >\n {scope}\n </span>\n ))}\n </div>\n </div>\n\n {/* Workspace IDs */}\n {delegation.workspaceIds.length > 0 && (\n <div>\n <p className=\"text-xs text-text-secondary mb-2\">\n {tr(\"devportal.workspaceScope\", \"Workspace Scope\")}\n </p>\n <div className=\"flex flex-wrap gap-2\">\n {delegation.workspaceIds.map((wsId) => (\n <code\n key={wsId}\n className=\"rounded bg-bg-sunken px-2 py-0.5 text-xs\"\n >\n {wsId}\n </code>\n ))}\n </div>\n </div>\n )}\n\n {/* Metadata */}\n <div className=\"flex items-center gap-4 text-xs text-text-secondary\">\n {delegation.expiresAt && (\n <span className=\"flex items-center gap-1\">\n <Clock size={12} />\n {tr(\"devportal.expires\", \"Expires\")}{\" \"}\n {new Date(delegation.expiresAt).toLocaleDateString()}\n </span>\n )}\n {!delegation.expiresAt && delegation.status === \"ACTIVE\" && (\n <span className=\"flex items-center gap-1\">\n <CheckCircle\n size={12}\n className=\"text-status-success-text\"\n />\n {tr(\"devportal.noExpiration\", \"No expiration\")}\n </span>\n )}\n {delegation.revokedAt && (\n <span className=\"flex items-center gap-1\">\n <XCircle size={12} className=\"text-status-error-text\" />\n {tr(\"devportal.revoked\", \"Revoked\")}{\" \"}\n {new Date(delegation.revokedAt).toLocaleDateString()}\n </span>\n )}\n </div>\n </div>\n ))}\n </div>\n ) : (\n <EmptyState\n illustration=\"empty-people\"\n icon={<Users size={32} />}\n title={tr(\"devportal.noDelegations\", \"No delegations\")}\n description={tr(\n \"devportal.noDelegationsDescription\",\n \"Grant a delegation to allow this app to act on your behalf\",\n )}\n action={\n <button\n onClick={onGrantDelegation}\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\"\n >\n <Plus size={16} />\n {tr(\"devportal.grantDelegation\", \"Grant Delegation\")}\n </button>\n }\n />\n )}\n </div>\n );\n};\n\n// =============================================================================\n// ANALYTICS TAB\n// =============================================================================\n\nconst AnalyticsTab: FC<{ analytics: ApplicationAnalytics[] }> = ({\n analytics,\n}) => {\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 const latest = analytics[0];\n const previous = analytics[1];\n\n const calculateTrend = (current: number, prev: number) => {\n if (!prev) return 0;\n return ((current - prev) / prev) * 100;\n };\n\n return (\n <div className=\"space-y-6\">\n {/* Summary Stats */}\n <div className=\"grid gap-4 sm:grid-cols-4\">\n <StatCard\n label={tr(\"devportal.activeUsers\", \"Active Users\")}\n value={latest?.activeUsers.toLocaleString() || \"0\"}\n trend={\n previous\n ? calculateTrend(latest.activeUsers, previous.activeUsers)\n : undefined\n }\n />\n <StatCard\n label={tr(\"devportal.apiCalls\", \"API Calls\")}\n value={latest ? `${(latest.apiCalls / 1000).toFixed(1)}K` : \"0\"}\n trend={\n previous\n ? calculateTrend(latest.apiCalls, previous.apiCalls)\n : undefined\n }\n />\n <StatCard\n label={tr(\"devportal.avgResponseTime\", \"Avg Response Time\")}\n value={\n latest?.avgResponseTime\n ? `${latest.avgResponseTime}ms`\n : tr(\"devportal.notAvailable\", \"N/A\")\n }\n trend={\n previous && latest?.avgResponseTime\n ? -calculateTrend(\n latest.avgResponseTime,\n previous.avgResponseTime || 1,\n )\n : undefined\n }\n />\n <StatCard\n label={tr(\"devportal.errorRate\", \"Error Rate\")}\n value={\n latest && latest.apiCalls > 0\n ? `${((latest.errors / latest.apiCalls) * 100).toFixed(2)}%`\n : \"0%\"\n }\n trend={\n previous && latest && latest.apiCalls > 0 && previous.apiCalls > 0\n ? -calculateTrend(\n latest.errors / latest.apiCalls,\n previous.errors / previous.apiCalls,\n )\n : undefined\n }\n />\n </div>\n\n {/* Daily breakdown */}\n <PageSection title={tr(\"devportal.dailyBreakdown\", \"Daily Breakdown\")}>\n {analytics.length > 0 ? (\n <DataTable\n data={analytics}\n keyField=\"id\"\n columns={[\n {\n key: \"date\",\n header: tr(\"devportal.date\", \"Date\"),\n render: (item) => new Date(item.date).toLocaleDateString(),\n },\n {\n key: \"activeUsers\",\n header: tr(\"devportal.activeUsers\", \"Active Users\"),\n render: (item) => item.activeUsers.toLocaleString(),\n },\n {\n key: \"newUsers\",\n header: tr(\"devportal.newUsers\", \"New Users\"),\n render: (item) => item.newUsers.toLocaleString(),\n },\n {\n key: \"apiCalls\",\n header: tr(\"devportal.apiCalls\", \"API Calls\"),\n render: (item) => item.apiCalls.toLocaleString(),\n },\n {\n key: \"errors\",\n header: tr(\"devportal.errors\", \"Errors\"),\n render: (item) => item.errors.toLocaleString(),\n },\n {\n key: \"avgResponseTime\",\n header: tr(\"devportal.avgResponse\", \"Avg Response\"),\n render: (item) =>\n item.avgResponseTime\n ? `${item.avgResponseTime}ms`\n : tr(\"devportal.notAvailable\", \"N/A\"),\n },\n {\n key: \"sessions\",\n header: tr(\"devportal.sessions\", \"Sessions\"),\n render: (item) => item.sessions.toLocaleString(),\n },\n ]}\n />\n ) : (\n <EmptyState\n illustration=\"empty-data\"\n icon={<BarChart3 size={32} />}\n title={tr(\"devportal.noAnalyticsData\", \"No analytics data\")}\n description={tr(\n \"devportal.noAnalyticsDataDescription\",\n \"Analytics data will appear here once the application starts receiving traffic.\",\n )}\n />\n )}\n </PageSection>\n </div>\n );\n};\n\n// =============================================================================\n// API PLAYGROUND TAB\n// =============================================================================\n\nconst SAMPLE_QUERY = `# Sample query — replace with your own\n# Note: introspection is disabled on this gateway for security.\n# Use a real query from your app's API schema instead.\nquery GetCurrentUser {\n currentUser {\n id\n email\n }\n}`;\n\nconst ApiPlaygroundTab: FC<{ app: Application }> = ({ app }) => {\n const { apiGatewayUrl, workspacesGatewayUrl, authToken } = useDevportal();\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 const [query, setQuery] = useState(SAMPLE_QUERY);\n const [variables, setVariables] = useState(\"{}\");\n const [response, setResponse] = useState<string>(\"\");\n const [loading, setLoading] = useState(false);\n const [endpoint, setEndpoint] = useState(\n `${apiGatewayUrl || \"https://gw-global.local.burdenoff.com\"}/global/graphql`,\n );\n const [bearerToken, setBearerToken] = useState(authToken || \"\");\n const [showAuthHelp, setShowAuthHelp] = useState(false);\n\n const handleExecute = useCallback(async () => {\n setLoading(true);\n setResponse(\"\");\n try {\n let parsedVars = {};\n try {\n parsedVars = JSON.parse(variables);\n } catch {\n setResponse(\n JSON.stringify({ error: \"Invalid JSON in variables\" }, null, 2),\n );\n setLoading(false);\n return;\n }\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n if (bearerToken) {\n headers[\"Authorization\"] = `Bearer ${bearerToken}`;\n }\n\n const res = await fetch(endpoint, {\n method: \"POST\",\n headers,\n body: JSON.stringify({ query, variables: parsedVars }),\n });\n\n const data = await res.json();\n setResponse(JSON.stringify(data, null, 2));\n } catch (err) {\n setResponse(\n JSON.stringify(\n { error: err instanceof Error ? err.message : \"Request failed\" },\n null,\n 2,\n ),\n );\n } finally {\n setLoading(false);\n }\n }, [query, variables, endpoint, bearerToken]);\n\n const handleAutoFillCredentials = useCallback(() => {\n if (authToken) {\n setBearerToken(authToken);\n }\n setShowAuthHelp(true);\n }, [authToken]);\n\n return (\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h3 className=\"text-lg font-semibold\">\n {tr(\"devportal.apiPlayground\", \"API Playground\")}\n </h3>\n <p className=\"text-sm text-text-secondary\">\n {tr(\n \"devportal.apiPlaygroundDescription\",\n \"Test GraphQL APIs in the context of\",\n )}{\" \"}\n <strong>{app.name}</strong>\n {app.appId && (\n <span className=\"ml-1 text-xs text-text-secondary\">\n (OAuth App: {app.appId.slice(0, 8)}...)\n </span>\n )}\n </p>\n </div>\n <button\n onClick={handleAutoFillCredentials}\n className=\"flex items-center gap-2 rounded-md border px-3 py-1.5 text-sm font-medium hover:bg-accent transition-colors\"\n >\n <Key size={14} />\n {tr(\"devportal.autoFillCredentials\", \"Auto-fill Credentials\")}\n </button>\n </div>\n\n {showAuthHelp && (\n <div className=\"rounded-lg border bg-status-info-bg-subtle p-4 text-sm space-y-2\">\n <p className=\"font-medium text-status-info-text\">\n {tr(\"devportal.authenticationGuide\", \"Authentication Guide\")}\n </p>\n <p className=\"text-status-info-text\">\n {tr(\n \"devportal.authenticationGuideText\",\n \"Your current session token has been filled in. For app-level authentication (Client Credentials flow), use the\",\n )}{\" \"}\n <strong>{tr(\"devportal.oauthClientsTab\", \"OAuth Clients\")}</strong>{\" \"}\n {tr(\n \"devportal.authenticationGuideText2\",\n \"tab to get the app's clientId and clientSecret, then call:\",\n )}\n </p>\n <pre className=\"rounded bg-status-info-bg-subtle p-2 text-xs overflow-x-auto text-status-info-text\">\n {`mutation {\n authenticateApp(input: {\n clientId: \"<your-client-id>\"\n clientSecret: \"<your-client-secret>\"\n scopes: []\n }) {\n accessToken\n tokenType\n expiresIn\n }\n}`}\n </pre>\n <p className=\"text-status-info-text\">\n {tr(\"devportal.useReturnedAccessToken\", \"Use the returned\")}{\" \"}\n <code className=\"bg-status-info-bg-subtle px-1 rounded\">\n accessToken\n </code>{\" \"}\n {tr(\"devportal.asBearerToken\", \"as the Bearer token below.\")}\n </p>\n <button\n onClick={() => setShowAuthHelp(false)}\n className=\"text-xs text-accent-blue hover:underline\"\n >\n {tr(\"devportal.dismiss\", \"Dismiss\")}\n </button>\n </div>\n )}\n\n {/* Endpoint */}\n <div>\n <label className=\"block text-sm font-medium mb-1\">\n {tr(\"devportal.gatewayEndpoint\", \"Gateway Endpoint\")}\n </label>\n <div className=\"flex gap-2\">\n <input\n type=\"text\"\n value={endpoint}\n onChange={(e) => setEndpoint(e.target.value)}\n className=\"flex-1 rounded-md border px-3 py-2 text-sm font-mono bg-bg-surface\"\n />\n <select\n onChange={(e) => setEndpoint(e.target.value)}\n className=\"rounded-md border px-3 py-2 text-sm bg-bg-surface\"\n value={endpoint}\n >\n <option\n value={`${apiGatewayUrl || \"https://gw-global.local.burdenoff.com\"}/global/graphql`}\n >\n {tr(\"devportal.globalGateway\", \"Global Gateway\")}\n </option>\n <option\n value={`${workspacesGatewayUrl || \"https://gw-wspace.local.burdenoff.com\"}/workspaces/graphql`}\n >\n {tr(\"devportal.workspaceGateway\", \"Workspace Gateway\")}\n </option>\n </select>\n </div>\n </div>\n\n {/* Bearer Token */}\n <div>\n <label className=\"block text-sm font-medium mb-1\">\n {tr(\"devportal.bearerToken\", \"Bearer Token\")}\n </label>\n <input\n type=\"password\"\n value={bearerToken}\n onChange={(e) => setBearerToken(e.target.value)}\n placeholder={tr(\n \"devportal.pasteAccessToken\",\n \"Paste access token here...\",\n )}\n className=\"w-full rounded-md border px-3 py-2 text-sm font-mono bg-bg-surface\"\n />\n </div>\n\n {/* Query + Variables side by side */}\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-4\">\n <div>\n <label className=\"block text-sm font-medium mb-1\">\n {tr(\"devportal.query\", \"Query\")}\n </label>\n <textarea\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n className=\"w-full h-64 rounded-md border px-3 py-2 text-sm font-mono bg-bg-surface resize-y\"\n spellCheck={false}\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium mb-1\">\n {tr(\"devportal.variablesJson\", \"Variables (JSON)\")}\n </label>\n <textarea\n value={variables}\n onChange={(e) => setVariables(e.target.value)}\n className=\"w-full h-64 rounded-md border px-3 py-2 text-sm font-mono bg-bg-surface resize-y\"\n spellCheck={false}\n />\n </div>\n </div>\n\n {/* Execute */}\n <button\n onClick={handleExecute}\n disabled={loading}\n className=\"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 transition-colors disabled:opacity-50\"\n >\n {loading ? (\n <Loader2 size={16} className=\"animate-spin\" />\n ) : (\n <ExternalLink size={16} />\n )}\n {loading\n ? tr(\"devportal.executing\", \"Executing...\")\n : tr(\"devportal.executeQuery\", \"Execute Query\")}\n </button>\n\n {/* Response */}\n {response && (\n <div>\n <label className=\"block text-sm font-medium mb-1\">\n {tr(\"devportal.response\", \"Response\")}\n </label>\n <pre className=\"w-full max-h-96 overflow-auto rounded-md border bg-bg-sunken p-4 text-xs font-mono\">\n {response}\n </pre>\n </div>\n )}\n </div>\n );\n};\n\n// =============================================================================\n// IMAGE UPLOAD COMPONENTS\n// =============================================================================\n\ninterface ImageUploadFieldProps {\n label: string;\n value: string;\n onChange: (url: string) => void;\n hint?: string;\n accept?: string;\n aspectClass?: string; // tailwind class for the preview container ratio\n upload: (file: File) => Promise<{ downloadUrl: string }>;\n uploading: boolean;\n progress: number;\n error: string | null;\n}\n\nconst ImageUploadField: FC<ImageUploadFieldProps> = ({\n label,\n value,\n onChange,\n hint,\n accept = \"image/png,image/jpeg,image/webp,image/gif,image/svg+xml\",\n aspectClass = \"aspect-square\",\n upload,\n uploading,\n progress,\n error,\n}) => {\n const inputRef = useRef<HTMLInputElement>(null);\n const [imgBroken, setImgBroken] = useState(false);\n const prevValue = useRef(value);\n if (prevValue.current !== value) {\n prevValue.current = value;\n if (imgBroken) setImgBroken(false);\n }\n\n const handleFile = useCallback(\n async (file: File) => {\n try {\n const result = await upload(file);\n onChange(result.downloadUrl);\n } catch {\n // error shown via error prop\n }\n },\n [upload, onChange],\n );\n\n return (\n <div className=\"space-y-1.5\">\n <label className=\"text-sm font-medium\">{label}</label>\n <div className=\"flex gap-3 items-start\">\n {/* Preview */}\n <div\n className={cn(\n \"relative shrink-0 w-20 rounded-lg border border-border-subtle bg-bg-sunken overflow-hidden flex items-center justify-center\",\n aspectClass,\n )}\n >\n {value && !imgBroken ? (\n <img\n src={value}\n alt={label}\n className=\"w-full h-full object-cover\"\n onError={() => setImgBroken(true)}\n />\n ) : (\n <Upload size={18} className=\"text-text-secondary opacity-40\" />\n )}\n {uploading && (\n <div className=\"absolute inset-0 bg-bg-overlay flex flex-col items-center justify-center gap-1\">\n <Loader2 size={14} className=\"animate-spin text-white\" />\n <span className=\"text-white text-xs\">{progress}%</span>\n </div>\n )}\n </div>\n {/* URL input + upload button */}\n <div className=\"flex-1 space-y-1.5\">\n <input\n type=\"url\"\n value={value}\n onChange={(e) => onChange(e.target.value)}\n placeholder=\"https://...\"\n className=\"w-full rounded-md border border-border-subtle bg-bg-input px-3 py-1.5 text-sm placeholder:text-text-placeholder focus:outline-none focus:ring-2 focus:ring-primary/30\"\n />\n <input\n ref={inputRef}\n type=\"file\"\n accept={accept}\n className=\"hidden\"\n onChange={(e) => {\n const f = e.target.files?.[0];\n if (f) void handleFile(f);\n e.target.value = \"\";\n }}\n />\n <button\n type=\"button\"\n disabled={uploading}\n onClick={() => inputRef.current?.click()}\n className=\"inline-flex items-center gap-1.5 rounded-md border px-2.5 py-1 text-xs font-medium hover:bg-bg-sunken transition-colors disabled:opacity-50\"\n >\n <Upload size={11} />\n {uploading ? `Uploading… ${progress}%` : \"Upload image\"}\n </button>\n {error && <p className=\"text-xs text-status-error-text\">{error}</p>}\n </div>\n </div>\n {hint && <p className=\"text-xs text-text-secondary\">{hint}</p>}\n </div>\n );\n};\n\ninterface ScreenshotGalleryProps {\n urls: string[];\n onChange: (urls: string[]) => void;\n upload: (file: File) => Promise<{ downloadUrl: string }>;\n uploading: boolean;\n progress: number;\n error: string | null;\n}\n\nconst ScreenshotGallery: FC<ScreenshotGalleryProps> = ({\n urls,\n onChange,\n upload,\n uploading,\n progress,\n error,\n}) => {\n const inputRef = useRef<HTMLInputElement>(null);\n const [urlInput, setUrlInput] = useState(\"\");\n\n const handleFile = useCallback(\n async (file: File) => {\n try {\n const result = await upload(file);\n onChange([...urls, result.downloadUrl]);\n } catch {\n // error shown via error prop\n }\n },\n [upload, onChange, urls],\n );\n\n const addUrl = () => {\n const trimmed = urlInput.trim();\n if (trimmed && !urls.includes(trimmed)) {\n onChange([...urls, trimmed]);\n setUrlInput(\"\");\n }\n };\n\n const remove = (idx: number) => {\n onChange(urls.filter((_, i) => i !== idx));\n };\n\n return (\n <div className=\"space-y-2\">\n <div className=\"flex flex-col gap-0.5\">\n <label className=\"text-sm font-medium\">Screenshots</label>\n <p className=\"text-xs text-text-muted\">\n Shown in the horizontal preview strip below the hero — wide landscape\n proportions work best (16:9)\n </p>\n </div>\n <div className=\"flex flex-wrap gap-3\">\n {urls.map((url, idx) => (\n <div\n key={idx}\n className=\"relative group w-36 aspect-video rounded-lg border border-border-subtle overflow-hidden bg-bg-sunken\"\n >\n <img\n src={url}\n alt={`Screenshot ${idx + 1}`}\n className=\"w-full h-full object-cover\"\n />\n <button\n type=\"button\"\n onClick={() => remove(idx)}\n className=\"absolute top-1 right-1 rounded-full bg-bg-overlay text-white p-0.5 opacity-0 group-hover:opacity-100 transition-opacity\"\n >\n <X size={12} />\n </button>\n </div>\n ))}\n {/* Upload slot */}\n <button\n type=\"button\"\n disabled={uploading}\n onClick={() => inputRef.current?.click()}\n className={cn(\n \"w-36 aspect-video rounded-lg border-2 border-dashed border-border-subtle flex flex-col items-center justify-center gap-1.5 text-text-secondary hover:border-border-strong hover:bg-bg-sunken transition-colors disabled:opacity-50\",\n )}\n >\n {uploading ? (\n <>\n <Loader2 size={18} className=\"animate-spin text-primary\" />\n <span className=\"text-xs\">{progress}%</span>\n </>\n ) : (\n <>\n <Upload size={18} />\n <span className=\"text-xs\">Add screenshot</span>\n </>\n )}\n </button>\n </div>\n {/* URL paste row */}\n <div className=\"flex gap-2\">\n <input\n type=\"url\"\n value={urlInput}\n onChange={(e) => setUrlInput(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") {\n e.preventDefault();\n addUrl();\n }\n }}\n placeholder=\"https://... paste a screenshot URL\"\n className=\"flex-1 rounded-md border border-border-subtle bg-bg-input px-3 py-1.5 text-sm placeholder:text-text-placeholder focus:outline-none focus:ring-2 focus:ring-primary/30\"\n />\n <button\n type=\"button\"\n onClick={addUrl}\n disabled={!urlInput.trim()}\n className=\"inline-flex items-center gap-1.5 rounded-md border px-2.5 py-1.5 text-xs font-medium hover:bg-bg-sunken transition-colors disabled:opacity-50\"\n >\n Add\n </button>\n </div>\n <input\n ref={inputRef}\n type=\"file\"\n accept=\"image/png,image/jpeg,image/webp,image/gif\"\n className=\"hidden\"\n onChange={(e) => {\n const f = e.target.files?.[0];\n if (f) void handleFile(f);\n e.target.value = \"\";\n }}\n />\n {error && <p className=\"text-xs text-status-error-text\">{error}</p>}\n </div>\n );\n};\n\n// =============================================================================\n// STORE LISTING TAB\n// =============================================================================\n\ninterface ManifestIdentity {\n version: string;\n displayName: string;\n}\n\ninterface ManifestInstall {\n type: string;\n url?: string;\n packageName?: string;\n registryUrl?: string;\n}\n\ninterface ManifestDigital {\n install: ManifestInstall;\n}\n\ninterface ManifestCompatibility {\n minPlatformVersion: string;\n}\n\ninterface StoreManifest {\n manifestVersion: string;\n itemType?: string;\n identity: ManifestIdentity;\n digital?: ManifestDigital;\n jsonContent?: string;\n permissions: string[];\n compatibility: ManifestCompatibility;\n}\n\ninterface StoreListingFormData {\n // Store Presentation\n iconUrl: string;\n bannerUrl: string;\n videoUrl: string;\n shortDescription: string;\n description: string;\n screenshotsText: string;\n // Links & Policies\n websiteUrl: string;\n documentationUrl: string;\n githubUrl: string;\n supportUrl: string;\n privacyPolicyUrl: string;\n termsOfServiceUrl: string;\n // Manifest\n manifestItemType: string;\n manifestDisplayName: string;\n manifestVersion: string;\n manifestInstallType: string;\n manifestPackageName: string;\n manifestRegistryUrl: string;\n manifestPermissionsText: string;\n manifestMinPlatformVersion: string;\n // JSON-only content (workflow / template)\n manifestJsonContent: string;\n}\n\n/** Item types whose entire payload IS a JSON document — no zip or binary needed. */\nconst JSON_ONLY_ITEM_TYPES = new Set([\"workflow\", \"template\"]);\n\nconst PRICING_TYPE_OPTIONS = [\n { value: \"FREE\", label: \"Free\" },\n { value: \"PAID\", label: \"Paid\" },\n];\n\nconst CURRENCY_OPTIONS = [\n { value: \"USD\", label: \"USD — US Dollar\" },\n { value: \"EUR\", label: \"EUR — Euro\" },\n { value: \"GBP\", label: \"GBP — British Pound\" },\n { value: \"INR\", label: \"INR — Indian Rupee\" },\n { value: \"CAD\", label: \"CAD — Canadian Dollar\" },\n { value: \"AUD\", label: \"AUD — Australian Dollar\" },\n { value: \"SGD\", label: \"SGD — Singapore Dollar\" },\n { value: \"JPY\", label: \"JPY — Japanese Yen\" },\n];\n\nconst ITEM_TYPE_OPTIONS_BY_APP_TYPE: Record<\n string,\n { value: string; label: string }[]\n> = {\n NODE: [\n { value: \"node\", label: \"Node\" },\n { value: \"agent\", label: \"Agent\" },\n { value: \"parser\", label: \"Parser\" },\n { value: \"datasink\", label: \"Data Sink\" },\n { value: \"component\", label: \"Component\" },\n ],\n WORKFLOW: [\n { value: \"workflow\", label: \"Workflow\" },\n { value: \"template\", label: \"Template\" },\n ],\n APP: [\n { value: \"app\", label: \"App\" },\n { value: \"integration\", label: \"Integration\" },\n { value: \"extension\", label: \"Extension\" },\n { value: \"widget\", label: \"Widget\" },\n { value: \"dashboard\", label: \"Dashboard\" },\n { value: \"console\", label: \"Console\" },\n { value: \"botapp\", label: \"Bot App\" },\n { value: \"vibemodule\", label: \"Vibe Module\" },\n { value: \"theme\", label: \"Theme\" },\n { value: \"plugin\", label: \"Plugin\" },\n ],\n};\n\nconst DEFAULT_ITEM_TYPE: Record<string, string> = {\n NODE: \"node\",\n WORKFLOW: \"workflow\",\n APP: \"app\",\n};\n\nconst INSTALL_TYPE_OPTIONS = [\n { value: \"zip\", label: \"zip\" },\n { value: \"builtin\", label: \"builtin\" },\n];\n\nfunction buildInitialFormData(app: Application): StoreListingFormData {\n const manifest = (app.manifest ?? {}) as Record<string, unknown>;\n const identity = (manifest.identity ?? {}) as Record<string, unknown>;\n const digital = (manifest.digital ?? {}) as Record<string, unknown>;\n const install = (digital.install ?? {}) as Record<string, unknown>;\n const compatibility = (manifest.compatibility ?? {}) as Record<\n string,\n unknown\n >;\n const permissions = Array.isArray(manifest.permissions)\n ? (manifest.permissions as string[])\n : [];\n\n const screenshots = Array.isArray(app.screenshots)\n ? (app.screenshots as string[]).join(\"\\n\")\n : \"\";\n\n return {\n iconUrl: app.iconUrl ?? \"\",\n bannerUrl: app.bannerUrl ?? \"\",\n videoUrl: app.videoUrl ?? \"\",\n shortDescription: app.shortDescription ?? \"\",\n description: app.description ?? \"\",\n screenshotsText: screenshots,\n websiteUrl: app.websiteUrl ?? \"\",\n documentationUrl: app.documentationUrl ?? \"\",\n githubUrl: app.githubUrl ?? \"\",\n supportUrl: app.supportUrl ?? \"\",\n privacyPolicyUrl: app.privacyPolicyUrl ?? \"\",\n termsOfServiceUrl: app.termsOfServiceUrl ?? \"\",\n manifestItemType:\n typeof manifest.itemType === \"string\"\n ? manifest.itemType\n : (DEFAULT_ITEM_TYPE[app.appType] ?? \"\"),\n manifestDisplayName:\n typeof identity.displayName === \"string\"\n ? identity.displayName\n : (app.name ?? \"\"),\n manifestVersion:\n typeof identity.version === \"string\" ? identity.version : \"\",\n manifestInstallType:\n typeof install.type === \"string\" ? install.type : \"zip\",\n manifestPackageName: \"\",\n manifestRegistryUrl:\n typeof install.url === \"string\"\n ? install.url\n : typeof install.registryUrl === \"string\"\n ? install.registryUrl\n : \"\",\n manifestPermissionsText: permissions.join(\"\\n\"),\n manifestMinPlatformVersion:\n typeof compatibility.minPlatformVersion === \"string\"\n ? compatibility.minPlatformVersion\n : \"\",\n manifestJsonContent:\n typeof manifest.jsonContent === \"string\"\n ? manifest.jsonContent\n : typeof manifest.content === \"string\"\n ? manifest.content\n : \"\",\n };\n}\n\nconst StoreListingTab: FC<{\n app: Application;\n versionCount?: number;\n isPackageApp?: boolean;\n pricingDone?: boolean;\n onNavigateToVersions?: () => void;\n onNavigateToPricing?: () => void;\n onNavigateToSubmission?: () => void;\n}> = ({\n app,\n versionCount = 0,\n isPackageApp = false,\n pricingDone = false,\n onNavigateToVersions,\n onNavigateToPricing,\n onNavigateToSubmission,\n}) => {\n const { workspacesGatewayUrl, authToken, workspaceId, getWorkspaceToken } =\n useDevportal();\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 [formData, setFormData] = useState<StoreListingFormData>(() =>\n buildInitialFormData(app),\n );\n const [isSaving, setIsSaving] = useState(false);\n const [saveResult, setSaveResult] = useState<\"success\" | \"error\" | null>(\n null,\n );\n // Tracks the form state as it exists on the server (last save or initial load).\n // isDirty compares current formData against this; Save is disabled when not dirty.\n const serverFormData = useRef<StoreListingFormData>(\n buildInitialFormData(app),\n );\n const appRef = useRef(app);\n appRef.current = app;\n\n const isDirty =\n JSON.stringify(formData) !== JSON.stringify(serverFormData.current);\n\n const [updateApplication] = useUpdateApplicationMutation();\n\n // Reset form only when navigating to a different app (not on every refetch)\n useEffect(() => {\n const initial = buildInitialFormData(appRef.current);\n setFormData(initial);\n serverFormData.current = initial;\n setSaveResult(null);\n }, [app.id]);\n\n const handleChange = (field: keyof StoreListingFormData, value: string) => {\n setFormData((prev) => ({ ...prev, [field]: value }));\n setSaveResult(null);\n };\n\n const isFormValid =\n formData.shortDescription.trim().length > 0 &&\n formData.privacyPolicyUrl.trim().length > 0 &&\n formData.termsOfServiceUrl.trim().length > 0;\n\n const handleSave = async () => {\n setIsSaving(true);\n setSaveResult(null);\n try {\n const screenshotUrls = formData.screenshotsText\n .split(\"\\n\")\n .map((s) => s.trim())\n .filter(Boolean);\n\n const permissions = formData.manifestPermissionsText\n .split(\"\\n\")\n .map((s) => s.trim())\n .filter(Boolean);\n\n const isJsonOnly = JSON_ONLY_ITEM_TYPES.has(formData.manifestItemType);\n\n // Build manifest by merging existing app.manifest with form values\n const baseManifest = (app.manifest ?? {}) as Record<string, unknown>;\n const updatedManifest: StoreManifest = {\n manifestVersion:\n typeof baseManifest.manifestVersion === \"string\"\n ? baseManifest.manifestVersion\n : \"1.0\",\n itemType: formData.manifestItemType || undefined,\n identity: {\n version: formData.manifestVersion || \"1.0.0\",\n displayName: formData.manifestDisplayName,\n },\n ...(isJsonOnly\n ? { jsonContent: formData.manifestJsonContent || undefined }\n : {\n digital: {\n install: {\n type: formData.manifestInstallType,\n ...(formData.manifestInstallType === \"zip\" &&\n formData.manifestRegistryUrl\n ? { url: formData.manifestRegistryUrl }\n : {}),\n },\n },\n }),\n permissions,\n compatibility: {\n minPlatformVersion: formData.manifestMinPlatformVersion,\n },\n };\n\n await updateApplication({\n variables: {\n id: app.id,\n input: {\n iconUrl: formData.iconUrl || null,\n bannerUrl: formData.bannerUrl || null,\n videoUrl: formData.videoUrl || null,\n shortDescription: formData.shortDescription || null,\n description: formData.description || null,\n screenshots:\n screenshotUrls.length > 0\n ? (screenshotUrls as unknown as Record<string, unknown>)\n : null,\n websiteUrl: formData.websiteUrl || null,\n documentationUrl: formData.documentationUrl || null,\n githubUrl: formData.githubUrl || null,\n supportUrl: formData.supportUrl || null,\n privacyPolicyUrl: formData.privacyPolicyUrl || null,\n termsOfServiceUrl: formData.termsOfServiceUrl || null,\n manifest: updatedManifest as unknown as Record<string, unknown>,\n },\n },\n });\n void nativeNotify(\"success\");\n setSaveResult(\"success\");\n // Mark current values as the new clean server state so isDirty = false\n serverFormData.current = formData;\n } catch {\n void nativeNotify(\"error\");\n setSaveResult(\"error\");\n } finally {\n setIsSaving(false);\n }\n };\n\n const {\n upload: uploadAsset,\n uploading: iconUploading,\n progress: iconProgress,\n error: iconUploadError,\n } = usePackageUpload(\n workspacesGatewayUrl,\n authToken,\n workspaceId,\n getWorkspaceToken,\n \"/DevPortal/Assets\",\n );\n const {\n upload: uploadBanner,\n uploading: bannerUploading,\n progress: bannerProgress,\n error: bannerUploadError,\n } = usePackageUpload(\n workspacesGatewayUrl,\n authToken,\n workspaceId,\n getWorkspaceToken,\n \"/DevPortal/Assets\",\n );\n const {\n upload: uploadScreenshot,\n uploading: screenshotUploading,\n progress: screenshotProgress,\n error: screenshotUploadError,\n } = usePackageUpload(\n workspacesGatewayUrl,\n authToken,\n workspaceId,\n getWorkspaceToken,\n \"/DevPortal/Assets\",\n );\n\n const isJsonOnlyType = JSON_ONLY_ITEM_TYPES.has(formData.manifestItemType);\n\n const isSubmitted = app.status === \"SUBMITTED\";\n const isPublished = app.status === \"PUBLISHED\";\n\n return (\n <div className=\"space-y-8 max-w-3xl\">\n {/* ── Status banner ─────────────────────────────────────── */}\n {isPublished ? (\n <div className=\"flex items-start gap-3 rounded-lg border border-success/30 bg-success/10 px-4 py-3\">\n <CheckCircle size={16} className=\"text-success mt-0.5 shrink-0\" />\n <div className=\"text-sm\">\n <span className=\"font-medium text-success\">\n {tr(\"devportal.storeListing.published\", \"Published\")}\n </span>\n {app.publishedAt && (\n <span className=\"text-text-secondary ml-2\">\n {tr(\"devportal.storeListing.since\", \"since\")}{\" \"}\n {new Date(app.publishedAt).toLocaleDateString()}\n </span>\n )}\n </div>\n </div>\n ) : isSubmitted ? (\n <div className=\"flex items-center justify-between gap-3 rounded-lg border border-primary/30 bg-action-primary-bg/5 px-4 py-3\">\n <div className=\"flex items-start gap-3\">\n <Clock size={16} className=\"text-primary mt-0.5 shrink-0\" />\n <div className=\"text-sm\">\n <span className=\"font-medium text-primary\">\n {tr(\n \"devportal.storeListing.underReview\",\n \"Submitted for review\",\n )}\n </span>\n {app.submittedAt && (\n <span className=\"text-text-secondary ml-2\">\n {new Date(app.submittedAt).toLocaleDateString()}\n </span>\n )}\n {app.reviewStatus && (\n <span className=\"text-text-secondary ml-2\">\n · {app.reviewStatus}\n </span>\n )}\n </div>\n </div>\n {onNavigateToSubmission && (\n <button\n type=\"button\"\n onClick={onNavigateToSubmission}\n className=\"shrink-0 text-xs text-primary hover:underline font-medium flex items-center gap-1\"\n >\n {tr(\"devportal.viewStatus\", \"View Status\")}\n <ExternalLink size={12} />\n </button>\n )}\n </div>\n ) : (\n <div className=\"flex items-start gap-3 rounded-lg border border-warning/30 bg-warning/5 px-4 py-3\">\n <AlertCircle size={16} className=\"text-warning mt-0.5 shrink-0\" />\n <div className=\"text-sm\">\n <span className=\"font-medium text-warning\">\n {tr(\"devportal.storeListing.draft\", \"Draft\")}\n </span>\n <span className=\"text-text-secondary ml-2\">\n {tr(\n \"devportal.storeListing.draftHint\",\n \"Complete your store listing and submit for review to publish.\",\n )}\n </span>\n </div>\n </div>\n )}\n\n {/* ── Section 1: Package ─────────────────────────────────── */}\n <PageSection\n title={tr(\"devportal.package\", \"Package\")}\n description={tr(\n \"devportal.packageDescription\",\n \"Technical configuration — how FluidGrid installs and runs this item\",\n )}\n >\n <div className=\"space-y-6\">\n {/* Item type — fine-grained store classification within the app's broad type */}\n <SelectField\n label={tr(\"devportal.storeItemType\", \"Item Type\")}\n value={formData.manifestItemType}\n onChange={(e) => {\n const next = e.target.value;\n handleChange(\"manifestItemType\", next);\n if (JSON_ONLY_ITEM_TYPES.has(next)) {\n handleChange(\"manifestInstallType\", \"json\");\n } else if (formData.manifestInstallType === \"json\") {\n handleChange(\"manifestInstallType\", \"zip\");\n }\n }}\n options={\n ITEM_TYPE_OPTIONS_BY_APP_TYPE[app.appType] ??\n ITEM_TYPE_OPTIONS_BY_APP_TYPE[\"APP\"]!\n }\n placeholder={tr(\"devportal.selectItemType\", \"Select item type…\")}\n hint={tr(\n \"devportal.storeItemTypeHint\",\n \"Sub-category shown in the marketplace (e.g. Node vs Agent vs Parser)\",\n )}\n />\n\n {/* Identity */}\n <InputField\n label={tr(\"devportal.manifestDisplayName\", \"Display Name\")}\n value={formData.manifestDisplayName}\n onChange={(e) =>\n handleChange(\"manifestDisplayName\", e.target.value)\n }\n placeholder=\"My Awesome Node\"\n />\n\n {/* JSON editor for template types — workflow JSON lives on the Versions tab */}\n {isJsonOnlyType && app.appType !== \"WORKFLOW\" && (\n <TextareaField\n label={tr(\"devportal.jsonContent\", \"Template Definition (JSON)\")}\n value={formData.manifestJsonContent}\n onChange={(e) =>\n handleChange(\"manifestJsonContent\", e.target.value)\n }\n rows={12}\n placeholder={'{\\n \"nodes\": [],\\n \"edges\": []\\n}'}\n hint={tr(\n \"devportal.jsonContentHint\",\n \"Paste the full JSON definition. Stored and applied directly — no zip needed.\",\n )}\n />\n )}\n {isJsonOnlyType && app.appType === \"WORKFLOW\" && (\n <p className=\"text-sm text-text-secondary rounded-md bg-bg-sunken px-3 py-2\">\n The Workflow Definition (JSON) is set per version. Go to the{\" \"}\n <strong>Versions</strong> tab to add or update it.\n </p>\n )}\n </div>\n </PageSection>\n\n {/* ── Section 2: Store Presence ──────────────────────────── */}\n <PageSection\n title={tr(\"devportal.storePresentation\", \"Store Presence\")}\n description={tr(\n \"devportal.storePresentationDescription\",\n \"Visual assets and copy shown to users browsing the marketplace\",\n )}\n >\n <div className=\"space-y-5\">\n <div className=\"grid gap-5 sm:grid-cols-2\">\n <ImageUploadField\n label={tr(\"devportal.iconUrl\", \"Icon\")}\n value={formData.iconUrl}\n onChange={(url) => handleChange(\"iconUrl\", url)}\n hint={tr(\n \"devportal.iconUrlHint\",\n \"Shown in marketplace cards and search — square proportions (1:1)\",\n )}\n aspectClass=\"aspect-square\"\n upload={uploadAsset}\n uploading={iconUploading}\n progress={iconProgress}\n error={iconUploadError}\n />\n <ImageUploadField\n label={tr(\"devportal.bannerUrl\", \"Banner\")}\n value={formData.bannerUrl}\n onChange={(url) => handleChange(\"bannerUrl\", url)}\n hint={tr(\n \"devportal.bannerUrlHint\",\n \"Fills the right panel on the product page — square or portrait works best on all screen sizes (1:1)\",\n )}\n aspectClass=\"aspect-square\"\n upload={uploadBanner}\n uploading={bannerUploading}\n progress={bannerProgress}\n error={bannerUploadError}\n />\n </div>\n <InputField\n label={tr(\"devportal.videoUrl\", \"Demo Video URL\")}\n value={formData.videoUrl}\n onChange={(e) => handleChange(\"videoUrl\", e.target.value)}\n placeholder=\"https://...\"\n hint={tr(\"devportal.videoUrlHint\", \"YouTube or Vimeo embed URL\")}\n />\n <TextareaField\n label={tr(\"devportal.shortDescription\", \"Short Description\")}\n value={formData.shortDescription}\n onChange={(e) => handleChange(\"shortDescription\", e.target.value)}\n maxLength={200}\n rows={2}\n hint={`${formData.shortDescription.length}/200 · ${tr(\"devportal.shortDescHint\", \"Shown in search results and cards\")}`}\n />\n <TextareaField\n label={tr(\"devportal.longDescription\", \"Full Description\")}\n value={formData.description}\n onChange={(e) => handleChange(\"description\", e.target.value)}\n rows={5}\n hint={tr(\"devportal.fullDescHint\", \"Markdown supported\")}\n />\n <ScreenshotGallery\n urls={formData.screenshotsText\n .split(\"\\n\")\n .map((s) => s.trim())\n .filter(Boolean)}\n onChange={(urls) =>\n handleChange(\"screenshotsText\", urls.join(\"\\n\"))\n }\n upload={uploadScreenshot}\n uploading={screenshotUploading}\n progress={screenshotProgress}\n error={screenshotUploadError}\n />\n </div>\n </PageSection>\n\n {/* ── Section 3: Links & Policies ────────────────────────── */}\n <PageSection\n title={tr(\"devportal.linksPolicies\", \"Links & Policies\")}\n description={tr(\n \"devportal.linksPoliciesDescription\",\n \"External resources and legal documents — privacy policy and terms are required for store submission\",\n )}\n >\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <InputField\n label={tr(\"devportal.websiteUrl\", \"Website\")}\n value={formData.websiteUrl}\n onChange={(e) => handleChange(\"websiteUrl\", e.target.value)}\n placeholder=\"https://...\"\n />\n <InputField\n label={tr(\"devportal.documentationUrl\", \"Documentation\")}\n value={formData.documentationUrl}\n onChange={(e) => handleChange(\"documentationUrl\", e.target.value)}\n placeholder=\"https://...\"\n />\n <InputField\n label={tr(\"devportal.githubUrl\", \"GitHub\")}\n value={formData.githubUrl}\n onChange={(e) => handleChange(\"githubUrl\", e.target.value)}\n placeholder=\"https://github.com/...\"\n />\n <InputField\n label={tr(\"devportal.supportUrl\", \"Support\")}\n value={formData.supportUrl}\n onChange={(e) => handleChange(\"supportUrl\", e.target.value)}\n placeholder=\"https://...\"\n />\n <InputField\n label={`${tr(\"devportal.privacyPolicyUrl\", \"Privacy Policy\")} *`}\n value={formData.privacyPolicyUrl}\n onChange={(e) => handleChange(\"privacyPolicyUrl\", e.target.value)}\n placeholder=\"https://...\"\n hint={tr(\n \"devportal.requiredForStore\",\n \"Required for store submission\",\n )}\n />\n <InputField\n label={`${tr(\"devportal.termsOfServiceUrl\", \"Terms of Service\")} *`}\n value={formData.termsOfServiceUrl}\n onChange={(e) => handleChange(\"termsOfServiceUrl\", e.target.value)}\n placeholder=\"https://...\"\n hint={tr(\n \"devportal.requiredForStore\",\n \"Required for store submission\",\n )}\n />\n </div>\n </PageSection>\n\n {/* Save store listing + next-step hint */}\n <div className=\"border-t pt-6 space-y-3\">\n {saveResult === \"success\" && (\n <div className=\"flex items-center gap-2 rounded-md border border-success/30 bg-success/10 px-3 py-2 text-sm text-success\">\n <CheckCircle size={15} className=\"shrink-0\" />\n {tr(\n \"devportal.storeListing.savedSuccess\",\n \"Store listing saved successfully.\",\n )}\n </div>\n )}\n {saveResult === \"error\" && (\n <div className=\"flex items-center gap-2 rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive\">\n <AlertCircle size={15} className=\"shrink-0\" />\n {tr(\n \"devportal.storeListing.savedError\",\n \"Failed to save. Please try again.\",\n )}\n </div>\n )}\n <div className=\"flex flex-wrap items-center gap-3\">\n <button\n type=\"button\"\n onClick={handleSave}\n disabled={isSaving || !isFormValid || !isDirty}\n title={\n !isFormValid\n ? tr(\n \"devportal.storeListing.requiredFieldsHint\",\n \"Fill in Short Description, Privacy Policy URL, and Terms of Service URL to save\",\n )\n : !isDirty\n ? tr(\n \"devportal.storeListing.noChanges\",\n \"All changes saved — edit any field to save again\",\n )\n : undefined\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 hover:bg-action-primary-bg/90 transition-colors disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n {isSaving ? (\n <>\n <Loader2 size={16} className=\"animate-spin\" />\n {tr(\"devportal.saving\", \"Saving…\")}\n </>\n ) : !isDirty ? (\n <>\n <Check size={16} />\n {tr(\"devportal.saved\", \"Saved\")}\n </>\n ) : (\n <>\n <Store size={16} />\n {tr(\"devportal.saveStoreListing\", \"Save Store Listing\")}\n </>\n )}\n </button>\n {!isFormValid && (\n <p className=\"text-xs text-text-secondary\">\n {tr(\n \"devportal.storeListing.requiredFieldsLabel\",\n \"Short Description, Privacy Policy URL, and Terms of Service URL are required\",\n )}\n </p>\n )}\n {/* Guide the user to their next incomplete step */}\n {isPackageApp && versionCount === 0 && onNavigateToVersions && (\n <button\n type=\"button\"\n onClick={onNavigateToVersions}\n className=\"inline-flex items-center gap-1.5 text-sm font-medium text-primary hover:underline underline-offset-2\"\n >\n {tr(\"devportal.nextUploadVersion\", \"Next: Upload a Version\")}\n <ChevronRight size={15} />\n </button>\n )}\n {(!isPackageApp || versionCount > 0) &&\n !pricingDone &&\n onNavigateToPricing && (\n <button\n type=\"button\"\n onClick={onNavigateToPricing}\n className=\"inline-flex items-center gap-1.5 text-sm font-medium text-primary hover:underline underline-offset-2\"\n >\n {tr(\"devportal.nextSetPricing\", \"Next: Set Pricing\")}\n <ChevronRight size={15} />\n </button>\n )}\n </div>\n </div>\n </div>\n );\n};\n\n// =============================================================================\n// HELPER COMPONENTS\n// =============================================================================\n\nconst StatCard: FC<{ label: string; value: string; trend?: number }> = ({\n label,\n value,\n trend,\n}) => {\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const v = t(key);\n return v === key ? fallback : v;\n };\n return (\n <GlassCard treatment=\"metric\" className=\"p-4\">\n <p className=\"text-sm text-text-secondary\">{label}</p>\n <p className=\"text-2xl font-bold tabular-nums\">{value}</p>\n {trend !== undefined && (\n <p\n className={cn(\n \"text-xs mt-1 tabular-nums\",\n trend > 0\n ? \"text-status-success-text\"\n : trend < 0\n ? \"text-status-error-text\"\n : \"text-text-secondary\",\n )}\n >\n {trend > 0 ? \"+\" : \"\"}\n {trend.toFixed(1)}% {tr(\"devportal.vsYesterday\", \"vs yesterday\")}\n </p>\n )}\n </GlassCard>\n );\n};\n\nconst LinkItem: FC<{ label: string; url: string }> = ({ label, url }) => (\n <a\n href={url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"flex items-center gap-2 text-sm text-primary hover:underline\"\n >\n <ExternalLink size={14} />\n {label}\n </a>\n);\n\n// =============================================================================\n// PERMISSIONS TAB\n// =============================================================================\n\n// Friendly labels/descriptions for known platform resources\nconst RESOURCE_META: Record<string, { label: string; description: string }> = {\n auth: {\n label: \"Authentication\",\n description: \"User identity and session management\",\n },\n billing: {\n label: \"Billing\",\n description: \"Billing accounts and subscriptions\",\n },\n files: { label: \"Files\", description: \"File storage and management\" },\n tags: { label: \"Tags\", description: \"Tags and labels on resources\" },\n calendar: { label: \"Calendar\", description: \"Events and scheduling\" },\n workflows: { label: \"Workflows\", description: \"Automation workflows\" },\n channels: { label: \"Channels\", description: \"Messaging channels\" },\n notifications: {\n label: \"Notifications\",\n description: \"Platform notifications\",\n },\n users: {\n label: \"Users & Members\",\n description: \"Workspace members and profiles\",\n },\n workspaces: {\n label: \"Workspaces\",\n description: \"Workspace settings and metadata\",\n },\n content: { label: \"Content\", description: \"Pages, documents, and content\" },\n analytics: {\n label: \"Analytics\",\n description: \"Usage analytics and reporting\",\n },\n webhooks: { label: \"Webhooks\", description: \"Webhook subscriptions\" },\n rbac: {\n label: \"Roles & Permissions\",\n description: \"Access control configuration\",\n },\n};\n\nconst RESOURCE_SUGGESTIONS = Object.keys(RESOURCE_META);\n\ntype PermissionLevel = \"read\" | \"write\";\ntype ScopeEntry = { resource: string; level: PermissionLevel };\n\nfunction parseScopesFromManifest(\n manifest: Record<string, unknown> | null | undefined,\n): ScopeEntry[] {\n if (!manifest || !Array.isArray(manifest.permissions)) return [];\n const result: ScopeEntry[] = [];\n for (const entry of manifest.permissions as Array<{\n resource: string;\n level: string;\n }>) {\n if (\n entry &&\n typeof entry === \"object\" &&\n typeof entry.resource === \"string\" &&\n entry.resource\n ) {\n result.push({\n resource: entry.resource,\n level: entry.level === \"write\" ? \"write\" : \"read\",\n });\n }\n }\n return result;\n}\n\nfunction parseScopesFromRequired(scopes: string[]): ScopeEntry[] {\n const result: ScopeEntry[] = [];\n for (const scope of scopes) {\n const colonIdx = scope.indexOf(\":\");\n if (colonIdx === -1) continue;\n const action = scope.slice(0, colonIdx);\n const resource = scope.slice(colonIdx + 1);\n if (resource) {\n result.push({ resource, level: action === \"write\" ? \"write\" : \"read\" });\n }\n }\n return result;\n}\n\nfunction mergeScopeEntries(\n fromManifest: ScopeEntry[],\n fromScopes: ScopeEntry[],\n): ScopeEntry[] {\n if (fromManifest.length > 0) return fromManifest;\n // Deduplicate by resource (keep first occurrence)\n const seen = new Set<string>();\n return fromScopes.filter((s) => {\n if (seen.has(s.resource)) return false;\n seen.add(s.resource);\n return true;\n });\n}\n\nconst LevelToggle: FC<{\n level: PermissionLevel;\n onChange: (l: PermissionLevel) => void;\n}> = ({ level, onChange }) => (\n <div className=\"flex items-center gap-0.5 rounded-md border border-border-subtle bg-bg-sunken/50 p-0.5\">\n {([\"read\", \"write\"] as PermissionLevel[]).map((l) => (\n <button\n key={l}\n type=\"button\"\n onClick={() => onChange(l)}\n className={`rounded px-2.5 py-1 text-xs font-medium transition-colors whitespace-nowrap ${\n level === l\n ? \"bg-bg-base text-text-primary shadow-sm\"\n : \"text-text-secondary hover:text-text-primary\"\n }`}\n >\n {l === \"read\" ? \"Read\" : \"Read & Write\"}\n </button>\n ))}\n </div>\n);\n\nconst PermissionsTab: FC<{\n app: Application;\n versionScopes?: string[];\n locked?: boolean;\n onNavigateToVersions?: () => void;\n}> = ({ app, versionScopes, locked = false, onNavigateToVersions }) => {\n const manifest = (app.manifest ?? {}) as Record<string, unknown>;\n const [scopes, setScopes] = useState<ScopeEntry[]>(() =>\n mergeScopeEntries(\n parseScopesFromManifest(manifest),\n parseScopesFromRequired(versionScopes ?? []),\n ),\n );\n const [adding, setAdding] = useState(false);\n const [newResource, setNewResource] = useState(\"\");\n const [newLevel, setNewLevel] = useState<PermissionLevel>(\"read\");\n const [saving, setSaving] = useState(false);\n const [saved, setSaved] = useState(false);\n const [updateApplication] = useUpdateApplicationMutation();\n\n const handleLevelChange = (resource: string, level: PermissionLevel) => {\n setSaved(false);\n setScopes((prev) =>\n prev.map((s) => (s.resource === resource ? { ...s, level } : s)),\n );\n };\n\n const handleRemove = (resource: string) => {\n setSaved(false);\n setScopes((prev) => prev.filter((s) => s.resource !== resource));\n };\n\n const handleAdd = () => {\n const res = newResource.trim().toLowerCase().replace(/\\s+/g, \"-\");\n if (!res || scopes.some((s) => s.resource === res)) return;\n setScopes((prev) => [...prev, { resource: res, level: newLevel }]);\n setNewResource(\"\");\n setNewLevel(\"read\");\n setAdding(false);\n setSaved(false);\n };\n\n const handleSave = async () => {\n setSaving(true);\n try {\n await updateApplication({\n variables: {\n id: app.id,\n input: {\n manifest: {\n ...manifest,\n permissions: scopes.map(({ resource, level }) => ({\n resource,\n level,\n })),\n },\n },\n },\n });\n setSaved(true);\n } finally {\n setSaving(false);\n }\n };\n\n const scopeList = (\n <div className=\"rounded-lg border border-border-subtle divide-y divide-border-subtle\">\n {scopes.map((scope) => (\n <div\n key={scope.resource}\n className=\"flex items-center gap-3 px-4 py-3 hover:bg-bg-sunken/30 transition-colors\"\n >\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm font-medium text-text-primary\">\n {RESOURCE_META[scope.resource]?.label ?? scope.resource}\n </p>\n {RESOURCE_META[scope.resource]?.description && (\n <p className=\"text-xs text-text-secondary\">\n {RESOURCE_META[scope.resource].description}\n </p>\n )}\n {!RESOURCE_META[scope.resource] && (\n <p className=\"text-xs text-text-tertiary font-mono\">\n custom scope\n </p>\n )}\n </div>\n {locked ? (\n <span\n className={`rounded-full px-2.5 py-0.5 text-xs font-medium ${\n scope.level === \"write\"\n ? \"bg-status-warning-bg text-status-warning-text\"\n : \"bg-bg-sunken text-text-secondary\"\n }`}\n >\n {scope.level === \"write\" ? \"Read & Write\" : \"Read\"}\n </span>\n ) : (\n <>\n <LevelToggle\n level={scope.level}\n onChange={(l) => handleLevelChange(scope.resource, l)}\n />\n <button\n type=\"button\"\n onClick={() => handleRemove(scope.resource)}\n title=\"Remove permission\"\n className=\"p-1.5 rounded text-text-tertiary hover:text-status-error-text hover:bg-status-error-bg-subtle transition-colors\"\n >\n <X size={14} />\n </button>\n </>\n )}\n </div>\n ))}\n </div>\n );\n\n return (\n <PageSection\n title=\"Permissions\"\n description=\"These are the permissions your app requests from users. Users see exactly this list when authorizing your app.\"\n >\n <div className=\"space-y-4\">\n {locked ? (\n <>\n <div className=\"rounded-lg border border-status-warning-bg bg-status-warning-bg-subtle p-3 flex gap-2 text-sm\">\n <Info\n size={15}\n className=\"flex-shrink-0 mt-0.5 text-status-warning-text\"\n />\n <span className=\"text-status-warning-text\">\n <strong>Permission changes require a new version.</strong> Your\n app is live and users have already consented to the permissions\n below. To request new or fewer permissions, publish a new\n version — existing users will be shown what changed and asked to\n re-consent before the new version takes effect.{\" \"}\n {onNavigateToVersions && (\n <button\n type=\"button\"\n onClick={onNavigateToVersions}\n className=\"underline font-medium hover:opacity-80 transition-opacity\"\n >\n Go to Versions →\n </button>\n )}\n </span>\n </div>\n {scopes.length === 0 ? (\n <div className=\"rounded-lg border border-border-subtle border-dashed p-6 text-center text-sm text-text-secondary\">\n No permissions configured for this version.\n </div>\n ) : (\n scopeList\n )}\n </>\n ) : (\n <>\n {scopes.length === 0 ? (\n <div className=\"rounded-lg border border-border-subtle border-dashed p-8 flex flex-col items-center gap-2 text-center text-text-secondary\">\n <Shield size={28} className=\"opacity-25\" />\n <p className=\"text-sm font-medium text-text-primary\">\n No permissions configured\n </p>\n <p className=\"text-xs\">\n Add the permissions your app needs to request from users.\n </p>\n </div>\n ) : (\n scopeList\n )}\n\n {adding ? (\n <div className=\"rounded-lg border border-border-subtle p-3 flex items-center gap-2 flex-wrap\">\n <input\n type=\"text\"\n value={newResource}\n onChange={(e) => setNewResource(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") handleAdd();\n if (e.key === \"Escape\") setAdding(false);\n }}\n placeholder=\"Resource (e.g. auth, files, widgets)\"\n list=\"perm-resource-suggestions\"\n autoFocus\n className=\"flex-1 min-w-40 rounded-md border border-border-subtle bg-bg-base px-3 py-1.5 text-sm focus:outline-none focus:ring-1 focus:ring-primary\"\n />\n <datalist id=\"perm-resource-suggestions\">\n {RESOURCE_SUGGESTIONS.filter(\n (r) => !scopes.some((s) => s.resource === r),\n ).map((r) => (\n <option key={r} value={r}>\n {RESOURCE_META[r].label}\n </option>\n ))}\n </datalist>\n <LevelToggle level={newLevel} onChange={setNewLevel} />\n <button\n type=\"button\"\n onClick={handleAdd}\n disabled={!newResource.trim()}\n className=\"px-3 py-1.5 rounded-md bg-action-primary-bg text-action-primary-text text-xs font-medium hover:bg-action-primary-bg/90 disabled:opacity-50 transition-colors\"\n >\n Add\n </button>\n <button\n type=\"button\"\n onClick={() => {\n setAdding(false);\n setNewResource(\"\");\n }}\n className=\"p-1.5 rounded text-text-secondary hover:text-text-primary transition-colors\"\n >\n <X size={14} />\n </button>\n </div>\n ) : (\n <button\n type=\"button\"\n onClick={() => setAdding(true)}\n className=\"flex items-center gap-1.5 text-sm text-text-secondary hover:text-text-primary transition-colors\"\n >\n <Plus size={14} />\n Add permission\n </button>\n )}\n\n <div className=\"rounded-lg border border-border-subtle bg-bg-sunken/30 p-3 flex gap-2 text-xs text-text-secondary\">\n <Info size={14} className=\"flex-shrink-0 mt-0.5\" />\n <span>\n <strong>Read & Write</strong> implies Read. Request only\n what your app genuinely needs — fewer permissions build more\n user trust.\n </span>\n </div>\n\n <div className=\"flex items-center justify-end gap-3\">\n {saved && (\n <span className=\"flex items-center gap-1.5 text-sm text-status-success-text\">\n <CheckCircle size={14} />\n Saved\n </span>\n )}\n <button\n type=\"button\"\n onClick={() => void handleSave()}\n disabled={saving}\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 transition-colors disabled:opacity-50\"\n >\n {saving ? (\n <Loader2 size={14} className=\"animate-spin\" />\n ) : (\n <Shield size={14} />\n )}\n Save Permissions\n </button>\n </div>\n </>\n )}\n </div>\n </PageSection>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ApplicationDetailPage.js","names":[],"sources":["../../../src/devportal/pages/ApplicationDetailPage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useState, useMemo, useCallback, useEffect, useRef } from \"react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport { useParams, useNavigate } from \"react-router-dom\";\nimport {\n AppWindow,\n Key,\n Webhook,\n BarChart3,\n Plus,\n ExternalLink,\n MoreHorizontal,\n Loader2,\n AlertCircle,\n CheckCircle,\n Clock,\n Shield,\n RefreshCw,\n Edit,\n XCircle,\n Power,\n Users,\n Store,\n FlaskConical,\n Upload,\n Info,\n X,\n SendHorizontal,\n Package,\n ChevronRight,\n Check,\n CircleDollarSign,\n TrendingUp,\n Wallet,\n Gift,\n Lock,\n Link,\n Copy,\n} from \"lucide-react\";\nimport {\n CTAOverflowMenu,\n EmphasisPanel,\n GlassCard,\n type CTAAction,\n} from \"@burdenoff/fe-libs/ui\";\nimport { PageLayout, PageSection } from \"../components/PageLayout\";\nimport {\n InputField,\n TextareaField,\n SelectField,\n} from \"../components/FormField\";\nimport {\n StatusBadge,\n VerifiedBadge,\n FeaturedBadge,\n} from \"../components/StatusBadge\";\nimport { DataTable, DetailList } from \"../components/DataTable\";\nimport { NewSecretAlert } from \"../components/SecretDisplay\";\nimport { EmptyState } from \"../components/EmptyState\";\nimport { LoadingState } from \"../components/LoadingState\";\nimport { ConfirmDialog } from \"../components/ConfirmDialog\";\nimport { SelectionCheckbox } from \"../components/SelectionCheckbox\";\nimport { GrantDelegationModal } from \"../components/GrantDelegationModal\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport { usePackageUpload } from \"../hooks/usePackageUpload\";\nimport { nativeNotify } from \"../../utils/nativeBridge\";\nimport { DEVPORTAL_PERMISSIONS } from \"../constants/permissions\";\nimport { useDevportalPermission } from \"../hooks/usePermission\";\nimport type {\n Application,\n Webhook as WebhookType,\n ApplicationAnalytics,\n AppUserDelegation,\n DelegationStatus,\n} from \"../types\";\nimport { cn } from \"../utils/cn\";\nimport { APP_TYPE_LABELS } from \"../utils/constants\";\nimport {\n useGetApplicationQuery,\n useGetWebhooksQuery,\n useGetApplicationAnalyticsQuery,\n useGetApplicationVersionsQuery,\n type GetApplicationVersionsQuery,\n useCurrentUserDelegationsQuery,\n useDeactivateAppMutation,\n useRotateAppSecretMutation,\n useRevokeDelegationMutation,\n useUpdateApplicationMutation,\n useInstallApplicationMutation,\n useUninstallApplicationMutation,\n useGetWorkspaceInstallationQuery,\n useSubmitApplicationMutation,\n usePublishApplicationVersionMutation,\n useGetOrganizationQuery,\n type ApplicationScopeFieldsFragment,\n useShareWorkflowMutation,\n useUnshareWorkflowMutation,\n} from \"../../generated/global-operations\";\n\n// =============================================================================\n// HELPERS\n// =============================================================================\n\n/** Safely map GraphQL response to Application type */\nfunction mapToApplication(\n data: NonNullable<\n ReturnType<typeof useGetApplicationQuery>[\"data\"]\n >[\"application\"],\n): Application | null {\n if (!data) return null;\n return {\n id: data.id,\n name: data.name,\n slug: data.slug,\n shortDescription: data.shortDescription || undefined,\n description: data.description || undefined,\n appType: data.appType,\n status: data.status,\n visibility: data.visibility,\n tenantId: data.tenantId,\n developerId: data.developerId,\n developerOrganizationId: data.developerOrganizationId || undefined,\n category: data.category || undefined,\n tags: data.tags || [],\n keywords: data.keywords || [],\n iconUrl: data.iconUrl || undefined,\n bannerUrl: data.bannerUrl || undefined,\n screenshots: Array.isArray(data.screenshots) ? data.screenshots : undefined,\n videoUrl: data.videoUrl || undefined,\n websiteUrl: data.websiteUrl || undefined,\n documentationUrl: data.documentationUrl || undefined,\n supportUrl: data.supportUrl || undefined,\n privacyPolicyUrl: data.privacyPolicyUrl || undefined,\n termsOfServiceUrl: data.termsOfServiceUrl || undefined,\n githubUrl: data.githubUrl || undefined,\n pricingType: data.pricingType || undefined,\n pricingDetails: data.pricingDetails ?? undefined,\n manifest: data.manifest ?? undefined,\n installCount: data.installCount,\n activeInstallCount: data.activeInstallCount,\n averageRating: data.averageRating ?? undefined,\n reviewCount: data.reviewCount,\n submittedAt: data.submittedAt || undefined,\n publishedAt: data.publishedAt || undefined,\n lastReviewedAt: data.lastReviewedAt || undefined,\n reviewStatus: data.reviewStatus,\n isFeatured: data.isFeatured,\n isVerified: data.isVerified,\n requiresApproval: data.requiresApproval,\n appId: data.appId || undefined,\n scopes: data.scopes?.map((s: ApplicationScopeFieldsFragment) => ({\n id: s.id,\n applicationId: s.applicationId,\n scope: s.scope,\n description: s.description || undefined,\n isRequired: s.isRequired,\n createdAt: s.createdAt,\n })),\n createdAt: data.createdAt,\n updatedAt: data.updatedAt,\n };\n}\n\n/**\n * Note: OAuth client and API key mappers removed.\n * OAuth apps and API keys are now managed centrally via auth-svc\n * (see /oauth and /api-keys routes).\n */\n\n/** Map GraphQL webhook response to local Webhook type */\nfunction mapToWebhook(\n gqlWebhook: NonNullable<\n ReturnType<typeof useGetWebhooksQuery>[\"data\"]\n >[\"webhooks\"][number],\n): WebhookType {\n return {\n id: gqlWebhook.id,\n applicationId: gqlWebhook.applicationId,\n name: gqlWebhook.name,\n description: gqlWebhook.description || undefined,\n url: gqlWebhook.url,\n secret: gqlWebhook.secret,\n events: gqlWebhook.events,\n isActive: gqlWebhook.isActive,\n status: gqlWebhook.status,\n maxRetries: gqlWebhook.maxRetries,\n retryDelay: gqlWebhook.retryDelay,\n retryEnabled: gqlWebhook.retryEnabled,\n lastTriggeredAt: gqlWebhook.lastTriggeredAt || undefined,\n lastSuccessAt: gqlWebhook.lastSuccessAt || undefined,\n lastFailureAt: gqlWebhook.lastFailureAt || undefined,\n lastFailureReason: gqlWebhook.lastFailureReason || undefined,\n failureCount: gqlWebhook.failureCount,\n successCount: gqlWebhook.successCount,\n createdAt: gqlWebhook.createdAt,\n updatedAt: gqlWebhook.updatedAt,\n };\n}\n\n/** Map GraphQL analytics response to local ApplicationAnalytics type */\nfunction mapToAnalytics(\n gqlAnalytics: NonNullable<\n ReturnType<typeof useGetApplicationAnalyticsQuery>[\"data\"]\n >[\"applicationAnalytics\"][number],\n): ApplicationAnalytics {\n return {\n id: gqlAnalytics.id,\n applicationId: gqlAnalytics.applicationId,\n date: gqlAnalytics.date,\n period: gqlAnalytics.period,\n apiCalls: gqlAnalytics.apiCalls,\n errors: gqlAnalytics.errors,\n sessions: gqlAnalytics.sessions,\n activeUsers: gqlAnalytics.activeUsers,\n newUsers: gqlAnalytics.newUsers,\n avgResponseTime: gqlAnalytics.avgResponseTime ?? undefined,\n avgSessionDuration: gqlAnalytics.avgSessionDuration ?? undefined,\n createdAt: gqlAnalytics.createdAt,\n };\n}\n\n/** Map GraphQL delegation response to local AppUserDelegation type */\nfunction mapToDelegation(\n gqlDelegation: NonNullable<\n ReturnType<typeof useCurrentUserDelegationsQuery>[\"data\"]\n >[\"currentUserDelegations\"][number],\n): AppUserDelegation {\n return {\n id: gqlDelegation.id,\n appId: gqlDelegation.appId,\n app: {\n id: gqlDelegation.app.id,\n name: gqlDelegation.app.name,\n description: gqlDelegation.app.description || undefined,\n type: gqlDelegation.app.type,\n status: gqlDelegation.app.status,\n },\n userId: gqlDelegation.userId,\n scopes: gqlDelegation.scopes,\n workspaceIds: gqlDelegation.workspaceIds ?? [],\n status: gqlDelegation.status as DelegationStatus,\n grantedAt: gqlDelegation.grantedAt,\n grantedBy: gqlDelegation.grantedBy,\n expiresAt: gqlDelegation.expiresAt || undefined,\n revokedAt: gqlDelegation.revokedAt || undefined,\n revokedBy: gqlDelegation.revokedBy || undefined,\n };\n}\n\n// =============================================================================\n// TAB DEFINITIONS\n// =============================================================================\n\ntype TabId =\n | \"overview\"\n | \"permissions\"\n | \"webhooks\"\n | \"delegations\"\n | \"analytics\"\n | \"playground\"\n | \"store-listing\"\n | \"versions\"\n | \"pricing\"\n | \"oauth\"\n | \"api-keys\";\n\nconst tabs: Array<{ id: TabId; label: string; icon: FC<{ size?: number }> }> = [\n { id: \"overview\", label: \"Overview\", icon: AppWindow },\n { id: \"analytics\", label: \"Analytics\", icon: BarChart3 },\n { id: \"store-listing\", label: \"Store Listing\", icon: Store },\n { id: \"versions\", label: \"Versions\", icon: Package },\n { id: \"pricing\", label: \"Pricing\", icon: CircleDollarSign },\n { id: \"permissions\", label: \"Permissions\", icon: Shield },\n { id: \"webhooks\", label: \"Webhooks\", icon: Webhook },\n { id: \"delegations\", label: \"Delegations\", icon: Users },\n { id: \"playground\", label: \"API Playground\", icon: ExternalLink },\n { id: \"oauth\", label: \"OAuth\", icon: Lock },\n { id: \"api-keys\", label: \"API Keys\", icon: Key },\n];\n\n// =============================================================================\n// DELEGATION STATUS HELPERS\n// =============================================================================\n\nconst DELEGATION_STATUS_STYLES: Record<DelegationStatus, string> = {\n ACTIVE: \"bg-status-success-bg-subtle text-status-success-text\",\n REVOKED: \"bg-status-error-bg-subtle text-status-error-text\",\n EXPIRED: \"bg-bg-sunken text-text-secondary\",\n};\n\n// =============================================================================\n// TAB LOADING SPINNER\n// =============================================================================\n\nconst TabLoadingSpinner: FC<{ message?: string }> = ({\n message = \"Loading...\",\n}) => (\n <div className=\"flex items-center justify-center gap-3 py-12\">\n <Loader2 size={20} className=\"animate-spin text-text-secondary\" />\n <p className=\"text-sm text-text-secondary\">{message}</p>\n </div>\n);\n\nconst TabErrorState: FC<{ message: string }> = ({ message }) => (\n <div className=\"flex flex-col items-center justify-center gap-2 py-12 text-center\">\n <AlertCircle size={32} className=\"text-status-error-text\" />\n <p className=\"text-sm text-text-secondary\">{message}</p>\n </div>\n);\n\n// =============================================================================\n// MAIN PAGE COMPONENT\n// =============================================================================\n\n/**\n * Application detail page with tabbed navigation\n */\nexport const ApplicationDetailPage: FC = () => {\n const { navigate, basePath, workspaceId } = useDevportal();\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 const { allowed: canUpdate } = useDevportalPermission(\n DEVPORTAL_PERMISSIONS.APP_UPDATE,\n );\n const { allowed: canDelete } = useDevportalPermission(\n DEVPORTAL_PERMISSIONS.APP_DELETE,\n );\n const { appId } = useParams<{ appId: string }>();\n const [activeTab, setActiveTab] = useState<TabId>(\"overview\");\n\n // ---- Dialogs ----\n const [showRotateSecretDialog, setShowRotateSecretDialog] = useState(false);\n const [showDeactivateDialog, setShowDeactivateDialog] = useState(false);\n const [newSecret, setNewSecret] = useState<string | null>(null);\n const [showDelegationModal, setShowDelegationModal] = useState(false);\n\n // ---- Application query ----\n const { data, loading, error, refetch } = useGetApplicationQuery({\n variables: { id: appId! },\n skip: !appId,\n });\n\n // ---- Mutations ----\n const [rotateAppSecret, { loading: rotateLoading }] =\n useRotateAppSecretMutation();\n const [deactivateApp, { loading: deactivateLoading }] =\n useDeactivateAppMutation();\n const [submitApplication, { loading: isSubmitting }] =\n useSubmitApplicationMutation();\n const [publishApplicationVersion] = usePublishApplicationVersionMutation();\n const [installApplication, { loading: installLoading }] =\n useInstallApplicationMutation();\n const [uninstallApplication, { loading: uninstallLoading }] =\n useUninstallApplicationMutation();\n const [shareWorkflow, { loading: shareLoading }] = useShareWorkflowMutation();\n const [unshareWorkflow, { loading: unshareLoading }] =\n useUnshareWorkflowMutation();\n const [linkCopied, setLinkCopied] = useState(false);\n\n // ---- Workspace installation status ----\n const { data: installationData, refetch: refetchInstallation } =\n useGetWorkspaceInstallationQuery({\n variables: {\n applicationId: appId,\n workspaceId: workspaceId ?? undefined,\n },\n skip: !workspaceId || !appId,\n fetchPolicy: \"cache-and-network\",\n });\n const activeInstallation =\n installationData?.appInstallations?.edges?.[0]?.node ?? null;\n\n // ---- Developer org (for platformFeeRate + billingAccountId) ----\n const { data: orgData } = useGetOrganizationQuery({\n variables: { id: data?.application?.developerOrganizationId ?? \"\" },\n skip: !data?.application?.developerOrganizationId,\n fetchPolicy: \"cache-first\",\n });\n\n const handleNavigate = useCallback(\n (path: string) => {\n navigate?.(`${basePath}${path}`);\n },\n [navigate, basePath],\n );\n\n // ---- Rotate Secret ----\n const handleRotateSecret = useCallback(async () => {\n const authAppId = data?.application?.appId;\n if (!authAppId) return;\n try {\n const result = await rotateAppSecret({ variables: { id: authAppId } });\n const secret = result.data?.rotateAppSecret.clientSecret;\n if (secret) {\n setNewSecret(secret);\n }\n setShowRotateSecretDialog(false);\n } catch {\n // Error is displayed via Apollo error state\n }\n }, [data?.application?.appId, rotateAppSecret]);\n\n // ---- Deactivate App ----\n const handleDeactivateApp = useCallback(async () => {\n if (!appId) return;\n try {\n await deactivateApp({ variables: { id: appId } });\n setShowDeactivateDialog(false);\n handleNavigate(\"/apps\");\n } catch {\n // Error is displayed via Apollo error state\n }\n }, [appId, deactivateApp, handleNavigate]);\n\n // ---- Test in Workspace ----\n const handleTestInWorkspace = useCallback(async () => {\n if (!appId || !workspaceId) return;\n try {\n await installApplication({\n variables: {\n input: {\n applicationId: appId,\n scope: \"WORKSPACE\" as const,\n workspaceId,\n autoUpdate: false,\n },\n },\n });\n void refetchInstallation();\n void nativeNotify(\"success\");\n } catch (err) {\n console.error(\"[DevPortal] Test in Workspace failed:\", err);\n void nativeNotify(\"error\");\n }\n }, [appId, workspaceId, installApplication, refetchInstallation]);\n\n // ---- Uninstall from Workspace ----\n const handleUninstall = useCallback(\n async (installationId: string) => {\n try {\n await uninstallApplication({ variables: { id: installationId } });\n void refetchInstallation();\n void nativeNotify(\"success\");\n } catch {\n void nativeNotify(\"error\");\n }\n },\n [uninstallApplication, refetchInstallation],\n );\n\n // ---- Submit for Review ----\n // Must stay before early returns (Rules of Hooks).\n const handleSubmitForReview = useCallback(async () => {\n if (!appId) return;\n try {\n // Auto-publish all draft versions so they go into review together with the app.\n const draftVersions = (data?.application?.versions?.edges ?? [])\n .map((e: { node: { id: string; status: string } }) => e.node)\n .filter((v: { id: string; status: string }) => v.status === \"draft\");\n for (const v of draftVersions) {\n await publishApplicationVersion({ variables: { id: v.id } });\n }\n await submitApplication({ variables: { id: appId } });\n void nativeNotify(\"success\");\n } catch (err) {\n console.error(\"[DevPortal] Submit failed:\", err);\n void nativeNotify(\"error\");\n } finally {\n void refetch();\n }\n }, [\n appId,\n data?.application?.versions?.edges,\n publishApplicationVersion,\n submitApplication,\n refetch,\n ]);\n\n // ---- Loading / Error / Not Found ----\n // Only show full-page loading on initial load (no cached data yet).\n // With cache-and-network, Apollo sets loading:true on background refetches even\n // when data is already in cache — guarding on !data prevents StoreListingTab\n // (and other tab panels) from unmounting and losing their local form state.\n if (loading && !data) {\n return (\n <LoadingState\n message={tr(\"devportal.loadingApplication\", \"Loading application...\")}\n />\n );\n }\n\n if (error) {\n return (\n <PageLayout\n title={tr(\"devportal.error\", \"Error\")}\n backLink={`${basePath}/apps`}\n backLabel={tr(\"devportal.backToApplications\", \"Back to Applications\")}\n >\n <div className=\"flex flex-col items-center justify-center py-12 text-center\">\n <AlertCircle size={48} className=\"text-status-error-text mb-4\" />\n <h3 className=\"text-lg font-semibold mb-2\">\n {tr(\n \"devportal.failedToLoadApplication\",\n \"Failed to load application\",\n )}\n </h3>\n <p className=\"text-sm text-text-secondary\">{error.message}</p>\n </div>\n </PageLayout>\n );\n }\n\n const app = mapToApplication(data?.application);\n\n if (!app) {\n return (\n <PageLayout\n title={tr(\"devportal.notFound\", \"Not Found\")}\n backLink={`${basePath}/apps`}\n backLabel={tr(\"devportal.backToApplications\", \"Back to Applications\")}\n >\n <EmptyState\n illustration=\"empty-generic\"\n icon={<AppWindow size={48} />}\n title={tr(\"devportal.applicationNotFound\", \"Application not found\")}\n description={tr(\n \"devportal.applicationNotFoundDescription\",\n \"The application you're looking for doesn't exist or you don't have access to it.\",\n )}\n />\n </PageLayout>\n );\n }\n\n const isPackageApp = app.appType === \"NODE\" || app.appType === \"WORKFLOW\";\n const isIntegrationApp = app.appType === \"API_INTEGRATION\";\n const versionCount = data?.application?.versions?.totalCount ?? 0;\n const isPaidApp = app.pricingType === \"PAID\";\n const devOrg = orgData?.developerOrganization;\n const platformFeeRate = devOrg?.platformFeeRate ?? 0.3;\n const billingAccountLinked = !!devOrg?.billingAccountId;\n\n // Pricing is \"done\" when the developer has explicitly chosen FREE or set a PAID price in credits\n const pricingDetailsRaw = (app.pricingDetails ?? {}) as Record<\n string,\n unknown\n >;\n const pricingDone =\n app.pricingType === \"FREE\" ||\n (app.pricingType === \"PAID\" &&\n typeof pricingDetailsRaw.price === \"number\" &&\n (pricingDetailsRaw.price as number) > 0);\n\n // Readiness: store listing + icon + version (pkg/integration) + billing acct (paid) + pricing chosen\n const isReadyToSubmit =\n !!app.description?.trim() &&\n !!app.category &&\n !!app.iconUrl &&\n (app.visibility === \"PUBLIC\" || app.visibility === \"UNLISTED\") &&\n ((!isPackageApp && !isIntegrationApp) || versionCount > 0) &&\n (!isPaidApp || billingAccountLinked) &&\n pricingDone;\n\n const canSubmit =\n isReadyToSubmit && app.status !== \"PUBLISHED\" && app.status !== \"SUBMITTED\";\n\n const headerActions: CTAAction[] = [\n ...(!isPackageApp\n ? [\n {\n label: tr(\"devportal.rotateSecret\", \"Rotate Secret\"),\n icon: <RefreshCw size={16} />,\n disabled: !app.appId,\n onSelect: () => setShowRotateSecretDialog(true),\n },\n ]\n : []),\n ...(!isPackageApp\n ? activeInstallation\n ? [\n {\n label: tr(\n \"devportal.uninstallFromWorkspace\",\n \"Uninstall from Workspace\",\n ),\n icon: <XCircle size={16} />,\n disabled: uninstallLoading || !workspaceId,\n onSelect: () => void handleUninstall(activeInstallation.id),\n },\n ]\n : [\n {\n label: tr(\"devportal.testInWorkspace\", \"Test in Workspace\"),\n icon: <FlaskConical size={16} />,\n disabled: installLoading || !workspaceId,\n onSelect: () => void handleTestInWorkspace(),\n },\n ]\n : []),\n {\n label: tr(\"devportal.deactivate\", \"Deactivate\"),\n icon: <Power size={16} />,\n intent: \"destructive\" as const,\n disabled: !canDelete,\n onSelect: () => setShowDeactivateDialog(true),\n },\n ];\n\n return (\n <PageLayout\n title={app.name}\n description={app.shortDescription}\n purpose={tr(\n \"devportal.appDetailPurpose\",\n \"Everything about this application in one place — its credentials, the permissions and webhooks it uses, its analytics, and its store listing. Use the tabs to configure each area, then edit or publish when it is ready.\",\n )}\n backLink={`${basePath}/apps`}\n backLabel={tr(\"devportal.backToApplications\", \"Back to Applications\")}\n actions={\n <div className=\"flex items-center gap-2\">\n {app.status === \"SUBMITTED\" ? (\n <div className=\"flex items-center gap-1.5 rounded-full border border-status-warning-bg bg-status-warning-bg-subtle px-3 py-1.5 text-xs font-medium text-status-warning-text\">\n <Clock size={13} />\n {tr(\"devportal.underReview\", \"Under Review\")}\n </div>\n ) : app.status !== \"PUBLISHED\" ? (\n <button\n type=\"button\"\n onClick={() => void handleSubmitForReview()}\n disabled={!canSubmit || isSubmitting}\n title={\n !isReadyToSubmit\n ? [\n !app.description?.trim() && \"Add full description\",\n !app.category && \"Select a category\",\n !app.iconUrl && \"Upload an app icon\",\n app.visibility === \"PRIVATE\" &&\n \"Set visibility to Public/Unlisted\",\n isPackageApp &&\n versionCount === 0 &&\n \"Upload at least one version\",\n !pricingDone &&\n \"Set pricing (choose Free or Paid in the Pricing tab)\",\n isPaidApp &&\n !billingAccountLinked &&\n \"Link a billing account to receive payments\",\n ]\n .filter(Boolean)\n .join(\" · \")\n : undefined\n }\n className={cn(\n \"inline-flex items-center gap-2 rounded-md px-5 py-2 text-sm font-medium whitespace-nowrap transition-colors\",\n canSubmit && !isSubmitting\n ? \"bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg/90 cursor-pointer\"\n : \"cursor-not-allowed bg-bg-muted text-text-tertiary ring-1 ring-border-subtle\",\n )}\n >\n {isSubmitting ? (\n <>\n <Loader2 size={15} className=\"animate-spin\" />\n {tr(\"devportal.submitting\", \"Submitting…\")}\n </>\n ) : (\n <>\n <SendHorizontal size={15} />\n {tr(\"devportal.submitForReview\", \"Submit for Review\")}\n </>\n )}\n </button>\n ) : null}\n <CTAOverflowMenu\n primary={{\n label: tr(\"devportal.editApp\", \"Edit App\"),\n icon: <Edit size={16} />,\n disabled: !canUpdate,\n onSelect: () => handleNavigate(`/apps/${app.id}/edit`),\n }}\n actions={headerActions}\n />\n </div>\n }\n >\n {/* New Secret Alert (shown after rotation) */}\n {newSecret && (\n <NewSecretAlert\n title={tr(\n \"devportal.newAppSecretGenerated\",\n \"New App Secret Generated\",\n )}\n secret={newSecret}\n description={tr(\n \"devportal.appSecretRotatedDescription\",\n \"Your app secret has been rotated. The old secret is no longer valid.\",\n )}\n onDismiss={() => setNewSecret(null)}\n />\n )}\n\n {/* Status badges */}\n <div className=\"flex flex-wrap items-center gap-2\">\n <StatusBadge status={app.status} type=\"app\" />\n <StatusBadge status={app.visibility} type=\"app\" />\n {app.isVerified && <VerifiedBadge verified />}\n {app.isFeatured && <FeaturedBadge />}\n <span className=\"text-sm text-text-secondary\">\n {APP_TYPE_LABELS[app.appType] || app.appType}\n </span>\n </div>\n\n {/* Share as public link — AUTOMATION apps only */}\n {app.appType === \"AUTOMATION\" && (\n <div className=\"rounded-lg border border-border-subtle bg-bg-elevated p-4\">\n <div className=\"flex items-start justify-between gap-4\">\n <div className=\"flex items-start gap-3\">\n <div className=\"mt-0.5 flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full bg-action-primary-bg-subtle\">\n <Link size={15} className=\"text-action-primary-text\" />\n </div>\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {tr(\"devportal.shareWorkflow.title\", \"Share as Public Link\")}\n </p>\n <p className=\"mt-0.5 text-xs text-text-secondary\">\n {app.visibility === \"UNLISTED\"\n ? tr(\n \"devportal.shareWorkflow.activeDesc\",\n \"Anyone with the link can preview and copy this workflow into their FluidGrids workspace.\",\n )\n : tr(\n \"devportal.shareWorkflow.inactiveDesc\",\n \"Generate a public link anyone can use to copy this workflow into their own FluidGrids workspace — no store review needed.\",\n )}\n </p>\n {app.visibility === \"UNLISTED\" && appId && (\n <div className=\"mt-2 flex items-center gap-2\">\n <code className=\"rounded bg-bg-canvas px-2 py-1 text-xs text-text-secondary\">\n {`${window.location.protocol}//${window.location.host.replace(/^app\\./, \"app.fluidgrids.com\").replace(/localhost:\\d+/, \"app.fluidgrids.com\")}/shared/${appId}`}\n </code>\n <button\n type=\"button\"\n className=\"flex items-center gap-1 rounded px-2 py-1 text-xs text-action-primary-text hover:bg-action-primary-bg-subtle transition-colors\"\n onClick={() => {\n const url = `${window.location.protocol}//${window.location.host}/shared/${appId}`;\n void navigator.clipboard.writeText(url).then(() => {\n setLinkCopied(true);\n setTimeout(() => setLinkCopied(false), 2000);\n });\n }}\n >\n {linkCopied ? <Check size={12} /> : <Copy size={12} />}\n {linkCopied\n ? tr(\"devportal.copied\", \"Copied!\")\n : tr(\"devportal.copyLink\", \"Copy Link\")}\n </button>\n </div>\n )}\n </div>\n </div>\n <button\n type=\"button\"\n disabled={shareLoading || unshareLoading || !app.manifest}\n title={\n !app.manifest\n ? tr(\n \"devportal.shareWorkflow.noManifestHint\",\n \"Add a workflow manifest before sharing\",\n )\n : undefined\n }\n onClick={() => {\n if (app.visibility === \"UNLISTED\") {\n void unshareWorkflow({ variables: { id: appId! } }).then(\n () => void refetch(),\n );\n } else {\n void shareWorkflow({ variables: { id: appId! } }).then(\n () => void refetch(),\n );\n }\n }}\n className={`flex-shrink-0 rounded-full px-3 py-1.5 text-xs font-medium transition-colors ${\n app.visibility === \"UNLISTED\"\n ? \"border border-status-error-bg text-status-error-text hover:bg-status-error-bg-subtle\"\n : \"bg-action-primary-bg text-text-on-action hover:opacity-90 disabled:opacity-50\"\n }`}\n >\n {shareLoading || unshareLoading ? (\n <Loader2 size={12} className=\"animate-spin\" />\n ) : app.visibility === \"UNLISTED\" ? (\n tr(\"devportal.shareWorkflow.stopSharing\", \"Stop Sharing\")\n ) : (\n tr(\"devportal.shareWorkflow.share\", \"Share Link\")\n )}\n </button>\n </div>\n </div>\n )}\n\n {/* Review status banner */}\n {app.status === \"SUBMITTED\" && (\n <div className=\"flex items-start gap-3 rounded-lg border border-border-subtle bg-status-warning-bg-subtle p-4\">\n <Clock\n size={18}\n className=\"text-status-warning-text mt-0.5 flex-shrink-0\"\n />\n <div className=\"text-sm\">\n <p className=\"font-medium text-status-warning-text\">\n {tr(\"devportal.underReview\", \"Under Review\")}\n </p>\n <p className=\"mt-0.5 text-text-secondary\">\n {tr(\n \"devportal.underReviewDesc\",\n \"Your submission is being reviewed by our team. You'll be notified of the outcome.\",\n )}\n {app.submittedAt && (\n <span className=\"ml-1\">\n Submitted {new Date(app.submittedAt).toLocaleDateString()}.\n </span>\n )}\n </p>\n </div>\n </div>\n )}\n {app.status === \"REJECTED\" && (\n <div className=\"flex items-start gap-3 rounded-lg border border-status-error-bg bg-status-error-bg-subtle p-4\">\n <XCircle\n size={18}\n className=\"text-status-error-text mt-0.5 flex-shrink-0\"\n />\n <div className=\"text-sm\">\n <p className=\"font-medium text-status-error-text\">\n {tr(\"devportal.reviewRejected\", \"Review Rejected\")}\n </p>\n <p className=\"mt-0.5 text-text-secondary\">\n {app.reviewNotes ||\n tr(\n \"devportal.reviewRejectedDesc\",\n \"Your submission was not approved. Please review the feedback, update your app, and re-submit.\",\n )}\n </p>\n <button\n type=\"button\"\n onClick={() => handleNavigate(`/apps/${app.id}/edit`)}\n className=\"mt-2 inline-flex items-center gap-1 text-xs font-medium text-primary underline\"\n >\n {tr(\"devportal.editAndResubmit\", \"Edit app and re-submit →\")}\n </button>\n </div>\n </div>\n )}\n {app.status === \"PUBLISHED\" && (\n <div className=\"flex items-start gap-3 rounded-lg border border-status-success-bg bg-status-success-bg-subtle p-4\">\n <CheckCircle\n size={18}\n className=\"text-status-success-text mt-0.5 flex-shrink-0\"\n />\n <div className=\"text-sm\">\n <p className=\"font-medium text-status-success-text\">\n {tr(\"devportal.liveInStore\", \"Live in the Store\")}\n </p>\n <p className=\"mt-0.5 text-text-secondary\">\n {tr(\n \"devportal.liveInStoreDesc\",\n \"Your app is published and visible to users in the marketplace.\",\n )}\n </p>\n </div>\n </div>\n )}\n\n {/* Setup wizard — shown when the app is in DRAFT or REJECTED and not yet ready */}\n {(app.status === \"DRAFT\" || app.status === \"REJECTED\") &&\n !isReadyToSubmit &&\n (() => {\n const storeDone =\n !!app.description?.trim() &&\n !!app.category &&\n !!app.iconUrl &&\n (app.visibility === \"PUBLIC\" || app.visibility === \"UNLISTED\");\n const versionsDone =\n (!isPackageApp && !isIntegrationApp) || versionCount > 0;\n const storeHints = [\n !app.description?.trim() && \"Add a full description\",\n !app.category && \"Select a category\",\n !app.iconUrl && \"Upload an app icon\",\n app.visibility === \"PRIVATE\" &&\n \"Set visibility to Public or Unlisted\",\n ].filter(Boolean) as string[];\n\n const wizardSteps = [\n {\n id: \"store\",\n label: tr(\n \"devportal.setupStoreListingStep\",\n \"Complete Store Listing\",\n ),\n hint: storeDone\n ? tr(\"devportal.done\", \"Done\")\n : storeHints.join(\" · \"),\n done: storeDone,\n onClick: () => setActiveTab(\"store-listing\"),\n },\n ...(isPackageApp\n ? [\n {\n id: \"version\",\n label: tr(\"devportal.setupVersionStep\", \"Upload a Version\"),\n hint: versionsDone\n ? tr(\"devportal.done\", \"Done\")\n : tr(\n \"devportal.uploadVersionHint\",\n \"Upload your ZIP bundle and manifest\",\n ),\n done: versionsDone,\n onClick: () => setActiveTab(\"versions\"),\n },\n ]\n : []),\n ...(isIntegrationApp\n ? [\n {\n id: \"version\",\n label: tr(\n \"devportal.setupIntegrationVersionStep\",\n \"Publish a Version\",\n ),\n hint: versionsDone\n ? tr(\"devportal.done\", \"Done\")\n : tr(\n \"devportal.integrationVersionHint\",\n \"Define required scopes and publish your first API version\",\n ),\n done: versionsDone,\n onClick: () => setActiveTab(\"versions\"),\n },\n {\n id: \"webhooks\",\n label: tr(\n \"devportal.setupWebhooksStep\",\n \"Configure Webhooks\",\n ),\n hint: tr(\n \"devportal.webhooksOptionalHint\",\n \"Set up endpoints to receive platform events (optional)\",\n ),\n done: false,\n onClick: () => setActiveTab(\"webhooks\"),\n },\n ]\n : []),\n {\n id: \"pricing\",\n label: tr(\"devportal.setupPricingStep\", \"Set Pricing\"),\n hint: pricingDone\n ? tr(\"devportal.done\", \"Done\")\n : tr(\n \"devportal.pricingHint\",\n \"Choose Free or set a credit price in the Pricing tab\",\n ),\n done: pricingDone,\n onClick: () => setActiveTab(\"pricing\"),\n },\n ...(isPaidApp\n ? [\n {\n id: \"billing\",\n label: tr(\n \"devportal.setupBillingStep\",\n \"Link Billing Account\",\n ),\n hint: billingAccountLinked\n ? tr(\"devportal.done\", \"Done\")\n : tr(\n \"devportal.billingAccountHint\",\n \"Link a billing account to receive payouts — required for paid apps\",\n ),\n done: billingAccountLinked,\n onClick: () => setActiveTab(\"pricing\"),\n },\n ]\n : []),\n {\n id: \"submit\",\n label: tr(\"devportal.submitForReview\", \"Submit for Review\"),\n hint: isReadyToSubmit\n ? tr(\n \"devportal.readyToSubmit\",\n \"Ready — click Submit for Review above\",\n )\n : !app.description?.trim()\n ? tr(\n \"devportal.hintMissingDescription\",\n \"Add a full description on the Store Listing tab\",\n )\n : !app.category\n ? tr(\n \"devportal.hintMissingCategory\",\n \"Select a category on the Store Listing tab\",\n )\n : !app.iconUrl\n ? tr(\n \"devportal.hintMissingIcon\",\n \"Upload an app icon on the Store Listing tab\",\n )\n : app.visibility === \"PRIVATE\"\n ? tr(\n \"devportal.hintPrivateVisibility\",\n \"Set visibility to Public or Unlisted\",\n )\n : (isPackageApp || isIntegrationApp) &&\n versionCount === 0\n ? tr(\n \"devportal.hintMissingVersion\",\n \"Upload at least one version\",\n )\n : !pricingDone\n ? tr(\n \"devportal.hintMissingPricing\",\n \"Choose Free or set a credit price in the Pricing tab\",\n )\n : isPaidApp && !billingAccountLinked\n ? tr(\n \"devportal.hintMissingBilling\",\n \"Link a billing account in the Pricing tab to receive payouts\",\n )\n : tr(\n \"devportal.completeStepsFirst\",\n \"Complete the steps above first\",\n ),\n done: false,\n onClick: undefined as (() => void) | undefined,\n },\n ];\n const completedCount = wizardSteps.filter((s) => s.done).length;\n\n return (\n <div className=\"rounded-xl border border-border-subtle bg-bg-surface shadow-sm\">\n <div className=\"flex items-center justify-between border-b border-border-subtle px-5 py-4\">\n <div className=\"flex items-center gap-3\">\n <div className=\"flex h-8 w-8 items-center justify-center rounded-full bg-action-primary-bg/10\">\n <Store size={16} className=\"text-primary\" />\n </div>\n <div>\n <p className=\"text-sm font-semibold text-text-primary\">\n {tr(\"devportal.completeSetup\", \"Complete your app setup\")}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {completedCount} of{\" \"}\n {wizardSteps.filter((s) => s.id !== \"submit\").length}{\" \"}\n {tr(\"devportal.stepsDone\", \"steps complete\")}\n </p>\n </div>\n </div>\n </div>\n <div className=\"divide-y divide-border-subtle\">\n {wizardSteps.map((step, idx) => (\n <button\n key={step.id}\n type=\"button\"\n onClick={step.onClick}\n disabled={!step.onClick}\n className={cn(\n \"w-full flex items-center gap-4 px-5 py-4 text-left transition-colors\",\n step.onClick\n ? \"hover:bg-bg-sunken/40 cursor-pointer\"\n : \"cursor-default opacity-60\",\n )}\n >\n <div\n className={cn(\n \"flex h-7 w-7 flex-shrink-0 items-center justify-center rounded-full text-xs font-bold\",\n step.done\n ? \"bg-status-success-bg text-status-success-text\"\n : \"border-2 border-border-subtle bg-bg-sunken text-text-secondary\",\n )}\n >\n {step.done ? <Check size={13} /> : idx + 1}\n </div>\n <div className=\"flex-1 min-w-0\">\n <p\n className={cn(\n \"text-sm font-medium\",\n step.done\n ? \"text-text-secondary line-through\"\n : \"text-text-primary\",\n )}\n >\n {step.label}\n </p>\n {step.hint && !step.done && (\n <p className=\"mt-0.5 text-xs text-text-secondary truncate\">\n {step.hint}\n </p>\n )}\n </div>\n {step.onClick && !step.done && (\n <ChevronRight\n size={16}\n className=\"flex-shrink-0 text-text-secondary\"\n />\n )}\n </button>\n ))}\n </div>\n </div>\n );\n })()}\n\n {/* Tabs */}\n <div className=\"border-b\">\n <nav\n className=\"-mb-px flex gap-4 overflow-x-auto\"\n role=\"tablist\"\n aria-label={tr(\n \"devportal.applicationSections\",\n \"Application sections\",\n )}\n >\n {tabs\n .filter((tab) => {\n // Package apps (NODE/WORKFLOW): hide integration-only tabs\n if (\n isPackageApp &&\n (tab.id === \"permissions\" ||\n tab.id === \"webhooks\" ||\n tab.id === \"delegations\" ||\n tab.id === \"playground\" ||\n tab.id === \"oauth\" ||\n tab.id === \"api-keys\")\n ) {\n return false;\n }\n // Non-package apps: hide versions tab unless it's an integration app\n if (!isPackageApp && !isIntegrationApp && tab.id === \"versions\") {\n return false;\n }\n // OAuth and API Keys only for integration apps\n if (\n !isIntegrationApp &&\n (tab.id === \"oauth\" || tab.id === \"api-keys\")\n ) {\n return false;\n }\n return true;\n })\n .map((tab) => {\n const Icon = tab.icon;\n return (\n <button\n key={tab.id}\n id={`application-tab-${tab.id}`}\n role=\"tab\"\n aria-selected={activeTab === tab.id}\n aria-controls={`application-panel-${tab.id}`}\n onClick={() => setActiveTab(tab.id)}\n className={cn(\n \"flex items-center gap-2 border-b-2 px-1 py-3 text-sm font-medium transition-colors\",\n activeTab === tab.id\n ? \"border-primary text-primary\"\n : \"border-transparent text-text-secondary hover:text-text-primary hover:border-muted-foreground\",\n )}\n >\n <Icon size={16} />\n {tab.label}\n </button>\n );\n })}\n </nav>\n </div>\n\n {/* Tab content */}\n <div\n className=\"mt-6\"\n id={`application-panel-${activeTab}`}\n role=\"tabpanel\"\n aria-labelledby={`application-tab-${activeTab}`}\n tabIndex={0}\n >\n {activeTab === \"overview\" && <OverviewTab app={app} />}\n {activeTab === \"permissions\" && (\n <PermissionsTab\n app={app}\n versionScopes={\n (data?.application?.versions?.edges?.[0]?.node?.requiredScopes ??\n []) as string[]\n }\n locked={\n app.status === \"PUBLISHED\" ||\n app.status === \"APPROVED\" ||\n app.status === \"ACTIVE\"\n }\n onNavigateToVersions={() => setActiveTab(\"versions\")}\n />\n )}\n {activeTab === \"webhooks\" && (\n <WebhooksTabConnected appId={app.id} onNavigate={handleNavigate} />\n )}\n {activeTab === \"delegations\" && (\n <DelegationsTabConnected\n authAppId={app.appId || undefined}\n appName={app.name}\n onGrantDelegation={() => setShowDelegationModal(true)}\n onNavigate={handleNavigate}\n />\n )}\n {activeTab === \"analytics\" && <AnalyticsTabConnected appId={app.id} />}\n {activeTab === \"playground\" && <ApiPlaygroundTab app={app} />}\n {activeTab === \"oauth\" && (\n <OAuthTabConnected appId={app.id} onNavigate={handleNavigate} />\n )}\n {activeTab === \"api-keys\" && (\n <ApiKeysTabConnected appId={app.id} onNavigate={handleNavigate} />\n )}\n {activeTab === \"store-listing\" && (\n <StoreListingTab\n app={app}\n versionCount={data?.application?.versions?.totalCount ?? 0}\n isPackageApp={isPackageApp}\n pricingDone={pricingDone}\n onNavigateToVersions={\n isPackageApp || isIntegrationApp\n ? () => setActiveTab(\"versions\")\n : undefined\n }\n onNavigateToPricing={() => setActiveTab(\"pricing\")}\n onNavigateToSubmission={() =>\n handleNavigate(`/apps/${app.id}/store-submission`)\n }\n />\n )}\n {activeTab === \"pricing\" && (\n <PricingTab\n app={app}\n platformFeeRate={platformFeeRate}\n billingAccountLinked={billingAccountLinked}\n onNavigateToRevenue={() => handleNavigate(\"/revenue\")}\n isReadyToSubmit={isReadyToSubmit}\n />\n )}\n {activeTab === \"versions\" && (\n <VersionsTabConnected\n appId={app.id}\n onNavigate={handleNavigate}\n pricingDone={pricingDone}\n onNavigateToPricing={() => setActiveTab(\"pricing\")}\n />\n )}\n </div>\n\n {/* Rotate Secret Confirmation */}\n <ConfirmDialog\n open={showRotateSecretDialog}\n onOpenChange={setShowRotateSecretDialog}\n onConfirm={handleRotateSecret}\n title={tr(\"devportal.rotateAppSecret\", \"Rotate App Secret\")}\n description={tr(\n \"devportal.rotateAppSecretDescription\",\n \"This will generate a new client secret and invalidate the current one. All existing integrations using the old secret will stop working immediately.\",\n )}\n confirmLabel={tr(\"devportal.rotateSecret\", \"Rotate Secret\")}\n cancelLabel={tr(\"devportal.cancel\", \"Cancel\")}\n variant=\"warning\"\n loading={rotateLoading}\n />\n\n {/* Deactivate App Confirmation */}\n <ConfirmDialog\n open={showDeactivateDialog}\n onOpenChange={setShowDeactivateDialog}\n onConfirm={handleDeactivateApp}\n title={tr(\"devportal.deactivateApplication\", \"Deactivate Application\")}\n description={tr(\n \"devportal.deactivateApplicationDescription\",\n \"This will deactivate the application. All OAuth clients, API keys, and webhooks associated with this app will stop functioning. This action can be reversed by reactivating the app.\",\n )}\n confirmLabel={tr(\"devportal.deactivate\", \"Deactivate\")}\n cancelLabel={tr(\"devportal.cancel\", \"Cancel\")}\n variant=\"destructive\"\n loading={deactivateLoading}\n />\n\n {/* Grant Delegation Modal */}\n <GrantDelegationModal\n open={showDelegationModal}\n onOpenChange={setShowDelegationModal}\n appId={app.appId || \"\"}\n appName={app.name}\n appScopes={app.scopes?.map((s) => s.scope) ?? []}\n onSuccess={() => {\n setShowDelegationModal(false);\n }}\n />\n </PageLayout>\n );\n};\n\n// =============================================================================\n// CONNECTED TAB WRAPPERS (data-fetching layer)\n// =============================================================================\n\n/**\n * OAuth tab — now links to centralized OAuth apps page (auth-svc).\n * Previously fetched devportal-svc OAuthClients per application.\n */\nconst OAuthTabConnected: FC<{\n appId: string;\n onNavigate: (path: string) => void;\n}> = ({ onNavigate }) => {\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 return (\n <div className=\"space-y-4 py-4 text-center\">\n <Shield className=\"mx-auto h-10 w-10 text-text-secondary\" />\n <h3 className=\"font-medium\">{tr(\"devportal.oauthApps\", \"OAuth Apps\")}</h3>\n <p className=\"text-sm text-text-secondary\">\n {tr(\n \"devportal.oauthAppsManagedCentrally\",\n \"OAuth apps are now managed centrally. Visit the OAuth Apps page to create and manage your apps.\",\n )}\n </p>\n <button\n onClick={() => onNavigate(\"/oauth\")}\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 transition-colors\"\n >\n <ExternalLink size={16} />\n {tr(\"devportal.manageOAuthApps\", \"Manage OAuth Apps\")}\n </button>\n </div>\n );\n};\n\n/**\n * API Keys tab — now links to centralized API keys page (auth-svc).\n * Previously fetched devportal-svc ApiKeys per application.\n */\nconst ApiKeysTabConnected: FC<{\n appId: string;\n onNavigate: (path: string) => void;\n}> = ({ onNavigate }) => {\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 return (\n <div className=\"space-y-4 py-4 text-center\">\n <Key className=\"mx-auto h-10 w-10 text-text-secondary\" />\n <h3 className=\"font-medium\">{tr(\"devportal.apiKeys\", \"API Keys\")}</h3>\n <p className=\"text-sm text-text-secondary\">\n {tr(\n \"devportal.apiKeysManagedCentrally\",\n \"API keys are now managed centrally. Visit the API Keys page to generate and manage your keys.\",\n )}\n </p>\n <button\n onClick={() => onNavigate(\"/api-keys\")}\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 transition-colors\"\n >\n <ExternalLink size={16} />\n {tr(\"devportal.manageApiKeys\", \"Manage API Keys\")}\n </button>\n </div>\n );\n};\n\n// =============================================================================\n// PRICING TAB\n// =============================================================================\n\n// 1 platform credit = $0.01 USD (matches the default rateUSD fallback in CreditsProvider)\nconst CREDIT_RATE_USD = 0.01;\nconst creditsToUsd = (credits: number) => credits * CREDIT_RATE_USD;\nconst usdToCredits = (usd: number) => Math.round(usd / CREDIT_RATE_USD);\n\nconst PricingTab: FC<{\n app: Application;\n platformFeeRate: number;\n billingAccountLinked: boolean;\n onNavigateToRevenue?: () => void;\n isReadyToSubmit?: boolean;\n}> = ({\n app,\n platformFeeRate,\n billingAccountLinked,\n onNavigateToRevenue,\n isReadyToSubmit = false,\n}) => {\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 pricingDetails = (app.pricingDetails ?? {}) as Record<string, unknown>;\n const [formData, setFormData] = useState({\n pricingType: app.pricingType ?? \"FREE\",\n // stored as credits in pricingDetails.price; older data may store USD — treat <1000 as USD legacy\n price:\n typeof pricingDetails.price === \"number\"\n ? String(pricingDetails.price)\n : \"\",\n });\n const [isSaving, setIsSaving] = useState(false);\n const [updateApplication] = useUpdateApplicationMutation();\n\n const appRef = useRef(app);\n appRef.current = app;\n useEffect(() => {\n const pd = (appRef.current.pricingDetails ?? {}) as Record<string, unknown>;\n setFormData({\n pricingType: appRef.current.pricingType ?? \"FREE\",\n price: typeof pd.price === \"number\" ? String(pd.price) : \"\",\n });\n }, [app.id]);\n\n const handleChange = (field: \"pricingType\" | \"price\", value: string) => {\n setFormData((prev) => ({ ...prev, [field]: value }));\n };\n\n const handleSave = async () => {\n setIsSaving(true);\n try {\n const existingDetails = (app.pricingDetails ?? {}) as Record<\n string,\n unknown\n >;\n const pricingDetailsUpdate: Record<string, unknown> = {\n ...existingDetails,\n };\n if (formData.pricingType !== \"FREE\") {\n const parsedCredits = parseInt(formData.price, 10);\n if (!isNaN(parsedCredits) && parsedCredits > 0) {\n pricingDetailsUpdate.price = parsedCredits;\n // always store currency as credits unit identifier\n pricingDetailsUpdate.currency = \"CREDITS\";\n }\n } else {\n delete pricingDetailsUpdate.price;\n delete pricingDetailsUpdate.currency;\n }\n await updateApplication({\n variables: {\n id: app.id,\n input: {\n pricingType: formData.pricingType || null,\n pricingDetails:\n Object.keys(pricingDetailsUpdate).length > 0\n ? pricingDetailsUpdate\n : null,\n },\n },\n });\n void nativeNotify(\"success\");\n } catch {\n void nativeNotify(\"error\");\n } finally {\n setIsSaving(false);\n }\n };\n\n const showPriceFields = formData.pricingType !== \"FREE\";\n const parsedCredits = parseInt(formData.price, 10);\n const hasValidPrice =\n showPriceFields && !isNaN(parsedCredits) && parsedCredits > 0;\n const priceUsd = hasValidPrice ? creditsToUsd(parsedCredits) : 0;\n const feeCredits = hasValidPrice\n ? Math.round(parsedCredits * platformFeeRate)\n : 0;\n const feeUsd = creditsToUsd(feeCredits);\n const payoutCredits = hasValidPrice ? parsedCredits - feeCredits : 0;\n const payoutUsd = creditsToUsd(payoutCredits);\n const fmtUsd = (n: number) =>\n \"$\" +\n n.toLocaleString(\"en-US\", {\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n });\n const fmtCredits = (n: number) => n.toLocaleString(\"en-US\") + \" cr\";\n\n return (\n <div className=\"space-y-8\">\n {/* ── Credits explained ── */}\n <div className=\"flex items-start gap-3 rounded-lg border border-border-subtle bg-bg-sunken px-4 py-3\">\n <CircleDollarSign size={16} className=\"mt-0.5 shrink-0 text-primary\" />\n <p className=\"text-sm text-text-secondary\">\n <span className=\"font-medium text-text-primary\">\n Platform credits\n </span>{\" \"}\n are the currency of the Burdenoff marketplace.{\" \"}\n <span className=\"font-medium\">\n 1 credit = {fmtUsd(CREDIT_RATE_USD)} USD.\n </span>{\" \"}\n Buyers purchase credits and spend them on apps. You earn credits on\n every sale and can withdraw them as cash via your billing account.\n </p>\n </div>\n\n {/* ── How monetization works ── */}\n <div className=\"space-y-3\">\n <div>\n <h2 className=\"text-lg font-semibold\">\n {tr(\"devportal.howMonetizationWorks\", \"How App Monetization Works\")}\n </h2>\n <p className=\"mt-1 text-sm text-text-secondary\">\n {tr(\n \"devportal.monetizationDesc\",\n \"Earn revenue when users install or purchase your app. Here's exactly how the money flows.\",\n )}\n </p>\n </div>\n <div className=\"grid gap-4 sm:grid-cols-3\">\n {/* Revenue share */}\n <div className=\"rounded-xl border border-border-subtle bg-bg-surface p-5 space-y-3\">\n <div className=\"flex h-9 w-9 items-center justify-center rounded-lg bg-status-success-bg-subtle\">\n <TrendingUp size={18} className=\"text-status-success-text\" />\n </div>\n <div>\n <p className=\"font-semibold\">\n {(100 - platformFeeRate * 100).toFixed(0)}% revenue share\n </p>\n <p className=\"mt-1 text-sm text-text-secondary\">\n You keep{\" \"}\n <span className=\"font-medium text-status-success-text\">\n {(100 - platformFeeRate * 100).toFixed(0)}%\n </span>{\" \"}\n of every sale in credits. The platform retains a{\" \"}\n <span className=\"font-medium\">\n {(platformFeeRate * 100).toFixed(0)}%\n </span>{\" \"}\n fee to cover infrastructure, payments processing, and\n marketplace operations.\n </p>\n </div>\n </div>\n {/* Payouts */}\n <div className=\"rounded-xl border border-border-subtle bg-bg-surface p-5 space-y-3\">\n <div className=\"flex h-9 w-9 items-center justify-center rounded-lg bg-action-primary-bg/10\">\n <Wallet size={18} className=\"text-primary\" />\n </div>\n <div>\n <p className=\"font-semibold\">Credits → cash via billing</p>\n <p className=\"mt-1 text-sm text-text-secondary\">\n Every sale instantly deposits your earned credits into your\n linked billing account. You can spend them on platform services\n or request a cash withdrawal. Track everything on the{\" \"}\n {onNavigateToRevenue ? (\n <button\n type=\"button\"\n onClick={onNavigateToRevenue}\n className=\"font-medium text-primary underline-offset-2 hover:underline\"\n >\n Revenue page\n </button>\n ) : (\n <span className=\"font-medium text-primary\">Revenue page</span>\n )}\n .\n </p>\n </div>\n </div>\n {/* Marketplace reach */}\n <div className=\"rounded-xl border border-border-subtle bg-bg-surface p-5 space-y-3\">\n <div className=\"flex h-9 w-9 items-center justify-center rounded-lg bg-status-warning-bg-subtle\">\n <Gift size={18} className=\"text-status-warning-text\" />\n </div>\n <div>\n <p className=\"font-semibold\">Reach the full marketplace</p>\n <p className=\"mt-1 text-sm text-text-secondary\">\n Any user with platform credits can discover and install your app\n directly from the marketplace. Free apps maximise reach; paid\n apps let you monetise your work.\n </p>\n </div>\n </div>\n </div>\n </div>\n\n {/* ── Set your price ── */}\n <div className=\"space-y-4\">\n <div>\n <h3 className=\"text-base font-semibold\">\n {tr(\"devportal.setPricingTitle\", \"Set Your Price\")}\n </h3>\n <p className=\"mt-0.5 text-sm text-text-secondary\">\n Choose <strong>Free</strong> to maximise installs, or{\" \"}\n <strong>Paid</strong> to earn credits on every install. Paid apps\n require a linked billing account before publishing.\n </p>\n </div>\n\n {/* Pricing type toggle */}\n <div className=\"flex flex-wrap gap-2\">\n {PRICING_TYPE_OPTIONS.map((opt) => (\n <button\n key={opt.value}\n type=\"button\"\n onClick={() => handleChange(\"pricingType\", opt.value)}\n className={cn(\n \"rounded-md border px-4 py-2 text-sm font-medium transition-colors\",\n formData.pricingType === opt.value\n ? \"bg-action-primary-bg text-action-primary-text border-primary\"\n : \"hover:bg-bg-sunken border-border-subtle\",\n )}\n >\n {opt.label}\n </button>\n ))}\n </div>\n\n {showPriceFields && (\n <div className=\"space-y-4\">\n {/* Credits price input */}\n <div className=\"max-w-xs\">\n <label className=\"mb-1.5 block text-sm font-medium\">\n Listing price{\" \"}\n <span className=\"text-text-tertiary font-normal\">\n (credits)\n </span>\n </label>\n <div className=\"relative flex items-center\">\n <input\n type=\"number\"\n min={1}\n step={1}\n value={formData.price}\n onChange={(e) => handleChange(\"price\", e.target.value)}\n placeholder=\"e.g. 1000\"\n className=\"w-full rounded-md border border-border-subtle bg-bg-input px-3 py-2 pr-20 text-sm focus:outline-none focus:ring-2 focus:ring-primary/50\"\n />\n <span className=\"pointer-events-none absolute right-3 text-xs text-text-tertiary\">\n credits\n </span>\n </div>\n {hasValidPrice && (\n <p className=\"mt-1.5 text-xs text-text-secondary\">\n ≈ {fmtUsd(priceUsd)} USD at the current credit rate (1 cr ={\" \"}\n {fmtUsd(CREDIT_RATE_USD)})\n </p>\n )}\n <p className=\"mt-1 text-xs text-text-tertiary\">\n {tr(\n \"devportal.priceHint\",\n \"Set the number of credits a buyer spends to install your app\",\n )}\n </p>\n </div>\n\n {/* Quick USD → credits helper */}\n <div className=\"flex items-center gap-2 text-xs text-text-secondary\">\n <span>Quick convert:</span>\n {[5, 10, 25, 50].map((usd) => (\n <button\n key={usd}\n type=\"button\"\n onClick={() =>\n handleChange(\"price\", String(usdToCredits(usd)))\n }\n className=\"rounded border border-border-subtle px-2 py-0.5 hover:bg-bg-sunken transition-colors\"\n >\n ${usd} = {usdToCredits(usd).toLocaleString()} cr\n </button>\n ))}\n </div>\n\n {/* Live revenue breakdown */}\n {hasValidPrice && (\n <div className=\"rounded-lg border border-border-subtle bg-bg-sunken p-4 space-y-3\">\n <p className=\"text-xs font-semibold uppercase tracking-wide text-text-secondary\">\n {tr(\n \"devportal.revenueBreakdown\",\n \"Revenue Breakdown per Sale\",\n )}\n </p>\n <div className=\"space-y-2 text-sm\">\n <div className=\"flex items-center justify-between\">\n <span className=\"text-text-secondary\">Buyer pays</span>\n <span className=\"font-medium tabular-nums\">\n {fmtCredits(parsedCredits)}{\" \"}\n <span className=\"text-text-tertiary text-xs\">\n ({fmtUsd(priceUsd)})\n </span>\n </span>\n </div>\n <div className=\"flex items-center justify-between text-status-error-text\">\n <span>\n Platform fee{\" \"}\n <span className=\"opacity-70\">\n ({(platformFeeRate * 100).toFixed(0)}%)\n </span>\n </span>\n <span className=\"tabular-nums\">\n − {fmtCredits(feeCredits)}{\" \"}\n <span className=\"text-xs opacity-70\">\n ({fmtUsd(feeUsd)})\n </span>\n </span>\n </div>\n <div className=\"flex items-center justify-between border-t border-border-subtle pt-2 font-semibold text-status-success-text\">\n <span>You earn</span>\n <span className=\"tabular-nums\">\n {fmtCredits(payoutCredits)}{\" \"}\n <span className=\"text-sm font-normal\">\n ≈ {fmtUsd(payoutUsd)}\n </span>\n </span>\n </div>\n </div>\n <p className=\"text-xs text-text-tertiary\">\n Credits are deposited to your billing account on each sale.\n Cash withdrawal is subject to platform terms and minimum\n payout thresholds.\n </p>\n </div>\n )}\n\n {/* Billing account warning */}\n {!billingAccountLinked && (\n <div className=\"flex items-start gap-3 rounded-lg border border-status-warning-bg bg-status-warning-bg-subtle p-4\">\n <AlertCircle\n size={16}\n className=\"mt-0.5 shrink-0 text-status-warning-text\"\n />\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm font-medium text-status-warning-text\">\n {tr(\n \"devportal.billingAccountRequired\",\n \"Billing account required to publish\",\n )}\n </p>\n <p className=\"mt-0.5 text-xs text-text-secondary\">\n Paid apps must have a billing account linked to your\n developer organization before you can submit for review.\n This is where your earned credits and cash withdrawals will\n be managed.\n </p>\n {onNavigateToRevenue && (\n <button\n type=\"button\"\n onClick={onNavigateToRevenue}\n className=\"mt-2 text-xs font-medium text-primary hover:underline underline-offset-2\"\n >\n {tr(\n \"devportal.goToRevenueBilling\",\n \"Go to Revenue & Billing →\",\n )}\n </button>\n )}\n </div>\n </div>\n )}\n </div>\n )}\n </div>\n\n {/* ── Terms & Conditions ── */}\n <div className=\"rounded-xl border border-border-subtle bg-bg-surface p-5 space-y-3\">\n <h3 className=\"text-sm font-semibold\">\n {tr(\"devportal.termsTitle\", \"Developer & Marketplace Terms\")}\n </h3>\n <ul className=\"space-y-2 text-sm text-text-secondary\">\n <li className=\"flex items-start gap-2\">\n <Check\n size={14}\n className=\"mt-0.5 shrink-0 text-status-success-text\"\n />\n <span>\n By publishing to the marketplace you agree to the{\" \"}\n <a\n href=\"/legal/developer-terms\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-primary underline-offset-2 hover:underline\"\n >\n Developer Program Agreement\n </a>\n .\n </span>\n </li>\n <li className=\"flex items-start gap-2\">\n <Check\n size={14}\n className=\"mt-0.5 shrink-0 text-status-success-text\"\n />\n <span>\n All prices are in platform credits. The USD equivalent is\n indicative only and may vary with the current credit rate.\n </span>\n </li>\n <li className=\"flex items-start gap-2\">\n <Check\n size={14}\n className=\"mt-0.5 shrink-0 text-status-success-text\"\n />\n <span>\n Earnings are credited to your billing account per-sale. Cash\n withdrawals are subject to a minimum threshold and applicable\n taxes in your jurisdiction.\n </span>\n </li>\n <li className=\"flex items-start gap-2\">\n <Check\n size={14}\n className=\"mt-0.5 shrink-0 text-status-success-text\"\n />\n <span>\n The platform reserves the right to adjust the credit rate, fee\n structure, or payout schedule with 30 days notice. See the{\" \"}\n <a\n href=\"/legal/marketplace-terms\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-primary underline-offset-2 hover:underline\"\n >\n Marketplace Terms\n </a>{\" \"}\n for full details.\n </span>\n </li>\n </ul>\n </div>\n\n {/* ── Save + all-set banner ── */}\n <div className=\"border-t border-border-subtle pt-6 space-y-4\">\n <button\n type=\"button\"\n onClick={() => void handleSave()}\n disabled={isSaving}\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 transition-colors disabled:opacity-50\"\n >\n {isSaving ? (\n <>\n <Loader2 size={16} className=\"animate-spin\" />\n {tr(\"devportal.saving\", \"Saving…\")}\n </>\n ) : (\n <>\n <CircleDollarSign size={16} />\n {tr(\"devportal.savePricing\", \"Save Pricing\")}\n </>\n )}\n </button>\n {/* All-set banner — shown when every pre-publish check passes */}\n {isReadyToSubmit && (\n <div className=\"flex items-start gap-3 rounded-lg border border-status-success-bg bg-status-success-bg-subtle px-4 py-3\">\n <Check\n size={16}\n className=\"mt-0.5 shrink-0 text-status-success-text\"\n />\n <div>\n <p className=\"text-sm font-medium text-status-success-text\">\n {tr(\"devportal.allSetToSubmit\", \"You're all set!\")}\n </p>\n <p className=\"mt-0.5 text-xs text-text-secondary\">\n {tr(\n \"devportal.allSetDesc\",\n \"Store listing, versions, and pricing are complete. Head to the top of the page and click Submit for Review.\",\n )}\n </p>\n </div>\n </div>\n )}\n </div>\n </div>\n );\n};\n\n/** Versions tab — inline list of application versions with link to the full management page */\nconst VersionsTabConnected: FC<{\n appId: string;\n onNavigate: (path: string) => void;\n pricingDone?: boolean;\n onNavigateToPricing?: () => void;\n}> = ({ appId, onNavigate, pricingDone = false, onNavigateToPricing }) => {\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 const { data, loading, error } = useGetApplicationVersionsQuery({\n variables: { applicationId: appId },\n fetchPolicy: \"cache-and-network\",\n });\n\n if (loading)\n return (\n <TabLoadingSpinner\n message={tr(\"devportal.loadingVersions\", \"Loading versions…\")}\n />\n );\n if (error) return <TabErrorState message={error.message} />;\n\n type VersionEdge = NonNullable<\n GetApplicationVersionsQuery[\"application\"]\n >[\"versions\"][\"edges\"][number];\n const edges: VersionEdge[] = data?.application?.versions?.edges ?? [];\n const versions = edges.map((e) => e.node);\n\n return (\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between\">\n <p className=\"text-sm text-text-secondary\">\n {versions.length}{\" \"}\n {versions.length !== 1\n ? tr(\"devportal.versions\", \"versions\")\n : tr(\"devportal.version\", \"version\")}\n </p>\n <button\n onClick={() => onNavigate(`/apps/${appId}/versions`)}\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 transition-colors\"\n >\n <Upload size={16} />\n {tr(\"devportal.uploadVersion\", \"Upload Version\")}\n </button>\n </div>\n\n {versions.length > 0 ? (\n <div className=\"overflow-hidden rounded-lg border border-border-subtle\">\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"border-b border-border-subtle bg-bg-sunken/50\">\n <th className=\"px-4 py-3 text-left font-medium text-text-secondary\">\n {tr(\"devportal.version\", \"Version\")}\n </th>\n <th className=\"px-4 py-3 text-left font-medium text-text-secondary\">\n {tr(\"devportal.status\", \"Status\")}\n </th>\n <th className=\"px-4 py-3 text-left font-medium text-text-secondary\">\n {tr(\"devportal.released\", \"Released\")}\n </th>\n <th className=\"px-4 py-3 text-left font-medium text-text-secondary\">\n {tr(\"devportal.flags\", \"Flags\")}\n </th>\n </tr>\n </thead>\n <tbody className=\"divide-y divide-border-subtle\">\n {versions.map((v) => (\n <>\n <tr\n key={v.id}\n className=\"hover:bg-bg-sunken/30 transition-colors\"\n >\n <td className=\"px-4 py-3 font-mono font-medium\">\n {v.version}\n </td>\n <td className=\"px-4 py-3\">\n <span\n className={cn(\n \"inline-flex rounded-full px-2 py-0.5 text-xs font-medium\",\n v.status === \"published\"\n ? \"bg-status-success-bg-subtle text-status-success-text\"\n : v.status === \"pending_review\"\n ? \"bg-status-info-bg-subtle text-status-info-text\"\n : v.status === \"rejected\"\n ? \"bg-status-error-bg-subtle text-status-error-text\"\n : v.status === \"deprecated\"\n ? \"bg-bg-sunken text-text-secondary\"\n : \"bg-status-warning-bg-subtle text-status-warning-text\",\n )}\n >\n {v.status === \"pending_review\" ? \"In Review\" : v.status}\n </span>\n </td>\n <td className=\"px-4 py-3 text-text-secondary\">\n {v.publishedAt\n ? new Date(v.publishedAt).toLocaleDateString()\n : new Date(v.createdAt).toLocaleDateString()}\n </td>\n <td className=\"px-4 py-3\">\n <div className=\"flex gap-1.5\">\n {v.isLatest && (\n <span className=\"rounded-full bg-action-primary-bg/10 px-2 py-0.5 text-xs text-primary font-medium\">\n latest\n </span>\n )}\n {v.isStable && (\n <span className=\"rounded-full bg-status-success-bg-subtle px-2 py-0.5 text-xs text-status-success-text font-medium\">\n stable\n </span>\n )}\n </div>\n </td>\n </tr>\n {v.status === \"rejected\" && v.reviewNotes && (\n <tr\n key={`${v.id}-notes`}\n className=\"bg-status-error-bg-subtle/40\"\n >\n <td colSpan={4} className=\"px-4 py-2\">\n <p className=\"text-xs text-status-error-text\">\n <span className=\"font-semibold\">\n Review feedback:{\" \"}\n </span>\n {v.reviewNotes}\n </p>\n </td>\n </tr>\n )}\n {v.status === \"pending_review\" && (\n <tr\n key={`${v.id}-review`}\n className=\"bg-status-info-bg-subtle/30\"\n >\n <td colSpan={4} className=\"px-4 py-2\">\n <p className=\"text-xs text-status-info-text\">\n Submitted for platform review — you will be notified\n once approved or if changes are needed.\n </p>\n </td>\n </tr>\n )}\n </>\n ))}\n </tbody>\n </table>\n </div>\n ) : (\n <EmptyState\n illustration=\"empty-generic\"\n icon={<Package size={32} />}\n title={tr(\"devportal.noVersions\", \"No versions yet\")}\n description={tr(\n \"devportal.noVersionsDescription\",\n \"Upload your first version to make this item available for review and distribution.\",\n )}\n action={\n <button\n onClick={() => onNavigate(`/apps/${appId}/versions`)}\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\"\n >\n <Upload size={16} />\n {tr(\"devportal.uploadVersion\", \"Upload Version\")}\n </button>\n }\n />\n )}\n {/* Next-step hint: guide to pricing — only once a version actually exists */}\n {versions.length > 0 && !pricingDone && onNavigateToPricing && (\n <div className=\"mt-4 flex items-center gap-3 rounded-lg border border-border-subtle bg-bg-sunken px-4 py-3\">\n <CircleDollarSign size={16} className=\"shrink-0 text-primary\" />\n <p className=\"flex-1 text-sm text-text-secondary\">\n {tr(\n \"devportal.versionsNextPricing\",\n \"You've got versions covered. Now set your pricing before you can submit.\",\n )}\n </p>\n <button\n type=\"button\"\n onClick={onNavigateToPricing}\n className=\"inline-flex items-center gap-1 text-sm font-medium text-primary hover:underline underline-offset-2 whitespace-nowrap\"\n >\n {tr(\"devportal.nextSetPricing\", \"Set Pricing\")}\n <ChevronRight size={15} />\n </button>\n </div>\n )}\n </div>\n );\n};\n\n/** Webhooks tab with real data from useGetWebhooksQuery */\nconst WebhooksTabConnected: FC<{\n appId: string;\n onNavigate: (path: string) => void;\n}> = ({ appId, onNavigate }) => {\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 const { data, loading, error } = useGetWebhooksQuery({\n variables: { applicationId: appId },\n });\n\n if (loading)\n return (\n <TabLoadingSpinner\n message={tr(\"devportal.loadingWebhooks\", \"Loading webhooks...\")}\n />\n );\n if (error) return <TabErrorState message={error.message} />;\n\n const webhooks = (data?.webhooks ?? []).map(mapToWebhook);\n\n return (\n <WebhooksTab appId={appId} webhooks={webhooks} onNavigate={onNavigate} />\n );\n};\n\n/** Delegations tab with real data from useCurrentUserDelegationsQuery */\nconst DelegationsTabConnected: FC<{\n authAppId?: string;\n appName: string;\n onGrantDelegation: () => void;\n onNavigate: (path: string) => void;\n}> = ({ authAppId, appName, onGrantDelegation, onNavigate }) => {\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 const { data, loading, error, refetch } = useCurrentUserDelegationsQuery();\n const [revokeDelegation] = useRevokeDelegationMutation();\n const [revokeConfirmIds, setRevokeConfirmIds] = useState<string[]>([]);\n const [revokeLoading, setRevokeLoading] = useState(false);\n const [selectedDelegationIds, setSelectedDelegationIds] = useState<\n Set<string>\n >(new Set());\n const [successMessage, setSuccessMessage] = useState<string | null>(null);\n\n const appDelegations = useMemo((): AppUserDelegation[] => {\n if (!data?.currentUserDelegations?.delegations) return [];\n return data.currentUserDelegations.delegations\n .filter((d: { appId: string }) => d.appId === authAppId)\n .map(mapToDelegation);\n }, [authAppId, data]);\n\n const activeAppDelegations = useMemo(\n () => appDelegations.filter((delegation) => delegation.status === \"ACTIVE\"),\n [appDelegations],\n );\n const selectedActiveDelegations = useMemo(\n () =>\n activeAppDelegations.filter((delegation) =>\n selectedDelegationIds.has(delegation.id),\n ),\n [activeAppDelegations, selectedDelegationIds],\n );\n const allVisibleSelected =\n activeAppDelegations.length > 0 &&\n activeAppDelegations.every((delegation) =>\n selectedDelegationIds.has(delegation.id),\n );\n const partiallySelected =\n activeAppDelegations.some((delegation) =>\n selectedDelegationIds.has(delegation.id),\n ) && !allVisibleSelected;\n\n const toggleDelegationSelection = useCallback(\n (delegationId: string, checked: boolean) => {\n setSelectedDelegationIds((prev) => {\n const next = new Set(prev);\n if (checked) {\n next.add(delegationId);\n } else {\n next.delete(delegationId);\n }\n return next;\n });\n },\n [],\n );\n\n const toggleAllVisibleDelegations = useCallback(\n (checked: boolean) => {\n setSelectedDelegationIds((prev) => {\n const next = new Set(prev);\n activeAppDelegations.forEach((delegation) => {\n if (checked) {\n next.add(delegation.id);\n } else {\n next.delete(delegation.id);\n }\n });\n return next;\n });\n },\n [activeAppDelegations],\n );\n\n const clearSelection = useCallback(() => {\n setSelectedDelegationIds(new Set());\n }, []);\n\n const handleRevoke = useCallback(\n async (delegationIds: string[]) => {\n setRevokeLoading(true);\n try {\n const results = await Promise.allSettled(\n delegationIds.map((delegationId) =>\n revokeDelegation({ variables: { id: delegationId } }),\n ),\n );\n const succeeded = results.filter(\n (result: PromiseSettledResult<unknown>) =>\n result.status === \"fulfilled\",\n ).length;\n const failed = results.length - succeeded;\n setSuccessMessage(\n `Revoked ${succeeded} delegation${succeeded === 1 ? \"\" : \"s\"}${failed > 0 ? ` • ${failed} failed` : \"\"}`,\n );\n setSelectedDelegationIds((prev) => {\n const next = new Set(prev);\n delegationIds.forEach((delegationId) => next.delete(delegationId));\n return next;\n });\n setRevokeConfirmIds([]);\n refetch();\n } catch {\n // Error handled by Apollo\n } finally {\n setRevokeLoading(false);\n }\n },\n [revokeDelegation, refetch],\n );\n\n if (!authAppId) {\n return (\n <EmptyState\n illustration=\"empty-generic\"\n icon={<Shield size={32} />}\n title={tr(\"devportal.linkAuthAppFirst\", \"Link an auth app first\")}\n description={tr(\n \"devportal.linkAuthAppFirstDescription\",\n \"Delegations are managed through auth apps. Create or link an auth app before granting app-as-user access.\",\n )}\n action={\n <button\n onClick={() => onNavigate(\"/oauth\")}\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\"\n >\n <ExternalLink size={16} />\n {tr(\"devportal.manageOAuthApps\", \"Manage OAuth Apps\")}\n </button>\n }\n />\n );\n }\n\n if (loading)\n return (\n <TabLoadingSpinner\n message={tr(\"devportal.loadingDelegations\", \"Loading delegations...\")}\n />\n );\n if (error) return <TabErrorState message={error.message} />;\n\n return (\n <>\n {successMessage && (\n <div className=\"rounded-lg border border-border-subtle bg-status-success-bg-subtle p-3 text-sm text-status-success-text\">\n <div className=\"flex items-center justify-between gap-3\">\n <span>{successMessage}</span>\n <button\n onClick={() => setSuccessMessage(null)}\n className=\"text-status-success-text hover:text-status-success-text\"\n >\n {tr(\"devportal.dismiss\", \"Dismiss\")}\n </button>\n </div>\n </div>\n )}\n\n <DelegationsTab\n appName={appName}\n delegations={appDelegations}\n onGrantDelegation={onGrantDelegation}\n onRevokeDelegation={(id) => setRevokeConfirmIds([id])}\n selectedDelegationIds={selectedDelegationIds}\n onToggleSelectDelegation={toggleDelegationSelection}\n onToggleAllDelegations={toggleAllVisibleDelegations}\n onClearSelection={clearSelection}\n onRevokeSelected={() =>\n setRevokeConfirmIds(\n selectedActiveDelegations.map((delegation) => delegation.id),\n )\n }\n allVisibleSelected={allVisibleSelected}\n partiallySelected={partiallySelected}\n />\n\n <ConfirmDialog\n open={revokeConfirmIds.length > 0}\n onOpenChange={(open) => {\n if (!open) setRevokeConfirmIds([]);\n }}\n onConfirm={() => {\n if (revokeConfirmIds.length > 0) {\n handleRevoke(revokeConfirmIds);\n }\n }}\n title={\n revokeConfirmIds.length > 1\n ? tr(\"devportal.revokeDelegations\", \"Revoke Delegations\")\n : tr(\"devportal.revokeDelegation\", \"Revoke Delegation\")\n }\n description={\n revokeConfirmIds.length > 1\n ? tr(\n \"devportal.revokeMultipleDelegationsDescription\",\n `This will immediately revoke ${revokeConfirmIds.length} selected delegations.`,\n )\n : tr(\n \"devportal.revokeDelegationDescription\",\n \"This will immediately revoke the delegation. The app will no longer be able to act on your behalf with the selected permissions.\",\n )\n }\n confirmLabel={tr(\"devportal.revoke\", \"Revoke\")}\n cancelLabel={tr(\"devportal.cancel\", \"Cancel\")}\n variant=\"destructive\"\n loading={revokeLoading}\n />\n </>\n );\n};\n\n/** Analytics tab with real data from useGetApplicationAnalyticsQuery */\nconst AnalyticsTabConnected: FC<{ appId: string }> = ({ appId }) => {\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 const now = useMemo(() => new Date(), []);\n const thirtyDaysAgo = useMemo(() => {\n const d = new Date(now);\n d.setDate(d.getDate() - 30);\n return d;\n }, [now]);\n\n const { data, loading, error } = useGetApplicationAnalyticsQuery({\n variables: {\n applicationId: appId,\n period: \"daily\",\n startDate: thirtyDaysAgo.toISOString(),\n endDate: now.toISOString(),\n },\n });\n\n if (loading)\n return (\n <TabLoadingSpinner\n message={tr(\"devportal.loadingAnalytics\", \"Loading analytics...\")}\n />\n );\n if (error) return <TabErrorState message={error.message} />;\n\n const analytics = (data?.applicationAnalytics ?? []).map(mapToAnalytics);\n\n return <AnalyticsTab analytics={analytics} />;\n};\n\n// =============================================================================\n// OVERVIEW TAB\n// =============================================================================\n\nconst OverviewTab: FC<{ app: Application }> = ({ app }) => {\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 return (\n <div className=\"grid gap-6 lg:grid-cols-3\">\n <div className=\"lg:col-span-2 space-y-6\">\n {/* Stats — primary emphasis zone */}\n <EmphasisPanel>\n <div className=\"grid gap-4 sm:grid-cols-4\">\n <StatCard\n label={tr(\"devportal.totalInstalls\", \"Total Installs\")}\n value={app.installCount.toLocaleString()}\n />\n <StatCard\n label={tr(\"devportal.activeInstalls\", \"Active Installs\")}\n value={app.activeInstallCount.toLocaleString()}\n />\n <StatCard\n label={tr(\"devportal.averageRating\", \"Average Rating\")}\n value={\n app.averageRating\n ? `${app.averageRating.toFixed(1)} ★`\n : tr(\"devportal.notAvailable\", \"N/A\")\n }\n />\n <StatCard\n label={tr(\"devportal.reviews\", \"Reviews\")}\n value={app.reviewCount.toString()}\n />\n </div>\n </EmphasisPanel>\n\n {/* Description */}\n <PageSection title={tr(\"devportal.description\", \"Description\")}>\n <div className=\"prose prose-sm max-w-none\">\n <pre className=\"whitespace-pre-wrap font-sans text-sm text-text-primary bg-transparent p-0 m-0\">\n {app.description ||\n tr(\n \"devportal.noDescriptionProvided\",\n \"No description provided.\",\n )}\n </pre>\n </div>\n </PageSection>\n\n {/* Tags & Keywords */}\n <PageSection title={tr(\"devportal.tagsAndKeywords\", \"Tags & Keywords\")}>\n <div className=\"space-y-3\">\n {app.tags.length > 0 && (\n <div>\n <p className=\"text-xs text-text-secondary mb-2\">\n {tr(\"devportal.tags\", \"Tags\")}\n </p>\n <div className=\"flex flex-wrap gap-2\">\n {app.tags.map((tag) => (\n <span\n key={tag}\n className=\"rounded-full bg-action-primary-bg/10 px-3 py-1 text-xs font-medium text-primary\"\n >\n {tag}\n </span>\n ))}\n </div>\n </div>\n )}\n {app.keywords.length > 0 && (\n <div>\n <p className=\"text-xs text-text-secondary mb-2\">\n {tr(\"devportal.keywords\", \"Keywords\")}\n </p>\n <div className=\"flex flex-wrap gap-2\">\n {app.keywords.map((keyword) => (\n <span\n key={keyword}\n className=\"rounded-full bg-bg-sunken px-3 py-1 text-xs\"\n >\n {keyword}\n </span>\n ))}\n </div>\n </div>\n )}\n </div>\n </PageSection>\n </div>\n\n {/* Sidebar */}\n <div className=\"space-y-6\">\n <PageSection title={tr(\"devportal.details\", \"Details\")}>\n <DetailList\n items={[\n {\n label: tr(\"devportal.appId\", \"App ID\"),\n value: <code className=\"text-xs\">{app.id}</code>,\n },\n { label: tr(\"devportal.slug\", \"Slug\"), value: app.slug },\n {\n label: tr(\"devportal.category\", \"Category\"),\n value:\n app.category ||\n tr(\"devportal.uncategorized\", \"Uncategorized\"),\n },\n {\n label: tr(\"devportal.pricing\", \"Pricing\"),\n value: (() => {\n if (app.pricingType === \"PAID\") {\n const pd = (app.pricingDetails ?? {}) as Record<\n string,\n unknown\n >;\n const price =\n typeof pd.price === \"number\" ? pd.price : null;\n const currency =\n typeof pd.currency === \"string\" ? pd.currency : \"USD\";\n return price != null\n ? `PAID — ${price} ${currency}`\n : \"PAID\";\n }\n return app.pricingType || tr(\"devportal.free\", \"Free\");\n })(),\n },\n {\n label: tr(\"devportal.created\", \"Created\"),\n value: new Date(app.createdAt).toLocaleDateString(),\n },\n {\n label: tr(\"devportal.updated\", \"Updated\"),\n value: new Date(app.updatedAt).toLocaleDateString(),\n },\n {\n label: tr(\"devportal.published\", \"Published\"),\n value: app.publishedAt\n ? new Date(app.publishedAt).toLocaleDateString()\n : tr(\"devportal.notPublished\", \"Not published\"),\n },\n ]}\n />\n </PageSection>\n\n <PageSection title={tr(\"devportal.links\", \"Links\")}>\n <div className=\"space-y-2\">\n {app.websiteUrl && (\n <LinkItem\n label={tr(\"devportal.website\", \"Website\")}\n url={app.websiteUrl}\n />\n )}\n {app.documentationUrl && (\n <LinkItem\n label={tr(\"devportal.documentation\", \"Documentation\")}\n url={app.documentationUrl}\n />\n )}\n {app.supportUrl && (\n <LinkItem\n label={tr(\"devportal.support\", \"Support\")}\n url={app.supportUrl}\n />\n )}\n {app.githubUrl && (\n <LinkItem\n label={tr(\"devportal.github\", \"GitHub\")}\n url={app.githubUrl}\n />\n )}\n {app.privacyPolicyUrl && (\n <LinkItem\n label={tr(\"devportal.privacyPolicy\", \"Privacy Policy\")}\n url={app.privacyPolicyUrl}\n />\n )}\n {app.termsOfServiceUrl && (\n <LinkItem\n label={tr(\"devportal.termsOfService\", \"Terms of Service\")}\n url={app.termsOfServiceUrl}\n />\n )}\n </div>\n </PageSection>\n </div>\n </div>\n );\n};\n\n// =============================================================================\n// OAUTH TAB\n// =============================================================================\n\n/**\n * Note: OAuthTab and ApiKeysTab presentation components removed.\n * OAuth apps and API keys are now managed centrally via auth-svc.\n * The connected wrappers above link to the /oauth and /api-keys pages.\n */\n\n// =============================================================================\n// WEBHOOKS TAB\n// =============================================================================\n\nconst WebhooksTab: FC<{\n appId: string;\n webhooks: WebhookType[];\n onNavigate: (path: string) => void;\n}> = ({ appId, webhooks, onNavigate }) => {\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 return (\n <div className=\"space-y-6\">\n <div className=\"flex items-center justify-between\">\n <p className=\"text-sm text-text-secondary\">\n {webhooks.length}{\" \"}\n {webhooks.length !== 1\n ? tr(\"devportal.webhooks\", \"webhooks\")\n : tr(\"devportal.webhook\", \"webhook\")}{\" \"}\n {tr(\"devportal.configured\", \"configured\")}\n </p>\n <button\n onClick={() => onNavigate(`/apps/${appId}/webhooks/new`)}\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 transition-colors\"\n >\n <Plus size={16} />\n {tr(\"devportal.addWebhook\", \"Add Webhook\")}\n </button>\n </div>\n\n {webhooks.length > 0 ? (\n <div className=\"space-y-4\">\n {webhooks.map((webhook) => (\n <div\n key={webhook.id}\n className=\"rounded-card border border-border-seam bg-bg-surface p-4 space-y-4 shadow-[var(--shadow-pop)]\"\n >\n <div className=\"flex items-start justify-between\">\n <div>\n <div className=\"flex items-center gap-2\">\n <h3 className=\"font-medium\">{webhook.name}</h3>\n <StatusBadge status={webhook.status} type=\"webhook\" />\n </div>\n {webhook.description && (\n <p className=\"text-sm text-text-secondary mt-1\">\n {webhook.description}\n </p>\n )}\n </div>\n <button\n onClick={() =>\n onNavigate(`/apps/${appId}/webhooks/${webhook.id}`)\n }\n className=\"rounded-md p-1 hover:bg-bg-sunken\"\n >\n <MoreHorizontal size={20} />\n </button>\n </div>\n\n <div>\n <p className=\"text-xs text-text-secondary mb-1\">\n {tr(\"devportal.endpointUrl\", \"Endpoint URL\")}\n </p>\n <code className=\"text-sm bg-bg-sunken px-2 py-1 rounded block truncate\">\n {webhook.url}\n </code>\n </div>\n\n <div>\n <p className=\"text-xs text-text-secondary mb-2\">\n {tr(\"devportal.events\", \"Events\")}\n </p>\n <div className=\"flex flex-wrap gap-2\">\n {webhook.events.map((event) => (\n <span\n key={event}\n className=\"rounded-full bg-bg-sunken px-2 py-0.5 text-xs\"\n >\n {event}\n </span>\n ))}\n </div>\n </div>\n\n <div className=\"grid gap-4 sm:grid-cols-4 text-sm\">\n <div>\n <p className=\"text-xs text-text-secondary\">\n {tr(\"devportal.success\", \"Success\")}\n </p>\n <p className=\"font-medium text-status-success-text\">\n {webhook.successCount.toLocaleString()}\n </p>\n </div>\n <div>\n <p className=\"text-xs text-text-secondary\">\n {tr(\"devportal.failed\", \"Failed\")}\n </p>\n <p className=\"font-medium text-status-error-text\">\n {webhook.failureCount.toLocaleString()}\n </p>\n </div>\n <div>\n <p className=\"text-xs text-text-secondary\">\n {tr(\"devportal.successRate\", \"Success Rate\")}\n </p>\n <p className=\"font-medium\">\n {webhook.successCount + webhook.failureCount > 0\n ? (\n (webhook.successCount /\n (webhook.successCount + webhook.failureCount)) *\n 100\n ).toFixed(1)\n : \"0.0\"}\n %\n </p>\n </div>\n <div>\n <p className=\"text-xs text-text-secondary\">\n {tr(\"devportal.lastTriggered\", \"Last Triggered\")}\n </p>\n <p className=\"font-medium\">\n {webhook.lastTriggeredAt\n ? new Date(webhook.lastTriggeredAt).toLocaleString()\n : tr(\"devportal.never\", \"Never\")}\n </p>\n </div>\n </div>\n </div>\n ))}\n </div>\n ) : (\n <EmptyState\n illustration=\"empty-notifications\"\n icon={<Webhook size={32} />}\n title={tr(\"devportal.noWebhooks\", \"No webhooks\")}\n description={tr(\n \"devportal.noWebhooksDescription\",\n \"Add a webhook to receive event notifications\",\n )}\n action={\n <button\n onClick={() => onNavigate(`/apps/${appId}/webhooks/new`)}\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\"\n >\n <Plus size={16} />\n {tr(\"devportal.addWebhook\", \"Add Webhook\")}\n </button>\n }\n />\n )}\n </div>\n );\n};\n\n// =============================================================================\n// DELEGATIONS TAB\n// =============================================================================\n\nconst DelegationsTab: FC<{\n appName: string;\n delegations: AppUserDelegation[];\n onGrantDelegation: () => void;\n onRevokeDelegation: (id: string) => void;\n selectedDelegationIds: Set<string>;\n onToggleSelectDelegation: (id: string, checked: boolean) => void;\n onToggleAllDelegations: (checked: boolean) => void;\n onClearSelection: () => void;\n onRevokeSelected: () => void;\n allVisibleSelected: boolean;\n partiallySelected: boolean;\n}> = ({\n appName,\n delegations,\n onGrantDelegation,\n onRevokeDelegation,\n selectedDelegationIds,\n onToggleSelectDelegation,\n onToggleAllDelegations,\n onClearSelection,\n onRevokeSelected,\n allVisibleSelected,\n partiallySelected,\n}) => {\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 const activeDelegations = delegations.filter((d) => d.status === \"ACTIVE\");\n const inactiveDelegations = delegations.filter((d) => d.status !== \"ACTIVE\");\n\n return (\n <div className=\"space-y-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <p className=\"text-sm text-text-secondary\">\n {delegations.length}{\" \"}\n {delegations.length !== 1\n ? tr(\"devportal.delegations\", \"delegations\")\n : tr(\"devportal.delegation\", \"delegation\")}{\" \"}\n {tr(\"devportal.for\", \"for\")} {appName}\n </p>\n {activeDelegations.length > 0 && (\n <p className=\"text-xs text-text-secondary mt-0.5\">\n {activeDelegations.length} {tr(\"devportal.active\", \"active\")},{\" \"}\n {inactiveDelegations.length}{\" \"}\n {tr(\"devportal.revokedExpired\", \"revoked/expired\")}\n </p>\n )}\n </div>\n <button\n onClick={onGrantDelegation}\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 transition-colors\"\n >\n <Plus size={16} />\n {tr(\"devportal.grantDelegation\", \"Grant Delegation\")}\n </button>\n </div>\n\n {activeDelegations.length > 0 && (\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-4\">\n <div className=\"flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <div className=\"flex items-center gap-2\">\n <SelectionCheckbox\n checked={allVisibleSelected}\n indeterminate={partiallySelected}\n onChange={onToggleAllDelegations}\n ariaLabel={tr(\n \"devportal.selectAllActiveDelegations\",\n \"Select all active app delegations\",\n )}\n />\n <span className=\"text-sm font-medium\">\n {tr(\"devportal.selectAllActive\", \"Select all active\")}\n </span>\n </div>\n {selectedDelegationIds.size > 0 && (\n <button\n onClick={onClearSelection}\n className=\"text-sm text-text-secondary hover:text-text-primary\"\n >\n {tr(\"devportal.clearSelection\", \"Clear selection\")}\n </button>\n )}\n </div>\n\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"rounded-full bg-bg-sunken px-3 py-1 text-sm font-medium text-text-secondary\">\n {selectedDelegationIds.size}{\" \"}\n {tr(\"devportal.selected\", \"selected\")}\n </span>\n <button\n onClick={onRevokeSelected}\n disabled={selectedDelegationIds.size === 0}\n className=\"rounded-md border border-status-error-bg px-3 py-2 text-sm font-medium text-status-error-text hover:bg-status-error-bg-subtle disabled:cursor-not-allowed disabled:opacity-50\"\n >\n {tr(\"devportal.revokeSelected\", \"Revoke Selected\")}\n {selectedDelegationIds.size > 0\n ? ` (${selectedDelegationIds.size})`\n : \"\"}\n </button>\n </div>\n </div>\n </div>\n )}\n\n {delegations.length > 0 ? (\n <div className=\"space-y-4\">\n {delegations.map((delegation) => (\n <div\n key={delegation.id}\n className=\"rounded-card border border-border-seam bg-bg-surface p-4 space-y-4 shadow-[var(--shadow-pop)]\"\n >\n <div className=\"flex items-start justify-between\">\n <div className=\"flex items-start gap-3\">\n {delegation.status === \"ACTIVE\" && (\n <div onClick={(event) => event.stopPropagation()}>\n <SelectionCheckbox\n checked={selectedDelegationIds.has(delegation.id)}\n onChange={(checked) =>\n onToggleSelectDelegation(delegation.id, checked)\n }\n ariaLabel={`Select delegation ${delegation.id}`}\n className=\"mt-1\"\n />\n </div>\n )}\n <div>\n <div className=\"flex items-center gap-2\">\n <h3 className=\"font-medium\">\n Delegation #{delegation.id.slice(0, 8)}\n </h3>\n <span\n className={cn(\n \"rounded-full px-2 py-0.5 text-xs font-medium\",\n DELEGATION_STATUS_STYLES[delegation.status],\n )}\n >\n {delegation.status}\n </span>\n </div>\n <p className=\"text-sm text-text-secondary mt-1\">\n {tr(\"devportal.granted\", \"Granted\")}{\" \"}\n {new Date(delegation.grantedAt).toLocaleDateString()}{\" \"}\n {tr(\"devportal.by\", \"by\")}{\" \"}\n {delegation.grantedBy === delegation.userId\n ? tr(\"devportal.you\", \"you\")\n : delegation.grantedBy.slice(0, 8)}\n </p>\n </div>\n </div>\n {delegation.status === \"ACTIVE\" && (\n <button\n onClick={() => onRevokeDelegation(delegation.id)}\n className=\"inline-flex items-center gap-1.5 rounded-md border border-border-subtle px-3 py-1.5 text-xs font-medium text-status-error-text hover:bg-status-error-bg-subtle transition-colors\"\n >\n <XCircle size={14} />\n {tr(\"devportal.revoke\", \"Revoke\")}\n </button>\n )}\n </div>\n\n {/* Scopes */}\n <div>\n <p className=\"text-xs text-text-secondary mb-2\">\n {tr(\"devportal.grantedScopes\", \"Granted Scopes\")}\n </p>\n <div className=\"flex flex-wrap gap-2\">\n {delegation.scopes.map((scope) => (\n <span\n key={scope}\n className=\"rounded-full bg-status-success-bg-subtle px-2 py-0.5 text-xs text-status-success-text\"\n >\n {scope}\n </span>\n ))}\n </div>\n </div>\n\n {/* Workspace IDs */}\n {delegation.workspaceIds.length > 0 && (\n <div>\n <p className=\"text-xs text-text-secondary mb-2\">\n {tr(\"devportal.workspaceScope\", \"Workspace Scope\")}\n </p>\n <div className=\"flex flex-wrap gap-2\">\n {delegation.workspaceIds.map((wsId) => (\n <code\n key={wsId}\n className=\"rounded bg-bg-sunken px-2 py-0.5 text-xs\"\n >\n {wsId}\n </code>\n ))}\n </div>\n </div>\n )}\n\n {/* Metadata */}\n <div className=\"flex items-center gap-4 text-xs text-text-secondary\">\n {delegation.expiresAt && (\n <span className=\"flex items-center gap-1\">\n <Clock size={12} />\n {tr(\"devportal.expires\", \"Expires\")}{\" \"}\n {new Date(delegation.expiresAt).toLocaleDateString()}\n </span>\n )}\n {!delegation.expiresAt && delegation.status === \"ACTIVE\" && (\n <span className=\"flex items-center gap-1\">\n <CheckCircle\n size={12}\n className=\"text-status-success-text\"\n />\n {tr(\"devportal.noExpiration\", \"No expiration\")}\n </span>\n )}\n {delegation.revokedAt && (\n <span className=\"flex items-center gap-1\">\n <XCircle size={12} className=\"text-status-error-text\" />\n {tr(\"devportal.revoked\", \"Revoked\")}{\" \"}\n {new Date(delegation.revokedAt).toLocaleDateString()}\n </span>\n )}\n </div>\n </div>\n ))}\n </div>\n ) : (\n <EmptyState\n illustration=\"empty-people\"\n icon={<Users size={32} />}\n title={tr(\"devportal.noDelegations\", \"No delegations\")}\n description={tr(\n \"devportal.noDelegationsDescription\",\n \"Grant a delegation to allow this app to act on your behalf\",\n )}\n action={\n <button\n onClick={onGrantDelegation}\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\"\n >\n <Plus size={16} />\n {tr(\"devportal.grantDelegation\", \"Grant Delegation\")}\n </button>\n }\n />\n )}\n </div>\n );\n};\n\n// =============================================================================\n// ANALYTICS TAB\n// =============================================================================\n\nconst AnalyticsTab: FC<{ analytics: ApplicationAnalytics[] }> = ({\n analytics,\n}) => {\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 const latest = analytics[0];\n const previous = analytics[1];\n\n const calculateTrend = (current: number, prev: number) => {\n if (!prev) return 0;\n return ((current - prev) / prev) * 100;\n };\n\n return (\n <div className=\"space-y-6\">\n {/* Summary Stats */}\n <div className=\"grid gap-4 sm:grid-cols-4\">\n <StatCard\n label={tr(\"devportal.activeUsers\", \"Active Users\")}\n value={latest?.activeUsers.toLocaleString() || \"0\"}\n trend={\n previous\n ? calculateTrend(latest.activeUsers, previous.activeUsers)\n : undefined\n }\n />\n <StatCard\n label={tr(\"devportal.apiCalls\", \"API Calls\")}\n value={latest ? `${(latest.apiCalls / 1000).toFixed(1)}K` : \"0\"}\n trend={\n previous\n ? calculateTrend(latest.apiCalls, previous.apiCalls)\n : undefined\n }\n />\n <StatCard\n label={tr(\"devportal.avgResponseTime\", \"Avg Response Time\")}\n value={\n latest?.avgResponseTime\n ? `${latest.avgResponseTime}ms`\n : tr(\"devportal.notAvailable\", \"N/A\")\n }\n trend={\n previous && latest?.avgResponseTime\n ? -calculateTrend(\n latest.avgResponseTime,\n previous.avgResponseTime || 1,\n )\n : undefined\n }\n />\n <StatCard\n label={tr(\"devportal.errorRate\", \"Error Rate\")}\n value={\n latest && latest.apiCalls > 0\n ? `${((latest.errors / latest.apiCalls) * 100).toFixed(2)}%`\n : \"0%\"\n }\n trend={\n previous && latest && latest.apiCalls > 0 && previous.apiCalls > 0\n ? -calculateTrend(\n latest.errors / latest.apiCalls,\n previous.errors / previous.apiCalls,\n )\n : undefined\n }\n />\n </div>\n\n {/* Daily breakdown */}\n <PageSection title={tr(\"devportal.dailyBreakdown\", \"Daily Breakdown\")}>\n {analytics.length > 0 ? (\n <DataTable\n data={analytics}\n keyField=\"id\"\n columns={[\n {\n key: \"date\",\n header: tr(\"devportal.date\", \"Date\"),\n render: (item) => new Date(item.date).toLocaleDateString(),\n },\n {\n key: \"activeUsers\",\n header: tr(\"devportal.activeUsers\", \"Active Users\"),\n render: (item) => item.activeUsers.toLocaleString(),\n },\n {\n key: \"newUsers\",\n header: tr(\"devportal.newUsers\", \"New Users\"),\n render: (item) => item.newUsers.toLocaleString(),\n },\n {\n key: \"apiCalls\",\n header: tr(\"devportal.apiCalls\", \"API Calls\"),\n render: (item) => item.apiCalls.toLocaleString(),\n },\n {\n key: \"errors\",\n header: tr(\"devportal.errors\", \"Errors\"),\n render: (item) => item.errors.toLocaleString(),\n },\n {\n key: \"avgResponseTime\",\n header: tr(\"devportal.avgResponse\", \"Avg Response\"),\n render: (item) =>\n item.avgResponseTime\n ? `${item.avgResponseTime}ms`\n : tr(\"devportal.notAvailable\", \"N/A\"),\n },\n {\n key: \"sessions\",\n header: tr(\"devportal.sessions\", \"Sessions\"),\n render: (item) => item.sessions.toLocaleString(),\n },\n ]}\n />\n ) : (\n <EmptyState\n illustration=\"empty-data\"\n icon={<BarChart3 size={32} />}\n title={tr(\"devportal.noAnalyticsData\", \"No analytics data\")}\n description={tr(\n \"devportal.noAnalyticsDataDescription\",\n \"Analytics data will appear here once the application starts receiving traffic.\",\n )}\n />\n )}\n </PageSection>\n </div>\n );\n};\n\n// =============================================================================\n// API PLAYGROUND TAB\n// =============================================================================\n\nconst SAMPLE_QUERY = `# Sample query — replace with your own\n# Note: introspection is disabled on this gateway for security.\n# Use a real query from your app's API schema instead.\nquery GetCurrentUser {\n currentUser {\n id\n email\n }\n}`;\n\nconst ApiPlaygroundTab: FC<{ app: Application }> = ({ app }) => {\n const { apiGatewayUrl, workspacesGatewayUrl, authToken } = useDevportal();\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 const [query, setQuery] = useState(SAMPLE_QUERY);\n const [variables, setVariables] = useState(\"{}\");\n const [response, setResponse] = useState<string>(\"\");\n const [loading, setLoading] = useState(false);\n const [endpoint, setEndpoint] = useState(\n `${apiGatewayUrl || \"https://gw-global.local.burdenoff.com\"}/global/graphql`,\n );\n const [bearerToken, setBearerToken] = useState(authToken || \"\");\n const [showAuthHelp, setShowAuthHelp] = useState(false);\n\n const handleExecute = useCallback(async () => {\n setLoading(true);\n setResponse(\"\");\n try {\n let parsedVars = {};\n try {\n parsedVars = JSON.parse(variables);\n } catch {\n setResponse(\n JSON.stringify({ error: \"Invalid JSON in variables\" }, null, 2),\n );\n setLoading(false);\n return;\n }\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n if (bearerToken) {\n headers[\"Authorization\"] = `Bearer ${bearerToken}`;\n }\n\n const res = await fetch(endpoint, {\n method: \"POST\",\n headers,\n body: JSON.stringify({ query, variables: parsedVars }),\n });\n\n const data = await res.json();\n setResponse(JSON.stringify(data, null, 2));\n } catch (err) {\n setResponse(\n JSON.stringify(\n { error: err instanceof Error ? err.message : \"Request failed\" },\n null,\n 2,\n ),\n );\n } finally {\n setLoading(false);\n }\n }, [query, variables, endpoint, bearerToken]);\n\n const handleAutoFillCredentials = useCallback(() => {\n if (authToken) {\n setBearerToken(authToken);\n }\n setShowAuthHelp(true);\n }, [authToken]);\n\n return (\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h3 className=\"text-lg font-semibold\">\n {tr(\"devportal.apiPlayground\", \"API Playground\")}\n </h3>\n <p className=\"text-sm text-text-secondary\">\n {tr(\n \"devportal.apiPlaygroundDescription\",\n \"Test GraphQL APIs in the context of\",\n )}{\" \"}\n <strong>{app.name}</strong>\n {app.appId && (\n <span className=\"ml-1 text-xs text-text-secondary\">\n (OAuth App: {app.appId.slice(0, 8)}...)\n </span>\n )}\n </p>\n </div>\n <button\n onClick={handleAutoFillCredentials}\n className=\"flex items-center gap-2 rounded-md border px-3 py-1.5 text-sm font-medium hover:bg-accent transition-colors\"\n >\n <Key size={14} />\n {tr(\"devportal.autoFillCredentials\", \"Auto-fill Credentials\")}\n </button>\n </div>\n\n {showAuthHelp && (\n <div className=\"rounded-lg border bg-status-info-bg-subtle p-4 text-sm space-y-2\">\n <p className=\"font-medium text-status-info-text\">\n {tr(\"devportal.authenticationGuide\", \"Authentication Guide\")}\n </p>\n <p className=\"text-status-info-text\">\n {tr(\n \"devportal.authenticationGuideText\",\n \"Your current session token has been filled in. For app-level authentication (Client Credentials flow), use the\",\n )}{\" \"}\n <strong>{tr(\"devportal.oauthClientsTab\", \"OAuth Clients\")}</strong>{\" \"}\n {tr(\n \"devportal.authenticationGuideText2\",\n \"tab to get the app's clientId and clientSecret, then call:\",\n )}\n </p>\n <pre className=\"rounded bg-status-info-bg-subtle p-2 text-xs overflow-x-auto text-status-info-text\">\n {`mutation {\n authenticateApp(input: {\n clientId: \"<your-client-id>\"\n clientSecret: \"<your-client-secret>\"\n scopes: []\n }) {\n accessToken\n tokenType\n expiresIn\n }\n}`}\n </pre>\n <p className=\"text-status-info-text\">\n {tr(\"devportal.useReturnedAccessToken\", \"Use the returned\")}{\" \"}\n <code className=\"bg-status-info-bg-subtle px-1 rounded\">\n accessToken\n </code>{\" \"}\n {tr(\"devportal.asBearerToken\", \"as the Bearer token below.\")}\n </p>\n <button\n onClick={() => setShowAuthHelp(false)}\n className=\"text-xs text-accent-blue hover:underline\"\n >\n {tr(\"devportal.dismiss\", \"Dismiss\")}\n </button>\n </div>\n )}\n\n {/* Endpoint */}\n <div>\n <label className=\"block text-sm font-medium mb-1\">\n {tr(\"devportal.gatewayEndpoint\", \"Gateway Endpoint\")}\n </label>\n <div className=\"flex gap-2\">\n <input\n type=\"text\"\n value={endpoint}\n onChange={(e) => setEndpoint(e.target.value)}\n className=\"flex-1 rounded-md border px-3 py-2 text-sm font-mono bg-bg-surface\"\n />\n <select\n onChange={(e) => setEndpoint(e.target.value)}\n className=\"rounded-md border px-3 py-2 text-sm bg-bg-surface\"\n value={endpoint}\n >\n <option\n value={`${apiGatewayUrl || \"https://gw-global.local.burdenoff.com\"}/global/graphql`}\n >\n {tr(\"devportal.globalGateway\", \"Global Gateway\")}\n </option>\n <option\n value={`${workspacesGatewayUrl || \"https://gw-wspace.local.burdenoff.com\"}/workspaces/graphql`}\n >\n {tr(\"devportal.workspaceGateway\", \"Workspace Gateway\")}\n </option>\n </select>\n </div>\n </div>\n\n {/* Bearer Token */}\n <div>\n <label className=\"block text-sm font-medium mb-1\">\n {tr(\"devportal.bearerToken\", \"Bearer Token\")}\n </label>\n <input\n type=\"password\"\n value={bearerToken}\n onChange={(e) => setBearerToken(e.target.value)}\n placeholder={tr(\n \"devportal.pasteAccessToken\",\n \"Paste access token here...\",\n )}\n className=\"w-full rounded-md border px-3 py-2 text-sm font-mono bg-bg-surface\"\n />\n </div>\n\n {/* Query + Variables side by side */}\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-4\">\n <div>\n <label className=\"block text-sm font-medium mb-1\">\n {tr(\"devportal.query\", \"Query\")}\n </label>\n <textarea\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n className=\"w-full h-64 rounded-md border px-3 py-2 text-sm font-mono bg-bg-surface resize-y\"\n spellCheck={false}\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium mb-1\">\n {tr(\"devportal.variablesJson\", \"Variables (JSON)\")}\n </label>\n <textarea\n value={variables}\n onChange={(e) => setVariables(e.target.value)}\n className=\"w-full h-64 rounded-md border px-3 py-2 text-sm font-mono bg-bg-surface resize-y\"\n spellCheck={false}\n />\n </div>\n </div>\n\n {/* Execute */}\n <button\n onClick={handleExecute}\n disabled={loading}\n className=\"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 transition-colors disabled:opacity-50\"\n >\n {loading ? (\n <Loader2 size={16} className=\"animate-spin\" />\n ) : (\n <ExternalLink size={16} />\n )}\n {loading\n ? tr(\"devportal.executing\", \"Executing...\")\n : tr(\"devportal.executeQuery\", \"Execute Query\")}\n </button>\n\n {/* Response */}\n {response && (\n <div>\n <label className=\"block text-sm font-medium mb-1\">\n {tr(\"devportal.response\", \"Response\")}\n </label>\n <pre className=\"w-full max-h-96 overflow-auto rounded-md border bg-bg-sunken p-4 text-xs font-mono\">\n {response}\n </pre>\n </div>\n )}\n </div>\n );\n};\n\n// =============================================================================\n// IMAGE UPLOAD COMPONENTS\n// =============================================================================\n\ninterface ImageUploadFieldProps {\n label: string;\n value: string;\n onChange: (url: string) => void;\n hint?: string;\n accept?: string;\n aspectClass?: string; // tailwind class for the preview container ratio\n upload: (file: File) => Promise<{ downloadUrl: string }>;\n uploading: boolean;\n progress: number;\n error: string | null;\n}\n\nconst ImageUploadField: FC<ImageUploadFieldProps> = ({\n label,\n value,\n onChange,\n hint,\n accept = \"image/png,image/jpeg,image/webp,image/gif,image/svg+xml\",\n aspectClass = \"aspect-square\",\n upload,\n uploading,\n progress,\n error,\n}) => {\n const inputRef = useRef<HTMLInputElement>(null);\n const [imgBroken, setImgBroken] = useState(false);\n const prevValue = useRef(value);\n if (prevValue.current !== value) {\n prevValue.current = value;\n if (imgBroken) setImgBroken(false);\n }\n\n const handleFile = useCallback(\n async (file: File) => {\n try {\n const result = await upload(file);\n onChange(result.downloadUrl);\n } catch {\n // error shown via error prop\n }\n },\n [upload, onChange],\n );\n\n return (\n <div className=\"space-y-1.5\">\n <label className=\"text-sm font-medium\">{label}</label>\n <div className=\"flex gap-3 items-start\">\n {/* Preview */}\n <div\n className={cn(\n \"relative shrink-0 w-20 rounded-lg border border-border-subtle bg-bg-sunken overflow-hidden flex items-center justify-center\",\n aspectClass,\n )}\n >\n {value && !imgBroken ? (\n <img\n src={value}\n alt={label}\n className=\"w-full h-full object-cover\"\n onError={() => setImgBroken(true)}\n />\n ) : (\n <Upload size={18} className=\"text-text-secondary opacity-40\" />\n )}\n {uploading && (\n <div className=\"absolute inset-0 bg-bg-overlay flex flex-col items-center justify-center gap-1\">\n <Loader2 size={14} className=\"animate-spin text-white\" />\n <span className=\"text-white text-xs\">{progress}%</span>\n </div>\n )}\n </div>\n {/* URL input + upload button */}\n <div className=\"flex-1 space-y-1.5\">\n <input\n type=\"url\"\n value={value}\n onChange={(e) => onChange(e.target.value)}\n placeholder=\"https://...\"\n className=\"w-full rounded-md border border-border-subtle bg-bg-input px-3 py-1.5 text-sm placeholder:text-text-placeholder focus:outline-none focus:ring-2 focus:ring-primary/30\"\n />\n <input\n ref={inputRef}\n type=\"file\"\n accept={accept}\n className=\"hidden\"\n onChange={(e) => {\n const f = e.target.files?.[0];\n if (f) void handleFile(f);\n e.target.value = \"\";\n }}\n />\n <button\n type=\"button\"\n disabled={uploading}\n onClick={() => inputRef.current?.click()}\n className=\"inline-flex items-center gap-1.5 rounded-md border px-2.5 py-1 text-xs font-medium hover:bg-bg-sunken transition-colors disabled:opacity-50\"\n >\n <Upload size={11} />\n {uploading ? `Uploading… ${progress}%` : \"Upload image\"}\n </button>\n {error && <p className=\"text-xs text-status-error-text\">{error}</p>}\n </div>\n </div>\n {hint && <p className=\"text-xs text-text-secondary\">{hint}</p>}\n </div>\n );\n};\n\ninterface ScreenshotGalleryProps {\n urls: string[];\n onChange: (urls: string[]) => void;\n upload: (file: File) => Promise<{ downloadUrl: string }>;\n uploading: boolean;\n progress: number;\n error: string | null;\n}\n\nconst ScreenshotGallery: FC<ScreenshotGalleryProps> = ({\n urls,\n onChange,\n upload,\n uploading,\n progress,\n error,\n}) => {\n const inputRef = useRef<HTMLInputElement>(null);\n const [urlInput, setUrlInput] = useState(\"\");\n\n const handleFile = useCallback(\n async (file: File) => {\n try {\n const result = await upload(file);\n onChange([...urls, result.downloadUrl]);\n } catch {\n // error shown via error prop\n }\n },\n [upload, onChange, urls],\n );\n\n const addUrl = () => {\n const trimmed = urlInput.trim();\n if (trimmed && !urls.includes(trimmed)) {\n onChange([...urls, trimmed]);\n setUrlInput(\"\");\n }\n };\n\n const remove = (idx: number) => {\n onChange(urls.filter((_, i) => i !== idx));\n };\n\n return (\n <div className=\"space-y-2\">\n <div className=\"flex flex-col gap-0.5\">\n <label className=\"text-sm font-medium\">Screenshots</label>\n <p className=\"text-xs text-text-muted\">\n Shown in the horizontal preview strip below the hero — wide landscape\n proportions work best (16:9)\n </p>\n </div>\n <div className=\"flex flex-wrap gap-3\">\n {urls.map((url, idx) => (\n <div\n key={idx}\n className=\"relative group w-36 aspect-video rounded-lg border border-border-subtle overflow-hidden bg-bg-sunken\"\n >\n <img\n src={url}\n alt={`Screenshot ${idx + 1}`}\n className=\"w-full h-full object-cover\"\n />\n <button\n type=\"button\"\n onClick={() => remove(idx)}\n className=\"absolute top-1 right-1 rounded-full bg-bg-overlay text-white p-0.5 opacity-0 group-hover:opacity-100 transition-opacity\"\n >\n <X size={12} />\n </button>\n </div>\n ))}\n {/* Upload slot */}\n <button\n type=\"button\"\n disabled={uploading}\n onClick={() => inputRef.current?.click()}\n className={cn(\n \"w-36 aspect-video rounded-lg border-2 border-dashed border-border-subtle flex flex-col items-center justify-center gap-1.5 text-text-secondary hover:border-border-strong hover:bg-bg-sunken transition-colors disabled:opacity-50\",\n )}\n >\n {uploading ? (\n <>\n <Loader2 size={18} className=\"animate-spin text-primary\" />\n <span className=\"text-xs\">{progress}%</span>\n </>\n ) : (\n <>\n <Upload size={18} />\n <span className=\"text-xs\">Add screenshot</span>\n </>\n )}\n </button>\n </div>\n {/* URL paste row */}\n <div className=\"flex gap-2\">\n <input\n type=\"url\"\n value={urlInput}\n onChange={(e) => setUrlInput(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") {\n e.preventDefault();\n addUrl();\n }\n }}\n placeholder=\"https://... paste a screenshot URL\"\n className=\"flex-1 rounded-md border border-border-subtle bg-bg-input px-3 py-1.5 text-sm placeholder:text-text-placeholder focus:outline-none focus:ring-2 focus:ring-primary/30\"\n />\n <button\n type=\"button\"\n onClick={addUrl}\n disabled={!urlInput.trim()}\n className=\"inline-flex items-center gap-1.5 rounded-md border px-2.5 py-1.5 text-xs font-medium hover:bg-bg-sunken transition-colors disabled:opacity-50\"\n >\n Add\n </button>\n </div>\n <input\n ref={inputRef}\n type=\"file\"\n accept=\"image/png,image/jpeg,image/webp,image/gif\"\n className=\"hidden\"\n onChange={(e) => {\n const f = e.target.files?.[0];\n if (f) void handleFile(f);\n e.target.value = \"\";\n }}\n />\n {error && <p className=\"text-xs text-status-error-text\">{error}</p>}\n </div>\n );\n};\n\n// =============================================================================\n// STORE LISTING TAB\n// =============================================================================\n\ninterface ManifestIdentity {\n version: string;\n displayName: string;\n}\n\ninterface ManifestInstall {\n type: string;\n url?: string;\n packageName?: string;\n registryUrl?: string;\n}\n\ninterface ManifestDigital {\n install: ManifestInstall;\n}\n\ninterface ManifestCompatibility {\n minPlatformVersion: string;\n}\n\ninterface StoreManifest {\n manifestVersion: string;\n itemType?: string;\n identity: ManifestIdentity;\n digital?: ManifestDigital;\n jsonContent?: string;\n permissions: string[];\n compatibility: ManifestCompatibility;\n}\n\ninterface StoreListingFormData {\n // Store Presentation\n iconUrl: string;\n bannerUrl: string;\n videoUrl: string;\n shortDescription: string;\n description: string;\n screenshotsText: string;\n // Links & Policies\n websiteUrl: string;\n documentationUrl: string;\n githubUrl: string;\n supportUrl: string;\n privacyPolicyUrl: string;\n termsOfServiceUrl: string;\n // Manifest\n manifestItemType: string;\n manifestDisplayName: string;\n manifestVersion: string;\n manifestInstallType: string;\n manifestPackageName: string;\n manifestRegistryUrl: string;\n manifestPermissionsText: string;\n manifestMinPlatformVersion: string;\n // JSON-only content (workflow / template)\n manifestJsonContent: string;\n}\n\n/** Item types whose entire payload IS a JSON document — no zip or binary needed. */\nconst JSON_ONLY_ITEM_TYPES = new Set([\"workflow\", \"template\"]);\n\nconst PRICING_TYPE_OPTIONS = [\n { value: \"FREE\", label: \"Free\" },\n { value: \"PAID\", label: \"Paid\" },\n];\n\nconst CURRENCY_OPTIONS = [\n { value: \"USD\", label: \"USD — US Dollar\" },\n { value: \"EUR\", label: \"EUR — Euro\" },\n { value: \"GBP\", label: \"GBP — British Pound\" },\n { value: \"INR\", label: \"INR — Indian Rupee\" },\n { value: \"CAD\", label: \"CAD — Canadian Dollar\" },\n { value: \"AUD\", label: \"AUD — Australian Dollar\" },\n { value: \"SGD\", label: \"SGD — Singapore Dollar\" },\n { value: \"JPY\", label: \"JPY — Japanese Yen\" },\n];\n\nconst ITEM_TYPE_OPTIONS_BY_APP_TYPE: Record<\n string,\n { value: string; label: string }[]\n> = {\n NODE: [\n { value: \"node\", label: \"Node\" },\n { value: \"agent\", label: \"Agent\" },\n { value: \"parser\", label: \"Parser\" },\n { value: \"datasink\", label: \"Data Sink\" },\n { value: \"component\", label: \"Component\" },\n ],\n WORKFLOW: [\n { value: \"workflow\", label: \"Workflow\" },\n { value: \"template\", label: \"Template\" },\n ],\n APP: [\n { value: \"app\", label: \"App\" },\n { value: \"integration\", label: \"Integration\" },\n { value: \"extension\", label: \"Extension\" },\n { value: \"widget\", label: \"Widget\" },\n { value: \"dashboard\", label: \"Dashboard\" },\n { value: \"console\", label: \"Console\" },\n { value: \"botapp\", label: \"Bot App\" },\n { value: \"vibemodule\", label: \"Vibe Module\" },\n { value: \"theme\", label: \"Theme\" },\n { value: \"plugin\", label: \"Plugin\" },\n ],\n};\n\nconst DEFAULT_ITEM_TYPE: Record<string, string> = {\n NODE: \"node\",\n WORKFLOW: \"workflow\",\n APP: \"app\",\n};\n\nconst INSTALL_TYPE_OPTIONS = [\n { value: \"zip\", label: \"zip\" },\n { value: \"builtin\", label: \"builtin\" },\n];\n\nfunction buildInitialFormData(app: Application): StoreListingFormData {\n const manifest = (app.manifest ?? {}) as Record<string, unknown>;\n const identity = (manifest.identity ?? {}) as Record<string, unknown>;\n const digital = (manifest.digital ?? {}) as Record<string, unknown>;\n const install = (digital.install ?? {}) as Record<string, unknown>;\n const compatibility = (manifest.compatibility ?? {}) as Record<\n string,\n unknown\n >;\n const permissions = Array.isArray(manifest.permissions)\n ? (manifest.permissions as string[])\n : [];\n\n const screenshots = Array.isArray(app.screenshots)\n ? (app.screenshots as string[]).join(\"\\n\")\n : \"\";\n\n return {\n iconUrl: app.iconUrl ?? \"\",\n bannerUrl: app.bannerUrl ?? \"\",\n videoUrl: app.videoUrl ?? \"\",\n shortDescription: app.shortDescription ?? \"\",\n description: app.description ?? \"\",\n screenshotsText: screenshots,\n websiteUrl: app.websiteUrl ?? \"\",\n documentationUrl: app.documentationUrl ?? \"\",\n githubUrl: app.githubUrl ?? \"\",\n supportUrl: app.supportUrl ?? \"\",\n privacyPolicyUrl: app.privacyPolicyUrl ?? \"\",\n termsOfServiceUrl: app.termsOfServiceUrl ?? \"\",\n manifestItemType:\n typeof manifest.itemType === \"string\"\n ? manifest.itemType\n : (DEFAULT_ITEM_TYPE[app.appType] ?? \"\"),\n manifestDisplayName:\n typeof identity.displayName === \"string\"\n ? identity.displayName\n : (app.name ?? \"\"),\n manifestVersion:\n typeof identity.version === \"string\" ? identity.version : \"\",\n manifestInstallType:\n typeof install.type === \"string\" ? install.type : \"zip\",\n manifestPackageName: \"\",\n manifestRegistryUrl:\n typeof install.url === \"string\"\n ? install.url\n : typeof install.registryUrl === \"string\"\n ? install.registryUrl\n : \"\",\n manifestPermissionsText: permissions.join(\"\\n\"),\n manifestMinPlatformVersion:\n typeof compatibility.minPlatformVersion === \"string\"\n ? compatibility.minPlatformVersion\n : \"\",\n manifestJsonContent:\n typeof manifest.jsonContent === \"string\"\n ? manifest.jsonContent\n : typeof manifest.content === \"string\"\n ? manifest.content\n : \"\",\n };\n}\n\nconst StoreListingTab: FC<{\n app: Application;\n versionCount?: number;\n isPackageApp?: boolean;\n pricingDone?: boolean;\n onNavigateToVersions?: () => void;\n onNavigateToPricing?: () => void;\n onNavigateToSubmission?: () => void;\n}> = ({\n app,\n versionCount = 0,\n isPackageApp = false,\n pricingDone = false,\n onNavigateToVersions,\n onNavigateToPricing,\n onNavigateToSubmission,\n}) => {\n const { workspacesGatewayUrl, authToken, workspaceId, getWorkspaceToken } =\n useDevportal();\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 [formData, setFormData] = useState<StoreListingFormData>(() =>\n buildInitialFormData(app),\n );\n const [isSaving, setIsSaving] = useState(false);\n const [saveResult, setSaveResult] = useState<\"success\" | \"error\" | null>(\n null,\n );\n // Tracks the form state as it exists on the server (last save or initial load).\n // isDirty compares current formData against this; Save is disabled when not dirty.\n const serverFormData = useRef<StoreListingFormData>(\n buildInitialFormData(app),\n );\n const appRef = useRef(app);\n appRef.current = app;\n\n const isDirty =\n JSON.stringify(formData) !== JSON.stringify(serverFormData.current);\n\n const [updateApplication] = useUpdateApplicationMutation();\n\n // Reset form only when navigating to a different app (not on every refetch)\n useEffect(() => {\n const initial = buildInitialFormData(appRef.current);\n setFormData(initial);\n serverFormData.current = initial;\n setSaveResult(null);\n }, [app.id]);\n\n const handleChange = (field: keyof StoreListingFormData, value: string) => {\n setFormData((prev) => ({ ...prev, [field]: value }));\n setSaveResult(null);\n };\n\n const isFormValid =\n formData.shortDescription.trim().length > 0 &&\n formData.privacyPolicyUrl.trim().length > 0 &&\n formData.termsOfServiceUrl.trim().length > 0;\n\n const handleSave = async () => {\n setIsSaving(true);\n setSaveResult(null);\n try {\n const screenshotUrls = formData.screenshotsText\n .split(\"\\n\")\n .map((s) => s.trim())\n .filter(Boolean);\n\n const permissions = formData.manifestPermissionsText\n .split(\"\\n\")\n .map((s) => s.trim())\n .filter(Boolean);\n\n const isJsonOnly = JSON_ONLY_ITEM_TYPES.has(formData.manifestItemType);\n\n // Build manifest by merging existing app.manifest with form values\n const baseManifest = (app.manifest ?? {}) as Record<string, unknown>;\n const updatedManifest: StoreManifest = {\n manifestVersion:\n typeof baseManifest.manifestVersion === \"string\"\n ? baseManifest.manifestVersion\n : \"1.0\",\n itemType: formData.manifestItemType || undefined,\n identity: {\n version: formData.manifestVersion || \"1.0.0\",\n displayName: formData.manifestDisplayName,\n },\n ...(isJsonOnly\n ? { jsonContent: formData.manifestJsonContent || undefined }\n : {\n digital: {\n install: {\n type: formData.manifestInstallType,\n ...(formData.manifestInstallType === \"zip\" &&\n formData.manifestRegistryUrl\n ? { url: formData.manifestRegistryUrl }\n : {}),\n },\n },\n }),\n permissions,\n compatibility: {\n minPlatformVersion: formData.manifestMinPlatformVersion,\n },\n };\n\n await updateApplication({\n variables: {\n id: app.id,\n input: {\n iconUrl: formData.iconUrl || null,\n bannerUrl: formData.bannerUrl || null,\n videoUrl: formData.videoUrl || null,\n shortDescription: formData.shortDescription || null,\n description: formData.description || null,\n screenshots:\n screenshotUrls.length > 0\n ? (screenshotUrls as unknown as Record<string, unknown>)\n : null,\n websiteUrl: formData.websiteUrl || null,\n documentationUrl: formData.documentationUrl || null,\n githubUrl: formData.githubUrl || null,\n supportUrl: formData.supportUrl || null,\n privacyPolicyUrl: formData.privacyPolicyUrl || null,\n termsOfServiceUrl: formData.termsOfServiceUrl || null,\n manifest: updatedManifest as unknown as Record<string, unknown>,\n },\n },\n });\n void nativeNotify(\"success\");\n setSaveResult(\"success\");\n // Mark current values as the new clean server state so isDirty = false\n serverFormData.current = formData;\n } catch {\n void nativeNotify(\"error\");\n setSaveResult(\"error\");\n } finally {\n setIsSaving(false);\n }\n };\n\n const {\n upload: uploadAsset,\n uploading: iconUploading,\n progress: iconProgress,\n error: iconUploadError,\n } = usePackageUpload(\n workspacesGatewayUrl,\n authToken,\n workspaceId,\n getWorkspaceToken,\n \"/DevPortal/Assets\",\n );\n const {\n upload: uploadBanner,\n uploading: bannerUploading,\n progress: bannerProgress,\n error: bannerUploadError,\n } = usePackageUpload(\n workspacesGatewayUrl,\n authToken,\n workspaceId,\n getWorkspaceToken,\n \"/DevPortal/Assets\",\n );\n const {\n upload: uploadScreenshot,\n uploading: screenshotUploading,\n progress: screenshotProgress,\n error: screenshotUploadError,\n } = usePackageUpload(\n workspacesGatewayUrl,\n authToken,\n workspaceId,\n getWorkspaceToken,\n \"/DevPortal/Assets\",\n );\n\n const isJsonOnlyType = JSON_ONLY_ITEM_TYPES.has(formData.manifestItemType);\n\n const isSubmitted = app.status === \"SUBMITTED\";\n const isPublished = app.status === \"PUBLISHED\";\n\n return (\n <div className=\"space-y-8 max-w-3xl\">\n {/* ── Status banner ─────────────────────────────────────── */}\n {isPublished ? (\n <div className=\"flex items-start gap-3 rounded-lg border border-success/30 bg-success/10 px-4 py-3\">\n <CheckCircle size={16} className=\"text-success mt-0.5 shrink-0\" />\n <div className=\"text-sm\">\n <span className=\"font-medium text-success\">\n {tr(\"devportal.storeListing.published\", \"Published\")}\n </span>\n {app.publishedAt && (\n <span className=\"text-text-secondary ml-2\">\n {tr(\"devportal.storeListing.since\", \"since\")}{\" \"}\n {new Date(app.publishedAt).toLocaleDateString()}\n </span>\n )}\n </div>\n </div>\n ) : isSubmitted ? (\n <div className=\"flex items-center justify-between gap-3 rounded-lg border border-primary/30 bg-action-primary-bg/5 px-4 py-3\">\n <div className=\"flex items-start gap-3\">\n <Clock size={16} className=\"text-primary mt-0.5 shrink-0\" />\n <div className=\"text-sm\">\n <span className=\"font-medium text-primary\">\n {tr(\n \"devportal.storeListing.underReview\",\n \"Submitted for review\",\n )}\n </span>\n {app.submittedAt && (\n <span className=\"text-text-secondary ml-2\">\n {new Date(app.submittedAt).toLocaleDateString()}\n </span>\n )}\n {app.reviewStatus && (\n <span className=\"text-text-secondary ml-2\">\n · {app.reviewStatus}\n </span>\n )}\n </div>\n </div>\n {onNavigateToSubmission && (\n <button\n type=\"button\"\n onClick={onNavigateToSubmission}\n className=\"shrink-0 text-xs text-primary hover:underline font-medium flex items-center gap-1\"\n >\n {tr(\"devportal.viewStatus\", \"View Status\")}\n <ExternalLink size={12} />\n </button>\n )}\n </div>\n ) : (\n <div className=\"flex items-start gap-3 rounded-lg border border-warning/30 bg-warning/5 px-4 py-3\">\n <AlertCircle size={16} className=\"text-warning mt-0.5 shrink-0\" />\n <div className=\"text-sm\">\n <span className=\"font-medium text-warning\">\n {tr(\"devportal.storeListing.draft\", \"Draft\")}\n </span>\n <span className=\"text-text-secondary ml-2\">\n {tr(\n \"devportal.storeListing.draftHint\",\n \"Complete your store listing and submit for review to publish.\",\n )}\n </span>\n </div>\n </div>\n )}\n\n {/* ── Section 1: Package ─────────────────────────────────── */}\n <PageSection\n title={tr(\"devportal.package\", \"Package\")}\n description={tr(\n \"devportal.packageDescription\",\n \"Technical configuration — how FluidGrid installs and runs this item\",\n )}\n >\n <div className=\"space-y-6\">\n {/* Item type — fine-grained store classification within the app's broad type */}\n <SelectField\n label={tr(\"devportal.storeItemType\", \"Item Type\")}\n value={formData.manifestItemType}\n onChange={(e) => {\n const next = e.target.value;\n handleChange(\"manifestItemType\", next);\n if (JSON_ONLY_ITEM_TYPES.has(next)) {\n handleChange(\"manifestInstallType\", \"json\");\n } else if (formData.manifestInstallType === \"json\") {\n handleChange(\"manifestInstallType\", \"zip\");\n }\n }}\n options={\n ITEM_TYPE_OPTIONS_BY_APP_TYPE[app.appType] ??\n ITEM_TYPE_OPTIONS_BY_APP_TYPE[\"APP\"]!\n }\n placeholder={tr(\"devportal.selectItemType\", \"Select item type…\")}\n hint={tr(\n \"devportal.storeItemTypeHint\",\n \"Sub-category shown in the marketplace (e.g. Node vs Agent vs Parser)\",\n )}\n />\n\n {/* Identity */}\n <InputField\n label={tr(\"devportal.manifestDisplayName\", \"Display Name\")}\n value={formData.manifestDisplayName}\n onChange={(e) =>\n handleChange(\"manifestDisplayName\", e.target.value)\n }\n placeholder=\"My Awesome Node\"\n />\n\n {/* JSON editor for template types — workflow JSON lives on the Versions tab */}\n {isJsonOnlyType && app.appType !== \"WORKFLOW\" && (\n <TextareaField\n label={tr(\"devportal.jsonContent\", \"Template Definition (JSON)\")}\n value={formData.manifestJsonContent}\n onChange={(e) =>\n handleChange(\"manifestJsonContent\", e.target.value)\n }\n rows={12}\n placeholder={'{\\n \"nodes\": [],\\n \"edges\": []\\n}'}\n hint={tr(\n \"devportal.jsonContentHint\",\n \"Paste the full JSON definition. Stored and applied directly — no zip needed.\",\n )}\n />\n )}\n {isJsonOnlyType && app.appType === \"WORKFLOW\" && (\n <p className=\"text-sm text-text-secondary rounded-md bg-bg-sunken px-3 py-2\">\n The Workflow Definition (JSON) is set per version. Go to the{\" \"}\n <strong>Versions</strong> tab to add or update it.\n </p>\n )}\n </div>\n </PageSection>\n\n {/* ── Section 2: Store Presence ──────────────────────────── */}\n <PageSection\n title={tr(\"devportal.storePresentation\", \"Store Presence\")}\n description={tr(\n \"devportal.storePresentationDescription\",\n \"Visual assets and copy shown to users browsing the marketplace\",\n )}\n >\n <div className=\"space-y-5\">\n <div className=\"grid gap-5 sm:grid-cols-2\">\n <ImageUploadField\n label={tr(\"devportal.iconUrl\", \"Icon\")}\n value={formData.iconUrl}\n onChange={(url) => handleChange(\"iconUrl\", url)}\n hint={tr(\n \"devportal.iconUrlHint\",\n \"Shown in marketplace cards and search — square proportions (1:1)\",\n )}\n aspectClass=\"aspect-square\"\n upload={uploadAsset}\n uploading={iconUploading}\n progress={iconProgress}\n error={iconUploadError}\n />\n <ImageUploadField\n label={tr(\"devportal.bannerUrl\", \"Banner\")}\n value={formData.bannerUrl}\n onChange={(url) => handleChange(\"bannerUrl\", url)}\n hint={tr(\n \"devportal.bannerUrlHint\",\n \"Fills the right panel on the product page — square or portrait works best on all screen sizes (1:1)\",\n )}\n aspectClass=\"aspect-square\"\n upload={uploadBanner}\n uploading={bannerUploading}\n progress={bannerProgress}\n error={bannerUploadError}\n />\n </div>\n <InputField\n label={tr(\"devportal.videoUrl\", \"Demo Video URL\")}\n value={formData.videoUrl}\n onChange={(e) => handleChange(\"videoUrl\", e.target.value)}\n placeholder=\"https://...\"\n hint={tr(\"devportal.videoUrlHint\", \"YouTube or Vimeo embed URL\")}\n />\n <TextareaField\n label={tr(\"devportal.shortDescription\", \"Short Description\")}\n value={formData.shortDescription}\n onChange={(e) => handleChange(\"shortDescription\", e.target.value)}\n maxLength={200}\n rows={2}\n hint={`${formData.shortDescription.length}/200 · ${tr(\"devportal.shortDescHint\", \"Shown in search results and cards\")}`}\n />\n <TextareaField\n label={tr(\"devportal.longDescription\", \"Full Description\")}\n value={formData.description}\n onChange={(e) => handleChange(\"description\", e.target.value)}\n rows={5}\n hint={tr(\"devportal.fullDescHint\", \"Markdown supported\")}\n />\n <ScreenshotGallery\n urls={formData.screenshotsText\n .split(\"\\n\")\n .map((s) => s.trim())\n .filter(Boolean)}\n onChange={(urls) =>\n handleChange(\"screenshotsText\", urls.join(\"\\n\"))\n }\n upload={uploadScreenshot}\n uploading={screenshotUploading}\n progress={screenshotProgress}\n error={screenshotUploadError}\n />\n </div>\n </PageSection>\n\n {/* ── Section 3: Links & Policies ────────────────────────── */}\n <PageSection\n title={tr(\"devportal.linksPolicies\", \"Links & Policies\")}\n description={tr(\n \"devportal.linksPoliciesDescription\",\n \"External resources and legal documents — privacy policy and terms are required for store submission\",\n )}\n >\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <InputField\n label={tr(\"devportal.websiteUrl\", \"Website\")}\n value={formData.websiteUrl}\n onChange={(e) => handleChange(\"websiteUrl\", e.target.value)}\n placeholder=\"https://...\"\n />\n <InputField\n label={tr(\"devportal.documentationUrl\", \"Documentation\")}\n value={formData.documentationUrl}\n onChange={(e) => handleChange(\"documentationUrl\", e.target.value)}\n placeholder=\"https://...\"\n />\n <InputField\n label={tr(\"devportal.githubUrl\", \"GitHub\")}\n value={formData.githubUrl}\n onChange={(e) => handleChange(\"githubUrl\", e.target.value)}\n placeholder=\"https://github.com/...\"\n />\n <InputField\n label={tr(\"devportal.supportUrl\", \"Support\")}\n value={formData.supportUrl}\n onChange={(e) => handleChange(\"supportUrl\", e.target.value)}\n placeholder=\"https://...\"\n />\n <InputField\n label={`${tr(\"devportal.privacyPolicyUrl\", \"Privacy Policy\")} *`}\n value={formData.privacyPolicyUrl}\n onChange={(e) => handleChange(\"privacyPolicyUrl\", e.target.value)}\n placeholder=\"https://...\"\n hint={tr(\n \"devportal.requiredForStore\",\n \"Required for store submission\",\n )}\n />\n <InputField\n label={`${tr(\"devportal.termsOfServiceUrl\", \"Terms of Service\")} *`}\n value={formData.termsOfServiceUrl}\n onChange={(e) => handleChange(\"termsOfServiceUrl\", e.target.value)}\n placeholder=\"https://...\"\n hint={tr(\n \"devportal.requiredForStore\",\n \"Required for store submission\",\n )}\n />\n </div>\n </PageSection>\n\n {/* Save store listing + next-step hint */}\n <div className=\"border-t pt-6 space-y-3\">\n {saveResult === \"success\" && (\n <div className=\"flex items-center gap-2 rounded-md border border-success/30 bg-success/10 px-3 py-2 text-sm text-success\">\n <CheckCircle size={15} className=\"shrink-0\" />\n {tr(\n \"devportal.storeListing.savedSuccess\",\n \"Store listing saved successfully.\",\n )}\n </div>\n )}\n {saveResult === \"error\" && (\n <div className=\"flex items-center gap-2 rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive\">\n <AlertCircle size={15} className=\"shrink-0\" />\n {tr(\n \"devportal.storeListing.savedError\",\n \"Failed to save. Please try again.\",\n )}\n </div>\n )}\n <div className=\"flex flex-wrap items-center gap-3\">\n <button\n type=\"button\"\n onClick={handleSave}\n disabled={isSaving || !isFormValid || !isDirty}\n title={\n !isFormValid\n ? tr(\n \"devportal.storeListing.requiredFieldsHint\",\n \"Fill in Short Description, Privacy Policy URL, and Terms of Service URL to save\",\n )\n : !isDirty\n ? tr(\n \"devportal.storeListing.noChanges\",\n \"All changes saved — edit any field to save again\",\n )\n : undefined\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 hover:bg-action-primary-bg/90 transition-colors disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n {isSaving ? (\n <>\n <Loader2 size={16} className=\"animate-spin\" />\n {tr(\"devportal.saving\", \"Saving…\")}\n </>\n ) : !isDirty ? (\n <>\n <Check size={16} />\n {tr(\"devportal.saved\", \"Saved\")}\n </>\n ) : (\n <>\n <Store size={16} />\n {tr(\"devportal.saveStoreListing\", \"Save Store Listing\")}\n </>\n )}\n </button>\n {!isFormValid && (\n <p className=\"text-xs text-text-secondary\">\n {tr(\n \"devportal.storeListing.requiredFieldsLabel\",\n \"Short Description, Privacy Policy URL, and Terms of Service URL are required\",\n )}\n </p>\n )}\n {/* Guide the user to their next incomplete step */}\n {isPackageApp && versionCount === 0 && onNavigateToVersions && (\n <button\n type=\"button\"\n onClick={onNavigateToVersions}\n className=\"inline-flex items-center gap-1.5 text-sm font-medium text-primary hover:underline underline-offset-2\"\n >\n {tr(\"devportal.nextUploadVersion\", \"Next: Upload a Version\")}\n <ChevronRight size={15} />\n </button>\n )}\n {(!isPackageApp || versionCount > 0) &&\n !pricingDone &&\n onNavigateToPricing && (\n <button\n type=\"button\"\n onClick={onNavigateToPricing}\n className=\"inline-flex items-center gap-1.5 text-sm font-medium text-primary hover:underline underline-offset-2\"\n >\n {tr(\"devportal.nextSetPricing\", \"Next: Set Pricing\")}\n <ChevronRight size={15} />\n </button>\n )}\n </div>\n </div>\n </div>\n );\n};\n\n// =============================================================================\n// HELPER COMPONENTS\n// =============================================================================\n\nconst StatCard: FC<{ label: string; value: string; trend?: number }> = ({\n label,\n value,\n trend,\n}) => {\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const v = t(key);\n return v === key ? fallback : v;\n };\n return (\n <GlassCard treatment=\"metric\" className=\"p-4\">\n <p className=\"text-sm text-text-secondary\">{label}</p>\n <p className=\"text-2xl font-bold tabular-nums\">{value}</p>\n {trend !== undefined && (\n <p\n className={cn(\n \"text-xs mt-1 tabular-nums\",\n trend > 0\n ? \"text-status-success-text\"\n : trend < 0\n ? \"text-status-error-text\"\n : \"text-text-secondary\",\n )}\n >\n {trend > 0 ? \"+\" : \"\"}\n {trend.toFixed(1)}% {tr(\"devportal.vsYesterday\", \"vs yesterday\")}\n </p>\n )}\n </GlassCard>\n );\n};\n\nconst LinkItem: FC<{ label: string; url: string }> = ({ label, url }) => (\n <a\n href={url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"flex items-center gap-2 text-sm text-primary hover:underline\"\n >\n <ExternalLink size={14} />\n {label}\n </a>\n);\n\n// =============================================================================\n// PERMISSIONS TAB\n// =============================================================================\n\n// Friendly labels/descriptions for known platform resources\nconst RESOURCE_META: Record<string, { label: string; description: string }> = {\n auth: {\n label: \"Authentication\",\n description: \"User identity and session management\",\n },\n billing: {\n label: \"Billing\",\n description: \"Billing accounts and subscriptions\",\n },\n files: { label: \"Files\", description: \"File storage and management\" },\n tags: { label: \"Tags\", description: \"Tags and labels on resources\" },\n calendar: { label: \"Calendar\", description: \"Events and scheduling\" },\n workflows: { label: \"Workflows\", description: \"Automation workflows\" },\n channels: { label: \"Channels\", description: \"Messaging channels\" },\n notifications: {\n label: \"Notifications\",\n description: \"Platform notifications\",\n },\n users: {\n label: \"Users & Members\",\n description: \"Workspace members and profiles\",\n },\n workspaces: {\n label: \"Workspaces\",\n description: \"Workspace settings and metadata\",\n },\n content: { label: \"Content\", description: \"Pages, documents, and content\" },\n analytics: {\n label: \"Analytics\",\n description: \"Usage analytics and reporting\",\n },\n webhooks: { label: \"Webhooks\", description: \"Webhook subscriptions\" },\n rbac: {\n label: \"Roles & Permissions\",\n description: \"Access control configuration\",\n },\n};\n\nconst RESOURCE_SUGGESTIONS = Object.keys(RESOURCE_META);\n\ntype PermissionLevel = \"read\" | \"write\";\ntype ScopeEntry = { resource: string; level: PermissionLevel };\n\nfunction parseScopesFromManifest(\n manifest: Record<string, unknown> | null | undefined,\n): ScopeEntry[] {\n if (!manifest || !Array.isArray(manifest.permissions)) return [];\n const result: ScopeEntry[] = [];\n for (const entry of manifest.permissions as Array<{\n resource: string;\n level: string;\n }>) {\n if (\n entry &&\n typeof entry === \"object\" &&\n typeof entry.resource === \"string\" &&\n entry.resource\n ) {\n result.push({\n resource: entry.resource,\n level: entry.level === \"write\" ? \"write\" : \"read\",\n });\n }\n }\n return result;\n}\n\nfunction parseScopesFromRequired(scopes: string[]): ScopeEntry[] {\n const result: ScopeEntry[] = [];\n for (const scope of scopes) {\n const colonIdx = scope.indexOf(\":\");\n if (colonIdx === -1) continue;\n const action = scope.slice(0, colonIdx);\n const resource = scope.slice(colonIdx + 1);\n if (resource) {\n result.push({ resource, level: action === \"write\" ? \"write\" : \"read\" });\n }\n }\n return result;\n}\n\nfunction mergeScopeEntries(\n fromManifest: ScopeEntry[],\n fromScopes: ScopeEntry[],\n): ScopeEntry[] {\n if (fromManifest.length > 0) return fromManifest;\n // Deduplicate by resource (keep first occurrence)\n const seen = new Set<string>();\n return fromScopes.filter((s) => {\n if (seen.has(s.resource)) return false;\n seen.add(s.resource);\n return true;\n });\n}\n\nconst LevelToggle: FC<{\n level: PermissionLevel;\n onChange: (l: PermissionLevel) => void;\n}> = ({ level, onChange }) => (\n <div className=\"flex items-center gap-0.5 rounded-md border border-border-subtle bg-bg-sunken/50 p-0.5\">\n {([\"read\", \"write\"] as PermissionLevel[]).map((l) => (\n <button\n key={l}\n type=\"button\"\n onClick={() => onChange(l)}\n className={`rounded px-2.5 py-1 text-xs font-medium transition-colors whitespace-nowrap ${\n level === l\n ? \"bg-bg-base text-text-primary shadow-sm\"\n : \"text-text-secondary hover:text-text-primary\"\n }`}\n >\n {l === \"read\" ? \"Read\" : \"Read & Write\"}\n </button>\n ))}\n </div>\n);\n\nconst PermissionsTab: FC<{\n app: Application;\n versionScopes?: string[];\n locked?: boolean;\n onNavigateToVersions?: () => void;\n}> = ({ app, versionScopes, locked = false, onNavigateToVersions }) => {\n const manifest = (app.manifest ?? {}) as Record<string, unknown>;\n const [scopes, setScopes] = useState<ScopeEntry[]>(() =>\n mergeScopeEntries(\n parseScopesFromManifest(manifest),\n parseScopesFromRequired(versionScopes ?? []),\n ),\n );\n const [adding, setAdding] = useState(false);\n const [newResource, setNewResource] = useState(\"\");\n const [newLevel, setNewLevel] = useState<PermissionLevel>(\"read\");\n const [saving, setSaving] = useState(false);\n const [saved, setSaved] = useState(false);\n const [updateApplication] = useUpdateApplicationMutation();\n\n const handleLevelChange = (resource: string, level: PermissionLevel) => {\n setSaved(false);\n setScopes((prev) =>\n prev.map((s) => (s.resource === resource ? { ...s, level } : s)),\n );\n };\n\n const handleRemove = (resource: string) => {\n setSaved(false);\n setScopes((prev) => prev.filter((s) => s.resource !== resource));\n };\n\n const handleAdd = () => {\n const res = newResource.trim().toLowerCase().replace(/\\s+/g, \"-\");\n if (!res || scopes.some((s) => s.resource === res)) return;\n setScopes((prev) => [...prev, { resource: res, level: newLevel }]);\n setNewResource(\"\");\n setNewLevel(\"read\");\n setAdding(false);\n setSaved(false);\n };\n\n const handleSave = async () => {\n setSaving(true);\n try {\n await updateApplication({\n variables: {\n id: app.id,\n input: {\n manifest: {\n ...manifest,\n permissions: scopes.map(({ resource, level }) => ({\n resource,\n level,\n })),\n },\n },\n },\n });\n setSaved(true);\n } finally {\n setSaving(false);\n }\n };\n\n const scopeList = (\n <div className=\"rounded-lg border border-border-subtle divide-y divide-border-subtle\">\n {scopes.map((scope) => (\n <div\n key={scope.resource}\n className=\"flex items-center gap-3 px-4 py-3 hover:bg-bg-sunken/30 transition-colors\"\n >\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm font-medium text-text-primary\">\n {RESOURCE_META[scope.resource]?.label ?? scope.resource}\n </p>\n {RESOURCE_META[scope.resource]?.description && (\n <p className=\"text-xs text-text-secondary\">\n {RESOURCE_META[scope.resource].description}\n </p>\n )}\n {!RESOURCE_META[scope.resource] && (\n <p className=\"text-xs text-text-tertiary font-mono\">\n custom scope\n </p>\n )}\n </div>\n {locked ? (\n <span\n className={`rounded-full px-2.5 py-0.5 text-xs font-medium ${\n scope.level === \"write\"\n ? \"bg-status-warning-bg text-status-warning-text\"\n : \"bg-bg-sunken text-text-secondary\"\n }`}\n >\n {scope.level === \"write\" ? \"Read & Write\" : \"Read\"}\n </span>\n ) : (\n <>\n <LevelToggle\n level={scope.level}\n onChange={(l) => handleLevelChange(scope.resource, l)}\n />\n <button\n type=\"button\"\n onClick={() => handleRemove(scope.resource)}\n title=\"Remove permission\"\n className=\"p-1.5 rounded text-text-tertiary hover:text-status-error-text hover:bg-status-error-bg-subtle transition-colors\"\n >\n <X size={14} />\n </button>\n </>\n )}\n </div>\n ))}\n </div>\n );\n\n return (\n <PageSection\n title=\"Permissions\"\n description=\"These are the permissions your app requests from users. Users see exactly this list when authorizing your app.\"\n >\n <div className=\"space-y-4\">\n {locked ? (\n <>\n <div className=\"rounded-lg border border-status-warning-bg bg-status-warning-bg-subtle p-3 flex gap-2 text-sm\">\n <Info\n size={15}\n className=\"flex-shrink-0 mt-0.5 text-status-warning-text\"\n />\n <span className=\"text-status-warning-text\">\n <strong>Permission changes require a new version.</strong> Your\n app is live and users have already consented to the permissions\n below. To request new or fewer permissions, publish a new\n version — existing users will be shown what changed and asked to\n re-consent before the new version takes effect.{\" \"}\n {onNavigateToVersions && (\n <button\n type=\"button\"\n onClick={onNavigateToVersions}\n className=\"underline font-medium hover:opacity-80 transition-opacity\"\n >\n Go to Versions →\n </button>\n )}\n </span>\n </div>\n {scopes.length === 0 ? (\n <div className=\"rounded-lg border border-border-subtle border-dashed p-6 text-center text-sm text-text-secondary\">\n No permissions configured for this version.\n </div>\n ) : (\n scopeList\n )}\n </>\n ) : (\n <>\n {scopes.length === 0 ? (\n <div className=\"rounded-lg border border-border-subtle border-dashed p-8 flex flex-col items-center gap-2 text-center text-text-secondary\">\n <Shield size={28} className=\"opacity-25\" />\n <p className=\"text-sm font-medium text-text-primary\">\n No permissions configured\n </p>\n <p className=\"text-xs\">\n Add the permissions your app needs to request from users.\n </p>\n </div>\n ) : (\n scopeList\n )}\n\n {adding ? (\n <div className=\"rounded-lg border border-border-subtle p-3 flex items-center gap-2 flex-wrap\">\n <input\n type=\"text\"\n value={newResource}\n onChange={(e) => setNewResource(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") handleAdd();\n if (e.key === \"Escape\") setAdding(false);\n }}\n placeholder=\"Resource (e.g. auth, files, widgets)\"\n list=\"perm-resource-suggestions\"\n autoFocus\n className=\"flex-1 min-w-40 rounded-md border border-border-subtle bg-bg-base px-3 py-1.5 text-sm focus:outline-none focus:ring-1 focus:ring-primary\"\n />\n <datalist id=\"perm-resource-suggestions\">\n {RESOURCE_SUGGESTIONS.filter(\n (r) => !scopes.some((s) => s.resource === r),\n ).map((r) => (\n <option key={r} value={r}>\n {RESOURCE_META[r].label}\n </option>\n ))}\n </datalist>\n <LevelToggle level={newLevel} onChange={setNewLevel} />\n <button\n type=\"button\"\n onClick={handleAdd}\n disabled={!newResource.trim()}\n className=\"px-3 py-1.5 rounded-md bg-action-primary-bg text-action-primary-text text-xs font-medium hover:bg-action-primary-bg/90 disabled:opacity-50 transition-colors\"\n >\n Add\n </button>\n <button\n type=\"button\"\n onClick={() => {\n setAdding(false);\n setNewResource(\"\");\n }}\n className=\"p-1.5 rounded text-text-secondary hover:text-text-primary transition-colors\"\n >\n <X size={14} />\n </button>\n </div>\n ) : (\n <button\n type=\"button\"\n onClick={() => setAdding(true)}\n className=\"flex items-center gap-1.5 text-sm text-text-secondary hover:text-text-primary transition-colors\"\n >\n <Plus size={14} />\n Add permission\n </button>\n )}\n\n <div className=\"rounded-lg border border-border-subtle bg-bg-sunken/30 p-3 flex gap-2 text-xs text-text-secondary\">\n <Info size={14} className=\"flex-shrink-0 mt-0.5\" />\n <span>\n <strong>Read & Write</strong> implies Read. Request only\n what your app genuinely needs — fewer permissions build more\n user trust.\n </span>\n </div>\n\n <div className=\"flex items-center justify-end gap-3\">\n {saved && (\n <span className=\"flex items-center gap-1.5 text-sm text-status-success-text\">\n <CheckCircle size={14} />\n Saved\n </span>\n )}\n <button\n type=\"button\"\n onClick={() => void handleSave()}\n disabled={saving}\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 transition-colors disabled:opacity-50\"\n >\n {saving ? (\n <Loader2 size={14} className=\"animate-spin\" />\n ) : (\n <Shield size={14} />\n )}\n Save Permissions\n </button>\n </div>\n </>\n )}\n </div>\n </PageSection>\n );\n};\n"],"mappings":"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"}
|