@burdenoff/microfe-devportal 2026.609.3 → 2026.611.1
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.
- package/dist/devportal/DevportalRoot.js +6 -1
- package/dist/devportal/DevportalRoot.js.map +1 -1
- package/dist/devportal/DevportalRoutes.js +169 -158
- package/dist/devportal/DevportalRoutes.js.map +1 -1
- package/dist/devportal/hooks/usePackageUpload.js +120 -0
- package/dist/devportal/hooks/usePackageUpload.js.map +1 -0
- package/dist/devportal/pages/AnalyticsDashboardPage.js +73 -62
- package/dist/devportal/pages/AnalyticsDashboardPage.js.map +1 -1
- package/dist/devportal/pages/AppLogsPage.js +89 -82
- package/dist/devportal/pages/AppLogsPage.js.map +1 -1
- package/dist/devportal/pages/ApplicationDetailPage.js +948 -367
- package/dist/devportal/pages/ApplicationDetailPage.js.map +1 -1
- package/dist/devportal/pages/ApplicationVersionsPage.js +56 -45
- package/dist/devportal/pages/ApplicationVersionsPage.js.map +1 -1
- package/dist/devportal/pages/CreateApiKeyPage.js +30 -32
- package/dist/devportal/pages/CreateApiKeyPage.js.map +1 -1
- package/dist/devportal/pages/CreateApplicationPage.js +8 -3
- package/dist/devportal/pages/CreateApplicationPage.js.map +1 -1
- package/dist/devportal/pages/CreateOAuthClientPage.js +4 -4
- package/dist/devportal/pages/CreateOAuthClientPage.js.map +1 -1
- package/dist/devportal/pages/CreateOrganizationPage.js +233 -228
- package/dist/devportal/pages/CreateOrganizationPage.js.map +1 -1
- package/dist/devportal/pages/CreateWebhookPage.js +159 -148
- package/dist/devportal/pages/CreateWebhookPage.js.map +1 -1
- package/dist/devportal/pages/DelegationsPage.js +1 -1
- package/dist/devportal/pages/DelegationsPage.js.map +1 -1
- package/dist/devportal/pages/EditApplicationPage.js +25 -17
- package/dist/devportal/pages/EditApplicationPage.js.map +1 -1
- package/dist/devportal/pages/ListingPreviewPage.js +159 -153
- package/dist/devportal/pages/ListingPreviewPage.js.map +1 -1
- package/dist/devportal/pages/OAuthClientDetailPage.js.map +1 -1
- package/dist/devportal/pages/OAuthClientsPage.js +2 -2
- package/dist/devportal/pages/OAuthClientsPage.js.map +1 -1
- package/dist/devportal/pages/OrganizationDetailPage.js +158 -153
- package/dist/devportal/pages/OrganizationDetailPage.js.map +1 -1
- package/dist/devportal/pages/OrganizationMembersPage.js +223 -212
- package/dist/devportal/pages/OrganizationMembersPage.js.map +1 -1
- package/dist/devportal/pages/PublishPage.js +172 -165
- package/dist/devportal/pages/PublishPage.js.map +1 -1
- package/dist/devportal/pages/ResourcesPage.js.map +1 -1
- package/dist/devportal/pages/RevenueDashboardPage.js +405 -0
- package/dist/devportal/pages/RevenueDashboardPage.js.map +1 -0
- package/dist/devportal/pages/SetupPage.js +170 -217
- package/dist/devportal/pages/SetupPage.js.map +1 -1
- package/dist/devportal/pages/StoreSubmissionPage.js +76 -97
- package/dist/devportal/pages/StoreSubmissionPage.js.map +1 -1
- package/dist/devportal/pages/WebhookDetailPage.js +172 -154
- package/dist/devportal/pages/WebhookDetailPage.js.map +1 -1
- package/dist/devportal/pages/WebhooksPage.js +218 -200
- package/dist/devportal/pages/WebhooksPage.js.map +1 -1
- package/dist/devportal/providers/DevportalProvider.js +16 -13
- package/dist/devportal/providers/DevportalProvider.js.map +1 -1
- package/dist/devportal/types/index.js.map +1 -1
- package/dist/generated/global-operations.js +310 -225
- package/dist/generated/global-operations.js.map +1 -1
- package/package.json +1 -1
- package/dist/devportal/pages/RevenueRedirectPage.js +0 -14
- package/dist/devportal/pages/RevenueRedirectPage.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OrganizationDetailPage.js","names":[],"sources":["../../../src/devportal/pages/OrganizationDetailPage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useState } from \"react\";\nimport { useParams } from \"react-router-dom\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport {\n Building2,\n Users,\n AppWindow,\n DollarSign,\n Settings,\n ExternalLink,\n CheckCircle,\n BarChart3,\n TrendingUp,\n ArrowRight,\n Plus,\n Edit,\n Shield,\n Loader2,\n AlertCircle,\n} from \"lucide-react\";\nimport { PageLayout, PageSection } from \"../components/PageLayout\";\nimport { StatusBadge, VerifiedBadge } from \"../components/StatusBadge\";\nimport { StatCard, StatCardGrid } from \"../components/StatCard\";\nimport { DataTable, DetailList } from \"../components/DataTable\";\nimport { AppListItem } from \"../components/AppCard\";\nimport { EmptyState } from \"../components/EmptyState\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport { PermissionGuard } from \"../components\";\nimport { DEVPORTAL_PERMISSIONS } from \"../constants/permissions\";\nimport { useDevportalPermission } from \"../hooks/usePermission\";\nimport type {\n DeveloperOrganization,\n Application,\n DeveloperOrgMember,\n} from \"../types\";\nimport { cn } from \"../utils/cn\";\nimport { ORG_ROLE_LABELS } from \"../utils/constants\";\nimport {\n useGetOrganizationQuery,\n useGetApplicationsQuery,\n} from \"../../generated/global-operations\";\nimport type {\n OrganizationFieldsFragment,\n OrgMemberFieldsFragment,\n ApplicationFieldsFragment,\n} from \"../../generated/global-operations\";\n\n/**\n * Map GraphQL organization fragment to local type\n */\nfunction mapOrganization(\n org: OrganizationFieldsFragment,\n): DeveloperOrganization {\n return {\n id: org.id,\n name: org.name,\n slug: org.slug,\n description: org.description ?? undefined,\n logoUrl: org.logoUrl ?? undefined,\n bannerUrl: org.bannerUrl ?? undefined,\n websiteUrl: org.websiteUrl ?? undefined,\n contactEmail: org.contactEmail ?? undefined,\n supportEmail: org.supportEmail ?? undefined,\n tier: org.tier as DeveloperOrganization[\"tier\"],\n partnerTier:\n (org.partnerTier as DeveloperOrganization[\"partnerTier\"]) ?? undefined,\n partnerSince: org.partnerSince ?? undefined,\n isVerified: org.isVerified ?? false,\n verifiedAt: org.verifiedAt ?? undefined,\n isCertified: org.isCertified ?? false,\n certifiedAt: org.certifiedAt ?? undefined,\n totalApps: org.totalApps ?? 0,\n publishedApps: org.publishedApps ?? 0,\n totalInstalls: org.totalInstalls ?? 0,\n activeInstalls: org.activeInstalls ?? 0,\n totalApiCalls: org.totalApiCalls ?? \"0\",\n averageRating: org.averageRating ?? undefined,\n totalRevenue: org.totalRevenue ?? 0,\n totalPlatformFees: org.totalPlatformFees ?? 0,\n totalPayouts: org.totalPayouts ?? 0,\n pendingBalance: org.pendingBalance ?? 0,\n lifetimeRevenue: org.lifetimeRevenue ?? 0,\n platformFeeRate: org.platformFeeRate ?? 0.3,\n apiCallsLimit: org.apiCallsLimit ?? 100000,\n storageLimit: org.storageLimit ?? \"1073741824\",\n apiCallsUsed: org.apiCallsUsed ?? \"0\",\n storageUsed: org.storageUsed ?? \"0\",\n taxId: org.taxId ?? undefined,\n taxCountry: org.taxCountry ?? undefined,\n taxFormVerified: org.taxFormVerified ?? false,\n legalEntityName: org.legalEntityName ?? undefined,\n legalEntityType: org.legalEntityType ?? undefined,\n createdAt: org.createdAt,\n updatedAt: org.updatedAt,\n };\n}\n\n/**\n * Map GraphQL member fragment to local type\n */\nfunction mapMember(member: OrgMemberFieldsFragment): DeveloperOrgMember {\n return {\n id: member.id,\n organizationId: member.organizationId,\n userId: member.userId,\n email: member.email ?? undefined,\n role: member.role as DeveloperOrgMember[\"role\"],\n isActive: member.isActive ?? true,\n isSuspended: member.isSuspended ?? false,\n suspendedAt: member.suspendedAt ?? undefined,\n suspendedReason: member.suspendedReason ?? undefined,\n joinedAt: member.joinedAt,\n lastActiveAt: member.lastActiveAt ?? undefined,\n permissions: member.permissions ?? undefined,\n invitedBy: member.invitedBy ?? undefined,\n invitationId: member.invitationId ?? undefined,\n createdAt: member.createdAt,\n updatedAt: member.updatedAt,\n };\n}\n\ntype TabId = \"overview\" | \"apps\" | \"members\" | \"settings\";\n\n/**\n * Organization detail page\n */\nexport const OrganizationDetailPage: FC = () => {\n const { navigate, basePath } = useDevportal();\n const { orgId: id } = useParams<{ orgId: string }>();\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.ORG_UPDATE,\n );\n const [activeTab, setActiveTab] = useState<TabId>(\"overview\");\n\n const tabs: Array<{ id: TabId; label: string; icon: FC<{ size?: number }> }> =\n [\n {\n id: \"overview\",\n label: tr(\"devportal.overview\", \"Overview\"),\n icon: Building2,\n },\n {\n id: \"apps\",\n label: tr(\"devportal.applications\", \"Applications\"),\n icon: AppWindow,\n },\n { id: \"members\", label: tr(\"devportal.members\", \"Members\"), icon: Users },\n {\n id: \"settings\",\n label: tr(\"devportal.settings\", \"Settings\"),\n icon: Settings,\n },\n ];\n\n // Fetch organization data\n const { data, loading, error } = useGetOrganizationQuery({\n variables: { id: id! },\n skip: !id,\n });\n\n // Fetch applications (filtered client-side for this org until organizationId filter is published to gateway)\n const { data: appsData } = useGetApplicationsQuery({\n variables: { limit: 50 },\n fetchPolicy: \"cache-and-network\",\n });\n\n const handleNavigate = (path: string) => {\n navigate?.(`${basePath}${path}`);\n };\n\n // Loading state\n if (loading) {\n return (\n <PageLayout\n title={tr(\"devportal.loadingDots\", \"Loading...\")}\n backLink={`${basePath}/organizations`}\n backLabel={tr(\"devportal.backToOrganizations\", \"Back to Organizations\")}\n >\n <div className=\"flex items-center justify-center py-12\">\n <Loader2 className=\"h-8 w-8 animate-spin text-muted-foreground\" />\n </div>\n </PageLayout>\n );\n }\n\n // Error state\n if (error || !data?.developerOrganization) {\n return (\n <PageLayout\n title={tr(\"devportal.organizationNotFound\", \"Organization Not Found\")}\n backLink={`${basePath}/organizations`}\n backLabel={tr(\"devportal.backToOrganizations\", \"Back to Organizations\")}\n >\n <div className=\"flex flex-col items-center justify-center py-12 gap-4\">\n <AlertCircle className=\"h-12 w-12 text-destructive\" />\n <h2 className=\"text-lg font-semibold\">\n {tr(\n \"devportal.organizationNotFoundLower\",\n \"Organization not found\",\n )}\n </h2>\n <p className=\"text-muted-foreground\">\n {error?.message ||\n tr(\n \"devportal.organizationNotFoundDescription\",\n \"The organization you're looking for doesn't exist or you don't have access to it.\",\n )}\n </p>\n <button\n onClick={() => handleNavigate(\"/organizations\")}\n className=\"mt-4 inline-flex items-center gap-2 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90\"\n >\n {tr(\"devportal.backToOrganizations\", \"Back to Organizations\")}\n </button>\n </div>\n </PageLayout>\n );\n }\n\n // Map GraphQL data to local types\n const org = mapOrganization(data.developerOrganization);\n const members = (data.developerOrganization.members ?? []).map(mapMember);\n // Filter apps by this org client-side (until organizationId query filter is in gateway supergraph)\n const allApps = (appsData?.applications?.edges?.map(\n (e: { node: ApplicationFieldsFragment }) => e.node,\n ) ?? []) as Application[];\n const apps = id\n ? allApps.filter((app) => app.developerOrganizationId === id)\n : allApps;\n\n // Calculate usage percentages\n const apiCallsUsedNum = parseInt(org.apiCallsUsed);\n const apiCallsPercent = (apiCallsUsedNum / org.apiCallsLimit) * 100;\n const storageUsedNum = parseInt(org.storageUsed);\n const storageLimitNum = parseInt(org.storageLimit);\n const storagePercent = (storageUsedNum / storageLimitNum) * 100;\n\n return (\n <PageLayout\n title={org.name}\n description={org.description}\n backLink={`${basePath}/organizations`}\n backLabel={tr(\"devportal.backToOrganizations\", \"Back to Organizations\")}\n actions={\n <div className=\"flex items-center gap-2\">\n <button\n onClick={() =>\n navigate?.(\n `/billing/earnings?developerOrgId=${encodeURIComponent(org.id)}&developerOrgName=${encodeURIComponent(org.name)}`,\n )\n }\n className=\"inline-flex items-center gap-2 rounded-md border px-4 py-2 text-sm font-medium hover:bg-muted transition-colors\"\n >\n <DollarSign size={16} />\n {tr(\"devportal.revenue\", \"Revenue\")}\n </button>\n <button\n onClick={() => setActiveTab(\"settings\")}\n disabled={!canUpdate}\n aria-disabled={!canUpdate}\n className=\"inline-flex items-center gap-2 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90 transition-colors disabled:opacity-50\"\n >\n <Edit size={16} />\n {tr(\"devportal.settings\", \"Settings\")}\n </button>\n </div>\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.organizationSections\",\n \"Organization sections\",\n )}\n >\n {tabs.map((tab) => {\n const Icon = tab.icon;\n return (\n <button\n key={tab.id}\n id={`organization-tab-${tab.id}`}\n role=\"tab\"\n aria-selected={activeTab === tab.id}\n aria-controls={`organization-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-muted-foreground hover:text-foreground 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={`organization-panel-${activeTab}`}\n role=\"tabpanel\"\n aria-labelledby={`organization-tab-${activeTab}`}\n tabIndex={0}\n >\n {activeTab === \"overview\" && (\n <OverviewTab\n org={org}\n apps={apps}\n members={members}\n apiCallsPercent={apiCallsPercent}\n storagePercent={storagePercent}\n onNavigate={handleNavigate}\n onShowApps={() => setActiveTab(\"apps\")}\n />\n )}\n {activeTab === \"apps\" && (\n <AppsTab apps={apps} onNavigate={handleNavigate} />\n )}\n {activeTab === \"members\" && (\n <MembersTab\n members={members}\n onNavigate={handleNavigate}\n orgId={org.id}\n />\n )}\n {activeTab === \"settings\" && <SettingsTab org={org} />}\n </div>\n </PageLayout>\n );\n};\n\n// Overview Tab\nconst OverviewTab: FC<{\n org: DeveloperOrganization;\n apps: Application[];\n members: DeveloperOrgMember[];\n apiCallsPercent: number;\n storagePercent: number;\n onNavigate: (path: string) => void;\n onShowApps: () => void;\n}> = ({\n org,\n apps,\n members,\n apiCallsPercent,\n storagePercent,\n onNavigate,\n onShowApps,\n}) => {\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n };\n\n return (\n <div className=\"grid gap-6 lg:grid-cols-3\">\n <div className=\"lg:col-span-2 space-y-6\">\n {/* Stats */}\n <StatCardGrid columns={4}>\n <StatCard\n title={tr(\"devportal.publishedApps\", \"Published Apps\")}\n value={`${org.publishedApps}/${org.totalApps}`}\n icon={<AppWindow size={20} />}\n />\n <StatCard\n title={tr(\"devportal.totalInstalls\", \"Total Installs\")}\n value={org.totalInstalls.toLocaleString()}\n icon={<TrendingUp size={20} />}\n trend={{\n value: 12,\n label: tr(\"devportal.thisMonth\", \"this month\"),\n }}\n />\n <StatCard\n title={tr(\"devportal.totalRevenue\", \"Total Revenue\")}\n value={`$${org.totalRevenue.toLocaleString()}`}\n icon={<DollarSign size={20} />}\n />\n <StatCard\n title={tr(\"devportal.avgRating\", \"Avg Rating\")}\n value={\n org.averageRating\n ? `${org.averageRating.toFixed(1)} ★`\n : tr(\"devportal.notAvailable\", \"N/A\")\n }\n icon={<BarChart3 size={20} />}\n />\n </StatCardGrid>\n\n {/* Recent Apps */}\n <PageSection\n title={tr(\"devportal.recentApplications\", \"Recent Applications\")}\n actions={\n <button\n onClick={onShowApps}\n className=\"text-sm text-primary hover:underline flex items-center gap-1\"\n >\n {tr(\"devportal.viewAll\", \"View all\")} <ArrowRight size={14} />\n </button>\n }\n >\n {apps.length > 0 ? (\n <div className=\"space-y-2\">\n {apps.slice(0, 3).map((app) => (\n <AppListItem\n key={app.id}\n app={app}\n onClick={() => onNavigate(`/apps/${app.id}`)}\n />\n ))}\n </div>\n ) : (\n <EmptyState\n icon={<AppWindow size={24} />}\n title={tr(\"devportal.noApplications\", \"No applications\")}\n description={tr(\n \"devportal.createYourFirstApplication\",\n \"Create your first application\",\n )}\n />\n )}\n </PageSection>\n\n {/* Usage Quotas */}\n <PageSection title={tr(\"devportal.usageAndQuotas\", \"Usage & Quotas\")}>\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <UsageCard\n label={tr(\"devportal.apiCalls\", \"API Calls\")}\n used={parseInt(org.apiCallsUsed)}\n limit={org.apiCallsLimit}\n percent={apiCallsPercent}\n format=\"number\"\n />\n <UsageCard\n label={tr(\"devportal.storage\", \"Storage\")}\n used={parseInt(org.storageUsed)}\n limit={parseInt(org.storageLimit)}\n percent={storagePercent}\n format=\"bytes\"\n />\n </div>\n {org.quotaResetAt && (\n <p className=\"text-xs text-muted-foreground mt-2\">\n {tr(\"devportal.quotasResetOn\", \"Quotas reset on\")}{\" \"}\n {new Date(org.quotaResetAt).toLocaleDateString()}\n </p>\n )}\n </PageSection>\n </div>\n\n {/* Sidebar */}\n <div className=\"space-y-6\">\n {/* Quick Stats */}\n <PageSection title={tr(\"devportal.revenueSummary\", \"Revenue Summary\")}>\n <DetailList\n items={[\n {\n label: tr(\"devportal.totalRevenue\", \"Total Revenue\"),\n value: `$${org.totalRevenue.toLocaleString()}`,\n },\n {\n label: tr(\"devportal.platformFees\", \"Platform Fees\"),\n value: `$${org.totalPlatformFees.toLocaleString()}`,\n },\n {\n label: tr(\"devportal.netPayouts\", \"Net Payouts\"),\n value: `$${org.totalPayouts.toLocaleString()}`,\n },\n {\n label: tr(\"devportal.pendingBalance\", \"Pending Balance\"),\n value: `$${org.pendingBalance.toLocaleString()}`,\n },\n {\n label: tr(\"devportal.lifetimeRevenue\", \"Lifetime Revenue\"),\n value: `$${org.lifetimeRevenue.toLocaleString()}`,\n },\n ]}\n />\n </PageSection>\n\n {/* Team */}\n <PageSection\n title={tr(\"devportal.teamMembers\", \"Team Members\")}\n actions={\n <button\n onClick={() => onNavigate(`/organizations/${org.id}/members`)}\n className=\"text-sm text-primary hover:underline\"\n >\n {tr(\"devportal.manage\", \"Manage\")}\n </button>\n }\n >\n <div className=\"space-y-2\">\n {members.slice(0, 3).map((member) => (\n <div\n key={member.id}\n className=\"flex items-center justify-between py-2\"\n >\n <div className=\"flex items-center gap-3\">\n <div className=\"h-8 w-8 rounded-full bg-primary/10 flex items-center justify-center text-sm font-medium text-primary\">\n {member.email?.charAt(0).toUpperCase() || \"U\"}\n </div>\n <div>\n <p className=\"text-sm font-medium\">{member.email}</p>\n <p className=\"text-xs text-muted-foreground\">\n {ORG_ROLE_LABELS[member.role]}\n </p>\n </div>\n </div>\n </div>\n ))}\n {members.length > 3 && (\n <p className=\"text-xs text-muted-foreground\">\n +{members.length - 3}{\" \"}\n {tr(\"devportal.moreMembers\", \"more members\")}\n </p>\n )}\n </div>\n </PageSection>\n\n {/* Links */}\n <PageSection title={tr(\"devportal.links\", \"Links\")}>\n <div className=\"space-y-2\">\n {org.websiteUrl && (\n <a\n href={org.websiteUrl}\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 {tr(\"devportal.website\", \"Website\")}\n </a>\n )}\n {org.contactEmail && (\n <a\n href={`mailto:${org.contactEmail}`}\n className=\"flex items-center gap-2 text-sm text-primary hover:underline\"\n >\n <ExternalLink size={14} />\n {org.contactEmail}\n </a>\n )}\n </div>\n </PageSection>\n </div>\n </div>\n );\n};\n\n// Apps Tab\nconst AppsTab: FC<{\n apps: Application[];\n onNavigate: (path: string) => void;\n}> = ({ apps, 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-muted-foreground\">\n {apps.length}{\" \"}\n {apps.length !== 1\n ? tr(\"devportal.applications\", \"applications\")\n : tr(\"devportal.application\", \"application\")}\n </p>\n <button\n onClick={() => onNavigate(\"/apps/new\")}\n className=\"inline-flex items-center gap-2 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90 transition-colors\"\n >\n <Plus size={16} />\n {tr(\"devportal.createApp\", \"Create App\")}\n </button>\n </div>\n\n {apps.length > 0 ? (\n <div className=\"space-y-2\">\n {apps.map((app) => (\n <AppListItem\n key={app.id}\n app={app}\n onClick={() => onNavigate(`/apps/${app.id}`)}\n />\n ))}\n </div>\n ) : (\n <EmptyState\n icon={<AppWindow size={32} />}\n title={tr(\"devportal.noApplications\", \"No applications\")}\n description={tr(\n \"devportal.createFirstAppForOrg\",\n \"Create your first application for this organization\",\n )}\n action={\n <button\n onClick={() => onNavigate(\"/apps/new\")}\n className=\"inline-flex items-center gap-2 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90\"\n >\n <Plus size={16} />\n {tr(\"devportal.createApp\", \"Create App\")}\n </button>\n }\n />\n )}\n </div>\n );\n};\n\n// Members Tab\nconst MembersTab: FC<{\n members: DeveloperOrgMember[];\n onNavigate: (path: string) => void;\n orgId: string;\n}> = ({ members, onNavigate, orgId }) => {\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-muted-foreground\">\n {members.length}{\" \"}\n {members.length !== 1\n ? tr(\"devportal.membersLower\", \"members\")\n : tr(\"devportal.memberLower\", \"member\")}\n </p>\n <button\n onClick={() => onNavigate(`/organizations/${orgId}/members`)}\n className=\"inline-flex items-center gap-2 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90 transition-colors\"\n >\n <Plus size={16} />\n {tr(\"devportal.inviteMember\", \"Invite Member\")}\n </button>\n </div>\n\n <DataTable\n data={members}\n keyField=\"id\"\n columns={[\n {\n key: \"email\",\n header: tr(\"devportal.memberColumn\", \"Member\"),\n render: (member) => (\n <div className=\"flex items-center gap-3\">\n <div className=\"h-8 w-8 rounded-full bg-primary/10 flex items-center justify-center text-sm font-medium text-primary\">\n {member.email?.charAt(0).toUpperCase() || \"U\"}\n </div>\n <span className=\"font-medium\">{member.email}</span>\n </div>\n ),\n },\n {\n key: \"role\",\n header: tr(\"devportal.roleColumn\", \"Role\"),\n render: (member) => (\n <span\n className={cn(\n \"inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium\",\n member.role === \"OWNER\"\n ? \"bg-accent-purple-subtle text-accent-purple\"\n : member.role === \"ADMIN\"\n ? \"bg-status-info-bg-subtle text-status-info-text\"\n : member.role === \"DEVELOPER\"\n ? \"bg-status-success-bg-subtle text-status-success-text\"\n : \"bg-bg-sunken text-text-primary\",\n )}\n >\n {ORG_ROLE_LABELS[member.role]}\n </span>\n ),\n },\n {\n key: \"joinedAt\",\n header: tr(\"devportal.joinedColumn\", \"Joined\"),\n render: (member) => new Date(member.joinedAt).toLocaleDateString(),\n },\n {\n key: \"lastActiveAt\",\n header: tr(\"devportal.lastActiveColumn\", \"Last Active\"),\n render: (member) =>\n member.lastActiveAt\n ? new Date(member.lastActiveAt).toLocaleDateString()\n : tr(\"devportal.never\", \"Never\"),\n },\n ]}\n />\n </div>\n );\n};\n\n// Settings Tab\nconst SettingsTab: FC<{ org: DeveloperOrganization }> = ({ org }) => {\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 max-w-2xl\">\n <PageSection\n title={tr(\"devportal.organizationDetails\", \"Organization Details\")}\n >\n <DetailList\n items={[\n {\n label: tr(\"devportal.organizationId\", \"Organization ID\"),\n value: <code className=\"text-xs\">{org.id}</code>,\n },\n { label: tr(\"devportal.slug\", \"Slug\"), value: org.slug },\n { label: tr(\"devportal.tier\", \"Tier\"), value: org.tier },\n {\n label: tr(\"devportal.partnerTier\", \"Partner Tier\"),\n value: org.partnerTier || tr(\"devportal.none\", \"None\"),\n },\n {\n label: tr(\"devportal.created\", \"Created\"),\n value: new Date(org.createdAt).toLocaleDateString(),\n },\n {\n label: tr(\"devportal.platformFeeRate\", \"Platform Fee Rate\"),\n value: `${(org.platformFeeRate * 100).toFixed(0)}%`,\n },\n ]}\n />\n </PageSection>\n\n <PageSection\n title={tr(\"devportal.legalInformation\", \"Legal Information\")}\n >\n <DetailList\n items={[\n {\n label: tr(\"devportal.legalEntityName\", \"Legal Entity Name\"),\n value:\n org.legalEntityName ||\n tr(\"devportal.notProvided\", \"Not provided\"),\n },\n {\n label: tr(\"devportal.entityType\", \"Entity Type\"),\n value:\n org.legalEntityType ||\n tr(\"devportal.notProvided\", \"Not provided\"),\n },\n {\n label: tr(\"devportal.taxId\", \"Tax ID\"),\n value: org.taxId\n ? `•••••${org.taxId.slice(-4)}`\n : tr(\"devportal.notProvided\", \"Not provided\"),\n },\n {\n label: tr(\"devportal.taxCountry\", \"Tax Country\"),\n value:\n org.taxCountry || tr(\"devportal.notProvided\", \"Not provided\"),\n },\n {\n label: tr(\"devportal.taxForm\", \"Tax Form\"),\n value:\n org.taxFormType ||\n tr(\"devportal.notSubmitted\", \"Not submitted\"),\n },\n {\n label: tr(\"devportal.taxFormStatus\", \"Tax Form Status\"),\n value: org.taxFormVerified ? (\n <span className=\"text-status-success-text flex items-center gap-1\">\n <CheckCircle size={14} />{\" \"}\n {tr(\"devportal.verified\", \"Verified\")}\n </span>\n ) : (\n tr(\"devportal.pendingVerification\", \"Pending verification\")\n ),\n },\n ]}\n />\n </PageSection>\n\n <PageSection\n title={tr(\"devportal.verificationStatus\", \"Verification Status\")}\n >\n <DetailList\n items={[\n {\n label: tr(\"devportal.verifiedLabel\", \"Verified\"),\n value: org.isVerified ? (\n <span className=\"text-status-success-text flex items-center gap-1\">\n <CheckCircle size={14} />{\" \"}\n {tr(\"devportal.verifiedVia\", \"Verified via\")}{\" \"}\n {org.verificationMethod}\n </span>\n ) : (\n tr(\"devportal.notVerified\", \"Not verified\")\n ),\n },\n {\n label: tr(\"devportal.certifiedLabel\", \"Certified\"),\n value: org.isCertified ? (\n <span className=\"text-accent-blue flex items-center gap-1\">\n <Shield size={14} />{\" \"}\n {tr(\"devportal.certifiedUntil\", \"Certified until\")}{\" \"}\n {org.certificationExpiry\n ? new Date(org.certificationExpiry).toLocaleDateString()\n : \"N/A\"}\n </span>\n ) : (\n tr(\"devportal.notCertified\", \"Not certified\")\n ),\n },\n ]}\n />\n </PageSection>\n </div>\n );\n};\n\n// Usage Card Component\nconst UsageCard: FC<{\n label: string;\n used: number;\n limit: number;\n percent: number;\n format: \"number\" | \"bytes\";\n}> = ({ label, used, limit, percent, format }) => {\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 formatValue = (value: number): string => {\n if (format === \"bytes\") {\n const gb = value / (1024 * 1024 * 1024);\n return `${gb.toFixed(1)} GB`;\n }\n if (value >= 1000000) {\n return `${(value / 1000000).toFixed(1)}M`;\n }\n if (value >= 1000) {\n return `${(value / 1000).toFixed(1)}K`;\n }\n return value.toLocaleString();\n };\n\n return (\n <div className=\"rounded-lg border p-4\">\n <div className=\"flex items-center justify-between mb-2\">\n <span className=\"text-sm font-medium\">{label}</span>\n <span className=\"text-xs text-muted-foreground\">\n {formatValue(used)} / {formatValue(limit)}\n </span>\n </div>\n <div className=\"h-2 rounded-full bg-muted overflow-hidden\">\n <div\n className={cn(\n \"h-full rounded-full transition-all\",\n percent > 90\n ? \"bg-status-error-bg-subtle\"\n : percent > 70\n ? \"bg-status-warning-bg-subtle\"\n : \"bg-primary\",\n )}\n style={{ width: `${Math.min(percent, 100)}%` }}\n />\n </div>\n <p className=\"text-xs text-muted-foreground mt-1\">\n {percent.toFixed(1)}% {tr(\"devportal.used\", \"used\")}\n </p>\n </div>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"OrganizationDetailPage.js","names":[],"sources":["../../../src/devportal/pages/OrganizationDetailPage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useState, useEffect } from \"react\";\nimport { useParams } from \"react-router-dom\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport {\n Building2,\n Users,\n AppWindow,\n DollarSign,\n Settings,\n ExternalLink,\n CheckCircle,\n BarChart3,\n TrendingUp,\n ArrowRight,\n Plus,\n Edit,\n Shield,\n Loader2,\n AlertCircle,\n} from \"lucide-react\";\nimport { PageLayout, PageSection } from \"../components/PageLayout\";\nimport { StatCard, StatCardGrid } from \"../components/StatCard\";\nimport { DataTable, DetailList } from \"../components/DataTable\";\nimport { AppListItem } from \"../components/AppCard\";\nimport { EmptyState } from \"../components/EmptyState\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport { DEVPORTAL_PERMISSIONS } from \"../constants/permissions\";\nimport { useDevportalPermission } from \"../hooks/usePermission\";\nimport type {\n DeveloperOrganization,\n Application,\n DeveloperOrgMember,\n} from \"../types\";\nimport { cn } from \"../utils/cn\";\nimport { ORG_ROLE_LABELS } from \"../utils/constants\";\nimport {\n useGetOrganizationQuery,\n useGetApplicationsQuery,\n} from \"../../generated/global-operations\";\nimport type {\n OrganizationFieldsFragment,\n OrgMemberFieldsFragment,\n ApplicationFieldsFragment,\n} from \"../../generated/global-operations\";\n\n/**\n * Map GraphQL organization fragment to local type\n */\nfunction mapOrganization(\n org: OrganizationFieldsFragment,\n): DeveloperOrganization {\n return {\n id: org.id,\n name: org.name,\n slug: org.slug,\n description: org.description ?? undefined,\n logoUrl: org.logoUrl ?? undefined,\n bannerUrl: org.bannerUrl ?? undefined,\n websiteUrl: org.websiteUrl ?? undefined,\n contactEmail: org.contactEmail ?? undefined,\n supportEmail: org.supportEmail ?? undefined,\n tier: org.tier as DeveloperOrganization[\"tier\"],\n partnerTier:\n (org.partnerTier as DeveloperOrganization[\"partnerTier\"]) ?? undefined,\n partnerSince: org.partnerSince ?? undefined,\n isVerified: org.isVerified ?? false,\n verifiedAt: org.verifiedAt ?? undefined,\n isCertified: org.isCertified ?? false,\n certifiedAt: org.certifiedAt ?? undefined,\n totalApps: org.totalApps ?? 0,\n publishedApps: org.publishedApps ?? 0,\n totalInstalls: org.totalInstalls ?? 0,\n activeInstalls: org.activeInstalls ?? 0,\n totalApiCalls: org.totalApiCalls ?? \"0\",\n averageRating: org.averageRating ?? undefined,\n totalRevenue: org.totalRevenue ?? 0,\n totalPlatformFees: org.totalPlatformFees ?? 0,\n totalPayouts: org.totalPayouts ?? 0,\n pendingBalance: org.pendingBalance ?? 0,\n lifetimeRevenue: org.lifetimeRevenue ?? 0,\n platformFeeRate: org.platformFeeRate ?? 0.3,\n apiCallsLimit: org.apiCallsLimit ?? 100000,\n storageLimit: org.storageLimit ?? \"1073741824\",\n apiCallsUsed: org.apiCallsUsed ?? \"0\",\n storageUsed: org.storageUsed ?? \"0\",\n taxId: org.taxId ?? undefined,\n taxCountry: org.taxCountry ?? undefined,\n taxFormVerified: org.taxFormVerified ?? false,\n legalEntityName: org.legalEntityName ?? undefined,\n legalEntityType: org.legalEntityType ?? undefined,\n createdAt: org.createdAt,\n updatedAt: org.updatedAt,\n };\n}\n\n/**\n * Map GraphQL member fragment to local type\n */\nfunction mapMember(member: OrgMemberFieldsFragment): DeveloperOrgMember {\n return {\n id: member.id,\n organizationId: member.organizationId,\n userId: member.userId,\n email: member.email ?? undefined,\n role: member.role as DeveloperOrgMember[\"role\"],\n isActive: member.isActive ?? true,\n isSuspended: member.isSuspended ?? false,\n suspendedAt: member.suspendedAt ?? undefined,\n suspendedReason: member.suspendedReason ?? undefined,\n joinedAt: member.joinedAt,\n lastActiveAt: member.lastActiveAt ?? undefined,\n permissions: member.permissions ?? undefined,\n invitedBy: member.invitedBy ?? undefined,\n invitationId: member.invitationId ?? undefined,\n createdAt: member.createdAt,\n updatedAt: member.updatedAt,\n };\n}\n\ntype TabId = \"overview\" | \"apps\" | \"members\" | \"settings\";\n\n/**\n * Organization detail page\n */\nexport const OrganizationDetailPage: FC = () => {\n const { navigate, basePath } = useDevportal();\n const { orgId: id } = useParams<{ orgId: string }>();\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.ORG_UPDATE,\n );\n const [activeTab, setActiveTab] = useState<TabId>(\"overview\");\n\n const tabs: Array<{ id: TabId; label: string; icon: FC<{ size?: number }> }> =\n [\n {\n id: \"overview\",\n label: tr(\"devportal.overview\", \"Overview\"),\n icon: Building2,\n },\n {\n id: \"apps\",\n label: tr(\"devportal.applications\", \"Applications\"),\n icon: AppWindow,\n },\n { id: \"members\", label: tr(\"devportal.members\", \"Members\"), icon: Users },\n {\n id: \"settings\",\n label: tr(\"devportal.settings\", \"Settings\"),\n icon: Settings,\n },\n ];\n\n // Fetch organization data\n const { data, loading, error } = useGetOrganizationQuery({\n variables: { id: id! },\n skip: !id,\n });\n\n // Fetch applications (filtered client-side for this org until organizationId filter is published to gateway)\n const { data: appsData } = useGetApplicationsQuery({\n variables: { limit: 50 },\n fetchPolicy: \"cache-and-network\",\n });\n\n const handleNavigate = (path: string) => {\n navigate?.(`${basePath}${path}`);\n };\n\n // Register org name in breadcrumb registry so the URL ID shows as the org name\n useEffect(() => {\n const name = data?.developerOrganization?.name;\n if (!id || !name) return;\n const reg = (\n window as unknown as {\n __breadcrumbRegistry?: {\n register: (id: string, name: string) => void;\n unregister: (id: string) => void;\n };\n }\n ).__breadcrumbRegistry;\n reg?.register(id, name);\n return () => reg?.unregister(id);\n }, [id, data?.developerOrganization?.name]);\n\n // Loading state\n if (loading) {\n return (\n <PageLayout\n title={tr(\"devportal.loadingDots\", \"Loading...\")}\n backLink={`${basePath}/organizations`}\n backLabel={tr(\"devportal.backToOrganizations\", \"Back to Organizations\")}\n >\n <div className=\"flex items-center justify-center py-12\">\n <Loader2 className=\"h-8 w-8 animate-spin text-muted-foreground\" />\n </div>\n </PageLayout>\n );\n }\n\n // Error state\n if (error || !data?.developerOrganization) {\n return (\n <PageLayout\n title={tr(\"devportal.organizationNotFound\", \"Organization Not Found\")}\n backLink={`${basePath}/organizations`}\n backLabel={tr(\"devportal.backToOrganizations\", \"Back to Organizations\")}\n >\n <div className=\"flex flex-col items-center justify-center py-12 gap-4\">\n <AlertCircle className=\"h-12 w-12 text-destructive\" />\n <h2 className=\"text-lg font-semibold\">\n {tr(\n \"devportal.organizationNotFoundLower\",\n \"Organization not found\",\n )}\n </h2>\n <p className=\"text-muted-foreground\">\n {error?.message ||\n tr(\n \"devportal.organizationNotFoundDescription\",\n \"The organization you're looking for doesn't exist or you don't have access to it.\",\n )}\n </p>\n <button\n onClick={() => handleNavigate(\"/organizations\")}\n className=\"mt-4 inline-flex items-center gap-2 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90\"\n >\n {tr(\"devportal.backToOrganizations\", \"Back to Organizations\")}\n </button>\n </div>\n </PageLayout>\n );\n }\n\n // Map GraphQL data to local types\n const org = mapOrganization(data.developerOrganization);\n const members = (data.developerOrganization.members ?? []).map(mapMember);\n // Filter apps by this org client-side (until organizationId query filter is in gateway supergraph)\n const allApps = (appsData?.applications?.edges?.map(\n (e: { node: ApplicationFieldsFragment }) => e.node,\n ) ?? []) as Application[];\n const apps = id\n ? allApps.filter((app) => app.developerOrganizationId === id)\n : allApps;\n\n // Calculate usage percentages\n const apiCallsUsedNum = parseInt(org.apiCallsUsed);\n const apiCallsPercent = (apiCallsUsedNum / org.apiCallsLimit) * 100;\n const storageUsedNum = parseInt(org.storageUsed);\n const storageLimitNum = parseInt(org.storageLimit);\n const storagePercent = (storageUsedNum / storageLimitNum) * 100;\n\n return (\n <PageLayout\n title={org.name}\n description={org.description}\n backLink={`${basePath}/organizations`}\n backLabel={tr(\"devportal.backToOrganizations\", \"Back to Organizations\")}\n actions={\n <div className=\"flex items-center gap-2\">\n <button\n onClick={() =>\n navigate?.(\n `/billing/earnings?developerOrgId=${encodeURIComponent(org.id)}&developerOrgName=${encodeURIComponent(org.name)}`,\n )\n }\n className=\"inline-flex items-center gap-2 rounded-md border px-4 py-2 text-sm font-medium hover:bg-muted transition-colors\"\n >\n <DollarSign size={16} />\n {tr(\"devportal.revenue\", \"Revenue\")}\n </button>\n <button\n onClick={() => setActiveTab(\"settings\")}\n disabled={!canUpdate}\n aria-disabled={!canUpdate}\n className=\"inline-flex items-center gap-2 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90 transition-colors disabled:opacity-50\"\n >\n <Edit size={16} />\n {tr(\"devportal.settings\", \"Settings\")}\n </button>\n </div>\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.organizationSections\",\n \"Organization sections\",\n )}\n >\n {tabs.map((tab) => {\n const Icon = tab.icon;\n return (\n <button\n key={tab.id}\n id={`organization-tab-${tab.id}`}\n role=\"tab\"\n aria-selected={activeTab === tab.id}\n aria-controls={`organization-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-muted-foreground hover:text-foreground 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={`organization-panel-${activeTab}`}\n role=\"tabpanel\"\n aria-labelledby={`organization-tab-${activeTab}`}\n tabIndex={0}\n >\n {activeTab === \"overview\" && (\n <OverviewTab\n org={org}\n apps={apps}\n members={members}\n apiCallsPercent={apiCallsPercent}\n storagePercent={storagePercent}\n onNavigate={handleNavigate}\n onShowApps={() => setActiveTab(\"apps\")}\n />\n )}\n {activeTab === \"apps\" && (\n <AppsTab apps={apps} onNavigate={handleNavigate} />\n )}\n {activeTab === \"members\" && (\n <MembersTab\n members={members}\n onNavigate={handleNavigate}\n orgId={org.id}\n />\n )}\n {activeTab === \"settings\" && <SettingsTab org={org} />}\n </div>\n </PageLayout>\n );\n};\n\n// Overview Tab\nconst OverviewTab: FC<{\n org: DeveloperOrganization;\n apps: Application[];\n members: DeveloperOrgMember[];\n apiCallsPercent: number;\n storagePercent: number;\n onNavigate: (path: string) => void;\n onShowApps: () => void;\n}> = ({\n org,\n apps,\n members,\n apiCallsPercent,\n storagePercent,\n onNavigate,\n onShowApps,\n}) => {\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n };\n\n return (\n <div className=\"grid gap-6 lg:grid-cols-3\">\n <div className=\"lg:col-span-2 space-y-6\">\n {/* Stats */}\n <StatCardGrid columns={4}>\n <StatCard\n title={tr(\"devportal.publishedApps\", \"Published Apps\")}\n value={`${org.publishedApps}/${org.totalApps}`}\n icon={<AppWindow size={20} />}\n />\n <StatCard\n title={tr(\"devportal.totalInstalls\", \"Total Installs\")}\n value={org.totalInstalls.toLocaleString()}\n icon={<TrendingUp size={20} />}\n trend={{\n value: 12,\n label: tr(\"devportal.thisMonth\", \"this month\"),\n }}\n />\n <StatCard\n title={tr(\"devportal.totalRevenue\", \"Total Revenue\")}\n value={`$${org.totalRevenue.toLocaleString()}`}\n icon={<DollarSign size={20} />}\n />\n <StatCard\n title={tr(\"devportal.avgRating\", \"Avg Rating\")}\n value={\n org.averageRating\n ? `${org.averageRating.toFixed(1)} ★`\n : tr(\"devportal.notAvailable\", \"N/A\")\n }\n icon={<BarChart3 size={20} />}\n />\n </StatCardGrid>\n\n {/* Recent Apps */}\n <PageSection\n title={tr(\"devportal.recentApplications\", \"Recent Applications\")}\n actions={\n <button\n onClick={onShowApps}\n className=\"text-sm text-primary hover:underline flex items-center gap-1\"\n >\n {tr(\"devportal.viewAll\", \"View all\")} <ArrowRight size={14} />\n </button>\n }\n >\n {apps.length > 0 ? (\n <div className=\"space-y-2\">\n {apps.slice(0, 3).map((app) => (\n <AppListItem\n key={app.id}\n app={app}\n onClick={() => onNavigate(`/apps/${app.id}`)}\n />\n ))}\n </div>\n ) : (\n <EmptyState\n icon={<AppWindow size={24} />}\n title={tr(\"devportal.noApplications\", \"No applications\")}\n description={tr(\n \"devportal.createYourFirstApplication\",\n \"Create your first application\",\n )}\n />\n )}\n </PageSection>\n\n {/* Usage Quotas */}\n <PageSection title={tr(\"devportal.usageAndQuotas\", \"Usage & Quotas\")}>\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <UsageCard\n label={tr(\"devportal.apiCalls\", \"API Calls\")}\n used={parseInt(org.apiCallsUsed)}\n limit={org.apiCallsLimit}\n percent={apiCallsPercent}\n format=\"number\"\n />\n <UsageCard\n label={tr(\"devportal.storage\", \"Storage\")}\n used={parseInt(org.storageUsed)}\n limit={parseInt(org.storageLimit)}\n percent={storagePercent}\n format=\"bytes\"\n />\n </div>\n {org.quotaResetAt && (\n <p className=\"text-xs text-muted-foreground mt-2\">\n {tr(\"devportal.quotasResetOn\", \"Quotas reset on\")}{\" \"}\n {new Date(org.quotaResetAt).toLocaleDateString()}\n </p>\n )}\n </PageSection>\n </div>\n\n {/* Sidebar */}\n <div className=\"space-y-6\">\n {/* Quick Stats */}\n <PageSection title={tr(\"devportal.revenueSummary\", \"Revenue Summary\")}>\n <DetailList\n items={[\n {\n label: tr(\"devportal.totalRevenue\", \"Total Revenue\"),\n value: `$${org.totalRevenue.toLocaleString()}`,\n },\n {\n label: tr(\"devportal.platformFees\", \"Platform Fees\"),\n value: `$${org.totalPlatformFees.toLocaleString()}`,\n },\n {\n label: tr(\"devportal.netPayouts\", \"Net Payouts\"),\n value: `$${org.totalPayouts.toLocaleString()}`,\n },\n {\n label: tr(\"devportal.pendingBalance\", \"Pending Balance\"),\n value: `$${org.pendingBalance.toLocaleString()}`,\n },\n {\n label: tr(\"devportal.lifetimeRevenue\", \"Lifetime Revenue\"),\n value: `$${org.lifetimeRevenue.toLocaleString()}`,\n },\n ]}\n />\n </PageSection>\n\n {/* Team */}\n <PageSection\n title={tr(\"devportal.teamMembers\", \"Team Members\")}\n actions={\n <button\n onClick={() => onNavigate(`/organizations/${org.id}/members`)}\n className=\"text-sm text-primary hover:underline\"\n >\n {tr(\"devportal.manage\", \"Manage\")}\n </button>\n }\n >\n <div className=\"space-y-2\">\n {members.slice(0, 3).map((member) => (\n <div\n key={member.id}\n className=\"flex items-center justify-between py-2\"\n >\n <div className=\"flex items-center gap-3\">\n <div className=\"h-8 w-8 rounded-full bg-primary/10 flex items-center justify-center text-sm font-medium text-primary\">\n {member.email?.charAt(0).toUpperCase() || \"U\"}\n </div>\n <div>\n <p className=\"text-sm font-medium\">{member.email}</p>\n <p className=\"text-xs text-muted-foreground\">\n {ORG_ROLE_LABELS[member.role]}\n </p>\n </div>\n </div>\n </div>\n ))}\n {members.length > 3 && (\n <p className=\"text-xs text-muted-foreground\">\n +{members.length - 3}{\" \"}\n {tr(\"devportal.moreMembers\", \"more members\")}\n </p>\n )}\n </div>\n </PageSection>\n\n {/* Links */}\n <PageSection title={tr(\"devportal.links\", \"Links\")}>\n <div className=\"space-y-2\">\n {org.websiteUrl && (\n <a\n href={org.websiteUrl}\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 {tr(\"devportal.website\", \"Website\")}\n </a>\n )}\n {org.contactEmail && (\n <a\n href={`mailto:${org.contactEmail}`}\n className=\"flex items-center gap-2 text-sm text-primary hover:underline\"\n >\n <ExternalLink size={14} />\n {org.contactEmail}\n </a>\n )}\n </div>\n </PageSection>\n </div>\n </div>\n );\n};\n\n// Apps Tab\nconst AppsTab: FC<{\n apps: Application[];\n onNavigate: (path: string) => void;\n}> = ({ apps, 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-muted-foreground\">\n {apps.length}{\" \"}\n {apps.length !== 1\n ? tr(\"devportal.applications\", \"applications\")\n : tr(\"devportal.application\", \"application\")}\n </p>\n <button\n onClick={() => onNavigate(\"/apps/new\")}\n className=\"inline-flex items-center gap-2 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90 transition-colors\"\n >\n <Plus size={16} />\n {tr(\"devportal.createApp\", \"Create App\")}\n </button>\n </div>\n\n {apps.length > 0 ? (\n <div className=\"space-y-2\">\n {apps.map((app) => (\n <AppListItem\n key={app.id}\n app={app}\n onClick={() => onNavigate(`/apps/${app.id}`)}\n />\n ))}\n </div>\n ) : (\n <EmptyState\n icon={<AppWindow size={32} />}\n title={tr(\"devportal.noApplications\", \"No applications\")}\n description={tr(\n \"devportal.createFirstAppForOrg\",\n \"Create your first application for this organization\",\n )}\n action={\n <button\n onClick={() => onNavigate(\"/apps/new\")}\n className=\"inline-flex items-center gap-2 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90\"\n >\n <Plus size={16} />\n {tr(\"devportal.createApp\", \"Create App\")}\n </button>\n }\n />\n )}\n </div>\n );\n};\n\n// Members Tab\nconst MembersTab: FC<{\n members: DeveloperOrgMember[];\n onNavigate: (path: string) => void;\n orgId: string;\n}> = ({ members, onNavigate, orgId }) => {\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-muted-foreground\">\n {members.length}{\" \"}\n {members.length !== 1\n ? tr(\"devportal.membersLower\", \"members\")\n : tr(\"devportal.memberLower\", \"member\")}\n </p>\n <button\n onClick={() => onNavigate(`/organizations/${orgId}/members`)}\n className=\"inline-flex items-center gap-2 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90 transition-colors\"\n >\n <Plus size={16} />\n {tr(\"devportal.inviteMember\", \"Invite Member\")}\n </button>\n </div>\n\n <DataTable\n data={members}\n keyField=\"id\"\n columns={[\n {\n key: \"email\",\n header: tr(\"devportal.memberColumn\", \"Member\"),\n render: (member) => (\n <div className=\"flex items-center gap-3\">\n <div className=\"h-8 w-8 rounded-full bg-primary/10 flex items-center justify-center text-sm font-medium text-primary\">\n {member.email?.charAt(0).toUpperCase() || \"U\"}\n </div>\n <span className=\"font-medium\">{member.email}</span>\n </div>\n ),\n },\n {\n key: \"role\",\n header: tr(\"devportal.roleColumn\", \"Role\"),\n render: (member) => (\n <span\n className={cn(\n \"inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium\",\n member.role === \"OWNER\"\n ? \"bg-accent-purple-subtle text-accent-purple\"\n : member.role === \"ADMIN\"\n ? \"bg-status-info-bg-subtle text-status-info-text\"\n : member.role === \"DEVELOPER\"\n ? \"bg-status-success-bg-subtle text-status-success-text\"\n : \"bg-bg-sunken text-text-primary\",\n )}\n >\n {ORG_ROLE_LABELS[member.role]}\n </span>\n ),\n },\n {\n key: \"joinedAt\",\n header: tr(\"devportal.joinedColumn\", \"Joined\"),\n render: (member) => new Date(member.joinedAt).toLocaleDateString(),\n },\n {\n key: \"lastActiveAt\",\n header: tr(\"devportal.lastActiveColumn\", \"Last Active\"),\n render: (member) =>\n member.lastActiveAt\n ? new Date(member.lastActiveAt).toLocaleDateString()\n : tr(\"devportal.never\", \"Never\"),\n },\n ]}\n />\n </div>\n );\n};\n\n// Settings Tab\nconst SettingsTab: FC<{ org: DeveloperOrganization }> = ({ org }) => {\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 max-w-2xl\">\n <PageSection\n title={tr(\"devportal.organizationDetails\", \"Organization Details\")}\n >\n <DetailList\n items={[\n {\n label: tr(\"devportal.organizationId\", \"Organization ID\"),\n value: <code className=\"text-xs\">{org.id}</code>,\n },\n { label: tr(\"devportal.slug\", \"Slug\"), value: org.slug },\n { label: tr(\"devportal.tier\", \"Tier\"), value: org.tier },\n {\n label: tr(\"devportal.partnerTier\", \"Partner Tier\"),\n value: org.partnerTier || tr(\"devportal.none\", \"None\"),\n },\n {\n label: tr(\"devportal.created\", \"Created\"),\n value: new Date(org.createdAt).toLocaleDateString(),\n },\n {\n label: tr(\"devportal.platformFeeRate\", \"Platform Fee Rate\"),\n value: `${(org.platformFeeRate * 100).toFixed(0)}%`,\n },\n ]}\n />\n </PageSection>\n\n <PageSection\n title={tr(\"devportal.legalInformation\", \"Legal Information\")}\n >\n <DetailList\n items={[\n {\n label: tr(\"devportal.legalEntityName\", \"Legal Entity Name\"),\n value:\n org.legalEntityName ||\n tr(\"devportal.notProvided\", \"Not provided\"),\n },\n {\n label: tr(\"devportal.entityType\", \"Entity Type\"),\n value:\n org.legalEntityType ||\n tr(\"devportal.notProvided\", \"Not provided\"),\n },\n {\n label: tr(\"devportal.taxId\", \"Tax ID\"),\n value: org.taxId\n ? `•••••${org.taxId.slice(-4)}`\n : tr(\"devportal.notProvided\", \"Not provided\"),\n },\n {\n label: tr(\"devportal.taxCountry\", \"Tax Country\"),\n value:\n org.taxCountry || tr(\"devportal.notProvided\", \"Not provided\"),\n },\n {\n label: tr(\"devportal.taxForm\", \"Tax Form\"),\n value:\n org.taxFormType ||\n tr(\"devportal.notSubmitted\", \"Not submitted\"),\n },\n {\n label: tr(\"devportal.taxFormStatus\", \"Tax Form Status\"),\n value: org.taxFormVerified ? (\n <span className=\"text-status-success-text flex items-center gap-1\">\n <CheckCircle size={14} />{\" \"}\n {tr(\"devportal.verified\", \"Verified\")}\n </span>\n ) : (\n tr(\"devportal.pendingVerification\", \"Pending verification\")\n ),\n },\n ]}\n />\n </PageSection>\n\n <PageSection\n title={tr(\"devportal.verificationStatus\", \"Verification Status\")}\n >\n <DetailList\n items={[\n {\n label: tr(\"devportal.verifiedLabel\", \"Verified\"),\n value: org.isVerified ? (\n <span className=\"text-status-success-text flex items-center gap-1\">\n <CheckCircle size={14} />{\" \"}\n {tr(\"devportal.verifiedVia\", \"Verified via\")}{\" \"}\n {org.verificationMethod}\n </span>\n ) : (\n tr(\"devportal.notVerified\", \"Not verified\")\n ),\n },\n {\n label: tr(\"devportal.certifiedLabel\", \"Certified\"),\n value: org.isCertified ? (\n <span className=\"text-accent-blue flex items-center gap-1\">\n <Shield size={14} />{\" \"}\n {tr(\"devportal.certifiedUntil\", \"Certified until\")}{\" \"}\n {org.certificationExpiry\n ? new Date(org.certificationExpiry).toLocaleDateString()\n : \"N/A\"}\n </span>\n ) : (\n tr(\"devportal.notCertified\", \"Not certified\")\n ),\n },\n ]}\n />\n </PageSection>\n </div>\n );\n};\n\n// Usage Card Component\nconst UsageCard: FC<{\n label: string;\n used: number;\n limit: number;\n percent: number;\n format: \"number\" | \"bytes\";\n}> = ({ label, used, limit, percent, format }) => {\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 formatValue = (value: number): string => {\n if (format === \"bytes\") {\n const gb = value / (1024 * 1024 * 1024);\n return `${gb.toFixed(1)} GB`;\n }\n if (value >= 1000000) {\n return `${(value / 1000000).toFixed(1)}M`;\n }\n if (value >= 1000) {\n return `${(value / 1000).toFixed(1)}K`;\n }\n return value.toLocaleString();\n };\n\n return (\n <div className=\"rounded-lg border p-4\">\n <div className=\"flex items-center justify-between mb-2\">\n <span className=\"text-sm font-medium\">{label}</span>\n <span className=\"text-xs text-muted-foreground\">\n {formatValue(used)} / {formatValue(limit)}\n </span>\n </div>\n <div className=\"h-2 rounded-full bg-muted overflow-hidden\">\n <div\n className={cn(\n \"h-full rounded-full transition-all\",\n percent > 90\n ? \"bg-status-error-bg-subtle\"\n : percent > 70\n ? \"bg-status-warning-bg-subtle\"\n : \"bg-primary\",\n )}\n style={{ width: `${Math.min(percent, 100)}%` }}\n />\n </div>\n <p className=\"text-xs text-muted-foreground mt-1\">\n {percent.toFixed(1)}% {tr(\"devportal.used\", \"used\")}\n </p>\n </div>\n );\n};\n"],"mappings":"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"}
|