@burdenoff/microfe-devportal 2026.917.2 → 2026.918.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/devportal/components/MultiSelectCombobox.d.ts +38 -0
- package/dist/devportal/components/MultiSelectCombobox.d.ts.map +1 -0
- package/dist/devportal/components/MultiSelectCombobox.js +80 -0
- package/dist/devportal/components/MultiSelectCombobox.js.map +1 -0
- package/dist/devportal/components/ReportOrderIssueModal.d.ts.map +1 -1
- package/dist/devportal/components/ReportOrderIssueModal.js.map +1 -1
- package/dist/devportal/hooks/usePackageUpload.d.ts.map +1 -1
- package/dist/devportal/hooks/usePackageUpload.js.map +1 -1
- package/dist/devportal/pages/ApplicationDetailPage.d.ts.map +1 -1
- package/dist/devportal/pages/ApplicationDetailPage.js.map +1 -1
- package/dist/devportal/pages/CreateApplicationPage.d.ts.map +1 -1
- package/dist/devportal/pages/CreateApplicationPage.js +204 -217
- package/dist/devportal/pages/CreateApplicationPage.js.map +1 -1
- package/dist/devportal/pages/CreatePhysicalItemPage.d.ts.map +1 -1
- package/dist/devportal/pages/CreatePhysicalItemPage.js.map +1 -1
- package/dist/devportal/pages/EditApplicationPage.d.ts.map +1 -1
- package/dist/devportal/pages/EditApplicationPage.js +142 -154
- package/dist/devportal/pages/EditApplicationPage.js.map +1 -1
- package/dist/devportal/pages/EditPhysicalItemPage.d.ts.map +1 -1
- package/dist/devportal/pages/EditPhysicalItemPage.js.map +1 -1
- package/dist/devportal/pages/PublishPage.d.ts.map +1 -1
- package/dist/devportal/pages/PublishPage.js.map +1 -1
- package/dist/devportal/pages/SellerDashboardPage.d.ts.map +1 -1
- package/dist/devportal/pages/SellerDashboardPage.js.map +1 -1
- package/dist/devportal/pages/SellerItemsPage.d.ts.map +1 -1
- package/dist/devportal/pages/SellerItemsPage.js.map +1 -1
- package/dist/devportal/types/index.d.ts.map +1 -1
- package/dist/devportal/types/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EditPhysicalItemPage.js","names":[],"sources":["../../../src/devportal/pages/EditPhysicalItemPage.tsx"],"sourcesContent":["import type { FC, ChangeEvent } from \"react\";\nimport { useState, useEffect } from \"react\";\nimport { useParams } from \"react-router\";\nimport {\n Loader2,\n AlertCircle,\n Info,\n Edit as EditIcon,\n CheckCircle,\n Clock,\n XCircle,\n ImageOff,\n} from \"lucide-react\";\nimport { EmphasisPanel, GlassCard } from \"@burdenoff/fe-libs/ui\";\nimport { PageLayout, PageSection } from \"../components/PageLayout\";\nimport {\n InputField,\n TextareaField,\n SelectField,\n CheckboxField,\n} from \"../components/FormField\";\nimport { ImageUploadField, ScreenshotGallery } from \"../components/ImageUploadField\";\nimport { DetailList } from \"../components/DataTable\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport { usePackageUpload } from \"../hooks/usePackageUpload\";\nimport { cn } from \"../utils/cn\";\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\ninterface FormState {\n name: 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 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 \"shortDescription\",\n \"price\",\n \"currency\",\n \"stockQuantity\",\n];\n\nconst PRODUCT_TYPE_LABELS: Record<string, string> = {\n MERCHANDISE: \"Merchandise\",\n HARDWARE: \"Hardware\",\n ACCESSORY: \"Accessory\",\n BOOK: \"Book\",\n EQUIPMENT: \"Equipment\",\n APPAREL: \"Apparel\",\n COLLECTIBLE: \"Collectible\",\n CONSUMABLE: \"Consumable\",\n};\n\nconst STATUS_BADGE_STYLES: Record<\n string,\n { label: string; className: string }\n> = {\n PUBLISHED: {\n label: \"Published\",\n className: \"text-status-success-text bg-status-success-bg-subtle\",\n },\n PENDING_REVIEW: {\n label: \"Pending Review\",\n className: \"text-status-warning-text bg-status-warning-bg-subtle\",\n },\n DRAFT: {\n label: \"Draft\",\n className: \"text-text-muted bg-bg-muted\",\n },\n REJECTED: {\n label: \"Rejected\",\n className: \"text-status-error-text bg-status-error-bg/10\",\n },\n INACTIVE: {\n label: \"Inactive\",\n className: \"text-text-muted bg-bg-muted\",\n },\n};\n\ntype TabId = \"overview\" | \"edit\";\n\n// ─── GraphQL ──────────────────────────────────────────────────────────────────\n\nconst GET_PRODUCT_QUERY = /* GraphQL */ `\n query GetPhysicalProduct($id: ID!) {\n product(id: $id) {\n id\n name\n slug\n type\n status\n nature\n description\n longDescription\n price\n currency\n tags\n stockQuantity\n sku\n trackInventory\n allowBackorder\n lowStockThreshold\n requiresShipping\n weight\n weightUnit\n length\n width\n height\n dimensionUnit\n brand\n manufacturer\n countryOfOrigin\n warrantyInfo\n returnPolicy\n icon\n bannerUrl\n screenshots\n category\n viewCount\n rating\n reviewCount\n createdAt\n updatedAt\n submittedAt\n reviewedAt\n reviewNotes\n rejectedReason\n publishedAt\n }\n }\n`;\n\nconst UPDATE_PHYSICAL_PRODUCT_MUTATION = /* GraphQL */ `\n mutation UpdatePhysicalProduct(\n $id: ID!\n $input: UpdatePhysicalProductInput!\n ) {\n updatePhysicalProduct(id: $id, input: $input) {\n id\n name\n status\n }\n }\n`;\n\nconst SUBMIT_PRODUCT_MUTATION = /* GraphQL */ `\n mutation SubmitProductForReview($id: ID!, $notes: String) {\n submitProduct(id: $id, notes: $notes) {\n id\n status\n }\n }\n`;\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\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 String(value).trim() !== \"\";\n });\n}\n\nconst StatCard: FC<{ label: string; value: string }> = ({ label, value }) => (\n <GlassCard treatment=\"metric\" className=\"p-4\">\n <p className=\"text-sm text-text-secondary\">{label}</p>\n <p className=\"text-2xl font-bold tabular-nums\">{value}</p>\n </GlassCard>\n);\n\n// ─── Component ────────────────────────────────────────────────────────────────\n\nexport const EditPhysicalItemPage: FC = () => {\n const {\n navigate,\n basePath,\n apiGatewayUrl,\n authToken,\n workspacesGatewayUrl,\n workspaceId,\n getWorkspaceToken,\n } = useDevportal();\n const { itemId } = useParams<{ itemId: string }>();\n\n const endpoint = `${apiGatewayUrl || \"\"}/global/graphql`;\n\n const [loadingProduct, setLoadingProduct] = useState(true);\n const [loadError, setLoadError] = useState<string | null>(null);\n const [productStatus, setProductStatus] = useState<string | null>(null);\n const [activeTab, setActiveTab] = useState<TabId>(\"overview\");\n\n interface OverviewInfo {\n slug: string;\n type: string;\n category: string | null;\n viewCount: number;\n rating: number | null;\n reviewCount: number;\n createdAt: string;\n updatedAt: string;\n submittedAt: string | null;\n reviewedAt: string | null;\n reviewNotes: string | null;\n rejectedReason: string | null;\n publishedAt: string | null;\n }\n const [overview, setOverview] = useState<OverviewInfo | null>(null);\n\n const [form, setForm] = useState<FormState>({\n name: \"\",\n shortDescription: \"\",\n longDescription: \"\",\n price: \"\",\n currency: \"USD\",\n tags: \"\",\n stockQuantity: \"0\",\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 [saving, setSaving] = useState(false);\n const [saveError, setSaveError] = useState<string | null>(null);\n const [saveSuccess, setSaveSuccess] = useState(false);\n\n const imagesUploading = iconUploading || bannerUploading || screenshotUploading;\n const isValid = isFormValid(form) && !imagesUploading;\n\n // ─── GQL 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 // ─── Load product ─────────────────────────────────────────────────────────\n\n useEffect(() => {\n if (!itemId) return;\n let cancelled = false;\n setLoadingProduct(true);\n setLoadError(null);\n\n const run = async () => {\n try {\n const data = await gqlFetch<{\n product: {\n id: string;\n name: string;\n slug: string;\n type: string;\n status: string;\n description: string | null;\n longDescription: string | null;\n price: number;\n currency: string;\n tags: string[] | null;\n stockQuantity: number;\n sku: string | null;\n trackInventory: boolean | null;\n allowBackorder: boolean | null;\n lowStockThreshold: number | null;\n requiresShipping: boolean | null;\n weight: number | null;\n weightUnit: string | null;\n length: number | null;\n width: number | null;\n height: number | null;\n dimensionUnit: string | null;\n brand: string | null;\n manufacturer: string | null;\n countryOfOrigin: string | null;\n warrantyInfo: string | null;\n returnPolicy: string | null;\n icon: string | null;\n bannerUrl: string | null;\n screenshots: string[] | null;\n category: string | null;\n viewCount: number;\n rating: number | null;\n reviewCount: number;\n createdAt: string;\n updatedAt: string;\n submittedAt: string | null;\n reviewedAt: string | null;\n reviewNotes: string | null;\n rejectedReason: string | null;\n publishedAt: string | null;\n } | null;\n }>(GET_PRODUCT_QUERY, { id: itemId });\n\n if (cancelled) return;\n const p = data.product;\n if (!p) {\n setLoadError(\"Product not found.\");\n return;\n }\n\n setProductStatus(p.status);\n setForm({\n name: p.name,\n shortDescription: p.description ?? \"\",\n longDescription: p.longDescription ?? \"\",\n price: String(p.price),\n currency: p.currency || \"USD\",\n tags: (p.tags ?? []).join(\", \"),\n stockQuantity: String(p.stockQuantity),\n sku: p.sku ?? \"\",\n trackInventory: p.trackInventory ?? true,\n allowBackorder: p.allowBackorder ?? false,\n lowStockThreshold:\n p.lowStockThreshold != null ? String(p.lowStockThreshold) : \"\",\n requiresShipping: p.requiresShipping ?? true,\n weightKg: p.weight != null ? String(p.weight) : \"\",\n weightUnit: p.weightUnit ?? \"KILOGRAM\",\n length: p.length != null ? String(p.length) : \"\",\n width: p.width != null ? String(p.width) : \"\",\n height: p.height != null ? String(p.height) : \"\",\n dimensionUnit: p.dimensionUnit ?? \"CENTIMETER\",\n brand: p.brand ?? \"\",\n manufacturer: p.manufacturer ?? \"\",\n countryOfOrigin: p.countryOfOrigin ?? \"\",\n warrantyInfo: p.warrantyInfo ?? \"\",\n returnPolicy: p.returnPolicy ?? \"\",\n });\n setOverview({\n slug: p.slug,\n type: p.type,\n category: p.category,\n viewCount: p.viewCount,\n rating: p.rating,\n reviewCount: p.reviewCount,\n createdAt: p.createdAt,\n updatedAt: p.updatedAt,\n submittedAt: p.submittedAt,\n reviewedAt: p.reviewedAt,\n reviewNotes: p.reviewNotes,\n rejectedReason: p.rejectedReason,\n publishedAt: p.publishedAt,\n });\n setIcon(p.icon ?? \"\");\n setBannerUrl(p.bannerUrl ?? \"\");\n setScreenshots(p.screenshots ?? []);\n } catch (err) {\n if (!cancelled) {\n setLoadError(\n err instanceof Error ? err.message : \"Failed to load product\",\n );\n }\n } finally {\n if (!cancelled) setLoadingProduct(false);\n }\n };\n\n void run();\n return () => {\n cancelled = true;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [itemId, endpoint, authToken]);\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 handleCheckboxChange =\n (key: \"trackInventory\" | \"requiresShipping\" | \"allowBackorder\") =>\n (e: ChangeEvent<HTMLInputElement>) => {\n setField(key, e.target.checked);\n };\n\n // ─── Save ─────────────────────────────────────────────────────────────────\n\n const handleSave = async (andResubmit = false) => {\n if (!isValid || saving || !itemId) return;\n setSaving(true);\n setSaveError(null);\n setSaveSuccess(false);\n\n try {\n const parsedTags = form.tags\n .split(\",\")\n .map((t) => t.trim())\n .filter(Boolean);\n const hasDimensions =\n form.length.trim() || form.width.trim() || form.height.trim();\n\n await gqlFetch(UPDATE_PHYSICAL_PRODUCT_MUTATION, {\n id: itemId,\n input: {\n name: form.name.trim(),\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 },\n });\n\n if (andResubmit) {\n await gqlFetch(SUBMIT_PRODUCT_MUTATION, {\n id: itemId,\n notes: \"Resubmitted after edits\",\n });\n }\n\n setSaveSuccess(true);\n setTimeout(() => {\n navigate?.(`${basePath}/seller/items`);\n }, 1500);\n } catch (err) {\n setSaveError(\n err instanceof Error ? err.message : \"Save failed. Please try again.\",\n );\n } finally {\n setSaving(false);\n }\n };\n\n // ─── Render ───────────────────────────────────────────────────────────────\n\n if (loadingProduct) {\n return (\n <PageLayout\n title=\"Edit Item\"\n backLink=\"/seller/items\"\n backLabel=\"Back to My Items\"\n >\n <div className=\"flex items-center justify-center py-20\">\n <Loader2 className=\"h-8 w-8 animate-spin text-text-secondary\" />\n </div>\n </PageLayout>\n );\n }\n\n if (loadError) {\n return (\n <PageLayout\n title=\"Edit Item\"\n backLink=\"/seller/items\"\n backLabel=\"Back to My Items\"\n >\n <div className=\"flex items-center gap-3 rounded-lg border border-status-error-border/50 bg-status-error-bg/10 px-4 py-3 text-sm\">\n <AlertCircle size={16} className=\"shrink-0 text-status-error-text\" />\n <span className=\"text-status-error-text\">{loadError}</span>\n </div>\n </PageLayout>\n );\n }\n\n const isDraft = productStatus === \"DRAFT\" || productStatus === \"REJECTED\";\n const canResubmit = isDraft;\n const statusStyle = productStatus\n ? STATUS_BADGE_STYLES[productStatus]\n : undefined;\n\n return (\n <PageLayout\n title={\n <div className=\"flex items-center gap-3\">\n {icon ? (\n <img\n src={icon}\n alt=\"\"\n className=\"h-10 w-10 shrink-0 rounded-input border border-border-subtle object-cover\"\n />\n ) : (\n <div className=\"flex h-10 w-10 shrink-0 items-center justify-center rounded-input border border-border-subtle bg-bg-sunken\">\n <ImageOff size={16} className=\"text-text-muted\" />\n </div>\n )}\n <span>{form.name || \"Item\"}</span>\n </div>\n }\n description={form.shortDescription || undefined}\n purpose=\"Everything about this listing in one place — its performance, its store presence, and its editable details. Use the tabs to review or update it.\"\n backLink=\"/seller/items\"\n backLabel=\"Back to My Items\"\n actions={\n activeTab === \"overview\" ? (\n <button\n type=\"button\"\n onClick={() => setActiveTab(\"edit\")}\n className=\"inline-flex items-center gap-2 rounded-button bg-action-primary-bg px-5 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90 transition-colors\"\n >\n <EditIcon size={15} />\n Edit Listing\n </button>\n ) : undefined\n }\n >\n <div className=\"space-y-6\">\n {/* Success banner */}\n {saveSuccess && (\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 Saved successfully! Redirecting to your items...\n </div>\n )}\n\n {/* Error banner */}\n {saveError && (\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 {saveError}\n </div>\n )}\n\n {/* Status badges */}\n <div className=\"flex flex-wrap items-center gap-2\">\n {statusStyle && (\n <span\n className={cn(\n \"inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium\",\n statusStyle.className,\n )}\n >\n {statusStyle.label}\n </span>\n )}\n <span className=\"text-sm text-text-secondary\">\n {PRODUCT_TYPE_LABELS[overview?.type ?? \"\"] || overview?.type}\n </span>\n {overview?.category && (\n <span className=\"rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs text-text-secondary\">\n {overview.category}\n </span>\n )}\n </div>\n\n {/* Status banner */}\n {productStatus === \"PENDING_REVIEW\" && (\n <div className=\"flex items-start gap-3 rounded-lg border border-border-subtle bg-status-warning-bg-subtle p-4\">\n <Clock\n size={18}\n className=\"text-status-warning-text mt-0.5 flex-shrink-0\"\n />\n <div className=\"text-sm\">\n <p className=\"font-medium text-status-warning-text\">\n Under Review\n </p>\n <p className=\"mt-0.5 text-text-secondary\">\n Your listing is being reviewed by our team. You'll be notified\n of the outcome.\n {overview?.submittedAt && (\n <span className=\"ml-1\">\n Submitted{\" \"}\n {new Date(overview.submittedAt).toLocaleDateString()}.\n </span>\n )}\n </p>\n </div>\n </div>\n )}\n {productStatus === \"REJECTED\" && (\n <div className=\"flex items-start gap-3 rounded-lg border border-status-error-bg bg-status-error-bg-subtle p-4\">\n <XCircle\n size={18}\n className=\"text-status-error-text mt-0.5 flex-shrink-0\"\n />\n <div className=\"text-sm\">\n <p className=\"font-medium text-status-error-text\">\n Review Rejected\n </p>\n <p className=\"mt-0.5 text-text-secondary\">\n {overview?.rejectedReason ||\n overview?.reviewNotes ||\n \"Your submission was not approved. Please review the feedback, update your listing, and re-submit.\"}\n </p>\n <button\n type=\"button\"\n onClick={() => setActiveTab(\"edit\")}\n className=\"mt-2 inline-flex items-center gap-1 text-xs font-medium text-primary underline\"\n >\n Edit listing and re-submit →\n </button>\n </div>\n </div>\n )}\n {productStatus === \"PUBLISHED\" && (\n <div className=\"flex items-start gap-3 rounded-lg border border-status-success-bg bg-status-success-bg-subtle p-4\">\n <CheckCircle\n size={18}\n className=\"text-status-success-text mt-0.5 flex-shrink-0\"\n />\n <div className=\"text-sm\">\n <p className=\"font-medium text-status-success-text\">\n Live in the Store\n </p>\n <p className=\"mt-0.5 text-text-secondary\">\n Your listing is published and visible to buyers in the\n marketplace.\n </p>\n </div>\n </div>\n )}\n\n {/* Tabs */}\n <div className=\"border-b\">\n <nav\n className=\"-mb-px flex gap-4 overflow-x-auto\"\n role=\"tablist\"\n aria-label=\"Item sections\"\n >\n {(\n [\n { id: \"overview\" as const, label: \"Overview\" },\n { id: \"edit\" as const, label: \"Edit Listing\" },\n ] satisfies { id: TabId; label: string }[]\n ).map((tab) => (\n <button\n key={tab.id}\n id={`item-tab-${tab.id}`}\n role=\"tab\"\n aria-selected={activeTab === tab.id}\n aria-controls={`item-panel-${tab.id}`}\n onClick={() => setActiveTab(tab.id)}\n className={cn(\n \"flex items-center gap-2 border-b-2 px-1 py-3 text-sm font-medium transition-colors\",\n activeTab === tab.id\n ? \"border-primary text-primary\"\n : \"border-transparent text-text-secondary hover:text-text-primary hover:border-muted-foreground\",\n )}\n >\n {tab.label}\n </button>\n ))}\n </nav>\n </div>\n\n {/* ── Overview tab ── */}\n {activeTab === \"overview\" && (\n <div\n id=\"item-panel-overview\"\n role=\"tabpanel\"\n aria-labelledby=\"item-tab-overview\"\n className=\"grid gap-6 lg:grid-cols-3\"\n >\n <div className=\"lg:col-span-2 space-y-6\">\n <EmphasisPanel>\n <div className=\"grid gap-4 sm:grid-cols-4\">\n <StatCard\n label=\"Price\"\n value={`${form.currency} ${Number(form.price || 0).toFixed(2)}`}\n />\n <StatCard label=\"Stock\" value={form.stockQuantity || \"0\"} />\n <StatCard\n label=\"Views\"\n value={(overview?.viewCount ?? 0).toLocaleString()}\n />\n <StatCard\n label=\"Rating\"\n value={\n overview?.rating\n ? `${overview.rating.toFixed(1)} ★`\n : \"N/A\"\n }\n />\n </div>\n </EmphasisPanel>\n\n <PageSection title=\"Product Images\">\n {icon || bannerUrl || screenshots.length > 0 ? (\n <div className=\"space-y-4\">\n <div className=\"flex flex-wrap gap-4\">\n {icon && (\n <div className=\"space-y-1\">\n <img\n src={icon}\n alt=\"Icon\"\n className=\"h-24 w-24 rounded-input border border-border-subtle object-cover\"\n />\n <p className=\"text-xs text-text-muted\">Icon</p>\n </div>\n )}\n {bannerUrl && (\n <div className=\"space-y-1\">\n <img\n src={bannerUrl}\n alt=\"Banner\"\n className=\"h-24 w-24 rounded-input border border-border-subtle object-cover\"\n />\n <p className=\"text-xs text-text-muted\">Banner</p>\n </div>\n )}\n </div>\n {screenshots.length > 0 && (\n <div className=\"space-y-1\">\n <p className=\"text-xs text-text-muted\">Screenshots</p>\n <div className=\"flex flex-wrap gap-3\">\n {screenshots.map((url, i) => (\n <img\n key={url}\n src={url}\n alt={`Screenshot ${i + 1}`}\n className=\"h-24 w-36 rounded-input border border-border-subtle object-cover\"\n />\n ))}\n </div>\n </div>\n )}\n </div>\n ) : (\n <p className=\"text-sm text-text-secondary\">\n No images uploaded yet.\n </p>\n )}\n </PageSection>\n\n <PageSection title=\"Description\">\n {form.shortDescription && (\n <p className=\"text-sm font-medium text-text-primary\">\n {form.shortDescription}\n </p>\n )}\n {form.longDescription ? (\n <p className=\"mt-2 whitespace-pre-wrap text-sm text-text-secondary\">\n {form.longDescription}\n </p>\n ) : (\n !form.shortDescription && (\n <p className=\"text-sm text-text-secondary\">\n No description provided.\n </p>\n )\n )}\n </PageSection>\n\n {form.tags && (\n <PageSection title=\"Tags\">\n <div className=\"flex flex-wrap gap-2\">\n {form.tags\n .split(\",\")\n .map((t) => t.trim())\n .filter(Boolean)\n .map((tag) => (\n <span\n key={tag}\n className=\"rounded-full bg-action-primary-bg/10 px-3 py-1 text-xs font-medium text-primary\"\n >\n {tag}\n </span>\n ))}\n </div>\n </PageSection>\n )}\n </div>\n\n {/* Sidebar */}\n <div className=\"space-y-6\">\n <PageSection title=\"Details\">\n <DetailList\n items={[\n {\n label: \"Item ID\",\n value: <code className=\"text-xs\">{itemId}</code>,\n },\n { label: \"Slug\", value: overview?.slug ?? \"—\" },\n {\n label: \"SKU\",\n value: form.sku || \"—\",\n },\n {\n label: \"Brand\",\n value: form.brand || \"—\",\n },\n {\n label: \"Created\",\n value: overview?.createdAt\n ? new Date(overview.createdAt).toLocaleDateString()\n : \"—\",\n },\n {\n label: \"Updated\",\n value: overview?.updatedAt\n ? new Date(overview.updatedAt).toLocaleDateString()\n : \"—\",\n },\n ...(overview?.publishedAt\n ? [\n {\n label: \"Published\",\n value: new Date(\n overview.publishedAt,\n ).toLocaleDateString(),\n },\n ]\n : []),\n ]}\n />\n </PageSection>\n\n <PageSection title=\"Inventory & Shipping\">\n <DetailList\n items={[\n {\n label: \"Stock quantity\",\n value: form.stockQuantity || \"0\",\n },\n {\n label: \"Track inventory\",\n value: form.trackInventory ? \"Yes\" : \"No\",\n },\n {\n label: \"Requires shipping\",\n value: form.requiresShipping ? \"Yes\" : \"No\",\n },\n ...(form.requiresShipping && form.weightKg\n ? [\n {\n label: \"Weight\",\n value: `${form.weightKg} ${form.weightUnit.toLowerCase()}`,\n },\n ]\n : []),\n ]}\n />\n </PageSection>\n </div>\n </div>\n )}\n\n {/* ── Edit Listing tab ── */}\n {activeTab === \"edit\" && (\n <div\n id=\"item-panel-edit\"\n role=\"tabpanel\"\n aria-labelledby=\"item-tab-edit\"\n className=\"space-y-8 max-w-3xl\"\n >\n {/* Status notice */}\n {productStatus && (\n <div 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 Current status:{\" \"}\n <span className=\"font-medium text-text-primary\">\n {productStatus.replace(/_/g, \" \")}\n </span>\n {canResubmit && (\n <span className=\"ml-1\">\n — use \"Save & Resubmit\" to send it for review again.\n </span>\n )}\n </div>\n )}\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={(e) => setField(\"name\", e.target.value)}\n placeholder=\"e.g. Wireless Ergonomic Keyboard\"\n maxLength={120}\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 1b: 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 2: 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.\"\n />\n </div>\n </PageSection>\n\n {/* ── Section 3: 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) =>\n setField(\"lowStockThreshold\", e.target.value)\n }\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 4: 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) =>\n setField(\"dimensionUnit\", e.target.value)\n }\n options={DIMENSION_UNITS}\n hint=\"Applies to length, width, and height above.\"\n />\n </>\n )}\n </div>\n </PageSection>\n\n {/* ── Section 5: 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 flex-wrap 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 <button\n type=\"button\"\n onClick={() => void handleSave(false)}\n disabled={!isValid || saving}\n aria-disabled={!isValid || saving}\n title={\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 \"border border-border-strong bg-bg-surface text-text-primary\",\n \"hover:bg-bg-sunken\",\n \"disabled:opacity-50 disabled:cursor-not-allowed\",\n )}\n >\n {saving ? (\n <>\n <Loader2 size={15} className=\"animate-spin\" />\n Saving...\n </>\n ) : (\n \"Save Changes\"\n )}\n </button>\n\n {canResubmit && (\n <button\n type=\"button\"\n onClick={() => void handleSave(true)}\n disabled={!isValid || saving}\n aria-disabled={!isValid || saving}\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 )}\n >\n {saving ? (\n <>\n <Loader2 size={15} className=\"animate-spin\" />\n Saving...\n </>\n ) : (\n \"Save & Resubmit for Review\"\n )}\n </button>\n )}\n </div>\n </div>\n )}\n </div>\n </PageLayout>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"EditPhysicalItemPage.js","names":[],"sources":["../../../src/devportal/pages/EditPhysicalItemPage.tsx"],"sourcesContent":["import type { FC, ChangeEvent } from \"react\";\nimport { useState, useEffect } from \"react\";\nimport { useParams } from \"react-router\";\nimport {\n Loader2,\n AlertCircle,\n Info,\n Edit as EditIcon,\n CheckCircle,\n Clock,\n XCircle,\n ImageOff,\n} from \"lucide-react\";\nimport { EmphasisPanel, GlassCard } from \"@burdenoff/fe-libs/ui\";\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 { DetailList } from \"../components/DataTable\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport { usePackageUpload } from \"../hooks/usePackageUpload\";\nimport { cn } from \"../utils/cn\";\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\ninterface FormState {\n name: 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 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 \"shortDescription\",\n \"price\",\n \"currency\",\n \"stockQuantity\",\n];\n\nconst PRODUCT_TYPE_LABELS: Record<string, string> = {\n MERCHANDISE: \"Merchandise\",\n HARDWARE: \"Hardware\",\n ACCESSORY: \"Accessory\",\n BOOK: \"Book\",\n EQUIPMENT: \"Equipment\",\n APPAREL: \"Apparel\",\n COLLECTIBLE: \"Collectible\",\n CONSUMABLE: \"Consumable\",\n};\n\nconst STATUS_BADGE_STYLES: Record<\n string,\n { label: string; className: string }\n> = {\n PUBLISHED: {\n label: \"Published\",\n className: \"text-status-success-text bg-status-success-bg-subtle\",\n },\n PENDING_REVIEW: {\n label: \"Pending Review\",\n className: \"text-status-warning-text bg-status-warning-bg-subtle\",\n },\n DRAFT: {\n label: \"Draft\",\n className: \"text-text-muted bg-bg-muted\",\n },\n REJECTED: {\n label: \"Rejected\",\n className: \"text-status-error-text bg-status-error-bg/10\",\n },\n INACTIVE: {\n label: \"Inactive\",\n className: \"text-text-muted bg-bg-muted\",\n },\n};\n\ntype TabId = \"overview\" | \"edit\";\n\n// ─── GraphQL ──────────────────────────────────────────────────────────────────\n\nconst GET_PRODUCT_QUERY = /* GraphQL */ `\n query GetPhysicalProduct($id: ID!) {\n product(id: $id) {\n id\n name\n slug\n type\n status\n nature\n description\n longDescription\n price\n currency\n tags\n stockQuantity\n sku\n trackInventory\n allowBackorder\n lowStockThreshold\n requiresShipping\n weight\n weightUnit\n length\n width\n height\n dimensionUnit\n brand\n manufacturer\n countryOfOrigin\n warrantyInfo\n returnPolicy\n icon\n bannerUrl\n screenshots\n category\n viewCount\n rating\n reviewCount\n createdAt\n updatedAt\n submittedAt\n reviewedAt\n reviewNotes\n rejectedReason\n publishedAt\n }\n }\n`;\n\nconst UPDATE_PHYSICAL_PRODUCT_MUTATION = /* GraphQL */ `\n mutation UpdatePhysicalProduct(\n $id: ID!\n $input: UpdatePhysicalProductInput!\n ) {\n updatePhysicalProduct(id: $id, input: $input) {\n id\n name\n status\n }\n }\n`;\n\nconst SUBMIT_PRODUCT_MUTATION = /* GraphQL */ `\n mutation SubmitProductForReview($id: ID!, $notes: String) {\n submitProduct(id: $id, notes: $notes) {\n id\n status\n }\n }\n`;\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\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 String(value).trim() !== \"\";\n });\n}\n\nconst StatCard: FC<{ label: string; value: string }> = ({ label, value }) => (\n <GlassCard treatment=\"metric\" className=\"p-4\">\n <p className=\"text-sm text-text-secondary\">{label}</p>\n <p className=\"text-2xl font-bold tabular-nums\">{value}</p>\n </GlassCard>\n);\n\n// ─── Component ────────────────────────────────────────────────────────────────\n\nexport const EditPhysicalItemPage: FC = () => {\n const {\n navigate,\n basePath,\n apiGatewayUrl,\n authToken,\n workspacesGatewayUrl,\n workspaceId,\n getWorkspaceToken,\n } = useDevportal();\n const { itemId } = useParams<{ itemId: string }>();\n\n const endpoint = `${apiGatewayUrl || \"\"}/global/graphql`;\n\n const [loadingProduct, setLoadingProduct] = useState(true);\n const [loadError, setLoadError] = useState<string | null>(null);\n const [productStatus, setProductStatus] = useState<string | null>(null);\n const [activeTab, setActiveTab] = useState<TabId>(\"overview\");\n\n interface OverviewInfo {\n slug: string;\n type: string;\n category: string | null;\n viewCount: number;\n rating: number | null;\n reviewCount: number;\n createdAt: string;\n updatedAt: string;\n submittedAt: string | null;\n reviewedAt: string | null;\n reviewNotes: string | null;\n rejectedReason: string | null;\n publishedAt: string | null;\n }\n const [overview, setOverview] = useState<OverviewInfo | null>(null);\n\n const [form, setForm] = useState<FormState>({\n name: \"\",\n shortDescription: \"\",\n longDescription: \"\",\n price: \"\",\n currency: \"USD\",\n tags: \"\",\n stockQuantity: \"0\",\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 [saving, setSaving] = useState(false);\n const [saveError, setSaveError] = useState<string | null>(null);\n const [saveSuccess, setSaveSuccess] = useState(false);\n\n const imagesUploading =\n iconUploading || bannerUploading || screenshotUploading;\n const isValid = isFormValid(form) && !imagesUploading;\n\n // ─── GQL 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 // ─── Load product ─────────────────────────────────────────────────────────\n\n useEffect(() => {\n if (!itemId) return;\n let cancelled = false;\n setLoadingProduct(true);\n setLoadError(null);\n\n const run = async () => {\n try {\n const data = await gqlFetch<{\n product: {\n id: string;\n name: string;\n slug: string;\n type: string;\n status: string;\n description: string | null;\n longDescription: string | null;\n price: number;\n currency: string;\n tags: string[] | null;\n stockQuantity: number;\n sku: string | null;\n trackInventory: boolean | null;\n allowBackorder: boolean | null;\n lowStockThreshold: number | null;\n requiresShipping: boolean | null;\n weight: number | null;\n weightUnit: string | null;\n length: number | null;\n width: number | null;\n height: number | null;\n dimensionUnit: string | null;\n brand: string | null;\n manufacturer: string | null;\n countryOfOrigin: string | null;\n warrantyInfo: string | null;\n returnPolicy: string | null;\n icon: string | null;\n bannerUrl: string | null;\n screenshots: string[] | null;\n category: string | null;\n viewCount: number;\n rating: number | null;\n reviewCount: number;\n createdAt: string;\n updatedAt: string;\n submittedAt: string | null;\n reviewedAt: string | null;\n reviewNotes: string | null;\n rejectedReason: string | null;\n publishedAt: string | null;\n } | null;\n }>(GET_PRODUCT_QUERY, { id: itemId });\n\n if (cancelled) return;\n const p = data.product;\n if (!p) {\n setLoadError(\"Product not found.\");\n return;\n }\n\n setProductStatus(p.status);\n setForm({\n name: p.name,\n shortDescription: p.description ?? \"\",\n longDescription: p.longDescription ?? \"\",\n price: String(p.price),\n currency: p.currency || \"USD\",\n tags: (p.tags ?? []).join(\", \"),\n stockQuantity: String(p.stockQuantity),\n sku: p.sku ?? \"\",\n trackInventory: p.trackInventory ?? true,\n allowBackorder: p.allowBackorder ?? false,\n lowStockThreshold:\n p.lowStockThreshold != null ? String(p.lowStockThreshold) : \"\",\n requiresShipping: p.requiresShipping ?? true,\n weightKg: p.weight != null ? String(p.weight) : \"\",\n weightUnit: p.weightUnit ?? \"KILOGRAM\",\n length: p.length != null ? String(p.length) : \"\",\n width: p.width != null ? String(p.width) : \"\",\n height: p.height != null ? String(p.height) : \"\",\n dimensionUnit: p.dimensionUnit ?? \"CENTIMETER\",\n brand: p.brand ?? \"\",\n manufacturer: p.manufacturer ?? \"\",\n countryOfOrigin: p.countryOfOrigin ?? \"\",\n warrantyInfo: p.warrantyInfo ?? \"\",\n returnPolicy: p.returnPolicy ?? \"\",\n });\n setOverview({\n slug: p.slug,\n type: p.type,\n category: p.category,\n viewCount: p.viewCount,\n rating: p.rating,\n reviewCount: p.reviewCount,\n createdAt: p.createdAt,\n updatedAt: p.updatedAt,\n submittedAt: p.submittedAt,\n reviewedAt: p.reviewedAt,\n reviewNotes: p.reviewNotes,\n rejectedReason: p.rejectedReason,\n publishedAt: p.publishedAt,\n });\n setIcon(p.icon ?? \"\");\n setBannerUrl(p.bannerUrl ?? \"\");\n setScreenshots(p.screenshots ?? []);\n } catch (err) {\n if (!cancelled) {\n setLoadError(\n err instanceof Error ? err.message : \"Failed to load product\",\n );\n }\n } finally {\n if (!cancelled) setLoadingProduct(false);\n }\n };\n\n void run();\n return () => {\n cancelled = true;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [itemId, endpoint, authToken]);\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 handleCheckboxChange =\n (key: \"trackInventory\" | \"requiresShipping\" | \"allowBackorder\") =>\n (e: ChangeEvent<HTMLInputElement>) => {\n setField(key, e.target.checked);\n };\n\n // ─── Save ─────────────────────────────────────────────────────────────────\n\n const handleSave = async (andResubmit = false) => {\n if (!isValid || saving || !itemId) return;\n setSaving(true);\n setSaveError(null);\n setSaveSuccess(false);\n\n try {\n const parsedTags = form.tags\n .split(\",\")\n .map((t) => t.trim())\n .filter(Boolean);\n const hasDimensions =\n form.length.trim() || form.width.trim() || form.height.trim();\n\n await gqlFetch(UPDATE_PHYSICAL_PRODUCT_MUTATION, {\n id: itemId,\n input: {\n name: form.name.trim(),\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 },\n });\n\n if (andResubmit) {\n await gqlFetch(SUBMIT_PRODUCT_MUTATION, {\n id: itemId,\n notes: \"Resubmitted after edits\",\n });\n }\n\n setSaveSuccess(true);\n setTimeout(() => {\n navigate?.(`${basePath}/seller/items`);\n }, 1500);\n } catch (err) {\n setSaveError(\n err instanceof Error ? err.message : \"Save failed. Please try again.\",\n );\n } finally {\n setSaving(false);\n }\n };\n\n // ─── Render ───────────────────────────────────────────────────────────────\n\n if (loadingProduct) {\n return (\n <PageLayout\n title=\"Edit Item\"\n backLink=\"/seller/items\"\n backLabel=\"Back to My Items\"\n >\n <div className=\"flex items-center justify-center py-20\">\n <Loader2 className=\"h-8 w-8 animate-spin text-text-secondary\" />\n </div>\n </PageLayout>\n );\n }\n\n if (loadError) {\n return (\n <PageLayout\n title=\"Edit Item\"\n backLink=\"/seller/items\"\n backLabel=\"Back to My Items\"\n >\n <div className=\"flex items-center gap-3 rounded-lg border border-status-error-border/50 bg-status-error-bg/10 px-4 py-3 text-sm\">\n <AlertCircle size={16} className=\"shrink-0 text-status-error-text\" />\n <span className=\"text-status-error-text\">{loadError}</span>\n </div>\n </PageLayout>\n );\n }\n\n const isDraft = productStatus === \"DRAFT\" || productStatus === \"REJECTED\";\n const canResubmit = isDraft;\n const statusStyle = productStatus\n ? STATUS_BADGE_STYLES[productStatus]\n : undefined;\n\n return (\n <PageLayout\n title={\n <div className=\"flex items-center gap-3\">\n {icon ? (\n <img\n src={icon}\n alt=\"\"\n className=\"h-10 w-10 shrink-0 rounded-input border border-border-subtle object-cover\"\n />\n ) : (\n <div className=\"flex h-10 w-10 shrink-0 items-center justify-center rounded-input border border-border-subtle bg-bg-sunken\">\n <ImageOff size={16} className=\"text-text-muted\" />\n </div>\n )}\n <span>{form.name || \"Item\"}</span>\n </div>\n }\n description={form.shortDescription || undefined}\n purpose=\"Everything about this listing in one place — its performance, its store presence, and its editable details. Use the tabs to review or update it.\"\n backLink=\"/seller/items\"\n backLabel=\"Back to My Items\"\n actions={\n activeTab === \"overview\" ? (\n <button\n type=\"button\"\n onClick={() => setActiveTab(\"edit\")}\n className=\"inline-flex items-center gap-2 rounded-button bg-action-primary-bg px-5 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90 transition-colors\"\n >\n <EditIcon size={15} />\n Edit Listing\n </button>\n ) : undefined\n }\n >\n <div className=\"space-y-6\">\n {/* Success banner */}\n {saveSuccess && (\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 Saved successfully! Redirecting to your items...\n </div>\n )}\n\n {/* Error banner */}\n {saveError && (\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 {saveError}\n </div>\n )}\n\n {/* Status badges */}\n <div className=\"flex flex-wrap items-center gap-2\">\n {statusStyle && (\n <span\n className={cn(\n \"inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium\",\n statusStyle.className,\n )}\n >\n {statusStyle.label}\n </span>\n )}\n <span className=\"text-sm text-text-secondary\">\n {PRODUCT_TYPE_LABELS[overview?.type ?? \"\"] || overview?.type}\n </span>\n {overview?.category && (\n <span className=\"rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs text-text-secondary\">\n {overview.category}\n </span>\n )}\n </div>\n\n {/* Status banner */}\n {productStatus === \"PENDING_REVIEW\" && (\n <div className=\"flex items-start gap-3 rounded-lg border border-border-subtle bg-status-warning-bg-subtle p-4\">\n <Clock\n size={18}\n className=\"text-status-warning-text mt-0.5 flex-shrink-0\"\n />\n <div className=\"text-sm\">\n <p className=\"font-medium text-status-warning-text\">\n Under Review\n </p>\n <p className=\"mt-0.5 text-text-secondary\">\n Your listing is being reviewed by our team. You'll be notified\n of the outcome.\n {overview?.submittedAt && (\n <span className=\"ml-1\">\n Submitted{\" \"}\n {new Date(overview.submittedAt).toLocaleDateString()}.\n </span>\n )}\n </p>\n </div>\n </div>\n )}\n {productStatus === \"REJECTED\" && (\n <div className=\"flex items-start gap-3 rounded-lg border border-status-error-bg bg-status-error-bg-subtle p-4\">\n <XCircle\n size={18}\n className=\"text-status-error-text mt-0.5 flex-shrink-0\"\n />\n <div className=\"text-sm\">\n <p className=\"font-medium text-status-error-text\">\n Review Rejected\n </p>\n <p className=\"mt-0.5 text-text-secondary\">\n {overview?.rejectedReason ||\n overview?.reviewNotes ||\n \"Your submission was not approved. Please review the feedback, update your listing, and re-submit.\"}\n </p>\n <button\n type=\"button\"\n onClick={() => setActiveTab(\"edit\")}\n className=\"mt-2 inline-flex items-center gap-1 text-xs font-medium text-primary underline\"\n >\n Edit listing and re-submit →\n </button>\n </div>\n </div>\n )}\n {productStatus === \"PUBLISHED\" && (\n <div className=\"flex items-start gap-3 rounded-lg border border-status-success-bg bg-status-success-bg-subtle p-4\">\n <CheckCircle\n size={18}\n className=\"text-status-success-text mt-0.5 flex-shrink-0\"\n />\n <div className=\"text-sm\">\n <p className=\"font-medium text-status-success-text\">\n Live in the Store\n </p>\n <p className=\"mt-0.5 text-text-secondary\">\n Your listing is published and visible to buyers in the\n marketplace.\n </p>\n </div>\n </div>\n )}\n\n {/* Tabs */}\n <div className=\"border-b\">\n <nav\n className=\"-mb-px flex gap-4 overflow-x-auto\"\n role=\"tablist\"\n aria-label=\"Item sections\"\n >\n {(\n [\n { id: \"overview\" as const, label: \"Overview\" },\n { id: \"edit\" as const, label: \"Edit Listing\" },\n ] satisfies { id: TabId; label: string }[]\n ).map((tab) => (\n <button\n key={tab.id}\n id={`item-tab-${tab.id}`}\n role=\"tab\"\n aria-selected={activeTab === tab.id}\n aria-controls={`item-panel-${tab.id}`}\n onClick={() => setActiveTab(tab.id)}\n className={cn(\n \"flex items-center gap-2 border-b-2 px-1 py-3 text-sm font-medium transition-colors\",\n activeTab === tab.id\n ? \"border-primary text-primary\"\n : \"border-transparent text-text-secondary hover:text-text-primary hover:border-muted-foreground\",\n )}\n >\n {tab.label}\n </button>\n ))}\n </nav>\n </div>\n\n {/* ── Overview tab ── */}\n {activeTab === \"overview\" && (\n <div\n id=\"item-panel-overview\"\n role=\"tabpanel\"\n aria-labelledby=\"item-tab-overview\"\n className=\"grid gap-6 lg:grid-cols-3\"\n >\n <div className=\"lg:col-span-2 space-y-6\">\n <EmphasisPanel>\n <div className=\"grid gap-4 sm:grid-cols-4\">\n <StatCard\n label=\"Price\"\n value={`${form.currency} ${Number(form.price || 0).toFixed(2)}`}\n />\n <StatCard label=\"Stock\" value={form.stockQuantity || \"0\"} />\n <StatCard\n label=\"Views\"\n value={(overview?.viewCount ?? 0).toLocaleString()}\n />\n <StatCard\n label=\"Rating\"\n value={\n overview?.rating\n ? `${overview.rating.toFixed(1)} ★`\n : \"N/A\"\n }\n />\n </div>\n </EmphasisPanel>\n\n <PageSection title=\"Product Images\">\n {icon || bannerUrl || screenshots.length > 0 ? (\n <div className=\"space-y-4\">\n <div className=\"flex flex-wrap gap-4\">\n {icon && (\n <div className=\"space-y-1\">\n <img\n src={icon}\n alt=\"Icon\"\n className=\"h-24 w-24 rounded-input border border-border-subtle object-cover\"\n />\n <p className=\"text-xs text-text-muted\">Icon</p>\n </div>\n )}\n {bannerUrl && (\n <div className=\"space-y-1\">\n <img\n src={bannerUrl}\n alt=\"Banner\"\n className=\"h-24 w-24 rounded-input border border-border-subtle object-cover\"\n />\n <p className=\"text-xs text-text-muted\">Banner</p>\n </div>\n )}\n </div>\n {screenshots.length > 0 && (\n <div className=\"space-y-1\">\n <p className=\"text-xs text-text-muted\">Screenshots</p>\n <div className=\"flex flex-wrap gap-3\">\n {screenshots.map((url, i) => (\n <img\n key={url}\n src={url}\n alt={`Screenshot ${i + 1}`}\n className=\"h-24 w-36 rounded-input border border-border-subtle object-cover\"\n />\n ))}\n </div>\n </div>\n )}\n </div>\n ) : (\n <p className=\"text-sm text-text-secondary\">\n No images uploaded yet.\n </p>\n )}\n </PageSection>\n\n <PageSection title=\"Description\">\n {form.shortDescription && (\n <p className=\"text-sm font-medium text-text-primary\">\n {form.shortDescription}\n </p>\n )}\n {form.longDescription ? (\n <p className=\"mt-2 whitespace-pre-wrap text-sm text-text-secondary\">\n {form.longDescription}\n </p>\n ) : (\n !form.shortDescription && (\n <p className=\"text-sm text-text-secondary\">\n No description provided.\n </p>\n )\n )}\n </PageSection>\n\n {form.tags && (\n <PageSection title=\"Tags\">\n <div className=\"flex flex-wrap gap-2\">\n {form.tags\n .split(\",\")\n .map((t) => t.trim())\n .filter(Boolean)\n .map((tag) => (\n <span\n key={tag}\n className=\"rounded-full bg-action-primary-bg/10 px-3 py-1 text-xs font-medium text-primary\"\n >\n {tag}\n </span>\n ))}\n </div>\n </PageSection>\n )}\n </div>\n\n {/* Sidebar */}\n <div className=\"space-y-6\">\n <PageSection title=\"Details\">\n <DetailList\n items={[\n {\n label: \"Item ID\",\n value: <code className=\"text-xs\">{itemId}</code>,\n },\n { label: \"Slug\", value: overview?.slug ?? \"—\" },\n {\n label: \"SKU\",\n value: form.sku || \"—\",\n },\n {\n label: \"Brand\",\n value: form.brand || \"—\",\n },\n {\n label: \"Created\",\n value: overview?.createdAt\n ? new Date(overview.createdAt).toLocaleDateString()\n : \"—\",\n },\n {\n label: \"Updated\",\n value: overview?.updatedAt\n ? new Date(overview.updatedAt).toLocaleDateString()\n : \"—\",\n },\n ...(overview?.publishedAt\n ? [\n {\n label: \"Published\",\n value: new Date(\n overview.publishedAt,\n ).toLocaleDateString(),\n },\n ]\n : []),\n ]}\n />\n </PageSection>\n\n <PageSection title=\"Inventory & Shipping\">\n <DetailList\n items={[\n {\n label: \"Stock quantity\",\n value: form.stockQuantity || \"0\",\n },\n {\n label: \"Track inventory\",\n value: form.trackInventory ? \"Yes\" : \"No\",\n },\n {\n label: \"Requires shipping\",\n value: form.requiresShipping ? \"Yes\" : \"No\",\n },\n ...(form.requiresShipping && form.weightKg\n ? [\n {\n label: \"Weight\",\n value: `${form.weightKg} ${form.weightUnit.toLowerCase()}`,\n },\n ]\n : []),\n ]}\n />\n </PageSection>\n </div>\n </div>\n )}\n\n {/* ── Edit Listing tab ── */}\n {activeTab === \"edit\" && (\n <div\n id=\"item-panel-edit\"\n role=\"tabpanel\"\n aria-labelledby=\"item-tab-edit\"\n className=\"space-y-8 max-w-3xl\"\n >\n {/* Status notice */}\n {productStatus && (\n <div 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 Current status:{\" \"}\n <span className=\"font-medium text-text-primary\">\n {productStatus.replace(/_/g, \" \")}\n </span>\n {canResubmit && (\n <span className=\"ml-1\">\n — use \"Save & Resubmit\" to send it for review again.\n </span>\n )}\n </div>\n )}\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={(e) => setField(\"name\", e.target.value)}\n placeholder=\"e.g. Wireless Ergonomic Keyboard\"\n maxLength={120}\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 1b: 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 2: 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.\"\n />\n </div>\n </PageSection>\n\n {/* ── Section 3: 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) =>\n setField(\"lowStockThreshold\", e.target.value)\n }\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 4: 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) =>\n setField(\"dimensionUnit\", e.target.value)\n }\n options={DIMENSION_UNITS}\n hint=\"Applies to length, width, and height above.\"\n />\n </>\n )}\n </div>\n </PageSection>\n\n {/* ── Section 5: 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 flex-wrap 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 <button\n type=\"button\"\n onClick={() => void handleSave(false)}\n disabled={!isValid || saving}\n aria-disabled={!isValid || saving}\n title={\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 \"border border-border-strong bg-bg-surface text-text-primary\",\n \"hover:bg-bg-sunken\",\n \"disabled:opacity-50 disabled:cursor-not-allowed\",\n )}\n >\n {saving ? (\n <>\n <Loader2 size={15} className=\"animate-spin\" />\n Saving...\n </>\n ) : (\n \"Save Changes\"\n )}\n </button>\n\n {canResubmit && (\n <button\n type=\"button\"\n onClick={() => void handleSave(true)}\n disabled={!isValid || saving}\n aria-disabled={!isValid || saving}\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 )}\n >\n {saving ? (\n <>\n <Loader2 size={15} className=\"animate-spin\" />\n Saving...\n </>\n ) : (\n \"Save & Resubmit for Review\"\n )}\n </button>\n )}\n </div>\n </div>\n )}\n </div>\n </PageLayout>\n );\n};\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PublishPage.d.ts","sourceRoot":"","sources":["../../../src/devportal/pages/PublishPage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AA2EhC,eAAO,MAAM,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"PublishPage.d.ts","sourceRoot":"","sources":["../../../src/devportal/pages/PublishPage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AA2EhC,eAAO,MAAM,WAAW,EAAE,EAguBzB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PublishPage.js","names":[],"sources":["../../../src/devportal/pages/PublishPage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useEffect, useState, useMemo } from \"react\";\nimport { useParams } from \"react-router\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport {\n CheckCircle,\n XCircle,\n AlertTriangle,\n Send,\n FileText,\n Shield,\n Image,\n Globe,\n Loader2,\n Eye,\n ArrowRight,\n PartyPopper,\n Link,\n Webhook,\n KeyRound,\n} from \"lucide-react\";\nimport { gql } from \"@apollo/client\";\nimport { useQuery } from \"@apollo/client/react\";\nimport { PageLayout, PageSection } from \"../components/PageLayout\";\nimport { Alert } from \"../components/ConfirmDialog\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport { PermissionGuard } from \"../components\";\nimport { DEVPORTAL_PERMISSIONS } from \"../constants/permissions\";\nimport {\n useGetApplicationQuery,\n useSubmitApplicationMutation,\n useSubmitApplicationForReviewMutation,\n} from \"../../generated/global-operations\";\nimport { useDevportalPermission } from \"../hooks\";\n\nconst MY_PUBLISHER_QUERY = gql`\n query PublishPagePublisher {\n myPublisher {\n id\n }\n }\n`;\nconst PUBLISHER_PRODUCTS_QUERY = gql`\n query PublishPageProducts($publisherId: String!) {\n products(filter: { publisherId: $publisherId }) {\n id\n productId\n }\n }\n`;\nconst APP_WEBHOOKS_QUERY = gql`\n query PublishPageWebhooks($applicationId: ID!) {\n webhooks(applicationId: $applicationId) {\n id\n }\n }\n`;\n\ninterface ChecklistItem {\n id: string;\n label: string;\n description: string;\n status: \"passed\" | \"failed\" | \"warning\" | \"pending\";\n icon: React.ReactNode;\n actionLabel?: string;\n actionPath?: string;\n}\n\nconst ALREADY_SUBMITTED_STATUSES = [\n \"SUBMITTED\",\n \"IN_REVIEW\",\n \"APPROVED\",\n \"PUBLISHED\",\n];\n\nexport const PublishPage: FC = () => {\n const { appId } = useParams<{ appId: string }>();\n const { navigate, basePath } = useDevportal();\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n };\n const [submitting, setSubmitting] = useState(false);\n const [submitError, setSubmitError] = useState<string | null>(null);\n const [submitted, setSubmitted] = useState(false);\n const [notes, setNotes] = useState(\"\");\n const submitPerm = useDevportalPermission(DEVPORTAL_PERMISSIONS.APP_SUBMIT);\n\n const {\n data,\n loading,\n error: queryError,\n } = useGetApplicationQuery({\n variables: { id: appId! },\n skip: !appId,\n fetchPolicy: \"network-only\",\n });\n\n const [submitApplication] = useSubmitApplicationMutation();\n const [submitApplicationForReview] = useSubmitApplicationForReviewMutation();\n\n // Two-step publisher lookup to find linked StoreProduct\n const { data: publisherData } = useQuery<{\n myPublisher: { id: string } | null;\n }>(MY_PUBLISHER_QUERY, { fetchPolicy: \"cache-first\" });\n const publisherId = publisherData?.myPublisher?.id ?? null;\n const { data: productsData } = useQuery<{\n products: { id: string; productId?: string | null }[];\n }>(PUBLISHER_PRODUCTS_QUERY, {\n variables: { publisherId: publisherId ?? \"\" },\n skip: !publisherId,\n fetchPolicy: \"cache-first\",\n });\n const linkedStoreProductId =\n productsData?.products?.find(\n (p: { id: string; productId?: string | null }) => p.productId === appId,\n )?.id ?? null;\n\n const isApiIntegration = data?.application?.appType === \"API_INTEGRATION\";\n const appManifest = data?.application?.manifest as\n Record<string, unknown> | null | undefined;\n const appOauth = appManifest?.[\"oauth\"] as\n Record<string, unknown> | undefined;\n const hasOAuthUrl = !!(\n appOauth?.[\"authorizationUrl\"] &&\n appOauth?.[\"tokenUrl\"] &&\n appOauth?.[\"clientId\"]\n );\n\n const { data: webhooksData } = useQuery<{ webhooks: { id: string }[] }>(\n APP_WEBHOOKS_QUERY,\n {\n variables: { applicationId: appId! },\n skip: !appId || !isApiIntegration,\n fetchPolicy: \"network-only\",\n },\n );\n const webhookCount = webhooksData?.webhooks?.length ?? 0;\n\n const app = data?.application;\n\n useEffect(() => {\n const name = app?.name;\n if (!appId || !name) return;\n const reg = (\n window as unknown as {\n __breadcrumbRegistry?: {\n register: (id: string, name: string) => void;\n unregister: (id: string) => void;\n };\n }\n ).__breadcrumbRegistry;\n reg?.register(appId, name);\n return () => reg?.unregister(appId);\n }, [appId, app?.name]);\n\n const isAlreadySubmitted = ALREADY_SUBMITTED_STATUSES.includes(\n app?.status ?? \"\",\n );\n\n const isPackageType = app?.appType === \"NODE\" || app?.appType === \"WORKFLOW\";\n const publishedVersionCount = app?.versions?.totalCount ?? 0;\n\n const checklist = useMemo((): ChecklistItem[] => {\n if (!app) return [];\n\n const screenshotCount = app.screenshots?.length ?? 0;\n\n const storeListingPath = `/apps/${appId}?tab=store-listing`;\n const versionsPath = `/apps/${appId}/versions`;\n const editPath = `/apps/${appId}/edit#oauth-config`;\n const webhooksPath = `/apps/${appId}/webhooks`;\n\n const items: ChecklistItem[] = [\n {\n id: \"name\",\n label: tr(\"devportal.checklistNameLabel\", \"Name & Short Description\"),\n description: tr(\n \"devportal.checklistNameDesc\",\n \"Name and short description are required for the store card\",\n ),\n status: app.name && app.shortDescription ? \"passed\" : \"failed\",\n icon: <FileText size={20} />,\n actionLabel: \"Edit store listing →\",\n actionPath: storeListingPath,\n },\n {\n id: \"category\",\n label: tr(\"devportal.checklistCategoryLabel\", \"Category\"),\n description: tr(\n \"devportal.checklistCategoryDesc\",\n \"A category helps users find your item in the marketplace\",\n ),\n status: app.category ? \"passed\" : \"failed\",\n icon: <Globe size={20} />,\n actionLabel: \"Edit app info →\",\n actionPath: `/apps/${appId}/edit`,\n },\n {\n id: \"privacy\",\n label: tr(\"devportal.checklistPrivacyLabel\", \"Privacy Policy\"),\n description: tr(\n \"devportal.checklistPrivacyDesc\",\n \"Privacy policy URL is required for store submission\",\n ),\n status: app.privacyPolicyUrl ? \"passed\" : \"failed\",\n icon: <Shield size={20} />,\n actionLabel: \"Edit store listing →\",\n actionPath: storeListingPath,\n },\n {\n id: \"terms\",\n label: tr(\"devportal.checklistTermsLabel\", \"Terms of Service\"),\n description: tr(\n \"devportal.checklistTermsDesc\",\n \"Terms of service URL is required for store submission\",\n ),\n status: app.termsOfServiceUrl ? \"passed\" : \"failed\",\n icon: <FileText size={20} />,\n actionLabel: \"Edit store listing →\",\n actionPath: storeListingPath,\n },\n {\n id: \"icon\",\n label: tr(\"devportal.checklistIconLabel\", \"App Icon\"),\n description: tr(\n \"devportal.checklistIconDesc\",\n \"An icon makes your listing stand out in the marketplace\",\n ),\n status: app.iconUrl ? \"passed\" : \"warning\",\n icon: <Image size={20} />,\n actionLabel: \"Edit store listing →\",\n actionPath: storeListingPath,\n },\n {\n id: \"screenshots\",\n label: tr(\"devportal.checklistScreenshotsLabel\", \"Screenshots\"),\n description: tr(\n \"devportal.checklistScreenshotsDesc\",\n \"At least 3 screenshots are recommended\",\n ),\n status:\n screenshotCount >= 3\n ? \"passed\"\n : screenshotCount > 0\n ? \"warning\"\n : \"warning\",\n icon: <Image size={20} />,\n actionLabel: \"Edit store listing →\",\n actionPath: storeListingPath,\n },\n ];\n\n if (isPackageType) {\n items.push({\n id: \"version\",\n label: tr(\"devportal.checklistVersionLabel\", \"Published Version\"),\n description: tr(\n \"devportal.checklistVersionDesc\",\n app?.appType === \"WORKFLOW\"\n ? \"At least one published version (manifest JSON) is required before submitting to the store\"\n : \"At least one published version (ZIP + manifest) is required before submitting to the store\",\n ),\n status: publishedVersionCount > 0 ? \"passed\" : \"failed\",\n icon: <CheckCircle size={20} />,\n actionLabel: \"Create a version →\",\n actionPath: versionsPath,\n });\n }\n\n if (app.appType === \"API_INTEGRATION\") {\n items.push({\n id: \"oauth\",\n label: tr(\"devportal.checklistOAuthLabel\", \"OAuth Configuration\"),\n description: tr(\n \"devportal.checklistOAuthDesc\",\n \"Authorization URL, Token URL and Client ID are required so users can connect their accounts. Without these the Connect button does not work.\",\n ),\n status: hasOAuthUrl ? \"passed\" : \"failed\",\n icon: <KeyRound size={20} />,\n actionLabel: \"Configure in Edit App →\",\n actionPath: editPath,\n });\n\n items.push({\n id: \"webhook\",\n label: tr(\"devportal.checklistWebhookLabel\", \"Webhook Endpoint\"),\n description: tr(\n \"devportal.checklistWebhookDesc\",\n \"At least one webhook endpoint must be configured so your server receives platform events after users connect. Without this the integration does nothing.\",\n ),\n status: webhookCount > 0 ? \"passed\" : \"failed\",\n icon: <Webhook size={20} />,\n actionLabel: \"Add a webhook →\",\n actionPath: webhooksPath,\n });\n\n items.push({\n id: \"documentation\",\n label: tr(\"devportal.checklistDocsLabel\", \"Documentation URL\"),\n description: tr(\n \"devportal.checklistDocsDesc\",\n \"Users need to know how to use and configure this integration. A documentation link is required for API integrations.\",\n ),\n status: app.documentationUrl ? \"passed\" : \"failed\",\n icon: <FileText size={20} />,\n actionLabel: \"Add documentation URL →\",\n actionPath: editPath,\n });\n\n items.push({\n id: \"website\",\n label: tr(\"devportal.checklistWebsiteLabel\", \"Website URL\"),\n description: tr(\n \"devportal.checklistWebsiteDesc\",\n \"Users need to verify who built this integration. A website URL is required so users know where to get support.\",\n ),\n status: app.websiteUrl ? \"passed\" : \"failed\",\n icon: <Link size={20} />,\n actionLabel: \"Add website URL →\",\n actionPath: editPath,\n });\n }\n\n items.push({\n id: \"status\",\n label: tr(\"devportal.checklistStatusLabel\", \"App Status\"),\n description: tr(\n \"devportal.checklistStatusDesc\",\n \"App must be in DRAFT or REJECTED state to submit\",\n ),\n status: [\"DRAFT\", \"REJECTED\"].includes(app.status ?? \"\")\n ? \"passed\"\n : \"warning\",\n icon: <CheckCircle size={20} />,\n });\n\n return items;\n }, [\n app,\n isPackageType,\n publishedVersionCount,\n webhookCount,\n hasOAuthUrl,\n appId,\n ]);\n\n const passedCount = checklist.filter((i) => i.status === \"passed\").length;\n const failedCount = checklist.filter((i) => i.status === \"failed\").length;\n const warningCount = checklist.filter((i) => i.status === \"warning\").length;\n const isSubmittableStatus = [\"DRAFT\", \"REJECTED\"].includes(app?.status ?? \"\");\n const canSubmit =\n !loading &&\n !queryError &&\n failedCount === 0 &&\n !!app &&\n !isAlreadySubmitted &&\n isSubmittableStatus;\n\n const getStatusIcon = (status: ChecklistItem[\"status\"]) => {\n switch (status) {\n case \"passed\":\n return <CheckCircle size={20} className=\"text-status-success-text\" />;\n case \"failed\":\n return <XCircle size={20} className=\"text-status-error-text\" />;\n case \"warning\":\n return <AlertTriangle size={20} className=\"text-status-warning-text\" />;\n default:\n return (\n <div className=\"h-5 w-5 rounded-full border-2 border-border-default\" />\n );\n }\n };\n\n const getStatusBg = (status: ChecklistItem[\"status\"]) => {\n switch (status) {\n case \"passed\":\n return \"bg-status-success-bg-subtle border-border-subtle\";\n case \"failed\":\n return \"bg-status-error-bg-subtle border-border-subtle\";\n case \"warning\":\n return \"bg-status-warning-bg-subtle border-border-subtle\";\n default:\n return \"bg-bg-canvas border-border-subtle\";\n }\n };\n\n const handleSubmit = async () => {\n if (!appId) return;\n setSubmitting(true);\n setSubmitError(null);\n try {\n // Submit Application for devportal review (sets Application.status = SUBMITTED)\n const result = await submitApplication({\n variables: { id: appId, notes: notes.trim() || undefined },\n });\n if (result.error) throw result.error;\n\n // Also submit ApplicationForReview to set StoreProduct.status = PENDING_REVIEW\n // so it appears in the store admin review queue at /store/dashboard/submissions\n await submitApplicationForReview({\n variables: { id: appId, notes: notes.trim() || undefined },\n });\n\n setSubmitted(true);\n } catch (err) {\n setSubmitError(\n err instanceof Error\n ? err.message\n : tr(\"devportal.submitFailedDefault\", \"Failed to submit for review\"),\n );\n } finally {\n setSubmitting(false);\n }\n };\n\n if (loading) {\n return (\n <PageLayout\n title={tr(\"devportal.publishToStoreTitle\", \"Publish to Store\")}\n description={tr(\n \"devportal.loadingApplicationDetails\",\n \"Loading application details...\",\n )}\n backLink={`/apps/${appId}`}\n backLabel={tr(\"devportal.backToApplication\", \"Back to Application\")}\n >\n <div className=\"flex items-center justify-center py-12\">\n <Loader2 className=\"animate-spin h-8 w-8 text-text-secondary\" />\n </div>\n </PageLayout>\n );\n }\n\n if (queryError || !app) {\n return (\n <PageLayout\n title={tr(\"devportal.publishToStoreTitle\", \"Publish to Store\")}\n description={tr(\n \"devportal.couldNotLoadApplication\",\n \"Could not load application\",\n )}\n backLink={`/apps/${appId}`}\n backLabel={tr(\"devportal.backToApplication\", \"Back to Application\")}\n >\n <Alert\n variant=\"error\"\n title={tr(\n \"devportal.failedToLoadApplication\",\n \"Failed to load application\",\n )}\n >\n {queryError?.message ??\n tr(\"devportal.applicationNotFound\", \"Application not found\")}\n </Alert>\n </PageLayout>\n );\n }\n\n if (submitted) {\n return (\n <PermissionGuard authOnly>\n <PageLayout\n title={tr(\"devportal.publishToStoreTitle\", \"Publish to Store\")}\n backLink={`/apps/${appId}`}\n backLabel={tr(\"devportal.backToApplication\", \"Back to Application\")}\n >\n <div className=\"flex flex-col items-center justify-center py-16 gap-6 text-center\">\n <div className=\"rounded-full bg-status-success-bg p-4\">\n <PartyPopper size={40} className=\"text-status-success-text\" />\n </div>\n <div className=\"space-y-2\">\n <h2 className=\"text-2xl font-bold\">\n {tr(\"devportal.submittedSuccessTitle\", \"Submitted for Review!\")}\n </h2>\n <p className=\"text-muted-foreground max-w-md\">\n {tr(\n \"devportal.submittedSuccessMsg\",\n \"Your app has been submitted to the marketplace review queue. You'll receive email notifications as the review progresses — typically 3–5 business days.\",\n )}\n </p>\n </div>\n <div className=\"rounded-lg border bg-muted/40 px-6 py-4 text-sm text-left space-y-2 max-w-md w-full\">\n <p className=\"font-medium\">What happens next:</p>\n <ul className=\"space-y-1 text-muted-foreground list-none\">\n <li className=\"flex items-start gap-2\">\n <CheckCircle\n size={14}\n className=\"mt-0.5 text-status-success-text shrink-0\"\n />{\" \"}\n Our team reviews your submission\n </li>\n <li className=\"flex items-start gap-2\">\n <CheckCircle\n size={14}\n className=\"mt-0.5 text-status-success-text shrink-0\"\n />{\" \"}\n You'll get an email on approval or if changes are needed\n </li>\n <li className=\"flex items-start gap-2\">\n <CheckCircle\n size={14}\n className=\"mt-0.5 text-status-success-text shrink-0\"\n />{\" \"}\n Once approved, your app goes live in the marketplace\n </li>\n </ul>\n </div>\n <button\n onClick={() => navigate?.(`${basePath}/apps/${appId}`)}\n className=\"inline-flex items-center gap-2 rounded-md border px-4 py-2 text-sm font-medium hover:bg-muted\"\n >\n Back to App\n </button>\n </div>\n </PageLayout>\n </PermissionGuard>\n );\n }\n\n return (\n <PermissionGuard authOnly>\n <PageLayout\n title={tr(\"devportal.publishToStoreTitle\", \"Publish to Store\")}\n description={`${tr(\"devportal.submitAppForReview\", \"Submit\")} \"${app.name}\" ${tr(\"devportal.forReviewAndPublication\", \"for review and publication\")}`}\n purpose={tr(\n \"devportal.publishPurpose\",\n \"Submitting sends your app to the review team, who check it against the marketplace guidelines before it goes live to users. Make sure the listing, screenshots, and permissions are final — preview the listing first, since changes after approval need another review.\",\n )}\n backLink={`/apps/${appId}`}\n backLabel={tr(\"devportal.backToApplication\", \"Back to Application\")}\n actions={\n <button\n onClick={() => navigate?.(`${basePath}/apps/${appId}/listing`)}\n className=\"inline-flex items-center gap-2 rounded-md border px-3 py-2 text-sm font-medium hover:bg-bg-sunken\"\n >\n <Eye size={16} />\n {tr(\"devportal.previewListing\", \"Preview Listing\")}\n </button>\n }\n >\n {isAlreadySubmitted && (\n <Alert\n variant=\"warning\"\n title={tr(\"devportal.alreadySubmittedTitle\", \"Already Submitted\")}\n >\n {tr(\"devportal.alreadySubmittedMsg1\", \"This app is currently in\")}{\" \"}\n <strong>{app.status}</strong>{\" \"}\n {tr(\n \"devportal.alreadySubmittedMsg2\",\n \"state and cannot be re-submitted until the review process is complete or the app is rejected.\",\n )}\n </Alert>\n )}\n\n {/* Progress Summary */}\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6\">\n <h2 className=\"text-lg font-semibold\">\n {tr(\"devportal.preSubmissionChecklist\", \"Pre-submission Checklist\")}\n </h2>\n <p className=\"mt-1 text-sm text-text-secondary\">\n {tr(\n \"devportal.completeAllRequiredItems\",\n \"Complete all required items before submitting for review\",\n )}\n </p>\n <div className=\"mt-4 flex gap-6\">\n <div className=\"flex items-center gap-2\">\n <CheckCircle size={20} className=\"text-status-success-text\" />\n <span>\n {passedCount} {tr(\"devportal.passed\", \"Passed\")}\n </span>\n </div>\n <div className=\"flex items-center gap-2\">\n <XCircle size={20} className=\"text-status-error-text\" />\n <span>\n {failedCount} {tr(\"devportal.failed\", \"Failed\")}\n </span>\n </div>\n <div className=\"flex items-center gap-2\">\n <AlertTriangle size={20} className=\"text-status-warning-text\" />\n <span>\n {warningCount} {tr(\"devportal.warnings\", \"Warnings\")}\n </span>\n </div>\n </div>\n </div>\n\n {/* Checklist Items */}\n <PageSection>\n <div className=\"space-y-3\">\n {checklist.map((item) => (\n <div\n key={item.id}\n className={`flex items-center gap-4 rounded-lg border p-4 ${getStatusBg(item.status)}`}\n >\n <div className=\"rounded-lg bg-bg-surface p-2\">{item.icon}</div>\n <div className=\"flex-1\">\n <p className=\"font-medium\">{item.label}</p>\n <p className=\"text-sm text-text-secondary\">\n {item.description}\n </p>\n {item.status !== \"passed\" && item.actionPath && (\n <button\n type=\"button\"\n onClick={() =>\n navigate?.(`${basePath}${item.actionPath}`)\n }\n className=\"mt-1 inline-flex items-center gap-1 text-xs text-primary hover:underline\"\n >\n {item.actionLabel ?? \"Fix this\"} <ArrowRight size={11} />\n </button>\n )}\n </div>\n {getStatusIcon(item.status)}\n </div>\n ))}\n </div>\n </PageSection>\n\n {/* Submission Notes */}\n {!isAlreadySubmitted && (\n <PageSection\n title={tr(\"devportal.notesForReviewerTitle\", \"Notes for Reviewer\")}\n description={tr(\n \"devportal.notesForReviewerDesc\",\n \"Optional message to the review team\",\n )}\n >\n <textarea\n value={notes}\n onChange={(e) => setNotes(e.target.value)}\n placeholder={tr(\n \"devportal.notesForReviewerPlaceholder\",\n \"Describe what your app does, any special review considerations, or testing instructions...\",\n )}\n rows={4}\n maxLength={1000}\n className=\"w-full rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm ring-offset-background placeholder:text-text-secondary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)] resize-none\"\n />\n <p className=\"mt-1 text-xs text-text-secondary text-right\">\n {notes.length}/1000\n </p>\n </PageSection>\n )}\n\n {/* Alerts */}\n {submitError && (\n <Alert\n variant=\"error\"\n title={tr(\"devportal.submissionFailedTitle\", \"Submission Failed\")}\n >\n {submitError}\n </Alert>\n )}\n\n {failedCount > 0 && !isAlreadySubmitted && (\n <Alert\n variant=\"error\"\n title={tr(\"devportal.cannotSubmitTitle\", \"Cannot Submit Yet\")}\n >\n {tr(\"devportal.pleaseFixItems1\", \"Please fix\")} {failedCount}{\" \"}\n {tr(\n \"devportal.pleaseFixItems2\",\n \"required item(s) before submitting for review.\",\n )}\n <div className=\"mt-2 flex flex-wrap gap-3\">\n <button\n onClick={() => navigate?.(`${basePath}/apps/${appId}`)}\n className=\"text-sm underline hover:no-underline\"\n >\n {tr(\n \"devportal.goToMarketplaceListing\",\n \"Update marketplace listing →\",\n )}\n </button>\n {isPackageType && publishedVersionCount === 0 && (\n <button\n onClick={() =>\n navigate?.(`${basePath}/apps/${appId}/versions`)\n }\n className=\"text-sm underline hover:no-underline\"\n >\n {tr(\"devportal.goToVersions\", \"Add a published version →\")}\n </button>\n )}\n {isApiIntegration && !hasOAuthUrl && (\n <button\n onClick={() =>\n navigate?.(`${basePath}/apps/${appId}/edit#oauth-config`)\n }\n className=\"text-sm underline hover:no-underline\"\n >\n Configure OAuth endpoints →\n </button>\n )}\n {isApiIntegration && webhookCount === 0 && (\n <button\n onClick={() =>\n navigate?.(`${basePath}/apps/${appId}/webhooks`)\n }\n className=\"text-sm underline hover:no-underline\"\n >\n Add a webhook →\n </button>\n )}\n </div>\n </Alert>\n )}\n\n {warningCount > 0 && failedCount === 0 && !isAlreadySubmitted && (\n <Alert\n variant=\"warning\"\n title={tr(\"devportal.warningsTitle\", \"Warnings\")}\n >\n {tr(\"devportal.warningsMsg1\", \"You have\")} {warningCount}{\" \"}\n {tr(\n \"devportal.warningsMsg2\",\n \"warning(s). While you can submit, addressing these may improve your app's chances of approval.\",\n )}\n </Alert>\n )}\n\n {/* Review Process Info */}\n <PageSection\n title={tr(\"devportal.reviewProcessTitle\", \"Review Process\")}\n >\n <div className=\"rounded-lg border bg-bg-sunken/50 p-4\">\n <ul className=\"space-y-2 text-sm\">\n <li className=\"flex items-start gap-2\">\n <CheckCircle size={16} className=\"mt-0.5 text-primary\" />\n <span>\n {tr(\n \"devportal.reviewProcessInfo1\",\n \"Review typically takes 3-5 business days\",\n )}\n </span>\n </li>\n <li className=\"flex items-start gap-2\">\n <CheckCircle size={16} className=\"mt-0.5 text-primary\" />\n <span>\n {tr(\n \"devportal.reviewProcessInfo2\",\n \"You'll receive notifications about review status changes\",\n )}\n </span>\n </li>\n <li className=\"flex items-start gap-2\">\n <CheckCircle size={16} className=\"mt-0.5 text-primary\" />\n <span>\n {tr(\n \"devportal.reviewProcessInfo3\",\n \"If changes are requested, you can resubmit without losing your place in the queue\",\n )}\n </span>\n </li>\n <li className=\"flex items-start gap-2\">\n <CheckCircle size={16} className=\"mt-0.5 text-primary\" />\n <span>\n {tr(\n \"devportal.reviewProcessInfo4\",\n \"Once approved and published, your app will be visible in the marketplace\",\n )}\n </span>\n </li>\n </ul>\n </div>\n </PageSection>\n\n {/* Actions */}\n <div className=\"flex gap-3\">\n <button\n onClick={() => navigate?.(`${basePath}/apps/${appId}`)}\n className=\"rounded-md border px-4 py-2 text-sm font-medium hover:bg-bg-sunken\"\n >\n {tr(\"devportal.cancelButton\", \"Cancel\")}\n </button>\n <button\n onClick={handleSubmit}\n disabled={!canSubmit || submitting || !submitPerm.allowed}\n aria-disabled={!canSubmit || submitting || !submitPerm.allowed}\n title={\n !submitPerm.allowed\n ? tr(\n \"devportal.common.noPermission\",\n \"You do not have permission to perform this action\",\n )\n : undefined\n }\n 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 disabled:opacity-50 disabled:cursor-not-allowed focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n >\n {submitting ? (\n <>\n <Loader2 size={16} className=\"animate-spin\" />\n {tr(\"devportal.submittingButton\", \"Submitting...\")}\n </>\n ) : (\n <>\n <Send size={16} />\n {tr(\"devportal.submitForReviewButton\", \"Submit for Review\")}\n </>\n )}\n </button>\n </div>\n </PageLayout>\n </PermissionGuard>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"PublishPage.js","names":[],"sources":["../../../src/devportal/pages/PublishPage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useEffect, useState, useMemo } from \"react\";\nimport { useParams } from \"react-router\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport {\n CheckCircle,\n XCircle,\n AlertTriangle,\n Send,\n FileText,\n Shield,\n Image,\n Globe,\n Loader2,\n Eye,\n ArrowRight,\n PartyPopper,\n Link,\n Webhook,\n KeyRound,\n} from \"lucide-react\";\nimport { gql } from \"@apollo/client\";\nimport { useQuery } from \"@apollo/client/react\";\nimport { PageLayout, PageSection } from \"../components/PageLayout\";\nimport { Alert } from \"../components/ConfirmDialog\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport { PermissionGuard } from \"../components\";\nimport { DEVPORTAL_PERMISSIONS } from \"../constants/permissions\";\nimport {\n useGetApplicationQuery,\n useSubmitApplicationMutation,\n useSubmitApplicationForReviewMutation,\n} from \"../../generated/global-operations\";\nimport { useDevportalPermission } from \"../hooks\";\n\nconst MY_PUBLISHER_QUERY = gql`\n query PublishPagePublisher {\n myPublisher {\n id\n }\n }\n`;\nconst PUBLISHER_PRODUCTS_QUERY = gql`\n query PublishPageProducts($publisherId: String!) {\n products(filter: { publisherId: $publisherId }) {\n id\n productId\n }\n }\n`;\nconst APP_WEBHOOKS_QUERY = gql`\n query PublishPageWebhooks($applicationId: ID!) {\n webhooks(applicationId: $applicationId) {\n id\n }\n }\n`;\n\ninterface ChecklistItem {\n id: string;\n label: string;\n description: string;\n status: \"passed\" | \"failed\" | \"warning\" | \"pending\";\n icon: React.ReactNode;\n actionLabel?: string;\n actionPath?: string;\n}\n\nconst ALREADY_SUBMITTED_STATUSES = [\n \"SUBMITTED\",\n \"IN_REVIEW\",\n \"APPROVED\",\n \"PUBLISHED\",\n];\n\nexport const PublishPage: FC = () => {\n const { appId } = useParams<{ appId: string }>();\n const { navigate, basePath } = useDevportal();\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n };\n const [submitting, setSubmitting] = useState(false);\n const [submitError, setSubmitError] = useState<string | null>(null);\n const [submitted, setSubmitted] = useState(false);\n const [notes, setNotes] = useState(\"\");\n const submitPerm = useDevportalPermission(DEVPORTAL_PERMISSIONS.APP_SUBMIT);\n\n const {\n data,\n loading,\n error: queryError,\n } = useGetApplicationQuery({\n variables: { id: appId! },\n skip: !appId,\n fetchPolicy: \"network-only\",\n });\n\n const [submitApplication] = useSubmitApplicationMutation();\n const [submitApplicationForReview] = useSubmitApplicationForReviewMutation();\n\n // Two-step publisher lookup to find linked StoreProduct\n const { data: publisherData } = useQuery<{\n myPublisher: { id: string } | null;\n }>(MY_PUBLISHER_QUERY, { fetchPolicy: \"cache-first\" });\n const publisherId = publisherData?.myPublisher?.id ?? null;\n const { data: productsData } = useQuery<{\n products: { id: string; productId?: string | null }[];\n }>(PUBLISHER_PRODUCTS_QUERY, {\n variables: { publisherId: publisherId ?? \"\" },\n skip: !publisherId,\n fetchPolicy: \"cache-first\",\n });\n const linkedStoreProductId =\n productsData?.products?.find(\n (p: { id: string; productId?: string | null }) => p.productId === appId,\n )?.id ?? null;\n\n const isApiIntegration = data?.application?.appType === \"API_INTEGRATION\";\n const appManifest = data?.application?.manifest as\n | Record<string, unknown>\n | null\n | undefined;\n const appOauth = appManifest?.[\"oauth\"] as\n | Record<string, unknown>\n | undefined;\n const hasOAuthUrl = !!(\n appOauth?.[\"authorizationUrl\"] &&\n appOauth?.[\"tokenUrl\"] &&\n appOauth?.[\"clientId\"]\n );\n\n const { data: webhooksData } = useQuery<{ webhooks: { id: string }[] }>(\n APP_WEBHOOKS_QUERY,\n {\n variables: { applicationId: appId! },\n skip: !appId || !isApiIntegration,\n fetchPolicy: \"network-only\",\n },\n );\n const webhookCount = webhooksData?.webhooks?.length ?? 0;\n\n const app = data?.application;\n\n useEffect(() => {\n const name = app?.name;\n if (!appId || !name) return;\n const reg = (\n window as unknown as {\n __breadcrumbRegistry?: {\n register: (id: string, name: string) => void;\n unregister: (id: string) => void;\n };\n }\n ).__breadcrumbRegistry;\n reg?.register(appId, name);\n return () => reg?.unregister(appId);\n }, [appId, app?.name]);\n\n const isAlreadySubmitted = ALREADY_SUBMITTED_STATUSES.includes(\n app?.status ?? \"\",\n );\n\n const isPackageType = app?.appType === \"NODE\" || app?.appType === \"WORKFLOW\";\n const publishedVersionCount = app?.versions?.totalCount ?? 0;\n\n const checklist = useMemo((): ChecklistItem[] => {\n if (!app) return [];\n\n const screenshotCount = app.screenshots?.length ?? 0;\n\n const storeListingPath = `/apps/${appId}?tab=store-listing`;\n const versionsPath = `/apps/${appId}/versions`;\n const editPath = `/apps/${appId}/edit#oauth-config`;\n const webhooksPath = `/apps/${appId}/webhooks`;\n\n const items: ChecklistItem[] = [\n {\n id: \"name\",\n label: tr(\"devportal.checklistNameLabel\", \"Name & Short Description\"),\n description: tr(\n \"devportal.checklistNameDesc\",\n \"Name and short description are required for the store card\",\n ),\n status: app.name && app.shortDescription ? \"passed\" : \"failed\",\n icon: <FileText size={20} />,\n actionLabel: \"Edit store listing →\",\n actionPath: storeListingPath,\n },\n {\n id: \"category\",\n label: tr(\"devportal.checklistCategoryLabel\", \"Category\"),\n description: tr(\n \"devportal.checklistCategoryDesc\",\n \"A category helps users find your item in the marketplace\",\n ),\n status: app.category ? \"passed\" : \"failed\",\n icon: <Globe size={20} />,\n actionLabel: \"Edit app info →\",\n actionPath: `/apps/${appId}/edit`,\n },\n {\n id: \"privacy\",\n label: tr(\"devportal.checklistPrivacyLabel\", \"Privacy Policy\"),\n description: tr(\n \"devportal.checklistPrivacyDesc\",\n \"Privacy policy URL is required for store submission\",\n ),\n status: app.privacyPolicyUrl ? \"passed\" : \"failed\",\n icon: <Shield size={20} />,\n actionLabel: \"Edit store listing →\",\n actionPath: storeListingPath,\n },\n {\n id: \"terms\",\n label: tr(\"devportal.checklistTermsLabel\", \"Terms of Service\"),\n description: tr(\n \"devportal.checklistTermsDesc\",\n \"Terms of service URL is required for store submission\",\n ),\n status: app.termsOfServiceUrl ? \"passed\" : \"failed\",\n icon: <FileText size={20} />,\n actionLabel: \"Edit store listing →\",\n actionPath: storeListingPath,\n },\n {\n id: \"icon\",\n label: tr(\"devportal.checklistIconLabel\", \"App Icon\"),\n description: tr(\n \"devportal.checklistIconDesc\",\n \"An icon makes your listing stand out in the marketplace\",\n ),\n status: app.iconUrl ? \"passed\" : \"warning\",\n icon: <Image size={20} />,\n actionLabel: \"Edit store listing →\",\n actionPath: storeListingPath,\n },\n {\n id: \"screenshots\",\n label: tr(\"devportal.checklistScreenshotsLabel\", \"Screenshots\"),\n description: tr(\n \"devportal.checklistScreenshotsDesc\",\n \"At least 3 screenshots are recommended\",\n ),\n status:\n screenshotCount >= 3\n ? \"passed\"\n : screenshotCount > 0\n ? \"warning\"\n : \"warning\",\n icon: <Image size={20} />,\n actionLabel: \"Edit store listing →\",\n actionPath: storeListingPath,\n },\n ];\n\n if (isPackageType) {\n items.push({\n id: \"version\",\n label: tr(\"devportal.checklistVersionLabel\", \"Published Version\"),\n description: tr(\n \"devportal.checklistVersionDesc\",\n app?.appType === \"WORKFLOW\"\n ? \"At least one published version (manifest JSON) is required before submitting to the store\"\n : \"At least one published version (ZIP + manifest) is required before submitting to the store\",\n ),\n status: publishedVersionCount > 0 ? \"passed\" : \"failed\",\n icon: <CheckCircle size={20} />,\n actionLabel: \"Create a version →\",\n actionPath: versionsPath,\n });\n }\n\n if (app.appType === \"API_INTEGRATION\") {\n items.push({\n id: \"oauth\",\n label: tr(\"devportal.checklistOAuthLabel\", \"OAuth Configuration\"),\n description: tr(\n \"devportal.checklistOAuthDesc\",\n \"Authorization URL, Token URL and Client ID are required so users can connect their accounts. Without these the Connect button does not work.\",\n ),\n status: hasOAuthUrl ? \"passed\" : \"failed\",\n icon: <KeyRound size={20} />,\n actionLabel: \"Configure in Edit App →\",\n actionPath: editPath,\n });\n\n items.push({\n id: \"webhook\",\n label: tr(\"devportal.checklistWebhookLabel\", \"Webhook Endpoint\"),\n description: tr(\n \"devportal.checklistWebhookDesc\",\n \"At least one webhook endpoint must be configured so your server receives platform events after users connect. Without this the integration does nothing.\",\n ),\n status: webhookCount > 0 ? \"passed\" : \"failed\",\n icon: <Webhook size={20} />,\n actionLabel: \"Add a webhook →\",\n actionPath: webhooksPath,\n });\n\n items.push({\n id: \"documentation\",\n label: tr(\"devportal.checklistDocsLabel\", \"Documentation URL\"),\n description: tr(\n \"devportal.checklistDocsDesc\",\n \"Users need to know how to use and configure this integration. A documentation link is required for API integrations.\",\n ),\n status: app.documentationUrl ? \"passed\" : \"failed\",\n icon: <FileText size={20} />,\n actionLabel: \"Add documentation URL →\",\n actionPath: editPath,\n });\n\n items.push({\n id: \"website\",\n label: tr(\"devportal.checklistWebsiteLabel\", \"Website URL\"),\n description: tr(\n \"devportal.checklistWebsiteDesc\",\n \"Users need to verify who built this integration. A website URL is required so users know where to get support.\",\n ),\n status: app.websiteUrl ? \"passed\" : \"failed\",\n icon: <Link size={20} />,\n actionLabel: \"Add website URL →\",\n actionPath: editPath,\n });\n }\n\n items.push({\n id: \"status\",\n label: tr(\"devportal.checklistStatusLabel\", \"App Status\"),\n description: tr(\n \"devportal.checklistStatusDesc\",\n \"App must be in DRAFT or REJECTED state to submit\",\n ),\n status: [\"DRAFT\", \"REJECTED\"].includes(app.status ?? \"\")\n ? \"passed\"\n : \"warning\",\n icon: <CheckCircle size={20} />,\n });\n\n return items;\n }, [\n app,\n isPackageType,\n publishedVersionCount,\n webhookCount,\n hasOAuthUrl,\n appId,\n ]);\n\n const passedCount = checklist.filter((i) => i.status === \"passed\").length;\n const failedCount = checklist.filter((i) => i.status === \"failed\").length;\n const warningCount = checklist.filter((i) => i.status === \"warning\").length;\n const isSubmittableStatus = [\"DRAFT\", \"REJECTED\"].includes(app?.status ?? \"\");\n const canSubmit =\n !loading &&\n !queryError &&\n failedCount === 0 &&\n !!app &&\n !isAlreadySubmitted &&\n isSubmittableStatus;\n\n const getStatusIcon = (status: ChecklistItem[\"status\"]) => {\n switch (status) {\n case \"passed\":\n return <CheckCircle size={20} className=\"text-status-success-text\" />;\n case \"failed\":\n return <XCircle size={20} className=\"text-status-error-text\" />;\n case \"warning\":\n return <AlertTriangle size={20} className=\"text-status-warning-text\" />;\n default:\n return (\n <div className=\"h-5 w-5 rounded-full border-2 border-border-default\" />\n );\n }\n };\n\n const getStatusBg = (status: ChecklistItem[\"status\"]) => {\n switch (status) {\n case \"passed\":\n return \"bg-status-success-bg-subtle border-border-subtle\";\n case \"failed\":\n return \"bg-status-error-bg-subtle border-border-subtle\";\n case \"warning\":\n return \"bg-status-warning-bg-subtle border-border-subtle\";\n default:\n return \"bg-bg-canvas border-border-subtle\";\n }\n };\n\n const handleSubmit = async () => {\n if (!appId) return;\n setSubmitting(true);\n setSubmitError(null);\n try {\n // Submit Application for devportal review (sets Application.status = SUBMITTED)\n const result = await submitApplication({\n variables: { id: appId, notes: notes.trim() || undefined },\n });\n if (result.error) throw result.error;\n\n // Also submit ApplicationForReview to set StoreProduct.status = PENDING_REVIEW\n // so it appears in the store admin review queue at /store/dashboard/submissions\n await submitApplicationForReview({\n variables: { id: appId, notes: notes.trim() || undefined },\n });\n\n setSubmitted(true);\n } catch (err) {\n setSubmitError(\n err instanceof Error\n ? err.message\n : tr(\"devportal.submitFailedDefault\", \"Failed to submit for review\"),\n );\n } finally {\n setSubmitting(false);\n }\n };\n\n if (loading) {\n return (\n <PageLayout\n title={tr(\"devportal.publishToStoreTitle\", \"Publish to Store\")}\n description={tr(\n \"devportal.loadingApplicationDetails\",\n \"Loading application details...\",\n )}\n backLink={`/apps/${appId}`}\n backLabel={tr(\"devportal.backToApplication\", \"Back to Application\")}\n >\n <div className=\"flex items-center justify-center py-12\">\n <Loader2 className=\"animate-spin h-8 w-8 text-text-secondary\" />\n </div>\n </PageLayout>\n );\n }\n\n if (queryError || !app) {\n return (\n <PageLayout\n title={tr(\"devportal.publishToStoreTitle\", \"Publish to Store\")}\n description={tr(\n \"devportal.couldNotLoadApplication\",\n \"Could not load application\",\n )}\n backLink={`/apps/${appId}`}\n backLabel={tr(\"devportal.backToApplication\", \"Back to Application\")}\n >\n <Alert\n variant=\"error\"\n title={tr(\n \"devportal.failedToLoadApplication\",\n \"Failed to load application\",\n )}\n >\n {queryError?.message ??\n tr(\"devportal.applicationNotFound\", \"Application not found\")}\n </Alert>\n </PageLayout>\n );\n }\n\n if (submitted) {\n return (\n <PermissionGuard authOnly>\n <PageLayout\n title={tr(\"devportal.publishToStoreTitle\", \"Publish to Store\")}\n backLink={`/apps/${appId}`}\n backLabel={tr(\"devportal.backToApplication\", \"Back to Application\")}\n >\n <div className=\"flex flex-col items-center justify-center py-16 gap-6 text-center\">\n <div className=\"rounded-full bg-status-success-bg p-4\">\n <PartyPopper size={40} className=\"text-status-success-text\" />\n </div>\n <div className=\"space-y-2\">\n <h2 className=\"text-2xl font-bold\">\n {tr(\"devportal.submittedSuccessTitle\", \"Submitted for Review!\")}\n </h2>\n <p className=\"text-muted-foreground max-w-md\">\n {tr(\n \"devportal.submittedSuccessMsg\",\n \"Your app has been submitted to the marketplace review queue. You'll receive email notifications as the review progresses — typically 3–5 business days.\",\n )}\n </p>\n </div>\n <div className=\"rounded-lg border bg-muted/40 px-6 py-4 text-sm text-left space-y-2 max-w-md w-full\">\n <p className=\"font-medium\">What happens next:</p>\n <ul className=\"space-y-1 text-muted-foreground list-none\">\n <li className=\"flex items-start gap-2\">\n <CheckCircle\n size={14}\n className=\"mt-0.5 text-status-success-text shrink-0\"\n />{\" \"}\n Our team reviews your submission\n </li>\n <li className=\"flex items-start gap-2\">\n <CheckCircle\n size={14}\n className=\"mt-0.5 text-status-success-text shrink-0\"\n />{\" \"}\n You'll get an email on approval or if changes are needed\n </li>\n <li className=\"flex items-start gap-2\">\n <CheckCircle\n size={14}\n className=\"mt-0.5 text-status-success-text shrink-0\"\n />{\" \"}\n Once approved, your app goes live in the marketplace\n </li>\n </ul>\n </div>\n <button\n onClick={() => navigate?.(`${basePath}/apps/${appId}`)}\n className=\"inline-flex items-center gap-2 rounded-md border px-4 py-2 text-sm font-medium hover:bg-muted\"\n >\n Back to App\n </button>\n </div>\n </PageLayout>\n </PermissionGuard>\n );\n }\n\n return (\n <PermissionGuard authOnly>\n <PageLayout\n title={tr(\"devportal.publishToStoreTitle\", \"Publish to Store\")}\n description={`${tr(\"devportal.submitAppForReview\", \"Submit\")} \"${app.name}\" ${tr(\"devportal.forReviewAndPublication\", \"for review and publication\")}`}\n purpose={tr(\n \"devportal.publishPurpose\",\n \"Submitting sends your app to the review team, who check it against the marketplace guidelines before it goes live to users. Make sure the listing, screenshots, and permissions are final — preview the listing first, since changes after approval need another review.\",\n )}\n backLink={`/apps/${appId}`}\n backLabel={tr(\"devportal.backToApplication\", \"Back to Application\")}\n actions={\n <button\n onClick={() => navigate?.(`${basePath}/apps/${appId}/listing`)}\n className=\"inline-flex items-center gap-2 rounded-md border px-3 py-2 text-sm font-medium hover:bg-bg-sunken\"\n >\n <Eye size={16} />\n {tr(\"devportal.previewListing\", \"Preview Listing\")}\n </button>\n }\n >\n {isAlreadySubmitted && (\n <Alert\n variant=\"warning\"\n title={tr(\"devportal.alreadySubmittedTitle\", \"Already Submitted\")}\n >\n {tr(\"devportal.alreadySubmittedMsg1\", \"This app is currently in\")}{\" \"}\n <strong>{app.status}</strong>{\" \"}\n {tr(\n \"devportal.alreadySubmittedMsg2\",\n \"state and cannot be re-submitted until the review process is complete or the app is rejected.\",\n )}\n </Alert>\n )}\n\n {/* Progress Summary */}\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6\">\n <h2 className=\"text-lg font-semibold\">\n {tr(\"devportal.preSubmissionChecklist\", \"Pre-submission Checklist\")}\n </h2>\n <p className=\"mt-1 text-sm text-text-secondary\">\n {tr(\n \"devportal.completeAllRequiredItems\",\n \"Complete all required items before submitting for review\",\n )}\n </p>\n <div className=\"mt-4 flex gap-6\">\n <div className=\"flex items-center gap-2\">\n <CheckCircle size={20} className=\"text-status-success-text\" />\n <span>\n {passedCount} {tr(\"devportal.passed\", \"Passed\")}\n </span>\n </div>\n <div className=\"flex items-center gap-2\">\n <XCircle size={20} className=\"text-status-error-text\" />\n <span>\n {failedCount} {tr(\"devportal.failed\", \"Failed\")}\n </span>\n </div>\n <div className=\"flex items-center gap-2\">\n <AlertTriangle size={20} className=\"text-status-warning-text\" />\n <span>\n {warningCount} {tr(\"devportal.warnings\", \"Warnings\")}\n </span>\n </div>\n </div>\n </div>\n\n {/* Checklist Items */}\n <PageSection>\n <div className=\"space-y-3\">\n {checklist.map((item) => (\n <div\n key={item.id}\n className={`flex items-center gap-4 rounded-lg border p-4 ${getStatusBg(item.status)}`}\n >\n <div className=\"rounded-lg bg-bg-surface p-2\">{item.icon}</div>\n <div className=\"flex-1\">\n <p className=\"font-medium\">{item.label}</p>\n <p className=\"text-sm text-text-secondary\">\n {item.description}\n </p>\n {item.status !== \"passed\" && item.actionPath && (\n <button\n type=\"button\"\n onClick={() =>\n navigate?.(`${basePath}${item.actionPath}`)\n }\n className=\"mt-1 inline-flex items-center gap-1 text-xs text-primary hover:underline\"\n >\n {item.actionLabel ?? \"Fix this\"} <ArrowRight size={11} />\n </button>\n )}\n </div>\n {getStatusIcon(item.status)}\n </div>\n ))}\n </div>\n </PageSection>\n\n {/* Submission Notes */}\n {!isAlreadySubmitted && (\n <PageSection\n title={tr(\"devportal.notesForReviewerTitle\", \"Notes for Reviewer\")}\n description={tr(\n \"devportal.notesForReviewerDesc\",\n \"Optional message to the review team\",\n )}\n >\n <textarea\n value={notes}\n onChange={(e) => setNotes(e.target.value)}\n placeholder={tr(\n \"devportal.notesForReviewerPlaceholder\",\n \"Describe what your app does, any special review considerations, or testing instructions...\",\n )}\n rows={4}\n maxLength={1000}\n className=\"w-full rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm ring-offset-background placeholder:text-text-secondary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)] resize-none\"\n />\n <p className=\"mt-1 text-xs text-text-secondary text-right\">\n {notes.length}/1000\n </p>\n </PageSection>\n )}\n\n {/* Alerts */}\n {submitError && (\n <Alert\n variant=\"error\"\n title={tr(\"devportal.submissionFailedTitle\", \"Submission Failed\")}\n >\n {submitError}\n </Alert>\n )}\n\n {failedCount > 0 && !isAlreadySubmitted && (\n <Alert\n variant=\"error\"\n title={tr(\"devportal.cannotSubmitTitle\", \"Cannot Submit Yet\")}\n >\n {tr(\"devportal.pleaseFixItems1\", \"Please fix\")} {failedCount}{\" \"}\n {tr(\n \"devportal.pleaseFixItems2\",\n \"required item(s) before submitting for review.\",\n )}\n <div className=\"mt-2 flex flex-wrap gap-3\">\n <button\n onClick={() => navigate?.(`${basePath}/apps/${appId}`)}\n className=\"text-sm underline hover:no-underline\"\n >\n {tr(\n \"devportal.goToMarketplaceListing\",\n \"Update marketplace listing →\",\n )}\n </button>\n {isPackageType && publishedVersionCount === 0 && (\n <button\n onClick={() =>\n navigate?.(`${basePath}/apps/${appId}/versions`)\n }\n className=\"text-sm underline hover:no-underline\"\n >\n {tr(\"devportal.goToVersions\", \"Add a published version →\")}\n </button>\n )}\n {isApiIntegration && !hasOAuthUrl && (\n <button\n onClick={() =>\n navigate?.(`${basePath}/apps/${appId}/edit#oauth-config`)\n }\n className=\"text-sm underline hover:no-underline\"\n >\n Configure OAuth endpoints →\n </button>\n )}\n {isApiIntegration && webhookCount === 0 && (\n <button\n onClick={() =>\n navigate?.(`${basePath}/apps/${appId}/webhooks`)\n }\n className=\"text-sm underline hover:no-underline\"\n >\n Add a webhook →\n </button>\n )}\n </div>\n </Alert>\n )}\n\n {warningCount > 0 && failedCount === 0 && !isAlreadySubmitted && (\n <Alert\n variant=\"warning\"\n title={tr(\"devportal.warningsTitle\", \"Warnings\")}\n >\n {tr(\"devportal.warningsMsg1\", \"You have\")} {warningCount}{\" \"}\n {tr(\n \"devportal.warningsMsg2\",\n \"warning(s). While you can submit, addressing these may improve your app's chances of approval.\",\n )}\n </Alert>\n )}\n\n {/* Review Process Info */}\n <PageSection\n title={tr(\"devportal.reviewProcessTitle\", \"Review Process\")}\n >\n <div className=\"rounded-lg border bg-bg-sunken/50 p-4\">\n <ul className=\"space-y-2 text-sm\">\n <li className=\"flex items-start gap-2\">\n <CheckCircle size={16} className=\"mt-0.5 text-primary\" />\n <span>\n {tr(\n \"devportal.reviewProcessInfo1\",\n \"Review typically takes 3-5 business days\",\n )}\n </span>\n </li>\n <li className=\"flex items-start gap-2\">\n <CheckCircle size={16} className=\"mt-0.5 text-primary\" />\n <span>\n {tr(\n \"devportal.reviewProcessInfo2\",\n \"You'll receive notifications about review status changes\",\n )}\n </span>\n </li>\n <li className=\"flex items-start gap-2\">\n <CheckCircle size={16} className=\"mt-0.5 text-primary\" />\n <span>\n {tr(\n \"devportal.reviewProcessInfo3\",\n \"If changes are requested, you can resubmit without losing your place in the queue\",\n )}\n </span>\n </li>\n <li className=\"flex items-start gap-2\">\n <CheckCircle size={16} className=\"mt-0.5 text-primary\" />\n <span>\n {tr(\n \"devportal.reviewProcessInfo4\",\n \"Once approved and published, your app will be visible in the marketplace\",\n )}\n </span>\n </li>\n </ul>\n </div>\n </PageSection>\n\n {/* Actions */}\n <div className=\"flex gap-3\">\n <button\n onClick={() => navigate?.(`${basePath}/apps/${appId}`)}\n className=\"rounded-md border px-4 py-2 text-sm font-medium hover:bg-bg-sunken\"\n >\n {tr(\"devportal.cancelButton\", \"Cancel\")}\n </button>\n <button\n onClick={handleSubmit}\n disabled={!canSubmit || submitting || !submitPerm.allowed}\n aria-disabled={!canSubmit || submitting || !submitPerm.allowed}\n title={\n !submitPerm.allowed\n ? tr(\n \"devportal.common.noPermission\",\n \"You do not have permission to perform this action\",\n )\n : undefined\n }\n 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 disabled:opacity-50 disabled:cursor-not-allowed focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n >\n {submitting ? (\n <>\n <Loader2 size={16} className=\"animate-spin\" />\n {tr(\"devportal.submittingButton\", \"Submitting...\")}\n </>\n ) : (\n <>\n <Send size={16} />\n {tr(\"devportal.submitForReviewButton\", \"Submit for Review\")}\n </>\n )}\n </button>\n </div>\n </PageLayout>\n </PermissionGuard>\n );\n};\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SellerDashboardPage.d.ts","sourceRoot":"","sources":["../../../src/devportal/pages/SellerDashboardPage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAa,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"SellerDashboardPage.d.ts","sourceRoot":"","sources":["../../../src/devportal/pages/SellerDashboardPage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAa,MAAM,OAAO,CAAC;AAgK3C,eAAO,MAAM,mBAAmB,EAAE,EAgUjC,CAAC"}
|