@burdenoff/microfe-devportal 2026.626.5 → 2026.626.7
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 } 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} from \"lucide-react\";\nimport {\n CTAOverflowMenu,\n EmphasisPanel,\n GlassCard,\n NextSteps,\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 useCurrentUserDelegationsQuery,\n useDeactivateAppMutation,\n useRotateAppSecretMutation,\n useRevokeDelegationMutation,\n useUpdateApplicationMutation,\n useInstallApplicationMutation,\n useUninstallApplicationMutation,\n useGetWorkspaceInstallationQuery,\n useSubmitApplicationMutation,\n type ApplicationScopeFieldsFragment,\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 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 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\nconst tabs: Array<{ id: TabId; label: string; icon: FC<{ size?: number }> }> = [\n { id: \"overview\", label: \"Overview\", icon: AppWindow },\n { id: \"permissions\", label: \"Permissions\", icon: Shield },\n { id: \"webhooks\", label: \"Webhooks\", icon: Webhook },\n { id: \"delegations\", label: \"Delegations\", icon: Users },\n { id: \"analytics\", label: \"Analytics\", icon: BarChart3 },\n { id: \"playground\", label: \"API Playground\", icon: ExternalLink },\n { id: \"store-listing\", label: \"Store Listing\", icon: Store },\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 } = 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 [installApplication, { loading: installLoading }] =\n useInstallApplicationMutation();\n const [uninstallApplication, { loading: uninstallLoading }] =\n useUninstallApplicationMutation();\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 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 // ---- 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 canSubmitForReview =\n app.status !== \"PUBLISHED\" &&\n (!isPackageApp || (data?.application?.versions?.totalCount ?? 0) > 0);\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 {\n label: tr(\"devportal.versions\", \"Versions\"),\n icon: <Clock size={16} />,\n onSelect: () => handleNavigate(`/apps/${app.id}/versions`),\n },\n ...(canSubmitForReview\n ? [\n {\n label: tr(\"devportal.submitForReview\", \"Submit for Review\"),\n icon: <SendHorizontal size={16} />,\n onSelect: () => setActiveTab(\"store-listing\"),\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 <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 }\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 {/* Guided next steps (dismissable) */}\n <NextSteps\n storageKey={`devportal-app-${app.id}`}\n steps={[\n {\n id: \"edit\",\n label: tr(\"devportal.editApp\", \"Edit App\"),\n description: tr(\n \"devportal.appDetailStepEdit\",\n \"Update the name, description, and settings\",\n ),\n icon: <Edit size={16} />,\n onClick: () => handleNavigate(`/apps/${app.id}/edit`),\n },\n ...(!isPackageApp\n ? [\n {\n id: \"permissions\",\n label: tr(\"devportal.permissions\", \"Permissions\"),\n description: tr(\n \"devportal.appDetailStepPermissions\",\n \"Request the scopes your app needs\",\n ),\n icon: <Shield size={16} />,\n onClick: () => setActiveTab(\"permissions\"),\n },\n {\n id: \"webhooks\",\n label: tr(\"devportal.webhooks\", \"Webhooks\"),\n description: tr(\n \"devportal.appDetailStepWebhooks\",\n \"Subscribe to events for real-time updates\",\n ),\n icon: <Webhook size={16} />,\n onClick: () => setActiveTab(\"webhooks\"),\n },\n ]\n : [\n {\n id: \"versions\",\n label: tr(\"devportal.versions\", \"Versions\"),\n description: tr(\n \"devportal.appDetailStepVersions\",\n \"Upload a zip package to create your first version\",\n ),\n icon: <Clock size={16} />,\n onClick: () => handleNavigate(`/apps/${app.id}/versions`),\n },\n ]),\n {\n id: \"store-listing\",\n label: tr(\"devportal.storeListing\", \"Store Listing\"),\n description: tr(\n \"devportal.appDetailStepStore\",\n \"Prepare and publish to the marketplace\",\n ),\n icon: <Store size={16} />,\n onClick: () => setActiveTab(\"store-listing\"),\n },\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 const isPackageType =\n app.appType === \"NODE\" || app.appType === \"WORKFLOW\";\n if (\n isPackageType &&\n (tab.id === \"permissions\" ||\n tab.id === \"webhooks\" ||\n tab.id === \"delegations\" ||\n tab.id === \"playground\")\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\" && <PermissionsTab app={app} />}\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 === \"store-listing\" && <StoreListingTab app={app} />}\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/** 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 - modify as needed\nquery IntrospectSchema {\n __schema {\n queryType { name }\n mutationType { name }\n types {\n name\n kind\n }\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\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 ? (\n <img\n src={value}\n alt={label}\n className=\"w-full h-full object-cover\"\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\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 remove = (idx: number) => {\n onChange(urls.filter((_, i) => i !== idx));\n };\n\n return (\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium\">Screenshots</label>\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 <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 // Pricing\n pricingType: string;\n price: string;\n currency: 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 = [\n { value: \"agent\", label: \"Agent\" },\n { value: \"node\", label: \"Node\" },\n { value: \"widget\", label: \"Widget\" },\n { value: \"workflow\", label: \"Workflow\" },\n { value: \"botapp\", label: \"Bot App\" },\n { value: \"console\", label: \"Console\" },\n { value: \"vibemodule\", label: \"Vibe Module\" },\n { value: \"dashboard\", label: \"Dashboard\" },\n { value: \"parser\", label: \"Parser\" },\n { value: \"datasink\", label: \"Data Sink\" },\n { value: \"app\", label: \"App\" },\n { value: \"template\", label: \"Template\" },\n { value: \"integration\", label: \"Integration\" },\n { value: \"extension\", label: \"Extension\" },\n { value: \"theme\", label: \"Theme\" },\n { value: \"plugin\", label: \"Plugin\" },\n { value: \"component\", label: \"Component\" },\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 pricingDetails = (app.pricingDetails ?? {}) as Record<string, unknown>;\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 pricingType: app.pricingType ?? \"\",\n price:\n typeof pricingDetails.price === \"number\"\n ? String(pricingDetails.price)\n : \"\",\n currency:\n typeof pricingDetails.currency === \"string\"\n ? pricingDetails.currency\n : \"\",\n manifestItemType:\n typeof manifest.itemType === \"string\" ? manifest.itemType : \"\",\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<{ app: Application }> = ({ app }) => {\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 isPackageApp = app.appType === \"NODE\" || app.appType === \"WORKFLOW\";\n const canSubmitForReview =\n app.status !== \"PUBLISHED\" &&\n (!isPackageApp || (app.versions?.length ?? 0) > 0);\n\n const [formData, setFormData] = useState<StoreListingFormData>(() =>\n buildInitialFormData(app),\n );\n const [isSaving, setIsSaving] = useState(false);\n const appRef = useRef(app);\n appRef.current = app;\n\n const [updateApplication] = useUpdateApplicationMutation();\n const [submitApplication, { loading: isSubmitting }] =\n useSubmitApplicationMutation();\n\n // Reset form only when navigating to a different app (not on every refetch)\n useEffect(() => {\n setFormData(buildInitialFormData(appRef.current));\n }, [app.id]);\n\n const handleChange = (field: keyof StoreListingFormData, value: string) => {\n setFormData((prev) => ({ ...prev, [field]: value }));\n };\n\n const handleSave = async () => {\n setIsSaving(true);\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 const existingPricingDetails = (app.pricingDetails ?? {}) as Record<\n string,\n unknown\n >;\n const pricingDetails: Record<string, unknown> = {\n ...existingPricingDetails,\n };\n if (formData.pricingType !== \"FREE\") {\n const parsedPrice = parseFloat(formData.price);\n if (!isNaN(parsedPrice)) {\n pricingDetails.price = parsedPrice;\n }\n if (formData.currency) {\n pricingDetails.currency = formData.currency;\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 pricingType: formData.pricingType || null,\n pricingDetails:\n Object.keys(pricingDetails).length > 0 ? pricingDetails : null,\n manifest: updatedManifest as unknown as Record<string, unknown>,\n },\n },\n });\n void nativeNotify(\"success\");\n } catch {\n void nativeNotify(\"error\");\n } finally {\n setIsSaving(false);\n }\n };\n\n const handleSubmitForReview = async () => {\n try {\n await submitApplication({ variables: { id: app.id } });\n void nativeNotify(\"success\");\n } catch {\n void nativeNotify(\"error\");\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 const showPriceFields = formData.pricingType !== \"FREE\";\n\n const isDraft = app.status === \"DRAFT\";\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-start gap-3 rounded-lg border border-primary/30 bg-action-primary-bg/5 px-4 py-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(\"devportal.storeListing.underReview\", \"Submitted for review\")}\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 ) : (\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 — the most important choice */}\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={ITEM_TYPE_OPTIONS}\n placeholder={tr(\"devportal.selectItemType\", \"Select item type…\")}\n hint={tr(\n \"devportal.storeItemTypeHint\",\n \"Determines how this item is categorised and how the platform runs it\",\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 workflow / template types */}\n {isJsonOnlyType && (\n <TextareaField\n label={tr(\n \"devportal.jsonContent\",\n formData.manifestItemType === \"workflow\"\n ? \"Workflow Definition (JSON)\"\n : \"Template Definition (JSON)\",\n )}\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\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 \"Square, 256×256 px recommended\",\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(\"devportal.bannerUrlHint\", \"1280×640 px recommended\")}\n aspectClass=\"aspect-video\"\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 {/* ── Section 4: Pricing ─────────────────────────────────── */}\n <PageSection\n title={tr(\"devportal.pricing\", \"Pricing\")}\n description={tr(\n \"devportal.pricingDescription\",\n \"How this item is priced in the marketplace\",\n )}\n >\n <div className=\"space-y-4\">\n <div>\n <label className=\"mb-2 block text-sm font-medium\">\n {tr(\"devportal.pricingType\", \"Pricing Type\")}\n </label>\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-3 py-1.5 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\",\n )}\n >\n {opt.label}\n </button>\n ))}\n </div>\n </div>\n {showPriceFields && (\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <InputField\n label={tr(\"devportal.price\", \"Price\")}\n type=\"number\"\n value={formData.price}\n onChange={(e) => handleChange(\"price\", e.target.value)}\n placeholder=\"0.00\"\n />\n <SelectField\n label={tr(\"devportal.currency\", \"Currency\")}\n value={formData.currency}\n onChange={(e) => handleChange(\"currency\", e.target.value)}\n options={CURRENCY_OPTIONS}\n placeholder={tr(\"devportal.selectCurrency\", \"Select currency…\")}\n />\n </div>\n )}\n </div>\n </PageSection>\n\n {/* Save + Submit for Review */}\n <div className=\"border-t pt-6 flex items-center gap-3 flex-wrap\">\n <button\n type=\"button\"\n onClick={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 <Store size={16} />\n {tr(\"devportal.saveStoreListing\", \"Save Store Listing\")}\n </>\n )}\n </button>\n {!isPublished && (\n <div className=\"flex flex-col gap-1\">\n <button\n type=\"button\"\n onClick={() => void handleSubmitForReview()}\n disabled={isSubmitting || isSaving || !canSubmitForReview}\n className=\"inline-flex items-center gap-2 rounded-md border border-primary px-4 py-2 text-sm font-medium text-primary hover:bg-action-primary-bg/5 transition-colors disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n {isSubmitting ? (\n <>\n <Loader2 size={16} className=\"animate-spin\" />\n {tr(\"devportal.submitting\", \"Submitting…\")}\n </>\n ) : (\n <>\n <CheckCircle size={16} />\n {isSubmitted\n ? tr(\"devportal.resubmitForReview\", \"Resubmit for Review\")\n : tr(\"devportal.submitForReview\", \"Submit for Review\")}\n </>\n )}\n </button>\n {!canSubmitForReview && isPackageApp && (\n <p className=\"text-xs text-text-secondary\">\n {tr(\n \"devportal.versionRequiredHint\",\n \"At least one version is required before submitting for review.\",\n )}\n </p>\n )}\n </div>\n )}\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\nconst PERMISSION_RESOURCES = [\n {\n id: \"auth\",\n label: \"Authentication\",\n description: \"User identity and session management\",\n },\n {\n id: \"billing\",\n label: \"Billing\",\n description: \"Billing accounts and subscriptions\",\n },\n { id: \"files\", label: \"Files\", description: \"File storage and management\" },\n { id: \"tags\", label: \"Tags\", description: \"Tags and labels on resources\" },\n { id: \"calendar\", label: \"Calendar\", description: \"Events and scheduling\" },\n { id: \"workflows\", label: \"Workflows\", description: \"Automation workflows\" },\n { id: \"channels\", label: \"Channels\", description: \"Messaging channels\" },\n {\n id: \"notifications\",\n label: \"Notifications\",\n description: \"Platform notifications\",\n },\n {\n id: \"users\",\n label: \"Users & Members\",\n description: \"Workspace members and profiles\",\n },\n {\n id: \"workspaces\",\n label: \"Workspaces\",\n description: \"Workspace settings and metadata\",\n },\n {\n id: \"content\",\n label: \"Content\",\n description: \"Pages, documents, and content\",\n },\n {\n id: \"analytics\",\n label: \"Analytics\",\n description: \"Usage analytics and reporting\",\n },\n { id: \"webhooks\", label: \"Webhooks\", description: \"Webhook subscriptions\" },\n {\n id: \"rbac\",\n label: \"Roles & Permissions\",\n description: \"Access control configuration\",\n },\n] as const;\n\ntype PermissionResourceId = (typeof PERMISSION_RESOURCES)[number][\"id\"];\ntype PermissionLevel = \"none\" | \"read\" | \"write\";\ntype PermissionMap = Record<PermissionResourceId, PermissionLevel>;\n\nfunction parseManifestPermissions(\n manifest: Record<string, unknown> | null | undefined,\n): PermissionMap {\n const base = Object.fromEntries(\n PERMISSION_RESOURCES.map((r) => [r.id, \"none\" as PermissionLevel]),\n ) as PermissionMap;\n if (!manifest || !Array.isArray(manifest.permissions)) return base;\n for (const entry of manifest.permissions as Array<{\n resource: string;\n level: string;\n }>) {\n if (entry.resource in base) {\n base[entry.resource as PermissionResourceId] =\n entry.level === \"write\" ? \"write\" : \"read\";\n }\n }\n return base;\n}\n\nconst PermissionsTab: FC<{ app: Application }> = ({ app }) => {\n const manifest = (app.manifest ?? {}) as Record<string, unknown>;\n const [permissions, setPermissions] = useState<PermissionMap>(() =>\n parseManifestPermissions(manifest),\n );\n const [saving, setSaving] = useState(false);\n const [saved, setSaved] = useState(false);\n const [updateApplication] = useUpdateApplicationMutation();\n\n const handleChange = (\n resource: PermissionResourceId,\n level: PermissionLevel,\n ) => {\n setSaved(false);\n setPermissions((prev) => ({ ...prev, [resource]: level }));\n };\n\n const handleSave = async () => {\n setSaving(true);\n try {\n const entries = Object.entries(permissions).filter(\n ([, level]) => level !== \"none\",\n );\n const newPermissions = entries.map(([resource, level]) => ({\n resource,\n level,\n }));\n await updateApplication({\n variables: {\n id: app.id,\n input: {\n manifest: {\n ...manifest,\n permissions: newPermissions,\n },\n },\n },\n });\n setSaved(true);\n } finally {\n setSaving(false);\n }\n };\n\n const levelLabels: Record<PermissionLevel, string> = {\n none: \"No access\",\n read: \"Read\",\n write: \"Read & Write\",\n };\n const levels: PermissionLevel[] = [\"none\", \"read\", \"write\"];\n\n return (\n <PageSection\n title=\"Permissions\"\n description=\"Define what platform data this app can request access to. Users see these when authorizing the app.\"\n >\n <div className=\"space-y-4\">\n <div className=\"overflow-x-auto 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 w-1/2\">\n Resource\n </th>\n {levels.map((l) => (\n <th\n key={l}\n className=\"px-4 py-3 text-center font-medium text-text-secondary\"\n >\n {levelLabels[l]}\n </th>\n ))}\n </tr>\n </thead>\n <tbody className=\"divide-y divide-border\">\n {PERMISSION_RESOURCES.map((resource) => (\n <tr\n key={resource.id}\n className=\"hover:bg-bg-sunken/30 transition-colors\"\n >\n <td className=\"px-4 py-3\">\n <p className=\"font-medium text-text-primary\">\n {resource.label}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {resource.description}\n </p>\n </td>\n {levels.map((level) => (\n <td key={level} className=\"px-4 py-3 text-center\">\n <input\n type=\"radio\"\n name={`perm-${resource.id}`}\n value={level}\n checked={permissions[resource.id] === level}\n onChange={() => handleChange(resource.id, level)}\n className=\"h-4 w-4 accent-primary cursor-pointer\"\n />\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\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 what\n your app genuinely needs — fewer permissions build more 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 </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} from \"lucide-react\";\nimport {\n CTAOverflowMenu,\n EmphasisPanel,\n GlassCard,\n NextSteps,\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 useCurrentUserDelegationsQuery,\n useDeactivateAppMutation,\n useRotateAppSecretMutation,\n useRevokeDelegationMutation,\n useUpdateApplicationMutation,\n useInstallApplicationMutation,\n useUninstallApplicationMutation,\n useGetWorkspaceInstallationQuery,\n useSubmitApplicationMutation,\n type ApplicationScopeFieldsFragment,\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 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\nconst tabs: Array<{ id: TabId; label: string; icon: FC<{ size?: number }> }> = [\n { id: \"overview\", label: \"Overview\", icon: AppWindow },\n { id: \"permissions\", label: \"Permissions\", icon: Shield },\n { id: \"webhooks\", label: \"Webhooks\", icon: Webhook },\n { id: \"delegations\", label: \"Delegations\", icon: Users },\n { id: \"analytics\", label: \"Analytics\", icon: BarChart3 },\n { id: \"playground\", label: \"API Playground\", icon: ExternalLink },\n { id: \"store-listing\", label: \"Store Listing\", icon: Store },\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 } = 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 [installApplication, { loading: installLoading }] =\n useInstallApplicationMutation();\n const [uninstallApplication, { loading: uninstallLoading }] =\n useUninstallApplicationMutation();\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 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 // ---- 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 canSubmitForReview =\n app.status !== \"PUBLISHED\" &&\n (!isPackageApp || (data?.application?.versions?.totalCount ?? 0) > 0);\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 {\n label: tr(\"devportal.versions\", \"Versions\"),\n icon: <Clock size={16} />,\n onSelect: () => handleNavigate(`/apps/${app.id}/versions`),\n },\n ...(app.status === \"SUBMITTED\"\n ? [\n {\n label: tr(\n \"devportal.viewSubmissionStatus\",\n \"View Submission Status\",\n ),\n icon: <ExternalLink size={16} />,\n onSelect: () => handleNavigate(`/apps/${app.id}/store-submission`),\n },\n ]\n : canSubmitForReview\n ? [\n {\n label: tr(\"devportal.submitForReview\", \"Submit for Review\"),\n icon: <SendHorizontal size={16} />,\n onSelect: () => setActiveTab(\"store-listing\"),\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 <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 }\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 {/* Guided next steps (dismissable) */}\n <NextSteps\n storageKey={`devportal-app-${app.id}`}\n steps={[\n {\n id: \"edit\",\n label: tr(\"devportal.editApp\", \"Edit App\"),\n description: tr(\n \"devportal.appDetailStepEdit\",\n \"Update the name, description, and settings\",\n ),\n icon: <Edit size={16} />,\n onClick: () => handleNavigate(`/apps/${app.id}/edit`),\n },\n ...(!isPackageApp\n ? [\n {\n id: \"permissions\",\n label: tr(\"devportal.permissions\", \"Permissions\"),\n description: tr(\n \"devportal.appDetailStepPermissions\",\n \"Request the scopes your app needs\",\n ),\n icon: <Shield size={16} />,\n onClick: () => setActiveTab(\"permissions\"),\n },\n {\n id: \"webhooks\",\n label: tr(\"devportal.webhooks\", \"Webhooks\"),\n description: tr(\n \"devportal.appDetailStepWebhooks\",\n \"Subscribe to events for real-time updates\",\n ),\n icon: <Webhook size={16} />,\n onClick: () => setActiveTab(\"webhooks\"),\n },\n ]\n : [\n {\n id: \"versions\",\n label: tr(\"devportal.versions\", \"Versions\"),\n description: tr(\n \"devportal.appDetailStepVersions\",\n \"Upload a zip package to create your first version\",\n ),\n icon: <Clock size={16} />,\n onClick: () => handleNavigate(`/apps/${app.id}/versions`),\n },\n ]),\n {\n id: \"store-listing\",\n label: tr(\"devportal.storeListing\", \"Store Listing\"),\n description: tr(\n \"devportal.appDetailStepStore\",\n \"Prepare and publish to the marketplace\",\n ),\n icon: <Store size={16} />,\n onClick: () => setActiveTab(\"store-listing\"),\n },\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 const isPackageType =\n app.appType === \"NODE\" || app.appType === \"WORKFLOW\";\n if (\n isPackageType &&\n (tab.id === \"permissions\" ||\n tab.id === \"webhooks\" ||\n tab.id === \"delegations\" ||\n tab.id === \"playground\")\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\" && <PermissionsTab app={app} />}\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 === \"store-listing\" && (\n <StoreListingTab\n app={app}\n versionCount={data?.application?.versions?.totalCount ?? 0}\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/** 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 - modify as needed\nquery IntrospectSchema {\n __schema {\n queryType { name }\n mutationType { name }\n types {\n name\n kind\n }\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\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 ? (\n <img\n src={value}\n alt={label}\n className=\"w-full h-full object-cover\"\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\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 remove = (idx: number) => {\n onChange(urls.filter((_, i) => i !== idx));\n };\n\n return (\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium\">Screenshots</label>\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 <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 // Pricing\n pricingType: string;\n price: string;\n currency: 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 pricingDetails = (app.pricingDetails ?? {}) as Record<string, unknown>;\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 pricingType: app.pricingType ?? \"\",\n price:\n typeof pricingDetails.price === \"number\"\n ? String(pricingDetails.price)\n : \"\",\n currency:\n typeof pricingDetails.currency === \"string\"\n ? pricingDetails.currency\n : \"\",\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<{ app: Application; versionCount?: number }> = ({\n app,\n versionCount = 0,\n}) => {\n const navigate = useNavigate();\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 isPackageApp = app.appType === \"NODE\" || app.appType === \"WORKFLOW\";\n const canSubmitForReview =\n app.status !== \"PUBLISHED\" && (!isPackageApp || versionCount > 0);\n\n const [formData, setFormData] = useState<StoreListingFormData>(() =>\n buildInitialFormData(app),\n );\n const [isSaving, setIsSaving] = useState(false);\n const appRef = useRef(app);\n appRef.current = app;\n\n const [updateApplication] = useUpdateApplicationMutation();\n const [submitApplication, { loading: isSubmitting }] =\n useSubmitApplicationMutation();\n\n // Reset form only when navigating to a different app (not on every refetch)\n useEffect(() => {\n setFormData(buildInitialFormData(appRef.current));\n }, [app.id]);\n\n const handleChange = (field: keyof StoreListingFormData, value: string) => {\n setFormData((prev) => ({ ...prev, [field]: value }));\n };\n\n const handleSave = async () => {\n setIsSaving(true);\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 const existingPricingDetails = (app.pricingDetails ?? {}) as Record<\n string,\n unknown\n >;\n const pricingDetails: Record<string, unknown> = {\n ...existingPricingDetails,\n };\n if (formData.pricingType !== \"FREE\") {\n const parsedPrice = parseFloat(formData.price);\n if (!isNaN(parsedPrice)) {\n pricingDetails.price = parsedPrice;\n }\n if (formData.currency) {\n pricingDetails.currency = formData.currency;\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 pricingType: formData.pricingType || null,\n pricingDetails:\n Object.keys(pricingDetails).length > 0 ? pricingDetails : null,\n manifest: updatedManifest as unknown as Record<string, unknown>,\n },\n },\n });\n void nativeNotify(\"success\");\n } catch {\n void nativeNotify(\"error\");\n } finally {\n setIsSaving(false);\n }\n };\n\n const handleSubmitForReview = async () => {\n try {\n await submitApplication({ variables: { id: app.id } });\n void nativeNotify(\"success\");\n } catch {\n void nativeNotify(\"error\");\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 const showPriceFields = formData.pricingType !== \"FREE\";\n\n const isDraft = app.status === \"DRAFT\";\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 <button\n type=\"button\"\n onClick={() => navigate(`/apps/${app.id}/store-submission`)}\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 </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 workflow / template types */}\n {isJsonOnlyType && (\n <TextareaField\n label={tr(\n \"devportal.jsonContent\",\n formData.manifestItemType === \"workflow\"\n ? \"Workflow Definition (JSON)\"\n : \"Template Definition (JSON)\",\n )}\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 </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 \"Square, 256×256 px recommended\",\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(\"devportal.bannerUrlHint\", \"1280×640 px recommended\")}\n aspectClass=\"aspect-video\"\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 {/* ── Section 4: Pricing ─────────────────────────────────── */}\n <PageSection\n title={tr(\"devportal.pricing\", \"Pricing\")}\n description={tr(\n \"devportal.pricingDescription\",\n \"How this item is priced in the marketplace\",\n )}\n >\n <div className=\"space-y-4\">\n <div>\n <label className=\"mb-2 block text-sm font-medium\">\n {tr(\"devportal.pricingType\", \"Pricing Type\")}\n </label>\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-3 py-1.5 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\",\n )}\n >\n {opt.label}\n </button>\n ))}\n </div>\n </div>\n {showPriceFields && (\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <InputField\n label={tr(\"devportal.price\", \"Price\")}\n type=\"number\"\n value={formData.price}\n onChange={(e) => handleChange(\"price\", e.target.value)}\n placeholder=\"0.00\"\n />\n <SelectField\n label={tr(\"devportal.currency\", \"Currency\")}\n value={formData.currency}\n onChange={(e) => handleChange(\"currency\", e.target.value)}\n options={CURRENCY_OPTIONS}\n placeholder={tr(\"devportal.selectCurrency\", \"Select currency…\")}\n />\n </div>\n )}\n </div>\n </PageSection>\n\n {/* Save + Submit for Review */}\n <div className=\"border-t pt-6 flex items-center gap-3 flex-wrap\">\n <button\n type=\"button\"\n onClick={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 <Store size={16} />\n {tr(\"devportal.saveStoreListing\", \"Save Store Listing\")}\n </>\n )}\n </button>\n {!isPublished && (\n <div className=\"flex flex-col gap-1\">\n <button\n type=\"button\"\n onClick={() => void handleSubmitForReview()}\n disabled={isSubmitting || isSaving || !canSubmitForReview}\n className=\"inline-flex items-center gap-2 rounded-md border border-primary px-4 py-2 text-sm font-medium text-primary hover:bg-action-primary-bg/5 transition-colors disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n {isSubmitting ? (\n <>\n <Loader2 size={16} className=\"animate-spin\" />\n {tr(\"devportal.submitting\", \"Submitting…\")}\n </>\n ) : (\n <>\n <CheckCircle size={16} />\n {isSubmitted\n ? tr(\"devportal.resubmitForReview\", \"Resubmit for Review\")\n : tr(\"devportal.submitForReview\", \"Submit for Review\")}\n </>\n )}\n </button>\n {!canSubmitForReview && isPackageApp && (\n <p className=\"text-xs text-text-secondary\">\n {tr(\n \"devportal.versionRequiredHint\",\n \"At least one version is required before submitting for review.\",\n )}\n </p>\n )}\n </div>\n )}\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\nconst PERMISSION_RESOURCES = [\n {\n id: \"auth\",\n label: \"Authentication\",\n description: \"User identity and session management\",\n },\n {\n id: \"billing\",\n label: \"Billing\",\n description: \"Billing accounts and subscriptions\",\n },\n { id: \"files\", label: \"Files\", description: \"File storage and management\" },\n { id: \"tags\", label: \"Tags\", description: \"Tags and labels on resources\" },\n { id: \"calendar\", label: \"Calendar\", description: \"Events and scheduling\" },\n { id: \"workflows\", label: \"Workflows\", description: \"Automation workflows\" },\n { id: \"channels\", label: \"Channels\", description: \"Messaging channels\" },\n {\n id: \"notifications\",\n label: \"Notifications\",\n description: \"Platform notifications\",\n },\n {\n id: \"users\",\n label: \"Users & Members\",\n description: \"Workspace members and profiles\",\n },\n {\n id: \"workspaces\",\n label: \"Workspaces\",\n description: \"Workspace settings and metadata\",\n },\n {\n id: \"content\",\n label: \"Content\",\n description: \"Pages, documents, and content\",\n },\n {\n id: \"analytics\",\n label: \"Analytics\",\n description: \"Usage analytics and reporting\",\n },\n { id: \"webhooks\", label: \"Webhooks\", description: \"Webhook subscriptions\" },\n {\n id: \"rbac\",\n label: \"Roles & Permissions\",\n description: \"Access control configuration\",\n },\n] as const;\n\ntype PermissionResourceId = (typeof PERMISSION_RESOURCES)[number][\"id\"];\ntype PermissionLevel = \"none\" | \"read\" | \"write\";\ntype PermissionMap = Record<PermissionResourceId, PermissionLevel>;\n\nfunction parseManifestPermissions(\n manifest: Record<string, unknown> | null | undefined,\n): PermissionMap {\n const base = Object.fromEntries(\n PERMISSION_RESOURCES.map((r) => [r.id, \"none\" as PermissionLevel]),\n ) as PermissionMap;\n if (!manifest || !Array.isArray(manifest.permissions)) return base;\n for (const entry of manifest.permissions as Array<{\n resource: string;\n level: string;\n }>) {\n if (entry.resource in base) {\n base[entry.resource as PermissionResourceId] =\n entry.level === \"write\" ? \"write\" : \"read\";\n }\n }\n return base;\n}\n\nconst PermissionsTab: FC<{ app: Application }> = ({ app }) => {\n const manifest = (app.manifest ?? {}) as Record<string, unknown>;\n const [permissions, setPermissions] = useState<PermissionMap>(() =>\n parseManifestPermissions(manifest),\n );\n const [saving, setSaving] = useState(false);\n const [saved, setSaved] = useState(false);\n const [updateApplication] = useUpdateApplicationMutation();\n\n const handleChange = (\n resource: PermissionResourceId,\n level: PermissionLevel,\n ) => {\n setSaved(false);\n setPermissions((prev) => ({ ...prev, [resource]: level }));\n };\n\n const handleSave = async () => {\n setSaving(true);\n try {\n const entries = Object.entries(permissions).filter(\n ([, level]) => level !== \"none\",\n );\n const newPermissions = entries.map(([resource, level]) => ({\n resource,\n level,\n }));\n await updateApplication({\n variables: {\n id: app.id,\n input: {\n manifest: {\n ...manifest,\n permissions: newPermissions,\n },\n },\n },\n });\n setSaved(true);\n } finally {\n setSaving(false);\n }\n };\n\n const levelLabels: Record<PermissionLevel, string> = {\n none: \"No access\",\n read: \"Read\",\n write: \"Read & Write\",\n };\n const levels: PermissionLevel[] = [\"none\", \"read\", \"write\"];\n\n return (\n <PageSection\n title=\"Permissions\"\n description=\"Define what platform data this app can request access to. Users see these when authorizing the app.\"\n >\n <div className=\"space-y-4\">\n <div className=\"overflow-x-auto 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 w-1/2\">\n Resource\n </th>\n {levels.map((l) => (\n <th\n key={l}\n className=\"px-4 py-3 text-center font-medium text-text-secondary\"\n >\n {levelLabels[l]}\n </th>\n ))}\n </tr>\n </thead>\n <tbody className=\"divide-y divide-border\">\n {PERMISSION_RESOURCES.map((resource) => (\n <tr\n key={resource.id}\n className=\"hover:bg-bg-sunken/30 transition-colors\"\n >\n <td className=\"px-4 py-3\">\n <p className=\"font-medium text-text-primary\">\n {resource.label}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {resource.description}\n </p>\n </td>\n {levels.map((level) => (\n <td key={level} className=\"px-4 py-3 text-center\">\n <input\n type=\"radio\"\n name={`perm-${resource.id}`}\n value={level}\n checked={permissions[resource.id] === level}\n onChange={() => handleChange(resource.id, level)}\n className=\"h-4 w-4 accent-primary cursor-pointer\"\n />\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\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 what\n your app genuinely needs — fewer permissions build more 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 </div>\n </PageSection>\n );\n};\n"],"mappings":"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"}
|