@aglyn/plugins-marketplace 1.11.0 → 1.12.0

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 (81) hide show
  1. package/package.json +14 -14
  2. package/src/lib/components/listing-content.component.js +78 -36
  3. package/src/lib/components/listing-content.component.js.map +1 -1
  4. package/src/lib/components/listing-detail-page.component.js +22 -9
  5. package/src/lib/components/listing-detail-page.component.js.map +1 -1
  6. package/src/lib/components/listing-review-status.component.d.ts +8 -0
  7. package/src/lib/components/listing-review-status.component.js +23 -3
  8. package/src/lib/components/listing-review-status.component.js.map +1 -1
  9. package/src/lib/components/listing-verification-request.component.d.ts +8 -0
  10. package/src/lib/components/listing-verification-request.component.js +12 -5
  11. package/src/lib/components/listing-verification-request.component.js.map +1 -1
  12. package/src/lib/components/marketplace-hub.component.js +2 -1
  13. package/src/lib/components/marketplace-hub.component.js.map +1 -1
  14. package/src/lib/components/org-seller-panel.component.d.ts +10 -0
  15. package/src/lib/components/org-seller-panel.component.js +26 -4
  16. package/src/lib/components/org-seller-panel.component.js.map +1 -1
  17. package/src/lib/components/starter-picker-shelf.component.js +13 -8
  18. package/src/lib/components/starter-picker-shelf.component.js.map +1 -1
  19. package/src/lib/declarations.d.ts +2 -1
  20. package/src/lib/declarations.js +5 -1
  21. package/src/lib/declarations.js.map +1 -1
  22. package/src/lib/model/marketplace-publisher-permissions.d.ts +26 -0
  23. package/src/lib/model/marketplace-publisher-permissions.js +64 -0
  24. package/src/lib/model/marketplace-publisher-permissions.js.map +1 -0
  25. package/src/lib/model/marketplace.js +2 -1
  26. package/src/lib/model/marketplace.js.map +1 -1
  27. package/src/lib/model/own-listing.d.ts +52 -0
  28. package/src/lib/model/own-listing.js +72 -0
  29. package/src/lib/model/own-listing.js.map +1 -0
  30. package/src/lib/model/starter-query.js +2 -0
  31. package/src/lib/model/starter-query.js.map +1 -1
  32. package/src/lib/server/connect.js +11 -5
  33. package/src/lib/server/connect.js.map +1 -1
  34. package/src/lib/server/install-dataset-schema.js +10 -2
  35. package/src/lib/server/install-dataset-schema.js.map +1 -1
  36. package/src/lib/server/install-email-starter.js +8 -2
  37. package/src/lib/server/install-email-starter.js.map +1 -1
  38. package/src/lib/server/install-email-template.js +8 -2
  39. package/src/lib/server/install-email-template.js.map +1 -1
  40. package/src/lib/server/install-layout.js +8 -2
  41. package/src/lib/server/install-layout.js.map +1 -1
  42. package/src/lib/server/install-plugin.js +24 -20
  43. package/src/lib/server/install-plugin.js.map +1 -1
  44. package/src/lib/server/install-template.js +8 -5
  45. package/src/lib/server/install-template.js.map +1 -1
  46. package/src/lib/server/install-theme.js +8 -2
  47. package/src/lib/server/install-theme.js.map +1 -1
  48. package/src/lib/server/install.js +10 -5
  49. package/src/lib/server/install.js.map +1 -1
  50. package/src/lib/server/listing-versions.js +24 -9
  51. package/src/lib/server/listing-versions.js.map +1 -1
  52. package/src/lib/server/own-listing.d.ts +46 -0
  53. package/src/lib/server/own-listing.js +52 -0
  54. package/src/lib/server/own-listing.js.map +1 -0
  55. package/src/lib/server/preview-image.d.ts +1 -1
  56. package/src/lib/server/preview-image.js +9 -8
  57. package/src/lib/server/preview-image.js.map +1 -1
  58. package/src/lib/server/publish-plugin.js +17 -19
  59. package/src/lib/server/publish-plugin.js.map +1 -1
  60. package/src/lib/server/publisher-permissions.d.ts +63 -0
  61. package/src/lib/server/publisher-permissions.js +51 -0
  62. package/src/lib/server/publisher-permissions.js.map +1 -0
  63. package/src/lib/server/publisher-profile-save.d.ts +4 -2
  64. package/src/lib/server/publisher-profile-save.js +12 -5
  65. package/src/lib/server/publisher-profile-save.js.map +1 -1
  66. package/src/lib/server/publisher-profile.d.ts +18 -6
  67. package/src/lib/server/publisher-profile.js +19 -8
  68. package/src/lib/server/publisher-profile.js.map +1 -1
  69. package/src/lib/server/reviews.js +6 -5
  70. package/src/lib/server/reviews.js.map +1 -1
  71. package/src/lib/server/sale-risk.d.ts +0 -6
  72. package/src/lib/server/sale-risk.js +0 -9
  73. package/src/lib/server/sale-risk.js.map +1 -1
  74. package/src/lib/server/sale.js +10 -9
  75. package/src/lib/server/sale.js.map +1 -1
  76. package/src/lib/server/site-starter-source.js +43 -17
  77. package/src/lib/server/site-starter-source.js.map +1 -1
  78. package/src/lib/server/update-artifact.js +11 -4
  79. package/src/lib/server/update-artifact.js.map +1 -1
  80. package/src/lib/server/verification-request.js +23 -7
  81. package/src/lib/server/verification-request.js.map +1 -1
@@ -11,6 +11,16 @@ export interface OrgSellerPanelProps {
11
11
  * table, which a plugin may not import.
12
12
  */
13
13
  basePath: string;
14
+ /**
15
+ * The viewer's resolved permissions, from the shell (AGL-4047). Saving the
16
+ * profile asks "Edit the publisher profile", a listing's edit, visibility
17
+ * and unpublish actions ask "Manage published listings", and setting up
18
+ * payouts asks "Manage marketplace payouts", as their routes (and, for the
19
+ * first two, the rules) do; a control the viewer may not use stays on
20
+ * screen, disabled, with the permission named. An absent key reads as
21
+ * allowed, as the map reads while it loads: the route still decides.
22
+ */
23
+ permissions?: Record<string, boolean | undefined>;
14
24
  }
15
25
  /**
16
26
  * Seller area (AGL-44/798/801): the org's marketplace identity and its
@@ -33,6 +33,7 @@ import { PUBLISHER_AGREEMENT_TITLE, PUBLISHER_AGREEMENT_VERSION, publisherAgreem
33
33
  reason these two were left out of the AGL-2319 sweep instead of swept wrong.
34
34
  */ import { PLATFORM_BRAND_LEGAL_NAME } from "@aglyn/aglyn/app-utils/platform-brand";
35
35
  import { LISTING_LOGO_HINT } from "../constants/listing-media.js";
36
+ import { MARKETPLACE_MANAGE_LISTINGS_PERMISSION, MARKETPLACE_PAYOUTS_PERMISSION, MARKETPLACE_PUBLISHER_PROFILE_PERMISSION, marketplacePublisherPermissionRefusal } from "../model/marketplace-publisher-permissions.js";
36
37
  import { useRouter } from "next/navigation";
37
38
  import { collection, doc, query, where } from "firebase/firestore";
38
39
  import { useCallback, useEffect, useState } from "react";
@@ -60,7 +61,10 @@ const HANDLE_PATTERN = /^[a-z0-9][a-z0-9-]{2,29}$/;
60
61
  */ export function OrgSellerPanel(props) {
61
62
  var _ref, _ref1, _ref2, _profile_lastPayoutFailureCents, _profile_lastPayoutFailureReason;
62
63
  var _profile_publisherAgreement, _rowMenu_listing, _rowMenu_listing1, _rowMenu_listing2, _rowMenu_listing3, _rowMenu_listing4, _rowMenu_listing5, _rowMenu_listing6;
63
- const { orgId, section, basePath } = props;
64
+ const { orgId, section, basePath, permissions } = props;
65
+ const canEditProfile = (permissions == null ? void 0 : permissions[MARKETPLACE_PUBLISHER_PROFILE_PERMISSION]) !== false;
66
+ const canManageListings = (permissions == null ? void 0 : permissions[MARKETPLACE_MANAGE_LISTINGS_PERMISSION]) !== false;
67
+ const canManagePayouts = (permissions == null ? void 0 : permissions[MARKETPLACE_PAYOUTS_PERMISSION]) !== false;
64
68
  const router = useRouter();
65
69
  const firestore = useFirestore();
66
70
  const { data: user } = useUser();
@@ -573,14 +577,19 @@ const HANDLE_PATTERN = /^[a-z0-9][a-z0-9-]{2,29}$/;
573
577
  /*#__PURE__*/ _jsx(PublisherAgreementCheckbox, {
574
578
  checked: profileAgreement.agreed,
575
579
  onChange: profileAgreement.setAgreed,
576
- disabled: profileBusy
580
+ disabled: profileBusy || !canEditProfile
577
581
  }),
578
582
  /*#__PURE__*/ _jsx(Button, {
579
583
  variant: "contained",
580
584
  color: "primary",
581
- disabled: profileBusy || !validHandle || !displayName.trim() || !profileAgreement.agreed,
585
+ disabled: profileBusy || !canEditProfile || !validHandle || !displayName.trim() || !profileAgreement.agreed,
582
586
  onClick: handleSave,
583
587
  children: profileBusy ? 'Saving…' : 'Save profile'
588
+ }),
589
+ canEditProfile ? null : /*#__PURE__*/ _jsx(Typography, {
590
+ variant: "caption",
591
+ color: "text.secondary",
592
+ children: marketplacePublisherPermissionRefusal(MARKETPLACE_PUBLISHER_PROFILE_PERMISSION)
584
593
  })
585
594
  ]
586
595
  })
@@ -631,6 +640,11 @@ const HANDLE_PATTERN = /^[a-z0-9][a-z0-9-]{2,29}$/;
631
640
  }) : /*#__PURE__*/ _jsxs(Stack, {
632
641
  spacing: 1,
633
642
  children: [
643
+ canManageListings ? null : /*#__PURE__*/ _jsx(Typography, {
644
+ variant: "caption",
645
+ color: "text.secondary",
646
+ children: marketplacePublisherPermissionRefusal(MARKETPLACE_MANAGE_LISTINGS_PERMISSION)
647
+ }),
634
648
  (listings != null ? listings : []).some((listing)=>listing.visibility === 'private') ? /*#__PURE__*/ _jsx(Typography, {
635
649
  variant: "caption",
636
650
  color: "text.secondary",
@@ -732,6 +746,7 @@ const HANDLE_PATTERN = /^[a-z0-9][a-z0-9-]{2,29}$/;
732
746
  children: 'Publish new version…'
733
747
  }) : null,
734
748
  /*#__PURE__*/ _jsx(MenuItem, {
749
+ disabled: !canManageListings,
735
750
  onClick: ()=>{
736
751
  var _ref;
737
752
  setEditListing((_ref = rowMenu == null ? void 0 : rowMenu.listing) != null ? _ref : null);
@@ -740,6 +755,7 @@ const HANDLE_PATTERN = /^[a-z0-9][a-z0-9-]{2,29}$/;
740
755
  children: 'Edit listing'
741
756
  }),
742
757
  ((_ref2 = rowMenu == null ? void 0 : (_rowMenu_listing2 = rowMenu.listing) == null ? void 0 : _rowMenu_listing2.artifactType) != null ? _ref2 : rowMenu == null ? void 0 : (_rowMenu_listing3 = rowMenu.listing) == null ? void 0 : _rowMenu_listing3.type) === 'plugin' ? /*#__PURE__*/ _jsx(MenuItem, {
758
+ disabled: !canManageListings,
743
759
  onClick: ()=>{
744
760
  const listing = rowMenu == null ? void 0 : rowMenu.listing;
745
761
  closeRowMenu();
@@ -752,6 +768,7 @@ const HANDLE_PATTERN = /^[a-z0-9][a-z0-9-]{2,29}$/;
752
768
  }) : null,
753
769
  /*#__PURE__*/ _jsx(Divider, {}),
754
770
  /*#__PURE__*/ _jsx(MenuItem, {
771
+ disabled: !canManageListings,
755
772
  sx: {
756
773
  color: (rowMenu == null ? void 0 : (_rowMenu_listing5 = rowMenu.listing) == null ? void 0 : _rowMenu_listing5.deletedAt) ? undefined : 'error.main'
757
774
  },
@@ -829,10 +846,15 @@ const HANDLE_PATTERN = /^[a-z0-9][a-z0-9-]{2,29}$/;
829
846
  /*#__PURE__*/ _jsx(Button, {
830
847
  variant: chargesEnabled ? 'outlined' : 'contained',
831
848
  color: "primary",
832
- disabled: payoutsBusy,
849
+ disabled: payoutsBusy || !canManagePayouts,
833
850
  onClick: handlePayouts,
834
851
  children: payoutsBusy ? 'Opening Stripe…' : readiness === 'ready' ? 'Payouts enabled — recheck status' : readiness === 'blocked' ? 'Finish payout setup in Stripe' : readiness === 'unverified' ? 'Reconnect Stripe to verify' : readiness === 'unknown' ? 'Recheck payout status' : 'Set up payouts'
835
852
  }),
853
+ canManagePayouts ? null : /*#__PURE__*/ _jsx(Typography, {
854
+ variant: "caption",
855
+ color: "text.secondary",
856
+ children: marketplacePublisherPermissionRefusal(MARKETPLACE_PAYOUTS_PERMISSION)
857
+ }),
836
858
  dashboardUrl ? /*#__PURE__*/ _jsx(Button, {
837
859
  variant: "text",
838
860
  color: "primary",
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/marketplace/src/lib/components/org-seller-panel.component.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport { trackEvent } from '@aglyn/aglyn/app-utils/analytics-events'\nimport { mdiDotsVertical } from '@aglyn/shared-data-mdi'\nimport { AppLink, CardDisplay, MdiIcon } from '@aglyn/shared-ui-jsx'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport {\n Alert,\n Avatar,\n Button,\n Chip,\n Divider,\n IconButton,\n Menu,\n MenuItem,\n Stack,\n TextField,\n Typography,\n} from '@mui/material'\nimport {\n PUBLISHER_AGREEMENT_TITLE,\n PUBLISHER_AGREEMENT_VERSION,\n publisherAgreementPresentation,\n publisherAgreementState,\n type PublisherAgreementConsent,\n} from '../model/publisher-agreement'\n/*\n THE LEGAL NAME, not `useBranding().branding.productName` (AGL-2351).\n\n Every other customer-facing string in the console reads the org's resolved\n product name, and doing that here would be false: the two sentences below say\n which entity holds a sales-tax registration and remits against it. A\n white-label agency holds neither. The value has to name the company that\n actually stands behind the money — the same reasoning that keeps\n `tx-return-webfile.ts` naming the entity rather than the product, and the\n reason these two were left out of the AGL-2319 sweep instead of swept wrong.\n*/\nimport { PLATFORM_BRAND_LEGAL_NAME } from '@aglyn/aglyn/app-utils/platform-brand'\nimport { LISTING_LOGO_HINT } from '../constants/listing-media'\nimport { useRouter } from 'next/navigation'\nimport { collection, doc, query, where } from 'firebase/firestore'\nimport { type ReactElement, useCallback, useEffect, useState } from 'react'\nimport { useFirestore, useUser } from '@aglyn/tenant-feature-instance'\nimport { authorizedFetch } from '@aglyn/shared-util-http/authorized-token'\nimport { pluginDocsHelp, useMediaPicker } from '@aglyn/aglyn'\nimport { useFirestoreCollection } from '@aglyn/tenant-feature-instance'\nimport { useFirestoreDoc } from '@aglyn/tenant-feature-instance'\nimport EditListingDialog from './edit-listing-dialog.component'\nimport {\n PublisherAgreementCheckbox,\n usePublisherAgreementConsent,\n} from './publisher-agreement-checkbox.component'\nimport PublisherAgreementConfirmDialog from './publisher-agreement-confirm-dialog.component'\nimport PublisherAgreementSummary from './publisher-agreement-summary.component'\nimport { listingPath, publishPluginPath } from '../model/marketplace-paths'\nimport { payoutReadiness } from '../model/payout-readiness'\nimport {\n summarizeSellerLedger,\n type SellerLedgerSale,\n} from '../model/seller-ledger-totals'\n\nconst HANDLE_PATTERN = /^[a-z0-9][a-z0-9-]{2,29}$/\n\nexport type OrgSellerSection = 'profile' | 'listings' | 'payouts' | 'sales'\n\nexport interface OrgSellerPanelProps {\n orgId: string\n /** Which seller card to render — one per Marketplace › seller tab. */\n section: OrgSellerSection\n /**\n * Where the marketplace hub is mounted under this organization, from the\n * shell (AGL-3080) — the panel's links to a listing and to the publish\n * form hang beneath it. It replaced an org slug and the console's route\n * table, which a plugin may not import.\n */\n basePath: string\n}\n\n/**\n * Seller area (AGL-44/798/801): the org's marketplace identity and its\n * published listings, folded out of the retired `/[orgSlug]/marketplace` page.\n * Each section (profile, listings, payouts, sales) is its own Marketplace\n * ROUTE (AGL-801/693), so this renders exactly one card per the `section`\n * prop. The shared Firestore hooks run regardless of which section is asked\n * for — Firebase dedupes identical listeners, and only the section the reader\n * navigated to is mounted at all, so the others never subscribe.\n */\nexport function OrgSellerPanel(props: OrgSellerPanelProps) {\n const { orgId, section, basePath } = props\n const router = useRouter()\n const firestore = useFirestore()\n const { data: user } = useUser()\n const { enqueueSnackbar } = useSnackbar()\n /** Bumped by Retry to re-subscribe the publisher profile (AGL-1380). */\n const [profileRetryNonce, setProfileRetryNonce] = useState(0)\n const { data: profile, status: profileStatus } = useFirestoreDoc<any>(\n // The org's marketplace identity (AGL-652), not the personal one. Held\n // at null rather than addressed as `publisherProfiles/-none-`: that\n // sentinel issued a guaranteed-denied read, and a denial now lands in\n // `status: 'error'`, which means something.\n () => (orgId ? doc(firestore, 'publisherProfiles', orgId) : null),\n [firestore, orgId, profileRetryNonce],\n { idField: '$id' },\n )\n /**\n * Three outcomes, not two (AGL-1380). An absent publisher profile is the\n * value BEFORE an answer as much as it is the value of a publisher who\n * never connected Stripe, so reading payout state off `stripeChargesEnabled`\n * alone told a publisher already taking payouts to \"Connect a Stripe\n * account\" and offered them the setup button that starts onboarding again.\n */\n const payoutsState: 'pending' | 'error' | 'loaded' =\n !orgId || profileStatus === 'loading'\n ? 'pending'\n : profileStatus === 'error'\n ? 'error'\n : 'loaded'\n /**\n * TWO questions, not one (AGL-1997). This card said \"Payouts are enabled\"\n * off `stripeChargesEnabled` — whether Stripe will let the account take\n * MONEY — and never read `stripePayoutsEnabled`, whether the money can\n * LEAVE. The decision itself lives in `payoutReadiness` so each of its six\n * outcomes can be asserted without mounting this tree.\n */\n const readiness = payoutReadiness({\n state: payoutsState,\n chargesEnabled: profile?.stripeChargesEnabled,\n payoutsEnabled: profile?.stripePayoutsEnabled,\n accountLivemode: profile?.stripeAccountLivemode,\n })\n /** Stripe will let this account take money — four of the seven outcomes. */\n const chargesEnabled =\n readiness === 'ready' ||\n readiness === 'blocked' ||\n readiness === 'unknown' ||\n readiness === 'unverified'\n // Both held at null while the org is unknown, like the profile above\n // (AGL-1440): AGL-1380 repaired the profile ref and left these two\n // `where`-clause siblings on the sentinel. The purchases query is the one\n // that matters — `marketplacePurchases` is buyer/seller-gated, and a\n // rules-shaped LIST is evaluated against the QUERY, so the sentinel was\n // denied wholesale and retried on the refusal cadence. The listings query\n // is public and merely wasted the round trip.\n const { data: listings } = useFirestoreCollection<any>(\n () =>\n orgId\n ? query(\n collection(firestore, 'marketplaceListings'),\n // Listings are org-owned (AGL-652): `profileId` is the org id,\n // not a uid — filtering by uid left this list permanently empty\n // (AGL-781).\n where('profileId', '==', orgId),\n )\n : null,\n [firestore, orgId],\n { idField: '$id' },\n )\n // Seller ledger (AGL-46): purchase records written by the Stripe webhook.\n const { data: sales } = useFirestoreCollection<any>(\n () =>\n orgId\n ? query(\n collection(firestore, 'marketplacePurchases'),\n // Sales belong to the ORG that published (AGL-652).\n where('sellerOrgId', '==', orgId),\n )\n : null,\n [firestore, orgId],\n { idField: '$id' },\n )\n // What the publisher was actually paid (AGL-2158) — see\n // `summarizeSellerLedger`, where the arithmetic and the reasoning live. This\n // card used to render `amountCents − feeCents` as \"net\", which is\n // `pretax + tax − fee`: the payout PLUS sales tax that was never the\n // publisher's, summed over refunded sales as well as live ones.\n const totals = summarizeSellerLedger(sales as SellerLedgerSale[] | undefined)\n\n const [payoutsBusy, setPayoutsBusy] = useState(false)\n /**\n * A one-time Stripe Express dashboard link from the connect route. Not\n * persisted: login links are single-use and short-lived, so a stored one is\n * a button that fails the second time it is pressed.\n */\n const [dashboardUrl, setDashboardUrl] = useState<string | null>(null)\n const handlePayouts = useCallback(async () => {\n setPayoutsBusy(true)\n try {\n const response = await authorizedFetch(user, '/api/marketplace/connect', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n // The acting org from the URL (AGL-861) — never let the server guess\n // which of the user's orgs is being set up for payouts.\n body: JSON.stringify({ orgId }),\n })\n const payload = await response.json()\n if (response.status === 501) {\n return void enqueueSnackbar(\n 'Payouts are not configured on this deployment',\n { variant: 'info', persist: false },\n )\n }\n if (!response.ok) {\n return void enqueueSnackbar(payload?.error ?? 'Payout setup failed', {\n variant: 'error',\n allowDuplicate: true,\n })\n }\n if (payload.chargesEnabled) {\n // Publisher-payout half of the same activation metric (AGL-1561),\n // gated on the transition for the same reason as the commerce card:\n // the connect handler is re-entrant and reports `true` on every\n // revisit. `chargesEnabled` is the pre-request state — the metric is\n // about CONNECTING (AGL-1997 split the two flags; payout readiness\n // can arrive days later and is not a second activation).\n if (!chargesEnabled) trackEvent('stripe_connected', {})\n // A WARNING THAT NAMES A PROBLEM MUST OFFER THE FIX.\n //\n // \"Finish payout setup in Stripe\" is the label this button carries in\n // exactly this state, and it could not open Stripe: the route returned\n // here with a status and no link, and this branch answered before the\n // `payload.url` check below ever ran. An Express account has no\n // password and no direct login, so a link minted by the platform is\n // the publisher's only way in — without one their share accumulates in\n // an account that cannot release it and nothing says why.\n if (payload.payoutsEnabled === false && payload.url) {\n return void window.location.assign(payload.url)\n }\n // Payouts are flowing, so the route answers with the Express dashboard\n // instead: balance, payout schedule, and the reason a payout failed.\n // Held rather than followed — this click was a status check.\n if (\n payload.payoutsEnabled !== false &&\n typeof payload.dashboardUrl === 'string'\n ) {\n setDashboardUrl(payload.dashboardUrl)\n }\n // The same split the card renders (AGL-1997): the route answers both\n // flags, so the toast must not announce payouts off the charges one.\n return void enqueueSnackbar(\n payload.payoutsEnabled === false\n ? 'Connected — payouts are not released yet'\n : 'Payouts are enabled',\n {\n variant: payload.payoutsEnabled === false ? 'warning' : 'success',\n persist: false,\n },\n )\n }\n if (payload.url) window.location.assign(payload.url)\n } catch (error) {\n console.error(error)\n enqueueSnackbar('An error has occurred', {\n variant: 'error',\n allowDuplicate: true,\n })\n } finally {\n setPayoutsBusy(false)\n }\n }, [orgId, user, chargesEnabled, enqueueSnackbar])\n\n const [handle, setHandle] = useState('')\n const [displayName, setDisplayName] = useState('')\n const [bio, setBio] = useState('')\n // Logo, support contact and social links (AGL-1009). `avatarUrl` and\n // `website` existed server-side already — they just had no form input and\n // no rendering, so they were dead fields until now.\n const [avatarUrl, setAvatarUrl] = useState('')\n /*\n * The console's media library, opened through the picker context rather\n * than by mounting its dialog (AGL-3080): the library is coupled to the\n * org and the session, which a plugin has no way to reach, and the console\n * provides `pickMedia` around every plugin page for exactly this. The URL\n * comes back already resolved — CDN path over the raw download URL\n * (AGL-1215) — so the panel no longer resolves one itself.\n */\n const { pickMedia } = useMediaPicker()\n const chooseLogo = useCallback(async () => {\n const picked = await pickMedia?.({ kind: 'image' })\n if (picked?.url) setAvatarUrl(picked.url)\n }, [pickMedia])\n const [website, setWebsite] = useState('')\n const [supportEmail, setSupportEmail] = useState('')\n const [supportUrl, setSupportUrl] = useState('')\n const [githubUrl, setGithubUrl] = useState('')\n const [xUrl, setXUrl] = useState('')\n const [linkedinUrl, setLinkedinUrl] = useState('')\n useEffect(() => {\n setHandle(profile?.handle ?? '')\n setDisplayName(profile?.displayName ?? '')\n setBio(profile?.bio ?? '')\n setAvatarUrl(profile?.avatarUrl ?? '')\n setWebsite(profile?.website ?? '')\n setSupportEmail(profile?.supportEmail ?? '')\n setSupportUrl(profile?.supportUrl ?? '')\n setGithubUrl(profile?.githubUrl ?? '')\n setXUrl(profile?.xUrl ?? '')\n setLinkedinUrl(profile?.linkedinUrl ?? '')\n }, [\n profile?.handle,\n profile?.displayName,\n profile?.bio,\n profile?.avatarUrl,\n profile?.website,\n profile?.supportEmail,\n profile?.supportUrl,\n profile?.githubUrl,\n profile?.xUrl,\n profile?.linkedinUrl,\n ])\n\n const validHandle = HANDLE_PATTERN.test(handle)\n // The publisher agreement, agreed to on this save (AGL-4105).\n const profileAgreement = usePublisherAgreementConsent()\n const [profileBusy, setProfileBusy] = useState(false)\n\n const handleSave = useCallback(async () => {\n if (!orgId || !validHandle || !displayName.trim()) return\n if (!profileAgreement.consent) return\n setProfileBusy(true)\n try {\n // Server-owned (AGL-652): the handle must be claimed transactionally in\n // publisherHandles, which a client write cannot do — two orgs racing\n // for one handle would both succeed and one would silently lose its\n // marketplace URL. The rules reject a client handle write outright.\n const response = await authorizedFetch(\n user,\n '/api/marketplace/publisher-profile',\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n orgId,\n handle,\n displayName: displayName.trim(),\n bio: bio.trim(),\n // AGL-1009: validated server-side (https-only, fixed social\n // hosts) — an empty string explicitly clears the stored field.\n avatarUrl: avatarUrl.trim(),\n website: website.trim(),\n supportEmail: supportEmail.trim(),\n supportUrl: supportUrl.trim(),\n githubUrl: githubUrl.trim(),\n xUrl: xUrl.trim(),\n linkedinUrl: linkedinUrl.trim(),\n agreement: profileAgreement.consent,\n }),\n },\n )\n const payload = await response.json().catch(() => null)\n if (!response.ok) {\n return enqueueSnackbar(payload?.error ?? 'Could not save the profile', {\n variant: 'warning',\n persist: false,\n })\n }\n enqueueSnackbar('Profile saved', { variant: 'success', persist: false })\n // Each save is its own agreement: the next one ticks the box again.\n profileAgreement.reset()\n } catch (error) {\n console.error(error)\n enqueueSnackbar('An error has occurred', {\n variant: 'error',\n allowDuplicate: true,\n })\n } finally {\n setProfileBusy(false)\n }\n }, [\n orgId,\n validHandle,\n handle,\n displayName,\n bio,\n avatarUrl,\n website,\n supportEmail,\n supportUrl,\n githubUrl,\n xUrl,\n linkedinUrl,\n profileAgreement,\n user,\n enqueueSnackbar,\n ])\n\n // The publisher agreement (AGL-1077). `none` and `outdated` get different\n // copy on purpose: \"you never agreed\" and \"the terms moved\" are different\n // situations, and one message for both reads as a bug in whichever case it\n // does not describe.\n const agreementState = publisherAgreementState(profile?.publisherAgreement)\n // Whether the document can be read at all (AGL-1660). While it has no\n // published page there is no link to render and no acceptance to collect —\n // the summary below is a summary OF something, and without the something it\n // is just seven sentences we wrote.\n const agreementPresentation = publisherAgreementPresentation(agreementState)\n const acceptedOn = (() => {\n const at = profile?.publisherAgreement?.acceptedAt\n const date = at?.toDate?.()\n return date ? date.toLocaleDateString() : ''\n })()\n\n // The listing open in the full editor (AGL-862), or null when closed.\n const [editListing, setEditListing] = useState<any | null>(null)\n // Per-row overflow menu (AGL-999): the anchor plus the row it belongs to,\n // so one <Menu> serves every row instead of one per listing.\n const [rowMenu, setRowMenu] = useState<{\n anchor: HTMLElement\n listing: any\n } | null>(null)\n const closeRowMenu = () => setRowMenu(null)\n const listingHref = (listing: any) => listingPath(basePath, listing.$id)\n // Shipping a new version was invisible as a path (AGL-1008): the only door\n // was the generic publish form, which reads entirely like first-time\n // publishing, so updating looked like creating a second listing. Same\n // form, pre-bound to the listing.\n const newVersionHref = (listing: any) =>\n publishPluginPath(basePath, listing.$id)\n\n // Private ⇄ public (AGL-968/994). Goes through the API rather than a client\n // write: making a listing public is gated on it actually carrying the docs\n // a stranger needs, and that check has to live somewhere a client can't\n // skip. No re-review either way — the bytes are unchanged.\n //\n // Unpublish ⇄ republish goes through the API too (AGL-3321). It was a\n // client write of `deletedAt`, but browse queries each listing's audience,\n // which only the server re-derives — so the rules now deny the field here.\n //\n // Both were saves on the click; each now asks first, with the publisher\n // agreement above its button (AGL-4105), and is made from that dialog.\n const [listingChange, setListingChange] = useState<{\n kind: 'visibility' | 'published'\n listing: any\n } | null>(null)\n const changeListing = useCallback(\n async (\n change: { kind: 'visibility' | 'published'; listing: any },\n agreement: PublisherAgreementConsent,\n ): Promise<string | null> => {\n const { kind, listing } = change\n const nextVisibility = listing.visibility === 'private' ? 'public' : 'private'\n try {\n const response = await authorizedFetch(\n user,\n '/api/marketplace/publish-plugin',\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(\n kind === 'visibility'\n ? {\n action: 'set-visibility',\n listingId: listing.$id,\n visibility: nextVisibility,\n agreement,\n }\n : {\n action: 'set-published',\n listingId: listing.$id,\n published: Boolean(listing.deletedAt),\n agreement,\n },\n ),\n },\n )\n const payload = await response.json().catch(() => ({}))\n if (!response.ok) {\n return String(\n payload?.error ??\n (kind === 'visibility'\n ? 'Visibility change failed'\n : 'Publishing change failed'),\n )\n }\n enqueueSnackbar(\n kind === 'visibility'\n ? nextVisibility === 'private'\n ? 'Now private — only your sites can install it'\n : 'Published to the marketplace'\n : listing.deletedAt\n ? 'Republished'\n : 'Unpublished',\n { variant: 'success', persist: false },\n )\n return null\n } catch (error) {\n console.error(error)\n return 'An error has occurred'\n }\n },\n [user, enqueueSnackbar],\n )\n const listingChangeCopy = (() => {\n const listing = listingChange?.listing\n const name = listing?.displayName || 'this listing'\n if (listingChange?.kind === 'visibility') {\n return listing?.visibility === 'private'\n ? {\n title: 'Make public?',\n body: `${name} is offered in the marketplace, not only to your organization’s sites.`,\n confirmLabel: 'Make public',\n destructive: false,\n }\n : {\n title: 'Make private?',\n body: `Only your organization’s sites can install ${name}. Private plugins never appear in the marketplace.`,\n confirmLabel: 'Make private',\n destructive: false,\n }\n }\n return listing?.deletedAt\n ? {\n title: 'Republish?',\n body: `${name} goes back on the marketplace.`,\n confirmLabel: 'Republish',\n destructive: false,\n }\n : {\n title: 'Unpublish?',\n body: `${name} comes off the marketplace. You can republish it later.`,\n confirmLabel: 'Unpublish',\n destructive: true,\n }\n })()\n\n const cards: Record<OrgSellerSection, ReactElement> = {\n profile: (\n <Stack spacing={2}>\n <CardDisplay\n header={'Public profile'}\n help={pluginDocsHelp('publisherHandbook', {\n anchor: '#public-profile',\n })}\n contentGutterX\n contentGutterY\n >\n <Stack spacing={2}>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Shown on every component you publish to the marketplace. A ' +\n 'profile is required before publishing.'}\n </Typography>\n <TextField\n label=\"Handle\"\n value={handle}\n onChange={(event) => setHandle(event.target.value.toLowerCase())}\n size=\"small\"\n error={Boolean(handle) && !validHandle}\n helperText={\n Boolean(handle) && !validHandle\n ? '3–30 chars: lowercase letters, digits, dashes'\n : ' '\n }\n />\n <TextField\n label=\"Display name\"\n value={displayName}\n onChange={(event) => setDisplayName(event.target.value)}\n size=\"small\"\n />\n <TextField\n label=\"Bio\"\n value={bio}\n onChange={(event) => setBio(event.target.value)}\n size=\"small\"\n multiline\n minRows={2}\n />\n {/* Logo (AGL-1009): picked from the media library like every\n other image the console chooses — never a pasted URL. */}\n {/* What to bring, said before the upload (AGL-2486). */}\n <Typography variant=\"caption\" color=\"text.secondary\" component=\"div\">\n {LISTING_LOGO_HINT}\n </Typography>\n <Stack direction=\"row\" spacing={2} sx={{ alignItems: 'center' }}>\n <Avatar\n src={avatarUrl || undefined}\n alt={displayName || 'Publisher logo'}\n sx={{ width: 56, height: 56 }}\n variant=\"rounded\"\n >\n {(displayName || handle || '?').slice(0, 1).toUpperCase()}\n </Avatar>\n <Stack direction=\"row\" spacing={1}>\n <Button size=\"small\" onClick={chooseLogo}>\n {avatarUrl ? 'Replace logo' : 'Choose logo from library'}\n </Button>\n {avatarUrl ? (\n <Button\n size=\"small\"\n color=\"error\"\n onClick={() => setAvatarUrl('')}\n >\n {'Remove'}\n </Button>\n ) : null}\n </Stack>\n </Stack>\n {/* Support contact (AGL-1009): buyers of a paid plugin need\n somewhere to go, and a reviewer needs it more. */}\n <TextField\n label=\"Support email\"\n value={supportEmail}\n onChange={(event) => setSupportEmail(event.target.value)}\n size=\"small\"\n type=\"email\"\n />\n <TextField\n label=\"Support URL\"\n value={supportUrl}\n onChange={(event) => setSupportUrl(event.target.value)}\n size=\"small\"\n helperText=\"Where buyers go for help with your plugins — https:// only\"\n />\n <TextField\n label=\"Website\"\n value={website}\n onChange={(event) => setWebsite(event.target.value)}\n size=\"small\"\n helperText=\"Your own site, linked from your publisher page — https:// only\"\n />\n {/* Fixed social set (AGL-1009): the storefront renders these as\n icons, so it is a known trio rather than a free-form list. */}\n <TextField\n label=\"GitHub\"\n value={githubUrl}\n onChange={(event) => setGithubUrl(event.target.value)}\n size=\"small\"\n helperText=\"https://github.com/…\"\n />\n <TextField\n label=\"X\"\n value={xUrl}\n onChange={(event) => setXUrl(event.target.value)}\n size=\"small\"\n helperText=\"https://x.com/…\"\n />\n <TextField\n label=\"LinkedIn\"\n value={linkedinUrl}\n onChange={(event) => setLinkedinUrl(event.target.value)}\n size=\"small\"\n helperText=\"https://linkedin.com/…\"\n />\n {/* Directly above Save profile (AGL-4105), which waits for it. */}\n <PublisherAgreementCheckbox\n checked={profileAgreement.agreed}\n onChange={profileAgreement.setAgreed}\n disabled={profileBusy}\n />\n <Button\n variant=\"contained\"\n color=\"primary\"\n disabled={\n profileBusy ||\n !validHandle ||\n !displayName.trim() ||\n !profileAgreement.agreed\n }\n onClick={handleSave}\n >\n {profileBusy ? 'Saving…' : 'Save profile'}\n </Button>\n </Stack>\n </CardDisplay>\n\n {/* The publisher agreement (AGL-1077). Agreed to on every save since\n AGL-4105 — the box above Save profile, above each listing's save,\n above every Publish — so this card says what the terms are and\n when the organization last agreed, and asks for nothing itself. */}\n <CardDisplay\n header={PUBLISHER_AGREEMENT_TITLE}\n help={pluginDocsHelp('publisherHandbook', {\n anchor: '#the-publisher-agreement',\n excerpt:\n 'The terms your organization publishes under — agreed to on ' +\n 'every save in the marketplace.',\n })}\n contentGutterX\n contentGutterY\n >\n <Stack spacing={2}>\n {/* An unpublished document replaces the rest (AGL-1660): while\n there is no page to read there is nothing to agree to, and the\n omission is entirely ours. */}\n {agreementPresentation.unavailableNotice ? (\n <Alert severity=\"warning\">\n {agreementPresentation.unavailableNotice}\n </Alert>\n ) : (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Every save in the marketplace — this profile, a listing, its ' +\n 'price or visibility, a new version, a component, template ' +\n `or layout — asks you to tick “I agree to the ${PUBLISHER_AGREEMENT_TITLE}” ` +\n 'first. We record who agreed, to which version, and when.'}\n </Typography>\n )}\n {agreementState === 'none' ? null : (\n <Typography variant=\"body2\">\n {`Last agreed to: version ${profile?.publisherAgreement?.version}` +\n (acceptedOn ? `, on ${acceptedOn}` : '') +\n (agreementState === 'outdated'\n ? `. The current version is ${PUBLISHER_AGREEMENT_VERSION}, ` +\n 'which your next save agrees to.'\n : '.')}\n </Typography>\n )}\n {/* The summary and the link, from the same presentation helper the\n box reads, so this card can never link an unreadable document. */}\n <PublisherAgreementSummary\n documentUrl={agreementPresentation.documentUrl}\n />\n </Stack>\n </CardDisplay>\n </Stack>\n ),\n listings: (\n <CardDisplay\n header={'Your listings'}\n help={pluginDocsHelp('publisherHandbook', { anchor: '#your-listings' })}\n contentGutterX\n contentGutterY\n >\n {(listings ?? []).length === 0 ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Publish a reusable component from a site’s Setup page to list ' +\n 'it here.'}\n </Typography>\n ) : (\n <Stack spacing={1}>\n {/* Private plugins are invisible in Browse by design (AGL-993),\n which makes this the only door to them — say so, or a\n publisher looking for the one they just uploaded will hunt\n for it in the marketplace grid. */}\n {(listings ?? []).some(\n (listing: any) => listing.visibility === 'private',\n ) ? (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {'Private plugins never appear in the marketplace — open one ' +\n 'with View to install it on your sites.'}\n </Typography>\n ) : null}\n {(listings ?? []).map((listing: any) => (\n <Stack\n key={listing.$id}\n direction=\"row\"\n spacing={1}\n sx={{\n alignItems: 'center',\n // The whole row is the way in (AGL-999) — the name and its\n // metadata are what you aim at, so they should behave like\n // the link they read as.\n borderRadius: 1,\n mx: -1,\n px: 1,\n '&:hover': { bgcolor: 'action.hover' },\n }}\n >\n <Stack\n onClick={() => router.push(listingHref(listing))}\n sx={{\n flex: 1,\n minWidth: 0,\n py: 0.75,\n cursor: 'pointer',\n }}\n >\n <Stack\n direction=\"row\"\n spacing={1}\n sx={{ alignItems: 'center', minWidth: 0 }}\n >\n <Typography variant=\"body2\" noWrap>\n {listing.displayName}\n </Typography>\n {/* This tab is the ONLY place a private listing appears\n (AGL-993 keeps it out of browse), so the row has to\n say which of the two things it is. */}\n {listing.visibility === 'private' ? (\n <Chip size=\"small\" variant=\"outlined\" label=\"Private\" />\n ) : null}\n </Stack>\n <Typography variant=\"caption\" color=\"text.secondary\">\n {`v${listing.latestVersion}` +\n (Number(listing.priceUsd ?? 0) > 0\n ? ` · $${listing.priceUsd}`\n : ' · free') +\n (listing.previewImageUrl ? ' · has preview' : '') +\n (listing.deletedAt ? ' · unpublished' : '')}\n </Typography>\n </Stack>\n {/* View what a buyer sees (AGL-988). The one action that\n stays visible (AGL-999): every other row action is either\n rare or destructive, and flattening them all out made the\n columns jump between rows — the action count varies by\n artifact type — while putting Unpublish at the end of the\n row, the easiest place to hit by mistake. */}\n <AppLink\n href={listingHref(listing)}\n newTab\n aria-label={`View ${listing.displayName}`}\n >\n <Button size=\"small\" color=\"primary\" component=\"span\">\n {'View'}\n </Button>\n </AppLink>\n <IconButton\n size=\"small\"\n aria-label={`More actions for ${listing.displayName}`}\n onClick={(event) =>\n setRowMenu({\n anchor: event.currentTarget,\n listing,\n })\n }\n >\n <MdiIcon path={mdiDotsVertical.path} fontSize=\"small\" />\n </IconButton>\n </Stack>\n ))}\n </Stack>\n )}\n {/* One menu for every row (AGL-999) — the open row is state, not a\n mounted <Menu> per listing. */}\n <Menu\n anchorEl={rowMenu?.anchor ?? null}\n open={Boolean(rowMenu)}\n onClose={closeRowMenu}\n >\n {/* Plugins only: bytes are the thing being shipped, and only a\n plugin listing has a bundle (AGL-1008). */}\n {(rowMenu?.listing?.artifactType ?? rowMenu?.listing?.type) ===\n 'plugin' ? (\n <MenuItem\n onClick={() => {\n const listing = rowMenu?.listing\n closeRowMenu()\n if (listing) router.push(newVersionHref(listing))\n }}\n >\n {'Publish new version…'}\n </MenuItem>\n ) : null}\n <MenuItem\n onClick={() => {\n setEditListing(rowMenu?.listing ?? null)\n closeRowMenu()\n }}\n >\n {'Edit listing'}\n </MenuItem>\n {/* Plugins only (AGL-994). `visibility` is enforced in\n `install-plugin`; the component/layout/template install routes\n have no such check, so offering the switch there would promise\n a boundary that does not exist. */}\n {(rowMenu?.listing?.artifactType ?? rowMenu?.listing?.type) ===\n 'plugin' ? (\n <MenuItem\n onClick={() => {\n const listing = rowMenu?.listing\n closeRowMenu()\n if (listing) setListingChange({ kind: 'visibility', listing })\n }}\n >\n {rowMenu?.listing?.visibility === 'private'\n ? 'Make public…'\n : 'Make private…'}\n </MenuItem>\n ) : null}\n <Divider />\n <MenuItem\n sx={{\n color: rowMenu?.listing?.deletedAt ? undefined : 'error.main',\n }}\n onClick={() => {\n const listing = rowMenu?.listing\n closeRowMenu()\n if (listing) setListingChange({ kind: 'published', listing })\n }}\n >\n {rowMenu?.listing?.deletedAt ? 'Republish…' : 'Unpublish…'}\n </MenuItem>\n </Menu>\n <PublisherAgreementConfirmDialog\n open={Boolean(listingChange)}\n title={listingChangeCopy.title}\n body={listingChangeCopy.body}\n confirmLabel={listingChangeCopy.confirmLabel}\n destructive={listingChangeCopy.destructive}\n onConfirm={(agreement) =>\n listingChange\n ? changeListing(listingChange, agreement)\n : Promise.resolve(null)\n }\n onClose={() => setListingChange(null)}\n />\n <EditListingDialog\n orgId={orgId}\n listing={editListing}\n open={Boolean(editListing)}\n onClose={() => setEditListing(null)}\n user={user}\n />\n </CardDisplay>\n ),\n payouts: (\n <CardDisplay\n header={'Payouts'}\n help={pluginDocsHelp('publisherHandbook', {\n anchor: '#set-up-payouts',\n })}\n contentGutterX\n contentGutterY\n >\n <Stack spacing={2}>\n {payoutsState === 'error' ? (\n // Neither sentence is safe here: \"Payouts are enabled\" and\n // \"Connect a Stripe account\" both state a payout arrangement we\n // failed to read, and the button under them acts on it.\n <Alert\n severity=\"error\"\n action={\n <Button\n color=\"inherit\"\n size=\"small\"\n onClick={() => setProfileRetryNonce((n) => n + 1)}\n >\n {'Retry'}\n </Button>\n }\n >\n {'We couldn’t load your payout setup. This says nothing about ' +\n 'whether payouts are on — nothing has changed.'}\n </Alert>\n ) : payoutsState === 'pending' ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Checking your payout setup…'}\n </Typography>\n ) : (\n <>\n {/* The charges-yes/payouts-no state (AGL-1997), which used to\n render as unqualified success. Stripe will let this account\n take money and will not let it out yet, so the honest thing\n is to say both halves — a publisher who reads \"enabled\" and\n sells has no reason to go finish verification. */}\n {readiness === 'blocked' ? (\n <Alert severity=\"warning\">\n {'Your Stripe account can take payments, but payouts are ' +\n 'not enabled yet — sales would stay in Stripe rather ' +\n 'than reaching your bank. Finish verification in Stripe ' +\n 'to release them.'}\n </Alert>\n ) : null}\n {/* AGL-2471. The connected account was never verified against\n this deployment's Stripe mode, and the sale gate refuses it\n — so the card must not imply the account works. Saying it\n plainly, with the one action that fixes it, is the whole\n difference between this and a storefront that looks ready\n and cannot take a payment. */}\n {readiness === 'unverified' ? (\n <Alert severity=\"error\">\n {'This Stripe account has not been verified for payments ' +\n 'here, so sales will be refused. Reconnect it to ' +\n 'confirm — if it was set up against Stripe test mode, ' +\n 'you will need to connect a live account.'}\n </Alert>\n ) : null}\n <Typography variant=\"body2\" color=\"text.secondary\">\n {readiness === 'ready'\n ? 'Payouts are enabled — paid listings transfer to your ' +\n 'Stripe account automatically (platform fee 20%, 30% on ' +\n 'the Free plan).'\n : readiness === 'unknown'\n ? // Connected, payout readiness unread. Says only what is\n // known, like the error branch above.\n 'Your Stripe account is connected. We haven’t checked ' +\n 'whether payouts are released yet — recheck to ' +\n 'confirm. The platform fee is 20% per sale (30% on ' +\n 'the Free plan).'\n : readiness === 'blocked' || readiness === 'unverified'\n ? 'The platform fee is 20% per sale (30% on the Free ' +\n 'plan).'\n : 'Connect a Stripe account to sell components. The ' +\n 'platform fee is 20% per sale (30% on the Free plan).'}\n </Typography>\n <Button\n variant={chargesEnabled ? 'outlined' : 'contained'}\n color=\"primary\"\n disabled={payoutsBusy}\n onClick={handlePayouts}\n >\n {payoutsBusy\n ? 'Opening Stripe…'\n : readiness === 'ready'\n ? 'Payouts enabled — recheck status'\n : readiness === 'blocked'\n ? 'Finish payout setup in Stripe'\n : readiness === 'unverified'\n ? 'Reconnect Stripe to verify'\n : readiness === 'unknown'\n ? 'Recheck payout status'\n : 'Set up payouts'}\n </Button>\n {/*\n Where the money actually is. Aglyn records no\n balance, no payout schedule, and handles no `payout.failed`\n event, so a publisher whose payout bounced cannot learn that\n here. An Express account has no direct login, which leaves a\n platform-minted link as the only route in.\n */}\n {dashboardUrl ? (\n <Button\n variant=\"text\"\n color=\"primary\"\n href={dashboardUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {'View payouts in Stripe'}\n </Button>\n ) : null}\n </>\n )}\n </Stack>\n </CardDisplay>\n ),\n sales: (\n <CardDisplay\n header={'Sales'}\n help={pluginDocsHelp('publishAPlugin', {\n anchor: '#paid-listings',\n excerpt:\n 'Sent to your Stripe account is your share after the platform ' +\n `fee — sales tax is collected on ${PLATFORM_BRAND_LEGAL_NAME}’s ` +\n 'registration and is never yours.',\n })}\n contentGutterX\n contentGutterY\n >\n {(sales ?? []).length === 0 ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'No sales yet. Paid listings appear here with what buyers paid ' +\n 'and what was paid out to you.'}\n </Typography>\n ) : (\n <Stack spacing={0.5}>\n <Typography variant=\"body2\">\n {`${totals.paidCount} sale${totals.paidCount === 1 ? '' : 's'}`}\n {totals.refundedCount > 0\n ? ` · ${totals.refundedCount} refunded or charged back`\n : ''}\n </Typography>\n {/*\n The payout FIRST, and named for what it is. It is the number a\n publisher reconciles against their Stripe account, and it is the\n one this card used to get wrong.\n\n \"Sent to your Stripe account\", not \"net paid out\".\n The figure sums `transferCents` — the instruction given at charge\n time — so it says the money was DISPATCHED and knows nothing\n about whether the payout from that balance to a bank succeeded.\n A publisher reading \"net paid out\" during a failed payout was\n told their money had landed by the one surface that should have\n warned them. The notice below carries the arrival.\n */}\n <Typography variant=\"body2\">\n {`Sent to your Stripe account $${(\n totals.sentToStripeCents / 100\n ).toFixed(2)}`}\n </Typography>\n {/*\n WHERE IT STOPPED, when it stopped. Mirrored onto the publisher\n profile by the `payout.failed` handler, and retired by the next\n successful payout — so this is a live problem, not a scar.\n */}\n {profile?.lastPayoutFailureAtMs ? (\n <Alert severity=\"warning\" variant=\"outlined\">\n {`A payout of $${(\n Number(profile.lastPayoutFailureCents ?? 0) / 100\n ).toFixed(2)} did not reach your bank on ${new Date(\n Number(profile.lastPayoutFailureAtMs),\n ).toLocaleDateString()} — ${String(\n profile.lastPayoutFailureReason ?? 'Stripe did not say why',\n )} The money is still in your Stripe account. Open Stripe to fix your payout details.`}\n </Alert>\n ) : null}\n <Typography variant=\"body2\" color=\"text.secondary\">\n {`Buyers paid $${(totals.buyersPaidCents / 100).toFixed(2)} · ` +\n `sales tax $${(totals.salesTaxCents / 100).toFixed(2)} · ` +\n `platform fee $${(totals.platformFeeCents / 100).toFixed(2)}`}\n </Typography>\n {totals.refundedCount > 0 ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {`$${(totals.returnedCents / 100).toFixed(2)} returned on refunded ` +\n 'and charged-back sales, and excluded above'}\n </Typography>\n ) : null}\n {/*\n THE COPY THAT LANDS WITH THE SMALLER NUMBER. A publisher who\n read `net $88.25` yesterday and reads `net paid out $80.00`\n today is owed the reason on the same card, not in a changelog.\n */}\n <Typography variant=\"caption\" color=\"text.secondary\">\n {'Sent to your Stripe account is the pre-tax price less the ' +\n 'platform fee. Sales tax is collected and remitted by ' +\n `${PLATFORM_BRAND_LEGAL_NAME} under its marketplace-provider ` +\n 'registration and was never part of your share. Reaching ' +\n 'your Stripe balance is not the same as reaching your bank — ' +\n 'a failed payout is called out above.'}\n </Typography>\n </Stack>\n )}\n </CardDisplay>\n ),\n }\n\n return cards[section]\n}\nOrgSellerPanel.displayName = 'OrgSellerPanel'\n\nexport default OrgSellerPanel\n"],"names":["trackEvent","mdiDotsVertical","AppLink","CardDisplay","MdiIcon","useSnackbar","Alert","Avatar","Button","Chip","Divider","IconButton","Menu","MenuItem","Stack","TextField","Typography","PUBLISHER_AGREEMENT_TITLE","PUBLISHER_AGREEMENT_VERSION","publisherAgreementPresentation","publisherAgreementState","PLATFORM_BRAND_LEGAL_NAME","LISTING_LOGO_HINT","useRouter","collection","doc","query","where","useCallback","useEffect","useState","useFirestore","useUser","authorizedFetch","pluginDocsHelp","useMediaPicker","useFirestoreCollection","useFirestoreDoc","EditListingDialog","PublisherAgreementCheckbox","usePublisherAgreementConsent","PublisherAgreementConfirmDialog","PublisherAgreementSummary","listingPath","publishPluginPath","payoutReadiness","summarizeSellerLedger","HANDLE_PATTERN","OrgSellerPanel","props","profile","rowMenu","orgId","section","basePath","router","firestore","data","user","enqueueSnackbar","profileRetryNonce","setProfileRetryNonce","status","profileStatus","idField","payoutsState","readiness","state","chargesEnabled","stripeChargesEnabled","payoutsEnabled","stripePayoutsEnabled","accountLivemode","stripeAccountLivemode","listings","sales","totals","payoutsBusy","setPayoutsBusy","dashboardUrl","setDashboardUrl","handlePayouts","response","method","headers","body","JSON","stringify","payload","json","variant","persist","ok","error","allowDuplicate","url","window","location","assign","console","handle","setHandle","displayName","setDisplayName","bio","setBio","avatarUrl","setAvatarUrl","pickMedia","chooseLogo","picked","kind","website","setWebsite","supportEmail","setSupportEmail","supportUrl","setSupportUrl","githubUrl","setGithubUrl","xUrl","setXUrl","linkedinUrl","setLinkedinUrl","validHandle","test","profileAgreement","profileBusy","setProfileBusy","handleSave","trim","consent","agreement","catch","reset","agreementState","publisherAgreement","agreementPresentation","acceptedOn","at","acceptedAt","date","toDate","toLocaleDateString","editListing","setEditListing","setRowMenu","closeRowMenu","listingHref","listing","$id","newVersionHref","listingChange","setListingChange","changeListing","change","nextVisibility","visibility","action","listingId","published","Boolean","deletedAt","String","listingChangeCopy","name","title","confirmLabel","destructive","cards","spacing","header","help","anchor","contentGutterX","contentGutterY","color","label","value","onChange","event","target","toLowerCase","size","helperText","multiline","minRows","component","direction","sx","alignItems","src","undefined","alt","width","height","slice","toUpperCase","onClick","type","checked","agreed","setAgreed","disabled","excerpt","unavailableNotice","severity","version","documentUrl","length","some","map","borderRadius","mx","px","bgcolor","push","flex","minWidth","py","cursor","noWrap","latestVersion","Number","priceUsd","previewImageUrl","href","newTab","aria-label","currentTarget","path","fontSize","anchorEl","open","onClose","artifactType","onConfirm","Promise","resolve","payouts","n","rel","paidCount","refundedCount","sentToStripeCents","toFixed","lastPayoutFailureAtMs","lastPayoutFailureCents","Date","lastPayoutFailureReason","buyersPaidCents","salesTaxCents","platformFeeCents","returnedCents"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/marketplace/src/lib/components/org-seller-panel.component.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport { trackEvent } from '@aglyn/aglyn/app-utils/analytics-events'\nimport { mdiDotsVertical } from '@aglyn/shared-data-mdi'\nimport { AppLink, CardDisplay, MdiIcon } from '@aglyn/shared-ui-jsx'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport {\n Alert,\n Avatar,\n Button,\n Chip,\n Divider,\n IconButton,\n Menu,\n MenuItem,\n Stack,\n TextField,\n Typography,\n} from '@mui/material'\nimport {\n PUBLISHER_AGREEMENT_TITLE,\n PUBLISHER_AGREEMENT_VERSION,\n publisherAgreementPresentation,\n publisherAgreementState,\n type PublisherAgreementConsent,\n} from '../model/publisher-agreement'\n/*\n THE LEGAL NAME, not `useBranding().branding.productName` (AGL-2351).\n\n Every other customer-facing string in the console reads the org's resolved\n product name, and doing that here would be false: the two sentences below say\n which entity holds a sales-tax registration and remits against it. A\n white-label agency holds neither. The value has to name the company that\n actually stands behind the money — the same reasoning that keeps\n `tx-return-webfile.ts` naming the entity rather than the product, and the\n reason these two were left out of the AGL-2319 sweep instead of swept wrong.\n*/\nimport { PLATFORM_BRAND_LEGAL_NAME } from '@aglyn/aglyn/app-utils/platform-brand'\nimport { LISTING_LOGO_HINT } from '../constants/listing-media'\nimport {\n MARKETPLACE_MANAGE_LISTINGS_PERMISSION,\n MARKETPLACE_PAYOUTS_PERMISSION,\n MARKETPLACE_PUBLISHER_PROFILE_PERMISSION,\n marketplacePublisherPermissionRefusal,\n} from '../model/marketplace-publisher-permissions'\nimport { useRouter } from 'next/navigation'\nimport { collection, doc, query, where } from 'firebase/firestore'\nimport { type ReactElement, useCallback, useEffect, useState } from 'react'\nimport { useFirestore, useUser } from '@aglyn/tenant-feature-instance'\nimport { authorizedFetch } from '@aglyn/shared-util-http/authorized-token'\nimport { pluginDocsHelp, useMediaPicker } from '@aglyn/aglyn'\nimport { useFirestoreCollection } from '@aglyn/tenant-feature-instance'\nimport { useFirestoreDoc } from '@aglyn/tenant-feature-instance'\nimport EditListingDialog from './edit-listing-dialog.component'\nimport {\n PublisherAgreementCheckbox,\n usePublisherAgreementConsent,\n} from './publisher-agreement-checkbox.component'\nimport PublisherAgreementConfirmDialog from './publisher-agreement-confirm-dialog.component'\nimport PublisherAgreementSummary from './publisher-agreement-summary.component'\nimport { listingPath, publishPluginPath } from '../model/marketplace-paths'\nimport { payoutReadiness } from '../model/payout-readiness'\nimport {\n summarizeSellerLedger,\n type SellerLedgerSale,\n} from '../model/seller-ledger-totals'\n\nconst HANDLE_PATTERN = /^[a-z0-9][a-z0-9-]{2,29}$/\n\nexport type OrgSellerSection = 'profile' | 'listings' | 'payouts' | 'sales'\n\nexport interface OrgSellerPanelProps {\n orgId: string\n /** Which seller card to render — one per Marketplace › seller tab. */\n section: OrgSellerSection\n /**\n * Where the marketplace hub is mounted under this organization, from the\n * shell (AGL-3080) — the panel's links to a listing and to the publish\n * form hang beneath it. It replaced an org slug and the console's route\n * table, which a plugin may not import.\n */\n basePath: string\n /**\n * The viewer's resolved permissions, from the shell (AGL-4047). Saving the\n * profile asks \"Edit the publisher profile\", a listing's edit, visibility\n * and unpublish actions ask \"Manage published listings\", and setting up\n * payouts asks \"Manage marketplace payouts\", as their routes (and, for the\n * first two, the rules) do; a control the viewer may not use stays on\n * screen, disabled, with the permission named. An absent key reads as\n * allowed, as the map reads while it loads: the route still decides.\n */\n permissions?: Record<string, boolean | undefined>\n}\n\n/**\n * Seller area (AGL-44/798/801): the org's marketplace identity and its\n * published listings, folded out of the retired `/[orgSlug]/marketplace` page.\n * Each section (profile, listings, payouts, sales) is its own Marketplace\n * ROUTE (AGL-801/693), so this renders exactly one card per the `section`\n * prop. The shared Firestore hooks run regardless of which section is asked\n * for — Firebase dedupes identical listeners, and only the section the reader\n * navigated to is mounted at all, so the others never subscribe.\n */\nexport function OrgSellerPanel(props: OrgSellerPanelProps) {\n const { orgId, section, basePath, permissions } = props\n const canEditProfile =\n permissions?.[MARKETPLACE_PUBLISHER_PROFILE_PERMISSION] !== false\n const canManageListings =\n permissions?.[MARKETPLACE_MANAGE_LISTINGS_PERMISSION] !== false\n const canManagePayouts =\n permissions?.[MARKETPLACE_PAYOUTS_PERMISSION] !== false\n const router = useRouter()\n const firestore = useFirestore()\n const { data: user } = useUser()\n const { enqueueSnackbar } = useSnackbar()\n /** Bumped by Retry to re-subscribe the publisher profile (AGL-1380). */\n const [profileRetryNonce, setProfileRetryNonce] = useState(0)\n const { data: profile, status: profileStatus } = useFirestoreDoc<any>(\n // The org's marketplace identity (AGL-652), not the personal one. Held\n // at null rather than addressed as `publisherProfiles/-none-`: that\n // sentinel issued a guaranteed-denied read, and a denial now lands in\n // `status: 'error'`, which means something.\n () => (orgId ? doc(firestore, 'publisherProfiles', orgId) : null),\n [firestore, orgId, profileRetryNonce],\n { idField: '$id' },\n )\n /**\n * Three outcomes, not two (AGL-1380). An absent publisher profile is the\n * value BEFORE an answer as much as it is the value of a publisher who\n * never connected Stripe, so reading payout state off `stripeChargesEnabled`\n * alone told a publisher already taking payouts to \"Connect a Stripe\n * account\" and offered them the setup button that starts onboarding again.\n */\n const payoutsState: 'pending' | 'error' | 'loaded' =\n !orgId || profileStatus === 'loading'\n ? 'pending'\n : profileStatus === 'error'\n ? 'error'\n : 'loaded'\n /**\n * TWO questions, not one (AGL-1997). This card said \"Payouts are enabled\"\n * off `stripeChargesEnabled` — whether Stripe will let the account take\n * MONEY — and never read `stripePayoutsEnabled`, whether the money can\n * LEAVE. The decision itself lives in `payoutReadiness` so each of its six\n * outcomes can be asserted without mounting this tree.\n */\n const readiness = payoutReadiness({\n state: payoutsState,\n chargesEnabled: profile?.stripeChargesEnabled,\n payoutsEnabled: profile?.stripePayoutsEnabled,\n accountLivemode: profile?.stripeAccountLivemode,\n })\n /** Stripe will let this account take money — four of the seven outcomes. */\n const chargesEnabled =\n readiness === 'ready' ||\n readiness === 'blocked' ||\n readiness === 'unknown' ||\n readiness === 'unverified'\n // Both held at null while the org is unknown, like the profile above\n // (AGL-1440): AGL-1380 repaired the profile ref and left these two\n // `where`-clause siblings on the sentinel. The purchases query is the one\n // that matters — `marketplacePurchases` is buyer/seller-gated, and a\n // rules-shaped LIST is evaluated against the QUERY, so the sentinel was\n // denied wholesale and retried on the refusal cadence. The listings query\n // is public and merely wasted the round trip.\n const { data: listings } = useFirestoreCollection<any>(\n () =>\n orgId\n ? query(\n collection(firestore, 'marketplaceListings'),\n // Listings are org-owned (AGL-652): `profileId` is the org id,\n // not a uid — filtering by uid left this list permanently empty\n // (AGL-781).\n where('profileId', '==', orgId),\n )\n : null,\n [firestore, orgId],\n { idField: '$id' },\n )\n // Seller ledger (AGL-46): purchase records written by the Stripe webhook.\n const { data: sales } = useFirestoreCollection<any>(\n () =>\n orgId\n ? query(\n collection(firestore, 'marketplacePurchases'),\n // Sales belong to the ORG that published (AGL-652).\n where('sellerOrgId', '==', orgId),\n )\n : null,\n [firestore, orgId],\n { idField: '$id' },\n )\n // What the publisher was actually paid (AGL-2158) — see\n // `summarizeSellerLedger`, where the arithmetic and the reasoning live. This\n // card used to render `amountCents − feeCents` as \"net\", which is\n // `pretax + tax − fee`: the payout PLUS sales tax that was never the\n // publisher's, summed over refunded sales as well as live ones.\n const totals = summarizeSellerLedger(sales as SellerLedgerSale[] | undefined)\n\n const [payoutsBusy, setPayoutsBusy] = useState(false)\n /**\n * A one-time Stripe Express dashboard link from the connect route. Not\n * persisted: login links are single-use and short-lived, so a stored one is\n * a button that fails the second time it is pressed.\n */\n const [dashboardUrl, setDashboardUrl] = useState<string | null>(null)\n const handlePayouts = useCallback(async () => {\n setPayoutsBusy(true)\n try {\n const response = await authorizedFetch(user, '/api/marketplace/connect', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n // The acting org from the URL (AGL-861) — never let the server guess\n // which of the user's orgs is being set up for payouts.\n body: JSON.stringify({ orgId }),\n })\n const payload = await response.json()\n if (response.status === 501) {\n return void enqueueSnackbar(\n 'Payouts are not configured on this deployment',\n { variant: 'info', persist: false },\n )\n }\n if (!response.ok) {\n return void enqueueSnackbar(payload?.error ?? 'Payout setup failed', {\n variant: 'error',\n allowDuplicate: true,\n })\n }\n if (payload.chargesEnabled) {\n // Publisher-payout half of the same activation metric (AGL-1561),\n // gated on the transition for the same reason as the commerce card:\n // the connect handler is re-entrant and reports `true` on every\n // revisit. `chargesEnabled` is the pre-request state — the metric is\n // about CONNECTING (AGL-1997 split the two flags; payout readiness\n // can arrive days later and is not a second activation).\n if (!chargesEnabled) trackEvent('stripe_connected', {})\n // A WARNING THAT NAMES A PROBLEM MUST OFFER THE FIX.\n //\n // \"Finish payout setup in Stripe\" is the label this button carries in\n // exactly this state, and it could not open Stripe: the route returned\n // here with a status and no link, and this branch answered before the\n // `payload.url` check below ever ran. An Express account has no\n // password and no direct login, so a link minted by the platform is\n // the publisher's only way in — without one their share accumulates in\n // an account that cannot release it and nothing says why.\n if (payload.payoutsEnabled === false && payload.url) {\n return void window.location.assign(payload.url)\n }\n // Payouts are flowing, so the route answers with the Express dashboard\n // instead: balance, payout schedule, and the reason a payout failed.\n // Held rather than followed — this click was a status check.\n if (\n payload.payoutsEnabled !== false &&\n typeof payload.dashboardUrl === 'string'\n ) {\n setDashboardUrl(payload.dashboardUrl)\n }\n // The same split the card renders (AGL-1997): the route answers both\n // flags, so the toast must not announce payouts off the charges one.\n return void enqueueSnackbar(\n payload.payoutsEnabled === false\n ? 'Connected — payouts are not released yet'\n : 'Payouts are enabled',\n {\n variant: payload.payoutsEnabled === false ? 'warning' : 'success',\n persist: false,\n },\n )\n }\n if (payload.url) window.location.assign(payload.url)\n } catch (error) {\n console.error(error)\n enqueueSnackbar('An error has occurred', {\n variant: 'error',\n allowDuplicate: true,\n })\n } finally {\n setPayoutsBusy(false)\n }\n }, [orgId, user, chargesEnabled, enqueueSnackbar])\n\n const [handle, setHandle] = useState('')\n const [displayName, setDisplayName] = useState('')\n const [bio, setBio] = useState('')\n // Logo, support contact and social links (AGL-1009). `avatarUrl` and\n // `website` existed server-side already — they just had no form input and\n // no rendering, so they were dead fields until now.\n const [avatarUrl, setAvatarUrl] = useState('')\n /*\n * The console's media library, opened through the picker context rather\n * than by mounting its dialog (AGL-3080): the library is coupled to the\n * org and the session, which a plugin has no way to reach, and the console\n * provides `pickMedia` around every plugin page for exactly this. The URL\n * comes back already resolved — CDN path over the raw download URL\n * (AGL-1215) — so the panel no longer resolves one itself.\n */\n const { pickMedia } = useMediaPicker()\n const chooseLogo = useCallback(async () => {\n const picked = await pickMedia?.({ kind: 'image' })\n if (picked?.url) setAvatarUrl(picked.url)\n }, [pickMedia])\n const [website, setWebsite] = useState('')\n const [supportEmail, setSupportEmail] = useState('')\n const [supportUrl, setSupportUrl] = useState('')\n const [githubUrl, setGithubUrl] = useState('')\n const [xUrl, setXUrl] = useState('')\n const [linkedinUrl, setLinkedinUrl] = useState('')\n useEffect(() => {\n setHandle(profile?.handle ?? '')\n setDisplayName(profile?.displayName ?? '')\n setBio(profile?.bio ?? '')\n setAvatarUrl(profile?.avatarUrl ?? '')\n setWebsite(profile?.website ?? '')\n setSupportEmail(profile?.supportEmail ?? '')\n setSupportUrl(profile?.supportUrl ?? '')\n setGithubUrl(profile?.githubUrl ?? '')\n setXUrl(profile?.xUrl ?? '')\n setLinkedinUrl(profile?.linkedinUrl ?? '')\n }, [\n profile?.handle,\n profile?.displayName,\n profile?.bio,\n profile?.avatarUrl,\n profile?.website,\n profile?.supportEmail,\n profile?.supportUrl,\n profile?.githubUrl,\n profile?.xUrl,\n profile?.linkedinUrl,\n ])\n\n const validHandle = HANDLE_PATTERN.test(handle)\n // The publisher agreement, agreed to on this save (AGL-4105).\n const profileAgreement = usePublisherAgreementConsent()\n const [profileBusy, setProfileBusy] = useState(false)\n\n const handleSave = useCallback(async () => {\n if (!orgId || !validHandle || !displayName.trim()) return\n if (!profileAgreement.consent) return\n setProfileBusy(true)\n try {\n // Server-owned (AGL-652): the handle must be claimed transactionally in\n // publisherHandles, which a client write cannot do — two orgs racing\n // for one handle would both succeed and one would silently lose its\n // marketplace URL. The rules reject a client handle write outright.\n const response = await authorizedFetch(\n user,\n '/api/marketplace/publisher-profile',\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n orgId,\n handle,\n displayName: displayName.trim(),\n bio: bio.trim(),\n // AGL-1009: validated server-side (https-only, fixed social\n // hosts) — an empty string explicitly clears the stored field.\n avatarUrl: avatarUrl.trim(),\n website: website.trim(),\n supportEmail: supportEmail.trim(),\n supportUrl: supportUrl.trim(),\n githubUrl: githubUrl.trim(),\n xUrl: xUrl.trim(),\n linkedinUrl: linkedinUrl.trim(),\n agreement: profileAgreement.consent,\n }),\n },\n )\n const payload = await response.json().catch(() => null)\n if (!response.ok) {\n return enqueueSnackbar(payload?.error ?? 'Could not save the profile', {\n variant: 'warning',\n persist: false,\n })\n }\n enqueueSnackbar('Profile saved', { variant: 'success', persist: false })\n // Each save is its own agreement: the next one ticks the box again.\n profileAgreement.reset()\n } catch (error) {\n console.error(error)\n enqueueSnackbar('An error has occurred', {\n variant: 'error',\n allowDuplicate: true,\n })\n } finally {\n setProfileBusy(false)\n }\n }, [\n orgId,\n validHandle,\n handle,\n displayName,\n bio,\n avatarUrl,\n website,\n supportEmail,\n supportUrl,\n githubUrl,\n xUrl,\n linkedinUrl,\n profileAgreement,\n user,\n enqueueSnackbar,\n ])\n\n // The publisher agreement (AGL-1077). `none` and `outdated` get different\n // copy on purpose: \"you never agreed\" and \"the terms moved\" are different\n // situations, and one message for both reads as a bug in whichever case it\n // does not describe.\n const agreementState = publisherAgreementState(profile?.publisherAgreement)\n // Whether the document can be read at all (AGL-1660). While it has no\n // published page there is no link to render and no acceptance to collect —\n // the summary below is a summary OF something, and without the something it\n // is just seven sentences we wrote.\n const agreementPresentation = publisherAgreementPresentation(agreementState)\n const acceptedOn = (() => {\n const at = profile?.publisherAgreement?.acceptedAt\n const date = at?.toDate?.()\n return date ? date.toLocaleDateString() : ''\n })()\n\n // The listing open in the full editor (AGL-862), or null when closed.\n const [editListing, setEditListing] = useState<any | null>(null)\n // Per-row overflow menu (AGL-999): the anchor plus the row it belongs to,\n // so one <Menu> serves every row instead of one per listing.\n const [rowMenu, setRowMenu] = useState<{\n anchor: HTMLElement\n listing: any\n } | null>(null)\n const closeRowMenu = () => setRowMenu(null)\n const listingHref = (listing: any) => listingPath(basePath, listing.$id)\n // Shipping a new version was invisible as a path (AGL-1008): the only door\n // was the generic publish form, which reads entirely like first-time\n // publishing, so updating looked like creating a second listing. Same\n // form, pre-bound to the listing.\n const newVersionHref = (listing: any) =>\n publishPluginPath(basePath, listing.$id)\n\n // Private ⇄ public (AGL-968/994). Goes through the API rather than a client\n // write: making a listing public is gated on it actually carrying the docs\n // a stranger needs, and that check has to live somewhere a client can't\n // skip. No re-review either way — the bytes are unchanged.\n //\n // Unpublish ⇄ republish goes through the API too (AGL-3321). It was a\n // client write of `deletedAt`, but browse queries each listing's audience,\n // which only the server re-derives — so the rules now deny the field here.\n //\n // Both were saves on the click; each now asks first, with the publisher\n // agreement above its button (AGL-4105), and is made from that dialog.\n const [listingChange, setListingChange] = useState<{\n kind: 'visibility' | 'published'\n listing: any\n } | null>(null)\n const changeListing = useCallback(\n async (\n change: { kind: 'visibility' | 'published'; listing: any },\n agreement: PublisherAgreementConsent,\n ): Promise<string | null> => {\n const { kind, listing } = change\n const nextVisibility = listing.visibility === 'private' ? 'public' : 'private'\n try {\n const response = await authorizedFetch(\n user,\n '/api/marketplace/publish-plugin',\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(\n kind === 'visibility'\n ? {\n action: 'set-visibility',\n listingId: listing.$id,\n visibility: nextVisibility,\n agreement,\n }\n : {\n action: 'set-published',\n listingId: listing.$id,\n published: Boolean(listing.deletedAt),\n agreement,\n },\n ),\n },\n )\n const payload = await response.json().catch(() => ({}))\n if (!response.ok) {\n return String(\n payload?.error ??\n (kind === 'visibility'\n ? 'Visibility change failed'\n : 'Publishing change failed'),\n )\n }\n enqueueSnackbar(\n kind === 'visibility'\n ? nextVisibility === 'private'\n ? 'Now private — only your sites can install it'\n : 'Published to the marketplace'\n : listing.deletedAt\n ? 'Republished'\n : 'Unpublished',\n { variant: 'success', persist: false },\n )\n return null\n } catch (error) {\n console.error(error)\n return 'An error has occurred'\n }\n },\n [user, enqueueSnackbar],\n )\n const listingChangeCopy = (() => {\n const listing = listingChange?.listing\n const name = listing?.displayName || 'this listing'\n if (listingChange?.kind === 'visibility') {\n return listing?.visibility === 'private'\n ? {\n title: 'Make public?',\n body: `${name} is offered in the marketplace, not only to your organization’s sites.`,\n confirmLabel: 'Make public',\n destructive: false,\n }\n : {\n title: 'Make private?',\n body: `Only your organization’s sites can install ${name}. Private plugins never appear in the marketplace.`,\n confirmLabel: 'Make private',\n destructive: false,\n }\n }\n return listing?.deletedAt\n ? {\n title: 'Republish?',\n body: `${name} goes back on the marketplace.`,\n confirmLabel: 'Republish',\n destructive: false,\n }\n : {\n title: 'Unpublish?',\n body: `${name} comes off the marketplace. You can republish it later.`,\n confirmLabel: 'Unpublish',\n destructive: true,\n }\n })()\n\n const cards: Record<OrgSellerSection, ReactElement> = {\n profile: (\n <Stack spacing={2}>\n <CardDisplay\n header={'Public profile'}\n help={pluginDocsHelp('publisherHandbook', {\n anchor: '#public-profile',\n })}\n contentGutterX\n contentGutterY\n >\n <Stack spacing={2}>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Shown on every component you publish to the marketplace. A ' +\n 'profile is required before publishing.'}\n </Typography>\n <TextField\n label=\"Handle\"\n value={handle}\n onChange={(event) => setHandle(event.target.value.toLowerCase())}\n size=\"small\"\n error={Boolean(handle) && !validHandle}\n helperText={\n Boolean(handle) && !validHandle\n ? '3–30 chars: lowercase letters, digits, dashes'\n : ' '\n }\n />\n <TextField\n label=\"Display name\"\n value={displayName}\n onChange={(event) => setDisplayName(event.target.value)}\n size=\"small\"\n />\n <TextField\n label=\"Bio\"\n value={bio}\n onChange={(event) => setBio(event.target.value)}\n size=\"small\"\n multiline\n minRows={2}\n />\n {/* Logo (AGL-1009): picked from the media library like every\n other image the console chooses — never a pasted URL. */}\n {/* What to bring, said before the upload (AGL-2486). */}\n <Typography variant=\"caption\" color=\"text.secondary\" component=\"div\">\n {LISTING_LOGO_HINT}\n </Typography>\n <Stack direction=\"row\" spacing={2} sx={{ alignItems: 'center' }}>\n <Avatar\n src={avatarUrl || undefined}\n alt={displayName || 'Publisher logo'}\n sx={{ width: 56, height: 56 }}\n variant=\"rounded\"\n >\n {(displayName || handle || '?').slice(0, 1).toUpperCase()}\n </Avatar>\n <Stack direction=\"row\" spacing={1}>\n <Button size=\"small\" onClick={chooseLogo}>\n {avatarUrl ? 'Replace logo' : 'Choose logo from library'}\n </Button>\n {avatarUrl ? (\n <Button\n size=\"small\"\n color=\"error\"\n onClick={() => setAvatarUrl('')}\n >\n {'Remove'}\n </Button>\n ) : null}\n </Stack>\n </Stack>\n {/* Support contact (AGL-1009): buyers of a paid plugin need\n somewhere to go, and a reviewer needs it more. */}\n <TextField\n label=\"Support email\"\n value={supportEmail}\n onChange={(event) => setSupportEmail(event.target.value)}\n size=\"small\"\n type=\"email\"\n />\n <TextField\n label=\"Support URL\"\n value={supportUrl}\n onChange={(event) => setSupportUrl(event.target.value)}\n size=\"small\"\n helperText=\"Where buyers go for help with your plugins — https:// only\"\n />\n <TextField\n label=\"Website\"\n value={website}\n onChange={(event) => setWebsite(event.target.value)}\n size=\"small\"\n helperText=\"Your own site, linked from your publisher page — https:// only\"\n />\n {/* Fixed social set (AGL-1009): the storefront renders these as\n icons, so it is a known trio rather than a free-form list. */}\n <TextField\n label=\"GitHub\"\n value={githubUrl}\n onChange={(event) => setGithubUrl(event.target.value)}\n size=\"small\"\n helperText=\"https://github.com/…\"\n />\n <TextField\n label=\"X\"\n value={xUrl}\n onChange={(event) => setXUrl(event.target.value)}\n size=\"small\"\n helperText=\"https://x.com/…\"\n />\n <TextField\n label=\"LinkedIn\"\n value={linkedinUrl}\n onChange={(event) => setLinkedinUrl(event.target.value)}\n size=\"small\"\n helperText=\"https://linkedin.com/…\"\n />\n {/* Directly above Save profile (AGL-4105), which waits for it. */}\n <PublisherAgreementCheckbox\n checked={profileAgreement.agreed}\n onChange={profileAgreement.setAgreed}\n disabled={profileBusy || !canEditProfile}\n />\n <Button\n variant=\"contained\"\n color=\"primary\"\n disabled={\n profileBusy ||\n !canEditProfile ||\n !validHandle ||\n !displayName.trim() ||\n !profileAgreement.agreed\n }\n onClick={handleSave}\n >\n {profileBusy ? 'Saving…' : 'Save profile'}\n </Button>\n {/* Why Save is off, named (AGL-4047). */}\n {canEditProfile ? null : (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {marketplacePublisherPermissionRefusal(\n MARKETPLACE_PUBLISHER_PROFILE_PERMISSION,\n )}\n </Typography>\n )}\n </Stack>\n </CardDisplay>\n\n {/* The publisher agreement (AGL-1077). Agreed to on every save since\n AGL-4105 — the box above Save profile, above each listing's save,\n above every Publish — so this card says what the terms are and\n when the organization last agreed, and asks for nothing itself. */}\n <CardDisplay\n header={PUBLISHER_AGREEMENT_TITLE}\n help={pluginDocsHelp('publisherHandbook', {\n anchor: '#the-publisher-agreement',\n excerpt:\n 'The terms your organization publishes under — agreed to on ' +\n 'every save in the marketplace.',\n })}\n contentGutterX\n contentGutterY\n >\n <Stack spacing={2}>\n {/* An unpublished document replaces the rest (AGL-1660): while\n there is no page to read there is nothing to agree to, and the\n omission is entirely ours. */}\n {agreementPresentation.unavailableNotice ? (\n <Alert severity=\"warning\">\n {agreementPresentation.unavailableNotice}\n </Alert>\n ) : (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Every save in the marketplace — this profile, a listing, its ' +\n 'price or visibility, a new version, a component, template ' +\n `or layout — asks you to tick “I agree to the ${PUBLISHER_AGREEMENT_TITLE}” ` +\n 'first. We record who agreed, to which version, and when.'}\n </Typography>\n )}\n {agreementState === 'none' ? null : (\n <Typography variant=\"body2\">\n {`Last agreed to: version ${profile?.publisherAgreement?.version}` +\n (acceptedOn ? `, on ${acceptedOn}` : '') +\n (agreementState === 'outdated'\n ? `. The current version is ${PUBLISHER_AGREEMENT_VERSION}, ` +\n 'which your next save agrees to.'\n : '.')}\n </Typography>\n )}\n {/* The summary and the link, from the same presentation helper the\n box reads, so this card can never link an unreadable document. */}\n <PublisherAgreementSummary\n documentUrl={agreementPresentation.documentUrl}\n />\n </Stack>\n </CardDisplay>\n </Stack>\n ),\n listings: (\n <CardDisplay\n header={'Your listings'}\n help={pluginDocsHelp('publisherHandbook', { anchor: '#your-listings' })}\n contentGutterX\n contentGutterY\n >\n {(listings ?? []).length === 0 ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Publish a reusable component from a site’s Setup page to list ' +\n 'it here.'}\n </Typography>\n ) : (\n <Stack spacing={1}>\n {/* Why a row's Edit, visibility and Unpublish are off, named\n (AGL-4047). */}\n {canManageListings ? null : (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {marketplacePublisherPermissionRefusal(\n MARKETPLACE_MANAGE_LISTINGS_PERMISSION,\n )}\n </Typography>\n )}\n {/* Private plugins are invisible in Browse by design (AGL-993),\n which makes this the only door to them — say so, or a\n publisher looking for the one they just uploaded will hunt\n for it in the marketplace grid. */}\n {(listings ?? []).some(\n (listing: any) => listing.visibility === 'private',\n ) ? (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {'Private plugins never appear in the marketplace — open one ' +\n 'with View to install it on your sites.'}\n </Typography>\n ) : null}\n {(listings ?? []).map((listing: any) => (\n <Stack\n key={listing.$id}\n direction=\"row\"\n spacing={1}\n sx={{\n alignItems: 'center',\n // The whole row is the way in (AGL-999) — the name and its\n // metadata are what you aim at, so they should behave like\n // the link they read as.\n borderRadius: 1,\n mx: -1,\n px: 1,\n '&:hover': { bgcolor: 'action.hover' },\n }}\n >\n <Stack\n onClick={() => router.push(listingHref(listing))}\n sx={{\n flex: 1,\n minWidth: 0,\n py: 0.75,\n cursor: 'pointer',\n }}\n >\n <Stack\n direction=\"row\"\n spacing={1}\n sx={{ alignItems: 'center', minWidth: 0 }}\n >\n <Typography variant=\"body2\" noWrap>\n {listing.displayName}\n </Typography>\n {/* This tab is the ONLY place a private listing appears\n (AGL-993 keeps it out of browse), so the row has to\n say which of the two things it is. */}\n {listing.visibility === 'private' ? (\n <Chip size=\"small\" variant=\"outlined\" label=\"Private\" />\n ) : null}\n </Stack>\n <Typography variant=\"caption\" color=\"text.secondary\">\n {`v${listing.latestVersion}` +\n (Number(listing.priceUsd ?? 0) > 0\n ? ` · $${listing.priceUsd}`\n : ' · free') +\n (listing.previewImageUrl ? ' · has preview' : '') +\n (listing.deletedAt ? ' · unpublished' : '')}\n </Typography>\n </Stack>\n {/* View what a buyer sees (AGL-988). The one action that\n stays visible (AGL-999): every other row action is either\n rare or destructive, and flattening them all out made the\n columns jump between rows — the action count varies by\n artifact type — while putting Unpublish at the end of the\n row, the easiest place to hit by mistake. */}\n <AppLink\n href={listingHref(listing)}\n newTab\n aria-label={`View ${listing.displayName}`}\n >\n <Button size=\"small\" color=\"primary\" component=\"span\">\n {'View'}\n </Button>\n </AppLink>\n <IconButton\n size=\"small\"\n aria-label={`More actions for ${listing.displayName}`}\n onClick={(event) =>\n setRowMenu({\n anchor: event.currentTarget,\n listing,\n })\n }\n >\n <MdiIcon path={mdiDotsVertical.path} fontSize=\"small\" />\n </IconButton>\n </Stack>\n ))}\n </Stack>\n )}\n {/* One menu for every row (AGL-999) — the open row is state, not a\n mounted <Menu> per listing. */}\n <Menu\n anchorEl={rowMenu?.anchor ?? null}\n open={Boolean(rowMenu)}\n onClose={closeRowMenu}\n >\n {/* Plugins only: bytes are the thing being shipped, and only a\n plugin listing has a bundle (AGL-1008). */}\n {(rowMenu?.listing?.artifactType ?? rowMenu?.listing?.type) ===\n 'plugin' ? (\n <MenuItem\n onClick={() => {\n const listing = rowMenu?.listing\n closeRowMenu()\n if (listing) router.push(newVersionHref(listing))\n }}\n >\n {'Publish new version…'}\n </MenuItem>\n ) : null}\n <MenuItem\n disabled={!canManageListings}\n onClick={() => {\n setEditListing(rowMenu?.listing ?? null)\n closeRowMenu()\n }}\n >\n {'Edit listing'}\n </MenuItem>\n {/* Plugins only (AGL-994). `visibility` is enforced in\n `install-plugin`; the component/layout/template install routes\n have no such check, so offering the switch there would promise\n a boundary that does not exist. */}\n {(rowMenu?.listing?.artifactType ?? rowMenu?.listing?.type) ===\n 'plugin' ? (\n <MenuItem\n disabled={!canManageListings}\n onClick={() => {\n const listing = rowMenu?.listing\n closeRowMenu()\n if (listing) setListingChange({ kind: 'visibility', listing })\n }}\n >\n {rowMenu?.listing?.visibility === 'private'\n ? 'Make public…'\n : 'Make private…'}\n </MenuItem>\n ) : null}\n <Divider />\n <MenuItem\n disabled={!canManageListings}\n sx={{\n color: rowMenu?.listing?.deletedAt ? undefined : 'error.main',\n }}\n onClick={() => {\n const listing = rowMenu?.listing\n closeRowMenu()\n if (listing) setListingChange({ kind: 'published', listing })\n }}\n >\n {rowMenu?.listing?.deletedAt ? 'Republish…' : 'Unpublish…'}\n </MenuItem>\n </Menu>\n <PublisherAgreementConfirmDialog\n open={Boolean(listingChange)}\n title={listingChangeCopy.title}\n body={listingChangeCopy.body}\n confirmLabel={listingChangeCopy.confirmLabel}\n destructive={listingChangeCopy.destructive}\n onConfirm={(agreement) =>\n listingChange\n ? changeListing(listingChange, agreement)\n : Promise.resolve(null)\n }\n onClose={() => setListingChange(null)}\n />\n <EditListingDialog\n orgId={orgId}\n listing={editListing}\n open={Boolean(editListing)}\n onClose={() => setEditListing(null)}\n user={user}\n />\n </CardDisplay>\n ),\n payouts: (\n <CardDisplay\n header={'Payouts'}\n help={pluginDocsHelp('publisherHandbook', {\n anchor: '#set-up-payouts',\n })}\n contentGutterX\n contentGutterY\n >\n <Stack spacing={2}>\n {payoutsState === 'error' ? (\n // Neither sentence is safe here: \"Payouts are enabled\" and\n // \"Connect a Stripe account\" both state a payout arrangement we\n // failed to read, and the button under them acts on it.\n <Alert\n severity=\"error\"\n action={\n <Button\n color=\"inherit\"\n size=\"small\"\n onClick={() => setProfileRetryNonce((n) => n + 1)}\n >\n {'Retry'}\n </Button>\n }\n >\n {'We couldn’t load your payout setup. This says nothing about ' +\n 'whether payouts are on — nothing has changed.'}\n </Alert>\n ) : payoutsState === 'pending' ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Checking your payout setup…'}\n </Typography>\n ) : (\n <>\n {/* The charges-yes/payouts-no state (AGL-1997), which used to\n render as unqualified success. Stripe will let this account\n take money and will not let it out yet, so the honest thing\n is to say both halves — a publisher who reads \"enabled\" and\n sells has no reason to go finish verification. */}\n {readiness === 'blocked' ? (\n <Alert severity=\"warning\">\n {'Your Stripe account can take payments, but payouts are ' +\n 'not enabled yet — sales would stay in Stripe rather ' +\n 'than reaching your bank. Finish verification in Stripe ' +\n 'to release them.'}\n </Alert>\n ) : null}\n {/* AGL-2471. The connected account was never verified against\n this deployment's Stripe mode, and the sale gate refuses it\n — so the card must not imply the account works. Saying it\n plainly, with the one action that fixes it, is the whole\n difference between this and a storefront that looks ready\n and cannot take a payment. */}\n {readiness === 'unverified' ? (\n <Alert severity=\"error\">\n {'This Stripe account has not been verified for payments ' +\n 'here, so sales will be refused. Reconnect it to ' +\n 'confirm — if it was set up against Stripe test mode, ' +\n 'you will need to connect a live account.'}\n </Alert>\n ) : null}\n <Typography variant=\"body2\" color=\"text.secondary\">\n {readiness === 'ready'\n ? 'Payouts are enabled — paid listings transfer to your ' +\n 'Stripe account automatically (platform fee 20%, 30% on ' +\n 'the Free plan).'\n : readiness === 'unknown'\n ? // Connected, payout readiness unread. Says only what is\n // known, like the error branch above.\n 'Your Stripe account is connected. We haven’t checked ' +\n 'whether payouts are released yet — recheck to ' +\n 'confirm. The platform fee is 20% per sale (30% on ' +\n 'the Free plan).'\n : readiness === 'blocked' || readiness === 'unverified'\n ? 'The platform fee is 20% per sale (30% on the Free ' +\n 'plan).'\n : 'Connect a Stripe account to sell components. The ' +\n 'platform fee is 20% per sale (30% on the Free plan).'}\n </Typography>\n <Button\n variant={chargesEnabled ? 'outlined' : 'contained'}\n color=\"primary\"\n disabled={payoutsBusy || !canManagePayouts}\n onClick={handlePayouts}\n >\n {payoutsBusy\n ? 'Opening Stripe…'\n : readiness === 'ready'\n ? 'Payouts enabled — recheck status'\n : readiness === 'blocked'\n ? 'Finish payout setup in Stripe'\n : readiness === 'unverified'\n ? 'Reconnect Stripe to verify'\n : readiness === 'unknown'\n ? 'Recheck payout status'\n : 'Set up payouts'}\n </Button>\n {/* Why the payout button is off, named (AGL-4047). */}\n {canManagePayouts ? null : (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {marketplacePublisherPermissionRefusal(\n MARKETPLACE_PAYOUTS_PERMISSION,\n )}\n </Typography>\n )}\n {/*\n Where the money actually is. Aglyn records no\n balance, no payout schedule, and handles no `payout.failed`\n event, so a publisher whose payout bounced cannot learn that\n here. An Express account has no direct login, which leaves a\n platform-minted link as the only route in.\n */}\n {dashboardUrl ? (\n <Button\n variant=\"text\"\n color=\"primary\"\n href={dashboardUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {'View payouts in Stripe'}\n </Button>\n ) : null}\n </>\n )}\n </Stack>\n </CardDisplay>\n ),\n sales: (\n <CardDisplay\n header={'Sales'}\n help={pluginDocsHelp('publishAPlugin', {\n anchor: '#paid-listings',\n excerpt:\n 'Sent to your Stripe account is your share after the platform ' +\n `fee — sales tax is collected on ${PLATFORM_BRAND_LEGAL_NAME}’s ` +\n 'registration and is never yours.',\n })}\n contentGutterX\n contentGutterY\n >\n {(sales ?? []).length === 0 ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'No sales yet. Paid listings appear here with what buyers paid ' +\n 'and what was paid out to you.'}\n </Typography>\n ) : (\n <Stack spacing={0.5}>\n <Typography variant=\"body2\">\n {`${totals.paidCount} sale${totals.paidCount === 1 ? '' : 's'}`}\n {totals.refundedCount > 0\n ? ` · ${totals.refundedCount} refunded or charged back`\n : ''}\n </Typography>\n {/*\n The payout FIRST, and named for what it is. It is the number a\n publisher reconciles against their Stripe account, and it is the\n one this card used to get wrong.\n\n \"Sent to your Stripe account\", not \"net paid out\".\n The figure sums `transferCents` — the instruction given at charge\n time — so it says the money was DISPATCHED and knows nothing\n about whether the payout from that balance to a bank succeeded.\n A publisher reading \"net paid out\" during a failed payout was\n told their money had landed by the one surface that should have\n warned them. The notice below carries the arrival.\n */}\n <Typography variant=\"body2\">\n {`Sent to your Stripe account $${(\n totals.sentToStripeCents / 100\n ).toFixed(2)}`}\n </Typography>\n {/*\n WHERE IT STOPPED, when it stopped. Mirrored onto the publisher\n profile by the `payout.failed` handler, and retired by the next\n successful payout — so this is a live problem, not a scar.\n */}\n {profile?.lastPayoutFailureAtMs ? (\n <Alert severity=\"warning\" variant=\"outlined\">\n {`A payout of $${(\n Number(profile.lastPayoutFailureCents ?? 0) / 100\n ).toFixed(2)} did not reach your bank on ${new Date(\n Number(profile.lastPayoutFailureAtMs),\n ).toLocaleDateString()} — ${String(\n profile.lastPayoutFailureReason ?? 'Stripe did not say why',\n )} The money is still in your Stripe account. Open Stripe to fix your payout details.`}\n </Alert>\n ) : null}\n <Typography variant=\"body2\" color=\"text.secondary\">\n {`Buyers paid $${(totals.buyersPaidCents / 100).toFixed(2)} · ` +\n `sales tax $${(totals.salesTaxCents / 100).toFixed(2)} · ` +\n `platform fee $${(totals.platformFeeCents / 100).toFixed(2)}`}\n </Typography>\n {totals.refundedCount > 0 ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {`$${(totals.returnedCents / 100).toFixed(2)} returned on refunded ` +\n 'and charged-back sales, and excluded above'}\n </Typography>\n ) : null}\n {/*\n THE COPY THAT LANDS WITH THE SMALLER NUMBER. A publisher who\n read `net $88.25` yesterday and reads `net paid out $80.00`\n today is owed the reason on the same card, not in a changelog.\n */}\n <Typography variant=\"caption\" color=\"text.secondary\">\n {'Sent to your Stripe account is the pre-tax price less the ' +\n 'platform fee. Sales tax is collected and remitted by ' +\n `${PLATFORM_BRAND_LEGAL_NAME} under its marketplace-provider ` +\n 'registration and was never part of your share. Reaching ' +\n 'your Stripe balance is not the same as reaching your bank — ' +\n 'a failed payout is called out above.'}\n </Typography>\n </Stack>\n )}\n </CardDisplay>\n ),\n }\n\n return cards[section]\n}\nOrgSellerPanel.displayName = 'OrgSellerPanel'\n\nexport default OrgSellerPanel\n"],"names":["trackEvent","mdiDotsVertical","AppLink","CardDisplay","MdiIcon","useSnackbar","Alert","Avatar","Button","Chip","Divider","IconButton","Menu","MenuItem","Stack","TextField","Typography","PUBLISHER_AGREEMENT_TITLE","PUBLISHER_AGREEMENT_VERSION","publisherAgreementPresentation","publisherAgreementState","PLATFORM_BRAND_LEGAL_NAME","LISTING_LOGO_HINT","MARKETPLACE_MANAGE_LISTINGS_PERMISSION","MARKETPLACE_PAYOUTS_PERMISSION","MARKETPLACE_PUBLISHER_PROFILE_PERMISSION","marketplacePublisherPermissionRefusal","useRouter","collection","doc","query","where","useCallback","useEffect","useState","useFirestore","useUser","authorizedFetch","pluginDocsHelp","useMediaPicker","useFirestoreCollection","useFirestoreDoc","EditListingDialog","PublisherAgreementCheckbox","usePublisherAgreementConsent","PublisherAgreementConfirmDialog","PublisherAgreementSummary","listingPath","publishPluginPath","payoutReadiness","summarizeSellerLedger","HANDLE_PATTERN","OrgSellerPanel","props","profile","rowMenu","orgId","section","basePath","permissions","canEditProfile","canManageListings","canManagePayouts","router","firestore","data","user","enqueueSnackbar","profileRetryNonce","setProfileRetryNonce","status","profileStatus","idField","payoutsState","readiness","state","chargesEnabled","stripeChargesEnabled","payoutsEnabled","stripePayoutsEnabled","accountLivemode","stripeAccountLivemode","listings","sales","totals","payoutsBusy","setPayoutsBusy","dashboardUrl","setDashboardUrl","handlePayouts","response","method","headers","body","JSON","stringify","payload","json","variant","persist","ok","error","allowDuplicate","url","window","location","assign","console","handle","setHandle","displayName","setDisplayName","bio","setBio","avatarUrl","setAvatarUrl","pickMedia","chooseLogo","picked","kind","website","setWebsite","supportEmail","setSupportEmail","supportUrl","setSupportUrl","githubUrl","setGithubUrl","xUrl","setXUrl","linkedinUrl","setLinkedinUrl","validHandle","test","profileAgreement","profileBusy","setProfileBusy","handleSave","trim","consent","agreement","catch","reset","agreementState","publisherAgreement","agreementPresentation","acceptedOn","at","acceptedAt","date","toDate","toLocaleDateString","editListing","setEditListing","setRowMenu","closeRowMenu","listingHref","listing","$id","newVersionHref","listingChange","setListingChange","changeListing","change","nextVisibility","visibility","action","listingId","published","Boolean","deletedAt","String","listingChangeCopy","name","title","confirmLabel","destructive","cards","spacing","header","help","anchor","contentGutterX","contentGutterY","color","label","value","onChange","event","target","toLowerCase","size","helperText","multiline","minRows","component","direction","sx","alignItems","src","undefined","alt","width","height","slice","toUpperCase","onClick","type","checked","agreed","setAgreed","disabled","excerpt","unavailableNotice","severity","version","documentUrl","length","some","map","borderRadius","mx","px","bgcolor","push","flex","minWidth","py","cursor","noWrap","latestVersion","Number","priceUsd","previewImageUrl","href","newTab","aria-label","currentTarget","path","fontSize","anchorEl","open","onClose","artifactType","onConfirm","Promise","resolve","payouts","n","rel","paidCount","refundedCount","sentToStripeCents","toFixed","lastPayoutFailureAtMs","lastPayoutFailureCents","Date","lastPayoutFailureReason","buyersPaidCents","salesTaxCents","platformFeeCents","returnedCents"],"mappings":"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"}
@@ -20,6 +20,7 @@ import { pluginDocsHelp } from "@aglyn/aglyn/app-utils/docs-help";
20
20
  import { resolveMediaSrc } from "@aglyn/aglyn/app-utils/media-ref";
21
21
  import { mdiWeb } from "@aglyn/shared-data-mdi";
22
22
  import { OptionCardGrid } from "@aglyn/shared-ui-jsx/components/option-card-grid.component";
23
+ import { BlockedControl } from "@aglyn/shared-ui-jsx/components/blocked-control.component";
23
24
  import { Alert, Box, Button, Link, LinearProgress, Skeleton, Stack } from "@mui/material";
24
25
  import { useEffect, useMemo, useRef, useState } from "react";
25
26
  import { useStarterAnswers } from "../hooks/use-starter-answers.js";
@@ -164,7 +165,7 @@ const narrowed = (filter)=>[
164
165
  * never read: its answers are what it sells, and the door would ask payment
165
166
  * for them. A door that still asks is told back to the dialog as unowned.
166
167
  */ export function StarterPickerShelf(props) {
167
- var _ref, _found_rows_find;
168
+ var _ref, _found_rows_find, _pickedRow_buyBlockedReason, _pickedRow_buyBlockedReason1;
168
169
  const { orgId, orgSlug, mode, search, filter, onPick, ready, selected } = props;
169
170
  // The pick the dialog opened on, restored after paying for it: asked for
170
171
  // by every search from then on, so it is listed (first) wherever the
@@ -379,14 +380,18 @@ const narrowed = (filter)=>[
379
380
  severity: "info",
380
381
  "data-starter-buy": pickedRow.listingId,
381
382
  sx: PICK_NOTE_SX,
382
- action: /*#__PURE__*/ _jsx(Button, {
383
- color: "inherit",
384
- size: "small",
385
- disabled: purchase.busy || !orgId,
386
- onClick: ()=>void buy(pickedRow),
387
- children: purchase.busy ? 'Opening…' : 'Buy and continue'
383
+ action: /*#__PURE__*/ _jsx(BlockedControl, {
384
+ blocked: Boolean(pickedRow.buyBlockedReason),
385
+ reason: (_pickedRow_buyBlockedReason = pickedRow.buyBlockedReason) != null ? _pickedRow_buyBlockedReason : '',
386
+ children: /*#__PURE__*/ _jsx(Button, {
387
+ color: "inherit",
388
+ size: "small",
389
+ disabled: purchase.busy || !orgId,
390
+ onClick: ()=>void buy(pickedRow),
391
+ children: purchase.busy ? 'Opening…' : 'Buy and continue'
392
+ })
388
393
  }),
389
- children: `${pickedRow.displayName || 'This starter'} costs ${starterPriceLabel(pickedRow.priceUsd)}. ` + 'Buy it here, then create your site from it.'
394
+ children: `${pickedRow.displayName || 'This starter'} costs ${starterPriceLabel(pickedRow.priceUsd)}. ` + ((_pickedRow_buyBlockedReason1 = pickedRow.buyBlockedReason) != null ? _pickedRow_buyBlockedReason1 : 'Buy it here, then create your site from it.')
390
395
  }) : null,
391
396
  purchase.error ? /*#__PURE__*/ _jsx(Alert, {
392
397
  severity: "error",