@burdenoff/microfe-devportal 2026.830.1 → 2026.830.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/dist/devportal/AdminDevportalRoot.d.ts.map +1 -1
  2. package/dist/devportal/AdminDevportalRoot.js +16 -19
  3. package/dist/devportal/AdminDevportalRoot.js.map +1 -1
  4. package/dist/devportal/DevportalRoot.d.ts.map +1 -1
  5. package/dist/devportal/DevportalRoot.js +36 -39
  6. package/dist/devportal/DevportalRoot.js.map +1 -1
  7. package/dist/devportal/components/AppCard.js +41 -41
  8. package/dist/devportal/components/ConfirmDialog.d.ts.map +1 -1
  9. package/dist/devportal/components/ConfirmDialog.js +19 -22
  10. package/dist/devportal/components/ConfirmDialog.js.map +1 -1
  11. package/dist/devportal/components/DataTable.d.ts.map +1 -1
  12. package/dist/devportal/components/DataTable.js +31 -34
  13. package/dist/devportal/components/DataTable.js.map +1 -1
  14. package/dist/devportal/components/FeatureFlaggedRoute.js +8 -8
  15. package/dist/devportal/components/FormField.d.ts.map +1 -1
  16. package/dist/devportal/components/FormField.js +26 -32
  17. package/dist/devportal/components/FormField.js.map +1 -1
  18. package/dist/devportal/components/GrantDelegationModal.js +64 -64
  19. package/dist/devportal/components/GrantDelegationModal.js.map +1 -1
  20. package/dist/devportal/components/LoadingState.d.ts.map +1 -1
  21. package/dist/devportal/components/LoadingState.js +5 -8
  22. package/dist/devportal/components/LoadingState.js.map +1 -1
  23. package/dist/devportal/components/PageLayout.d.ts.map +1 -1
  24. package/dist/devportal/components/PageLayout.js +10 -13
  25. package/dist/devportal/components/PageLayout.js.map +1 -1
  26. package/dist/devportal/components/PermissionGuard.d.ts.map +1 -1
  27. package/dist/devportal/components/PermissionGuard.js +11 -14
  28. package/dist/devportal/components/PermissionGuard.js.map +1 -1
  29. package/dist/devportal/components/SecretDisplay.d.ts.map +1 -1
  30. package/dist/devportal/components/SecretDisplay.js +24 -30
  31. package/dist/devportal/components/SecretDisplay.js.map +1 -1
  32. package/dist/devportal/components/SectionNav.d.ts.map +1 -1
  33. package/dist/devportal/components/SectionNav.js +24 -27
  34. package/dist/devportal/components/SectionNav.js.map +1 -1
  35. package/dist/devportal/components/StatusBadge.d.ts.map +1 -1
  36. package/dist/devportal/components/StatusBadge.js +24 -33
  37. package/dist/devportal/components/StatusBadge.js.map +1 -1
  38. package/dist/devportal/index.d.ts +1 -0
  39. package/dist/devportal/index.d.ts.map +1 -1
  40. package/dist/devportal/index.js +1 -0
  41. package/dist/devportal/pages/AdminReviewPage.js +172 -172
  42. package/dist/devportal/pages/AnalyticsDashboardPage.js +43 -43
  43. package/dist/devportal/pages/AnalyticsDashboardPage.js.map +1 -1
  44. package/dist/devportal/pages/ApiKeysPage.js +119 -119
  45. package/dist/devportal/pages/ApiKeysPage.js.map +1 -1
  46. package/dist/devportal/pages/AppLogsPage.js +45 -45
  47. package/dist/devportal/pages/ApplicationDetailPage.js +607 -607
  48. package/dist/devportal/pages/ApplicationVersionsPage.js +13 -13
  49. package/dist/devportal/pages/ApplicationsPage.d.ts.map +1 -1
  50. package/dist/devportal/pages/ApplicationsPage.js +104 -101
  51. package/dist/devportal/pages/ApplicationsPage.js.map +1 -1
  52. package/dist/devportal/pages/CreateApiKeyPage.js +45 -45
  53. package/dist/devportal/pages/CreateApplicationPage.js +38 -38
  54. package/dist/devportal/pages/CreateApplicationPage.js.map +1 -1
  55. package/dist/devportal/pages/CreateOAuthClientPage.js +52 -52
  56. package/dist/devportal/pages/CreateOrganizationPage.js +26 -26
  57. package/dist/devportal/pages/CreateWebhookPage.d.ts.map +1 -1
  58. package/dist/devportal/pages/CreateWebhookPage.js +48 -48
  59. package/dist/devportal/pages/CreateWebhookPage.js.map +1 -1
  60. package/dist/devportal/pages/DashboardPage.d.ts.map +1 -1
  61. package/dist/devportal/pages/DashboardPage.js +66 -72
  62. package/dist/devportal/pages/DashboardPage.js.map +1 -1
  63. package/dist/devportal/pages/DelegationsPage.js +174 -174
  64. package/dist/devportal/pages/DocumentationPage.js +93 -93
  65. package/dist/devportal/pages/EditApplicationPage.js +14 -14
  66. package/dist/devportal/pages/EditApplicationPage.js.map +1 -1
  67. package/dist/devportal/pages/ListingPreviewPage.js +76 -76
  68. package/dist/devportal/pages/OAuthClientDetailPage.js +75 -75
  69. package/dist/devportal/pages/OAuthClientDetailPage.js.map +1 -1
  70. package/dist/devportal/pages/OAuthClientsPage.js +64 -64
  71. package/dist/devportal/pages/OrganizationDetailPage.js +189 -189
  72. package/dist/devportal/pages/OrganizationDetailPage.js.map +1 -1
  73. package/dist/devportal/pages/OrganizationMembersPage.js +10 -10
  74. package/dist/devportal/pages/OrganizationsPage.d.ts.map +1 -1
  75. package/dist/devportal/pages/OrganizationsPage.js +163 -154
  76. package/dist/devportal/pages/OrganizationsPage.js.map +1 -1
  77. package/dist/devportal/pages/PublishPage.js +104 -104
  78. package/dist/devportal/pages/PublishPage.js.map +1 -1
  79. package/dist/devportal/pages/PublisherProfilePage.js +55 -55
  80. package/dist/devportal/pages/ResourcesPage.js +60 -60
  81. package/dist/devportal/pages/RevenueDashboardPage.js +60 -60
  82. package/dist/devportal/pages/RevenueDashboardPage.js.map +1 -1
  83. package/dist/devportal/pages/SellerDashboardPage.js +83 -83
  84. package/dist/devportal/pages/SellerItemsPage.js +163 -163
  85. package/dist/devportal/pages/SellerItemsPage.js.map +1 -1
  86. package/dist/devportal/pages/SellerOrdersPage.js +63 -63
  87. package/dist/devportal/pages/SettingsPage.js +21 -21
  88. package/dist/devportal/pages/SetupPage.js +183 -183
  89. package/dist/devportal/pages/SetupPage.js.map +1 -1
  90. package/dist/devportal/pages/StoreSubmissionPage.js +5 -5
  91. package/dist/devportal/pages/WebhookDetailPage.js +123 -123
  92. package/dist/devportal/pages/WebhookDetailPage.js.map +1 -1
  93. package/dist/devportal/pages/WebhooksPage.js +118 -118
  94. package/dist/devportal/pages/WebhooksPage.js.map +1 -1
  95. package/dist/devportal/utils/i18n.d.ts +9 -2
  96. package/dist/devportal/utils/i18n.d.ts.map +1 -1
  97. package/dist/devportal/utils/i18n.js +13 -10
  98. package/dist/devportal/utils/i18n.js.map +1 -1
  99. package/dist/index.js +2 -1
  100. package/dist/translations/en.d.ts +1251 -0
  101. package/dist/translations/en.d.ts.map +1 -0
  102. package/dist/translations/en.js +1235 -0
  103. package/dist/translations/en.js.map +1 -0
  104. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"RevenueDashboardPage.js","names":[],"sources":["../../../src/devportal/pages/RevenueDashboardPage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useMemo, useState } from \"react\";\nimport { useSearchParams } from \"react-router\";\nimport {\n Bar,\n BarChart,\n CartesianGrid,\n Line,\n LineChart,\n ResponsiveContainer,\n Tooltip,\n XAxis,\n YAxis,\n} from \"recharts\";\nimport {\n AlertCircle,\n ArrowDownToLine,\n Building2,\n Check,\n CreditCard,\n DollarSign,\n Link2,\n Loader2,\n Wallet,\n} from \"lucide-react\";\nimport { EmphasisPanel, GlassCard } from \"@burdenoff/fe-libs/ui\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport { PageLayout, PageSection } from \"../components/PageLayout\";\nimport { DataTable } from \"../components/DataTable\";\nimport { EmptyState } from \"../components/EmptyState\";\nimport { StatCard, StatCardGrid } from \"../components/StatCard\";\nimport { StatusBadge } from \"../components/StatusBadge\";\nimport type { DeveloperOrganization } from \"../types\";\nimport {\n type GetMyOrganizationsQuery,\n type GetRevenueDashboardDataQuery,\n getErrorMessage,\n useGetBillingAccountsByOrgQuery,\n useGetMyOrganizationsQuery,\n useGetRevenueDashboardDataQuery,\n useLinkDevOrgBillingAccountMutation,\n} from \"../hooks\";\nimport { cn } from \"../utils/cn\";\nimport { useTr } from \"../utils/i18n\";\n\ntype TimeRange = \"30d\" | \"90d\" | \"12m\";\n\nconst chartColors = {\n primary: \"var(--color-chart-1)\",\n secondary: \"var(--color-chart-2)\",\n tertiary: \"var(--color-chart-4)\",\n};\n\ntype RevenueSale =\n GetRevenueDashboardDataQuery[\"developerOrgSales\"][\"edges\"][number][\"node\"];\ntype RevenuePayout =\n GetRevenueDashboardDataQuery[\"developerOrgPayouts\"][\"edges\"][number][\"node\"];\n\nconst daysByRange: Record<TimeRange, number> = {\n \"30d\": 30,\n \"90d\": 90,\n \"12m\": 365,\n};\n\nexport const RevenueDashboardPage: FC = () => {\n const tr = useTr();\n const { activeOrgId, tenantId } = useDevportal();\n const [timeRange, setTimeRange] = useState<TimeRange>(\"90d\");\n const [linkingBilling, setLinkingBilling] = useState(false);\n const [linkBillingError, setLinkBillingError] = useState<string | null>(null);\n\n const [linkBillingAccount] = useLinkDevOrgBillingAccountMutation();\n const [showBillingPicker, setShowBillingPicker] = useState(false);\n const [selectedBillingAccountId, setSelectedBillingAccountId] = useState<\n string | null\n >(null);\n const [searchParams] = useSearchParams();\n const now = useMemo(() => new Date(), []);\n\n const { data: billingAccountsData, loading: billingAccountsLoading } =\n useGetBillingAccountsByOrgQuery({\n fetchPolicy: \"cache-and-network\",\n context: { headers: { \"x-org-id\": tenantId ?? \"\" } },\n });\n // searchParams kept for deep-link compatibility (URL ?org= still works via OrgSwitcher auto-select)\n void searchParams;\n const startDate = useMemo(() => {\n const nextDate = new Date(now);\n nextDate.setDate(nextDate.getDate() - daysByRange[timeRange]);\n return nextDate.toISOString();\n }, [now, timeRange]);\n\n const {\n data: organizationsData,\n loading: organizationsLoading,\n error: organizationsError,\n } = useGetMyOrganizationsQuery({\n fetchPolicy: \"cache-and-network\",\n });\n const { data, loading, error } = useGetRevenueDashboardDataQuery({\n variables: {\n organizationId: activeOrgId ?? \"\",\n period: \"monthly\",\n startDate,\n endDate: now.toISOString(),\n salesLimit: 10,\n salesOffset: 0,\n payoutsLimit: 10,\n payoutsOffset: 0,\n },\n skip: !activeOrgId,\n fetchPolicy: \"cache-and-network\",\n });\n\n const organizations: DeveloperOrganization[] = useMemo(\n () =>\n organizationsData?.myDeveloperOrganizations?.map(\n (\n organization: GetMyOrganizationsQuery[\"myDeveloperOrganizations\"][number],\n ) => organization as unknown as DeveloperOrganization,\n ) ?? [],\n [organizationsData?.myDeveloperOrganizations],\n );\n\n const selectedOrganization = organizations.find(\n (organization) => organization.id === activeOrgId,\n );\n\n type BillingAccount = NonNullable<\n typeof billingAccountsData\n >[\"getBillingAccountsByOrg\"][number];\n const existingBillingAccounts: BillingAccount[] =\n billingAccountsData?.getBillingAccountsByOrg ?? [];\n\n const linkedBillingAccount =\n existingBillingAccounts.find(\n (a) => a.id === selectedOrganization?.billingAccountId,\n ) ?? null;\n\n const handleOpenBillingPicker = () => {\n // Pre-select the currently linked account; fall back to default or first\n setSelectedBillingAccountId(\n selectedOrganization?.billingAccountId ??\n existingBillingAccounts.find((a) => a.isDefault)?.id ??\n existingBillingAccounts[0]?.id ??\n null,\n );\n setShowBillingPicker(true);\n };\n\n const handleLinkExisting = async () => {\n if (!activeOrgId || !selectedBillingAccountId) return;\n setLinkingBilling(true);\n setLinkBillingError(null);\n try {\n await linkBillingAccount({\n variables: {\n organizationId: activeOrgId,\n billingAccountId: selectedBillingAccountId,\n },\n refetchQueries: [\"GetMyOrganizations\"],\n });\n setShowBillingPicker(false);\n } catch (err) {\n setLinkBillingError(\n err instanceof Error ? err.message : \"Failed to link billing account\",\n );\n } finally {\n setLinkingBilling(false);\n }\n };\n\n const summary = data?.developerOrgRevenueSummary;\n const analytics = [...(data?.developerOrgRevenueAnalytics ?? [])].sort(\n (left, right) =>\n new Date(left.date).getTime() - new Date(right.date).getTime(),\n );\n const sales: RevenueSale[] =\n data?.developerOrgSales?.edges?.map(\n (\n edge: GetRevenueDashboardDataQuery[\"developerOrgSales\"][\"edges\"][number],\n ) => edge.node,\n ) ?? [];\n const payouts: RevenuePayout[] =\n data?.developerOrgPayouts?.edges?.map(\n (\n edge: GetRevenueDashboardDataQuery[\"developerOrgPayouts\"][\"edges\"][number],\n ) => edge.node,\n ) ?? [];\n\n const chartData = analytics.map((entry) => ({\n date: new Date(entry.date).toLocaleDateString(undefined, {\n month: \"short\",\n day: \"numeric\",\n }),\n grossRevenue: entry.grossRevenue,\n netRevenue: entry.netRevenue,\n platformFees: entry.platformFees,\n refunds: entry.refunds,\n salesCount: entry.salesCount,\n }));\n\n if (organizationsLoading && !organizationsData) {\n return (\n <PageLayout\n title={tr(\"devportal.revenue.title\", \"Revenue\")}\n description={tr(\n \"devportal.revenue.description\",\n \"Track real revenue, sales, and payout activity for your developer organizations\",\n )}\n >\n <div className=\"flex items-center justify-center py-16 text-text-secondary\">\n <Loader2 className=\"h-8 w-8 animate-spin\" />\n </div>\n </PageLayout>\n );\n }\n\n if (organizationsError) {\n return (\n <PageLayout\n title={tr(\"devportal.revenue.title\", \"Revenue\")}\n description={tr(\n \"devportal.revenue.description\",\n \"Track real revenue, sales, and payout activity for your developer organizations\",\n )}\n >\n <EmptyState\n icon={<AlertCircle size={32} className=\"text-status-error-text\" />}\n title={tr(\n \"devportal.revenue.errorLoadOrgs\",\n \"Unable to load organizations\",\n )}\n description={getErrorMessage(organizationsError)}\n />\n </PageLayout>\n );\n }\n\n if (!activeOrgId) {\n return (\n <PageLayout\n title={tr(\"devportal.revenue.title\", \"Revenue\")}\n description={tr(\n \"devportal.revenue.description\",\n \"Track real revenue, sales, and payout activity for your developer organizations\",\n )}\n >\n <EmptyState\n illustration=\"empty-people\"\n icon={<Building2 size={32} className=\"text-text-secondary\" />}\n title={tr(\n \"devportal.revenue.selectOrgTitle\",\n \"Select an organization\",\n )}\n description={tr(\n \"devportal.revenue.selectOrgHint\",\n \"Use the organization switcher in the nav bar above to choose which organization's revenue to view.\",\n )}\n />\n </PageLayout>\n );\n }\n\n if (error) {\n return (\n <PageLayout\n title={tr(\"devportal.revenue.title\", \"Revenue\")}\n description={tr(\n \"devportal.revenue.description\",\n \"Track real revenue, sales, and payout activity for your developer organizations\",\n )}\n >\n <EmptyState\n icon={<AlertCircle size={32} className=\"text-status-error-text\" />}\n title={tr(\n \"devportal.revenue.errorLoadData\",\n \"Unable to load revenue data\",\n )}\n description={getErrorMessage(error)}\n />\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title={tr(\"devportal.revenue.title\", \"Revenue\")}\n description={\n selectedOrganization\n ? `${tr(\"devportal.revenue.financialPerformanceFor\", \"Financial performance for\")} ${selectedOrganization.name}`\n : tr(\n \"devportal.revenue.shortDescription\",\n \"Track revenue, sales, and payouts\",\n )\n }\n purpose={tr(\n \"devportal.revenue.purpose\",\n \"Revenue tracks the money your paid apps earn — gross sales, platform fees, and what gets paid out to your organization. Link a billing account, then use this to reconcile payouts and watch growth across time ranges.\",\n )}\n actions={\n <div className=\"flex flex-wrap gap-2\">\n <select\n value={timeRange}\n onChange={(event) => setTimeRange(event.target.value as TimeRange)}\n aria-label={tr(\n \"devportal.revenue.selectRangeAria\",\n \"Select time range\",\n )}\n className=\"rounded-md border bg-bg-surface px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-primary\"\n >\n <option value=\"30d\">\n {tr(\"devportal.revenue.range.30d\", \"Last 30 days\")}\n </option>\n <option value=\"90d\">\n {tr(\"devportal.revenue.range.90d\", \"Last 90 days\")}\n </option>\n <option value=\"12m\">\n {tr(\"devportal.revenue.range.12m\", \"Last 12 months\")}\n </option>\n </select>\n </div>\n }\n >\n {/* Billing account link banner for orgs not yet linked */}\n {selectedOrganization && !selectedOrganization.billingAccountId && (\n <div className=\"mb-6 rounded-card border border-border-seam bg-status-info-bg-subtle p-4 flex flex-col gap-3\">\n <div className=\"flex items-start gap-3\">\n <Link2\n size={20}\n className=\"text-accent-blue flex-shrink-0 mt-0.5\"\n />\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm font-medium text-status-info-text\">\n {tr(\n \"devportal.revenue.billingNotLinkedTitle\",\n \"Link a billing account to receive store revenue\",\n )}\n </p>\n <p className=\"mt-1 text-sm text-status-info-text\">\n {tr(\n \"devportal.revenue.billingNotLinkedDesc\",\n \"Once linked, net earnings from app sales will appear in your billing credits — you can spend them on platform services or withdraw to your bank.\",\n )}\n </p>\n {linkBillingError && (\n <p className=\"mt-2 text-sm text-status-error-text\">\n {linkBillingError}\n </p>\n )}\n </div>\n <button\n type=\"button\"\n onClick={handleOpenBillingPicker}\n disabled={linkingBilling || billingAccountsLoading}\n className=\"inline-flex items-center gap-2 rounded-md bg-action-primary-bg px-3 py-1.5 text-xs font-medium text-action-primary-text hover:bg-action-primary-bg/90 transition-colors disabled:opacity-50 flex-shrink-0\"\n >\n {linkingBilling || billingAccountsLoading ? (\n <Loader2 size={14} className=\"animate-spin\" />\n ) : (\n <Link2 size={14} />\n )}\n {linkingBilling\n ? tr(\"devportal.revenue.linking\", \"Linking...\")\n : tr(\n \"devportal.revenue.linkBillingAccount\",\n \"Link Billing Account\",\n )}\n </button>\n </div>\n\n {/* No billing accounts message */}\n {showBillingPicker && existingBillingAccounts.length === 0 && (\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-4 ml-8 text-sm text-text-secondary\">\n {tr(\n \"devportal.revenue.noBillingAccounts\",\n \"You don't have any billing accounts yet. Create one from your account billing settings first.\",\n )}\n </div>\n )}\n\n {/* Billing account picker — shown when user has existing accounts */}\n {showBillingPicker && existingBillingAccounts.length > 0 && (\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-4 ml-8 space-y-3\">\n <p className=\"text-sm font-medium\">\n {tr(\n \"devportal.revenue.chooseBillingAccount\",\n \"Choose a billing account to link\",\n )}\n </p>\n <div className=\"space-y-2\">\n {existingBillingAccounts.map((account) => (\n <button\n key={account.id}\n type=\"button\"\n onClick={() =>\n setSelectedBillingAccountId(account.id ?? null)\n }\n className={cn(\n \"flex w-full items-center gap-3 rounded-md border px-3 py-2.5 text-sm text-left transition-colors\",\n selectedBillingAccountId === account.id\n ? \"border-primary bg-action-primary-bg/5 text-text-primary\"\n : \"border-border-subtle hover:bg-accent text-text-primary\",\n )}\n >\n <Check\n size={14}\n className={cn(\n \"flex-shrink-0\",\n selectedBillingAccountId === account.id\n ? \"opacity-100 text-primary\"\n : \"opacity-0\",\n )}\n />\n <div className=\"flex-1 min-w-0\">\n <p className=\"font-medium truncate\">{account.name}</p>\n {account.isDefault && (\n <p className=\"text-xs text-text-secondary\">\n {tr(\"devportal.revenue.defaultAccount\", \"Default\")}\n </p>\n )}\n </div>\n </button>\n ))}\n </div>\n <div className=\"flex items-center justify-end gap-2 pt-1\">\n <button\n type=\"button\"\n onClick={() => {\n setShowBillingPicker(false);\n setLinkBillingError(null);\n }}\n className=\"rounded-md px-3 py-1.5 text-xs font-medium text-text-secondary hover:bg-accent transition-colors\"\n >\n {tr(\"devportal.cancel\", \"Cancel\")}\n </button>\n <button\n type=\"button\"\n disabled={linkingBilling || !selectedBillingAccountId}\n onClick={() => void handleLinkExisting()}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-action-primary-bg px-3 py-1.5 text-xs font-medium text-action-primary-text hover:bg-action-primary-bg/90 transition-colors disabled:opacity-50\"\n >\n {linkingBilling ? (\n <Loader2 size={13} className=\"animate-spin\" />\n ) : (\n <Link2 size={13} />\n )}\n {tr(\"devportal.revenue.confirm\", \"Confirm\")}\n </button>\n </div>\n </div>\n )}\n </div>\n )}\n\n {/* Linked billing account info — shown when billing is already linked */}\n {selectedOrganization?.billingAccountId && (\n <div className=\"mb-6 rounded-lg border border-border-subtle bg-bg-surface p-3 flex flex-col gap-3\">\n <div className=\"flex items-center gap-3\">\n <CreditCard\n size={16}\n className=\"text-text-secondary flex-shrink-0\"\n />\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm font-medium truncate\">\n {linkedBillingAccount?.name ??\n tr(\"devportal.revenue.billingAccount\", \"Billing account\")}\n </p>\n <p className=\"text-xs text-text-secondary truncate\">\n {linkedBillingAccount\n ? `${linkedBillingAccount.currency}${linkedBillingAccount.email ? ` · ${linkedBillingAccount.email}` : \"\"}`\n : selectedOrganization.billingAccountId}\n </p>\n </div>\n {!showBillingPicker && (\n <button\n type=\"button\"\n onClick={handleOpenBillingPicker}\n disabled={billingAccountsLoading}\n className=\"text-xs text-text-secondary hover:text-text-primary transition-colors flex-shrink-0 disabled:opacity-50\"\n >\n {tr(\"devportal.revenue.changeBillingAccount\", \"Change\")}\n </button>\n )}\n </div>\n {/* Picker for changing the linked account */}\n {showBillingPicker && existingBillingAccounts.length > 0 && (\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-4 space-y-3\">\n <p className=\"text-sm font-medium\">\n {tr(\n \"devportal.revenue.chooseBillingAccount\",\n \"Choose a billing account to link\",\n )}\n </p>\n <div className=\"space-y-2\">\n {existingBillingAccounts.map((account) => (\n <button\n key={account.id}\n type=\"button\"\n onClick={() =>\n setSelectedBillingAccountId(account.id ?? null)\n }\n className={cn(\n \"flex w-full items-center gap-3 rounded-md border px-3 py-2.5 text-sm text-left transition-colors\",\n selectedBillingAccountId === account.id\n ? \"border-primary bg-action-primary-bg/5 text-text-primary\"\n : \"border-border-subtle hover:bg-accent text-text-primary\",\n )}\n >\n <Check\n size={14}\n className={cn(\n \"flex-shrink-0\",\n selectedBillingAccountId === account.id\n ? \"opacity-100 text-primary\"\n : \"opacity-0\",\n )}\n />\n <div className=\"flex-1 min-w-0\">\n <p className=\"font-medium truncate\">{account.name}</p>\n {account.isDefault && (\n <p className=\"text-xs text-text-secondary\">\n {tr(\"devportal.revenue.defaultAccount\", \"Default\")}\n </p>\n )}\n </div>\n </button>\n ))}\n </div>\n <div className=\"flex items-center justify-end gap-2 pt-1\">\n <button\n type=\"button\"\n onClick={() => {\n setShowBillingPicker(false);\n setLinkBillingError(null);\n }}\n className=\"rounded-md px-3 py-1.5 text-xs font-medium text-text-secondary hover:bg-accent transition-colors\"\n >\n {tr(\"devportal.cancel\", \"Cancel\")}\n </button>\n <button\n type=\"button\"\n disabled={linkingBilling || !selectedBillingAccountId}\n onClick={() => void handleLinkExisting()}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-action-primary-bg px-3 py-1.5 text-xs font-medium text-action-primary-text hover:bg-action-primary-bg/90 transition-colors disabled:opacity-50\"\n >\n {linkingBilling ? (\n <Loader2 size={13} className=\"animate-spin\" />\n ) : (\n <Link2 size={13} />\n )}\n {tr(\"devportal.revenue.confirm\", \"Confirm\")}\n </button>\n </div>\n {linkBillingError && (\n <p className=\"text-xs text-status-error-text\">\n {linkBillingError}\n </p>\n )}\n </div>\n )}\n </div>\n )}\n\n {loading && !summary ? (\n <div className=\"flex items-center justify-center py-16 text-text-secondary\">\n <Loader2 className=\"h-8 w-8 animate-spin\" />\n </div>\n ) : summary ? (\n <>\n <EmphasisPanel className=\"mb-6\">\n <StatCardGrid columns={4}>\n <StatCard\n title={tr(\"devportal.revenue.grossRevenue\", \"Gross Revenue\")}\n value={`$${summary.totalGrossRevenue.toLocaleString()}`}\n icon={<DollarSign size={20} />}\n />\n <StatCard\n title={tr(\"devportal.revenue.netRevenue\", \"Net Revenue\")}\n value={`$${summary.totalNetRevenue.toLocaleString()}`}\n icon={<Wallet size={20} />}\n />\n <StatCard\n title={tr(\n \"devportal.revenue.pendingBalance\",\n \"Pending Balance\",\n )}\n value={`$${summary.pendingBalance.toLocaleString()}`}\n icon={<CreditCard size={20} />}\n description={\n summary.nextPayoutDate\n ? `${tr(\"devportal.revenue.nextPayout\", \"Next payout\")} ${new Date(summary.nextPayoutDate).toLocaleDateString()}`\n : tr(\n \"devportal.revenue.noPayoutScheduled\",\n \"No payout scheduled\",\n )\n }\n />\n <StatCard\n title={tr(\"devportal.revenue.platformFees\", \"Platform Fees\")}\n value={`$${summary.totalPlatformFees.toLocaleString()}`}\n icon={<ArrowDownToLine size={20} />}\n description={`${summary.totalRefundsCount} ${tr(\"devportal.revenue.refunds\", \"refunds\")}`}\n />\n </StatCardGrid>\n </EmphasisPanel>\n\n <div className=\"grid gap-6 xl:grid-cols-2\">\n <PageSection\n title={tr(\"devportal.revenue.revenueTrend\", \"Revenue trend\")}\n >\n <GlassCard treatment=\"insight\" className=\"p-4\">\n {chartData.length > 0 ? (\n <ResponsiveContainer width=\"100%\" height={300}>\n <LineChart data={chartData}>\n <CartesianGrid\n strokeDasharray=\"3 3\"\n stroke=\"var(--color-chart-grid)\"\n />\n <XAxis\n dataKey=\"date\"\n stroke=\"var(--color-chart-axis)\"\n fontSize={12}\n />\n <YAxis stroke=\"var(--color-chart-axis)\" fontSize={12} />\n <Tooltip\n contentStyle={{\n backgroundColor: \"var(--color-card)\",\n border: \"1px solid var(--color-border-default)\",\n borderRadius: 12,\n }}\n />\n <Line\n type=\"monotone\"\n dataKey=\"grossRevenue\"\n stroke={chartColors.primary}\n strokeWidth={2}\n dot={false}\n />\n <Line\n type=\"monotone\"\n dataKey=\"netRevenue\"\n stroke={chartColors.secondary}\n strokeWidth={2}\n dot={false}\n />\n </LineChart>\n </ResponsiveContainer>\n ) : (\n <div className=\"flex h-[300px] flex-col items-center justify-center gap-2 text-text-secondary\">\n <p className=\"text-sm font-medium\">\n {tr(\"devportal.revenue.noTrendData\", \"No trend data yet\")}\n </p>\n <p className=\"text-xs text-text-tertiary\">\n {tr(\n \"devportal.revenue.noTrendDataHint\",\n \"Revenue trend appears once daily analytics have been aggregated.\",\n )}\n </p>\n </div>\n )}\n </GlassCard>\n </PageSection>\n\n <PageSection\n title={tr(\n \"devportal.revenue.topApps\",\n \"Top applications by revenue\",\n )}\n >\n {summary.topApps.length > 0 ? (\n <div className=\"space-y-2\">\n {summary.topApps.map(\n (\n application: GetRevenueDashboardDataQuery[\"developerOrgRevenueSummary\"][\"topApps\"][number],\n ) => (\n <GlassCard\n key={application.applicationId}\n treatment=\"insight\"\n className=\"border-border-seam p-4\"\n >\n <div className=\"flex items-start justify-between gap-3\">\n <div>\n <p className=\"font-medium\">\n {application.applicationName}\n </p>\n <p className=\"text-sm text-text-secondary\">\n {application.salesCount}{\" \"}\n {tr(\"devportal.revenue.sales\", \"sales\")}\n </p>\n </div>\n <div className=\"text-right\">\n <p className=\"font-semibold\">\n ${application.grossRevenue.toLocaleString()}\n </p>\n <p className=\"text-sm text-text-secondary\">\n {tr(\"devportal.revenue.net\", \"Net\")} $\n {application.netRevenue.toLocaleString()}\n </p>\n </div>\n </div>\n </GlassCard>\n ),\n )}\n </div>\n ) : (\n <EmptyState\n illustration=\"empty-data\"\n icon={<Building2 size={24} />}\n title={tr(\n \"devportal.revenue.noLeadersTitle\",\n \"No revenue leaders yet\",\n )}\n description={tr(\n \"devportal.revenue.noLeadersDescription\",\n \"Top-performing applications will appear here once revenue is recorded.\",\n )}\n />\n )}\n </PageSection>\n </div>\n\n <PageSection\n title={tr(\"devportal.revenue.salesVolume\", \"Sales volume\")}\n >\n <GlassCard treatment=\"insight\" className=\"p-4\">\n {chartData.length > 0 ? (\n <ResponsiveContainer width=\"100%\" height={280}>\n <BarChart data={chartData}>\n <CartesianGrid\n strokeDasharray=\"3 3\"\n stroke=\"var(--color-chart-grid)\"\n />\n <XAxis\n dataKey=\"date\"\n stroke=\"var(--color-chart-axis)\"\n fontSize={12}\n />\n <YAxis stroke=\"var(--color-chart-axis)\" fontSize={12} />\n <Tooltip\n contentStyle={{\n backgroundColor: \"var(--color-card)\",\n border: \"1px solid var(--color-border-default)\",\n borderRadius: 12,\n }}\n />\n <Bar\n dataKey=\"salesCount\"\n fill={chartColors.tertiary}\n radius={[6, 6, 0, 0]}\n />\n </BarChart>\n </ResponsiveContainer>\n ) : (\n <div className=\"flex h-[280px] flex-col items-center justify-center gap-2 text-text-secondary\">\n <p className=\"text-sm font-medium\">\n {tr(\n \"devportal.revenue.noVolumeData\",\n \"No sales volume data yet\",\n )}\n </p>\n <p className=\"text-xs text-text-tertiary\">\n {tr(\n \"devportal.revenue.noVolumeDataHint\",\n \"Sales volume by period appears once analytics have been aggregated.\",\n )}\n </p>\n </div>\n )}\n </GlassCard>\n </PageSection>\n\n <div className=\"grid gap-6 xl:grid-cols-2\">\n <PageSection\n title={tr(\"devportal.revenue.recentSales\", \"Recent sales\")}\n >\n <DataTable\n data={sales}\n keyField=\"id\"\n columns={[\n {\n key: \"application\",\n header: tr(\"devportal.revenue.application\", \"Application\"),\n render: (sale) =>\n sale.application?.name ||\n sale.planName ||\n tr(\"devportal.common.unknown\", \"Unknown\"),\n },\n {\n key: \"grossAmount\",\n header: tr(\"devportal.revenue.gross\", \"Gross\"),\n render: (sale) => `$${sale.grossAmount.toLocaleString()}`,\n },\n {\n key: \"netAmount\",\n header: tr(\"devportal.revenue.net\", \"Net\"),\n render: (sale) => `$${sale.netAmount.toLocaleString()}`,\n },\n {\n key: \"status\",\n header: tr(\"devportal.revenue.status\", \"Status\"),\n render: (sale) => (\n <StatusBadge status={sale.status} type=\"app\" />\n ),\n },\n ]}\n />\n </PageSection>\n\n <PageSection\n title={tr(\"devportal.revenue.payoutHistory\", \"Payout history\")}\n >\n <DataTable\n data={payouts}\n keyField=\"id\"\n columns={[\n {\n key: \"periodLabel\",\n header: tr(\"devportal.revenue.period\", \"Period\"),\n render: (payout) => payout.periodLabel,\n },\n {\n key: \"netAmount\",\n header: tr(\"devportal.revenue.netPayout\", \"Net payout\"),\n render: (payout) => `$${payout.netAmount.toLocaleString()}`,\n },\n {\n key: \"status\",\n header: tr(\"devportal.revenue.status\", \"Status\"),\n render: (payout) => (\n <StatusBadge status={payout.status} type=\"app\" />\n ),\n },\n ]}\n />\n </PageSection>\n </div>\n </>\n ) : (\n <EmptyState\n illustration=\"empty-data\"\n icon={<DollarSign size={32} />}\n title={tr(\"devportal.revenue.noDataTitle\", \"No revenue data yet\")}\n description={tr(\n \"devportal.revenue.noDataDescription\",\n \"Revenue metrics will appear after this organization starts recording marketplace sales.\",\n )}\n />\n )}\n </PageLayout>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"RevenueDashboardPage.js","names":[],"sources":["../../../src/devportal/pages/RevenueDashboardPage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useMemo, useState } from \"react\";\nimport { useSearchParams } from \"react-router\";\nimport {\n Bar,\n BarChart,\n CartesianGrid,\n Line,\n LineChart,\n ResponsiveContainer,\n Tooltip,\n XAxis,\n YAxis,\n} from \"recharts\";\nimport {\n AlertCircle,\n ArrowDownToLine,\n Building2,\n Check,\n CreditCard,\n DollarSign,\n Link2,\n Loader2,\n Wallet,\n} from \"lucide-react\";\nimport { EmphasisPanel, GlassCard } from \"@burdenoff/fe-libs/ui\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport { PageLayout, PageSection } from \"../components/PageLayout\";\nimport { DataTable } from \"../components/DataTable\";\nimport { EmptyState } from \"../components/EmptyState\";\nimport { StatCard, StatCardGrid } from \"../components/StatCard\";\nimport { StatusBadge } from \"../components/StatusBadge\";\nimport type { DeveloperOrganization } from \"../types\";\nimport {\n type GetMyOrganizationsQuery,\n type GetRevenueDashboardDataQuery,\n getErrorMessage,\n useGetBillingAccountsByOrgQuery,\n useGetMyOrganizationsQuery,\n useGetRevenueDashboardDataQuery,\n useLinkDevOrgBillingAccountMutation,\n} from \"../hooks\";\nimport { cn } from \"../utils/cn\";\nimport { useTr } from \"../utils/i18n\";\n\ntype TimeRange = \"30d\" | \"90d\" | \"12m\";\n\nconst chartColors = {\n primary: \"var(--color-chart-1)\",\n secondary: \"var(--color-chart-2)\",\n tertiary: \"var(--color-chart-4)\",\n};\n\ntype RevenueSale =\n GetRevenueDashboardDataQuery[\"developerOrgSales\"][\"edges\"][number][\"node\"];\ntype RevenuePayout =\n GetRevenueDashboardDataQuery[\"developerOrgPayouts\"][\"edges\"][number][\"node\"];\n\nconst daysByRange: Record<TimeRange, number> = {\n \"30d\": 30,\n \"90d\": 90,\n \"12m\": 365,\n};\n\nexport const RevenueDashboardPage: FC = () => {\n const tr = useTr();\n const { activeOrgId, tenantId } = useDevportal();\n const [timeRange, setTimeRange] = useState<TimeRange>(\"90d\");\n const [linkingBilling, setLinkingBilling] = useState(false);\n const [linkBillingError, setLinkBillingError] = useState<string | null>(null);\n\n const [linkBillingAccount] = useLinkDevOrgBillingAccountMutation();\n const [showBillingPicker, setShowBillingPicker] = useState(false);\n const [selectedBillingAccountId, setSelectedBillingAccountId] = useState<\n string | null\n >(null);\n const [searchParams] = useSearchParams();\n const now = useMemo(() => new Date(), []);\n\n const { data: billingAccountsData, loading: billingAccountsLoading } =\n useGetBillingAccountsByOrgQuery({\n fetchPolicy: \"cache-and-network\",\n context: { headers: { \"x-org-id\": tenantId ?? \"\" } },\n });\n // searchParams kept for deep-link compatibility (URL ?org= still works via OrgSwitcher auto-select)\n void searchParams;\n const startDate = useMemo(() => {\n const nextDate = new Date(now);\n nextDate.setDate(nextDate.getDate() - daysByRange[timeRange]);\n return nextDate.toISOString();\n }, [now, timeRange]);\n\n const {\n data: organizationsData,\n loading: organizationsLoading,\n error: organizationsError,\n } = useGetMyOrganizationsQuery({\n fetchPolicy: \"cache-and-network\",\n });\n const { data, loading, error } = useGetRevenueDashboardDataQuery({\n variables: {\n organizationId: activeOrgId ?? \"\",\n period: \"monthly\",\n startDate,\n endDate: now.toISOString(),\n salesLimit: 10,\n salesOffset: 0,\n payoutsLimit: 10,\n payoutsOffset: 0,\n },\n skip: !activeOrgId,\n fetchPolicy: \"cache-and-network\",\n });\n\n const organizations: DeveloperOrganization[] = useMemo(\n () =>\n organizationsData?.myDeveloperOrganizations?.map(\n (\n organization: GetMyOrganizationsQuery[\"myDeveloperOrganizations\"][number],\n ) => organization as unknown as DeveloperOrganization,\n ) ?? [],\n [organizationsData?.myDeveloperOrganizations],\n );\n\n const selectedOrganization = organizations.find(\n (organization) => organization.id === activeOrgId,\n );\n\n type BillingAccount = NonNullable<\n typeof billingAccountsData\n >[\"getBillingAccountsByOrg\"][number];\n const existingBillingAccounts: BillingAccount[] =\n billingAccountsData?.getBillingAccountsByOrg ?? [];\n\n const linkedBillingAccount =\n existingBillingAccounts.find(\n (a) => a.id === selectedOrganization?.billingAccountId,\n ) ?? null;\n\n const handleOpenBillingPicker = () => {\n // Pre-select the currently linked account; fall back to default or first\n setSelectedBillingAccountId(\n selectedOrganization?.billingAccountId ??\n existingBillingAccounts.find((a) => a.isDefault)?.id ??\n existingBillingAccounts[0]?.id ??\n null,\n );\n setShowBillingPicker(true);\n };\n\n const handleLinkExisting = async () => {\n if (!activeOrgId || !selectedBillingAccountId) return;\n setLinkingBilling(true);\n setLinkBillingError(null);\n try {\n await linkBillingAccount({\n variables: {\n organizationId: activeOrgId,\n billingAccountId: selectedBillingAccountId,\n },\n refetchQueries: [\"GetMyOrganizations\"],\n });\n setShowBillingPicker(false);\n } catch (err) {\n setLinkBillingError(\n err instanceof Error ? err.message : \"Failed to link billing account\",\n );\n } finally {\n setLinkingBilling(false);\n }\n };\n\n const summary = data?.developerOrgRevenueSummary;\n const analytics = [...(data?.developerOrgRevenueAnalytics ?? [])].sort(\n (left, right) =>\n new Date(left.date).getTime() - new Date(right.date).getTime(),\n );\n const sales: RevenueSale[] =\n data?.developerOrgSales?.edges?.map(\n (\n edge: GetRevenueDashboardDataQuery[\"developerOrgSales\"][\"edges\"][number],\n ) => edge.node,\n ) ?? [];\n const payouts: RevenuePayout[] =\n data?.developerOrgPayouts?.edges?.map(\n (\n edge: GetRevenueDashboardDataQuery[\"developerOrgPayouts\"][\"edges\"][number],\n ) => edge.node,\n ) ?? [];\n\n const chartData = analytics.map((entry) => ({\n date: new Date(entry.date).toLocaleDateString(undefined, {\n month: \"short\",\n day: \"numeric\",\n }),\n grossRevenue: entry.grossRevenue,\n netRevenue: entry.netRevenue,\n platformFees: entry.platformFees,\n refunds: entry.refunds,\n salesCount: entry.salesCount,\n }));\n\n if (organizationsLoading && !organizationsData) {\n return (\n <PageLayout\n title={tr(\"devportal.revenue.title\", \"Revenue\")}\n description={tr(\n \"devportal.revenue.description\",\n \"Track real revenue, sales, and payout activity for your developer organizations\",\n )}\n >\n <div className=\"flex items-center justify-center py-16 text-text-secondary\">\n <Loader2 className=\"h-8 w-8 animate-spin\" />\n </div>\n </PageLayout>\n );\n }\n\n if (organizationsError) {\n return (\n <PageLayout\n title={tr(\"devportal.revenue.title\", \"Revenue\")}\n description={tr(\n \"devportal.revenue.description\",\n \"Track real revenue, sales, and payout activity for your developer organizations\",\n )}\n >\n <EmptyState\n icon={<AlertCircle size={32} className=\"text-status-error-text\" />}\n title={tr(\n \"devportal.revenue.errorLoadOrgs\",\n \"Unable to load organizations\",\n )}\n description={getErrorMessage(organizationsError)}\n />\n </PageLayout>\n );\n }\n\n if (!activeOrgId) {\n return (\n <PageLayout\n title={tr(\"devportal.revenue.title\", \"Revenue\")}\n description={tr(\n \"devportal.revenue.description\",\n \"Track real revenue, sales, and payout activity for your developer organizations\",\n )}\n >\n <EmptyState\n illustration=\"empty-people\"\n icon={<Building2 size={32} className=\"text-text-secondary\" />}\n title={tr(\n \"devportal.revenue.selectOrgTitle\",\n \"Select an organization\",\n )}\n description={tr(\n \"devportal.revenue.selectOrgHint\",\n \"Use the organization switcher in the nav bar above to choose which organization's revenue to view.\",\n )}\n />\n </PageLayout>\n );\n }\n\n if (error) {\n return (\n <PageLayout\n title={tr(\"devportal.revenue.title\", \"Revenue\")}\n description={tr(\n \"devportal.revenue.description\",\n \"Track real revenue, sales, and payout activity for your developer organizations\",\n )}\n >\n <EmptyState\n icon={<AlertCircle size={32} className=\"text-status-error-text\" />}\n title={tr(\n \"devportal.revenue.errorLoadData\",\n \"Unable to load revenue data\",\n )}\n description={getErrorMessage(error)}\n />\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title={tr(\"devportal.revenue.title\", \"Revenue\")}\n description={\n selectedOrganization\n ? `${tr(\"devportal.revenue.financialPerformanceFor\", \"Financial performance for\")} ${selectedOrganization.name}`\n : tr(\n \"devportal.revenue.shortDescription\",\n \"Track revenue, sales, and payouts\",\n )\n }\n purpose={tr(\n \"devportal.revenue.purpose\",\n \"Revenue tracks the money your paid apps earn — gross sales, platform fees, and what gets paid out to your organization. Link a billing account, then use this to reconcile payouts and watch growth across time ranges.\",\n )}\n actions={\n <div className=\"flex flex-wrap gap-2\">\n <select\n value={timeRange}\n onChange={(event) => setTimeRange(event.target.value as TimeRange)}\n aria-label={tr(\n \"devportal.revenue.selectRangeAria\",\n \"Select time range\",\n )}\n className=\"rounded-md border bg-bg-surface px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-primary\"\n >\n <option value=\"30d\">\n {tr(\"devportal.revenue.range.30d\", \"Last 30 days\")}\n </option>\n <option value=\"90d\">\n {tr(\"devportal.revenue.range.90d\", \"Last 90 days\")}\n </option>\n <option value=\"12m\">\n {tr(\"devportal.revenue.range.12m\", \"Last 12 months\")}\n </option>\n </select>\n </div>\n }\n >\n {/* Billing account link banner for orgs not yet linked */}\n {selectedOrganization && !selectedOrganization.billingAccountId && (\n <div className=\"mb-6 rounded-card border border-border-seam bg-status-info-bg-subtle p-4 flex flex-col gap-3\">\n <div className=\"flex items-start gap-3\">\n <Link2\n size={20}\n className=\"text-accent-blue flex-shrink-0 mt-0.5\"\n />\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm font-medium text-status-info-text\">\n {tr(\n \"devportal.revenue.billingNotLinkedTitle\",\n \"Link a billing account to receive store revenue\",\n )}\n </p>\n <p className=\"mt-1 text-sm text-status-info-text\">\n {tr(\n \"devportal.revenue.billingNotLinkedDesc\",\n \"Once linked, net earnings from app sales will appear in your billing credits — you can spend them on platform services or withdraw to your bank.\",\n )}\n </p>\n {linkBillingError && (\n <p className=\"mt-2 text-sm text-status-error-text\">\n {linkBillingError}\n </p>\n )}\n </div>\n <button\n type=\"button\"\n onClick={handleOpenBillingPicker}\n disabled={linkingBilling || billingAccountsLoading}\n className=\"inline-flex items-center gap-2 rounded-md bg-action-primary-bg px-3 py-1.5 text-xs font-medium text-action-primary-text hover:bg-action-primary-bg/90 transition-colors disabled:opacity-50 flex-shrink-0\"\n >\n {linkingBilling || billingAccountsLoading ? (\n <Loader2 size={14} className=\"animate-spin\" />\n ) : (\n <Link2 size={14} />\n )}\n {linkingBilling\n ? tr(\"devportal.revenue.linking\", \"Linking...\")\n : tr(\n \"devportal.revenue.linkBillingAccount\",\n \"Link Billing Account\",\n )}\n </button>\n </div>\n\n {/* No billing accounts message */}\n {showBillingPicker && existingBillingAccounts.length === 0 && (\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-4 ml-8 text-sm text-text-secondary\">\n {tr(\n \"devportal.revenue.noBillingAccounts\",\n \"You don't have any billing accounts yet. Create one from your account billing settings first.\",\n )}\n </div>\n )}\n\n {/* Billing account picker — shown when user has existing accounts */}\n {showBillingPicker && existingBillingAccounts.length > 0 && (\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-4 ml-8 space-y-3\">\n <p className=\"text-sm font-medium\">\n {tr(\n \"devportal.revenue.chooseBillingAccount\",\n \"Choose a billing account to link\",\n )}\n </p>\n <div className=\"space-y-2\">\n {existingBillingAccounts.map((account) => (\n <button\n key={account.id}\n type=\"button\"\n onClick={() =>\n setSelectedBillingAccountId(account.id ?? null)\n }\n className={cn(\n \"flex w-full items-center gap-3 rounded-md border px-3 py-2.5 text-sm text-left transition-colors\",\n selectedBillingAccountId === account.id\n ? \"border-primary bg-action-primary-bg/5 text-text-primary\"\n : \"border-border-subtle hover:bg-accent text-text-primary\",\n )}\n >\n <Check\n size={14}\n className={cn(\n \"flex-shrink-0\",\n selectedBillingAccountId === account.id\n ? \"opacity-100 text-primary\"\n : \"opacity-0\",\n )}\n />\n <div className=\"flex-1 min-w-0\">\n <p className=\"font-medium truncate\">{account.name}</p>\n {account.isDefault && (\n <p className=\"text-xs text-text-secondary\">\n {tr(\"devportal.revenue.defaultAccount\", \"Default\")}\n </p>\n )}\n </div>\n </button>\n ))}\n </div>\n <div className=\"flex items-center justify-end gap-2 pt-1\">\n <button\n type=\"button\"\n onClick={() => {\n setShowBillingPicker(false);\n setLinkBillingError(null);\n }}\n className=\"rounded-md px-3 py-1.5 text-xs font-medium text-text-secondary hover:bg-accent transition-colors\"\n >\n {tr(\"devportal.cancel\", \"Cancel\")}\n </button>\n <button\n type=\"button\"\n disabled={linkingBilling || !selectedBillingAccountId}\n onClick={() => void handleLinkExisting()}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-action-primary-bg px-3 py-1.5 text-xs font-medium text-action-primary-text hover:bg-action-primary-bg/90 transition-colors disabled:opacity-50\"\n >\n {linkingBilling ? (\n <Loader2 size={13} className=\"animate-spin\" />\n ) : (\n <Link2 size={13} />\n )}\n {tr(\"devportal.revenue.confirm\", \"Confirm\")}\n </button>\n </div>\n </div>\n )}\n </div>\n )}\n\n {/* Linked billing account info — shown when billing is already linked */}\n {selectedOrganization?.billingAccountId && (\n <div className=\"mb-6 rounded-lg border border-border-subtle bg-bg-surface p-3 flex flex-col gap-3\">\n <div className=\"flex items-center gap-3\">\n <CreditCard\n size={16}\n className=\"text-text-secondary flex-shrink-0\"\n />\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm font-medium truncate\">\n {linkedBillingAccount?.name ??\n tr(\"devportal.revenue.billingAccount\", \"Billing account\")}\n </p>\n <p className=\"text-xs text-text-secondary truncate\">\n {linkedBillingAccount\n ? `${linkedBillingAccount.currency}${linkedBillingAccount.email ? ` · ${linkedBillingAccount.email}` : \"\"}`\n : selectedOrganization.billingAccountId}\n </p>\n </div>\n {!showBillingPicker && (\n <button\n type=\"button\"\n onClick={handleOpenBillingPicker}\n disabled={billingAccountsLoading}\n className=\"text-xs text-text-secondary hover:text-text-primary transition-colors flex-shrink-0 disabled:opacity-50\"\n >\n {tr(\"devportal.revenue.changeBillingAccount\", \"Change\")}\n </button>\n )}\n </div>\n {/* Picker for changing the linked account */}\n {showBillingPicker && existingBillingAccounts.length > 0 && (\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-4 space-y-3\">\n <p className=\"text-sm font-medium\">\n {tr(\n \"devportal.revenue.chooseBillingAccount\",\n \"Choose a billing account to link\",\n )}\n </p>\n <div className=\"space-y-2\">\n {existingBillingAccounts.map((account) => (\n <button\n key={account.id}\n type=\"button\"\n onClick={() =>\n setSelectedBillingAccountId(account.id ?? null)\n }\n className={cn(\n \"flex w-full items-center gap-3 rounded-md border px-3 py-2.5 text-sm text-left transition-colors\",\n selectedBillingAccountId === account.id\n ? \"border-primary bg-action-primary-bg/5 text-text-primary\"\n : \"border-border-subtle hover:bg-accent text-text-primary\",\n )}\n >\n <Check\n size={14}\n className={cn(\n \"flex-shrink-0\",\n selectedBillingAccountId === account.id\n ? \"opacity-100 text-primary\"\n : \"opacity-0\",\n )}\n />\n <div className=\"flex-1 min-w-0\">\n <p className=\"font-medium truncate\">{account.name}</p>\n {account.isDefault && (\n <p className=\"text-xs text-text-secondary\">\n {tr(\"devportal.revenue.defaultAccount\", \"Default\")}\n </p>\n )}\n </div>\n </button>\n ))}\n </div>\n <div className=\"flex items-center justify-end gap-2 pt-1\">\n <button\n type=\"button\"\n onClick={() => {\n setShowBillingPicker(false);\n setLinkBillingError(null);\n }}\n className=\"rounded-md px-3 py-1.5 text-xs font-medium text-text-secondary hover:bg-accent transition-colors\"\n >\n {tr(\"devportal.cancel\", \"Cancel\")}\n </button>\n <button\n type=\"button\"\n disabled={linkingBilling || !selectedBillingAccountId}\n onClick={() => void handleLinkExisting()}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-action-primary-bg px-3 py-1.5 text-xs font-medium text-action-primary-text hover:bg-action-primary-bg/90 transition-colors disabled:opacity-50\"\n >\n {linkingBilling ? (\n <Loader2 size={13} className=\"animate-spin\" />\n ) : (\n <Link2 size={13} />\n )}\n {tr(\"devportal.revenue.confirm\", \"Confirm\")}\n </button>\n </div>\n {linkBillingError && (\n <p className=\"text-xs text-status-error-text\">\n {linkBillingError}\n </p>\n )}\n </div>\n )}\n </div>\n )}\n\n {loading && !summary ? (\n <div className=\"flex items-center justify-center py-16 text-text-secondary\">\n <Loader2 className=\"h-8 w-8 animate-spin\" />\n </div>\n ) : summary ? (\n <>\n <EmphasisPanel className=\"mb-6\">\n <StatCardGrid columns={4}>\n <StatCard\n title={tr(\"devportal.revenue.grossRevenue\", \"Gross Revenue\")}\n value={`$${summary.totalGrossRevenue.toLocaleString()}`}\n icon={<DollarSign size={20} />}\n />\n <StatCard\n title={tr(\"devportal.revenue.netRevenue\", \"Net Revenue\")}\n value={`$${summary.totalNetRevenue.toLocaleString()}`}\n icon={<Wallet size={20} />}\n />\n <StatCard\n title={tr(\n \"devportal.revenue.pendingBalance\",\n \"Pending Balance\",\n )}\n value={`$${summary.pendingBalance.toLocaleString()}`}\n icon={<CreditCard size={20} />}\n description={\n summary.nextPayoutDate\n ? `${tr(\"devportal.revenue.nextPayout\", \"Next payout\")} ${new Date(summary.nextPayoutDate).toLocaleDateString()}`\n : tr(\n \"devportal.revenue.noPayoutScheduled\",\n \"No payout scheduled\",\n )\n }\n />\n <StatCard\n title={tr(\"devportal.revenue.platformFees\", \"Platform Fees\")}\n value={`$${summary.totalPlatformFees.toLocaleString()}`}\n icon={<ArrowDownToLine size={20} />}\n description={`${summary.totalRefundsCount} ${tr(\"devportal.revenue.refunds\", \"refunds\")}`}\n />\n </StatCardGrid>\n </EmphasisPanel>\n\n <div className=\"grid gap-6 xl:grid-cols-2\">\n <PageSection\n title={tr(\"devportal.revenue.revenueTrend\", \"Revenue trend\")}\n >\n <GlassCard treatment=\"insight\" className=\"p-4\">\n {chartData.length > 0 ? (\n <ResponsiveContainer width=\"100%\" height={300}>\n <LineChart data={chartData}>\n <CartesianGrid\n strokeDasharray=\"3 3\"\n stroke=\"var(--color-chart-grid)\"\n />\n <XAxis\n dataKey=\"date\"\n stroke=\"var(--color-chart-axis)\"\n fontSize={12}\n />\n <YAxis stroke=\"var(--color-chart-axis)\" fontSize={12} />\n <Tooltip\n contentStyle={{\n backgroundColor: \"var(--color-card)\",\n border: \"1px solid var(--color-border-default)\",\n borderRadius: 12,\n }}\n />\n <Line\n type=\"monotone\"\n dataKey=\"grossRevenue\"\n stroke={chartColors.primary}\n strokeWidth={2}\n dot={false}\n />\n <Line\n type=\"monotone\"\n dataKey=\"netRevenue\"\n stroke={chartColors.secondary}\n strokeWidth={2}\n dot={false}\n />\n </LineChart>\n </ResponsiveContainer>\n ) : (\n <div className=\"flex h-[300px] flex-col items-center justify-center gap-2 text-text-secondary\">\n <p className=\"text-sm font-medium\">\n {tr(\"devportal.revenue.noTrendData\", \"No trend data yet\")}\n </p>\n <p className=\"text-xs text-text-tertiary\">\n {tr(\n \"devportal.revenue.noTrendDataHint\",\n \"Revenue trend appears once daily analytics have been aggregated.\",\n )}\n </p>\n </div>\n )}\n </GlassCard>\n </PageSection>\n\n <PageSection\n title={tr(\n \"devportal.revenue.topApps\",\n \"Top applications by revenue\",\n )}\n >\n {summary.topApps.length > 0 ? (\n <div className=\"space-y-2\">\n {summary.topApps.map(\n (\n application: GetRevenueDashboardDataQuery[\"developerOrgRevenueSummary\"][\"topApps\"][number],\n ) => (\n <GlassCard\n key={application.applicationId}\n treatment=\"insight\"\n className=\"border-border-seam p-4\"\n >\n <div className=\"flex items-start justify-between gap-3\">\n <div>\n <p className=\"font-medium\">\n {application.applicationName}\n </p>\n <p className=\"text-sm text-text-secondary\">\n {application.salesCount}{\" \"}\n {tr(\"devportal.revenue.sales\", \"sales\")}\n </p>\n </div>\n <div className=\"text-right\">\n <p className=\"font-semibold\">\n ${application.grossRevenue.toLocaleString()}\n </p>\n <p className=\"text-sm text-text-secondary\">\n {tr(\"devportal.revenue.net\", \"Net\")} $\n {application.netRevenue.toLocaleString()}\n </p>\n </div>\n </div>\n </GlassCard>\n ),\n )}\n </div>\n ) : (\n <EmptyState\n illustration=\"empty-data\"\n icon={<Building2 size={24} />}\n title={tr(\n \"devportal.revenue.noLeadersTitle\",\n \"No revenue leaders yet\",\n )}\n description={tr(\n \"devportal.revenue.noLeadersDescription\",\n \"Top-performing applications will appear here once revenue is recorded.\",\n )}\n />\n )}\n </PageSection>\n </div>\n\n <PageSection\n title={tr(\"devportal.revenue.salesVolume\", \"Sales volume\")}\n >\n <GlassCard treatment=\"insight\" className=\"p-4\">\n {chartData.length > 0 ? (\n <ResponsiveContainer width=\"100%\" height={280}>\n <BarChart data={chartData}>\n <CartesianGrid\n strokeDasharray=\"3 3\"\n stroke=\"var(--color-chart-grid)\"\n />\n <XAxis\n dataKey=\"date\"\n stroke=\"var(--color-chart-axis)\"\n fontSize={12}\n />\n <YAxis stroke=\"var(--color-chart-axis)\" fontSize={12} />\n <Tooltip\n contentStyle={{\n backgroundColor: \"var(--color-card)\",\n border: \"1px solid var(--color-border-default)\",\n borderRadius: 12,\n }}\n />\n <Bar\n dataKey=\"salesCount\"\n fill={chartColors.tertiary}\n radius={[6, 6, 0, 0]}\n />\n </BarChart>\n </ResponsiveContainer>\n ) : (\n <div className=\"flex h-[280px] flex-col items-center justify-center gap-2 text-text-secondary\">\n <p className=\"text-sm font-medium\">\n {tr(\n \"devportal.revenue.noVolumeData\",\n \"No sales volume data yet\",\n )}\n </p>\n <p className=\"text-xs text-text-tertiary\">\n {tr(\n \"devportal.revenue.noVolumeDataHint\",\n \"Sales volume by period appears once analytics have been aggregated.\",\n )}\n </p>\n </div>\n )}\n </GlassCard>\n </PageSection>\n\n <div className=\"grid gap-6 xl:grid-cols-2\">\n <PageSection\n title={tr(\"devportal.revenue.recentSales\", \"Recent sales\")}\n >\n <DataTable\n data={sales}\n keyField=\"id\"\n columns={[\n {\n key: \"application\",\n header: tr(\"devportal.revenue.application\", \"Application\"),\n render: (sale) =>\n sale.application?.name ||\n sale.planName ||\n tr(\"devportal.common.unknown\", \"Unknown\"),\n },\n {\n key: \"grossAmount\",\n header: tr(\"devportal.revenue.gross\", \"Gross\"),\n render: (sale) => `$${sale.grossAmount.toLocaleString()}`,\n },\n {\n key: \"netAmount\",\n header: tr(\"devportal.revenue.net\", \"Net\"),\n render: (sale) => `$${sale.netAmount.toLocaleString()}`,\n },\n {\n key: \"status\",\n header: tr(\"devportal.revenue.status\", \"Status\"),\n render: (sale) => (\n <StatusBadge status={sale.status} type=\"app\" />\n ),\n },\n ]}\n />\n </PageSection>\n\n <PageSection\n title={tr(\"devportal.revenue.payoutHistory\", \"Payout history\")}\n >\n <DataTable\n data={payouts}\n keyField=\"id\"\n columns={[\n {\n key: \"periodLabel\",\n header: tr(\"devportal.revenue.period\", \"Period\"),\n render: (payout) => payout.periodLabel,\n },\n {\n key: \"netAmount\",\n header: tr(\"devportal.revenue.netPayout\", \"Net payout\"),\n render: (payout) => `$${payout.netAmount.toLocaleString()}`,\n },\n {\n key: \"status\",\n header: tr(\"devportal.revenue.status\", \"Status\"),\n render: (payout) => (\n <StatusBadge status={payout.status} type=\"app\" />\n ),\n },\n ]}\n />\n </PageSection>\n </div>\n </>\n ) : (\n <EmptyState\n illustration=\"empty-data\"\n icon={<DollarSign size={32} />}\n title={tr(\"devportal.revenue.noDataTitle\", \"No revenue data yet\")}\n description={tr(\n \"devportal.revenue.noDataDescription\",\n \"Revenue metrics will appear after this organization starts recording marketplace sales.\",\n )}\n />\n )}\n </PageLayout>\n );\n};\n"],"mappings":"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"}
@@ -4,9 +4,9 @@ import { PageLayout as n } from "../components/PageLayout.js";
4
4
  import { PermissionGuard as r } from "../components/PermissionGuard.js";
5
5
  import "../components/index.js";
6
6
  import { useEffect as i, useState as a } from "react";
7
- import { useI18n as o } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
8
- import { ArrowRight as s, Building2 as c, CheckCircle2 as l, Clock as u, DollarSign as d, Download as f, Loader2 as p, Package as m, Plus as h } from "lucide-react";
9
- import { Fragment as g, jsx as _, jsxs as v } from "react/jsx-runtime";
7
+ import { ArrowRight as o, Building2 as s, CheckCircle2 as c, Clock as l, DollarSign as u, Download as d, Loader2 as f, Package as p, Plus as m } from "lucide-react";
8
+ import { Fragment as h, jsx as g, jsxs as _ } from "react/jsx-runtime";
9
+ import { useI18n as v } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
10
10
  import { GlassCard as y, GradientText as b } from "@burdenoff/fe-libs/ui";
11
11
  //#region src/devportal/pages/SellerDashboardPage.tsx
12
12
  var x = {
@@ -41,7 +41,7 @@ function S(e, t) {
41
41
  }).format(e)} ${n}`;
42
42
  }
43
43
  var C = "\n query SellerDashboardBootstrap {\n myDeveloperOrganizations {\n id\n name\n slug\n logoUrl\n isVerified\n publishedApps\n totalInstalls\n totalRevenue\n }\n myPublisher {\n id\n }\n }\n", w = "\n query SellerDashboardProducts($publisherId: String!) {\n products(filter: { publisherId: $publisherId, nature: PHYSICAL }, limit: 3, offset: 0) {\n id\n name\n slug\n type\n status\n price\n currency\n stockQuantity\n icon\n }\n }\n", T = () => {
44
- let { navigate: d, basePath: f, apiGatewayUrl: y, authToken: x } = e(), { t: S } = o(), T = (e, t) => {
44
+ let { navigate: u, basePath: d, apiGatewayUrl: y, authToken: x } = e(), { t: S } = v(), T = (e, t) => {
45
45
  let n = S(e);
46
46
  return n === e ? t : n;
47
47
  }, A = y ?? "/global/graphql", [j, M] = a(!0), [N, P] = a(!1), [F, I] = a([]), [L, R] = a(null), [z, B] = a([]);
@@ -107,100 +107,100 @@ var C = "\n query SellerDashboardBootstrap {\n myDeveloperOrganizations {\n
107
107
  x
108
108
  ]);
109
109
  let V = j, H = j || N, U = !V && F.length > 0, W = !V && L !== null, G = z.length, K = z.filter((e) => e.status === "PENDING_REVIEW").length, q = z.filter((e) => e.status === "PUBLISHED").length, J = (e) => {
110
- d?.(`${f}${e}`);
110
+ u?.(`${d}${e}`);
111
111
  };
112
- return /* @__PURE__ */ _(r, {
112
+ return /* @__PURE__ */ g(r, {
113
113
  authOnly: !0,
114
- children: /* @__PURE__ */ _(n, {
115
- title: /* @__PURE__ */ v(g, { children: [
114
+ children: /* @__PURE__ */ g(n, {
115
+ title: /* @__PURE__ */ _(h, { children: [
116
116
  T("devportal.seller", "Seller"),
117
117
  " ",
118
- /* @__PURE__ */ _(b, { children: T("devportal.dashboard", "Dashboard") })
118
+ /* @__PURE__ */ g(b, { children: T("devportal.dashboard", "Dashboard") })
119
119
  ] }),
120
- actions: U ? /* @__PURE__ */ v("button", {
120
+ actions: U ? /* @__PURE__ */ _("button", {
121
121
  onClick: () => J("/seller/items/new"),
122
122
  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",
123
- children: [/* @__PURE__ */ _(h, { size: 16 }), T("devportal.listAnItem", "List an Item")]
124
- }) : V ? null : /* @__PURE__ */ v("button", {
123
+ children: [/* @__PURE__ */ g(m, { size: 16 }), T("devportal.listAnItem", "List an Item")]
124
+ }) : V ? null : /* @__PURE__ */ _("button", {
125
125
  onClick: () => J("/organizations/new"),
126
126
  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",
127
- children: [/* @__PURE__ */ _(h, { size: 16 }), T("devportal.createOrganization", "Create Organization")]
127
+ children: [/* @__PURE__ */ g(m, { size: 16 }), T("devportal.createOrganization", "Create Organization")]
128
128
  }),
129
- children: /* @__PURE__ */ v("div", {
129
+ children: /* @__PURE__ */ _("div", {
130
130
  className: "flex flex-col gap-8",
131
131
  children: [
132
- /* @__PURE__ */ _("div", {
132
+ /* @__PURE__ */ g("div", {
133
133
  className: "flex items-center gap-6 border-b border-border-seam pb-6",
134
- children: H ? /* @__PURE__ */ _(p, { className: "h-4 w-4 animate-spin text-text-secondary" }) : /* @__PURE__ */ v(g, { children: [
135
- /* @__PURE__ */ _(E, {
136
- icon: /* @__PURE__ */ _(m, { size: 14 }),
134
+ children: H ? /* @__PURE__ */ g(f, { className: "h-4 w-4 animate-spin text-text-secondary" }) : /* @__PURE__ */ _(h, { children: [
135
+ /* @__PURE__ */ g(E, {
136
+ icon: /* @__PURE__ */ g(p, { size: 14 }),
137
137
  value: G,
138
138
  label: T("devportal.items", "Items")
139
139
  }),
140
- /* @__PURE__ */ _("div", { className: "h-4 w-px bg-border-seam" }),
141
- /* @__PURE__ */ _(E, {
142
- icon: /* @__PURE__ */ _(u, { size: 14 }),
140
+ /* @__PURE__ */ g("div", { className: "h-4 w-px bg-border-seam" }),
141
+ /* @__PURE__ */ g(E, {
142
+ icon: /* @__PURE__ */ g(l, { size: 14 }),
143
143
  value: K,
144
144
  label: T("devportal.pendingReview", "Pending Review")
145
145
  }),
146
- /* @__PURE__ */ _("div", { className: "h-4 w-px bg-border-seam" }),
147
- /* @__PURE__ */ _(E, {
148
- icon: /* @__PURE__ */ _(l, { size: 14 }),
146
+ /* @__PURE__ */ g("div", { className: "h-4 w-px bg-border-seam" }),
147
+ /* @__PURE__ */ g(E, {
148
+ icon: /* @__PURE__ */ g(c, { size: 14 }),
149
149
  value: q,
150
150
  label: T("devportal.published", "Published")
151
151
  }),
152
- /* @__PURE__ */ _("div", { className: "h-4 w-px bg-border-seam" }),
153
- /* @__PURE__ */ _(E, {
154
- icon: /* @__PURE__ */ _(c, { size: 14 }),
152
+ /* @__PURE__ */ g("div", { className: "h-4 w-px bg-border-seam" }),
153
+ /* @__PURE__ */ g(E, {
154
+ icon: /* @__PURE__ */ g(s, { size: 14 }),
155
155
  value: F.length,
156
156
  label: T("devportal.organizations", "Organizations")
157
157
  })
158
158
  ] })
159
159
  }),
160
- /* @__PURE__ */ _(D, {
160
+ /* @__PURE__ */ g(D, {
161
161
  title: T("devportal.recentListings", "Recent Listings"),
162
- action: z.length > 0 ? /* @__PURE__ */ v("button", {
162
+ action: z.length > 0 ? /* @__PURE__ */ _("button", {
163
163
  onClick: () => J("/seller/items"),
164
164
  className: "inline-flex items-center gap-1 text-sm font-medium text-primary hover:underline",
165
- children: [T("devportal.viewAll", "View all"), /* @__PURE__ */ _(s, { size: 14 })]
165
+ children: [T("devportal.viewAll", "View all"), /* @__PURE__ */ g(o, { size: 14 })]
166
166
  }) : void 0,
167
- children: V || N ? /* @__PURE__ */ _("div", {
167
+ children: V || N ? /* @__PURE__ */ g("div", {
168
168
  className: "flex items-center justify-center py-12",
169
- children: /* @__PURE__ */ _(p, { className: "h-6 w-6 animate-spin text-text-secondary" })
170
- }) : z.length > 0 ? /* @__PURE__ */ _("div", {
169
+ children: /* @__PURE__ */ g(f, { className: "h-6 w-6 animate-spin text-text-secondary" })
170
+ }) : z.length > 0 ? /* @__PURE__ */ g("div", {
171
171
  className: "grid gap-4 grid-cols-1 sm:grid-cols-2 lg:grid-cols-3",
172
- children: z.slice(0, 3).map((e) => /* @__PURE__ */ _(O, {
172
+ children: z.slice(0, 3).map((e) => /* @__PURE__ */ g(O, {
173
173
  product: e,
174
174
  onClick: () => J("/seller/items")
175
175
  }, e.id))
176
- }) : /* @__PURE__ */ _(t, {
176
+ }) : /* @__PURE__ */ g(t, {
177
177
  illustration: "empty-data",
178
178
  title: W ? T("devportal.listYourFirstItem", "List your first item") : T("devportal.registerAsPublisherFirst", "Register as publisher first"),
179
179
  description: W ? T("devportal.addPhysicalProductsToYourStore", "Add physical products to your store and they will appear here") : T("devportal.createOrgToStartSelling", "Create an organization to start selling physical products"),
180
- action: U ? /* @__PURE__ */ v("button", {
180
+ action: U ? /* @__PURE__ */ _("button", {
181
181
  onClick: () => J("/seller/items/new"),
182
182
  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",
183
- children: [/* @__PURE__ */ _(h, { size: 16 }), T("devportal.listAnItem", "List an Item")]
184
- }) : /* @__PURE__ */ v("button", {
183
+ children: [/* @__PURE__ */ g(m, { size: 16 }), T("devportal.listAnItem", "List an Item")]
184
+ }) : /* @__PURE__ */ _("button", {
185
185
  onClick: () => J("/organizations/new"),
186
186
  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",
187
- children: [/* @__PURE__ */ _(h, { size: 16 }), T("devportal.createOrganization", "Create Organization")]
187
+ children: [/* @__PURE__ */ g(m, { size: 16 }), T("devportal.createOrganization", "Create Organization")]
188
188
  })
189
189
  })
190
190
  }),
191
- (V || F.length > 0) && /* @__PURE__ */ _(D, {
191
+ (V || F.length > 0) && /* @__PURE__ */ g(D, {
192
192
  title: T("devportal.yourOrganizations", "Your Organizations"),
193
- action: F.length > 0 ? /* @__PURE__ */ v("button", {
193
+ action: F.length > 0 ? /* @__PURE__ */ _("button", {
194
194
  onClick: () => J("/organizations"),
195
195
  className: "inline-flex items-center gap-1 text-sm font-medium text-primary hover:underline",
196
- children: [T("devportal.viewAll", "View all"), /* @__PURE__ */ _(s, { size: 14 })]
196
+ children: [T("devportal.viewAll", "View all"), /* @__PURE__ */ g(o, { size: 14 })]
197
197
  }) : void 0,
198
- children: V ? /* @__PURE__ */ _("div", {
198
+ children: V ? /* @__PURE__ */ g("div", {
199
199
  className: "flex items-center justify-center py-12",
200
- children: /* @__PURE__ */ _(p, { className: "h-6 w-6 animate-spin text-text-secondary" })
201
- }) : /* @__PURE__ */ _("div", {
200
+ children: /* @__PURE__ */ g(f, { className: "h-6 w-6 animate-spin text-text-secondary" })
201
+ }) : /* @__PURE__ */ g("div", {
202
202
  className: "grid gap-4 sm:grid-cols-2 lg:grid-cols-3",
203
- children: F.slice(0, 3).map((e) => /* @__PURE__ */ _(k, {
203
+ children: F.slice(0, 3).map((e) => /* @__PURE__ */ g(k, {
204
204
  org: e,
205
205
  onClick: () => J(`/organizations/${e.id}`)
206
206
  }, e.id))
@@ -210,34 +210,34 @@ var C = "\n query SellerDashboardBootstrap {\n myDeveloperOrganizations {\n
210
210
  })
211
211
  })
212
212
  });
213
- }, E = ({ icon: e, value: t, label: n }) => /* @__PURE__ */ v("div", {
213
+ }, E = ({ icon: e, value: t, label: n }) => /* @__PURE__ */ _("div", {
214
214
  className: "flex items-center gap-1.5",
215
215
  children: [
216
- /* @__PURE__ */ _("span", {
216
+ /* @__PURE__ */ g("span", {
217
217
  className: "text-text-muted",
218
218
  children: e
219
219
  }),
220
- /* @__PURE__ */ _("span", {
220
+ /* @__PURE__ */ g("span", {
221
221
  className: "text-sm font-semibold tabular-nums",
222
222
  children: t
223
223
  }),
224
- /* @__PURE__ */ _("span", {
224
+ /* @__PURE__ */ g("span", {
225
225
  className: "text-sm text-text-secondary",
226
226
  children: n
227
227
  })
228
228
  ]
229
- }), D = ({ title: e, action: t, children: n }) => /* @__PURE__ */ v("section", {
229
+ }), D = ({ title: e, action: t, children: n }) => /* @__PURE__ */ _("section", {
230
230
  className: "flex flex-col gap-4",
231
- children: [/* @__PURE__ */ v("div", {
231
+ children: [/* @__PURE__ */ _("div", {
232
232
  className: "flex items-center justify-between",
233
- children: [/* @__PURE__ */ _("h2", {
233
+ children: [/* @__PURE__ */ g("h2", {
234
234
  className: "text-sm font-semibold uppercase tracking-wider text-text-secondary",
235
235
  children: e
236
236
  }), t]
237
237
  }), n]
238
238
  }), O = ({ product: e, onClick: t }) => {
239
239
  let n = x[e.status] ?? x.DRAFT;
240
- return /* @__PURE__ */ v(y, {
240
+ return /* @__PURE__ */ _(y, {
241
241
  treatment: "insight",
242
242
  role: "button",
243
243
  tabIndex: 0,
@@ -246,49 +246,49 @@ var C = "\n query SellerDashboardBootstrap {\n myDeveloperOrganizations {\n
246
246
  onKeyDown: (e) => {
247
247
  (e.key === "Enter" || e.key === " ") && (e.preventDefault(), t());
248
248
  },
249
- children: [/* @__PURE__ */ v("div", {
249
+ children: [/* @__PURE__ */ _("div", {
250
250
  className: "flex items-center gap-3 mb-4",
251
251
  children: [
252
- e.icon ? /* @__PURE__ */ _("img", {
252
+ e.icon ? /* @__PURE__ */ g("img", {
253
253
  src: e.icon,
254
254
  alt: e.name,
255
255
  className: "h-10 w-10 rounded-xl object-cover shrink-0"
256
- }) : /* @__PURE__ */ _("div", {
256
+ }) : /* @__PURE__ */ g("div", {
257
257
  className: "flex h-10 w-10 items-center justify-center rounded-xl bg-action-primary-bg/15 text-primary shrink-0",
258
- children: /* @__PURE__ */ _(m, { size: 20 })
258
+ children: /* @__PURE__ */ g(p, { size: 20 })
259
259
  }),
260
- /* @__PURE__ */ v("div", {
260
+ /* @__PURE__ */ _("div", {
261
261
  className: "min-w-0 flex-1",
262
- children: [/* @__PURE__ */ _("p", {
262
+ children: [/* @__PURE__ */ g("p", {
263
263
  className: "font-semibold truncate text-text-primary",
264
264
  children: e.name
265
- }), /* @__PURE__ */ _("p", {
265
+ }), /* @__PURE__ */ g("p", {
266
266
  className: "text-xs text-text-secondary mt-0.5",
267
267
  children: S(e.price, e.currency)
268
268
  })]
269
269
  }),
270
- /* @__PURE__ */ _("span", {
270
+ /* @__PURE__ */ g("span", {
271
271
  className: `shrink-0 rounded-full px-2.5 py-0.5 text-xs font-medium ${n.className}`,
272
272
  children: n.label
273
273
  })
274
274
  ]
275
- }), /* @__PURE__ */ v("div", {
275
+ }), /* @__PURE__ */ _("div", {
276
276
  className: "flex items-center gap-2 text-sm",
277
- children: [/* @__PURE__ */ _(m, {
277
+ children: [/* @__PURE__ */ g(p, {
278
278
  size: 12,
279
279
  className: "text-text-muted shrink-0"
280
- }), /* @__PURE__ */ _("span", {
280
+ }), /* @__PURE__ */ g("span", {
281
281
  className: e.stockQuantity === 0 ? "text-status-error-text" : "text-text-secondary",
282
282
  children: e.stockQuantity === 0 ? "Out of stock" : `${e.stockQuantity} in stock`
283
283
  })]
284
284
  })]
285
285
  });
286
286
  }, k = ({ org: e, onClick: t }) => {
287
- let { t: n } = o(), r = (e, t) => {
287
+ let { t: n } = v(), r = (e, t) => {
288
288
  let r = n(e);
289
289
  return r === e ? t : r;
290
290
  }, i = e.name.split(" ").map((e) => e[0]).join("").slice(0, 2).toUpperCase();
291
- return /* @__PURE__ */ v(y, {
291
+ return /* @__PURE__ */ _(y, {
292
292
  treatment: "insight",
293
293
  role: "button",
294
294
  tabIndex: 0,
@@ -297,23 +297,23 @@ var C = "\n query SellerDashboardBootstrap {\n myDeveloperOrganizations {\n
297
297
  onKeyDown: (e) => {
298
298
  (e.key === "Enter" || e.key === " ") && (e.preventDefault(), t());
299
299
  },
300
- children: [/* @__PURE__ */ v("div", {
300
+ children: [/* @__PURE__ */ _("div", {
301
301
  className: "flex items-center gap-3 mb-4",
302
302
  children: [
303
- e.logoUrl ? /* @__PURE__ */ _("img", {
303
+ e.logoUrl ? /* @__PURE__ */ g("img", {
304
304
  src: e.logoUrl,
305
305
  alt: e.name,
306
306
  className: "h-10 w-10 rounded-xl object-cover"
307
- }) : /* @__PURE__ */ _("div", {
307
+ }) : /* @__PURE__ */ g("div", {
308
308
  className: "flex h-10 w-10 items-center justify-center rounded-xl bg-action-primary-bg/15 text-primary text-sm font-bold",
309
309
  children: i
310
310
  }),
311
- /* @__PURE__ */ v("div", {
311
+ /* @__PURE__ */ _("div", {
312
312
  className: "min-w-0 flex-1",
313
- children: [/* @__PURE__ */ _("p", {
313
+ children: [/* @__PURE__ */ g("p", {
314
314
  className: "font-semibold truncate text-text-primary",
315
315
  children: e.name
316
- }), /* @__PURE__ */ v("p", {
316
+ }), /* @__PURE__ */ _("p", {
317
317
  className: "text-xs text-text-secondary mt-0.5",
318
318
  children: [
319
319
  e.publishedApps ?? 0,
@@ -322,34 +322,34 @@ var C = "\n query SellerDashboardBootstrap {\n myDeveloperOrganizations {\n
322
322
  ]
323
323
  })]
324
324
  }),
325
- /* @__PURE__ */ _(s, {
325
+ /* @__PURE__ */ g(o, {
326
326
  size: 15,
327
327
  className: "text-text-muted shrink-0"
328
328
  })
329
329
  ]
330
- }), /* @__PURE__ */ v("div", {
330
+ }), /* @__PURE__ */ _("div", {
331
331
  className: "grid grid-cols-2 gap-3",
332
- children: [/* @__PURE__ */ v("div", {
332
+ children: [/* @__PURE__ */ _("div", {
333
333
  className: "flex items-center gap-2 rounded-lg bg-bg-muted px-3 py-2",
334
- children: [/* @__PURE__ */ _(f, {
334
+ children: [/* @__PURE__ */ g(d, {
335
335
  size: 12,
336
336
  className: "text-text-muted shrink-0"
337
- }), /* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("p", {
337
+ }), /* @__PURE__ */ _("div", { children: [/* @__PURE__ */ g("p", {
338
338
  className: "text-[11px] text-text-secondary leading-none mb-0.5",
339
339
  children: r("devportal.installs", "Installs")
340
- }), /* @__PURE__ */ _("p", {
340
+ }), /* @__PURE__ */ g("p", {
341
341
  className: "text-sm font-semibold tabular-nums",
342
342
  children: (e.totalInstalls ?? 0).toLocaleString()
343
343
  })] })]
344
- }), /* @__PURE__ */ v("div", {
344
+ }), /* @__PURE__ */ _("div", {
345
345
  className: "flex items-center gap-2 rounded-lg bg-bg-muted px-3 py-2",
346
- children: [/* @__PURE__ */ _(d, {
346
+ children: [/* @__PURE__ */ g(u, {
347
347
  size: 12,
348
348
  className: "text-text-muted shrink-0"
349
- }), /* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("p", {
349
+ }), /* @__PURE__ */ _("div", { children: [/* @__PURE__ */ g("p", {
350
350
  className: "text-[11px] text-text-secondary leading-none mb-0.5",
351
351
  children: r("devportal.revenue", "Revenue")
352
- }), /* @__PURE__ */ v("p", {
352
+ }), /* @__PURE__ */ _("p", {
353
353
  className: "text-sm font-semibold tabular-nums",
354
354
  children: ["$", (e.totalRevenue ?? 0).toLocaleString()]
355
355
  })] })]