@burdenoff/microfe-devportal 2026.1112.1 → 2026.1113.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/dist/devportal/components/AppCard.js +73 -70
  2. package/dist/devportal/components/AppCard.js.map +1 -1
  3. package/dist/devportal/components/ImageUploadField.js +82 -80
  4. package/dist/devportal/components/ImageUploadField.js.map +1 -1
  5. package/dist/devportal/components/StoreImage.d.ts +15 -0
  6. package/dist/devportal/components/StoreImage.js +30 -0
  7. package/dist/devportal/components/StoreImage.js.map +1 -0
  8. package/dist/devportal/components/index.d.ts +1 -0
  9. package/dist/devportal/components/index.js +17 -16
  10. package/dist/devportal/hooks/usePackageUpload.d.ts +46 -4
  11. package/dist/devportal/hooks/usePackageUpload.js +90 -36
  12. package/dist/devportal/hooks/usePackageUpload.js.map +1 -1
  13. package/dist/devportal/pages/AdminReviewPage.js +205 -202
  14. package/dist/devportal/pages/AdminReviewPage.js.map +1 -1
  15. package/dist/devportal/pages/ApplicationDetailPage.js +2 -2
  16. package/dist/devportal/pages/ApplicationDetailPage.js.map +1 -1
  17. package/dist/devportal/pages/ApplicationsPage.js +201 -199
  18. package/dist/devportal/pages/ApplicationsPage.js.map +1 -1
  19. package/dist/devportal/pages/CreateOrganizationPage.js +120 -114
  20. package/dist/devportal/pages/CreateOrganizationPage.js.map +1 -1
  21. package/dist/devportal/pages/CreatePhysicalItemPage.js +2 -2
  22. package/dist/devportal/pages/CreatePhysicalItemPage.js.map +1 -1
  23. package/dist/devportal/pages/EditApplicationPage.js +84 -73
  24. package/dist/devportal/pages/EditApplicationPage.js.map +1 -1
  25. package/dist/devportal/pages/EditPhysicalItemPage.js +312 -307
  26. package/dist/devportal/pages/EditPhysicalItemPage.js.map +1 -1
  27. package/dist/devportal/pages/ListingPreviewPage.js +175 -171
  28. package/dist/devportal/pages/ListingPreviewPage.js.map +1 -1
  29. package/dist/devportal/pages/OAuthClientDetailPage.js +134 -115
  30. package/dist/devportal/pages/OAuthClientDetailPage.js.map +1 -1
  31. package/dist/devportal/pages/SellerDashboardPage.js +118 -116
  32. package/dist/devportal/pages/SellerDashboardPage.js.map +1 -1
  33. package/dist/devportal/pages/SellerItemsPage.js +202 -199
  34. package/dist/devportal/pages/SellerItemsPage.js.map +1 -1
  35. package/dist/devportal/pages/SetupPage.js +141 -143
  36. package/dist/devportal/pages/SetupPage.js.map +1 -1
  37. package/dist/devportal/pages/StoreSubmissionPage.js +133 -131
  38. package/dist/devportal/pages/StoreSubmissionPage.js.map +1 -1
  39. package/dist/devportal/utils/errorMessage.d.ts +2 -0
  40. package/dist/devportal/utils/errorMessage.js +7 -0
  41. package/dist/devportal/utils/errorMessage.js.map +1 -0
  42. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"CreatePhysicalItemPage.js","names":["_Fragment","PRODUCT_CATEGORIES","STORE_CATEGORIES","CURRENCIES","WEIGHT_UNITS","DIMENSION_UNITS","REQUIRED_FIELDS","MY_PUBLISHER_QUERY","REGISTER_PUBLISHER_MUTATION","CREATE_PHYSICAL_PRODUCT_MUTATION","SUBMIT_PRODUCT_MUTATION","deriveSlug","name","isFormValid","value","form","field","CreatePhysicalItemPage","useDevportal","sellerOrganization","sellerOrganizations","sellerOrgLoading","sellerOrgError","useSellerOrganization","setForm","useState","icon","setIcon","bannerUrl","setBannerUrl","screenshots","setScreenshots","uploadIcon","iconUploading","iconProgress","iconUploadError","usePackageUpload","workspacesGatewayUrl","authToken","workspaceId","getWorkspaceToken","uploadBanner","bannerUploading","bannerProgress","bannerUploadError","uploadScreenshot","screenshotUploading","screenshotProgress","screenshotUploadError","submitting","setSubmitting","submitError","setSubmitError","submitSuccess","setSubmitSuccess","imagesUploading","isValid","endpoint","resolveGlobalGraphqlEndpoint","apiGatewayUrl","setField","prev","key","handleNameChange","handleCheckboxChange","e","gqlFetch","json","PageLayout","PageSection","SelectField","selectOrganization","org","InputField","TextareaField","ImageUploadField","ScreenshotGallery","CheckboxField","Fragment","Info","navigate","basePath","publisherId","parsedTags","t","hasDimensions","newProductId","productId","err","cn","Loader2"],"sources":["../../../src/devportal/pages/CreatePhysicalItemPage.tsx"],"sourcesContent":["import type { FC, ChangeEvent } from \"react\";\nimport { useState } from \"react\";\nimport { Loader2, Info } from \"lucide-react\";\nimport { PageLayout, PageSection } from \"../components/PageLayout\";\nimport {\n InputField,\n TextareaField,\n SelectField,\n CheckboxField,\n} from \"../components/FormField\";\nimport {\n ImageUploadField,\n ScreenshotGallery,\n} from \"../components/ImageUploadField\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport { useSellerOrganization } from \"../hooks/useSellerOrganization\";\nimport { usePackageUpload } from \"../hooks/usePackageUpload\";\nimport { cn } from \"../utils/cn\";\nimport { resolveGlobalGraphqlEndpoint } from \"../utils/graphqlEndpoint\";\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\ninterface FormState {\n name: string;\n slug: string;\n type: string;\n category: string;\n shortDescription: string;\n longDescription: string;\n price: string;\n currency: string;\n tags: string;\n stockQuantity: string;\n sku: string;\n trackInventory: boolean;\n allowBackorder: boolean;\n lowStockThreshold: string;\n requiresShipping: boolean;\n weightKg: string;\n weightUnit: string;\n length: string;\n width: string;\n height: string;\n dimensionUnit: string;\n brand: string;\n manufacturer: string;\n countryOfOrigin: string;\n warrantyInfo: string;\n returnPolicy: string;\n}\n\n// ─── Constants ────────────────────────────────────────────────────────────────\n\nconst PRODUCT_CATEGORIES = [\n { value: \"MERCHANDISE\", label: \"Merchandise\" },\n { value: \"HARDWARE\", label: \"Hardware\" },\n { value: \"ACCESSORY\", label: \"Accessory\" },\n { value: \"BOOK\", label: \"Book\" },\n { value: \"EQUIPMENT\", label: \"Equipment\" },\n { value: \"APPAREL\", label: \"Apparel\" },\n { value: \"COLLECTIBLE\", label: \"Collectible\" },\n { value: \"CONSUMABLE\", label: \"Consumable\" },\n];\n\n// Store category (the product `category` string, distinct from the ProductType above).\n// The five `agri-` slugs are the HealthyBowl Agri-Inputs Store discriminator: picking one lists\n// the item in that farmer-facing storefront (roadmap #26). Leave blank for general listings.\nconst STORE_CATEGORIES = [\n { value: \"agri-seeds\", label: \"Agri-Inputs — Seeds\" },\n { value: \"agri-fertilizer\", label: \"Agri-Inputs — Organic Fertilizer\" },\n { value: \"agri-biopesticide\", label: \"Agri-Inputs — Bio-Pesticides\" },\n { value: \"agri-tools\", label: \"Agri-Inputs — Tools\" },\n { value: \"agri-irrigation\", label: \"Agri-Inputs — Irrigation\" },\n];\n\nconst CURRENCIES = [\n { value: \"USD\", label: \"USD — US Dollar\" },\n { value: \"INR\", label: \"INR — Indian Rupee\" },\n { value: \"EUR\", label: \"EUR — Euro\" },\n { value: \"GBP\", label: \"GBP — British Pound\" },\n { value: \"SGD\", label: \"SGD — Singapore Dollar\" },\n { value: \"AED\", label: \"AED — UAE Dirham\" },\n];\n\nconst WEIGHT_UNITS = [\n { value: \"GRAM\", label: \"Grams (g)\" },\n { value: \"KILOGRAM\", label: \"Kilograms (kg)\" },\n { value: \"OUNCE\", label: \"Ounces (oz)\" },\n { value: \"POUND\", label: \"Pounds (lb)\" },\n];\n\nconst DIMENSION_UNITS = [\n { value: \"CENTIMETER\", label: \"Centimeters (cm)\" },\n { value: \"INCH\", label: \"Inches (in)\" },\n { value: \"METER\", label: \"Meters (m)\" },\n];\n\nconst REQUIRED_FIELDS: (keyof FormState)[] = [\n \"name\",\n \"slug\",\n \"type\",\n \"shortDescription\",\n \"price\",\n \"currency\",\n \"stockQuantity\",\n];\n\n// ─── GraphQL strings ──────────────────────────────────────────────────────────\n\nconst MY_PUBLISHER_QUERY = /* GraphQL */ `\n query SellerMyPublisher {\n myPublisher {\n id\n }\n }\n`;\n\nconst REGISTER_PUBLISHER_MUTATION = /* GraphQL */ `\n mutation RegisterPublisher($input: RegisterPublisherInput!) {\n registerPublisher(input: $input) {\n id\n name\n email\n }\n }\n`;\n\nconst CREATE_PHYSICAL_PRODUCT_MUTATION = /* GraphQL */ `\n mutation CreatePhysicalProduct($input: CreatePhysicalProductInput!) {\n createPhysicalProduct(input: $input) {\n id\n name\n slug\n status\n nature\n type\n price\n currency\n icon\n bannerUrl\n screenshots\n }\n }\n`;\n\nconst SUBMIT_PRODUCT_MUTATION = /* GraphQL */ `\n mutation SubmitProduct($id: ID!, $notes: String) {\n submitProduct(id: $id, notes: $notes) {\n id\n status\n }\n }\n`;\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction deriveSlug(name: string): string {\n return name.toLowerCase().replace(/[^a-z0-9]+/g, \"-\");\n}\n\nfunction isFormValid(form: FormState): boolean {\n return REQUIRED_FIELDS.every((field) => {\n const value = form[field];\n if (typeof value === \"boolean\") return true;\n return value.trim() !== \"\";\n });\n}\n\n// ─── Component ────────────────────────────────────────────────────────────────\n\nexport const CreatePhysicalItemPage: FC = () => {\n const {\n navigate,\n basePath,\n productId,\n apiGatewayUrl,\n authToken,\n workspacesGatewayUrl,\n workspaceId,\n getWorkspaceToken,\n } = useDevportal();\n const {\n organization: sellerOrganization,\n organizations: sellerOrganizations,\n loading: sellerOrgLoading,\n error: sellerOrgError,\n selectOrganization,\n } = useSellerOrganization();\n\n const [form, setForm] = useState<FormState>({\n name: \"\",\n slug: \"\",\n type: \"\",\n category: \"\",\n shortDescription: \"\",\n longDescription: \"\",\n price: \"\",\n currency: \"\",\n tags: \"\",\n stockQuantity: \"1\",\n sku: \"\",\n trackInventory: true,\n allowBackorder: false,\n lowStockThreshold: \"\",\n requiresShipping: true,\n weightKg: \"\",\n weightUnit: \"KILOGRAM\",\n length: \"\",\n width: \"\",\n height: \"\",\n dimensionUnit: \"CENTIMETER\",\n brand: \"\",\n manufacturer: \"\",\n countryOfOrigin: \"\",\n warrantyInfo: \"\",\n returnPolicy: \"\",\n });\n\n const [icon, setIcon] = useState(\"\");\n const [bannerUrl, setBannerUrl] = useState(\"\");\n const [screenshots, setScreenshots] = useState<string[]>([]);\n const {\n upload: uploadIcon,\n uploading: iconUploading,\n progress: iconProgress,\n error: iconUploadError,\n } = usePackageUpload(\n workspacesGatewayUrl,\n authToken,\n workspaceId,\n getWorkspaceToken,\n \"/DevPortal/Assets\",\n );\n const {\n upload: uploadBanner,\n uploading: bannerUploading,\n progress: bannerProgress,\n error: bannerUploadError,\n } = usePackageUpload(\n workspacesGatewayUrl,\n authToken,\n workspaceId,\n getWorkspaceToken,\n \"/DevPortal/Assets\",\n );\n const {\n upload: uploadScreenshot,\n uploading: screenshotUploading,\n progress: screenshotProgress,\n error: screenshotUploadError,\n } = usePackageUpload(\n workspacesGatewayUrl,\n authToken,\n workspaceId,\n getWorkspaceToken,\n \"/DevPortal/Assets\",\n );\n\n const [submitting, setSubmitting] = useState(false);\n const [submitError, setSubmitError] = useState<string | null>(null);\n const [submitSuccess, setSubmitSuccess] = useState(false);\n\n const imagesUploading =\n iconUploading || bannerUploading || screenshotUploading;\n const isValid = isFormValid(form) && !!sellerOrganization && !imagesUploading;\n const endpoint = resolveGlobalGraphqlEndpoint(apiGatewayUrl);\n\n // ─── Field helpers ────────────────────────────────────────────────────────\n\n const setField = <K extends keyof FormState>(key: K, value: FormState[K]) => {\n setForm((prev) => ({ ...prev, [key]: value }));\n };\n\n const handleNameChange = (e: ChangeEvent<HTMLInputElement>) => {\n const name = e.target.value;\n setForm((prev) => ({\n ...prev,\n name,\n slug: deriveSlug(name),\n }));\n };\n\n const handleCheckboxChange =\n (key: \"trackInventory\" | \"requiresShipping\" | \"allowBackorder\") =>\n (e: ChangeEvent<HTMLInputElement>) => {\n setField(key, e.target.checked);\n };\n\n // ─── GraphQL fetch helper ─────────────────────────────────────────────────\n\n async function gqlFetch<T = unknown>(\n query: string,\n variables?: Record<string, unknown>,\n ): Promise<T> {\n const res = await fetch(endpoint, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...(authToken ? { Authorization: `Bearer ${authToken}` } : {}),\n },\n credentials: \"include\",\n body: JSON.stringify({ query, variables }),\n });\n const json = (await res.json()) as {\n data?: T;\n errors?: { message: string }[];\n };\n if (json.errors?.length) {\n throw new Error(json.errors.map((e) => e.message).join(\"; \"));\n }\n return json.data as T;\n }\n\n // ─── Submit flow ──────────────────────────────────────────────────────────\n\n const handleSubmit = async () => {\n if (!isValid || submitting || !sellerOrganization) return;\n setSubmitting(true);\n setSubmitError(null);\n\n try {\n // Step 1: check if publisher exists\n const publisherData = await gqlFetch<{\n myPublisher: { id: string } | null;\n }>(MY_PUBLISHER_QUERY);\n\n let publisherId = publisherData.myPublisher?.id ?? null;\n\n if (!publisherId) {\n const registerData = await gqlFetch<{\n registerPublisher: { id: string };\n }>(REGISTER_PUBLISHER_MUTATION, {\n input: {\n name: sellerOrganization.legalEntityName ?? sellerOrganization.name,\n email: sellerOrganization.contactEmail ?? \"seller@burdenoff.com\",\n websiteUrl: sellerOrganization.websiteUrl ?? null,\n legalName:\n sellerOrganization.legalEntityName ?? sellerOrganization.name,\n country: sellerOrganization.taxCountry ?? null,\n contactEmail: sellerOrganization.contactEmail ?? null,\n },\n });\n\n publisherId = registerData.registerPublisher.id;\n }\n\n // Step 2: create the product, linked to the seller's PHYSICAL org —\n // validated server-side (createPhysicalProduct rejects any org that\n // isn't PHYSICAL-kind, see DeveloperOrgKind / BOFF-7285).\n const parsedTags = form.tags\n .split(\",\")\n .map((t) => t.trim())\n .filter(Boolean);\n\n const hasDimensions =\n form.length.trim() || form.width.trim() || form.height.trim();\n\n const productData = await gqlFetch<{\n createPhysicalProduct: { id: string };\n }>(CREATE_PHYSICAL_PRODUCT_MUTATION, {\n input: {\n name: form.name.trim(),\n slug: form.slug.trim(),\n type: form.type,\n category: form.category.trim() || null,\n description: form.shortDescription.trim(),\n longDescription: form.longDescription.trim() || null,\n price: parseFloat(form.price),\n currency: form.currency,\n tags: parsedTags.length > 0 ? parsedTags : null,\n stockQuantity: parseInt(form.stockQuantity, 10),\n sku: form.sku.trim() || null,\n trackInventory: form.trackInventory,\n allowBackorder: form.allowBackorder,\n lowStockThreshold: form.lowStockThreshold.trim()\n ? parseInt(form.lowStockThreshold, 10)\n : null,\n requiresShipping: form.requiresShipping,\n weight:\n form.requiresShipping && form.weightKg.trim()\n ? parseFloat(form.weightKg)\n : null,\n weightUnit:\n form.requiresShipping && form.weightKg.trim()\n ? form.weightUnit\n : null,\n length:\n form.requiresShipping && form.length.trim()\n ? parseFloat(form.length)\n : null,\n width:\n form.requiresShipping && form.width.trim()\n ? parseFloat(form.width)\n : null,\n height:\n form.requiresShipping && form.height.trim()\n ? parseFloat(form.height)\n : null,\n dimensionUnit:\n form.requiresShipping && hasDimensions ? form.dimensionUnit : null,\n brand: form.brand.trim() || null,\n manufacturer: form.manufacturer.trim() || null,\n countryOfOrigin: form.countryOfOrigin.trim() || null,\n warrantyInfo: form.warrantyInfo.trim() || null,\n returnPolicy: form.returnPolicy.trim() || null,\n icon: icon || null,\n bannerUrl: bannerUrl || null,\n screenshots: screenshots.length > 0 ? screenshots : null,\n // Tags this listing with the host product (e.g. \"healthybowl\") so\n // it can be filtered to that product's marketplace. Only set when\n // the host shell actually passes a productId — stays exactly as\n // before (no tag) for any shell that doesn't opt in.\n compatibleProducts: productId ? [productId] : null,\n organizationId: sellerOrganization.id,\n },\n });\n\n const newProductId = productData.createPhysicalProduct.id;\n\n // Step 3: submit for review\n await gqlFetch(SUBMIT_PRODUCT_MUTATION, {\n id: newProductId,\n notes: \"Submitted from seller portal\",\n });\n\n // Step 4: success\n setSubmitSuccess(true);\n setTimeout(() => {\n navigate?.(`${basePath}/seller/items`);\n }, 2000);\n } catch (err) {\n setSubmitError(\n err instanceof Error\n ? err.message\n : \"Submission failed. Please try again.\",\n );\n } finally {\n setSubmitting(false);\n }\n };\n\n // ─── Render ───────────────────────────────────────────────────────────────\n\n return (\n <PageLayout\n title=\"List a Physical Item\"\n description=\"Fill in all required details. Your listing will be reviewed before it appears in the store.\"\n backLink=\"/seller/items\"\n backLabel=\"Back to My Items\"\n >\n <div className=\"space-y-8 max-w-3xl\">\n {/* Success banner */}\n {submitSuccess && (\n <div className=\"rounded-card border border-status-success-text/30 bg-status-success-bg-subtle px-4 py-3 text-sm text-status-success-text\">\n Your listing has been submitted for review! Redirecting...\n </div>\n )}\n\n {/* Error banner */}\n {submitError && (\n <div className=\"rounded-card border border-status-error-text/30 bg-status-error-bg-subtle px-4 py-3 text-sm text-status-error-text\">\n {submitError}\n </div>\n )}\n\n {/* Seller org resolution error — the form can't be submitted without one */}\n {sellerOrgError && (\n <div className=\"rounded-card border border-status-error-text/30 bg-status-error-bg-subtle px-4 py-3 text-sm text-status-error-text\">\n Couldn't set up your seller organization: {sellerOrgError}\n </div>\n )}\n\n {/* ── Section 0: Seller Organization ── */}\n <PageSection\n title=\"Seller Organization\"\n description=\"The seller organization this item will be listed under.\"\n >\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6 space-y-3\">\n <SelectField\n label=\"Organization\"\n required\n value={sellerOrganization?.id ?? \"\"}\n onChange={(e) => selectOrganization(e.target.value)}\n options={sellerOrganizations.map((org) => ({\n value: org.id,\n label: org.name,\n }))}\n placeholder={\n sellerOrgLoading\n ? \"Resolving your seller organization…\"\n : \"Select an organization\"\n }\n disabled={sellerOrgLoading || sellerOrganizations.length <= 1}\n hint={\n sellerOrganizations.length > 1\n ? \"You have more than one seller organization — pick the one this item belongs to.\"\n : sellerOrganization\n ? `Automatically set to your only seller organization, \"${sellerOrganization.name}\".`\n : undefined\n }\n />\n </div>\n </PageSection>\n\n {/* ── Section 1: Basic Information ── */}\n <PageSection\n title=\"Basic Information\"\n description=\"Core details shown in the store listing.\"\n >\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6 space-y-5\">\n <InputField\n label=\"Name\"\n required\n value={form.name}\n onChange={handleNameChange}\n placeholder=\"e.g. Wireless Ergonomic Keyboard\"\n maxLength={120}\n />\n\n <InputField\n label=\"Slug\"\n required\n value={form.slug}\n onChange={(e) => setField(\"slug\", e.target.value)}\n placeholder=\"auto-derived-from-name\"\n hint=\"URL-friendly identifier. Auto-derived from name; you can edit it.\"\n />\n\n <SelectField\n label=\"Product Type\"\n required\n value={form.type}\n onChange={(e) => setField(\"type\", e.target.value)}\n options={PRODUCT_CATEGORIES}\n placeholder=\"Select a type\"\n />\n\n <SelectField\n label=\"Store Category\"\n value={form.category}\n onChange={(e) => setField(\"category\", e.target.value)}\n options={STORE_CATEGORIES}\n placeholder=\"General / uncategorised\"\n hint=\"Pick an Agri-Inputs category to list this item in the HealthyBowl Agri-Inputs Store. Leave blank for a general store listing.\"\n />\n\n <InputField\n label=\"Short Description\"\n required\n value={form.shortDescription}\n onChange={(e) => setField(\"shortDescription\", e.target.value)}\n placeholder=\"One-line summary shown on the store card\"\n maxLength={160}\n hint={`${form.shortDescription.length}/160`}\n />\n\n <TextareaField\n label=\"Long Description\"\n value={form.longDescription}\n onChange={(e) => setField(\"longDescription\", e.target.value)}\n rows={5}\n placeholder=\"Detailed product description, features, specs…\"\n />\n </div>\n </PageSection>\n\n {/* ── Section 2: Product Images ── */}\n <PageSection\n title=\"Product Images\"\n description=\"Visual assets shown to buyers browsing the store.\"\n >\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6 space-y-5\">\n <div className=\"grid gap-5 sm:grid-cols-2\">\n <ImageUploadField\n label=\"Icon\"\n value={icon}\n onChange={setIcon}\n hint=\"Shown in marketplace cards and search — square proportions (1:1)\"\n aspectClass=\"aspect-square\"\n upload={uploadIcon}\n uploading={iconUploading}\n progress={iconProgress}\n error={iconUploadError}\n />\n <ImageUploadField\n label=\"Banner\"\n value={bannerUrl}\n onChange={setBannerUrl}\n hint=\"Fills the right panel on the product page — square or portrait works best on all screen sizes (1:1)\"\n aspectClass=\"aspect-square\"\n upload={uploadBanner}\n uploading={bannerUploading}\n progress={bannerProgress}\n error={bannerUploadError}\n />\n </div>\n <ScreenshotGallery\n urls={screenshots}\n onChange={setScreenshots}\n upload={uploadScreenshot}\n uploading={screenshotUploading}\n progress={screenshotProgress}\n error={screenshotUploadError}\n />\n </div>\n </PageSection>\n\n {/* ── Section 3: Pricing ── */}\n <PageSection title=\"Pricing\">\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6 space-y-5\">\n <div className=\"grid grid-cols-1 gap-5 sm:grid-cols-2\">\n <InputField\n label=\"Price\"\n required\n type=\"number\"\n value={form.price}\n onChange={(e) => setField(\"price\", e.target.value)}\n placeholder=\"0.00\"\n min={0.01}\n step=\"0.01\"\n />\n\n <SelectField\n label=\"Currency\"\n required\n value={form.currency}\n onChange={(e) => setField(\"currency\", e.target.value)}\n options={CURRENCIES}\n placeholder=\"Select currency\"\n />\n </div>\n\n <InputField\n label=\"Tags\"\n value={form.tags}\n onChange={(e) => setField(\"tags\", e.target.value)}\n placeholder=\"mechanical, wireless, ergonomic\"\n hint=\"Comma-separated keywords to help buyers find your item.\"\n />\n </div>\n </PageSection>\n\n {/* ── Section 4: Inventory ── */}\n <PageSection title=\"Inventory\">\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6 space-y-5\">\n <div className=\"grid grid-cols-1 gap-5 sm:grid-cols-2\">\n <InputField\n label=\"Stock Quantity\"\n required\n type=\"number\"\n value={form.stockQuantity}\n onChange={(e) => setField(\"stockQuantity\", e.target.value)}\n min={0}\n step={1}\n />\n\n <InputField\n label=\"SKU\"\n value={form.sku}\n onChange={(e) => setField(\"sku\", e.target.value)}\n placeholder=\"e.g. KB-WL-001\"\n hint=\"Your internal stock-keeping unit reference.\"\n />\n </div>\n\n <InputField\n label=\"Low Stock Threshold\"\n type=\"number\"\n value={form.lowStockThreshold}\n onChange={(e) => setField(\"lowStockThreshold\", e.target.value)}\n placeholder=\"e.g. 5\"\n min={0}\n step={1}\n hint=\"Get flagged when stock falls to or below this number.\"\n />\n\n <CheckboxField\n label=\"Track Inventory\"\n description=\"Automatically reduce stock when orders are placed.\"\n checked={form.trackInventory}\n onChange={handleCheckboxChange(\"trackInventory\")}\n />\n\n <CheckboxField\n label=\"Allow Backorder\"\n description=\"Let buyers order even when stock quantity is zero.\"\n checked={form.allowBackorder}\n onChange={handleCheckboxChange(\"allowBackorder\")}\n />\n </div>\n </PageSection>\n\n {/* ── Section 5: Shipping ── */}\n <PageSection title=\"Shipping\">\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6 space-y-5\">\n <CheckboxField\n label=\"Requires Shipping\"\n description=\"This item will be physically shipped to the buyer.\"\n checked={form.requiresShipping}\n onChange={handleCheckboxChange(\"requiresShipping\")}\n />\n\n {form.requiresShipping && (\n <>\n <div className=\"grid grid-cols-1 gap-5 sm:grid-cols-2\">\n <InputField\n label=\"Weight\"\n type=\"number\"\n value={form.weightKg}\n onChange={(e) => setField(\"weightKg\", e.target.value)}\n placeholder=\"0.0\"\n min={0}\n step=\"0.01\"\n hint=\"Used to calculate shipping costs.\"\n />\n\n <SelectField\n label=\"Weight Unit\"\n value={form.weightUnit}\n onChange={(e) => setField(\"weightUnit\", e.target.value)}\n options={WEIGHT_UNITS}\n />\n </div>\n\n <div className=\"grid grid-cols-1 gap-5 sm:grid-cols-3\">\n <InputField\n label=\"Length\"\n type=\"number\"\n value={form.length}\n onChange={(e) => setField(\"length\", e.target.value)}\n placeholder=\"0.0\"\n min={0}\n step=\"0.01\"\n />\n\n <InputField\n label=\"Width\"\n type=\"number\"\n value={form.width}\n onChange={(e) => setField(\"width\", e.target.value)}\n placeholder=\"0.0\"\n min={0}\n step=\"0.01\"\n />\n\n <InputField\n label=\"Height\"\n type=\"number\"\n value={form.height}\n onChange={(e) => setField(\"height\", e.target.value)}\n placeholder=\"0.0\"\n min={0}\n step=\"0.01\"\n />\n </div>\n\n <SelectField\n label=\"Dimension Unit\"\n value={form.dimensionUnit}\n onChange={(e) => setField(\"dimensionUnit\", e.target.value)}\n options={DIMENSION_UNITS}\n hint=\"Applies to length, width, and height above.\"\n />\n </>\n )}\n\n <p className=\"flex items-start gap-2 rounded-input border border-border-subtle bg-bg-sunken px-3 py-2 text-xs text-text-secondary\">\n <Info size={13} className=\"mt-0.5 shrink-0 text-text-muted\" />\n Delivery fees are configured at the organization level in store\n settings.\n </p>\n </div>\n </PageSection>\n\n {/* ── Section 6: Product Details ── */}\n <PageSection\n title=\"Product Details\"\n description=\"Optional supplemental information for buyers.\"\n >\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6 space-y-5\">\n <div className=\"grid grid-cols-1 gap-5 sm:grid-cols-2\">\n <InputField\n label=\"Brand\"\n value={form.brand}\n onChange={(e) => setField(\"brand\", e.target.value)}\n placeholder=\"e.g. Logitech\"\n />\n\n <InputField\n label=\"Manufacturer\"\n value={form.manufacturer}\n onChange={(e) => setField(\"manufacturer\", e.target.value)}\n placeholder=\"e.g. Logitech Manufacturing Ltd.\"\n />\n </div>\n\n <InputField\n label=\"Country of Origin\"\n value={form.countryOfOrigin}\n onChange={(e) => setField(\"countryOfOrigin\", e.target.value)}\n placeholder=\"e.g. China\"\n />\n\n <InputField\n label=\"Warranty Info\"\n value={form.warrantyInfo}\n onChange={(e) => setField(\"warrantyInfo\", e.target.value)}\n placeholder=\"e.g. 1-year limited manufacturer warranty\"\n />\n\n <TextareaField\n label=\"Return Policy\"\n value={form.returnPolicy}\n onChange={(e) => setField(\"returnPolicy\", e.target.value)}\n rows={3}\n placeholder=\"e.g. 30-day returns accepted\"\n />\n </div>\n </PageSection>\n\n {/* ── Actions ── */}\n <div className=\"flex items-center gap-3 pb-8\">\n <button\n type=\"button\"\n onClick={() => navigate?.(`${basePath}/seller/items`)}\n className=\"rounded-button border border-border-strong px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n Cancel\n </button>\n\n <div className=\"relative\">\n <button\n type=\"button\"\n onClick={handleSubmit}\n disabled={!isValid || submitting}\n aria-disabled={!isValid || submitting}\n title={\n sellerOrgLoading\n ? \"Setting up your seller organization...\"\n : !isValid\n ? \"Fill in all required fields to continue\"\n : undefined\n }\n className={cn(\n \"inline-flex items-center gap-2 rounded-button px-5 py-2 text-sm font-medium transition-colors\",\n \"bg-action-primary-bg text-action-primary-text\",\n \"hover:bg-action-primary-bg/90\",\n \"disabled:opacity-50 disabled:cursor-not-allowed\",\n \"focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2\",\n )}\n >\n {submitting ? (\n <>\n <Loader2 size={15} className=\"animate-spin\" />\n Submitting...\n </>\n ) : sellerOrgLoading ? (\n <>\n <Loader2 size={15} className=\"animate-spin\" />\n Setting up your store...\n </>\n ) : (\n \"Create & Submit for Review\"\n )}\n </button>\n </div>\n </div>\n </div>\n </PageLayout>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"CreatePhysicalItemPage.js","names":["_Fragment","PRODUCT_CATEGORIES","STORE_CATEGORIES","CURRENCIES","WEIGHT_UNITS","DIMENSION_UNITS","REQUIRED_FIELDS","MY_PUBLISHER_QUERY","REGISTER_PUBLISHER_MUTATION","CREATE_PHYSICAL_PRODUCT_MUTATION","SUBMIT_PRODUCT_MUTATION","deriveSlug","name","isFormValid","value","form","field","CreatePhysicalItemPage","useDevportal","sellerOrganization","sellerOrganizations","sellerOrgLoading","sellerOrgError","useSellerOrganization","setForm","useState","icon","setIcon","bannerUrl","setBannerUrl","screenshots","setScreenshots","uploadIcon","iconUploading","iconProgress","iconUploadError","useAssetUpload","workspacesGatewayUrl","authToken","workspaceId","getWorkspaceToken","uploadBanner","bannerUploading","bannerProgress","bannerUploadError","uploadScreenshot","screenshotUploading","screenshotProgress","screenshotUploadError","submitting","setSubmitting","submitError","setSubmitError","submitSuccess","setSubmitSuccess","imagesUploading","isValid","endpoint","resolveGlobalGraphqlEndpoint","apiGatewayUrl","setField","prev","key","handleNameChange","handleCheckboxChange","e","gqlFetch","json","PageLayout","PageSection","SelectField","selectOrganization","org","InputField","TextareaField","ImageUploadField","ScreenshotGallery","CheckboxField","Fragment","Info","navigate","basePath","publisherId","parsedTags","t","hasDimensions","newProductId","productId","err","cn","Loader2"],"sources":["../../../src/devportal/pages/CreatePhysicalItemPage.tsx"],"sourcesContent":["import type { FC, ChangeEvent } from \"react\";\nimport { useState } from \"react\";\nimport { Loader2, Info } from \"lucide-react\";\nimport { PageLayout, PageSection } from \"../components/PageLayout\";\nimport {\n InputField,\n TextareaField,\n SelectField,\n CheckboxField,\n} from \"../components/FormField\";\nimport {\n ImageUploadField,\n ScreenshotGallery,\n} from \"../components/ImageUploadField\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport { useSellerOrganization } from \"../hooks/useSellerOrganization\";\nimport { useAssetUpload } from \"../hooks/usePackageUpload\";\nimport { cn } from \"../utils/cn\";\nimport { resolveGlobalGraphqlEndpoint } from \"../utils/graphqlEndpoint\";\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\ninterface FormState {\n name: string;\n slug: string;\n type: string;\n category: string;\n shortDescription: string;\n longDescription: string;\n price: string;\n currency: string;\n tags: string;\n stockQuantity: string;\n sku: string;\n trackInventory: boolean;\n allowBackorder: boolean;\n lowStockThreshold: string;\n requiresShipping: boolean;\n weightKg: string;\n weightUnit: string;\n length: string;\n width: string;\n height: string;\n dimensionUnit: string;\n brand: string;\n manufacturer: string;\n countryOfOrigin: string;\n warrantyInfo: string;\n returnPolicy: string;\n}\n\n// ─── Constants ────────────────────────────────────────────────────────────────\n\nconst PRODUCT_CATEGORIES = [\n { value: \"MERCHANDISE\", label: \"Merchandise\" },\n { value: \"HARDWARE\", label: \"Hardware\" },\n { value: \"ACCESSORY\", label: \"Accessory\" },\n { value: \"BOOK\", label: \"Book\" },\n { value: \"EQUIPMENT\", label: \"Equipment\" },\n { value: \"APPAREL\", label: \"Apparel\" },\n { value: \"COLLECTIBLE\", label: \"Collectible\" },\n { value: \"CONSUMABLE\", label: \"Consumable\" },\n];\n\n// Store category (the product `category` string, distinct from the ProductType above).\n// The five `agri-` slugs are the HealthyBowl Agri-Inputs Store discriminator: picking one lists\n// the item in that farmer-facing storefront (roadmap #26). Leave blank for general listings.\nconst STORE_CATEGORIES = [\n { value: \"agri-seeds\", label: \"Agri-Inputs — Seeds\" },\n { value: \"agri-fertilizer\", label: \"Agri-Inputs — Organic Fertilizer\" },\n { value: \"agri-biopesticide\", label: \"Agri-Inputs — Bio-Pesticides\" },\n { value: \"agri-tools\", label: \"Agri-Inputs — Tools\" },\n { value: \"agri-irrigation\", label: \"Agri-Inputs — Irrigation\" },\n];\n\nconst CURRENCIES = [\n { value: \"USD\", label: \"USD — US Dollar\" },\n { value: \"INR\", label: \"INR — Indian Rupee\" },\n { value: \"EUR\", label: \"EUR — Euro\" },\n { value: \"GBP\", label: \"GBP — British Pound\" },\n { value: \"SGD\", label: \"SGD — Singapore Dollar\" },\n { value: \"AED\", label: \"AED — UAE Dirham\" },\n];\n\nconst WEIGHT_UNITS = [\n { value: \"GRAM\", label: \"Grams (g)\" },\n { value: \"KILOGRAM\", label: \"Kilograms (kg)\" },\n { value: \"OUNCE\", label: \"Ounces (oz)\" },\n { value: \"POUND\", label: \"Pounds (lb)\" },\n];\n\nconst DIMENSION_UNITS = [\n { value: \"CENTIMETER\", label: \"Centimeters (cm)\" },\n { value: \"INCH\", label: \"Inches (in)\" },\n { value: \"METER\", label: \"Meters (m)\" },\n];\n\nconst REQUIRED_FIELDS: (keyof FormState)[] = [\n \"name\",\n \"slug\",\n \"type\",\n \"shortDescription\",\n \"price\",\n \"currency\",\n \"stockQuantity\",\n];\n\n// ─── GraphQL strings ──────────────────────────────────────────────────────────\n\nconst MY_PUBLISHER_QUERY = /* GraphQL */ `\n query SellerMyPublisher {\n myPublisher {\n id\n }\n }\n`;\n\nconst REGISTER_PUBLISHER_MUTATION = /* GraphQL */ `\n mutation RegisterPublisher($input: RegisterPublisherInput!) {\n registerPublisher(input: $input) {\n id\n name\n email\n }\n }\n`;\n\nconst CREATE_PHYSICAL_PRODUCT_MUTATION = /* GraphQL */ `\n mutation CreatePhysicalProduct($input: CreatePhysicalProductInput!) {\n createPhysicalProduct(input: $input) {\n id\n name\n slug\n status\n nature\n type\n price\n currency\n icon\n bannerUrl\n screenshots\n }\n }\n`;\n\nconst SUBMIT_PRODUCT_MUTATION = /* GraphQL */ `\n mutation SubmitProduct($id: ID!, $notes: String) {\n submitProduct(id: $id, notes: $notes) {\n id\n status\n }\n }\n`;\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction deriveSlug(name: string): string {\n return name.toLowerCase().replace(/[^a-z0-9]+/g, \"-\");\n}\n\nfunction isFormValid(form: FormState): boolean {\n return REQUIRED_FIELDS.every((field) => {\n const value = form[field];\n if (typeof value === \"boolean\") return true;\n return value.trim() !== \"\";\n });\n}\n\n// ─── Component ────────────────────────────────────────────────────────────────\n\nexport const CreatePhysicalItemPage: FC = () => {\n const {\n navigate,\n basePath,\n productId,\n apiGatewayUrl,\n authToken,\n workspacesGatewayUrl,\n workspaceId,\n getWorkspaceToken,\n } = useDevportal();\n const {\n organization: sellerOrganization,\n organizations: sellerOrganizations,\n loading: sellerOrgLoading,\n error: sellerOrgError,\n selectOrganization,\n } = useSellerOrganization();\n\n const [form, setForm] = useState<FormState>({\n name: \"\",\n slug: \"\",\n type: \"\",\n category: \"\",\n shortDescription: \"\",\n longDescription: \"\",\n price: \"\",\n currency: \"\",\n tags: \"\",\n stockQuantity: \"1\",\n sku: \"\",\n trackInventory: true,\n allowBackorder: false,\n lowStockThreshold: \"\",\n requiresShipping: true,\n weightKg: \"\",\n weightUnit: \"KILOGRAM\",\n length: \"\",\n width: \"\",\n height: \"\",\n dimensionUnit: \"CENTIMETER\",\n brand: \"\",\n manufacturer: \"\",\n countryOfOrigin: \"\",\n warrantyInfo: \"\",\n returnPolicy: \"\",\n });\n\n const [icon, setIcon] = useState(\"\");\n const [bannerUrl, setBannerUrl] = useState(\"\");\n const [screenshots, setScreenshots] = useState<string[]>([]);\n const {\n upload: uploadIcon,\n uploading: iconUploading,\n progress: iconProgress,\n error: iconUploadError,\n } = useAssetUpload(\n workspacesGatewayUrl,\n authToken,\n workspaceId,\n getWorkspaceToken,\n );\n const {\n upload: uploadBanner,\n uploading: bannerUploading,\n progress: bannerProgress,\n error: bannerUploadError,\n } = useAssetUpload(\n workspacesGatewayUrl,\n authToken,\n workspaceId,\n getWorkspaceToken,\n );\n const {\n upload: uploadScreenshot,\n uploading: screenshotUploading,\n progress: screenshotProgress,\n error: screenshotUploadError,\n } = useAssetUpload(\n workspacesGatewayUrl,\n authToken,\n workspaceId,\n getWorkspaceToken,\n );\n\n const [submitting, setSubmitting] = useState(false);\n const [submitError, setSubmitError] = useState<string | null>(null);\n const [submitSuccess, setSubmitSuccess] = useState(false);\n\n const imagesUploading =\n iconUploading || bannerUploading || screenshotUploading;\n const isValid = isFormValid(form) && !!sellerOrganization && !imagesUploading;\n const endpoint = resolveGlobalGraphqlEndpoint(apiGatewayUrl);\n\n // ─── Field helpers ────────────────────────────────────────────────────────\n\n const setField = <K extends keyof FormState>(key: K, value: FormState[K]) => {\n setForm((prev) => ({ ...prev, [key]: value }));\n };\n\n const handleNameChange = (e: ChangeEvent<HTMLInputElement>) => {\n const name = e.target.value;\n setForm((prev) => ({\n ...prev,\n name,\n slug: deriveSlug(name),\n }));\n };\n\n const handleCheckboxChange =\n (key: \"trackInventory\" | \"requiresShipping\" | \"allowBackorder\") =>\n (e: ChangeEvent<HTMLInputElement>) => {\n setField(key, e.target.checked);\n };\n\n // ─── GraphQL fetch helper ─────────────────────────────────────────────────\n\n async function gqlFetch<T = unknown>(\n query: string,\n variables?: Record<string, unknown>,\n ): Promise<T> {\n const res = await fetch(endpoint, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...(authToken ? { Authorization: `Bearer ${authToken}` } : {}),\n },\n credentials: \"include\",\n body: JSON.stringify({ query, variables }),\n });\n const json = (await res.json()) as {\n data?: T;\n errors?: { message: string }[];\n };\n if (json.errors?.length) {\n throw new Error(json.errors.map((e) => e.message).join(\"; \"));\n }\n return json.data as T;\n }\n\n // ─── Submit flow ──────────────────────────────────────────────────────────\n\n const handleSubmit = async () => {\n if (!isValid || submitting || !sellerOrganization) return;\n setSubmitting(true);\n setSubmitError(null);\n\n try {\n // Step 1: check if publisher exists\n const publisherData = await gqlFetch<{\n myPublisher: { id: string } | null;\n }>(MY_PUBLISHER_QUERY);\n\n let publisherId = publisherData.myPublisher?.id ?? null;\n\n if (!publisherId) {\n const registerData = await gqlFetch<{\n registerPublisher: { id: string };\n }>(REGISTER_PUBLISHER_MUTATION, {\n input: {\n name: sellerOrganization.legalEntityName ?? sellerOrganization.name,\n email: sellerOrganization.contactEmail ?? \"seller@burdenoff.com\",\n websiteUrl: sellerOrganization.websiteUrl ?? null,\n legalName:\n sellerOrganization.legalEntityName ?? sellerOrganization.name,\n country: sellerOrganization.taxCountry ?? null,\n contactEmail: sellerOrganization.contactEmail ?? null,\n },\n });\n\n publisherId = registerData.registerPublisher.id;\n }\n\n // Step 2: create the product, linked to the seller's PHYSICAL org —\n // validated server-side (createPhysicalProduct rejects any org that\n // isn't PHYSICAL-kind, see DeveloperOrgKind / BOFF-7285).\n const parsedTags = form.tags\n .split(\",\")\n .map((t) => t.trim())\n .filter(Boolean);\n\n const hasDimensions =\n form.length.trim() || form.width.trim() || form.height.trim();\n\n const productData = await gqlFetch<{\n createPhysicalProduct: { id: string };\n }>(CREATE_PHYSICAL_PRODUCT_MUTATION, {\n input: {\n name: form.name.trim(),\n slug: form.slug.trim(),\n type: form.type,\n category: form.category.trim() || null,\n description: form.shortDescription.trim(),\n longDescription: form.longDescription.trim() || null,\n price: parseFloat(form.price),\n currency: form.currency,\n tags: parsedTags.length > 0 ? parsedTags : null,\n stockQuantity: parseInt(form.stockQuantity, 10),\n sku: form.sku.trim() || null,\n trackInventory: form.trackInventory,\n allowBackorder: form.allowBackorder,\n lowStockThreshold: form.lowStockThreshold.trim()\n ? parseInt(form.lowStockThreshold, 10)\n : null,\n requiresShipping: form.requiresShipping,\n weight:\n form.requiresShipping && form.weightKg.trim()\n ? parseFloat(form.weightKg)\n : null,\n weightUnit:\n form.requiresShipping && form.weightKg.trim()\n ? form.weightUnit\n : null,\n length:\n form.requiresShipping && form.length.trim()\n ? parseFloat(form.length)\n : null,\n width:\n form.requiresShipping && form.width.trim()\n ? parseFloat(form.width)\n : null,\n height:\n form.requiresShipping && form.height.trim()\n ? parseFloat(form.height)\n : null,\n dimensionUnit:\n form.requiresShipping && hasDimensions ? form.dimensionUnit : null,\n brand: form.brand.trim() || null,\n manufacturer: form.manufacturer.trim() || null,\n countryOfOrigin: form.countryOfOrigin.trim() || null,\n warrantyInfo: form.warrantyInfo.trim() || null,\n returnPolicy: form.returnPolicy.trim() || null,\n icon: icon || null,\n bannerUrl: bannerUrl || null,\n screenshots: screenshots.length > 0 ? screenshots : null,\n // Tags this listing with the host product (e.g. \"healthybowl\") so\n // it can be filtered to that product's marketplace. Only set when\n // the host shell actually passes a productId — stays exactly as\n // before (no tag) for any shell that doesn't opt in.\n compatibleProducts: productId ? [productId] : null,\n organizationId: sellerOrganization.id,\n },\n });\n\n const newProductId = productData.createPhysicalProduct.id;\n\n // Step 3: submit for review\n await gqlFetch(SUBMIT_PRODUCT_MUTATION, {\n id: newProductId,\n notes: \"Submitted from seller portal\",\n });\n\n // Step 4: success\n setSubmitSuccess(true);\n setTimeout(() => {\n navigate?.(`${basePath}/seller/items`);\n }, 2000);\n } catch (err) {\n setSubmitError(\n err instanceof Error\n ? err.message\n : \"Submission failed. Please try again.\",\n );\n } finally {\n setSubmitting(false);\n }\n };\n\n // ─── Render ───────────────────────────────────────────────────────────────\n\n return (\n <PageLayout\n title=\"List a Physical Item\"\n description=\"Fill in all required details. Your listing will be reviewed before it appears in the store.\"\n backLink=\"/seller/items\"\n backLabel=\"Back to My Items\"\n >\n <div className=\"space-y-8 max-w-3xl\">\n {/* Success banner */}\n {submitSuccess && (\n <div className=\"rounded-card border border-status-success-text/30 bg-status-success-bg-subtle px-4 py-3 text-sm text-status-success-text\">\n Your listing has been submitted for review! Redirecting...\n </div>\n )}\n\n {/* Error banner */}\n {submitError && (\n <div className=\"rounded-card border border-status-error-text/30 bg-status-error-bg-subtle px-4 py-3 text-sm text-status-error-text\">\n {submitError}\n </div>\n )}\n\n {/* Seller org resolution error — the form can't be submitted without one */}\n {sellerOrgError && (\n <div className=\"rounded-card border border-status-error-text/30 bg-status-error-bg-subtle px-4 py-3 text-sm text-status-error-text\">\n Couldn't set up your seller organization: {sellerOrgError}\n </div>\n )}\n\n {/* ── Section 0: Seller Organization ── */}\n <PageSection\n title=\"Seller Organization\"\n description=\"The seller organization this item will be listed under.\"\n >\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6 space-y-3\">\n <SelectField\n label=\"Organization\"\n required\n value={sellerOrganization?.id ?? \"\"}\n onChange={(e) => selectOrganization(e.target.value)}\n options={sellerOrganizations.map((org) => ({\n value: org.id,\n label: org.name,\n }))}\n placeholder={\n sellerOrgLoading\n ? \"Resolving your seller organization…\"\n : \"Select an organization\"\n }\n disabled={sellerOrgLoading || sellerOrganizations.length <= 1}\n hint={\n sellerOrganizations.length > 1\n ? \"You have more than one seller organization — pick the one this item belongs to.\"\n : sellerOrganization\n ? `Automatically set to your only seller organization, \"${sellerOrganization.name}\".`\n : undefined\n }\n />\n </div>\n </PageSection>\n\n {/* ── Section 1: Basic Information ── */}\n <PageSection\n title=\"Basic Information\"\n description=\"Core details shown in the store listing.\"\n >\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6 space-y-5\">\n <InputField\n label=\"Name\"\n required\n value={form.name}\n onChange={handleNameChange}\n placeholder=\"e.g. Wireless Ergonomic Keyboard\"\n maxLength={120}\n />\n\n <InputField\n label=\"Slug\"\n required\n value={form.slug}\n onChange={(e) => setField(\"slug\", e.target.value)}\n placeholder=\"auto-derived-from-name\"\n hint=\"URL-friendly identifier. Auto-derived from name; you can edit it.\"\n />\n\n <SelectField\n label=\"Product Type\"\n required\n value={form.type}\n onChange={(e) => setField(\"type\", e.target.value)}\n options={PRODUCT_CATEGORIES}\n placeholder=\"Select a type\"\n />\n\n <SelectField\n label=\"Store Category\"\n value={form.category}\n onChange={(e) => setField(\"category\", e.target.value)}\n options={STORE_CATEGORIES}\n placeholder=\"General / uncategorised\"\n hint=\"Pick an Agri-Inputs category to list this item in the HealthyBowl Agri-Inputs Store. Leave blank for a general store listing.\"\n />\n\n <InputField\n label=\"Short Description\"\n required\n value={form.shortDescription}\n onChange={(e) => setField(\"shortDescription\", e.target.value)}\n placeholder=\"One-line summary shown on the store card\"\n maxLength={160}\n hint={`${form.shortDescription.length}/160`}\n />\n\n <TextareaField\n label=\"Long Description\"\n value={form.longDescription}\n onChange={(e) => setField(\"longDescription\", e.target.value)}\n rows={5}\n placeholder=\"Detailed product description, features, specs…\"\n />\n </div>\n </PageSection>\n\n {/* ── Section 2: Product Images ── */}\n <PageSection\n title=\"Product Images\"\n description=\"Visual assets shown to buyers browsing the store.\"\n >\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6 space-y-5\">\n <div className=\"grid gap-5 sm:grid-cols-2\">\n <ImageUploadField\n label=\"Icon\"\n value={icon}\n onChange={setIcon}\n hint=\"Shown in marketplace cards and search — square proportions (1:1)\"\n aspectClass=\"aspect-square\"\n upload={uploadIcon}\n uploading={iconUploading}\n progress={iconProgress}\n error={iconUploadError}\n />\n <ImageUploadField\n label=\"Banner\"\n value={bannerUrl}\n onChange={setBannerUrl}\n hint=\"Fills the right panel on the product page — square or portrait works best on all screen sizes (1:1)\"\n aspectClass=\"aspect-square\"\n upload={uploadBanner}\n uploading={bannerUploading}\n progress={bannerProgress}\n error={bannerUploadError}\n />\n </div>\n <ScreenshotGallery\n urls={screenshots}\n onChange={setScreenshots}\n upload={uploadScreenshot}\n uploading={screenshotUploading}\n progress={screenshotProgress}\n error={screenshotUploadError}\n />\n </div>\n </PageSection>\n\n {/* ── Section 3: Pricing ── */}\n <PageSection title=\"Pricing\">\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6 space-y-5\">\n <div className=\"grid grid-cols-1 gap-5 sm:grid-cols-2\">\n <InputField\n label=\"Price\"\n required\n type=\"number\"\n value={form.price}\n onChange={(e) => setField(\"price\", e.target.value)}\n placeholder=\"0.00\"\n min={0.01}\n step=\"0.01\"\n />\n\n <SelectField\n label=\"Currency\"\n required\n value={form.currency}\n onChange={(e) => setField(\"currency\", e.target.value)}\n options={CURRENCIES}\n placeholder=\"Select currency\"\n />\n </div>\n\n <InputField\n label=\"Tags\"\n value={form.tags}\n onChange={(e) => setField(\"tags\", e.target.value)}\n placeholder=\"mechanical, wireless, ergonomic\"\n hint=\"Comma-separated keywords to help buyers find your item.\"\n />\n </div>\n </PageSection>\n\n {/* ── Section 4: Inventory ── */}\n <PageSection title=\"Inventory\">\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6 space-y-5\">\n <div className=\"grid grid-cols-1 gap-5 sm:grid-cols-2\">\n <InputField\n label=\"Stock Quantity\"\n required\n type=\"number\"\n value={form.stockQuantity}\n onChange={(e) => setField(\"stockQuantity\", e.target.value)}\n min={0}\n step={1}\n />\n\n <InputField\n label=\"SKU\"\n value={form.sku}\n onChange={(e) => setField(\"sku\", e.target.value)}\n placeholder=\"e.g. KB-WL-001\"\n hint=\"Your internal stock-keeping unit reference.\"\n />\n </div>\n\n <InputField\n label=\"Low Stock Threshold\"\n type=\"number\"\n value={form.lowStockThreshold}\n onChange={(e) => setField(\"lowStockThreshold\", e.target.value)}\n placeholder=\"e.g. 5\"\n min={0}\n step={1}\n hint=\"Get flagged when stock falls to or below this number.\"\n />\n\n <CheckboxField\n label=\"Track Inventory\"\n description=\"Automatically reduce stock when orders are placed.\"\n checked={form.trackInventory}\n onChange={handleCheckboxChange(\"trackInventory\")}\n />\n\n <CheckboxField\n label=\"Allow Backorder\"\n description=\"Let buyers order even when stock quantity is zero.\"\n checked={form.allowBackorder}\n onChange={handleCheckboxChange(\"allowBackorder\")}\n />\n </div>\n </PageSection>\n\n {/* ── Section 5: Shipping ── */}\n <PageSection title=\"Shipping\">\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6 space-y-5\">\n <CheckboxField\n label=\"Requires Shipping\"\n description=\"This item will be physically shipped to the buyer.\"\n checked={form.requiresShipping}\n onChange={handleCheckboxChange(\"requiresShipping\")}\n />\n\n {form.requiresShipping && (\n <>\n <div className=\"grid grid-cols-1 gap-5 sm:grid-cols-2\">\n <InputField\n label=\"Weight\"\n type=\"number\"\n value={form.weightKg}\n onChange={(e) => setField(\"weightKg\", e.target.value)}\n placeholder=\"0.0\"\n min={0}\n step=\"0.01\"\n hint=\"Used to calculate shipping costs.\"\n />\n\n <SelectField\n label=\"Weight Unit\"\n value={form.weightUnit}\n onChange={(e) => setField(\"weightUnit\", e.target.value)}\n options={WEIGHT_UNITS}\n />\n </div>\n\n <div className=\"grid grid-cols-1 gap-5 sm:grid-cols-3\">\n <InputField\n label=\"Length\"\n type=\"number\"\n value={form.length}\n onChange={(e) => setField(\"length\", e.target.value)}\n placeholder=\"0.0\"\n min={0}\n step=\"0.01\"\n />\n\n <InputField\n label=\"Width\"\n type=\"number\"\n value={form.width}\n onChange={(e) => setField(\"width\", e.target.value)}\n placeholder=\"0.0\"\n min={0}\n step=\"0.01\"\n />\n\n <InputField\n label=\"Height\"\n type=\"number\"\n value={form.height}\n onChange={(e) => setField(\"height\", e.target.value)}\n placeholder=\"0.0\"\n min={0}\n step=\"0.01\"\n />\n </div>\n\n <SelectField\n label=\"Dimension Unit\"\n value={form.dimensionUnit}\n onChange={(e) => setField(\"dimensionUnit\", e.target.value)}\n options={DIMENSION_UNITS}\n hint=\"Applies to length, width, and height above.\"\n />\n </>\n )}\n\n <p className=\"flex items-start gap-2 rounded-input border border-border-subtle bg-bg-sunken px-3 py-2 text-xs text-text-secondary\">\n <Info size={13} className=\"mt-0.5 shrink-0 text-text-muted\" />\n Delivery fees are configured at the organization level in store\n settings.\n </p>\n </div>\n </PageSection>\n\n {/* ── Section 6: Product Details ── */}\n <PageSection\n title=\"Product Details\"\n description=\"Optional supplemental information for buyers.\"\n >\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6 space-y-5\">\n <div className=\"grid grid-cols-1 gap-5 sm:grid-cols-2\">\n <InputField\n label=\"Brand\"\n value={form.brand}\n onChange={(e) => setField(\"brand\", e.target.value)}\n placeholder=\"e.g. Logitech\"\n />\n\n <InputField\n label=\"Manufacturer\"\n value={form.manufacturer}\n onChange={(e) => setField(\"manufacturer\", e.target.value)}\n placeholder=\"e.g. Logitech Manufacturing Ltd.\"\n />\n </div>\n\n <InputField\n label=\"Country of Origin\"\n value={form.countryOfOrigin}\n onChange={(e) => setField(\"countryOfOrigin\", e.target.value)}\n placeholder=\"e.g. China\"\n />\n\n <InputField\n label=\"Warranty Info\"\n value={form.warrantyInfo}\n onChange={(e) => setField(\"warrantyInfo\", e.target.value)}\n placeholder=\"e.g. 1-year limited manufacturer warranty\"\n />\n\n <TextareaField\n label=\"Return Policy\"\n value={form.returnPolicy}\n onChange={(e) => setField(\"returnPolicy\", e.target.value)}\n rows={3}\n placeholder=\"e.g. 30-day returns accepted\"\n />\n </div>\n </PageSection>\n\n {/* ── Actions ── */}\n <div className=\"flex items-center gap-3 pb-8\">\n <button\n type=\"button\"\n onClick={() => navigate?.(`${basePath}/seller/items`)}\n className=\"rounded-button border border-border-strong px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n Cancel\n </button>\n\n <div className=\"relative\">\n <button\n type=\"button\"\n onClick={handleSubmit}\n disabled={!isValid || submitting}\n aria-disabled={!isValid || submitting}\n title={\n sellerOrgLoading\n ? \"Setting up your seller organization...\"\n : !isValid\n ? \"Fill in all required fields to continue\"\n : undefined\n }\n className={cn(\n \"inline-flex items-center gap-2 rounded-button px-5 py-2 text-sm font-medium transition-colors\",\n \"bg-action-primary-bg text-action-primary-text\",\n \"hover:bg-action-primary-bg/90\",\n \"disabled:opacity-50 disabled:cursor-not-allowed\",\n \"focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2\",\n )}\n >\n {submitting ? (\n <>\n <Loader2 size={15} className=\"animate-spin\" />\n Submitting...\n </>\n ) : sellerOrgLoading ? (\n <>\n <Loader2 size={15} className=\"animate-spin\" />\n Setting up your store...\n </>\n ) : (\n \"Create & Submit for Review\"\n )}\n </button>\n </div>\n </div>\n </div>\n </PageLayout>\n );\n};\n"],"mappings":"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"}
@@ -3,13 +3,13 @@ import { PageLayout as t, PageSection as n } from "../components/PageLayout.js";
3
3
  import { CheckboxField as r, InputField as i, SelectField as a, TagInput as o, TextareaField as ee } from "../components/FormField.js";
4
4
  import { MarkdownEditor as te } from "../components/MarkdownEditor.js";
5
5
  import { MultiSelectCombobox as ne } from "../components/MultiSelectCombobox.js";
6
- import { StatusBadge as s } from "../components/StatusBadge.js";
7
- import { ConfirmDialog as c } from "../components/ConfirmDialog.js";
8
- import { LoadingState as re } from "../components/LoadingState.js";
9
- import { EmptyState as ie } from "../components/EmptyState.js";
10
- import { useDevportal as ae } from "../providers/DevportalProvider.js";
11
- import { PermissionGuard as oe } from "../components/PermissionGuard.js";
12
- import { nativeImpact as se, nativeNotify as l } from "../../utils/nativeBridge.js";
6
+ import { StatusBadge as re } from "../components/StatusBadge.js";
7
+ import { ConfirmDialog as s } from "../components/ConfirmDialog.js";
8
+ import { LoadingState as ie } from "../components/LoadingState.js";
9
+ import { EmptyState as ae } from "../components/EmptyState.js";
10
+ import { useDevportal as oe } from "../providers/DevportalProvider.js";
11
+ import { PermissionGuard as se } from "../components/PermissionGuard.js";
12
+ import { nativeImpact as c, nativeNotify as l } from "../../utils/nativeBridge.js";
13
13
  import "../components/index.js";
14
14
  import { DEVPORTAL_PERMISSIONS as u } from "../constants/permissions.js";
15
15
  import { useProducts as ce } from "../hooks/useProducts.js";
@@ -87,13 +87,13 @@ function Ae(e) {
87
87
  } : null;
88
88
  }
89
89
  var b = () => {
90
- let { navigate: f, basePath: b } = ae(), { appId: x } = Ee(), { t: S } = De(), { products: C } = ce(), { allowed: w } = d(u.APP_UPDATE), { allowed: T } = d(u.APP_DELETE), E = (e, t) => {
90
+ let { navigate: f, basePath: b } = oe(), { appId: x } = Ee(), { t: S } = De(), { products: C } = ce(), { allowed: w } = d(u.APP_UPDATE), { allowed: T } = d(u.APP_DELETE), E = (e, t) => {
91
91
  let n = S(e);
92
92
  return n === e ? t : n;
93
- }, [D, O] = m(!1), [k, A] = m({}), [je, j] = m(!1), [M, N] = m(!1), [Me, P] = m(!1), [F, I] = m(!1), [L, R] = m(!1), [z, B] = m(!1), [V, Ne] = m(null), [Pe, H] = m(!1), { data: U, loading: Fe, error: W, refetch: Ie } = de({
93
+ }, [D, O] = m(!1), [k, A] = m({}), [je, j] = m(!1), [Me, M] = m(!1), [Ne, N] = m(!1), [P, F] = m(!1), [I, L] = m(!1), [R, z] = m(!1), [B, Pe] = m(null), [Fe, V] = m(!1), { data: H, loading: Ie, error: U, refetch: Le } = de({
94
94
  variables: { id: x },
95
95
  skip: !x
96
- }), [G] = pe(), [Le] = ue(), [Re] = le(), [ze] = fe(), K = Ae(U?.application);
96
+ }), [W] = pe(), [Re] = ue(), [ze] = le(), [Be] = fe(), [Ve, G] = m(!1), K = Ae(H?.application);
97
97
  p(() => {
98
98
  let e = K?.name;
99
99
  if (!x || !e) return;
@@ -142,42 +142,42 @@ var b = () => {
142
142
  oauthRevokeUrl: K.oauthRevokeUrl || "",
143
143
  requiresApproval: K.requiresApproval
144
144
  });
145
- let e = U?.application?.manifest?.compatibility, t = Array.isArray(e?.products) ? e.products : [];
146
- X(t), I(!1);
145
+ let e = H?.application?.manifest?.compatibility, t = Array.isArray(e?.products) ? e.products : [];
146
+ X(t), F(!1);
147
147
  }
148
- }, [U?.application]);
148
+ }, [H?.application]);
149
149
  let Z = (e) => {
150
150
  f?.(`${b}${e}`);
151
151
  }, Q = (e, t) => {
152
152
  J((n) => ({
153
153
  ...n,
154
154
  [e]: t
155
- })), I(!0), k[e] && A((t) => ({
155
+ })), F(!0), k[e] && A((t) => ({
156
156
  ...t,
157
157
  [e]: void 0
158
158
  }));
159
159
  }, $ = async () => {
160
160
  if (x) {
161
- B(!0);
161
+ z(!0);
162
162
  try {
163
- let e = (await ze({ variables: { id: x } })).data?.rotateApplicationSigningSecret?.signingSecret;
164
- e && (Ne(e), R(!0));
163
+ let e = (await Be({ variables: { id: x } })).data?.rotateApplicationSigningSecret?.signingSecret;
164
+ e && (Pe(e), L(!0));
165
165
  } catch {
166
166
  l("error");
167
167
  } finally {
168
- B(!1);
168
+ z(!1);
169
169
  }
170
170
  }
171
- }, Be = async (e) => {
172
- await navigator.clipboard.writeText(e), H(!0), setTimeout(() => H(!1), 2e3);
173
- }, Ve = () => {
171
+ }, He = async (e) => {
172
+ await navigator.clipboard.writeText(e), V(!0), setTimeout(() => V(!1), 2e3);
173
+ }, Ue = () => {
174
174
  let e = {};
175
175
  return q.name.trim() ? q.name.length < 3 ? e.name = E("devportal.appNameMinLength", "Name must be at least 3 characters") : q.name.length > 100 && (e.name = E("devportal.appNameMaxLength", "Name must be less than 100 characters")) : e.name = E("devportal.appNameRequired", "Application name is required"), q.slug.trim() ? /^[a-z0-9-]+$/.test(q.slug) || (e.slug = E("devportal.slugInvalidChars", "Slug can only contain lowercase letters, numbers, and hyphens")) : e.slug = E("devportal.slugRequired", "Slug is required"), q.shortDescription.trim() ? q.shortDescription.length > 200 && (e.shortDescription = E("devportal.shortDescriptionMaxLength", "Short description must be less than 200 characters")) : e.shortDescription = E("devportal.shortDescriptionRequired", "Short description is required"), q.appType || (e.appType = E("devportal.appTypeRequired", "Application type is required")), q.category || (e.category = E("devportal.categoryRequired", "Category is required")), A(e), Object.keys(e).length === 0;
176
- }, He = async (e) => {
177
- if (e.preventDefault(), Ve() && K) {
176
+ }, We = async (e) => {
177
+ if (e.preventDefault(), Ue() && K) {
178
178
  O(!0);
179
179
  try {
180
- await G({ variables: {
180
+ await W({ variables: {
181
181
  id: K.id,
182
182
  input: {
183
183
  name: q.name,
@@ -198,40 +198,40 @@ var b = () => {
198
198
  oauthRevokeUrl: q.oauthRevokeUrl || null,
199
199
  compatibleProducts: Y
200
200
  }
201
- } }), I(!1);
201
+ } }), F(!1);
202
202
  } catch (e) {
203
203
  console.error("Failed to update application:", e);
204
204
  } finally {
205
205
  O(!1);
206
206
  }
207
207
  }
208
- }, Ue = async () => {
208
+ }, Ge = async () => {
209
209
  if (K) {
210
- se("medium");
210
+ c("medium");
211
211
  try {
212
- await Le({ variables: { id: K.id } }), l("success"), Z("/apps");
212
+ await Re({ variables: { id: K.id } }), l("success"), Z("/apps");
213
213
  } catch (e) {
214
214
  l("error"), console.error("Failed to delete application:", e);
215
215
  }
216
216
  }
217
- }, We = async () => {
217
+ }, Ke = async () => {
218
218
  if (K) try {
219
- await G({ variables: {
219
+ await W({ variables: {
220
220
  id: K.id,
221
221
  input: { visibility: "PRIVATE" }
222
- } }), N(!1);
222
+ } }), M(!1);
223
223
  } catch (e) {
224
224
  console.error("Failed to deprecate application:", e);
225
225
  }
226
- }, Ge = async () => {
226
+ }, qe = async () => {
227
227
  if (K) try {
228
- await Re({ variables: { id: K.id } }), P(!1), Z("/apps");
228
+ await ze({ variables: { id: K.id } }), N(!1), Z("/apps");
229
229
  } catch (e) {
230
230
  console.error("Failed to deactivate application:", e);
231
231
  }
232
232
  };
233
- if (Fe) return /* @__PURE__ */ _(re, { message: E("devportal.loadingApplication", "Loading application...") });
234
- if (W) return /* @__PURE__ */ _(t, {
233
+ if (Ie) return /* @__PURE__ */ _(ie, { message: E("devportal.loadingApplication", "Loading application...") });
234
+ if (U) return /* @__PURE__ */ _(t, {
235
235
  title: E("devportal.error", "Error"),
236
236
  backLink: `${b}/apps`,
237
237
  backLabel: E("devportal.backToApplications", "Back to Applications"),
@@ -248,7 +248,7 @@ var b = () => {
248
248
  }),
249
249
  /* @__PURE__ */ _("p", {
250
250
  className: "text-sm text-text-secondary",
251
- children: W.message
251
+ children: U.message
252
252
  })
253
253
  ]
254
254
  })
@@ -257,15 +257,15 @@ var b = () => {
257
257
  title: E("devportal.notFound", "Not Found"),
258
258
  backLink: `${b}/apps`,
259
259
  backLabel: E("devportal.backToApplications", "Back to Applications"),
260
- children: /* @__PURE__ */ _(ie, {
260
+ children: /* @__PURE__ */ _(ae, {
261
261
  illustration: "empty-generic",
262
262
  icon: /* @__PURE__ */ _(ge, { size: 48 }),
263
263
  title: E("devportal.applicationNotFound", "Application not found"),
264
264
  description: E("devportal.applicationNotFoundDescription", "The application you're looking for doesn't exist or you don't have access to it.")
265
265
  })
266
266
  });
267
- let Ke = K.status === "DRAFT" || K.status === "REJECTED", qe = K.status === "PUBLISHED", Je = K.status === "ACTIVE" || K.status === "PUBLISHED";
268
- return /* @__PURE__ */ _(oe, {
267
+ let Je = K.status === "DRAFT" || K.status === "REJECTED", Ye = K.status === "PUBLISHED", Xe = K.status === "ACTIVE" || K.status === "PUBLISHED";
268
+ return /* @__PURE__ */ _(se, {
269
269
  authOnly: !0,
270
270
  children: /* @__PURE__ */ v(t, {
271
271
  title: `${E("devportal.editAppTitlePrefix", "Edit:")} ${K.name}`,
@@ -275,14 +275,14 @@ var b = () => {
275
275
  backLabel: E("devportal.backToApplication", "Back to Application"),
276
276
  actions: /* @__PURE__ */ _("div", {
277
277
  className: "flex items-center gap-2",
278
- children: /* @__PURE__ */ _(s, {
278
+ children: /* @__PURE__ */ _(re, {
279
279
  status: K.status,
280
280
  type: "app"
281
281
  })
282
282
  }),
283
283
  children: [
284
284
  /* @__PURE__ */ v("form", {
285
- onSubmit: He,
285
+ onSubmit: We,
286
286
  className: "space-y-8 max-w-3xl",
287
287
  children: [
288
288
  K.status === "PUBLISHED" && /* @__PURE__ */ v("div", {
@@ -412,7 +412,7 @@ var b = () => {
412
412
  })),
413
413
  selected: Y,
414
414
  onChange: (e) => {
415
- X(e), I(!0);
415
+ X(e), F(!0);
416
416
  },
417
417
  placeholder: "Select products…",
418
418
  searchPlaceholder: "Search products…"
@@ -495,7 +495,7 @@ var b = () => {
495
495
  hint: "We POST to this URL when a user uninstalls your integration"
496
496
  }),
497
497
  (() => {
498
- let e = V ?? U?.application?.signingSecret, t = "boff_sk_" + "•".repeat(32);
498
+ let e = B ?? H?.application?.signingSecret, t = "boff_sk_" + "•".repeat(32);
499
499
  return /* @__PURE__ */ v("div", {
500
500
  className: "space-y-1.5",
501
501
  children: [
@@ -523,21 +523,21 @@ var b = () => {
523
523
  children: [
524
524
  /* @__PURE__ */ _("code", {
525
525
  className: "flex-1 px-3 py-2 text-xs font-mono text-text-primary truncate",
526
- children: L ? e : t
526
+ children: I ? e : t
527
527
  }),
528
528
  /* @__PURE__ */ _("button", {
529
529
  type: "button",
530
- onClick: () => R((e) => !e),
530
+ onClick: () => L((e) => !e),
531
531
  className: "px-2 py-2 text-text-secondary hover:text-text-primary border-l border-border-default",
532
- title: L ? "Hide" : "Reveal",
533
- children: _(L ? xe : be, { size: 14 })
532
+ title: I ? "Hide" : "Reveal",
533
+ children: _(I ? xe : be, { size: 14 })
534
534
  }),
535
535
  /* @__PURE__ */ _("button", {
536
536
  type: "button",
537
- onClick: () => Be(e),
537
+ onClick: () => He(e),
538
538
  className: "px-2 py-2 text-text-secondary hover:text-text-primary border-l border-border-default",
539
539
  title: "Copy to clipboard",
540
- children: Pe ? /* @__PURE__ */ _(ve, {
540
+ children: Fe ? /* @__PURE__ */ _(ve, {
541
541
  size: 14,
542
542
  className: "text-green-500"
543
543
  }) : /* @__PURE__ */ _(ye, { size: 14 })
@@ -545,26 +545,26 @@ var b = () => {
545
545
  ]
546
546
  }), /* @__PURE__ */ v("button", {
547
547
  type: "button",
548
- onClick: $,
549
- disabled: z,
548
+ onClick: () => G(!0),
549
+ disabled: R,
550
550
  className: "flex items-center gap-1.5 px-3 py-2 text-xs rounded-md border border-border-default bg-bg-default text-text-primary hover:bg-bg-subtle disabled:opacity-50",
551
551
  title: "Rotate signing secret",
552
552
  children: [/* @__PURE__ */ _(h, {
553
553
  size: 12,
554
- className: z ? "animate-spin" : ""
554
+ className: R ? "animate-spin" : ""
555
555
  }), "Rotate"]
556
556
  })]
557
557
  }) : /* @__PURE__ */ v("button", {
558
558
  type: "button",
559
559
  onClick: $,
560
- disabled: z,
560
+ disabled: R,
561
561
  className: "flex items-center gap-1.5 px-3 py-2 text-xs rounded-md border border-border-default bg-bg-default text-text-primary hover:bg-bg-subtle disabled:opacity-50",
562
562
  children: [/* @__PURE__ */ _(h, {
563
563
  size: 12,
564
- className: z ? "animate-spin" : ""
564
+ className: R ? "animate-spin" : ""
565
565
  }), "Generate Signing Secret"]
566
566
  }),
567
- V && /* @__PURE__ */ _("p", {
567
+ B && /* @__PURE__ */ _("p", {
568
568
  className: "text-xs text-amber-600 dark:text-amber-400",
569
569
  children: "New secret generated. Copy it now — the old secret is already invalidated."
570
570
  })
@@ -587,7 +587,7 @@ var b = () => {
587
587
  })
588
588
  })
589
589
  }),
590
- Ke && /* @__PURE__ */ v("div", {
590
+ Je && /* @__PURE__ */ v("div", {
591
591
  className: "rounded-lg border border-border-subtle bg-bg-sunken p-4 space-y-2",
592
592
  children: [/* @__PURE__ */ v("p", {
593
593
  className: "text-sm font-medium text-text-primary flex items-center gap-2",
@@ -615,11 +615,11 @@ var b = () => {
615
615
  },
616
616
  {
617
617
  label: E("devportal.checkSaved", "All changes saved"),
618
- ok: !F
618
+ ok: !P
619
619
  },
620
620
  ...K?.appType === "NODE" || K?.appType === "WORKFLOW" ? [{
621
621
  label: E("devportal.checkVersion", "At least one version uploaded"),
622
- ok: (U?.application?.versions?.totalCount ?? 0) > 0
622
+ ok: (H?.application?.versions?.totalCount ?? 0) > 0
623
623
  }] : []
624
624
  ].map((e) => /* @__PURE__ */ v("div", {
625
625
  className: "flex items-center gap-2 text-sm",
@@ -641,7 +641,7 @@ var b = () => {
641
641
  className: "flex items-center justify-end",
642
642
  children: /* @__PURE__ */ _("button", {
643
643
  type: "submit",
644
- disabled: D || !F || !w,
644
+ disabled: D || !P || !w,
645
645
  "aria-disabled": !w,
646
646
  className: "inline-flex items-center gap-2 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90 transition-colors disabled:opacity-50",
647
647
  children: D ? /* @__PURE__ */ v(g, { children: [/* @__PURE__ */ _("span", { className: "h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent" }), E("devportal.saving", "Saving...")] }) : /* @__PURE__ */ v(g, { children: [/* @__PURE__ */ _(Ce, { size: 16 }), E("devportal.saveChanges", "Save Changes")] })
@@ -660,15 +660,15 @@ var b = () => {
660
660
  /* @__PURE__ */ v("div", {
661
661
  className: "mt-4 flex gap-3",
662
662
  children: [
663
- qe && /* @__PURE__ */ v("button", {
663
+ Ye && /* @__PURE__ */ v("button", {
664
664
  type: "button",
665
- onClick: () => N(!0),
665
+ onClick: () => M(!0),
666
666
  className: "inline-flex items-center gap-2 rounded-md border border-accent-orange bg-bg-surface px-3 py-1.5 text-sm font-medium text-accent-orange hover:bg-accent-orange-subtle transition-colors",
667
667
  children: [/* @__PURE__ */ _(_e, { size: 14 }), E("devportal.deprecateApp", "Deprecate App")]
668
668
  }),
669
- Je && /* @__PURE__ */ v("button", {
669
+ Xe && /* @__PURE__ */ v("button", {
670
670
  type: "button",
671
- onClick: () => P(!0),
671
+ onClick: () => N(!0),
672
672
  className: "inline-flex items-center gap-2 rounded-md border border-accent-orange bg-bg-surface px-3 py-1.5 text-sm font-medium text-accent-orange hover:bg-accent-orange-subtle transition-colors",
673
673
  children: [/* @__PURE__ */ _(Se, { size: 14 }), E("devportal.deactivateApp", "Deactivate App")]
674
674
  }),
@@ -687,32 +687,43 @@ var b = () => {
687
687
  })
688
688
  ]
689
689
  }),
690
- /* @__PURE__ */ _(c, {
690
+ /* @__PURE__ */ _(s, {
691
+ open: Ve,
692
+ onOpenChange: G,
693
+ title: E("devportal.rotateSigningSecret", "Rotate signing secret"),
694
+ description: E("devportal.rotateSigningSecretConfirm", "A new signing secret is created and the current one stops working straight away. Update every integration that verifies this app's signatures first, or they will start failing."),
695
+ confirmLabel: E("devportal.rotateSecret", "Rotate secret"),
696
+ variant: "warning",
697
+ onConfirm: async () => {
698
+ await $(), G(!1);
699
+ }
700
+ }),
701
+ /* @__PURE__ */ _(s, {
691
702
  open: je,
692
703
  onOpenChange: j,
693
704
  title: E("devportal.deleteApplication", "Delete Application"),
694
705
  description: E("devportal.deleteApplicationConfirm", `Are you sure you want to delete "${K.name}"? This action cannot be undone. All OAuth clients, API keys, webhooks, and analytics data will be permanently deleted.`),
695
706
  confirmLabel: E("devportal.deleteApplication", "Delete Application"),
696
707
  variant: "destructive",
697
- onConfirm: Ue
708
+ onConfirm: Ge
698
709
  }),
699
- /* @__PURE__ */ _(c, {
700
- open: M,
701
- onOpenChange: N,
710
+ /* @__PURE__ */ _(s, {
711
+ open: Me,
712
+ onOpenChange: M,
702
713
  title: E("devportal.deprecateApplication", "Deprecate Application"),
703
714
  description: E("devportal.deprecateApplicationConfirm", `Are you sure you want to deprecate "${K.name}"? Existing users will still be able to use the app, but it will no longer be visible in the marketplace and new installations will be disabled.`),
704
715
  confirmLabel: E("devportal.deprecateApplication", "Deprecate Application"),
705
716
  variant: "warning",
706
- onConfirm: We
717
+ onConfirm: Ke
707
718
  }),
708
- /* @__PURE__ */ _(c, {
709
- open: Me,
710
- onOpenChange: P,
719
+ /* @__PURE__ */ _(s, {
720
+ open: Ne,
721
+ onOpenChange: N,
711
722
  title: E("devportal.deactivateApplication", "Deactivate Application"),
712
723
  description: E("devportal.deactivateApplicationConfirm", `Are you sure you want to deactivate "${K.name}"? This will revoke all active tokens and disable the app from the auth-svc layer. The app will no longer be able to authenticate or act on behalf of users.`),
713
724
  confirmLabel: E("devportal.deactivateApplication", "Deactivate Application"),
714
725
  variant: "destructive",
715
- onConfirm: Ge
726
+ onConfirm: qe
716
727
  })
717
728
  ]
718
729
  })