@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.
- package/LICENSE +21 -0
- package/README.md +31 -0
- package/dist/vite-plugin/index.js +51 -0
- package/package.json +64 -0
- package/src/api-client.ts +203 -0
- package/src/components/centered-message.tsx +8 -0
- package/src/components/finance/balance-summary.tsx +69 -0
- package/src/components/onboarding-nav-badge.tsx +38 -0
- package/src/components/orders/fulfillment-deliveries.tsx +116 -0
- package/src/components/orders/fulfillment-delivery-dialog.tsx +82 -0
- package/src/components/orders/fulfillment-edit-dialog.tsx +95 -0
- package/src/components/orders/fulfillment-fulfill-form.tsx +132 -0
- package/src/components/orders/fulfillment-label-upload-dialog.tsx +95 -0
- package/src/components/orders/fulfillment-split-dialog.tsx +142 -0
- package/src/components/orders/fulfillments-card.tsx +289 -0
- package/src/components/orders/line-label.ts +28 -0
- package/src/components/orders/order-cancel-dialog.tsx +74 -0
- package/src/components/orders/order-cards.tsx +297 -0
- package/src/components/orders/order-earnings-card.tsx +99 -0
- package/src/components/orders/order-notes-cards.tsx +83 -0
- package/src/components/orders/order-payment-card.tsx +94 -0
- package/src/components/orders/post-sale-cards.tsx +347 -0
- package/src/components/orders/post-sale-create-dialogs.tsx +201 -0
- package/src/components/orders/returns-card.tsx +258 -0
- package/src/components/orders/shipping-label-row.tsx +124 -0
- package/src/components/product-status-card.tsx +111 -0
- package/src/components/read-row.tsx +16 -0
- package/src/components/retryable-error.tsx +23 -0
- package/src/components/seller-address-card.tsx +123 -0
- package/src/components/seller-business-card.tsx +152 -0
- package/src/components/seller-returns-location-card.tsx +151 -0
- package/src/components/seller-switcher.tsx +124 -0
- package/src/components/seller-tax-identifiers-card.tsx +63 -0
- package/src/create-router.ts +32 -0
- package/src/hooks/use-fulfillments.ts +155 -0
- package/src/hooks/use-ledger.ts +46 -0
- package/src/hooks/use-order.ts +62 -0
- package/src/hooks/use-post-sale.ts +202 -0
- package/src/hooks/use-reasons.ts +34 -0
- package/src/hooks/use-stock-locations.ts +23 -0
- package/src/hooks/use-store-timezone.ts +26 -0
- package/src/i18n.ts +26 -0
- package/src/index.ts +27 -0
- package/src/lib/packing-slip.ts +109 -0
- package/src/locales/en.json +841 -0
- package/src/nav/default.ts +108 -0
- package/src/nav/settings.ts +114 -0
- package/src/pages/accept-invitation.tsx +127 -0
- package/src/pages/delivery-methods.tsx +647 -0
- package/src/pages/earnings.tsx +44 -0
- package/src/pages/forgot-password.tsx +100 -0
- package/src/pages/home.tsx +132 -0
- package/src/pages/login.tsx +94 -0
- package/src/pages/onboarding.tsx +539 -0
- package/src/pages/order.tsx +119 -0
- package/src/pages/orders.tsx +33 -0
- package/src/pages/payout.tsx +154 -0
- package/src/pages/payouts.tsx +32 -0
- package/src/pages/policies.tsx +292 -0
- package/src/pages/product.tsx +250 -0
- package/src/pages/products.tsx +228 -0
- package/src/pages/profile.tsx +389 -0
- package/src/pages/reset-password.tsx +105 -0
- package/src/pages/seller-picker.tsx +46 -0
- package/src/pages/team.tsx +468 -0
- package/src/panel-chrome.tsx +36 -0
- package/src/routeTree.gen.ts +590 -0
- package/src/routes/__root.tsx +15 -0
- package/src/routes/_authenticated/$sellerId/earnings/index.tsx +15 -0
- package/src/routes/_authenticated/$sellerId/index.tsx +6 -0
- package/src/routes/_authenticated/$sellerId/onboarding.tsx +6 -0
- package/src/routes/_authenticated/$sellerId/orders/$orderId.tsx +6 -0
- package/src/routes/_authenticated/$sellerId/orders/index.tsx +15 -0
- package/src/routes/_authenticated/$sellerId/payouts/$payoutId.tsx +7 -0
- package/src/routes/_authenticated/$sellerId/payouts/index.tsx +15 -0
- package/src/routes/_authenticated/$sellerId/products/$productId.tsx +6 -0
- package/src/routes/_authenticated/$sellerId/products/index.tsx +23 -0
- package/src/routes/_authenticated/$sellerId/products/new.tsx +6 -0
- package/src/routes/_authenticated/$sellerId/profile.tsx +6 -0
- package/src/routes/_authenticated/$sellerId/settings/delivery-methods.tsx +14 -0
- package/src/routes/_authenticated/$sellerId/settings/index.tsx +18 -0
- package/src/routes/_authenticated/$sellerId/settings/package-types.tsx +21 -0
- package/src/routes/_authenticated/$sellerId/settings/policies.tsx +14 -0
- package/src/routes/_authenticated/$sellerId/settings/stock-locations.tsx +22 -0
- package/src/routes/_authenticated/$sellerId/settings/team.tsx +6 -0
- package/src/routes/_authenticated/$sellerId/settings.tsx +18 -0
- package/src/routes/_authenticated/$sellerId.tsx +49 -0
- package/src/routes/_authenticated/index.tsx +48 -0
- package/src/routes/_authenticated.tsx +13 -0
- package/src/routes/accept-invitation.$invitationId.tsx +19 -0
- package/src/routes/forgot-password.tsx +15 -0
- package/src/routes/login.tsx +15 -0
- package/src/routes/reset-password.tsx +21 -0
- package/src/schemas/fulfillment.ts +31 -0
- package/src/seller-dashboard.tsx +50 -0
- package/src/styles.css +18 -0
- package/src/tables/delivery-methods.tsx +68 -0
- package/src/tables/orders.tsx +116 -0
- package/src/tables/payouts.tsx +87 -0
- package/src/tables/policies.tsx +37 -0
- package/src/tables/products.tsx +56 -0
- package/src/tables/transfers.tsx +118 -0
- 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('<', '<')
|
|
8
|
+
.replaceAll('>', '>')
|
|
9
|
+
.replaceAll('"', '"')
|
|
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
|
+
}
|