@burdenoff/microfe-devportal 2026.916.7 → 2026.917.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/dist/devportal/components/ImageUploadField.d.ts +30 -0
  2. package/dist/devportal/components/ImageUploadField.d.ts.map +1 -0
  3. package/dist/devportal/components/ImageUploadField.js +182 -0
  4. package/dist/devportal/components/ImageUploadField.js.map +1 -0
  5. package/dist/devportal/components/ManifestViewer.d.ts +12 -0
  6. package/dist/devportal/components/ManifestViewer.d.ts.map +1 -0
  7. package/dist/devportal/components/ManifestViewer.js +58 -0
  8. package/dist/devportal/components/ManifestViewer.js.map +1 -0
  9. package/dist/devportal/components/index.d.ts +1 -0
  10. package/dist/devportal/components/index.d.ts.map +1 -1
  11. package/dist/devportal/components/index.js +1 -0
  12. package/dist/devportal/pages/AdminReviewPage.d.ts.map +1 -1
  13. package/dist/devportal/pages/AdminReviewPage.js +54 -64
  14. package/dist/devportal/pages/AdminReviewPage.js.map +1 -1
  15. package/dist/devportal/pages/ApplicationDetailPage.d.ts.map +1 -1
  16. package/dist/devportal/pages/ApplicationDetailPage.js +712 -883
  17. package/dist/devportal/pages/ApplicationDetailPage.js.map +1 -1
  18. package/dist/devportal/pages/ApplicationVersionsPage.d.ts.map +1 -1
  19. package/dist/devportal/pages/ApplicationVersionsPage.js +304 -272
  20. package/dist/devportal/pages/ApplicationVersionsPage.js.map +1 -1
  21. package/dist/devportal/pages/CreatePhysicalItemPage.d.ts.map +1 -1
  22. package/dist/devportal/pages/CreatePhysicalItemPage.js +238 -331
  23. package/dist/devportal/pages/CreatePhysicalItemPage.js.map +1 -1
  24. package/dist/devportal/pages/EditPhysicalItemPage.d.ts.map +1 -1
  25. package/dist/devportal/pages/EditPhysicalItemPage.js +352 -408
  26. package/dist/devportal/pages/EditPhysicalItemPage.js.map +1 -1
  27. package/dist/translations/en.d.ts +4 -1
  28. package/dist/translations/en.d.ts.map +1 -1
  29. package/dist/translations/en.js +5 -2
  30. package/dist/translations/en.js.map +1 -1
  31. 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, DragEvent } from \"react\";\nimport { useState, useEffect, useCallback, useRef } from \"react\";\nimport { useParams } from \"react-router\";\nimport {\n Loader2,\n AlertCircle,\n Info,\n Upload,\n X,\n AlertTriangle,\n RotateCw,\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 { DetailList } from \"../components/DataTable\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport { usePackageUpload } from \"../hooks/usePackageUpload\";\nimport { cn } from \"../utils/cn\";\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\ninterface ImagePreview {\n id: string;\n file?: File;\n url: string;\n uploading: boolean;\n downloadUrl?: string;\n error?: string;\n}\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 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 [images, setImages] = useState<ImagePreview[]>([]);\n const [isDragOver, setIsDragOver] = useState(false);\n const fileInputRef = useRef<HTMLInputElement>(null);\n const { upload: uploadImage } = 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 = images.some((img) => img.uploading);\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 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 setImages(\n [p.icon, ...(p.screenshots ?? [])]\n .filter((url): url is string => !!url)\n .map((url) => ({\n id: crypto.randomUUID(),\n url,\n downloadUrl: url,\n uploading: false,\n })),\n );\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 // ─── Image handling ───────────────────────────────────────────────────────\n // Existing images loaded from the product start with downloadUrl already\n // set (no upload needed). Newly dropped/selected files upload immediately\n // to /DevPortal/Assets via usePackageUpload — same pipeline as create.\n\n const uploadOne = useCallback(\n (id: string, file: File) => {\n uploadImage(file)\n .then((result) => {\n setImages((prev) =>\n prev.map((img) =>\n img.id === id\n ? {\n ...img,\n uploading: false,\n downloadUrl: result.downloadUrl,\n error: undefined,\n }\n : img,\n ),\n );\n })\n .catch((err) => {\n setImages((prev) =>\n prev.map((img) =>\n img.id === id\n ? {\n ...img,\n uploading: false,\n error: err instanceof Error ? err.message : \"Upload failed\",\n }\n : img,\n ),\n );\n });\n },\n [uploadImage],\n );\n\n const addFiles = useCallback(\n (files: FileList | File[]) => {\n const incoming = Array.from(files).filter((f) =>\n f.type.startsWith(\"image/\"),\n );\n const previews: ImagePreview[] = incoming.map((file) => ({\n id: crypto.randomUUID(),\n file,\n url: URL.createObjectURL(file),\n uploading: true,\n }));\n setImages((prev) => [...prev, ...previews]);\n previews.forEach((preview) => uploadOne(preview.id, preview.file!));\n },\n [uploadOne],\n );\n\n const handleFileInput = (e: ChangeEvent<HTMLInputElement>) => {\n if (e.target.files) addFiles(e.target.files);\n e.target.value = \"\";\n };\n\n const handleDrop = (e: DragEvent<HTMLDivElement>) => {\n e.preventDefault();\n setIsDragOver(false);\n if (e.dataTransfer.files) addFiles(e.dataTransfer.files);\n };\n\n const handleDragOver = (e: DragEvent<HTMLDivElement>) => {\n e.preventDefault();\n setIsDragOver(true);\n };\n\n const handleDragLeave = () => setIsDragOver(false);\n\n const removeImage = (id: string) => {\n setImages((prev) => {\n const target = prev.find((img) => img.id === id);\n if (target?.file) URL.revokeObjectURL(target.url);\n return prev.filter((img) => img.id !== id);\n });\n };\n\n const retryUpload = (id: string) => {\n const target = images.find((img) => img.id === id);\n if (!target?.file) return;\n setImages((prev) =>\n prev.map((img) =>\n img.id === id ? { ...img, uploading: true, error: undefined } : img,\n ),\n );\n uploadOne(id, target.file);\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 uploadedImageUrls = images\n .map((img) => img.downloadUrl)\n .filter((url): url is string => !!url);\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: uploadedImageUrls[0] ?? null,\n screenshots:\n uploadedImageUrls.length > 1 ? uploadedImageUrls.slice(1) : 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 mainImage = images.find((img) => img.downloadUrl) ?? images[0];\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 {mainImage ? (\n <img\n src={mainImage.url}\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 {images.length > 0 ? (\n <div className=\"flex flex-wrap gap-3\">\n {images.map((img, i) => (\n <img\n key={img.id}\n src={img.url}\n alt={`Product image ${i + 1}`}\n className=\"h-24 w-24 rounded-input border border-border-subtle object-cover\"\n />\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=\"The first image is used as the main icon.\"\n >\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6 space-y-4\">\n <div\n onDrop={handleDrop}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onClick={() => fileInputRef.current?.click()}\n className={cn(\n \"flex flex-col items-center justify-center gap-3 rounded-input border-2 border-dashed px-6 py-10 cursor-pointer transition-colors\",\n isDragOver\n ? \"border-action-primary-bg bg-action-primary-bg/5\"\n : \"border-border-subtle hover:border-border-strong\",\n )}\n >\n <Upload\n size={28}\n className={\n isDragOver ? \"text-action-primary-bg\" : \"text-text-muted\"\n }\n />\n <div className=\"text-center space-y-1\">\n <p className=\"text-sm font-medium text-text-primary\">\n Drag and drop images here\n </p>\n <p className=\"text-xs text-text-muted\">\n or click to browse — accepts any image format, multiple\n files\n </p>\n </div>\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/*\"\n multiple\n className=\"sr-only\"\n onChange={handleFileInput}\n />\n </div>\n\n {images.length > 0 && (\n <div className=\"flex flex-wrap gap-3\">\n {(() => {\n const firstUploadedId = images.find(\n (im) => im.downloadUrl,\n )?.id;\n return images.map((img, i) => (\n <div key={img.id} className=\"relative group\">\n <img\n src={img.url}\n alt={`Product image ${i + 1}`}\n className={cn(\n \"h-20 w-20 rounded-input object-cover border\",\n img.error\n ? \"border-status-error-text/50\"\n : \"border-border-subtle\",\n )}\n />\n {img.uploading && (\n <div className=\"absolute inset-0 flex items-center justify-center rounded-input bg-bg-overlay\">\n <Loader2\n size={16}\n className=\"animate-spin text-white\"\n />\n </div>\n )}\n {img.error && (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n retryUpload(img.id);\n }}\n title={`${img.error} — click to retry`}\n className=\"absolute inset-0 flex flex-col items-center justify-center gap-0.5 rounded-input bg-status-error-bg/80 text-status-error-text\"\n >\n <AlertTriangle size={14} />\n <RotateCw size={11} />\n </button>\n )}\n {img.id === firstUploadedId && (\n <span className=\"absolute bottom-0 left-0 right-0 rounded-b-input bg-bg-surface/80 text-center text-[10px] font-medium py-0.5 text-text-secondary\">\n Main\n </span>\n )}\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n removeImage(img.id);\n }}\n className=\"absolute -top-1.5 -right-1.5 hidden group-hover:flex h-5 w-5 items-center justify-center rounded-full bg-bg-surface border border-border-subtle text-text-muted hover:text-status-error-text hover:border-status-error-text/40 transition-colors\"\n aria-label=\"Remove image\"\n >\n <X size={11} />\n </button>\n </div>\n ));\n })()}\n </div>\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 { 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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"}
@@ -461,7 +461,6 @@ export declare const enTranslations: {
461
461
  gridView: string;
462
462
  guides: string;
463
463
  hide: string;
464
- hideManifest: string;
465
464
  hintMissingBilling: string;
466
465
  hintMissingCategory: string;
467
466
  hintMissingDescription: string;
@@ -552,7 +551,9 @@ export declare const enTranslations: {
552
551
  manageYourDevTeams: string;
553
552
  manageYourOrganizationsTeam: string;
554
553
  manageYourPhysicalProductListings: string;
554
+ manifest: string;
555
555
  manifestDisplayName: string;
556
+ manifestJson: string;
556
557
  manualVerification: string;
557
558
  markdownSupported: string;
558
559
  marketplacePreview: string;
@@ -615,6 +616,7 @@ export declare const enTranslations: {
615
616
  noGrantedDelegationsDescription: string;
616
617
  noItemsMatchYourSearch: string;
617
618
  noItemsYet: string;
619
+ noManifest: string;
618
620
  noMatchingWorkspaces: string;
619
621
  noMembers: string;
620
622
  noOAuthAppsFound: string;
@@ -1180,6 +1182,7 @@ export declare const enTranslations: {
1180
1182
  versionDeprecateFailed: string;
1181
1183
  versionDeprecatedSuccess: string;
1182
1184
  versionHint: string;
1185
+ versionHintAutoFilled: string;
1183
1186
  versionManagement: string;
1184
1187
  versionManagementDescription: string;
1185
1188
  versionManagementPurposeIntegration: string;
@@ -1 +1 @@
1
- {"version":3,"file":"en.d.ts","sourceRoot":"","sources":["../../src/translations/en.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA44C1B,CAAC"}
1
+ {"version":3,"file":"en.d.ts","sourceRoot":"","sources":["../../src/translations/en.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAi5C1B,CAAC"}
@@ -449,7 +449,6 @@ var e = { devportal: {
449
449
  gridView: "Grid view",
450
450
  guides: "Guides",
451
451
  hide: "Hide",
452
- hideManifest: "Hide manifest",
453
452
  hintMissingBilling: "Link a billing account in the Pricing tab to receive payouts",
454
453
  hintMissingCategory: "Select a category on the Store Listing tab",
455
454
  hintMissingDescription: "Add a full description on the Store Listing tab",
@@ -540,7 +539,9 @@ var e = { devportal: {
540
539
  manageYourDevTeams: "Manage your development teams",
541
540
  manageYourOrganizationsTeam: "Manage your organization's team",
542
541
  manageYourPhysicalProductListings: "Manage your physical product listings.",
542
+ manifest: "Manifest",
543
543
  manifestDisplayName: "Display Name",
544
+ manifestJson: "manifest.json",
544
545
  manualVerification: "Manual review",
545
546
  markdownSupported: "Markdown formatting is supported",
546
547
  marketplacePreview: "Marketplace Preview",
@@ -603,6 +604,7 @@ var e = { devportal: {
603
604
  noGrantedDelegationsDescription: "You haven't granted any app delegations to other users.",
604
605
  noItemsMatchYourSearch: "No items match your search",
605
606
  noItemsYet: "No items yet",
607
+ noManifest: "No manifest",
606
608
  noMatchingWorkspaces: "No matching workspaces",
607
609
  noMembers: "No members",
608
610
  noOAuthAppsFound: "No OAuth apps found",
@@ -1161,7 +1163,8 @@ var e = { devportal: {
1161
1163
  versionCreatedSuccess: "Version created successfully",
1162
1164
  versionDeprecateFailed: "Failed to deprecate version",
1163
1165
  versionDeprecatedSuccess: "Version deprecated successfully",
1164
- versionHint: "Use semantic versioning (major.minor.patch)",
1166
+ versionHint: "Use semantic versioning (major.minor.patch). Upload a manifest.json/manifest with a version to fill this in automatically.",
1167
+ versionHintAutoFilled: "Filled in from the manifest's version — edit it there if this is wrong.",
1165
1168
  versionManagement: "Version Management",
1166
1169
  versionManagementDescription: "Manage your application versions",
1167
1170
  versionManagementPurposeIntegration: "Versions track permission and webhook changes for your integration. No zip or manifest is needed — create a new version whenever you add or change required scopes so users can review and accept the updated permissions.",