@spree/seller-dashboard 1.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +31 -0
  3. package/dist/vite-plugin/index.js +51 -0
  4. package/package.json +64 -0
  5. package/src/api-client.ts +203 -0
  6. package/src/components/centered-message.tsx +8 -0
  7. package/src/components/finance/balance-summary.tsx +69 -0
  8. package/src/components/onboarding-nav-badge.tsx +38 -0
  9. package/src/components/orders/fulfillment-deliveries.tsx +116 -0
  10. package/src/components/orders/fulfillment-delivery-dialog.tsx +82 -0
  11. package/src/components/orders/fulfillment-edit-dialog.tsx +95 -0
  12. package/src/components/orders/fulfillment-fulfill-form.tsx +132 -0
  13. package/src/components/orders/fulfillment-label-upload-dialog.tsx +95 -0
  14. package/src/components/orders/fulfillment-split-dialog.tsx +142 -0
  15. package/src/components/orders/fulfillments-card.tsx +289 -0
  16. package/src/components/orders/line-label.ts +28 -0
  17. package/src/components/orders/order-cancel-dialog.tsx +74 -0
  18. package/src/components/orders/order-cards.tsx +297 -0
  19. package/src/components/orders/order-earnings-card.tsx +99 -0
  20. package/src/components/orders/order-notes-cards.tsx +83 -0
  21. package/src/components/orders/order-payment-card.tsx +94 -0
  22. package/src/components/orders/post-sale-cards.tsx +347 -0
  23. package/src/components/orders/post-sale-create-dialogs.tsx +201 -0
  24. package/src/components/orders/returns-card.tsx +258 -0
  25. package/src/components/orders/shipping-label-row.tsx +124 -0
  26. package/src/components/product-status-card.tsx +111 -0
  27. package/src/components/read-row.tsx +16 -0
  28. package/src/components/retryable-error.tsx +23 -0
  29. package/src/components/seller-address-card.tsx +123 -0
  30. package/src/components/seller-business-card.tsx +152 -0
  31. package/src/components/seller-returns-location-card.tsx +151 -0
  32. package/src/components/seller-switcher.tsx +124 -0
  33. package/src/components/seller-tax-identifiers-card.tsx +63 -0
  34. package/src/create-router.ts +32 -0
  35. package/src/hooks/use-fulfillments.ts +155 -0
  36. package/src/hooks/use-ledger.ts +46 -0
  37. package/src/hooks/use-order.ts +62 -0
  38. package/src/hooks/use-post-sale.ts +202 -0
  39. package/src/hooks/use-reasons.ts +34 -0
  40. package/src/hooks/use-stock-locations.ts +23 -0
  41. package/src/hooks/use-store-timezone.ts +26 -0
  42. package/src/i18n.ts +26 -0
  43. package/src/index.ts +27 -0
  44. package/src/lib/packing-slip.ts +109 -0
  45. package/src/locales/en.json +841 -0
  46. package/src/nav/default.ts +108 -0
  47. package/src/nav/settings.ts +114 -0
  48. package/src/pages/accept-invitation.tsx +127 -0
  49. package/src/pages/delivery-methods.tsx +647 -0
  50. package/src/pages/earnings.tsx +44 -0
  51. package/src/pages/forgot-password.tsx +100 -0
  52. package/src/pages/home.tsx +132 -0
  53. package/src/pages/login.tsx +94 -0
  54. package/src/pages/onboarding.tsx +539 -0
  55. package/src/pages/order.tsx +119 -0
  56. package/src/pages/orders.tsx +33 -0
  57. package/src/pages/payout.tsx +154 -0
  58. package/src/pages/payouts.tsx +32 -0
  59. package/src/pages/policies.tsx +292 -0
  60. package/src/pages/product.tsx +250 -0
  61. package/src/pages/products.tsx +228 -0
  62. package/src/pages/profile.tsx +389 -0
  63. package/src/pages/reset-password.tsx +105 -0
  64. package/src/pages/seller-picker.tsx +46 -0
  65. package/src/pages/team.tsx +468 -0
  66. package/src/panel-chrome.tsx +36 -0
  67. package/src/routeTree.gen.ts +590 -0
  68. package/src/routes/__root.tsx +15 -0
  69. package/src/routes/_authenticated/$sellerId/earnings/index.tsx +15 -0
  70. package/src/routes/_authenticated/$sellerId/index.tsx +6 -0
  71. package/src/routes/_authenticated/$sellerId/onboarding.tsx +6 -0
  72. package/src/routes/_authenticated/$sellerId/orders/$orderId.tsx +6 -0
  73. package/src/routes/_authenticated/$sellerId/orders/index.tsx +15 -0
  74. package/src/routes/_authenticated/$sellerId/payouts/$payoutId.tsx +7 -0
  75. package/src/routes/_authenticated/$sellerId/payouts/index.tsx +15 -0
  76. package/src/routes/_authenticated/$sellerId/products/$productId.tsx +6 -0
  77. package/src/routes/_authenticated/$sellerId/products/index.tsx +23 -0
  78. package/src/routes/_authenticated/$sellerId/products/new.tsx +6 -0
  79. package/src/routes/_authenticated/$sellerId/profile.tsx +6 -0
  80. package/src/routes/_authenticated/$sellerId/settings/delivery-methods.tsx +14 -0
  81. package/src/routes/_authenticated/$sellerId/settings/index.tsx +18 -0
  82. package/src/routes/_authenticated/$sellerId/settings/package-types.tsx +21 -0
  83. package/src/routes/_authenticated/$sellerId/settings/policies.tsx +14 -0
  84. package/src/routes/_authenticated/$sellerId/settings/stock-locations.tsx +22 -0
  85. package/src/routes/_authenticated/$sellerId/settings/team.tsx +6 -0
  86. package/src/routes/_authenticated/$sellerId/settings.tsx +18 -0
  87. package/src/routes/_authenticated/$sellerId.tsx +49 -0
  88. package/src/routes/_authenticated/index.tsx +48 -0
  89. package/src/routes/_authenticated.tsx +13 -0
  90. package/src/routes/accept-invitation.$invitationId.tsx +19 -0
  91. package/src/routes/forgot-password.tsx +15 -0
  92. package/src/routes/login.tsx +15 -0
  93. package/src/routes/reset-password.tsx +21 -0
  94. package/src/schemas/fulfillment.ts +31 -0
  95. package/src/seller-dashboard.tsx +50 -0
  96. package/src/styles.css +18 -0
  97. package/src/tables/delivery-methods.tsx +68 -0
  98. package/src/tables/orders.tsx +116 -0
  99. package/src/tables/payouts.tsx +87 -0
  100. package/src/tables/policies.tsx +37 -0
  101. package/src/tables/products.tsx +56 -0
  102. package/src/tables/transfers.tsx +118 -0
  103. package/src/vite/index.ts +87 -0
@@ -0,0 +1,109 @@
1
+ import type { Fulfillment, Order } from '@spree/seller-sdk'
2
+ import type { TFunction } from 'i18next'
3
+
4
+ function escapeHtml(value: string): string {
5
+ return value
6
+ .replaceAll('&', '&')
7
+ .replaceAll('<', '&lt;')
8
+ .replaceAll('>', '&gt;')
9
+ .replaceAll('"', '&quot;')
10
+ }
11
+
12
+ function addressBlock(order: Order): string {
13
+ const address = order.shipping_address
14
+ if (!address) return ''
15
+
16
+ return [
17
+ [address.first_name, address.last_name].filter(Boolean).join(' '),
18
+ address.company,
19
+ address.address1,
20
+ address.address2,
21
+ [address.city, address.state_name ?? address.state_code, address.postal_code]
22
+ .filter(Boolean)
23
+ .join(', '),
24
+ address.country_name || address.country_code,
25
+ ]
26
+ .filter(Boolean)
27
+ .map((line) => escapeHtml(String(line)))
28
+ .join('<br>')
29
+ }
30
+
31
+ function itemRows(fulfillment: Fulfillment): string {
32
+ return (fulfillment.fulfillment_items ?? [])
33
+ .map(
34
+ (item) => `
35
+ <tr>
36
+ <td>
37
+ ${escapeHtml(item.name ?? item.id)}
38
+ ${item.options_text ? `<div class="muted">${escapeHtml(item.options_text)}</div>` : ''}
39
+ </td>
40
+ <td class="qty">${item.quantity}</td>
41
+ </tr>`,
42
+ )
43
+ .join('')
44
+ }
45
+
46
+ /**
47
+ * Opens a printable packing slip for one parcel in a new window.
48
+ *
49
+ * A generated document rather than a panel route: the panel's own chrome
50
+ * would print with an in-app page, and everything the slip needs is already
51
+ * loaded on the order screen. No prices — a packing slip says what is in the
52
+ * box, not what it cost.
53
+ */
54
+ export function printPackingSlip(order: Order, fulfillment: Fulfillment, t: TFunction): void {
55
+ const title = t('orders.fulfillments.packing_slip_title', { number: order.number })
56
+
57
+ const html = `<!doctype html>
58
+ <html>
59
+ <head>
60
+ <meta charset="utf-8">
61
+ <title>${escapeHtml(title)}</title>
62
+ <style>
63
+ body { font-family: -apple-system, system-ui, sans-serif; margin: 40px; color: #111; }
64
+ h1 { font-size: 20px; margin: 0 0 4px; }
65
+ .muted { color: #666; font-size: 12px; }
66
+ .columns { display: flex; gap: 48px; margin: 24px 0; }
67
+ h2 { font-size: 12px; text-transform: uppercase; letter-spacing: 0.05em; color: #666; margin: 0 0 6px; }
68
+ table { width: 100%; border-collapse: collapse; margin-top: 8px; }
69
+ th { text-align: left; font-size: 12px; text-transform: uppercase; letter-spacing: 0.05em; color: #666;
70
+ border-bottom: 1px solid #ddd; padding: 6px 0; }
71
+ td { padding: 8px 0; border-bottom: 1px solid #eee; font-size: 14px; vertical-align: top; }
72
+ .qty { text-align: right; width: 60px; }
73
+ </style>
74
+ </head>
75
+ <body>
76
+ <h1>${escapeHtml(title)}</h1>
77
+ <div class="muted">${escapeHtml(fulfillment.number ?? '')}</div>
78
+
79
+ <div class="columns">
80
+ <div>
81
+ <h2>${escapeHtml(t('orders.fulfillments.ship_to'))}</h2>
82
+ <div>${addressBlock(order)}</div>
83
+ </div>
84
+ <div>
85
+ <h2>${escapeHtml(t('orders.fulfillments.ships_from_label'))}</h2>
86
+ <div>${escapeHtml(fulfillment.stock_location_name ?? '')}</div>
87
+ </div>
88
+ </div>
89
+
90
+ <table>
91
+ <thead>
92
+ <tr>
93
+ <th>${escapeHtml(t('orders.items'))}</th>
94
+ <th class="qty">${escapeHtml(t('orders.columns.quantity'))}</th>
95
+ </tr>
96
+ </thead>
97
+ <tbody>${itemRows(fulfillment)}</tbody>
98
+ </table>
99
+ </body>
100
+ </html>`
101
+
102
+ const printWindow = window.open('', '_blank')
103
+ if (!printWindow) return
104
+
105
+ printWindow.document.write(html)
106
+ printWindow.document.close()
107
+ printWindow.focus()
108
+ printWindow.print()
109
+ }