@burdenoff/microfe-store 2026.626.1 → 2026.626.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.
@@ -1 +0,0 @@
1
- {"version":3,"file":"PublisherDashboardPage.js","names":[],"sources":["../../src/pages/PublisherDashboardPage.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { useMemo } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { ArrowLeft, Star, Download, Plus, LineChart, MessageSquare } from 'lucide-react';\nimport { useStore } from '../providers/StoreProvider';\nimport { useMyPublishedProducts } from '../hooks/useStoreGraphQL';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n GlassCard,\n EmphasisPanel,\n PagePurpose,\n NextSteps,\n IllustratedEmptyState,\n} from '@burdenoff/fe-libs/ui';\n\nexport const PublisherDashboardPage: FC = () => {\n const navigate = useNavigate();\n const { basePath } = useStore();\n const { t } = useI18n();\n const { products, loading, error, refetch } = useMyPublishedProducts();\n\n const metrics = useMemo(() => {\n const totalProducts = products.length;\n const totalDownloads = products.reduce((sum, p) => sum + (p.downloads ?? 0), 0);\n const avgRating =\n totalProducts > 0 ? products.reduce((sum, p) => sum + (p.rating ?? 0), 0) / totalProducts : 0;\n return {\n totalProducts,\n totalDownloads,\n avgRating,\n };\n }, [products]);\n\n return (\n <div className=\"flex h-full flex-col\">\n <header className=\"border-b border-border-seam bg-bg-surface px-6 py-4\">\n <div className=\"mx-auto flex max-w-6xl items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n <button\n type=\"button\"\n onClick={() => navigate(-1)}\n aria-label=\"Go back\"\n className=\"cursor-pointer rounded-lg p-2 text-text-muted transition-colors hover:bg-bg-sunken hover:text-text-primary\"\n >\n <ArrowLeft className=\"size-5\" />\n </button>\n <div>\n <h1 className=\"text-2xl font-bold text-text-primary\">\n {t('pages.publisherDashboard.title', { defaultValue: 'Publisher Dashboard' })}\n </h1>\n <p className=\"text-sm text-text-muted\">\n {t('pages.publisherDashboard.subtitle', {\n defaultValue: 'Manage your published products and performance',\n })}\n </p>\n </div>\n </div>\n\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/publisher/submit`)}\n className=\"inline-flex cursor-pointer items-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-semibold text-action-primary-text\"\n >\n <Plus className=\"size-4\" />\n Submit Product\n </button>\n </div>\n </header>\n\n <main className=\"flex-1 overflow-y-auto p-6\">\n <div className=\"mx-auto max-w-6xl space-y-6\">\n <PagePurpose>\n Your home base as a marketplace seller. Track how your published products are performing\n — downloads, ratings and revenue — submit new products for review, and respond to\n customer reviews. Use it to decide what to build next and to keep your listings healthy.\n </PagePurpose>\n\n <NextSteps\n storageKey=\"store-publisher-dashboard\"\n steps={[\n {\n id: 'submit',\n label: 'Submit a product',\n description: 'List a new app or tool for review and publishing.',\n icon: <Plus className=\"size-4\" />,\n onClick: () => navigate(`${basePath}/publisher/submit`),\n done: metrics.totalProducts > 0,\n },\n {\n id: 'revenue',\n label: 'Check your earnings',\n description: 'See revenue and payouts across your products.',\n icon: <LineChart className=\"size-4\" />,\n onClick: () => navigate(`${basePath}/publisher/revenue`),\n },\n {\n id: 'track',\n label: 'Track submission status',\n description: 'Follow products through the review pipeline.',\n onClick: () => navigate(`${basePath}/publisher/submissions`),\n },\n ]}\n />\n\n <div className=\"grid gap-4 sm:grid-cols-3\">\n <GlassCard treatment=\"metric\" className=\"p-4\">\n <p className=\"text-xs uppercase tracking-wide text-text-muted\">\n {t('pages.publisherDashboard.totalProducts', {\n defaultValue: 'Published products',\n })}\n </p>\n <p className=\"mt-2 text-2xl font-bold tabular-nums text-text-primary\">\n {metrics.totalProducts}\n </p>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"p-4\">\n <p className=\"text-xs uppercase tracking-wide text-text-muted\">\n {t('pages.publisherDashboard.totalInstalls', { defaultValue: 'Total downloads' })}\n </p>\n <p className=\"mt-2 text-2xl font-bold tabular-nums text-text-primary\">\n {metrics.totalDownloads}\n </p>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"p-4\">\n <p className=\"text-xs uppercase tracking-wide text-text-muted\">\n {t('pages.publisherDashboard.avgRating', { defaultValue: 'Average rating' })}\n </p>\n <p className=\"mt-2 text-2xl font-bold tabular-nums text-text-primary\">\n {metrics.avgRating.toFixed(1)}\n </p>\n </GlassCard>\n </div>\n\n <EmphasisPanel>\n <div className=\"mb-4 flex items-center justify-between\">\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {t('pages.publisherDashboard.yourProducts', { defaultValue: 'Your Products' })}\n </h2>\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/publisher/revenue`)}\n className=\"inline-flex cursor-pointer items-center gap-1.5 text-sm font-medium text-text-link hover:underline\"\n >\n <LineChart className=\"size-4\" />\n Revenue\n </button>\n </div>\n\n {loading ? (\n <p role=\"status\" className=\"text-sm text-text-muted\">\n {t('common.loading', { defaultValue: 'Loading...' })}\n </p>\n ) : error ? (\n <div role=\"alert\" className=\"space-y-2\">\n <p className=\"text-sm text-status-error-text\">\n {t('pages.publisherDashboard.failedToLoad', {\n defaultValue: 'Failed to load publisher products.',\n })}\n </p>\n <button\n type=\"button\"\n onClick={() => refetch()}\n className=\"cursor-pointer rounded-lg bg-action-primary-bg px-3 py-1.5 text-xs font-semibold text-action-primary-text\"\n >\n Retry\n </button>\n </div>\n ) : products.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title={t('pages.publisherDashboard.noProductsTitle', {\n defaultValue: 'No published products yet',\n })}\n description={t('pages.publisherDashboard.noProducts', {\n defaultValue:\n 'No published products yet. Submit your first product to get started.',\n })}\n action={\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/publisher/submit`)}\n className=\"inline-flex cursor-pointer items-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-semibold text-action-primary-text hover:opacity-90\"\n >\n <Plus className=\"size-4\" />\n Submit Product\n </button>\n }\n />\n ) : (\n <ul className=\"space-y-3\">\n {products.map((product) => (\n <li\n key={product.id}\n className=\"flex items-center justify-between rounded-lg border border-border-seam bg-bg-surface p-3 transition-[box-shadow,border-color] hover:border-border-strong hover:shadow-[var(--shadow-pop)]\"\n >\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/marketplace/product/${product.id}`)}\n className=\"flex flex-1 cursor-pointer items-center justify-between text-left\"\n >\n <div>\n <p className=\"font-medium text-text-primary\">{product.name}</p>\n <p className=\"text-xs text-text-muted\">{product.status}</p>\n </div>\n <div className=\"flex items-center gap-4 text-xs text-text-muted\">\n <span className=\"inline-flex items-center gap-1\">\n <Star className=\"size-3.5\" />\n {(product.rating ?? 0).toFixed(1)}\n </span>\n <span className=\"inline-flex items-center gap-1\">\n <Download className=\"size-3.5\" />\n {product.downloads}\n </span>\n </div>\n </button>\n <button\n type=\"button\"\n onClick={() =>\n navigate(`${basePath}/publisher/product/${product.id}/reviews`)\n }\n className=\"ml-3 inline-flex cursor-pointer items-center gap-1 rounded-md px-2 py-1 text-xs font-medium text-text-link hover:bg-bg-sunken hover:underline\"\n title=\"View reviews\"\n >\n <MessageSquare className=\"size-3.5\" />\n Reviews\n </button>\n </li>\n ))}\n </ul>\n )}\n </EmphasisPanel>\n </div>\n </main>\n </div>\n );\n};\n"],"mappings":"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"}
@@ -1,142 +0,0 @@
1
- import { useDeveloperEarnings as e } from "../hooks/useStoreGraphQL.js";
2
- import { useMemo as t } from "react";
3
- import { useI18n as n } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
4
- import { ArrowLeft as r, Clock3 as i, TrendingUp as a, Wallet as o } from "lucide-react";
5
- import { Fragment as s, jsx as c, jsxs as l } from "react/jsx-runtime";
6
- import { useNavigate as u } from "react-router-dom";
7
- import { EmphasisPanel as d, GlassCard as f, IllustratedEmptyState as p, PagePurpose as m } from "@burdenoff/fe-libs/ui";
8
- //#region src/pages/PublisherRevenuePage.tsx
9
- var h = () => {
10
- let h = u(), { earnings: g, loading: _, error: v, refetch: y } = e(), { t: b } = n(), x = g ?? null, S = x?.currency || "USD", C = t(() => new Intl.NumberFormat(void 0, {
11
- style: "currency",
12
- currency: S,
13
- maximumFractionDigits: 2
14
- }), [S]);
15
- return /* @__PURE__ */ l("div", {
16
- className: "flex h-full flex-col",
17
- children: [/* @__PURE__ */ c("header", {
18
- className: "border-b border-border-seam bg-bg-surface px-6 py-4",
19
- children: /* @__PURE__ */ l("div", {
20
- className: "mx-auto flex max-w-6xl items-center gap-3",
21
- children: [/* @__PURE__ */ c("button", {
22
- type: "button",
23
- onClick: () => h(-1),
24
- "aria-label": "Go back",
25
- className: "cursor-pointer rounded-lg p-2 text-text-muted hover:bg-bg-sunken hover:text-text-primary",
26
- children: /* @__PURE__ */ c(r, { className: "size-5" })
27
- }), /* @__PURE__ */ l("div", { children: [/* @__PURE__ */ c("h1", {
28
- className: "text-2xl font-bold text-text-primary",
29
- children: b("pages.publisherRevenue.title", { defaultValue: "Revenue" })
30
- }), /* @__PURE__ */ c("p", {
31
- className: "text-sm text-text-muted",
32
- children: b("pages.publisherRevenue.subtitle", { defaultValue: "Track publisher earnings and payouts" })
33
- })] })]
34
- })
35
- }), /* @__PURE__ */ c("main", {
36
- className: "flex-1 overflow-y-auto p-6",
37
- children: /* @__PURE__ */ l("div", {
38
- className: "mx-auto max-w-6xl space-y-6",
39
- children: [/* @__PURE__ */ c(m, { children: "See what your published products are actually earning. Track total and monthly revenue, how many orders came in, and which products sell best — so you know where your income comes from and which listings are worth doubling down on." }), _ ? /* @__PURE__ */ c("p", {
40
- role: "status",
41
- className: "text-sm text-text-muted",
42
- children: "Loading earnings…"
43
- }) : v ? /* @__PURE__ */ l("div", {
44
- role: "alert",
45
- className: "space-y-2 rounded-xl border border-status-error-border bg-status-error-bg-subtle p-6",
46
- children: [/* @__PURE__ */ c("p", {
47
- className: "text-sm text-status-error-text",
48
- children: b("pages.publisherRevenue.failedToLoad", { defaultValue: "Failed to load earnings data." })
49
- }), /* @__PURE__ */ c("button", {
50
- type: "button",
51
- onClick: () => y(),
52
- className: "cursor-pointer rounded-lg bg-action-primary-bg px-3 py-1.5 text-xs font-semibold text-action-primary-text",
53
- children: "Retry"
54
- })]
55
- }) : x ? /* @__PURE__ */ l(s, { children: [/* @__PURE__ */ l("div", {
56
- className: "grid gap-4 sm:grid-cols-3",
57
- children: [
58
- /* @__PURE__ */ l(f, {
59
- treatment: "metric",
60
- className: "p-4",
61
- children: [/* @__PURE__ */ l("div", {
62
- className: "inline-flex items-center gap-2 text-xs uppercase tracking-wide text-text-muted",
63
- children: [
64
- /* @__PURE__ */ c(o, { className: "size-4" }),
65
- " ",
66
- b("pages.publisherRevenue.totalEarnings", { defaultValue: "Total earnings" })
67
- ]
68
- }), /* @__PURE__ */ c("p", {
69
- className: "mt-2 text-2xl font-bold tabular-nums text-text-primary",
70
- children: C.format(x.totalEarnings)
71
- })]
72
- }),
73
- /* @__PURE__ */ l(f, {
74
- treatment: "metric",
75
- className: "p-4",
76
- children: [/* @__PURE__ */ l("div", {
77
- className: "inline-flex items-center gap-2 text-xs uppercase tracking-wide text-text-muted",
78
- children: [
79
- /* @__PURE__ */ c(i, { className: "size-4" }),
80
- " ",
81
- b("pages.publisherRevenue.monthlyEarnings", { defaultValue: "Monthly earnings" })
82
- ]
83
- }), /* @__PURE__ */ c("p", {
84
- className: "mt-2 text-2xl font-bold tabular-nums text-text-primary",
85
- children: C.format(x.monthlyEarnings)
86
- })]
87
- }),
88
- /* @__PURE__ */ l(f, {
89
- treatment: "metric",
90
- className: "p-4",
91
- children: [/* @__PURE__ */ l("div", {
92
- className: "inline-flex items-center gap-2 text-xs uppercase tracking-wide text-text-muted",
93
- children: [
94
- /* @__PURE__ */ c(a, { className: "size-4" }),
95
- " ",
96
- b("pages.publisherRevenue.monthlyOrders", { defaultValue: "Monthly orders" })
97
- ]
98
- }), /* @__PURE__ */ c("p", {
99
- className: "mt-2 text-2xl font-bold tabular-nums text-text-primary",
100
- children: x.monthlyOrders
101
- })]
102
- })
103
- ]
104
- }), /* @__PURE__ */ l(d, { children: [/* @__PURE__ */ c("h2", {
105
- className: "mb-3 text-lg font-semibold text-text-primary",
106
- children: b("pages.publisherRevenue.topSelling", { defaultValue: "Top Selling Items" })
107
- }), !x.topSellingItems || x.topSellingItems.length === 0 ? /* @__PURE__ */ c("p", {
108
- className: "text-sm text-text-muted",
109
- children: b("pages.publisherRevenue.noSales", { defaultValue: "No product sales found for this period." })
110
- }) : /* @__PURE__ */ c("ul", {
111
- className: "space-y-2",
112
- children: x.topSellingItems.map((e) => /* @__PURE__ */ l("li", {
113
- className: "flex items-center justify-between rounded-lg border border-border-seam bg-bg-surface p-3",
114
- children: [/* @__PURE__ */ l("div", { children: [/* @__PURE__ */ c("p", {
115
- className: "text-sm font-medium text-text-primary",
116
- children: e.storeProduct.name
117
- }), /* @__PURE__ */ l("p", {
118
- className: "text-xs text-text-muted",
119
- children: [
120
- e.totalSales,
121
- " total sales • ",
122
- e.monthlySales,
123
- " this period"
124
- ]
125
- })] }), /* @__PURE__ */ c("p", {
126
- className: "text-sm font-semibold text-text-primary",
127
- children: C.format(e.totalEarnings)
128
- })]
129
- }, e.storeProduct.id))
130
- })] })] }) : /* @__PURE__ */ c(p, {
131
- illustration: "empty-data",
132
- title: b("pages.publisherRevenue.noRevenueTitle", { defaultValue: "No revenue data yet" }),
133
- description: b("pages.publisherRevenue.noRevenue", { defaultValue: "No revenue data available yet. Earnings will appear here once your published products start selling." })
134
- })]
135
- })
136
- })]
137
- });
138
- };
139
- //#endregion
140
- export { h as PublisherRevenuePage };
141
-
142
- //# sourceMappingURL=PublisherRevenuePage.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"PublisherRevenuePage.js","names":[],"sources":["../../src/pages/PublisherRevenuePage.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { useMemo } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { ArrowLeft, Wallet, Clock3, TrendingUp } from 'lucide-react';\nimport { useDeveloperEarnings } from '../hooks/useStoreGraphQL';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n GlassCard,\n EmphasisPanel,\n PagePurpose,\n IllustratedEmptyState,\n} from '@burdenoff/fe-libs/ui';\n\ninterface EarningsPayload {\n totalEarnings: number;\n monthlyEarnings: number;\n totalOrders: number;\n monthlyOrders: number;\n currency: string;\n earnings?: Array<{\n month: string;\n year: number;\n earnings: number;\n orders: number;\n currency: string;\n }>;\n topSellingItems?: Array<{\n storeProduct: { id: string; name: string };\n totalSales: number;\n totalEarnings: number;\n monthlySales: number;\n monthlyEarnings: number;\n currency: string;\n }>;\n}\n\nexport const PublisherRevenuePage: FC = () => {\n const navigate = useNavigate();\n const { earnings, loading, error, refetch } = useDeveloperEarnings();\n const { t } = useI18n();\n\n const data = (earnings as EarningsPayload | null) ?? null;\n const currency = data?.currency || 'USD';\n\n const fmt = useMemo(\n () =>\n new Intl.NumberFormat(undefined, {\n style: 'currency',\n currency,\n maximumFractionDigits: 2,\n }),\n [currency]\n );\n\n return (\n <div className=\"flex h-full flex-col\">\n <header className=\"border-b border-border-seam bg-bg-surface px-6 py-4\">\n <div className=\"mx-auto flex max-w-6xl items-center gap-3\">\n <button\n type=\"button\"\n onClick={() => navigate(-1)}\n aria-label=\"Go back\"\n className=\"cursor-pointer rounded-lg p-2 text-text-muted hover:bg-bg-sunken hover:text-text-primary\"\n >\n <ArrowLeft className=\"size-5\" />\n </button>\n <div>\n <h1 className=\"text-2xl font-bold text-text-primary\">\n {t('pages.publisherRevenue.title', { defaultValue: 'Revenue' })}\n </h1>\n <p className=\"text-sm text-text-muted\">\n {t('pages.publisherRevenue.subtitle', {\n defaultValue: 'Track publisher earnings and payouts',\n })}\n </p>\n </div>\n </div>\n </header>\n\n <main className=\"flex-1 overflow-y-auto p-6\">\n <div className=\"mx-auto max-w-6xl space-y-6\">\n <PagePurpose>\n See what your published products are actually earning. Track total and monthly revenue,\n how many orders came in, and which products sell best — so you know where your income\n comes from and which listings are worth doubling down on.\n </PagePurpose>\n {loading ? (\n <p role=\"status\" className=\"text-sm text-text-muted\">\n Loading earnings…\n </p>\n ) : error ? (\n <div\n role=\"alert\"\n className=\"space-y-2 rounded-xl border border-status-error-border bg-status-error-bg-subtle p-6\"\n >\n <p className=\"text-sm text-status-error-text\">\n {t('pages.publisherRevenue.failedToLoad', {\n defaultValue: 'Failed to load earnings data.',\n })}\n </p>\n <button\n type=\"button\"\n onClick={() => refetch()}\n className=\"cursor-pointer rounded-lg bg-action-primary-bg px-3 py-1.5 text-xs font-semibold text-action-primary-text\"\n >\n Retry\n </button>\n </div>\n ) : !data ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title={t('pages.publisherRevenue.noRevenueTitle', {\n defaultValue: 'No revenue data yet',\n })}\n description={t('pages.publisherRevenue.noRevenue', {\n defaultValue:\n 'No revenue data available yet. Earnings will appear here once your published products start selling.',\n })}\n />\n ) : (\n <>\n <div className=\"grid gap-4 sm:grid-cols-3\">\n <GlassCard treatment=\"metric\" className=\"p-4\">\n <div className=\"inline-flex items-center gap-2 text-xs uppercase tracking-wide text-text-muted\">\n <Wallet className=\"size-4\" />{' '}\n {t('pages.publisherRevenue.totalEarnings', { defaultValue: 'Total earnings' })}\n </div>\n <p className=\"mt-2 text-2xl font-bold tabular-nums text-text-primary\">\n {fmt.format(data.totalEarnings)}\n </p>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"p-4\">\n <div className=\"inline-flex items-center gap-2 text-xs uppercase tracking-wide text-text-muted\">\n <Clock3 className=\"size-4\" />{' '}\n {t('pages.publisherRevenue.monthlyEarnings', {\n defaultValue: 'Monthly earnings',\n })}\n </div>\n <p className=\"mt-2 text-2xl font-bold tabular-nums text-text-primary\">\n {fmt.format(data.monthlyEarnings)}\n </p>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"p-4\">\n <div className=\"inline-flex items-center gap-2 text-xs uppercase tracking-wide text-text-muted\">\n <TrendingUp className=\"size-4\" />{' '}\n {t('pages.publisherRevenue.monthlyOrders', { defaultValue: 'Monthly orders' })}\n </div>\n <p className=\"mt-2 text-2xl font-bold tabular-nums text-text-primary\">\n {data.monthlyOrders}\n </p>\n </GlassCard>\n </div>\n\n <EmphasisPanel>\n <h2 className=\"mb-3 text-lg font-semibold text-text-primary\">\n {t('pages.publisherRevenue.topSelling', { defaultValue: 'Top Selling Items' })}\n </h2>\n {!data.topSellingItems || data.topSellingItems.length === 0 ? (\n <p className=\"text-sm text-text-muted\">\n {t('pages.publisherRevenue.noSales', {\n defaultValue: 'No product sales found for this period.',\n })}\n </p>\n ) : (\n <ul className=\"space-y-2\">\n {data.topSellingItems.map((item) => (\n <li\n key={item.storeProduct.id}\n className=\"flex items-center justify-between rounded-lg border border-border-seam bg-bg-surface p-3\"\n >\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {item.storeProduct.name}\n </p>\n <p className=\"text-xs text-text-muted\">\n {item.totalSales} total sales • {item.monthlySales} this period\n </p>\n </div>\n <p className=\"text-sm font-semibold text-text-primary\">\n {fmt.format(item.totalEarnings)}\n </p>\n </li>\n ))}\n </ul>\n )}\n </EmphasisPanel>\n </>\n )}\n </div>\n </main>\n </div>\n );\n};\n"],"mappings":"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"}
@@ -1,188 +0,0 @@
1
- import { useStore as e } from "../providers/StoreProvider.js";
2
- import { useSubmissionStatusUpdatedSubscription as t } from "../generated/global-operations.js";
3
- import { useMyPublishedProducts as n } from "../hooks/useStoreGraphQL.js";
4
- import { useMemo as r } from "react";
5
- import { useI18n as i } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
6
- import { ArrowLeft as a, CheckCircle2 as o, Clock3 as s, MessageSquare as c, XCircle as l } from "lucide-react";
7
- import { jsx as u, jsxs as d } from "react/jsx-runtime";
8
- import { useNavigate as f } from "react-router-dom";
9
- import { EmphasisPanel as p, GlassCard as m, IllustratedEmptyState as h, PagePurpose as g } from "@burdenoff/fe-libs/ui";
10
- //#region src/pages/PublisherSubmissionsPage.tsx
11
- var _ = (e) => e === "PUBLISHED" || e === "APPROVED" ? "bg-status-success-bg-subtle text-status-success-text" : e === "REJECTED" || e === "UNLISTED" ? "bg-status-error-bg-subtle text-status-error-text" : e === "PENDING" || e === "SUBMITTED" || e === "UNDER_REVIEW" ? "bg-status-warning-bg-subtle text-status-warning-text" : "bg-bg-sunken text-text-muted", v = () => {
12
- let v = f(), { basePath: y, currentUser: b } = e(), { products: x, hasMore: S, loading: C, error: w, refetch: T, loadMore: E } = n(), { t: D } = i(), O = b?.id;
13
- t({
14
- variables: { publisherId: O ?? "" },
15
- skip: !O,
16
- onData: () => {
17
- T();
18
- },
19
- onError: (e) => {
20
- console.warn("SubmissionStatusUpdated subscription error:", e.message);
21
- }
22
- });
23
- let k = r(() => {
24
- let e = x.filter((e) => e.status === "PUBLISHED" || e.status === "APPROVED").length, t = x.filter((e) => e.status === "REJECTED" || e.status === "UNLISTED").length;
25
- return {
26
- approved: e,
27
- rejected: t,
28
- pending: x.length - e - t
29
- };
30
- }, [x]);
31
- return /* @__PURE__ */ d("div", {
32
- className: "flex h-full flex-col",
33
- children: [/* @__PURE__ */ u("header", {
34
- className: "border-b border-border-seam bg-bg-surface px-6 py-4",
35
- children: /* @__PURE__ */ d("div", {
36
- className: "mx-auto flex max-w-6xl items-center gap-3",
37
- children: [/* @__PURE__ */ u("button", {
38
- type: "button",
39
- onClick: () => v(-1),
40
- "aria-label": "Go back",
41
- className: "cursor-pointer rounded-lg p-2 text-text-muted hover:bg-bg-sunken hover:text-text-primary",
42
- children: /* @__PURE__ */ u(a, { className: "size-5" })
43
- }), /* @__PURE__ */ d("div", { children: [/* @__PURE__ */ u("h1", {
44
- className: "text-2xl font-bold text-text-primary",
45
- children: D("pages.publisherSubmissions.title", { defaultValue: "Submissions" })
46
- }), /* @__PURE__ */ u("p", {
47
- className: "text-sm text-text-muted",
48
- children: D("pages.publisherSubmissions.subtitle", { defaultValue: "Track approval status for your store products" })
49
- })] })]
50
- })
51
- }), /* @__PURE__ */ u("main", {
52
- className: "flex-1 overflow-y-auto p-6",
53
- children: /* @__PURE__ */ d("div", {
54
- className: "mx-auto max-w-6xl space-y-6",
55
- children: [
56
- /* @__PURE__ */ u(g, { children: "Follow each product you've submitted through the review pipeline — pending, approved or rejected — so you always know what's live and what still needs attention. If a submission is rejected, open it to read the moderator's reason and resubmit a fixed version." }),
57
- /* @__PURE__ */ d("div", {
58
- className: "grid gap-4 sm:grid-cols-3",
59
- children: [
60
- /* @__PURE__ */ d(m, {
61
- treatment: "metric",
62
- className: "p-4",
63
- children: [/* @__PURE__ */ d("div", {
64
- className: "inline-flex items-center gap-2 text-xs uppercase tracking-wide text-text-muted",
65
- children: [
66
- /* @__PURE__ */ u(s, { className: "size-4" }),
67
- " ",
68
- D("store.status.pending", { defaultValue: "Pending" })
69
- ]
70
- }), /* @__PURE__ */ u("p", {
71
- className: "mt-2 text-2xl font-bold tabular-nums text-text-primary",
72
- children: k.pending
73
- })]
74
- }),
75
- /* @__PURE__ */ d(m, {
76
- treatment: "metric",
77
- className: "p-4",
78
- children: [/* @__PURE__ */ d("div", {
79
- className: "inline-flex items-center gap-2 text-xs uppercase tracking-wide text-text-muted",
80
- children: [
81
- /* @__PURE__ */ u(o, { className: "size-4" }),
82
- " ",
83
- D("store.status.approved", { defaultValue: "Approved" })
84
- ]
85
- }), /* @__PURE__ */ u("p", {
86
- className: "mt-2 text-2xl font-bold tabular-nums text-text-primary",
87
- children: k.approved
88
- })]
89
- }),
90
- /* @__PURE__ */ d(m, {
91
- treatment: "metric",
92
- className: "p-4",
93
- children: [/* @__PURE__ */ d("div", {
94
- className: "inline-flex items-center gap-2 text-xs uppercase tracking-wide text-text-muted",
95
- children: [
96
- /* @__PURE__ */ u(l, { className: "size-4" }),
97
- " ",
98
- D("store.status.rejected", { defaultValue: "Rejected" })
99
- ]
100
- }), /* @__PURE__ */ u("p", {
101
- className: "mt-2 text-2xl font-bold tabular-nums text-text-primary",
102
- children: k.rejected
103
- })]
104
- })
105
- ]
106
- }),
107
- /* @__PURE__ */ d(p, { children: [/* @__PURE__ */ d("div", {
108
- className: "mb-4 flex items-center justify-between",
109
- children: [/* @__PURE__ */ u("h2", {
110
- className: "text-lg font-semibold text-text-primary",
111
- children: D("pages.publisherSubmissions.timeline", { defaultValue: "Submission Timeline" })
112
- }), /* @__PURE__ */ u("button", {
113
- type: "button",
114
- onClick: () => v(`${y}/publisher/submit`),
115
- className: "cursor-pointer rounded-lg bg-action-primary-bg px-3 py-1.5 text-sm font-semibold text-action-primary-text",
116
- children: D("pages.publisherSubmissions.newSubmission", { defaultValue: "New Submission" })
117
- })]
118
- }), C ? /* @__PURE__ */ u("p", {
119
- role: "status",
120
- className: "text-sm text-text-muted",
121
- children: "Loading submissions…"
122
- }) : w ? /* @__PURE__ */ d("div", {
123
- role: "alert",
124
- className: "space-y-2",
125
- children: [/* @__PURE__ */ u("p", {
126
- className: "text-sm text-status-error-text",
127
- children: D("pages.publisherSubmissions.failedToLoad", { defaultValue: "Failed to load submissions." })
128
- }), /* @__PURE__ */ u("button", {
129
- type: "button",
130
- onClick: () => T(),
131
- className: "cursor-pointer rounded-lg bg-action-primary-bg px-3 py-1.5 text-xs font-semibold text-action-primary-text",
132
- children: "Retry"
133
- })]
134
- }) : x.length === 0 ? /* @__PURE__ */ u(h, {
135
- illustration: "empty-data",
136
- title: D("pages.publisherSubmissions.emptyTitle", { defaultValue: "No submissions found yet." }),
137
- description: D("pages.publisherSubmissions.emptyDescription", { defaultValue: "Submit a product to start tracking it through review here." }),
138
- action: /* @__PURE__ */ u("button", {
139
- type: "button",
140
- onClick: () => v(`${y}/publisher/submit`),
141
- className: "cursor-pointer rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-semibold text-action-primary-text hover:opacity-90",
142
- children: D("pages.publisherSubmissions.newSubmission", { defaultValue: "New Submission" })
143
- })
144
- }) : /* @__PURE__ */ d("ul", {
145
- className: "space-y-3",
146
- children: [x.map((e) => /* @__PURE__ */ d("li", {
147
- className: "flex items-center justify-between rounded-lg border border-border-seam bg-bg-surface p-3 transition-[box-shadow,border-color] hover:border-border-strong hover:shadow-[var(--shadow-pop)]",
148
- children: [/* @__PURE__ */ d("button", {
149
- type: "button",
150
- onClick: () => v(`${y}/marketplace/product/${e.id}`),
151
- className: "flex flex-1 cursor-pointer items-center justify-between text-left",
152
- children: [/* @__PURE__ */ d("div", { children: [/* @__PURE__ */ u("p", {
153
- className: "font-medium text-text-primary",
154
- children: e.name
155
- }), /* @__PURE__ */ d("p", {
156
- className: "text-xs text-text-muted",
157
- children: ["Reviews: ", e.reviewCount]
158
- })] }), /* @__PURE__ */ u("span", {
159
- className: `rounded-full px-2.5 py-1 text-xs font-semibold ${_(e.status)}`,
160
- children: e.status
161
- })]
162
- }), /* @__PURE__ */ d("button", {
163
- type: "button",
164
- onClick: () => v(`${y}/publisher/product/${e.id}/reviews`),
165
- className: "ml-3 inline-flex cursor-pointer items-center gap-1 rounded-md px-2 py-1 text-xs font-medium text-text-link hover:bg-bg-sunken hover:underline",
166
- title: "View reviews",
167
- children: [/* @__PURE__ */ u(c, { className: "size-3.5" }), "Reviews"]
168
- })]
169
- }, e.id)), S && /* @__PURE__ */ u("li", {
170
- className: "flex justify-center pt-4 list-none",
171
- children: /* @__PURE__ */ u("button", {
172
- type: "button",
173
- onClick: E,
174
- disabled: C,
175
- className: "rounded-lg border border-border-default px-6 py-2.5 text-sm font-medium text-text-primary hover:bg-bg-subtle disabled:opacity-50",
176
- children: C ? "Loading…" : "Load more"
177
- })
178
- })]
179
- })] })
180
- ]
181
- })
182
- })]
183
- });
184
- };
185
- //#endregion
186
- export { v as PublisherSubmissionsPage };
187
-
188
- //# sourceMappingURL=PublisherSubmissionsPage.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"PublisherSubmissionsPage.js","names":[],"sources":["../../src/pages/PublisherSubmissionsPage.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { useMemo } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { ArrowLeft, Clock3, CheckCircle2, XCircle, MessageSquare } from 'lucide-react';\nimport { useStore } from '../providers/StoreProvider';\nimport { useMyPublishedProducts } from '../hooks/useStoreGraphQL';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n GlassCard,\n EmphasisPanel,\n PagePurpose,\n IllustratedEmptyState,\n} from '@burdenoff/fe-libs/ui';\nimport { useSubmissionStatusUpdatedSubscription } from '../generated/global-operations';\n\nconst statusClass = (status: string): string => {\n if (status === 'PUBLISHED' || status === 'APPROVED') {\n return 'bg-status-success-bg-subtle text-status-success-text';\n }\n if (status === 'REJECTED' || status === 'UNLISTED') {\n return 'bg-status-error-bg-subtle text-status-error-text';\n }\n if (status === 'PENDING' || status === 'SUBMITTED' || status === 'UNDER_REVIEW') {\n return 'bg-status-warning-bg-subtle text-status-warning-text';\n }\n return 'bg-bg-sunken text-text-muted';\n};\n\nexport const PublisherSubmissionsPage: FC = () => {\n const navigate = useNavigate();\n const { basePath, currentUser } = useStore();\n const { products, hasMore, loading, error, refetch, loadMore } = useMyPublishedProducts();\n const { t } = useI18n();\n\n const publisherId = currentUser?.id;\n useSubmissionStatusUpdatedSubscription({\n variables: { publisherId: publisherId ?? '' },\n skip: !publisherId,\n onData: () => {\n void refetch();\n },\n onError: (err) => {\n console.warn('SubmissionStatusUpdated subscription error:', err.message);\n },\n });\n\n const grouped = useMemo(() => {\n const approved = products.filter(\n (p) => p.status === 'PUBLISHED' || p.status === 'APPROVED'\n ).length;\n const rejected = products.filter(\n (p) => p.status === 'REJECTED' || p.status === 'UNLISTED'\n ).length;\n const pending = products.length - approved - rejected;\n return { approved, rejected, pending };\n }, [products]);\n\n return (\n <div className=\"flex h-full flex-col\">\n <header className=\"border-b border-border-seam bg-bg-surface px-6 py-4\">\n <div className=\"mx-auto flex max-w-6xl items-center gap-3\">\n <button\n type=\"button\"\n onClick={() => navigate(-1)}\n aria-label=\"Go back\"\n className=\"cursor-pointer rounded-lg p-2 text-text-muted hover:bg-bg-sunken hover:text-text-primary\"\n >\n <ArrowLeft className=\"size-5\" />\n </button>\n <div>\n <h1 className=\"text-2xl font-bold text-text-primary\">\n {t('pages.publisherSubmissions.title', { defaultValue: 'Submissions' })}\n </h1>\n <p className=\"text-sm text-text-muted\">\n {t('pages.publisherSubmissions.subtitle', {\n defaultValue: 'Track approval status for your store products',\n })}\n </p>\n </div>\n </div>\n </header>\n\n <main className=\"flex-1 overflow-y-auto p-6\">\n <div className=\"mx-auto max-w-6xl space-y-6\">\n <PagePurpose>\n Follow each product you've submitted through the review pipeline — pending, approved or\n rejected — so you always know what's live and what still needs attention. If a submission\n is rejected, open it to read the moderator's reason and resubmit a fixed version.\n </PagePurpose>\n <div className=\"grid gap-4 sm:grid-cols-3\">\n <GlassCard treatment=\"metric\" className=\"p-4\">\n <div className=\"inline-flex items-center gap-2 text-xs uppercase tracking-wide text-text-muted\">\n <Clock3 className=\"size-4\" />{' '}\n {t('store.status.pending', { defaultValue: 'Pending' })}\n </div>\n <p className=\"mt-2 text-2xl font-bold tabular-nums text-text-primary\">\n {grouped.pending}\n </p>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"p-4\">\n <div className=\"inline-flex items-center gap-2 text-xs uppercase tracking-wide text-text-muted\">\n <CheckCircle2 className=\"size-4\" />{' '}\n {t('store.status.approved', { defaultValue: 'Approved' })}\n </div>\n <p className=\"mt-2 text-2xl font-bold tabular-nums text-text-primary\">\n {grouped.approved}\n </p>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"p-4\">\n <div className=\"inline-flex items-center gap-2 text-xs uppercase tracking-wide text-text-muted\">\n <XCircle className=\"size-4\" />{' '}\n {t('store.status.rejected', { defaultValue: 'Rejected' })}\n </div>\n <p className=\"mt-2 text-2xl font-bold tabular-nums text-text-primary\">\n {grouped.rejected}\n </p>\n </GlassCard>\n </div>\n\n <EmphasisPanel>\n <div className=\"mb-4 flex items-center justify-between\">\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {t('pages.publisherSubmissions.timeline', { defaultValue: 'Submission Timeline' })}\n </h2>\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/publisher/submit`)}\n className=\"cursor-pointer rounded-lg bg-action-primary-bg px-3 py-1.5 text-sm font-semibold text-action-primary-text\"\n >\n {t('pages.publisherSubmissions.newSubmission', { defaultValue: 'New Submission' })}\n </button>\n </div>\n\n {loading ? (\n <p role=\"status\" className=\"text-sm text-text-muted\">\n Loading submissions…\n </p>\n ) : error ? (\n <div role=\"alert\" className=\"space-y-2\">\n <p className=\"text-sm text-status-error-text\">\n {t('pages.publisherSubmissions.failedToLoad', {\n defaultValue: 'Failed to load submissions.',\n })}\n </p>\n <button\n type=\"button\"\n onClick={() => refetch()}\n className=\"cursor-pointer rounded-lg bg-action-primary-bg px-3 py-1.5 text-xs font-semibold text-action-primary-text\"\n >\n Retry\n </button>\n </div>\n ) : products.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title={t('pages.publisherSubmissions.emptyTitle', {\n defaultValue: 'No submissions found yet.',\n })}\n description={t('pages.publisherSubmissions.emptyDescription', {\n defaultValue:\n 'Submit a product to start tracking it through review here.',\n })}\n action={\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/publisher/submit`)}\n className=\"cursor-pointer rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-semibold text-action-primary-text hover:opacity-90\"\n >\n {t('pages.publisherSubmissions.newSubmission', {\n defaultValue: 'New Submission',\n })}\n </button>\n }\n />\n ) : (\n <ul className=\"space-y-3\">\n {products.map((product) => (\n <li\n key={product.id}\n className=\"flex items-center justify-between rounded-lg border border-border-seam bg-bg-surface p-3 transition-[box-shadow,border-color] hover:border-border-strong hover:shadow-[var(--shadow-pop)]\"\n >\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/marketplace/product/${product.id}`)}\n className=\"flex flex-1 cursor-pointer items-center justify-between text-left\"\n >\n <div>\n <p className=\"font-medium text-text-primary\">{product.name}</p>\n <p className=\"text-xs text-text-muted\">Reviews: {product.reviewCount}</p>\n </div>\n <span\n className={`rounded-full px-2.5 py-1 text-xs font-semibold ${statusClass(product.status)}`}\n >\n {product.status}\n </span>\n </button>\n <button\n type=\"button\"\n onClick={() =>\n navigate(`${basePath}/publisher/product/${product.id}/reviews`)\n }\n className=\"ml-3 inline-flex cursor-pointer items-center gap-1 rounded-md px-2 py-1 text-xs font-medium text-text-link hover:bg-bg-sunken hover:underline\"\n title=\"View reviews\"\n >\n <MessageSquare className=\"size-3.5\" />\n Reviews\n </button>\n </li>\n ))}\n {hasMore && (\n <li className=\"flex justify-center pt-4 list-none\">\n <button\n type=\"button\"\n onClick={loadMore}\n disabled={loading}\n className=\"rounded-lg border border-border-default px-6 py-2.5 text-sm font-medium text-text-primary hover:bg-bg-subtle disabled:opacity-50\"\n >\n {loading ? 'Loading\\u2026' : 'Load more'}\n </button>\n </li>\n )}\n </ul>\n )}\n </EmphasisPanel>\n </div>\n </main>\n </div>\n );\n};\n"],"mappings":"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"}