@develemit/commerce-admin 0.0.0-stage → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/README.md +136 -2
  2. package/dist/client/admin-client.d.ts +31 -0
  3. package/dist/client/errors.d.ts +41 -0
  4. package/dist/client/index.d.ts +3 -0
  5. package/dist/client/index.js +1 -0
  6. package/dist/client/map-error.d.ts +2 -0
  7. package/dist/client/transport.d.ts +19 -0
  8. package/dist/client-n_IYb4iK.js +146 -0
  9. package/dist/client-n_IYb4iK.js.map +1 -0
  10. package/dist/components/admin-layout/admin-layout.d.ts +13 -0
  11. package/dist/components/admin-table/admin-table.d.ts +13 -0
  12. package/dist/components/confirm-dialog/confirm-dialog.d.ts +12 -0
  13. package/dist/components/error-message/error-message.d.ts +5 -0
  14. package/dist/components/money/money.d.ts +5 -0
  15. package/dist/components/notice/notice.d.ts +9 -0
  16. package/dist/components/status-badge/status-badge.d.ts +3 -0
  17. package/dist/index.d.ts +24 -0
  18. package/dist/index.js +2346 -0
  19. package/dist/index.js.map +1 -0
  20. package/dist/lib/image-labels.d.ts +24 -0
  21. package/dist/lib/image-rules.d.ts +4 -0
  22. package/dist/lib/money-input.d.ts +2 -0
  23. package/dist/lib/order-action-labels.d.ts +28 -0
  24. package/dist/lib/order-labels.d.ts +66 -0
  25. package/dist/lib/product-filter.d.ts +6 -0
  26. package/dist/lib/product-form.d.ts +29 -0
  27. package/dist/lib/product-labels.d.ts +52 -0
  28. package/dist/lib/provider.d.ts +73 -0
  29. package/dist/lib/refund-rules.d.ts +7 -0
  30. package/dist/lib/shipping-labels.d.ts +33 -0
  31. package/dist/lib/shipping-rates.d.ts +31 -0
  32. package/dist/lib/use-admin-mutation.d.ts +7 -0
  33. package/dist/lib/use-admin-query.d.ts +7 -0
  34. package/dist/lib/use-debounced.d.ts +1 -0
  35. package/dist/lib/use-image-upload.d.ts +18 -0
  36. package/dist/lib/use-order-pages.d.ts +17 -0
  37. package/dist/lib/use-product-pages.d.ts +30 -0
  38. package/dist/styles.css +405 -0
  39. package/dist/views/orders/admin-order-detail.d.ts +10 -0
  40. package/dist/views/orders/admin-order-list.d.ts +1 -0
  41. package/dist/views/orders/order-actions.d.ts +7 -0
  42. package/dist/views/orders/order-fulfillment.d.ts +4 -0
  43. package/dist/views/orders/order-items.d.ts +4 -0
  44. package/dist/views/orders/order-refunds.d.ts +4 -0
  45. package/dist/views/orders/refund-dialog.d.ts +8 -0
  46. package/dist/views/orders/resolve-button.d.ts +7 -0
  47. package/dist/views/orders/ship-form.d.ts +7 -0
  48. package/dist/views/orders/test-helpers.d.ts +3 -0
  49. package/dist/views/products/admin-product-editor.d.ts +9 -0
  50. package/dist/views/products/admin-product-images.d.ts +6 -0
  51. package/dist/views/products/admin-product-list.d.ts +1 -0
  52. package/dist/views/products/image-tile.d.ts +14 -0
  53. package/dist/views/products/product-fields.d.ts +12 -0
  54. package/dist/views/products/test-helpers.d.ts +6 -0
  55. package/dist/views/products/upload-picker.d.ts +7 -0
  56. package/dist/views/shipping/admin-shipping-rates.d.ts +4 -0
  57. package/dist/views/shipping/shipping-rate-row.d.ts +15 -0
  58. package/package.json +44 -3
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["_Fragment","_Fragment","_Fragment","_Fragment","AdminUnauthorizedError","InvalidImageError","RefundGatewayError","RefundOutcomeUnknownError","InvalidOrderStateError","AdminInvalidInputError","InsufficientStockError","RefundExceedsBalanceError","defaultOrderLabels","defaultShippingLabels","defaultProductLabels","defaults","priority","id","AdminContext","createContext","mergeOrderLabels","base","overrides","mergeProductLabels","AdminProvider","value","hrefs","labels","useAdmin","useContext","useAdminClient","client","useAdminQuery","fnRef","useRef","fn","reloadCount","setReloadCount","useState","settled","setSettled","request","key","controller","prev","reload","useCallback","n","current","useAdminMutation","pending","setPending","error","setError","args","err","AdminLayout","kit","items","extraNav","i","header","renderLink","item","footer","AdminTable","rows","caption","columns","c","row","rowKey","StatusBadge","status","Money","text","locale","cents","FOCUSABLE","ConfirmDialog","panelRef","useEffect","open","trigger","event","onCancel","focusable","first","last","title","children","destructive","onConfirm","confirmLabel","Notice","toast","onDismiss","timer","duration","role","variant","className","KEYED","AdminNotFoundError","ImageTooLargeError","errorKey","type","ErrorMessage","isSold","product","displayStatus","serverStatus","filter","serverStock","useDebounced","debounced","setDebounced","delayMs","useProductPages","query","appended","setAppended","more","page","extra","nextCursor","FILTERS","AdminProductList","copy","setFilter","search","setSearch","q","stock","pages","updated","setUpdated","apply","kind","confirm","result","p","emptyText","MONEY","parseMoneyInput","raw","match","whole","fraction","formatMoneyInput","FIELD_ORDER","emptyForm","formFromProduct","fieldFor","head","path","mapped","mapServerIssues","errors","issue","issues","field","message","firstInvalidField","blankToNull","trimmed","validateForm","priceCents","form","quantity","parsed","adminProductInputSchema","currency","PATCH_KEYS","buildPatch","patch","input","original","ACCEPTED_TYPES","fill","template","values","imageFileProblem","file","useImageUpload","entries","setEntries","nextId","chain","onUploadedRef","onUploaded","entry","change","drop","send","productId","alt","added","files","reason","ImageTile","name","image","index","move","direction","onMove","busy","renderImage","total","onRemove","UploadPicker","pick","onFiles","byPosition","images","a","b","AdminProductImages","initial","setImages","busyId","setBusyId","reordering","setReordering","setAlt","failure","setFailure","reorderFailed","setReorderFailed","removing","setRemoving","focusTarget","listRef","target","find","other","to","previous","next","upload","Fragment","dismiss","FieldShell","described","help","label","CATEGORY_LIST_ID","DetailsFields","suggestCategories","categories","props","onChange","category","STATUSES","SalesFields","statusLabels","AdminProductEditor","ExistingProductEditor","ProductFormView","setBase","setForm","fieldErrors","setFieldErrors","saved","setSaved","showErrors","found","formEl","save","onSubmit","onSaved","imagesSlot","group","useOrderPages","TABS","tabQuery","tab","AdminOrderList","setTab","date","o","pendingRefundCents","order","r","sum","remainingRefundCents","hasPendingRefund","canRestock","amountCents","canShip","canRefund","RefundDialog","keyRef","remaining","amount","setAmount","setReason","restock","setRestock","invalid","setInvalid","refund","amountValid","restockOffered","retryable","onDone","onClose","ResolveButton","resolve","submit","stockError","names","isHttpUrl","protocol","ShipForm","carrier","setCarrier","trackingNumber","setTrackingNumber","trackingUrl","setTrackingUrl","urlError","setUrlError","ship","reship","url","OrderActions","refunding","setRefunding","setMessage","done","OrderFulfillment","f","OrderItems","OrderRefunds","addressLines","region","l","AdminOrderDetail","orderId","lines","actions","counter","newKey","toDrafts","rates","rate","blankDraft","snapshot","drafts","_key","rest","parseDays","checkDrafts","rowErrors","seen","draft","min","max","shippingRatesInputSchema","noActive","SERVER_FIELDS","serverRowErrors","at","segment","ShippingRateRow","fieldId","disabled","AdminShippingRates","setDrafts","baseline","setBaseline","loaded","setLoaded","setRowErrors","blocked","setBlocked","removedAny","setRemovedAny","lastDirty","dirty","onDirtyChange","edit","d","_cleared","add","confirmRemove","check","mixedCurrency","serverErrors"],"sources":["../src/lib/order-action-labels.ts","../src/lib/order-labels.ts","../src/lib/shipping-labels.ts","../src/lib/image-labels.ts","../src/lib/product-labels.ts","../src/lib/provider.tsx","../src/lib/use-admin-query.ts","../src/lib/use-admin-mutation.ts","../src/components/admin-layout/admin-layout.tsx","../src/components/admin-table/admin-table.tsx","../src/components/status-badge/status-badge.tsx","../src/components/money/money.tsx","../src/components/confirm-dialog/confirm-dialog.tsx","../src/components/notice/notice.tsx","../src/components/error-message/error-message.tsx","../src/lib/product-filter.ts","../src/lib/use-debounced.ts","../src/lib/use-product-pages.ts","../src/views/products/admin-product-list.tsx","../src/lib/money-input.ts","../src/lib/product-form.ts","../src/lib/image-rules.ts","../src/lib/use-image-upload.ts","../src/views/products/image-tile.tsx","../src/views/products/upload-picker.tsx","../src/views/products/admin-product-images.tsx","../src/views/products/product-fields.tsx","../src/views/products/admin-product-editor.tsx","../src/lib/use-order-pages.ts","../src/views/orders/admin-order-list.tsx","../src/lib/refund-rules.ts","../src/views/orders/refund-dialog.tsx","../src/views/orders/resolve-button.tsx","../src/views/orders/ship-form.tsx","../src/views/orders/order-actions.tsx","../src/views/orders/order-fulfillment.tsx","../src/views/orders/order-items.tsx","../src/views/orders/order-refunds.tsx","../src/views/orders/admin-order-detail.tsx","../src/lib/shipping-rates.ts","../src/views/shipping/shipping-rate-row.tsx","../src/views/shipping/admin-shipping-rates.tsx"],"sourcesContent":["export interface OrderActionLabels {\n ship: string;\n reship: string;\n shipHeading: string;\n carrier: string;\n trackingNumber: string;\n trackingUrl: string;\n trackingUrlInvalid: string;\n shipped: string;\n refund: string;\n refundTitle: string;\n refundAmount: string;\n refundAmountInvalid: string;\n refundReason: string;\n refundSubmit: string;\n refundRetry: string;\n restock: string;\n restockWarning: string;\n refundPending: string;\n refundUnknown: string;\n refundGateway: string;\n refundDone: string;\n resolve: string;\n resolveHelp: string;\n resolved: string;\n restockThenResolve: string;\n}\n\nexport const defaultOrderActionLabels: OrderActionLabels = {\n ship: 'Mark as shipped',\n reship: 'Update tracking',\n shipHeading: 'Shipping',\n carrier: 'Carrier',\n trackingNumber: 'Tracking number',\n trackingUrl: 'Tracking URL',\n trackingUrlInvalid: 'Enter a full link starting with http:// or https://.',\n shipped: 'Shipping details saved.',\n refund: 'Refund…',\n refundTitle: 'Refund order',\n refundAmount: 'Amount',\n refundAmountInvalid:\n 'Enter an amount above zero and no more than the balance.',\n refundReason: 'Reason',\n refundSubmit: 'Refund',\n refundRetry: 'Retry refund',\n restock: 'Restock items',\n restockWarning: 'Only restock if the item came back.',\n refundPending:\n 'A refund is already pending on this order. Wait for it to finish or refresh before refunding again.',\n refundUnknown:\n 'We could not confirm whether this refund went through; it may have succeeded. Retrying is safe, it will not refund twice.',\n refundGateway:\n 'The payment provider rejected the refund. Retrying is safe, it will not refund twice.',\n refundDone: 'Refund sent.',\n resolve: 'Resolve order',\n resolveHelp:\n 'This order was paid but its stock ran out. Restock the items and resolve it, or refund it.',\n resolved: 'Order resolved.',\n restockThenResolve: 'Restock, then resolve',\n};\n","import type { OrderActionLabels } from './order-action-labels';\nimport { defaultOrderActionLabels } from './order-action-labels';\n\nexport type OrderTab =\n 'paid' | 'shipped' | 'needs_attention' | 'pending_refund' | 'all';\n\nexport interface OrderLabels {\n title: string;\n searchLabel: string;\n searchPlaceholder: string;\n tabs: Record<OrderTab, string>;\n empty: Record<OrderTab, string>;\n noMatches: string;\n loadMore: string;\n columns: {\n order: string;\n status: string;\n email: string;\n items: string;\n total: string;\n date: string;\n };\n noEmail: string;\n detailTitle: string;\n back: string;\n placed: string;\n buyer: string;\n itemsHeading: string;\n itemColumns: { name: string; price: string; quantity: string; line: string };\n subtotal: string;\n shipping: string;\n total: string;\n shippingAddress: string;\n noAddress: string;\n fulfillment: string;\n notShipped: string;\n shippedOn: string;\n carrier: string;\n tracking: string;\n trackShipment: string;\n refunds: string;\n noRefunds: string;\n refundColumns: {\n amount: string;\n reason: string;\n source: string;\n status: string;\n restocked: string;\n date: string;\n };\n refundSources: { admin: string; gateway: string };\n refundStatuses: { pending: string; succeeded: string };\n yes: string;\n no: string;\n refunded: string;\n remaining: string;\n actions: OrderActionLabels;\n}\n\nexport const defaultOrderLabels: OrderLabels = {\n title: 'Orders',\n searchLabel: 'Search orders',\n searchPlaceholder: 'Search by email or order id',\n tabs: {\n paid: 'To ship',\n shipped: 'Shipped',\n needs_attention: 'Needs attention',\n pending_refund: 'Pending refund',\n all: 'All',\n },\n empty: {\n paid: 'Nothing waiting to ship.',\n shipped: 'No shipped orders yet.',\n needs_attention: 'No orders need attention.',\n pending_refund: 'No refunds are pending.',\n all: 'No orders yet.',\n },\n noMatches: 'No orders match that search.',\n loadMore: 'Load more',\n columns: {\n order: 'Order',\n status: 'Status',\n email: 'Buyer',\n items: 'Items',\n total: 'Total',\n date: 'Placed',\n },\n noEmail: 'No email',\n detailTitle: 'Order',\n back: 'Back to orders',\n placed: 'Placed',\n buyer: 'Buyer',\n itemsHeading: 'Items',\n itemColumns: {\n name: 'Item',\n price: 'Price',\n quantity: 'Qty',\n line: 'Subtotal',\n },\n subtotal: 'Subtotal',\n shipping: 'Shipping',\n total: 'Total',\n shippingAddress: 'Shipping address',\n noAddress: 'No shipping address.',\n fulfillment: 'Fulfillment',\n notShipped: 'Not shipped',\n shippedOn: 'Shipped',\n carrier: 'Carrier',\n tracking: 'Tracking',\n trackShipment: 'Track shipment',\n refunds: 'Refunds',\n noRefunds: 'No refunds.',\n refundColumns: {\n amount: 'Amount',\n reason: 'Reason',\n source: 'Source',\n status: 'Status',\n restocked: 'Restocked',\n date: 'Date',\n },\n refundSources: { admin: 'Admin', gateway: 'Payment provider' },\n refundStatuses: { pending: 'Pending', succeeded: 'Refunded' },\n yes: 'Yes',\n no: 'No',\n refunded: 'Refunded',\n remaining: 'Remaining balance',\n actions: defaultOrderActionLabels,\n};\n","export interface ShippingLabels {\n title: string;\n loading: string;\n empty: string;\n add: string;\n save: string;\n saved: string;\n label: string;\n amount: string;\n currency: string;\n mixedCurrency: string;\n minDays: string;\n maxDays: string;\n active: string;\n rowName: string;\n moveEarlier: string;\n moveLater: string;\n remove: string;\n removeTitle: string;\n removeBody: string;\n newRateLabel: string;\n removalWarning: string;\n unsaved: string;\n noActive: string;\n labelRequired: string;\n labelDuplicate: string;\n amountInvalid: string;\n currencyInvalid: string;\n daysInvalid: string;\n daysOrder: string;\n rowInvalid: string;\n}\n\nexport const defaultShippingLabels: ShippingLabels = {\n title: 'Shipping rates',\n loading: 'Loading shipping rates…',\n empty: 'No shipping rates yet. Add one so customers can check out.',\n add: 'Add a rate',\n save: 'Save changes',\n saved: 'Shipping rates saved.',\n label: 'Name',\n amount: 'Price',\n currency: 'Currency',\n mixedCurrency:\n 'These rates use more than one currency. Checkout needs them to match your shop currency ({currency}).',\n minDays: 'Fastest (days)',\n maxDays: 'Slowest (days)',\n active: 'Offered at checkout',\n rowName: 'Rate {n}',\n moveEarlier: 'Move earlier',\n moveLater: 'Move later',\n remove: 'Remove',\n removeTitle: 'Remove this rate?',\n removeBody:\n 'It disappears from checkout once you save. Past orders are not affected.',\n newRateLabel: 'New rate',\n removalWarning:\n 'Saving replaces all rates. Rates you removed will no longer appear at checkout.',\n unsaved: 'You have unsaved changes.',\n noActive:\n 'Keep at least one rate offered at checkout, or customers cannot pay.',\n labelRequired: 'Give this rate a name.',\n labelDuplicate: 'Another rate already has this name.',\n amountInvalid: 'Enter a price like 5.00.',\n currencyInvalid: 'Use a 3-letter currency code like USD.',\n daysInvalid: 'Use a whole number of days, or leave blank.',\n daysOrder: 'Fastest cannot be more than slowest.',\n rowInvalid: 'These details are not valid.',\n};\n","export interface ImageLabels {\n title: string;\n empty: string;\n add: string;\n takePhoto: string;\n dropHint: string;\n altLabel: string;\n altHelp: string;\n altWarning: string;\n cover: string;\n photoName: string;\n moveEarlier: string;\n moveLater: string;\n remove: string;\n removeTitle: string;\n removeBody: string;\n uploading: string;\n working: string;\n tooLarge: string;\n wrongType: string;\n reorderFailed: string;\n dismiss: string;\n}\n\nexport const defaultImageLabels: ImageLabels = {\n title: 'Photos',\n empty: 'Add a photo so this can go live.',\n add: 'Add photos',\n takePhoto: 'Take photo',\n dropHint: 'Drop photos here, or use the buttons.',\n altLabel: 'Photo description',\n altHelp: 'Describe what the photo shows, for people who cannot see it.',\n altWarning: 'No description yet. Add one so everyone can enjoy this photo.',\n cover: 'Cover',\n photoName: 'Photo {n}',\n moveEarlier: 'Move earlier',\n moveLater: 'Move later',\n remove: 'Remove',\n removeTitle: 'Remove this photo?',\n removeBody: 'It will be deleted from this product.',\n uploading: 'Uploading…',\n working: 'Working…',\n tooLarge: '{name} is larger than 8 MB.',\n wrongType: '{name} must be a JPEG, PNG, WebP or HEIC image.',\n reorderFailed: 'The photos could not be reordered. The old order is back.',\n dismiss: 'Dismiss',\n};\n","import { defaultImageLabels, type ImageLabels } from './image-labels';\n\nexport type ProductFilter = 'all' | 'live' | 'sold' | 'draft' | 'archived';\n\nexport interface ProductLabels {\n title: string;\n newProduct: string;\n searchLabel: string;\n searchPlaceholder: string;\n filters: Record<ProductFilter, string>;\n empty: Record<ProductFilter, string>;\n noMatches: string;\n loadMore: string;\n columns: {\n image: string;\n name: string;\n price: string;\n status: string;\n quantity: string;\n actions: string;\n };\n noImage: string;\n viewInShop: string;\n markSold: string;\n archive: string;\n markSoldTitle: string;\n markSoldBody: string;\n archiveTitle: string;\n archiveBody: string;\n updated: string;\n createTitle: string;\n editTitle: string;\n saved: string;\n fields: {\n name: string;\n category: string;\n description: string;\n materials: string;\n dimensions: string;\n price: string;\n quantity: string;\n status: string;\n featured: string;\n };\n images: ImageLabels;\n statusHelp: string;\n priceHelp: string;\n validation: {\n required: string;\n price: string;\n quantity: string;\n };\n}\n\nexport const defaultProductLabels: ProductLabels = {\n title: 'Products',\n newProduct: 'New product',\n searchLabel: 'Search products',\n searchPlaceholder: 'Search by name',\n filters: {\n all: 'All',\n live: 'Live',\n sold: 'Sold',\n draft: 'Drafts',\n archived: 'Archived',\n },\n empty: {\n all: 'No products yet. Add your first piece.',\n live: 'Nothing is live in the shop right now.',\n sold: 'Nothing has sold out yet.',\n draft: 'No drafts.',\n archived: 'No archived products.',\n },\n noMatches: 'No products match that search.',\n loadMore: 'Load more',\n columns: {\n image: 'Image',\n name: 'Name',\n price: 'Price',\n status: 'Status',\n quantity: 'In stock',\n actions: 'Actions',\n },\n noImage: 'No image',\n viewInShop: 'View in shop',\n markSold: 'Mark sold',\n archive: 'Archive',\n markSoldTitle: 'Mark as sold?',\n markSoldBody: 'This sets the stock to zero. Customers will see it as sold.',\n archiveTitle: 'Archive this product?',\n archiveBody: 'It will disappear from the shop. You can restore it later.',\n updated: 'Product updated.',\n createTitle: 'New product',\n editTitle: 'Edit product',\n saved: 'Saved.',\n fields: {\n name: 'Name',\n category: 'Category',\n description: 'Description',\n materials: 'Materials',\n dimensions: 'Dimensions',\n price: 'Price',\n quantity: 'Quantity',\n status: 'Status',\n featured: 'Feature this product on the home page',\n },\n images: defaultImageLabels,\n statusHelp:\n 'Draft is hidden. Active is live in the shop. Archived is hidden and kept. Mark a piece sold from the product list.',\n priceHelp: 'In dollars, for example 48.00.',\n validation: {\n required: 'This field is required.',\n price: 'Enter a price like 48 or 48.50.',\n quantity: 'Enter a whole number, zero or more.',\n },\n};\n","import type { AdminClient } from '../client';\nimport { createContext, useContext, type ReactNode } from 'react';\nimport { defaultOrderLabels, type OrderLabels } from './order-labels';\nimport { defaultShippingLabels, type ShippingLabels } from './shipping-labels';\nimport { defaultProductLabels, type ProductLabels } from './product-labels';\n\nexport interface LinkProps {\n href: string;\n children: ReactNode;\n className?: string;\n}\n\nexport interface AdminImageProps {\n src: string;\n alt: string;\n sizes?: string;\n className?: string;\n priority?: boolean;\n}\n\nexport type AdminErrorKey =\n | 'unauthorized'\n | 'notFound'\n | 'invalidInput'\n | 'invalidOrderState'\n | 'insufficientStock'\n | 'refundExceedsBalance'\n | 'refundGateway'\n | 'refundOutcomeUnknown'\n | 'imageInvalid'\n | 'imageTooLarge'\n | 'generic';\n\nexport interface AdminLabels {\n loading: string;\n empty: string;\n save: string;\n cancel: string;\n confirm: string;\n dismiss: string;\n navLabel: string;\n nav: { products: string; orders: string; shippingRates: string };\n statuses: Record<string, string>;\n errors: Record<AdminErrorKey, string>;\n products: ProductLabels;\n orders: OrderLabels;\n shipping: ShippingLabels;\n}\n\nexport interface AdminConfig {\n renderLink: (props: LinkProps) => ReactNode;\n renderImage: (props: AdminImageProps) => ReactNode;\n locale: string;\n currency: string;\n hrefs: {\n products: string;\n product: (id: string) => string;\n newProduct: string;\n orders: string;\n order: (id: string) => string;\n shippingRates: string;\n storefrontProduct?: (slug: string) => string;\n };\n client: AdminClient | null;\n labels: AdminLabels;\n}\n\nconst defaults: AdminConfig = {\n renderLink: ({ href, children, className }) => (\n <a href={href} className={className}>\n {children}\n </a>\n ),\n renderImage: ({ src, alt, sizes, className, priority }) => (\n <img\n src={src}\n alt={alt}\n sizes={sizes}\n className={className}\n loading={priority ? 'eager' : 'lazy'}\n decoding=\"async\"\n fetchPriority={priority ? 'high' : undefined}\n />\n ),\n locale: 'en-US',\n currency: 'USD',\n hrefs: {\n products: '/admin/products',\n product: (id) => `/admin/products/${id}`,\n newProduct: '/admin/products/new',\n orders: '/admin/orders',\n order: (id) => `/admin/orders/${id}`,\n shippingRates: '/admin/shipping-rates',\n },\n client: null,\n labels: {\n loading: 'Loading…',\n empty: 'Nothing here yet.',\n save: 'Save',\n cancel: 'Cancel',\n confirm: 'Confirm',\n dismiss: 'Dismiss',\n navLabel: 'Admin',\n nav: {\n products: 'Products',\n orders: 'Orders',\n shippingRates: 'Shipping rates',\n },\n statuses: {\n draft: 'Draft',\n active: 'Active',\n archived: 'Archived',\n pending: 'Pending',\n paid: 'Paid',\n shipped: 'Shipped',\n cancelled: 'Cancelled',\n expired: 'Expired',\n needs_attention: 'Needs attention',\n refunded: 'Refunded',\n sold: 'Sold',\n },\n errors: {\n unauthorized: 'You are not signed in or not allowed to do this.',\n notFound: 'We could not find that.',\n invalidInput:\n 'Some of the details are not valid. Check them and try again.',\n invalidOrderState:\n 'This order cannot be changed that way in its current state.',\n insufficientStock: 'Not enough stock is available.',\n refundExceedsBalance: 'The refund is more than the remaining balance.',\n refundGateway:\n 'The payment provider rejected the refund. Try again shortly.',\n refundOutcomeUnknown:\n 'Refund outcome unknown — retry with the same request.',\n imageInvalid: 'That image could not be used. Try a different file.',\n imageTooLarge: 'That image is too large. Choose a smaller one.',\n generic: 'Something went wrong. Try again.',\n },\n products: defaultProductLabels,\n orders: defaultOrderLabels,\n shipping: defaultShippingLabels,\n },\n};\n\nconst AdminContext = createContext<AdminConfig>(defaults);\n\ntype DeepPartial<T> = {\n [K in keyof T]?: T[K] extends object ? Partial<T[K]> : T[K];\n};\n\nfunction mergeOrderLabels(\n overrides: DeepPartial<OrderLabels> | undefined,\n): OrderLabels {\n const base = defaultOrderLabels;\n return {\n ...base,\n ...overrides,\n tabs: { ...base.tabs, ...overrides?.tabs },\n empty: { ...base.empty, ...overrides?.empty },\n columns: { ...base.columns, ...overrides?.columns },\n itemColumns: { ...base.itemColumns, ...overrides?.itemColumns },\n refundColumns: { ...base.refundColumns, ...overrides?.refundColumns },\n refundSources: { ...base.refundSources, ...overrides?.refundSources },\n refundStatuses: { ...base.refundStatuses, ...overrides?.refundStatuses },\n actions: { ...base.actions, ...overrides?.actions },\n } as OrderLabels;\n}\n\nexport interface AdminProviderProps extends Partial<\n Omit<AdminConfig, 'hrefs' | 'labels'>\n> {\n hrefs?: Partial<AdminConfig['hrefs']>;\n labels?: Partial<\n Omit<\n AdminLabels,\n 'nav' | 'statuses' | 'errors' | 'products' | 'orders' | 'shipping'\n > & {\n nav: Partial<AdminLabels['nav']>;\n statuses: Partial<AdminLabels['statuses']>;\n errors: Partial<AdminLabels['errors']>;\n products: DeepPartial<ProductLabels>;\n orders: DeepPartial<OrderLabels>;\n shipping: Partial<ShippingLabels>;\n }\n >;\n children: ReactNode;\n}\n\nfunction mergeProductLabels(\n overrides: DeepPartial<ProductLabels> | undefined,\n): ProductLabels {\n const base = defaultProductLabels;\n return {\n ...base,\n ...overrides,\n filters: { ...base.filters, ...overrides?.filters },\n empty: { ...base.empty, ...overrides?.empty },\n columns: { ...base.columns, ...overrides?.columns },\n fields: { ...base.fields, ...overrides?.fields },\n validation: { ...base.validation, ...overrides?.validation },\n images: { ...base.images, ...overrides?.images },\n } as ProductLabels;\n}\n\nexport function AdminProvider({\n children,\n hrefs,\n labels,\n ...overrides\n}: AdminProviderProps) {\n const value: AdminConfig = {\n ...defaults,\n ...overrides,\n hrefs: { ...defaults.hrefs, ...hrefs },\n labels: {\n ...defaults.labels,\n ...labels,\n nav: { ...defaults.labels.nav, ...labels?.nav },\n statuses: { ...defaults.labels.statuses, ...labels?.statuses } as Record<\n string,\n string\n >,\n errors: {\n ...defaults.labels.errors,\n ...labels?.errors,\n } as AdminLabels['errors'],\n products: mergeProductLabels(labels?.products),\n orders: mergeOrderLabels(labels?.orders),\n shipping: { ...defaultShippingLabels, ...labels?.shipping },\n },\n };\n return (\n <AdminContext.Provider value={value}>{children}</AdminContext.Provider>\n );\n}\n\nexport function useAdmin(): AdminConfig {\n return useContext(AdminContext);\n}\n\nexport function useAdminClient(): AdminClient {\n const { client } = useAdmin();\n if (!client) {\n throw new Error('AdminProvider needs a `client` to render this view.');\n }\n return client;\n}\n","import { useCallback, useEffect, useRef, useState } from 'react';\n\nexport interface AdminQuery<T> {\n data: T | undefined;\n error: unknown;\n loading: boolean;\n reload: () => void;\n}\n\ninterface Settled<T> {\n request: string;\n data: T | undefined;\n error: unknown;\n}\n\nexport function useAdminQuery<T>(\n key: readonly unknown[],\n fn: (signal: AbortSignal) => Promise<T>,\n): AdminQuery<T> {\n const fnRef = useRef(fn);\n useEffect(() => {\n fnRef.current = fn;\n });\n const [reloadCount, setReloadCount] = useState(0);\n const [settled, setSettled] = useState<Settled<T>>({\n request: '',\n data: undefined,\n error: undefined,\n });\n const request = `${JSON.stringify(key)}#${reloadCount}`;\n\n useEffect(() => {\n const controller = new AbortController();\n fnRef\n .current(controller.signal)\n .then((data) => {\n if (!controller.signal.aborted)\n setSettled({ request, data, error: undefined });\n })\n .catch((error: unknown) => {\n if (!controller.signal.aborted)\n setSettled((prev) => ({ request, data: prev.data, error }));\n });\n return () => controller.abort();\n }, [request]);\n\n const reload = useCallback(() => setReloadCount((n) => n + 1), []);\n const current = settled.request === request;\n return {\n data: settled.data,\n error: current ? settled.error : undefined,\n loading: !current,\n reload,\n };\n}\n","import { useCallback, useEffect, useRef, useState } from 'react';\n\nexport interface AdminMutation<A extends unknown[], R> {\n run: (...args: A) => Promise<R | undefined>;\n pending: boolean;\n error: unknown;\n reset: () => void;\n}\n\nexport function useAdminMutation<A extends unknown[], R>(\n fn: (...args: A) => Promise<R>,\n): AdminMutation<A, R> {\n const fnRef = useRef(fn);\n useEffect(() => {\n fnRef.current = fn;\n });\n const [pending, setPending] = useState(false);\n const [error, setError] = useState<unknown>(undefined);\n\n const run = useCallback(async (...args: A) => {\n setPending(true);\n setError(undefined);\n try {\n return await fnRef.current(...args);\n } catch (err) {\n setError(err);\n return undefined;\n } finally {\n setPending(false);\n }\n }, []);\n\n const reset = useCallback(() => setError(undefined), []);\n return { run, pending, error, reset };\n}\n","import type { ReactNode } from 'react';\nimport { useAdmin } from '../../lib/provider';\n\nexport interface ExtraNavItem {\n href: string;\n label: string;\n position?: 'start' | 'end';\n}\n\nexport interface AdminLayoutProps {\n children: ReactNode;\n extraNav?: ExtraNavItem[];\n header?: ReactNode;\n footer?: ReactNode;\n}\n\nexport function AdminLayout({\n children,\n extraNav = [],\n header,\n footer,\n}: AdminLayoutProps) {\n const { hrefs, labels, renderLink } = useAdmin();\n const kit: ExtraNavItem[] = [\n { href: hrefs.products, label: labels.nav.products },\n { href: hrefs.orders, label: labels.nav.orders },\n { href: hrefs.shippingRates, label: labels.nav.shippingRates },\n ];\n const items = [\n ...extraNav.filter((i) => i.position === 'start'),\n ...kit,\n ...extraNav.filter((i) => i.position !== 'start'),\n ];\n return (\n <div className=\"sfa-root sfa-layout\">\n {header ? <header className=\"sfa-layout__header\">{header}</header> : null}\n <nav className=\"sfa-nav\" aria-label={labels.navLabel}>\n <ul>\n {items.map((item) => (\n <li key={item.href}>\n {renderLink({\n href: item.href,\n className: 'sfa-nav__link',\n children: item.label,\n })}\n </li>\n ))}\n </ul>\n </nav>\n <main className=\"sfa-layout__content\">{children}</main>\n {footer ? <footer className=\"sfa-layout__footer\">{footer}</footer> : null}\n </div>\n );\n}\n","import type { ReactNode } from 'react';\nimport { useAdmin } from '../../lib/provider';\n\nexport interface AdminColumn<T> {\n key: string;\n header: string;\n render: (row: T) => ReactNode;\n}\n\nexport interface AdminTableProps<T> {\n columns: AdminColumn<T>[];\n rows: T[];\n rowKey: (row: T) => string;\n caption?: string;\n}\n\nexport function AdminTable<T>({\n columns,\n rows,\n rowKey,\n caption,\n}: AdminTableProps<T>) {\n const { labels } = useAdmin();\n if (rows.length === 0) return <p className=\"sfa-empty\">{labels.empty}</p>;\n return (\n <table className=\"sfa-table sfa-table--stacked\">\n {caption ? <caption>{caption}</caption> : null}\n <thead>\n <tr>\n {columns.map((c) => (\n <th key={c.key} scope=\"col\">\n {c.header}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {rows.map((row) => (\n <tr key={rowKey(row)}>\n {columns.map((c) => (\n <td key={c.key} data-label={c.header}>\n {c.render(row)}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n );\n}\n","import { useAdmin } from '../../lib/provider';\n\nexport function StatusBadge({ status }: { status: string }) {\n const { labels } = useAdmin();\n return (\n <span className={`sfa-badge sfa-badge--${status.replace(/_/g, '-')}`}>\n {labels.statuses[status] ?? status}\n </span>\n );\n}\n","import { useAdmin } from '../../lib/provider';\n\nexport interface MoneyProps {\n cents: number;\n currency: string;\n}\n\nexport function Money({ cents, currency }: MoneyProps) {\n const { locale } = useAdmin();\n const text = new Intl.NumberFormat(locale, {\n style: 'currency',\n currency,\n }).format(cents / 100);\n return <span className=\"sfa-money\">{text}</span>;\n}\n","import { useEffect, useRef, type KeyboardEvent, type ReactNode } from 'react';\nimport { useAdmin } from '../../lib/provider';\n\nconst FOCUSABLE =\n 'button:not([disabled]), [href], input:not([disabled]), select, textarea, [tabindex]:not([tabindex=\"-1\"])';\n\nexport interface ConfirmDialogProps {\n open: boolean;\n title: string;\n children?: ReactNode;\n confirmLabel?: string;\n destructive?: boolean;\n pending?: boolean;\n onConfirm: () => void;\n onCancel: () => void;\n}\n\nexport function ConfirmDialog({\n open,\n title,\n children,\n confirmLabel,\n destructive = false,\n pending = false,\n onConfirm,\n onCancel,\n}: ConfirmDialogProps) {\n const { labels } = useAdmin();\n const panelRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!open) return;\n const trigger = document.activeElement as HTMLElement | null;\n panelRef.current?.querySelector<HTMLElement>(FOCUSABLE)?.focus();\n return () => trigger?.focus();\n }, [open]);\n\n if (!open) return null;\n\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n event.stopPropagation();\n onCancel();\n return;\n }\n if (event.key !== 'Tab') return;\n const focusable = Array.from(\n panelRef.current?.querySelectorAll<HTMLElement>(FOCUSABLE) ?? [],\n );\n if (focusable.length === 0) return;\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n if (event.shiftKey && document.activeElement === first) {\n event.preventDefault();\n last.focus();\n } else if (!event.shiftKey && document.activeElement === last) {\n event.preventDefault();\n first.focus();\n }\n };\n\n return (\n <div className=\"sfa-dialog-backdrop\" onKeyDown={onKeyDown}>\n <div\n ref={panelRef}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={title}\n className=\"sfa-dialog\"\n >\n <h2 className=\"sfa-dialog__title\">{title}</h2>\n {children}\n <div className=\"sfa-dialog__actions\">\n <button type=\"button\" className=\"sfa-btn\" onClick={onCancel}>\n {labels.cancel}\n </button>\n <button\n type=\"button\"\n className={`sfa-btn ${destructive ? 'sfa-btn--danger' : 'sfa-btn--primary'}`}\n disabled={pending}\n onClick={onConfirm}\n >\n {confirmLabel ?? labels.confirm}\n </button>\n </div>\n </div>\n </div>\n );\n}\n","import { useEffect, type ReactNode } from 'react';\nimport { useAdmin } from '../../lib/provider';\n\nexport interface NoticeProps {\n variant: 'success' | 'error' | 'warning';\n children: ReactNode;\n toast?: boolean;\n duration?: number;\n onDismiss?: () => void;\n}\n\nexport function Notice({\n variant,\n children,\n toast = false,\n duration = 4000,\n onDismiss,\n}: NoticeProps) {\n const { labels } = useAdmin();\n\n useEffect(() => {\n if (!toast || !onDismiss) return;\n const timer = setTimeout(onDismiss, duration);\n return () => clearTimeout(timer);\n }, [toast, duration, onDismiss]);\n\n const role = variant === 'error' ? 'alert' : 'status';\n const className = `sfa-notice sfa-notice--${variant}${toast ? ' sfa-notice--toast' : ''}`;\n return (\n <div role={role} className={className}>\n <span className=\"sfa-notice__body\">{children}</span>\n {onDismiss && !toast ? (\n <button type=\"button\" className=\"sfa-btn\" onClick={onDismiss}>\n {labels.dismiss}\n </button>\n ) : null}\n </div>\n );\n}\n","import {\n AdminInvalidInputError,\n AdminNotFoundError,\n AdminUnauthorizedError,\n ImageTooLargeError,\n InsufficientStockError,\n InvalidImageError,\n InvalidOrderStateError,\n RefundExceedsBalanceError,\n RefundGatewayError,\n RefundOutcomeUnknownError,\n} from '../../client';\nimport { useAdmin, type AdminErrorKey } from '../../lib/provider';\nimport { Notice } from '../notice/notice';\n\nconst KEYED: Array<[new (...args: never[]) => Error, AdminErrorKey]> = [\n [AdminUnauthorizedError, 'unauthorized'],\n [AdminNotFoundError, 'notFound'],\n [AdminInvalidInputError, 'invalidInput'],\n [InvalidOrderStateError, 'invalidOrderState'],\n [InsufficientStockError, 'insufficientStock'],\n [RefundExceedsBalanceError, 'refundExceedsBalance'],\n [RefundGatewayError, 'refundGateway'],\n [RefundOutcomeUnknownError, 'refundOutcomeUnknown'],\n [ImageTooLargeError, 'imageTooLarge'],\n [InvalidImageError, 'imageInvalid'],\n];\n\nexport function errorKey(error: unknown): AdminErrorKey {\n return KEYED.find(([type]) => error instanceof type)?.[1] ?? 'generic';\n}\n\nexport function ErrorMessage({ error }: { error: unknown }) {\n const { labels } = useAdmin();\n if (!error) return null;\n return <Notice variant=\"error\">{labels.errors[errorKey(error)]}</Notice>;\n}\n","import type {\n AdminProduct,\n ProductStatus,\n} from '@develemit/commerce-contracts';\nimport type { ProductFilter } from './product-labels';\n\nexport function isSold(product: AdminProduct): boolean {\n return product.status === 'active' && product.quantity === 0;\n}\n\nexport function displayStatus(product: AdminProduct): string {\n return isSold(product) ? 'sold' : product.status;\n}\n\nexport function serverStatus(filter: ProductFilter): ProductStatus | undefined {\n switch (filter) {\n case 'live':\n case 'sold':\n return 'active';\n case 'draft':\n case 'archived':\n return filter;\n case 'all':\n return undefined;\n }\n}\n\nexport function serverStock(filter: ProductFilter): 'in' | 'sold' | undefined {\n if (filter === 'live') return 'in';\n if (filter === 'sold') return 'sold';\n return undefined;\n}\n","import { useEffect, useState } from 'react';\n\nexport function useDebounced<T>(value: T, delayMs: number): T {\n const [debounced, setDebounced] = useState(value);\n useEffect(() => {\n const timer = setTimeout(() => setDebounced(value), delayMs);\n return () => clearTimeout(timer);\n }, [value, delayMs]);\n return debounced;\n}\n","import { useState } from 'react';\nimport type {\n AdminProduct,\n AdminProductPage,\n} from '@develemit/commerce-contracts';\nimport type { AdminProductQuery } from '../client/admin-client';\nimport { useAdminClient } from './provider';\nimport { useAdminMutation } from './use-admin-mutation';\nimport { useAdminQuery } from './use-admin-query';\n\ninterface Appended {\n base: AdminProductPage;\n items: AdminProduct[];\n nextCursor: string | null;\n}\n\nexport function useProductPages(query: Omit<AdminProductQuery, 'cursor'>) {\n const client = useAdminClient();\n const first = useAdminQuery(['admin-products', query], () =>\n client.listProducts(query),\n );\n const [appended, setAppended] = useState<Appended | null>(null);\n const more = useAdminMutation(\n async (cursor: string, base: AdminProductPage) => {\n const page = await client.listProducts({ ...query, cursor });\n setAppended((prev) => ({\n base,\n items: [...(prev?.base === base ? prev.items : []), ...page.items],\n nextCursor: page.nextCursor,\n }));\n },\n );\n\n const base = first.data;\n const extra = appended && appended.base === base ? appended : null;\n const nextCursor = extra ? extra.nextCursor : (base?.nextCursor ?? null);\n return {\n items: [...(base?.items ?? []), ...(extra?.items ?? [])],\n loaded: base !== undefined,\n loading: first.loading,\n error: first.error ?? more.error,\n hasMore: !first.loading && nextCursor !== null,\n loadingMore: more.pending,\n reload: first.reload,\n loadMore: () => {\n if (base && nextCursor) void more.run(nextCursor, base);\n },\n };\n}\n","import { useState } from 'react';\nimport type { AdminProduct } from '@develemit/commerce-contracts';\nimport {\n AdminTable,\n type AdminColumn,\n} from '../../components/admin-table/admin-table';\nimport { ConfirmDialog } from '../../components/confirm-dialog/confirm-dialog';\nimport { ErrorMessage } from '../../components/error-message/error-message';\nimport { Money } from '../../components/money/money';\nimport { Notice } from '../../components/notice/notice';\nimport { StatusBadge } from '../../components/status-badge/status-badge';\nimport {\n displayStatus,\n serverStatus,\n serverStock,\n} from '../../lib/product-filter';\nimport type { ProductFilter } from '../../lib/product-labels';\nimport { useAdmin, useAdminClient } from '../../lib/provider';\nimport { useAdminMutation } from '../../lib/use-admin-mutation';\nimport { useDebounced } from '../../lib/use-debounced';\nimport { useProductPages } from '../../lib/use-product-pages';\n\nconst FILTERS: ProductFilter[] = ['all', 'live', 'sold', 'draft', 'archived'];\n\ntype RowAction = { kind: 'sold' | 'archive'; product: AdminProduct };\n\nexport function AdminProductList() {\n const client = useAdminClient();\n const { labels, hrefs, renderLink } = useAdmin();\n const copy = labels.products;\n const [filter, setFilter] = useState<ProductFilter>('all');\n const [search, setSearch] = useState('');\n const q = useDebounced(search.trim(), 300);\n const status = serverStatus(filter);\n const stock = serverStock(filter);\n const pages = useProductPages({\n ...(status ? { status } : {}),\n ...(stock ? { stock } : {}),\n ...(q ? { q } : {}),\n });\n const [pending, setPending] = useState<RowAction | null>(null);\n const [updated, setUpdated] = useState(false);\n\n const apply = useAdminMutation(({ kind, product }: RowAction) =>\n client.updateProduct(\n product.id,\n kind === 'sold' ? { sold: true } : { status: 'archived' },\n ),\n );\n\n const confirm = async () => {\n if (!pending) return;\n const result = await apply.run(pending);\n setPending(null);\n if (!result) return;\n setUpdated(true);\n pages.reload();\n };\n\n const columns: AdminColumn<AdminProduct>[] = [\n {\n key: 'image',\n header: copy.columns.image,\n render: (p) =>\n p.images[0] ? (\n <img\n className=\"sfa-thumb\"\n src={p.images[0].url}\n alt={p.images[0].alt}\n width={48}\n height={48}\n />\n ) : (\n <span className=\"sfa-thumb sfa-thumb--empty\">{copy.noImage}</span>\n ),\n },\n {\n key: 'name',\n header: copy.columns.name,\n render: (p) =>\n renderLink({\n href: hrefs.product(p.id),\n children: p.name,\n className: 'sfa-link--tap',\n }),\n },\n {\n key: 'price',\n header: copy.columns.price,\n render: (p) => <Money cents={p.priceCents} currency={p.currency} />,\n },\n {\n key: 'status',\n header: copy.columns.status,\n render: (p) => <StatusBadge status={displayStatus(p)} />,\n },\n {\n key: 'quantity',\n header: copy.columns.quantity,\n render: (p) => p.quantity,\n },\n {\n key: 'actions',\n header: copy.columns.actions,\n render: (p) => (\n <div className=\"sfa-row-actions\">\n {p.status === 'active' && hrefs.storefrontProduct\n ? renderLink({\n href: hrefs.storefrontProduct(p.slug),\n children: copy.viewInShop,\n className: 'sfa-btn',\n })\n : null}\n {p.status !== 'archived' && p.quantity > 0 ? (\n <button\n type=\"button\"\n className=\"sfa-btn\"\n onClick={() => setPending({ kind: 'sold', product: p })}\n >\n {copy.markSold}\n </button>\n ) : null}\n {p.status !== 'archived' ? (\n <button\n type=\"button\"\n className=\"sfa-btn\"\n onClick={() => setPending({ kind: 'archive', product: p })}\n >\n {copy.archive}\n </button>\n ) : null}\n </div>\n ),\n },\n ];\n\n const rows = pages.items;\n const emptyText = q ? copy.noMatches : copy.empty[filter];\n\n return (\n <section className=\"sfa-products\">\n <header className=\"sfa-products__header\">\n <h1>{copy.title}</h1>\n {renderLink({\n href: hrefs.newProduct,\n children: copy.newProduct,\n className: 'sfa-btn sfa-btn--primary',\n })}\n </header>\n <div className=\"sfa-products__toolbar\">\n <div\n role=\"group\"\n aria-label={copy.columns.status}\n className=\"sfa-filter-group\"\n >\n {FILTERS.map((value) => (\n <button\n key={value}\n type=\"button\"\n className=\"sfa-btn sfa-filter\"\n aria-pressed={filter === value}\n onClick={() => setFilter(value)}\n >\n {copy.filters[value]}\n </button>\n ))}\n </div>\n <input\n type=\"search\"\n aria-label={copy.searchLabel}\n placeholder={copy.searchPlaceholder}\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n />\n </div>\n <ErrorMessage error={pages.error ?? apply.error} />\n {pages.loading && !pages.loaded ? (\n <p>{labels.loading}</p>\n ) : rows.length === 0 ? (\n <p className=\"sfa-empty\">{emptyText}</p>\n ) : (\n <AdminTable columns={columns} rows={rows} rowKey={(p) => p.id} />\n )}\n {pages.hasMore ? (\n <button\n type=\"button\"\n className=\"sfa-btn sfa-products__more\"\n disabled={pages.loadingMore}\n onClick={pages.loadMore}\n >\n {copy.loadMore}\n </button>\n ) : null}\n <ConfirmDialog\n open={pending !== null}\n title={\n pending?.kind === 'archive' ? copy.archiveTitle : copy.markSoldTitle\n }\n confirmLabel={\n pending?.kind === 'archive' ? copy.archive : copy.markSold\n }\n pending={apply.pending}\n onConfirm={confirm}\n onCancel={() => setPending(null)}\n >\n <p>\n {pending?.product.name}\n {' — '}\n {pending?.kind === 'archive' ? copy.archiveBody : copy.markSoldBody}\n </p>\n </ConfirmDialog>\n {updated ? (\n <Notice variant=\"success\" toast onDismiss={() => setUpdated(false)}>\n {copy.updated}\n </Notice>\n ) : null}\n </section>\n );\n}\n","const MONEY = /^\\$?\\s*(\\d+|\\d{1,3}(?:,\\d{3})+)?(?:\\.(\\d{1,2}))?$/;\n\nexport function parseMoneyInput(raw: string): number | null {\n const text = raw.trim();\n const match = MONEY.exec(text);\n if (!match || (!match[1] && !match[2])) return null;\n const whole = Number((match[1] ?? '0').replace(/,/g, ''));\n const fraction = Number((match[2] ?? '').padEnd(2, '0'));\n const cents = whole * 100 + fraction;\n return Number.isSafeInteger(cents) ? cents : null;\n}\n\nexport function formatMoneyInput(cents: number): string {\n const whole = Math.floor(cents / 100);\n const fraction = String(cents % 100).padStart(2, '0');\n return `${whole}.${fraction}`;\n}\n","import {\n adminProductInputSchema,\n type AdminProduct,\n type AdminProductInput,\n type AdminProductPatch,\n type ProductStatus,\n} from '@develemit/commerce-contracts';\nimport { formatMoneyInput, parseMoneyInput } from './money-input';\nimport type { ProductLabels } from './product-labels';\n\nexport const FIELD_ORDER = [\n 'name',\n 'category',\n 'description',\n 'materials',\n 'dimensions',\n 'price',\n 'quantity',\n 'status',\n 'featured',\n] as const;\n\nexport type FieldName = (typeof FIELD_ORDER)[number];\nexport type FieldErrors = Partial<Record<FieldName, string>>;\n\nexport interface ProductForm {\n name: string;\n category: string;\n description: string;\n materials: string;\n dimensions: string;\n price: string;\n quantity: string;\n status: ProductStatus;\n featured: boolean;\n}\n\nexport const emptyForm: ProductForm = {\n name: '',\n category: '',\n description: '',\n materials: '',\n dimensions: '',\n price: '',\n quantity: '1',\n status: 'draft',\n featured: false,\n};\n\nexport function formFromProduct(product: AdminProduct): ProductForm {\n return {\n name: product.name,\n category: product.category,\n description: product.description,\n materials: product.materials ?? '',\n dimensions: product.dimensions ?? '',\n price: formatMoneyInput(product.priceCents),\n quantity: String(product.quantity),\n status: product.status,\n featured: product.featured,\n };\n}\n\nfunction fieldFor(path: unknown): FieldName | undefined {\n const head = Array.isArray(path) ? String(path[0] ?? '') : String(path ?? '');\n const mapped = head === 'priceCents' ? 'price' : head;\n return (FIELD_ORDER as readonly string[]).includes(mapped)\n ? (mapped as FieldName)\n : undefined;\n}\n\nexport function mapServerIssues(issues: unknown[]): FieldErrors {\n const errors: FieldErrors = {};\n for (const issue of issues) {\n const { path, message } = (issue ?? {}) as {\n path?: unknown;\n message?: unknown;\n };\n const field = fieldFor(path);\n if (field && !errors[field]) {\n errors[field] = typeof message === 'string' ? message : 'Invalid value.';\n }\n }\n return errors;\n}\n\nexport function firstInvalidField(errors: FieldErrors): FieldName | undefined {\n return FIELD_ORDER.find((field) => errors[field]);\n}\n\nexport type ValidationResult =\n { ok: true; input: AdminProductInput } | { ok: false; errors: FieldErrors };\n\nfunction blankToNull(value: string): string | null {\n const trimmed = value.trim();\n return trimmed === '' ? null : trimmed;\n}\n\nexport function validateForm(\n form: ProductForm,\n labels: ProductLabels,\n currency?: string,\n): ValidationResult {\n const errors: FieldErrors = {};\n const priceCents = parseMoneyInput(form.price);\n if (priceCents === null) errors.price = labels.validation.price;\n const quantity = /^\\d+$/.test(form.quantity.trim())\n ? Number(form.quantity.trim())\n : null;\n if (quantity === null) errors.quantity = labels.validation.quantity;\n\n const parsed = adminProductInputSchema.safeParse({\n name: form.name,\n description: form.description,\n materials: blankToNull(form.materials),\n dimensions: blankToNull(form.dimensions),\n priceCents: priceCents ?? 0,\n ...(currency ? { currency } : {}),\n category: form.category,\n quantity: quantity ?? 0,\n status: form.status,\n featured: form.featured,\n });\n if (!parsed.success) {\n for (const issue of parsed.error.issues) {\n const field = fieldFor(issue.path);\n if (field && !errors[field]) errors[field] = labels.validation.required;\n }\n }\n if (!parsed.success || Object.keys(errors).length > 0) {\n return { ok: false, errors };\n }\n return { ok: true, input: parsed.data };\n}\n\nconst PATCH_KEYS = [\n 'name',\n 'description',\n 'materials',\n 'dimensions',\n 'priceCents',\n 'category',\n 'quantity',\n 'status',\n 'featured',\n] as const;\n\nexport function buildPatch(\n original: AdminProduct,\n input: AdminProductInput,\n): AdminProductPatch {\n const patch: Record<string, unknown> = {};\n for (const key of PATCH_KEYS) {\n const next = input[key] ?? null;\n if (next !== original[key]) patch[key] = input[key];\n }\n return patch as AdminProductPatch;\n}\n","import type { ImageLabels } from './image-labels';\n\nexport const MAX_IMAGE_BYTES = 8 * 1024 * 1024;\n\nconst ACCEPTED_TYPES = ['image/jpeg', 'image/png', 'image/webp', 'image/heic'];\n\nexport function fill(template: string, values: Record<string, string>) {\n return template.replace(/\\{(\\w+)\\}/g, (_, key: string) => values[key] ?? '');\n}\n\nexport function imageFileProblem(\n file: File,\n labels: ImageLabels,\n): string | null {\n if (!ACCEPTED_TYPES.includes(file.type)) {\n return fill(labels.wrongType, { name: file.name });\n }\n if (file.size > MAX_IMAGE_BYTES) {\n return fill(labels.tooLarge, { name: file.name });\n }\n return null;\n}\n","import { useCallback, useEffect, useRef, useState } from 'react';\nimport type { AdminProduct } from '@develemit/commerce-contracts';\nimport { imageFileProblem } from './image-rules';\nimport { useAdmin, useAdminClient } from './provider';\n\nexport interface UploadEntry {\n id: number;\n name: string;\n status: 'queued' | 'uploading' | 'error';\n reason?: string;\n error?: unknown;\n}\n\ninterface Options {\n productId: string;\n onUploaded: (product: AdminProduct) => void;\n}\n\nexport function useImageUpload({ productId, onUploaded }: Options) {\n const client = useAdminClient();\n const { labels } = useAdmin();\n const [entries, setEntries] = useState<UploadEntry[]>([]);\n const nextId = useRef(0);\n const chain = useRef<Promise<void>>(Promise.resolve());\n const onUploadedRef = useRef(onUploaded);\n useEffect(() => {\n onUploadedRef.current = onUploaded;\n });\n\n const patch = (id: number, change: Partial<UploadEntry>) =>\n setEntries((prev) =>\n prev.map((entry) => (entry.id === id ? { ...entry, ...change } : entry)),\n );\n const drop = (id: number) =>\n setEntries((prev) => prev.filter((entry) => entry.id !== id));\n\n const send = async (id: number, file: File, alt: string) => {\n patch(id, { status: 'uploading' });\n try {\n const product = await client.uploadProductImage(productId, file, alt);\n onUploadedRef.current(product);\n drop(id);\n } catch (error) {\n patch(id, { status: 'error', error });\n }\n };\n\n const upload = useCallback(\n (files: File[], alt: string) => {\n const added = files.map((file) => ({\n id: nextId.current++,\n file,\n reason: imageFileProblem(file, labels.products.images),\n }));\n setEntries((prev) => [\n ...prev,\n ...added.map(({ id, file, reason }): UploadEntry => ({\n id,\n name: file.name,\n status: reason ? 'error' : 'queued',\n reason: reason ?? undefined,\n })),\n ]);\n for (const { id, file, reason } of added) {\n if (reason) continue;\n chain.current = chain.current.then(() => send(id, file, alt.trim()));\n }\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [client, productId, labels],\n );\n\n return { entries, upload, dismiss: drop };\n}\n","import type { AdminProduct } from '@develemit/commerce-contracts';\nimport { fill } from '../../lib/image-rules';\nimport type { ImageLabels } from '../../lib/image-labels';\nimport { useAdmin } from '../../lib/provider';\n\nexport type AdminProductImage = AdminProduct['images'][number];\nexport type MoveDirection = 'earlier' | 'later';\n\nexport interface ImageTileProps {\n image: AdminProductImage;\n index: number;\n total: number;\n busy: boolean;\n labels: ImageLabels;\n onMove: (direction: MoveDirection) => void;\n onRemove: () => void;\n}\n\nexport function ImageTile({\n image,\n index,\n total,\n busy,\n labels,\n onMove,\n onRemove,\n}: ImageTileProps) {\n const { renderImage } = useAdmin();\n const name = image.alt || fill(labels.photoName, { n: String(index + 1) });\n const move = (direction: MoveDirection, text: string, disabled: boolean) => (\n <button\n type=\"button\"\n className=\"sfa-btn\"\n data-image-id={image.id}\n data-move={direction}\n aria-label={`${text}: ${name}`}\n disabled={disabled}\n onClick={() => onMove(direction)}\n >\n {text}\n </button>\n );\n return (\n <li className=\"sfa-image-tile\" aria-busy={busy} data-image-id={image.id}>\n {renderImage({\n src: image.url,\n alt: image.alt,\n sizes: '160px',\n className: 'sfa-image-tile__img',\n })}\n {index === 0 ? (\n <span className=\"sfa-image-tile__cover\">{labels.cover}</span>\n ) : null}\n {busy ? (\n <span className=\"sfa-spinner\" role=\"status\">\n {labels.working}\n </span>\n ) : null}\n <div className=\"sfa-image-tile__actions\">\n {move('earlier', labels.moveEarlier, index === 0)}\n {move('later', labels.moveLater, index === total - 1)}\n <button\n type=\"button\"\n className=\"sfa-btn sfa-btn--danger\"\n aria-label={`${labels.remove}: ${name}`}\n onClick={onRemove}\n >\n {labels.remove}\n </button>\n </div>\n </li>\n );\n}\n","import type { ChangeEvent } from 'react';\nimport type { ImageLabels } from '../../lib/image-labels';\n\ninterface UploadPickerProps {\n labels: ImageLabels;\n onFiles: (files: File[]) => void;\n}\n\nexport function UploadPicker({ labels, onFiles }: UploadPickerProps) {\n const pick = (event: ChangeEvent<HTMLInputElement>) => {\n onFiles(Array.from(event.target.files ?? []));\n event.target.value = '';\n };\n return (\n <div className=\"sfa-image-picker\">\n <label className=\"sfa-btn sfa-image-picker__btn\">\n {labels.add}\n <input\n type=\"file\"\n accept=\"image/*\"\n multiple\n className=\"sfa-sr-only\"\n onChange={pick}\n />\n </label>\n <label className=\"sfa-btn sfa-image-picker__btn\">\n {labels.takePhoto}\n <input\n type=\"file\"\n accept=\"image/*\"\n capture=\"environment\"\n className=\"sfa-sr-only\"\n onChange={pick}\n />\n </label>\n </div>\n );\n}\n","import { useEffect, useRef, useState, type DragEvent } from 'react';\nimport { ConfirmDialog } from '../../components/confirm-dialog/confirm-dialog';\nimport { ErrorMessage } from '../../components/error-message/error-message';\nimport { Notice } from '../../components/notice/notice';\nimport { useAdmin, useAdminClient } from '../../lib/provider';\nimport { useImageUpload } from '../../lib/use-image-upload';\nimport {\n ImageTile,\n type AdminProductImage,\n type MoveDirection,\n} from './image-tile';\nimport { UploadPicker } from './upload-picker';\n\nexport interface AdminProductImagesProps {\n productId: string;\n images: AdminProductImage[];\n}\n\nconst byPosition = (images: AdminProductImage[]) =>\n [...images].sort((a, b) => a.position - b.position);\n\nexport function AdminProductImages({\n productId,\n images: initial,\n}: AdminProductImagesProps) {\n const client = useAdminClient();\n const { labels } = useAdmin();\n const copy = labels.products.images;\n const [images, setImages] = useState(() => byPosition(initial));\n const [busyId, setBusyId] = useState<string | null>(null);\n const [reordering, setReordering] = useState(false);\n const [alt, setAlt] = useState('');\n const [failure, setFailure] = useState<unknown>(undefined);\n const [reorderFailed, setReorderFailed] = useState(false);\n const [removing, setRemoving] = useState<AdminProductImage | null>(null);\n const focusTarget = useRef<{ id: string; direction: MoveDirection } | null>(\n null,\n );\n const listRef = useRef<HTMLUListElement>(null);\n\n const { entries, upload, dismiss } = useImageUpload({\n productId,\n onUploaded: (product) => setImages(byPosition(product.images)),\n });\n\n useEffect(() => {\n const target = focusTarget.current;\n if (!target) return;\n focusTarget.current = null;\n const find = (direction: MoveDirection) =>\n listRef.current?.querySelector<HTMLButtonElement>(\n `[data-image-id=\"${target.id}\"][data-move=\"${direction}\"]:not(:disabled)`,\n );\n const other = target.direction === 'earlier' ? 'later' : 'earlier';\n (find(target.direction) ?? find(other))?.focus();\n }, [images]);\n\n const move = async (index: number, direction: MoveDirection) => {\n const to = direction === 'earlier' ? index - 1 : index + 1;\n if (reordering || to < 0 || to >= images.length) return;\n const previous = images;\n const next = [...images];\n [next[index], next[to]] = [next[to], next[index]];\n focusTarget.current = { id: images[index].id, direction };\n setImages(next);\n setReordering(true);\n setBusyId(images[index].id);\n setFailure(undefined);\n setReorderFailed(false);\n try {\n const product = await client.reorderProductImages(\n productId,\n next.map((image) => image.id),\n );\n setImages(byPosition(product.images));\n } catch (error) {\n focusTarget.current = { id: images[index].id, direction };\n setImages(previous);\n setFailure(error);\n setReorderFailed(true);\n } finally {\n setReordering(false);\n setBusyId(null);\n }\n };\n\n const confirmRemove = async () => {\n if (!removing) return;\n const target = removing;\n setRemoving(null);\n setBusyId(target.id);\n setFailure(undefined);\n setReorderFailed(false);\n try {\n const product = await client.deleteProductImage(productId, target.id);\n setImages(byPosition(product.images));\n } catch (error) {\n setFailure(error);\n } finally {\n setBusyId(null);\n }\n };\n\n const onDrop = (event: DragEvent) => {\n event.preventDefault();\n upload(Array.from(event.dataTransfer.files), alt);\n };\n\n return (\n <div\n className=\"sfa-images\"\n onDragOver={(event) => event.preventDefault()}\n onDrop={onDrop}\n >\n <h2>{copy.title}</h2>\n {reorderFailed ? (\n <Notice variant=\"error\" onDismiss={() => setReorderFailed(false)}>\n {copy.reorderFailed}\n </Notice>\n ) : (\n <ErrorMessage error={failure} />\n )}\n <div className=\"sfa-field\">\n <label className=\"sfa-field__label\" htmlFor={`${productId}-image-alt`}>\n {copy.altLabel}\n </label>\n <input\n id={`${productId}-image-alt`}\n value={alt}\n onChange={(event) => setAlt(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === 'Enter') event.preventDefault();\n }}\n />\n <p className=\"sfa-field__help\">{copy.altHelp}</p>\n {alt.trim() === '' ? (\n <p className=\"sfa-field__error\">{copy.altWarning}</p>\n ) : null}\n </div>\n <UploadPicker labels={copy} onFiles={(files) => upload(files, alt)} />\n <p className=\"sfa-field__help\">{copy.dropHint}</p>\n {images.length === 0 && entries.length === 0 ? <p>{copy.empty}</p> : null}\n <ul ref={listRef} className=\"sfa-image-grid\">\n {images.map((image, index) => (\n <ImageTile\n key={image.id}\n image={image}\n index={index}\n total={images.length}\n busy={busyId === image.id}\n labels={copy}\n onMove={(direction) => move(index, direction)}\n onRemove={() => setRemoving(image)}\n />\n ))}\n {entries.map((entry) => (\n <li\n key={entry.id}\n className=\"sfa-image-tile\"\n aria-busy={entry.status !== 'error'}\n >\n <span>{entry.name}</span>\n {entry.status === 'error' ? (\n <>\n {entry.reason ? (\n <Notice variant=\"error\">{entry.reason}</Notice>\n ) : (\n <ErrorMessage error={entry.error} />\n )}\n <button\n type=\"button\"\n className=\"sfa-btn\"\n onClick={() => dismiss(entry.id)}\n >\n {copy.dismiss}\n </button>\n </>\n ) : (\n <span className=\"sfa-spinner\" role=\"status\">\n {entry.status === 'uploading' ? copy.uploading : copy.working}\n </span>\n )}\n </li>\n ))}\n </ul>\n <ConfirmDialog\n open={removing !== null}\n title={copy.removeTitle}\n destructive\n confirmLabel={copy.remove}\n onConfirm={confirmRemove}\n onCancel={() => setRemoving(null)}\n >\n <p>{copy.removeBody}</p>\n </ConfirmDialog>\n </div>\n );\n}\n","import type { ReactNode } from 'react';\nimport type { ProductStatus } from '@develemit/commerce-contracts';\nimport type {\n FieldErrors,\n FieldName,\n ProductForm,\n} from '../../lib/product-form';\nimport type { ProductLabels } from '../../lib/product-labels';\n\ninterface ControlProps {\n id: string;\n name: FieldName;\n 'aria-invalid': boolean;\n 'aria-describedby'?: string;\n}\n\ninterface FieldShellProps {\n name: FieldName;\n label: string;\n error?: string;\n help?: string;\n children: (props: ControlProps) => ReactNode;\n}\n\nfunction FieldShell({ name, label, error, help, children }: FieldShellProps) {\n const id = `sfa-field-${name}`;\n const described = [help ? `${id}-help` : '', error ? `${id}-error` : '']\n .filter(Boolean)\n .join(' ');\n return (\n <div className=\"sfa-field\">\n <label htmlFor={id} className=\"sfa-field__label\">\n {label}\n </label>\n {children({\n id,\n name,\n 'aria-invalid': Boolean(error),\n 'aria-describedby': described || undefined,\n })}\n {help ? (\n <p id={`${id}-help`} className=\"sfa-field__help\">\n {help}\n </p>\n ) : null}\n {error ? (\n <p id={`${id}-error`} className=\"sfa-field__error\">\n {error}\n </p>\n ) : null}\n </div>\n );\n}\n\nexport interface FieldGroupProps {\n form: ProductForm;\n errors: FieldErrors;\n labels: ProductLabels;\n statusLabels: Record<string, string>;\n categories?: string[];\n onChange: <K extends keyof ProductForm>(\n field: K,\n value: ProductForm[K],\n ) => void;\n}\n\nconst CATEGORY_LIST_ID = 'sfa-field-category-options';\n\nexport function DetailsFields({\n form,\n errors,\n labels,\n categories,\n onChange,\n}: FieldGroupProps) {\n const suggestCategories = Boolean(categories?.length);\n const text = (name: 'name' | 'category' | 'materials' | 'dimensions') => (\n <FieldShell name={name} label={labels.fields[name]} error={errors[name]}>\n {(props) => (\n <input\n {...props}\n type=\"text\"\n list={\n name === 'category' && suggestCategories\n ? CATEGORY_LIST_ID\n : undefined\n }\n value={form[name]}\n onChange={(e) => onChange(name, e.target.value)}\n />\n )}\n </FieldShell>\n );\n return (\n <>\n {text('name')}\n {text('category')}\n {suggestCategories ? (\n <datalist id={CATEGORY_LIST_ID}>\n {categories?.map((category) => (\n <option key={category} value={category} />\n ))}\n </datalist>\n ) : null}\n <FieldShell\n name=\"description\"\n label={labels.fields.description}\n error={errors.description}\n >\n {(props) => (\n <textarea\n {...props}\n rows={5}\n value={form.description}\n onChange={(e) => onChange('description', e.target.value)}\n />\n )}\n </FieldShell>\n {text('materials')}\n {text('dimensions')}\n </>\n );\n}\n\nconst STATUSES: ProductStatus[] = ['draft', 'active', 'archived'];\n\nexport function SalesFields({\n form,\n errors,\n labels,\n statusLabels,\n onChange,\n}: FieldGroupProps) {\n return (\n <>\n <FieldShell\n name=\"price\"\n label={labels.fields.price}\n error={errors.price}\n help={labels.priceHelp}\n >\n {(props) => (\n <input\n {...props}\n type=\"text\"\n inputMode=\"decimal\"\n value={form.price}\n onChange={(e) => onChange('price', e.target.value)}\n />\n )}\n </FieldShell>\n <FieldShell\n name=\"quantity\"\n label={labels.fields.quantity}\n error={errors.quantity}\n >\n {(props) => (\n <input\n {...props}\n type=\"text\"\n inputMode=\"numeric\"\n value={form.quantity}\n onChange={(e) => onChange('quantity', e.target.value)}\n />\n )}\n </FieldShell>\n <FieldShell\n name=\"status\"\n label={labels.fields.status}\n error={errors.status}\n help={labels.statusHelp}\n >\n {(props) => (\n <select\n {...props}\n value={form.status}\n onChange={(e) =>\n onChange('status', e.target.value as ProductStatus)\n }\n >\n {STATUSES.map((status) => (\n <option key={status} value={status}>\n {statusLabels[status] ?? status}\n </option>\n ))}\n </select>\n )}\n </FieldShell>\n <div className=\"sfa-field\">\n <label className=\"sfa-check\" htmlFor=\"sfa-field-featured\">\n <input\n id=\"sfa-field-featured\"\n name=\"featured\"\n type=\"checkbox\"\n checked={form.featured}\n onChange={(e) => onChange('featured', e.target.checked)}\n />\n <span>{labels.fields.featured}</span>\n </label>\n </div>\n </>\n );\n}\n","import { useState, type FormEvent, type ReactNode } from 'react';\nimport type { AdminProduct } from '@develemit/commerce-contracts';\nimport { AdminInvalidInputError } from '../../client';\nimport { ErrorMessage } from '../../components/error-message/error-message';\nimport { Notice } from '../../components/notice/notice';\nimport {\n buildPatch,\n emptyForm,\n firstInvalidField,\n formFromProduct,\n mapServerIssues,\n validateForm,\n type FieldErrors,\n type ProductForm,\n} from '../../lib/product-form';\nimport { useAdmin, useAdminClient } from '../../lib/provider';\nimport { useAdminMutation } from '../../lib/use-admin-mutation';\nimport { useAdminQuery } from '../../lib/use-admin-query';\nimport { AdminProductImages } from './admin-product-images';\nimport { DetailsFields, SalesFields } from './product-fields';\n\nexport interface AdminProductEditorProps {\n productId?: string;\n onSaved?: (product: AdminProduct) => void;\n imagesSlot?: ReactNode;\n categories?: string[];\n}\n\nexport function AdminProductEditor({\n productId,\n onSaved,\n imagesSlot,\n categories,\n}: AdminProductEditorProps) {\n if (!productId) {\n return (\n <ProductFormView\n product={undefined}\n onSaved={onSaved}\n imagesSlot={null}\n categories={categories}\n />\n );\n }\n return (\n <ExistingProductEditor\n productId={productId}\n onSaved={onSaved}\n imagesSlot={imagesSlot}\n categories={categories}\n />\n );\n}\n\nfunction ExistingProductEditor({\n productId,\n onSaved,\n imagesSlot,\n categories,\n}: AdminProductEditorProps & { productId: string }) {\n const client = useAdminClient();\n const { labels } = useAdmin();\n const query = useAdminQuery(['admin-product', productId], () =>\n client.getProduct(productId),\n );\n if (query.error) return <ErrorMessage error={query.error} />;\n if (!query.data) return <p>{labels.loading}</p>;\n return (\n <ProductFormView\n key={query.data.id}\n product={query.data}\n onSaved={onSaved}\n imagesSlot={imagesSlot}\n categories={categories}\n />\n );\n}\n\ninterface ProductFormViewProps {\n product: AdminProduct | undefined;\n onSaved?: (product: AdminProduct) => void;\n imagesSlot: ReactNode;\n categories?: string[];\n}\n\nfunction ProductFormView({\n product,\n onSaved,\n imagesSlot,\n categories,\n}: ProductFormViewProps) {\n const client = useAdminClient();\n const { labels } = useAdmin();\n const copy = labels.products;\n const [base, setBase] = useState(product);\n const [form, setForm] = useState<ProductForm>(\n product ? formFromProduct(product) : emptyForm,\n );\n const [fieldErrors, setFieldErrors] = useState<FieldErrors>({});\n const [saved, setSaved] = useState(false);\n\n const showErrors = (formEl: HTMLFormElement, found: FieldErrors) => {\n setFieldErrors(found);\n const name = firstInvalidField(found);\n if (name) (formEl.elements.namedItem(name) as HTMLElement | null)?.focus();\n };\n\n const save = useAdminMutation(\n async (formEl: HTMLFormElement): Promise<AdminProduct | undefined> => {\n const result = validateForm(form, copy, base?.currency);\n if (!result.ok) {\n showErrors(formEl, result.errors);\n return undefined;\n }\n try {\n if (!base) return await client.createProduct(result.input);\n const patch = buildPatch(base, result.input);\n return Object.keys(patch).length === 0\n ? base\n : await client.updateProduct(base.id, patch);\n } catch (error) {\n if (!(error instanceof AdminInvalidInputError)) throw error;\n showErrors(formEl, mapServerIssues(error.issues));\n return undefined;\n }\n },\n );\n\n const onChange: Parameters<typeof DetailsFields>[0]['onChange'] = (\n field,\n value,\n ) => {\n setForm((prev) => ({ ...prev, [field]: value }));\n setFieldErrors((prev) => ({\n ...prev,\n [field]: undefined,\n }));\n };\n\n const onSubmit = async (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n setSaved(false);\n setFieldErrors({});\n save.reset();\n const result = await save.run(event.currentTarget);\n if (!result) return;\n setBase(result);\n setForm(formFromProduct(result));\n setSaved(true);\n onSaved?.(result);\n };\n\n const images = product\n ? (imagesSlot ?? (\n <AdminProductImages productId={product.id} images={product.images} />\n ))\n : null;\n const group = {\n form,\n errors: fieldErrors,\n labels: copy,\n statusLabels: labels.statuses,\n categories,\n onChange,\n };\n return (\n <form noValidate className=\"sfa-form\" onSubmit={onSubmit}>\n <h1>{product ? copy.editTitle : copy.createTitle}</h1>\n <ErrorMessage error={save.error} />\n <DetailsFields {...group} />\n <SalesFields {...group} />\n {images ? (\n <section data-slot=\"images\" className=\"sfa-form__images\">\n {images}\n </section>\n ) : null}\n <button\n type=\"submit\"\n className=\"sfa-btn sfa-btn--primary\"\n disabled={save.pending}\n >\n {labels.save}\n </button>\n {saved ? (\n <Notice variant=\"success\" toast onDismiss={() => setSaved(false)}>\n {copy.saved}\n </Notice>\n ) : null}\n </form>\n );\n}\n","import { useState } from 'react';\nimport type {\n AdminOrderListItem,\n AdminOrderPage,\n} from '@develemit/commerce-contracts';\nimport type { AdminOrderQuery } from '../client/admin-client';\nimport { useAdminClient } from './provider';\nimport { useAdminMutation } from './use-admin-mutation';\nimport { useAdminQuery } from './use-admin-query';\n\ninterface Appended {\n base: AdminOrderPage;\n items: AdminOrderListItem[];\n nextCursor: string | null;\n}\n\nexport function useOrderPages(query: Omit<AdminOrderQuery, 'cursor'>) {\n const client = useAdminClient();\n const first = useAdminQuery(['admin-orders', query], () =>\n client.listOrders(query),\n );\n const [appended, setAppended] = useState<Appended | null>(null);\n const more = useAdminMutation(\n async (cursor: string, base: AdminOrderPage) => {\n const page = await client.listOrders({ ...query, cursor });\n setAppended((prev) => ({\n base,\n items: [...(prev?.base === base ? prev.items : []), ...page.items],\n nextCursor: page.nextCursor,\n }));\n },\n );\n\n const base = first.data;\n const extra = appended && appended.base === base ? appended : null;\n const nextCursor = extra ? extra.nextCursor : (base?.nextCursor ?? null);\n return {\n items: [...(base?.items ?? []), ...(extra?.items ?? [])],\n loading: first.loading,\n error: first.error ?? more.error,\n hasMore: !first.loading && nextCursor !== null,\n loadingMore: more.pending,\n loadMore: () => {\n if (base && nextCursor) void more.run(nextCursor, base);\n },\n };\n}\n","import { useState } from 'react';\nimport type { AdminOrderListItem } from '@develemit/commerce-contracts';\nimport type { AdminOrderQuery } from '../../client/admin-client';\nimport {\n AdminTable,\n type AdminColumn,\n} from '../../components/admin-table/admin-table';\nimport { ErrorMessage } from '../../components/error-message/error-message';\nimport { Money } from '../../components/money/money';\nimport { StatusBadge } from '../../components/status-badge/status-badge';\nimport type { OrderTab } from '../../lib/order-labels';\nimport { useAdmin } from '../../lib/provider';\nimport { useDebounced } from '../../lib/use-debounced';\nimport { useOrderPages } from '../../lib/use-order-pages';\n\nconst TABS: OrderTab[] = [\n 'paid',\n 'shipped',\n 'needs_attention',\n 'pending_refund',\n 'all',\n];\n\nfunction tabQuery(tab: OrderTab): AdminOrderQuery {\n if (tab === 'pending_refund') return { hasPendingRefund: true };\n if (tab === 'all') return {};\n return { status: tab };\n}\n\nexport function AdminOrderList() {\n const { labels, locale, hrefs, renderLink } = useAdmin();\n const copy = labels.orders;\n const [tab, setTab] = useState<OrderTab>('paid');\n const [search, setSearch] = useState('');\n const q = useDebounced(search.trim(), 300);\n const pages = useOrderPages({ ...tabQuery(tab), ...(q ? { q } : {}) });\n const date = new Intl.DateTimeFormat(locale);\n\n const columns: AdminColumn<AdminOrderListItem>[] = [\n {\n key: 'order',\n header: copy.columns.order,\n render: (o) =>\n renderLink({\n href: hrefs.order(o.id),\n children: o.id,\n className: 'sfa-link--tap',\n }),\n },\n {\n key: 'status',\n header: copy.columns.status,\n render: (o) => <StatusBadge status={o.status} />,\n },\n {\n key: 'email',\n header: copy.columns.email,\n render: (o) => o.email ?? copy.noEmail,\n },\n { key: 'items', header: copy.columns.items, render: (o) => o.itemCount },\n {\n key: 'total',\n header: copy.columns.total,\n render: (o) => <Money cents={o.totalCents} currency={o.currency} />,\n },\n {\n key: 'date',\n header: copy.columns.date,\n render: (o) => date.format(new Date(o.createdAt)),\n },\n ];\n\n return (\n <section className=\"sfa-orders\">\n <h1>{copy.title}</h1>\n <div className=\"sfa-orders__toolbar\">\n <div\n role=\"group\"\n aria-label={copy.columns.status}\n className=\"sfa-filter-group\"\n >\n {TABS.map((value) => (\n <button\n key={value}\n type=\"button\"\n className=\"sfa-btn sfa-filter\"\n aria-pressed={tab === value}\n onClick={() => setTab(value)}\n >\n {copy.tabs[value]}\n </button>\n ))}\n </div>\n <input\n type=\"search\"\n aria-label={copy.searchLabel}\n placeholder={copy.searchPlaceholder}\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n />\n </div>\n <ErrorMessage error={pages.error} />\n {pages.loading ? (\n <p>{labels.loading}</p>\n ) : pages.items.length === 0 ? (\n <p className=\"sfa-empty\">{q ? copy.noMatches : copy.empty[tab]}</p>\n ) : (\n <AdminTable columns={columns} rows={pages.items} rowKey={(o) => o.id} />\n )}\n {pages.hasMore ? (\n <button\n type=\"button\"\n className=\"sfa-btn sfa-orders__more\"\n disabled={pages.loadingMore}\n onClick={pages.loadMore}\n >\n {copy.loadMore}\n </button>\n ) : null}\n </section>\n );\n}\n","import type { AdminOrderDetail } from '@develemit/commerce-contracts';\n\nexport function pendingRefundCents(order: AdminOrderDetail): number {\n return order.refunds\n .filter((r) => r.status === 'pending')\n .reduce((sum, r) => sum + r.amountCents, 0);\n}\n\nexport function remainingRefundCents(order: AdminOrderDetail): number {\n return order.totalCents - order.refundedCents - pendingRefundCents(order);\n}\n\nexport function hasPendingRefund(order: AdminOrderDetail): boolean {\n return order.refunds.some((r) => r.status === 'pending');\n}\n\nexport function canRestock(\n order: AdminOrderDetail,\n amountCents: number | null,\n): boolean {\n return (\n order.status !== 'needs_attention' &&\n amountCents !== null &&\n amountCents === remainingRefundCents(order)\n );\n}\n\nexport function canShip(order: AdminOrderDetail): boolean {\n return order.status === 'paid' || order.status === 'shipped';\n}\n\nexport function canRefund(order: AdminOrderDetail): boolean {\n return (\n (canShip(order) || order.status === 'needs_attention') &&\n remainingRefundCents(order) > 0\n );\n}\n","import { useRef, useState } from 'react';\nimport type { AdminOrderDetail } from '@develemit/commerce-contracts';\nimport { RefundGatewayError, RefundOutcomeUnknownError } from '../../client';\nimport { ConfirmDialog } from '../../components/confirm-dialog/confirm-dialog';\nimport { ErrorMessage } from '../../components/error-message/error-message';\nimport { Notice } from '../../components/notice/notice';\nimport { formatMoneyInput, parseMoneyInput } from '../../lib/money-input';\nimport { useAdmin, useAdminClient } from '../../lib/provider';\nimport {\n canRestock,\n hasPendingRefund,\n remainingRefundCents,\n} from '../../lib/refund-rules';\nimport { useAdminMutation } from '../../lib/use-admin-mutation';\n\ninterface RefundDialogProps {\n order: AdminOrderDetail;\n onClose: () => void;\n onDone: (message: string) => void;\n}\n\nexport function RefundDialog({ order, onClose, onDone }: RefundDialogProps) {\n const client = useAdminClient();\n const copy = useAdmin().labels.orders.actions;\n const keyRef = useRef(crypto.randomUUID());\n const remaining = remainingRefundCents(order);\n const [amount, setAmount] = useState(formatMoneyInput(remaining));\n const [reason, setReason] = useState('');\n const [restock, setRestock] = useState(false);\n const [invalid, setInvalid] = useState(false);\n const refund = useAdminMutation(client.refundOrder);\n\n const cents = parseMoneyInput(amount);\n const amountValid = cents !== null && cents > 0 && cents <= remaining;\n const restockOffered = canRestock(order, cents);\n const retryable =\n refund.error instanceof RefundGatewayError ||\n refund.error instanceof RefundOutcomeUnknownError;\n\n const submit = async () => {\n if (!amountValid) {\n setInvalid(true);\n return;\n }\n setInvalid(false);\n const result = await refund.run(\n order.id,\n {\n amountCents: cents,\n reason: reason.trim() || undefined,\n restock: restock && restockOffered,\n },\n { idempotencyKey: keyRef.current },\n );\n if (result) onDone(copy.refundDone);\n };\n\n return (\n <ConfirmDialog\n open\n title={copy.refundTitle}\n confirmLabel={retryable ? copy.refundRetry : copy.refundSubmit}\n destructive\n pending={refund.pending}\n onConfirm={submit}\n onCancel={onClose}\n >\n {hasPendingRefund(order) ? (\n <Notice variant=\"warning\">{copy.refundPending}</Notice>\n ) : null}\n <div className=\"sfa-field\">\n <label htmlFor=\"sfa-refund-amount\" className=\"sfa-field__label\">\n {copy.refundAmount}\n </label>\n <input\n id=\"sfa-refund-amount\"\n inputMode=\"decimal\"\n value={amount}\n disabled={retryable}\n aria-invalid={invalid && !amountValid}\n onChange={(e) => setAmount(e.target.value)}\n />\n {invalid && !amountValid ? (\n <p className=\"sfa-field__error\">{copy.refundAmountInvalid}</p>\n ) : null}\n </div>\n <div className=\"sfa-field\">\n <label htmlFor=\"sfa-refund-reason\" className=\"sfa-field__label\">\n {copy.refundReason}\n </label>\n <textarea\n id=\"sfa-refund-reason\"\n maxLength={500}\n value={reason}\n disabled={retryable}\n onChange={(e) => setReason(e.target.value)}\n />\n </div>\n {restockOffered ? (\n <div className=\"sfa-field\">\n <label>\n <input\n type=\"checkbox\"\n checked={restock}\n disabled={retryable}\n onChange={(e) => setRestock(e.target.checked)}\n />{' '}\n {copy.restock}\n </label>\n <p className=\"sfa-field__help\">{copy.restockWarning}</p>\n </div>\n ) : null}\n {refund.error instanceof RefundOutcomeUnknownError ? (\n <Notice variant=\"warning\">{copy.refundUnknown}</Notice>\n ) : refund.error instanceof RefundGatewayError ? (\n <Notice variant=\"warning\">{copy.refundGateway}</Notice>\n ) : (\n <ErrorMessage error={refund.error} />\n )}\n </ConfirmDialog>\n );\n}\n","import type { AdminOrderDetail } from '@develemit/commerce-contracts';\nimport { InsufficientStockError } from '../../client';\nimport { ErrorMessage } from '../../components/error-message/error-message';\nimport { Notice } from '../../components/notice/notice';\nimport { useAdmin, useAdminClient } from '../../lib/provider';\nimport { useAdminMutation } from '../../lib/use-admin-mutation';\n\ninterface ResolveButtonProps {\n order: AdminOrderDetail;\n onDone: (message: string) => void;\n}\n\nexport function ResolveButton({ order, onDone }: ResolveButtonProps) {\n const client = useAdminClient();\n const { labels, hrefs, renderLink } = useAdmin();\n const copy = labels.orders.actions;\n const resolve = useAdminMutation(client.resolveOrder);\n\n const submit = async () => {\n const result = await resolve.run(order.id);\n if (result) onDone(copy.resolved);\n };\n\n const stockError =\n resolve.error instanceof InsufficientStockError ? resolve.error : null;\n const names = new Map(order.items.map((i) => [i.productId, i.name]));\n\n return (\n <div className=\"sfa-order__action\">\n <p>{copy.resolveHelp}</p>\n {stockError ? (\n <Notice variant=\"error\">\n {labels.errors.insufficientStock}\n <ul>\n {stockError.productIds.map((id) => (\n <li key={id}>\n {renderLink({\n href: hrefs.product(id),\n children: `${copy.restockThenResolve}: ${names.get(id) ?? id}`,\n className: 'sfa-link--tap',\n })}\n </li>\n ))}\n </ul>\n </Notice>\n ) : (\n <ErrorMessage error={resolve.error} />\n )}\n <button\n type=\"button\"\n className=\"sfa-btn sfa-btn--primary\"\n disabled={resolve.pending}\n onClick={submit}\n >\n {copy.resolve}\n </button>\n </div>\n );\n}\n","import { useState, type FormEvent } from 'react';\nimport type { AdminOrderDetail } from '@develemit/commerce-contracts';\nimport { ErrorMessage } from '../../components/error-message/error-message';\nimport { useAdmin, useAdminClient } from '../../lib/provider';\nimport { useAdminMutation } from '../../lib/use-admin-mutation';\n\nfunction isHttpUrl(value: string): boolean {\n try {\n const { protocol } = new URL(value);\n return protocol === 'http:' || protocol === 'https:';\n } catch {\n return false;\n }\n}\n\ninterface ShipFormProps {\n order: AdminOrderDetail;\n onDone: (message: string) => void;\n}\n\nexport function ShipForm({ order, onDone }: ShipFormProps) {\n const client = useAdminClient();\n const copy = useAdmin().labels.orders.actions;\n const current = order.fulfillment;\n const [carrier, setCarrier] = useState(current?.carrier ?? '');\n const [trackingNumber, setTrackingNumber] = useState(\n current?.trackingNumber ?? '',\n );\n const [trackingUrl, setTrackingUrl] = useState(current?.trackingUrl ?? '');\n const [urlError, setUrlError] = useState(false);\n const ship = useAdminMutation(client.shipOrder);\n const reship = order.status === 'shipped';\n\n const submit = async (event: FormEvent) => {\n event.preventDefault();\n const url = trackingUrl.trim();\n if (url && !isHttpUrl(url)) {\n setUrlError(true);\n return;\n }\n setUrlError(false);\n const result = await ship.run(order.id, {\n carrier: carrier.trim() || undefined,\n trackingNumber: trackingNumber.trim() || undefined,\n trackingUrl: url || undefined,\n });\n if (result) onDone(copy.shipped);\n };\n\n return (\n <form className=\"sfa-order__action\" onSubmit={submit}>\n <h3>{copy.shipHeading}</h3>\n <div className=\"sfa-field\">\n <label htmlFor=\"sfa-ship-carrier\" className=\"sfa-field__label\">\n {copy.carrier}\n </label>\n <input\n id=\"sfa-ship-carrier\"\n value={carrier}\n onChange={(e) => setCarrier(e.target.value)}\n />\n </div>\n <div className=\"sfa-field\">\n <label htmlFor=\"sfa-ship-number\" className=\"sfa-field__label\">\n {copy.trackingNumber}\n </label>\n <input\n id=\"sfa-ship-number\"\n value={trackingNumber}\n onChange={(e) => setTrackingNumber(e.target.value)}\n />\n </div>\n <div className=\"sfa-field\">\n <label htmlFor=\"sfa-ship-url\" className=\"sfa-field__label\">\n {copy.trackingUrl}\n </label>\n <input\n id=\"sfa-ship-url\"\n value={trackingUrl}\n aria-invalid={urlError}\n aria-describedby={urlError ? 'sfa-ship-url-error' : undefined}\n onChange={(e) => setTrackingUrl(e.target.value)}\n />\n {urlError ? (\n <p id=\"sfa-ship-url-error\" className=\"sfa-field__error\">\n {copy.trackingUrlInvalid}\n </p>\n ) : null}\n </div>\n <ErrorMessage error={ship.error} />\n <button\n type=\"submit\"\n className=\"sfa-btn sfa-btn--primary\"\n disabled={ship.pending}\n >\n {reship ? copy.reship : copy.ship}\n </button>\n </form>\n );\n}\n","import { useState } from 'react';\nimport type { AdminOrderDetail } from '@develemit/commerce-contracts';\nimport { Notice } from '../../components/notice/notice';\nimport { useAdmin } from '../../lib/provider';\nimport { canRefund, canShip } from '../../lib/refund-rules';\nimport { RefundDialog } from './refund-dialog';\nimport { ResolveButton } from './resolve-button';\nimport { ShipForm } from './ship-form';\n\ninterface OrderActionsProps {\n order: AdminOrderDetail;\n reload: () => void;\n}\n\nexport function OrderActions({ order, reload }: OrderActionsProps) {\n const copy = useAdmin().labels.orders.actions;\n const [refunding, setRefunding] = useState(false);\n const [message, setMessage] = useState<string | null>(null);\n\n const done = (text: string) => {\n setRefunding(false);\n setMessage(text);\n reload();\n };\n const closeRefund = () => {\n setRefunding(false);\n reload();\n };\n\n return (\n <div className=\"sfa-order__actions\">\n {message ? (\n <Notice variant=\"success\" onDismiss={() => setMessage(null)}>\n {message}\n </Notice>\n ) : null}\n {canShip(order) ? <ShipForm order={order} onDone={done} /> : null}\n {order.status === 'needs_attention' ? (\n <ResolveButton order={order} onDone={done} />\n ) : null}\n {canRefund(order) ? (\n <button\n type=\"button\"\n className=\"sfa-btn sfa-btn--danger\"\n onClick={() => setRefunding(true)}\n >\n {copy.refund}\n </button>\n ) : null}\n {refunding ? (\n <RefundDialog order={order} onClose={closeRefund} onDone={done} />\n ) : null}\n </div>\n );\n}\n","import type { AdminOrderDetail } from '@develemit/commerce-contracts';\nimport { useAdmin } from '../../lib/provider';\n\nexport function OrderFulfillment({ order }: { order: AdminOrderDetail }) {\n const { labels, locale, renderLink } = useAdmin();\n const copy = labels.orders;\n const f = order.fulfillment;\n return (\n <section className=\"sfa-order__section\">\n <h2>{copy.fulfillment}</h2>\n {f ? (\n <dl>\n <dt>{copy.shippedOn}</dt>\n <dd>\n {new Intl.DateTimeFormat(locale).format(new Date(f.shippedAt))}\n </dd>\n {f.carrier ? (\n <>\n <dt>{copy.carrier}</dt>\n <dd>{f.carrier}</dd>\n </>\n ) : null}\n {f.trackingNumber ? (\n <>\n <dt>{copy.tracking}</dt>\n <dd>{f.trackingNumber}</dd>\n </>\n ) : null}\n {f.trackingUrl ? (\n <dd>\n {renderLink({\n href: f.trackingUrl,\n children: copy.trackShipment,\n className: 'sfa-link--tap',\n })}\n </dd>\n ) : null}\n </dl>\n ) : (\n <p>{copy.notShipped}</p>\n )}\n </section>\n );\n}\n","import type { AdminOrderDetail } from '@develemit/commerce-contracts';\nimport {\n AdminTable,\n type AdminColumn,\n} from '../../components/admin-table/admin-table';\nimport { Money } from '../../components/money/money';\nimport { useAdmin } from '../../lib/provider';\n\ntype Item = AdminOrderDetail['items'][number];\n\nexport function OrderItems({ order }: { order: AdminOrderDetail }) {\n const { labels } = useAdmin();\n const copy = labels.orders;\n const { currency } = order;\n const columns: AdminColumn<Item>[] = [\n { key: 'name', header: copy.itemColumns.name, render: (i) => i.name },\n {\n key: 'price',\n header: copy.itemColumns.price,\n render: (i) => <Money cents={i.priceCents} currency={currency} />,\n },\n {\n key: 'quantity',\n header: copy.itemColumns.quantity,\n render: (i) => i.quantity,\n },\n {\n key: 'line',\n header: copy.itemColumns.line,\n render: (i) => (\n <Money cents={i.priceCents * i.quantity} currency={currency} />\n ),\n },\n ];\n return (\n <section className=\"sfa-order__section\">\n <h2>{copy.itemsHeading}</h2>\n <AdminTable\n columns={columns}\n rows={order.items}\n rowKey={(i) => i.productId}\n />\n <dl className=\"sfa-order__totals\">\n <dt>{copy.subtotal}</dt>\n <dd>\n <Money cents={order.subtotalCents} currency={currency} />\n </dd>\n <dt>{order.shippingLabel ?? copy.shipping}</dt>\n <dd>\n <Money cents={order.shippingCents} currency={currency} />\n </dd>\n <dt>{copy.total}</dt>\n <dd>\n <Money cents={order.totalCents} currency={currency} />\n </dd>\n </dl>\n </section>\n );\n}\n","import type { AdminOrderDetail } from '@develemit/commerce-contracts';\nimport {\n AdminTable,\n type AdminColumn,\n} from '../../components/admin-table/admin-table';\nimport { Money } from '../../components/money/money';\nimport { useAdmin } from '../../lib/provider';\n\ntype Refund = AdminOrderDetail['refunds'][number];\n\nexport function OrderRefunds({ order }: { order: AdminOrderDetail }) {\n const { labels, locale } = useAdmin();\n const copy = labels.orders;\n const { currency } = order;\n const date = new Intl.DateTimeFormat(locale);\n const columns: AdminColumn<Refund>[] = [\n {\n key: 'amount',\n header: copy.refundColumns.amount,\n render: (r) => <Money cents={r.amountCents} currency={currency} />,\n },\n {\n key: 'reason',\n header: copy.refundColumns.reason,\n render: (r) => r.reason ?? '—',\n },\n {\n key: 'source',\n header: copy.refundColumns.source,\n render: (r) => copy.refundSources[r.source],\n },\n {\n key: 'status',\n header: copy.refundColumns.status,\n render: (r) => (\n <span\n className={`sfa-badge sfa-badge--refund-${r.status}`}\n data-refund-status={r.status}\n >\n {copy.refundStatuses[r.status]}\n </span>\n ),\n },\n {\n key: 'restocked',\n header: copy.refundColumns.restocked,\n render: (r) => (r.restocked ? copy.yes : copy.no),\n },\n {\n key: 'date',\n header: copy.refundColumns.date,\n render: (r) => date.format(new Date(r.createdAt)),\n },\n ];\n const remaining = order.totalCents - order.refundedCents;\n return (\n <section className=\"sfa-order__section\">\n <h2>{copy.refunds}</h2>\n {order.refunds.length === 0 ? (\n <p>{copy.noRefunds}</p>\n ) : (\n <>\n <AdminTable\n columns={columns}\n rows={order.refunds}\n rowKey={(r) => r.id}\n />\n <dl className=\"sfa-order__totals\">\n <dt>{copy.refunded}</dt>\n <dd>\n <Money cents={order.refundedCents} currency={currency} />\n </dd>\n <dt>{copy.remaining}</dt>\n <dd>\n <Money cents={remaining} currency={currency} />\n </dd>\n </dl>\n </>\n )}\n </section>\n );\n}\n","import type { ReactNode } from 'react';\nimport type { AdminOrderDetail as OrderDetail } from '@develemit/commerce-contracts';\nimport { ErrorMessage } from '../../components/error-message/error-message';\nimport { Money } from '../../components/money/money';\nimport { StatusBadge } from '../../components/status-badge/status-badge';\nimport { useAdmin, useAdminClient } from '../../lib/provider';\nimport { useAdminQuery } from '../../lib/use-admin-query';\nimport { OrderActions } from './order-actions';\nimport { OrderFulfillment } from './order-fulfillment';\nimport { OrderItems } from './order-items';\nimport { OrderRefunds } from './order-refunds';\n\nexport interface AdminOrderDetailProps {\n orderId: string;\n actions?: (ctx: { order: OrderDetail; reload: () => void }) => ReactNode;\n}\n\nfunction addressLines(order: OrderDetail): string[] {\n const a = order.shippingAddress;\n if (!a) return [];\n const region = [a.city, a.state, a.postalCode].filter(Boolean).join(' ');\n return [a.name, a.line1, a.line2, region, a.country].filter(\n (l): l is string => Boolean(l),\n );\n}\n\nexport function AdminOrderDetail({ orderId, actions }: AdminOrderDetailProps) {\n const client = useAdminClient();\n const { labels, locale, hrefs, renderLink } = useAdmin();\n const copy = labels.orders;\n const query = useAdminQuery(['admin-order', orderId], () =>\n client.getOrder(orderId),\n );\n if (query.error) return <ErrorMessage error={query.error} />;\n const order = query.data;\n if (!order) return <p>{labels.loading}</p>;\n const lines = addressLines(order);\n\n return (\n <article className=\"sfa-order\">\n {renderLink({\n href: hrefs.orders,\n children: copy.back,\n className: 'sfa-link--tap',\n })}\n <header className=\"sfa-order__header\">\n <h1>\n {copy.detailTitle} {order.id}\n </h1>\n <StatusBadge status={order.status} />\n <span>\n {copy.placed}{' '}\n {new Intl.DateTimeFormat(locale).format(new Date(order.createdAt))}\n </span>\n <Money cents={order.totalCents} currency={order.currency} />\n </header>\n <section className=\"sfa-order__section\">\n <h2>{copy.buyer}</h2>\n <p>{order.email ?? labels.orders.noEmail}</p>\n </section>\n <OrderItems order={order} />\n <section className=\"sfa-order__section\">\n <h2>{copy.shippingAddress}</h2>\n {lines.length === 0 ? (\n <p>{copy.noAddress}</p>\n ) : (\n <address className=\"sfa-order__address\">\n {lines.map((l) => (\n <div key={l}>{l}</div>\n ))}\n </address>\n )}\n </section>\n <OrderFulfillment order={order} />\n <OrderRefunds order={order} />\n <section className=\"sfa-order__section\">\n {actions ? (\n actions({ order, reload: query.reload })\n ) : (\n <OrderActions order={order} reload={query.reload} />\n )}\n </section>\n </article>\n );\n}\n","import {\n shippingRatesInputSchema,\n type ShippingRate,\n type ShippingRateInput,\n} from '@develemit/commerce-contracts';\nimport { formatMoneyInput, parseMoneyInput } from './money-input';\nimport type { ShippingLabels } from './shipping-labels';\n\nexport interface RateDraft {\n key: string;\n label: string;\n amount: string;\n currency: string;\n minDays: string;\n maxDays: string;\n active: boolean;\n}\n\nexport interface RateErrors {\n label?: string;\n amount?: string;\n minDays?: string;\n maxDays?: string;\n currency?: string;\n row?: string;\n}\n\nexport interface DraftCheck {\n rates: ShippingRateInput[];\n rowErrors: Record<string, RateErrors>;\n noActive: boolean;\n valid: boolean;\n}\n\nlet counter = 0;\nexport const newKey = () => `rate-${++counter}`;\n\nexport function toDrafts(rates: ShippingRate[]): RateDraft[] {\n return [...rates]\n .sort((a, b) => a.sort - b.sort)\n .map((rate) => ({\n key: newKey(),\n label: rate.label,\n amount: formatMoneyInput(rate.amountCents),\n currency: rate.currency,\n minDays: rate.minDays == null ? '' : String(rate.minDays),\n maxDays: rate.maxDays == null ? '' : String(rate.maxDays),\n active: rate.active,\n }));\n}\n\nexport function blankDraft(currency: string, label: string): RateDraft {\n return {\n key: newKey(),\n label,\n amount: '',\n currency,\n minDays: '',\n maxDays: '',\n active: true,\n };\n}\n\nexport const snapshot = (drafts: RateDraft[]) =>\n JSON.stringify(drafts.map(({ key: _key, ...rest }) => rest));\n\nfunction parseDays(raw: string): number | null | undefined {\n const text = raw.trim();\n if (text === '') return null;\n return /^\\d+$/.test(text) ? Number(text) : undefined;\n}\n\nexport function checkDrafts(\n drafts: RateDraft[],\n copy: ShippingLabels,\n): DraftCheck {\n const rowErrors: Record<string, RateErrors> = {};\n const rates: ShippingRateInput[] = [];\n const seen = new Map<string, number>();\n drafts.forEach((draft) => {\n const name = draft.label.trim();\n seen.set(name, (seen.get(name) ?? 0) + 1);\n });\n\n drafts.forEach((draft, index) => {\n const errors: RateErrors = {};\n const label = draft.label.trim();\n const cents = parseMoneyInput(draft.amount);\n const min = parseDays(draft.minDays);\n const max = parseDays(draft.maxDays);\n if (label === '') errors.label = copy.labelRequired;\n else if ((seen.get(label) ?? 0) > 1) errors.label = copy.labelDuplicate;\n if (!/^[A-Z]{3}$/.test(draft.currency))\n errors.currency = copy.currencyInvalid;\n if (cents === null) errors.amount = copy.amountInvalid;\n if (min === undefined) errors.minDays = copy.daysInvalid;\n if (max === undefined) errors.maxDays = copy.daysInvalid;\n if (typeof min === 'number' && typeof max === 'number' && min > max) {\n errors.minDays = copy.daysOrder;\n }\n if (Object.keys(errors).length > 0) rowErrors[draft.key] = errors;\n rates.push({\n label,\n amountCents: cents ?? 0,\n currency: draft.currency,\n minDays: min ?? null,\n maxDays: max ?? null,\n active: draft.active,\n sort: index,\n });\n });\n\n if (Object.keys(rowErrors).length === 0) {\n const parsed = shippingRatesInputSchema.safeParse(rates);\n if (!parsed.success) {\n for (const issue of parsed.error.issues) {\n const key =\n typeof issue.path[0] === 'number'\n ? drafts[issue.path[0]]?.key\n : undefined;\n if (key) rowErrors[key] = { row: copy.rowInvalid };\n }\n }\n }\n\n const noActive = !drafts.some((draft) => draft.active);\n return {\n rates,\n rowErrors,\n noActive,\n valid: Object.keys(rowErrors).length === 0 && !noActive,\n };\n}\n\nconst SERVER_FIELDS: Record<string, keyof RateErrors> = {\n label: 'label',\n amountCents: 'amount',\n currency: 'currency',\n minDays: 'minDays',\n maxDays: 'maxDays',\n};\n\nexport function serverRowErrors(\n issues: unknown[],\n drafts: RateDraft[],\n copy: ShippingLabels,\n): Record<string, RateErrors> {\n const result: Record<string, RateErrors> = {};\n for (const issue of issues) {\n const path = (issue as { path?: unknown[] } | null)?.path ?? [];\n const at = path.findIndex((segment) => typeof segment === 'number');\n const key = at >= 0 ? drafts[path[at] as number]?.key : undefined;\n if (!key) continue;\n const last = path[path.length - 1];\n const field =\n path.length - 1 > at && typeof last === 'string'\n ? SERVER_FIELDS[last]\n : undefined;\n result[key] = { ...result[key], [field ?? 'row']: copy.rowInvalid };\n }\n return result;\n}\n","import { fill } from '../../lib/image-rules';\nimport type { RateDraft, RateErrors } from '../../lib/shipping-rates';\nimport type { ShippingLabels } from '../../lib/shipping-labels';\n\nexport type RateMove = 'earlier' | 'later';\n\nexport interface ShippingRateRowProps {\n draft: RateDraft;\n index: number;\n total: number;\n errors: RateErrors;\n disabled: boolean;\n labels: ShippingLabels;\n onChange: (patch: Partial<RateDraft>) => void;\n onMove: (direction: RateMove) => void;\n onRemove: () => void;\n}\n\nexport function ShippingRateRow({\n draft,\n index,\n total,\n errors,\n disabled,\n labels,\n onChange,\n onMove,\n onRemove,\n}: ShippingRateRowProps) {\n const name =\n draft.label.trim() || fill(labels.rowName, { n: String(index + 1) });\n const field = (\n id: string,\n text: string,\n value: string,\n key: 'label' | 'amount' | 'minDays' | 'maxDays',\n inputMode?: 'decimal' | 'numeric',\n ) => {\n const error = errors[key];\n const fieldId = `${draft.key}-${id}`;\n return (\n <div className=\"sfa-field\">\n <label className=\"sfa-field__label\" htmlFor={fieldId}>\n {text}\n </label>\n <input\n id={fieldId}\n value={value}\n inputMode={inputMode}\n disabled={disabled}\n aria-invalid={Boolean(error)}\n aria-describedby={error ? `${fieldId}-error` : undefined}\n onChange={(event) => onChange({ [key]: event.target.value })}\n />\n {error ? (\n <p id={`${fieldId}-error`} className=\"sfa-field__error\">\n {error}\n </p>\n ) : null}\n </div>\n );\n };\n\n return (\n <li className=\"sfa-rate\" data-rate-key={draft.key}>\n {field('label', labels.label, draft.label, 'label')}\n {field('amount', labels.amount, draft.amount, 'amount', 'decimal')}\n <div className=\"sfa-field\">\n <span className=\"sfa-field__label\">{labels.currency}</span>\n <span\n className=\"sfa-rate__currency\"\n aria-invalid={Boolean(errors.currency)}\n >\n {draft.currency}\n </span>\n {errors.currency ? (\n <p className=\"sfa-field__error\">{errors.currency}</p>\n ) : null}\n </div>\n {field('min', labels.minDays, draft.minDays, 'minDays', 'numeric')}\n {field('max', labels.maxDays, draft.maxDays, 'maxDays', 'numeric')}\n <label className=\"sfa-rate__active\">\n <input\n type=\"checkbox\"\n checked={draft.active}\n disabled={disabled}\n onChange={(event) => onChange({ active: event.target.checked })}\n />\n {labels.active}\n </label>\n {errors.row ? <p className=\"sfa-field__error\">{errors.row}</p> : null}\n <div className=\"sfa-rate__actions\">\n <button\n type=\"button\"\n className=\"sfa-btn\"\n aria-label={`${labels.moveEarlier}: ${name}`}\n disabled={disabled || index === 0}\n onClick={() => onMove('earlier')}\n >\n {labels.moveEarlier}\n </button>\n <button\n type=\"button\"\n className=\"sfa-btn\"\n aria-label={`${labels.moveLater}: ${name}`}\n disabled={disabled || index === total - 1}\n onClick={() => onMove('later')}\n >\n {labels.moveLater}\n </button>\n <button\n type=\"button\"\n className=\"sfa-btn sfa-btn--danger\"\n aria-label={`${labels.remove}: ${name}`}\n disabled={disabled}\n onClick={onRemove}\n >\n {labels.remove}\n </button>\n </div>\n </li>\n );\n}\n","import { useEffect, useRef, useState } from 'react';\nimport { AdminInvalidInputError } from '../../client';\nimport { ConfirmDialog } from '../../components/confirm-dialog/confirm-dialog';\nimport { ErrorMessage } from '../../components/error-message/error-message';\nimport { Notice } from '../../components/notice/notice';\nimport { fill } from '../../lib/image-rules';\nimport { useAdmin, useAdminClient } from '../../lib/provider';\nimport {\n blankDraft,\n checkDrafts,\n serverRowErrors,\n snapshot,\n toDrafts,\n type RateDraft,\n type RateErrors,\n} from '../../lib/shipping-rates';\nimport { useAdminMutation } from '../../lib/use-admin-mutation';\nimport { useAdminQuery } from '../../lib/use-admin-query';\nimport { ShippingRateRow, type RateMove } from './shipping-rate-row';\n\nexport interface AdminShippingRatesProps {\n onDirtyChange?: (dirty: boolean) => void;\n}\n\nexport function AdminShippingRates({ onDirtyChange }: AdminShippingRatesProps) {\n const client = useAdminClient();\n const { labels, currency } = useAdmin();\n const copy = labels.shipping;\n const query = useAdminQuery(['shipping-rates'], () =>\n client.listShippingRates(),\n );\n const [drafts, setDrafts] = useState<RateDraft[]>([]);\n const [baseline, setBaseline] = useState('[]');\n const [loaded, setLoaded] = useState<unknown>(undefined);\n const [removing, setRemoving] = useState<RateDraft | null>(null);\n const [rowErrors, setRowErrors] = useState<Record<string, RateErrors>>({});\n const [blocked, setBlocked] = useState(false);\n const [saved, setSaved] = useState(false);\n const [removedAny, setRemovedAny] = useState(false);\n const save = useAdminMutation(\n (rates: Parameters<typeof client.replaceShippingRates>[0]) =>\n client.replaceShippingRates(rates),\n );\n const lastDirty = useRef<boolean | undefined>(undefined);\n\n if (query.data && query.data !== loaded) {\n const next = toDrafts(query.data);\n setLoaded(query.data);\n setDrafts(next);\n setBaseline(snapshot(next));\n }\n\n const dirty = loaded !== undefined && snapshot(drafts) !== baseline;\n useEffect(() => {\n if (lastDirty.current === dirty) return;\n lastDirty.current = dirty;\n onDirtyChange?.(dirty);\n }, [dirty, onDirtyChange]);\n\n const edit = (next: RateDraft[]) => {\n setDrafts(next);\n setSaved(false);\n setBlocked(false);\n };\n\n const patch = (key: string, change: Partial<RateDraft>) => {\n edit(drafts.map((d) => (d.key === key ? { ...d, ...change } : d)));\n setRowErrors(({ [key]: _cleared, ...rest }) => rest);\n };\n\n const move = (index: number, direction: RateMove) => {\n const to = direction === 'earlier' ? index - 1 : index + 1;\n if (to < 0 || to >= drafts.length) return;\n const next = [...drafts];\n [next[index], next[to]] = [next[to], next[index]];\n edit(next);\n };\n\n const add = () => edit([...drafts, blankDraft(currency, copy.newRateLabel)]);\n\n const confirmRemove = () => {\n if (!removing) return;\n edit(drafts.filter((d) => d.key !== removing.key));\n setRemovedAny(true);\n setRemoving(null);\n };\n\n const submit = async () => {\n const check = checkDrafts(drafts, copy);\n setRowErrors(check.rowErrors);\n setBlocked(check.noActive);\n if (!check.valid) return;\n const result = await save.run(check.rates);\n if (!result) return;\n const next = toDrafts(result);\n setDrafts(next);\n setBaseline(snapshot(next));\n setRowErrors({});\n setRemovedAny(false);\n setSaved(true);\n };\n\n const mixedCurrency = drafts.some((d) => d.currency !== currency);\n\n const serverErrors =\n save.error instanceof AdminInvalidInputError\n ? serverRowErrors(save.error.issues, drafts, copy)\n : {};\n\n if (query.loading && !query.data) return <p role=\"status\">{copy.loading}</p>;\n if (!query.data) return <ErrorMessage error={query.error} />;\n\n return (\n <div className=\"sfa-shipping\">\n <h2>{copy.title}</h2>\n {removedAny ? (\n <Notice variant=\"warning\">{copy.removalWarning}</Notice>\n ) : null}\n {mixedCurrency ? (\n <Notice variant=\"warning\">\n {fill(copy.mixedCurrency, { currency })}\n </Notice>\n ) : null}\n {blocked ? <Notice variant=\"error\">{copy.noActive}</Notice> : null}\n <ErrorMessage error={save.error} />\n {saved ? <Notice variant=\"success\">{copy.saved}</Notice> : null}\n {dirty ? <p className=\"sfa-field__help\">{copy.unsaved}</p> : null}\n {drafts.length === 0 ? <p>{copy.empty}</p> : null}\n <ul className=\"sfa-rates\">\n {drafts.map((draft, index) => (\n <ShippingRateRow\n key={draft.key}\n draft={draft}\n index={index}\n total={drafts.length}\n errors={{ ...serverErrors[draft.key], ...rowErrors[draft.key] }}\n disabled={save.pending}\n labels={copy}\n onChange={(change) => patch(draft.key, change)}\n onMove={(direction) => move(index, direction)}\n onRemove={() => setRemoving(draft)}\n />\n ))}\n </ul>\n <div className=\"sfa-shipping__actions\">\n <button type=\"button\" className=\"sfa-btn\" onClick={add}>\n {copy.add}\n </button>\n <button\n type=\"button\"\n className=\"sfa-btn sfa-btn--primary\"\n disabled={save.pending}\n onClick={submit}\n >\n {copy.save}\n </button>\n </div>\n <ConfirmDialog\n open={removing !== null}\n title={copy.removeTitle}\n destructive\n confirmLabel={copy.remove}\n onConfirm={confirmRemove}\n onCancel={() => setRemoving(null)}\n >\n <p>{copy.removeBody}</p>\n </ConfirmDialog>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ export interface ImageLabels {
2
+ title: string;
3
+ empty: string;
4
+ add: string;
5
+ takePhoto: string;
6
+ dropHint: string;
7
+ altLabel: string;
8
+ altHelp: string;
9
+ altWarning: string;
10
+ cover: string;
11
+ photoName: string;
12
+ moveEarlier: string;
13
+ moveLater: string;
14
+ remove: string;
15
+ removeTitle: string;
16
+ removeBody: string;
17
+ uploading: string;
18
+ working: string;
19
+ tooLarge: string;
20
+ wrongType: string;
21
+ reorderFailed: string;
22
+ dismiss: string;
23
+ }
24
+ export declare const defaultImageLabels: ImageLabels;
@@ -0,0 +1,4 @@
1
+ import { ImageLabels } from './image-labels';
2
+ export declare const MAX_IMAGE_BYTES: number;
3
+ export declare function fill(template: string, values: Record<string, string>): string;
4
+ export declare function imageFileProblem(file: File, labels: ImageLabels): string | null;
@@ -0,0 +1,2 @@
1
+ export declare function parseMoneyInput(raw: string): number | null;
2
+ export declare function formatMoneyInput(cents: number): string;
@@ -0,0 +1,28 @@
1
+ export interface OrderActionLabels {
2
+ ship: string;
3
+ reship: string;
4
+ shipHeading: string;
5
+ carrier: string;
6
+ trackingNumber: string;
7
+ trackingUrl: string;
8
+ trackingUrlInvalid: string;
9
+ shipped: string;
10
+ refund: string;
11
+ refundTitle: string;
12
+ refundAmount: string;
13
+ refundAmountInvalid: string;
14
+ refundReason: string;
15
+ refundSubmit: string;
16
+ refundRetry: string;
17
+ restock: string;
18
+ restockWarning: string;
19
+ refundPending: string;
20
+ refundUnknown: string;
21
+ refundGateway: string;
22
+ refundDone: string;
23
+ resolve: string;
24
+ resolveHelp: string;
25
+ resolved: string;
26
+ restockThenResolve: string;
27
+ }
28
+ export declare const defaultOrderActionLabels: OrderActionLabels;
@@ -0,0 +1,66 @@
1
+ import { OrderActionLabels } from './order-action-labels';
2
+ export type OrderTab = 'paid' | 'shipped' | 'needs_attention' | 'pending_refund' | 'all';
3
+ export interface OrderLabels {
4
+ title: string;
5
+ searchLabel: string;
6
+ searchPlaceholder: string;
7
+ tabs: Record<OrderTab, string>;
8
+ empty: Record<OrderTab, string>;
9
+ noMatches: string;
10
+ loadMore: string;
11
+ columns: {
12
+ order: string;
13
+ status: string;
14
+ email: string;
15
+ items: string;
16
+ total: string;
17
+ date: string;
18
+ };
19
+ noEmail: string;
20
+ detailTitle: string;
21
+ back: string;
22
+ placed: string;
23
+ buyer: string;
24
+ itemsHeading: string;
25
+ itemColumns: {
26
+ name: string;
27
+ price: string;
28
+ quantity: string;
29
+ line: string;
30
+ };
31
+ subtotal: string;
32
+ shipping: string;
33
+ total: string;
34
+ shippingAddress: string;
35
+ noAddress: string;
36
+ fulfillment: string;
37
+ notShipped: string;
38
+ shippedOn: string;
39
+ carrier: string;
40
+ tracking: string;
41
+ trackShipment: string;
42
+ refunds: string;
43
+ noRefunds: string;
44
+ refundColumns: {
45
+ amount: string;
46
+ reason: string;
47
+ source: string;
48
+ status: string;
49
+ restocked: string;
50
+ date: string;
51
+ };
52
+ refundSources: {
53
+ admin: string;
54
+ gateway: string;
55
+ };
56
+ refundStatuses: {
57
+ pending: string;
58
+ succeeded: string;
59
+ };
60
+ yes: string;
61
+ no: string;
62
+ refunded: string;
63
+ remaining: string;
64
+ actions: OrderActionLabels;
65
+ }
66
+ export declare const defaultOrderLabels: OrderLabels;
@@ -0,0 +1,6 @@
1
+ import { AdminProduct, ProductStatus } from '@develemit/commerce-contracts';
2
+ import { ProductFilter } from './product-labels';
3
+ export declare function isSold(product: AdminProduct): boolean;
4
+ export declare function displayStatus(product: AdminProduct): string;
5
+ export declare function serverStatus(filter: ProductFilter): ProductStatus | undefined;
6
+ export declare function serverStock(filter: ProductFilter): 'in' | 'sold' | undefined;
@@ -0,0 +1,29 @@
1
+ import { AdminProduct, AdminProductInput, AdminProductPatch, ProductStatus } from '@develemit/commerce-contracts';
2
+ import { ProductLabels } from './product-labels';
3
+ export declare const FIELD_ORDER: readonly ["name", "category", "description", "materials", "dimensions", "price", "quantity", "status", "featured"];
4
+ export type FieldName = (typeof FIELD_ORDER)[number];
5
+ export type FieldErrors = Partial<Record<FieldName, string>>;
6
+ export interface ProductForm {
7
+ name: string;
8
+ category: string;
9
+ description: string;
10
+ materials: string;
11
+ dimensions: string;
12
+ price: string;
13
+ quantity: string;
14
+ status: ProductStatus;
15
+ featured: boolean;
16
+ }
17
+ export declare const emptyForm: ProductForm;
18
+ export declare function formFromProduct(product: AdminProduct): ProductForm;
19
+ export declare function mapServerIssues(issues: unknown[]): FieldErrors;
20
+ export declare function firstInvalidField(errors: FieldErrors): FieldName | undefined;
21
+ export type ValidationResult = {
22
+ ok: true;
23
+ input: AdminProductInput;
24
+ } | {
25
+ ok: false;
26
+ errors: FieldErrors;
27
+ };
28
+ export declare function validateForm(form: ProductForm, labels: ProductLabels, currency?: string): ValidationResult;
29
+ export declare function buildPatch(original: AdminProduct, input: AdminProductInput): AdminProductPatch;