@spree/seller-dashboard 1.0.0-rc.4 → 1.0.0-rc.6
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/package.json +30 -20
- package/src/components/orders/fulfillment-edit-dialog.tsx +2 -1
- package/src/components/orders/fulfillment-label-upload-dialog.tsx +1 -1
- package/src/components/orders/fulfillments-card.tsx +3 -2
- package/src/components/orders/order-cards.tsx +1 -1
- package/src/components/orders/post-sale-cards.tsx +3 -3
- package/src/components/orders/returns-card.tsx +2 -1
- package/src/hooks/use-fulfillments.ts +1 -1
- package/src/hooks/use-post-sale.ts +2 -1
- package/src/index.ts +1 -0
- package/src/pages/onboarding.tsx +7 -3
- package/src/pages/policies.tsx +21 -9
- package/src/pages/product.tsx +14 -5
- package/src/pages/products.tsx +2 -1
- package/src/routes/_authenticated/$sellerId/settings/package-types.tsx +1 -1
- package/src/routes/_authenticated/$sellerId/settings/stock-locations.tsx +1 -1
- package/src/tables/orders.tsx +9 -23
- package/src/tables/payouts.tsx +2 -3
- package/src/tables/products.tsx +1 -3
- package/src/tables/transfers.tsx +3 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spree/seller-dashboard",
|
|
3
|
-
"version": "1.0.0-rc.
|
|
3
|
+
"version": "1.0.0-rc.6",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Spree marketplace seller panel — the seller-facing counterpart to the admin dashboard.",
|
|
@@ -40,34 +40,44 @@
|
|
|
40
40
|
"@dnd-kit/core": "^6.3.1",
|
|
41
41
|
"@dnd-kit/sortable": "^10.0.0",
|
|
42
42
|
"@dnd-kit/utilities": "^3.2.2",
|
|
43
|
-
"@tanstack/
|
|
44
|
-
"@tanstack/react-router": "^1.133.32",
|
|
45
|
-
"@tanstack/router-plugin": "^1.167.35",
|
|
43
|
+
"@tanstack/router-plugin": "^1.168.46",
|
|
46
44
|
"@tanstack/virtual-file-routes": "^1.162.0",
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"zod": "^4.4.3",
|
|
52
|
-
"@spree/dashboard-ui": "1.0.0-rc.3",
|
|
53
|
-
"@spree/seller-sdk": "1.0.0-rc.3",
|
|
54
|
-
"@spree/dashboard-core": "1.0.0-rc.3"
|
|
45
|
+
"lucide-react": "^1.58.0",
|
|
46
|
+
"zod": "^4.6.7",
|
|
47
|
+
"@spree/seller-sdk": "1.0.0-rc.5",
|
|
48
|
+
"@spree/core": "^0.2.0"
|
|
55
49
|
},
|
|
56
50
|
"peerDependencies": {
|
|
57
|
-
"react": "^
|
|
58
|
-
"react-
|
|
51
|
+
"@tanstack/react-query": "^5.104.3",
|
|
52
|
+
"@tanstack/react-router": "^1.170.44",
|
|
53
|
+
"i18next": "^26.4.7",
|
|
54
|
+
"react": "^19.3.1",
|
|
55
|
+
"react-dom": "^19.3.1",
|
|
56
|
+
"react-hook-form": "^7.90.0",
|
|
57
|
+
"react-i18next": "^17.0.20",
|
|
58
|
+
"@spree/admin-sdk": "^1.0.0-rc.5",
|
|
59
|
+
"@spree/dashboard-core": "^1.0.0-rc.5",
|
|
60
|
+
"@spree/dashboard-ui": "^1.0.0-rc.5"
|
|
59
61
|
},
|
|
60
62
|
"devDependencies": {
|
|
61
63
|
"@biomejs/biome": "^2.4.14",
|
|
62
|
-
"@
|
|
64
|
+
"@tanstack/react-query": "^5.104.3",
|
|
65
|
+
"@tanstack/react-router": "^1.170.44",
|
|
66
|
+
"@types/node": "^26.6.5",
|
|
63
67
|
"@types/react": "^19.2.2",
|
|
64
68
|
"@types/react-dom": "^19.2.1",
|
|
65
69
|
"@vitejs/plugin-react": "^6.0.1",
|
|
66
|
-
"
|
|
67
|
-
"react
|
|
68
|
-
"
|
|
69
|
-
"
|
|
70
|
-
"
|
|
70
|
+
"i18next": "^26.4.7",
|
|
71
|
+
"react": "^19.3.1",
|
|
72
|
+
"react-dom": "^19.3.1",
|
|
73
|
+
"react-hook-form": "^7.90.0",
|
|
74
|
+
"react-i18next": "^17.0.20",
|
|
75
|
+
"tsup": "^9.0.0",
|
|
76
|
+
"typescript": "~7.0.2",
|
|
77
|
+
"vite": "^8.3.4",
|
|
78
|
+
"@spree/dashboard-core": "1.0.0-rc.5",
|
|
79
|
+
"@spree/dashboard-ui": "1.0.0-rc.5",
|
|
80
|
+
"@spree/admin-sdk": "1.0.0-rc.5"
|
|
71
81
|
},
|
|
72
82
|
"scripts": {
|
|
73
83
|
"build": "pnpm generate:routes && tsup",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { isZeroMoney } from '@spree/core'
|
|
1
2
|
import { formatMoney, useMoneyLocale } from '@spree/dashboard-core'
|
|
2
3
|
import { FulfillmentEditDialog as SharedFulfillmentEditDialog } from '@spree/dashboard-ui'
|
|
3
|
-
import { type Fulfillment,
|
|
4
|
+
import { type Fulfillment, SpreeError } from '@spree/seller-sdk'
|
|
4
5
|
import { useState } from 'react'
|
|
5
6
|
import { useTranslation } from 'react-i18next'
|
|
6
7
|
import { useFulfillmentActions } from '../../hooks/use-fulfillments'
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { zodResolver } from '@hookform/resolvers/zod'
|
|
2
|
+
import type { CurrencyCode } from '@spree/core'
|
|
2
3
|
import {
|
|
3
4
|
EMPTY_FILE_UPLOAD_VALUE,
|
|
4
5
|
FileUploadField,
|
|
@@ -9,7 +10,6 @@ import {
|
|
|
9
10
|
mapSpreeErrorsToForm,
|
|
10
11
|
} from '@spree/dashboard-core'
|
|
11
12
|
import { LabelUploadDialog } from '@spree/dashboard-ui'
|
|
12
|
-
import type { CurrencyCode } from '@spree/seller-sdk'
|
|
13
13
|
import { useState } from 'react'
|
|
14
14
|
import { useForm } from 'react-hook-form'
|
|
15
15
|
import { useTranslation } from 'react-i18next'
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { FULFILLMENT_STATUSES, subsetOf } from '@spree/core'
|
|
1
2
|
import { fulfillmentItemRows } from '@spree/dashboard-core'
|
|
2
3
|
import {
|
|
3
4
|
Badge,
|
|
@@ -44,8 +45,8 @@ import { ShippingLabelRow } from './shipping-label-row'
|
|
|
44
45
|
// A parcel that has not gone out is the only one still to ship or cancel.
|
|
45
46
|
// Reading these off "not unfulfilled" once badged a canceled parcel as a
|
|
46
47
|
// success.
|
|
47
|
-
const CAN_SHIP = ['unfulfilled']
|
|
48
|
-
const CAN_CANCEL = ['unfulfilled']
|
|
48
|
+
const CAN_SHIP = subsetOf(FULFILLMENT_STATUSES, ['unfulfilled'])
|
|
49
|
+
const CAN_CANCEL = subsetOf(FULFILLMENT_STATUSES, ['unfulfilled'])
|
|
49
50
|
|
|
50
51
|
/** Every parcel owed on this order, and what the seller can do with each. */
|
|
51
52
|
export function FulfillmentsCard({ order }: { order: Order }) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isZeroMoney } from '@spree/core'
|
|
1
2
|
import {
|
|
2
3
|
AddressFormDialog,
|
|
3
4
|
formatMoney,
|
|
@@ -21,7 +22,6 @@ import {
|
|
|
21
22
|
} from '@spree/dashboard-ui'
|
|
22
23
|
import { EllipsisVerticalIcon, PencilIcon } from '@spree/dashboard-ui/icons'
|
|
23
24
|
import type { Order, OrderAddressParams } from '@spree/seller-sdk'
|
|
24
|
-
import { isZeroMoney } from '@spree/seller-sdk'
|
|
25
25
|
import { type ReactNode, useState } from 'react'
|
|
26
26
|
import { useTranslation } from 'react-i18next'
|
|
27
27
|
import { sellerClient } from '../../api-client'
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { CLAIM_STATUSES, EXCHANGE_STATUSES, subsetOf, sumMoney } from '@spree/core'
|
|
1
2
|
import { currencyParts, formatMoney, isPositiveMoney, useMoneyLocale } from '@spree/dashboard-core'
|
|
2
3
|
import {
|
|
3
4
|
Button,
|
|
@@ -23,7 +24,6 @@ import {
|
|
|
23
24
|
ShieldAlertIcon,
|
|
24
25
|
} from '@spree/dashboard-ui/icons'
|
|
25
26
|
import type { Claim, Order } from '@spree/seller-sdk'
|
|
26
|
-
import { sumMoney } from '@spree/seller-sdk'
|
|
27
27
|
import i18n from 'i18next'
|
|
28
28
|
import { useState } from 'react'
|
|
29
29
|
import { useTranslation } from 'react-i18next'
|
|
@@ -36,8 +36,8 @@ import {
|
|
|
36
36
|
import { lineLabel } from './line-label'
|
|
37
37
|
import { CreateClaimDialog } from './post-sale-create-dialogs'
|
|
38
38
|
|
|
39
|
-
const EXCHANGE_ACTIONABLE = ['requested', 'approved', 'received']
|
|
40
|
-
const CLAIM_ACTIONABLE = ['open', 'approved']
|
|
39
|
+
const EXCHANGE_ACTIONABLE = subsetOf(EXCHANGE_STATUSES, ['requested', 'approved', 'received'])
|
|
40
|
+
const CLAIM_ACTIONABLE = subsetOf(CLAIM_STATUSES, ['open', 'approved'])
|
|
41
41
|
|
|
42
42
|
/**
|
|
43
43
|
* Goods swapped for different ones.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { RETURN_STATUSES, subsetOf } from '@spree/core'
|
|
1
2
|
import {
|
|
2
3
|
currencyParts,
|
|
3
4
|
formatMoney,
|
|
@@ -35,7 +36,7 @@ import { CreateReturnDialog, fulfilledUnits } from './post-sale-create-dialogs'
|
|
|
35
36
|
|
|
36
37
|
// Refunded and canceled returns are finished; offering a menu on them would
|
|
37
38
|
// open onto nothing.
|
|
38
|
-
const ACTIONABLE = ['requested', 'approved', 'received']
|
|
39
|
+
const ACTIONABLE = subsetOf(RETURN_STATUSES, ['requested', 'approved', 'received'])
|
|
39
40
|
|
|
40
41
|
/**
|
|
41
42
|
* Goods coming back on this order.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import type { CurrencyCode } from '@spree/core'
|
|
1
2
|
import { useResourceKeyBuilder } from '@spree/dashboard-core'
|
|
2
3
|
import { toastManager } from '@spree/dashboard-ui'
|
|
3
|
-
import type { CurrencyCode } from '@spree/seller-sdk'
|
|
4
4
|
import { useMutation, useQueryClient } from '@tanstack/react-query'
|
|
5
5
|
import { sellerClient } from '../api-client'
|
|
6
6
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ClaimResolution } from '@spree/core'
|
|
1
2
|
import { useResourceKey, useResourceKeyBuilder } from '@spree/dashboard-core'
|
|
2
3
|
import { toastManager } from '@spree/dashboard-ui'
|
|
3
4
|
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
|
|
@@ -182,7 +183,7 @@ export function useClaimActions(orderId: string) {
|
|
|
182
183
|
replacementLineItemIds,
|
|
183
184
|
}: {
|
|
184
185
|
claimId: string
|
|
185
|
-
resolution:
|
|
186
|
+
resolution: ClaimResolution
|
|
186
187
|
refundMethod?: 'original_payment' | 'store_credit'
|
|
187
188
|
amount?: string
|
|
188
189
|
replacementLineItemIds?: string[]
|
package/src/index.ts
CHANGED
package/src/pages/onboarding.tsx
CHANGED
|
@@ -10,6 +10,8 @@ import {
|
|
|
10
10
|
AccordionContent,
|
|
11
11
|
AccordionItem,
|
|
12
12
|
AccordionTrigger,
|
|
13
|
+
Alert,
|
|
14
|
+
AlertDescription,
|
|
13
15
|
Badge,
|
|
14
16
|
Button,
|
|
15
17
|
Card,
|
|
@@ -28,6 +30,7 @@ import {
|
|
|
28
30
|
import {
|
|
29
31
|
CheckCircle2Icon,
|
|
30
32
|
ChevronRightIcon,
|
|
33
|
+
CircleAlertIcon,
|
|
31
34
|
CircleIcon,
|
|
32
35
|
ClockIcon,
|
|
33
36
|
ExternalLinkIcon,
|
|
@@ -284,9 +287,10 @@ function RequirementAction({ requirement }: { requirement: RequirementStatus })
|
|
|
284
287
|
|
|
285
288
|
// A rejection the seller cannot read is a rejection they cannot act on.
|
|
286
289
|
const rejection = submission?.status === 'rejected' && submission.review_note && (
|
|
287
|
-
<
|
|
288
|
-
|
|
289
|
-
|
|
290
|
+
<Alert variant="destructive">
|
|
291
|
+
<CircleAlertIcon />
|
|
292
|
+
<AlertDescription>{submission.review_note}</AlertDescription>
|
|
293
|
+
</Alert>
|
|
290
294
|
)
|
|
291
295
|
|
|
292
296
|
// Nothing to do on a finished line. The header already carries the tick and
|
package/src/pages/policies.tsx
CHANGED
|
@@ -15,6 +15,11 @@ import {
|
|
|
15
15
|
FieldError,
|
|
16
16
|
FieldLabel,
|
|
17
17
|
Input,
|
|
18
|
+
Item,
|
|
19
|
+
ItemActions,
|
|
20
|
+
ItemContent,
|
|
21
|
+
ItemGroup,
|
|
22
|
+
ItemTitle,
|
|
18
23
|
RichTextEditor,
|
|
19
24
|
RowActions,
|
|
20
25
|
Sheet,
|
|
@@ -128,19 +133,26 @@ export function PoliciesPage({ search }: { search: ResourceSearch }) {
|
|
|
128
133
|
</CardHeader>
|
|
129
134
|
<CardContent className="flex flex-col gap-3">
|
|
130
135
|
<p className="text-muted-foreground text-sm">{t('policies.required.description')}</p>
|
|
131
|
-
<
|
|
136
|
+
<ItemGroup className="gap-2">
|
|
132
137
|
{outstanding.map((name) => (
|
|
133
|
-
<
|
|
138
|
+
<Item
|
|
134
139
|
key={name}
|
|
135
|
-
|
|
140
|
+
role="listitem"
|
|
141
|
+
variant="outline"
|
|
142
|
+
size="sm"
|
|
143
|
+
className="border-border-subtle"
|
|
136
144
|
>
|
|
137
|
-
<
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
145
|
+
<ItemContent>
|
|
146
|
+
<ItemTitle>{name}</ItemTitle>
|
|
147
|
+
</ItemContent>
|
|
148
|
+
<ItemActions>
|
|
149
|
+
<Button size="sm" variant="outline" onClick={() => setCreatingName(name)}>
|
|
150
|
+
{t('policies.required.write')}
|
|
151
|
+
</Button>
|
|
152
|
+
</ItemActions>
|
|
153
|
+
</Item>
|
|
142
154
|
))}
|
|
143
|
-
</
|
|
155
|
+
</ItemGroup>
|
|
144
156
|
</CardContent>
|
|
145
157
|
</Card>
|
|
146
158
|
)}
|
package/src/pages/product.tsx
CHANGED
|
@@ -2,6 +2,7 @@ import { zodResolver } from '@hookform/resolvers/zod'
|
|
|
2
2
|
import {
|
|
3
3
|
CategorizationCard,
|
|
4
4
|
extensionFormValues,
|
|
5
|
+
extensionRowValues,
|
|
5
6
|
extensionSubmitValues,
|
|
6
7
|
GeneralCard,
|
|
7
8
|
InventoryCard,
|
|
@@ -17,6 +18,7 @@ import {
|
|
|
17
18
|
Slot,
|
|
18
19
|
VariantsCard,
|
|
19
20
|
variantToWirePayload,
|
|
21
|
+
withExtensionRowValues,
|
|
20
22
|
} from '@spree/dashboard-core'
|
|
21
23
|
import { FormActions, ResourceLayout, StatusBadge, toastManager } from '@spree/dashboard-ui'
|
|
22
24
|
import type { ProductCreateParams } from '@spree/seller-sdk'
|
|
@@ -106,7 +108,7 @@ export function ProductPage({ mode }: { mode: 'new' | 'edit' }) {
|
|
|
106
108
|
if (form.formState.isDirty) return
|
|
107
109
|
|
|
108
110
|
form.reset({
|
|
109
|
-
...productToFormValues(product as PanelProduct, product.media),
|
|
111
|
+
...productToFormValues(product as PanelProduct, product.media, 'seller.product'),
|
|
110
112
|
...extensionFormValues('seller.product', product),
|
|
111
113
|
})
|
|
112
114
|
}, [product, form])
|
|
@@ -137,6 +139,7 @@ export function ProductPage({ mode }: { mode: 'new' | 'edit' }) {
|
|
|
137
139
|
// cards offer both — an allow-list that omitted them let a seller
|
|
138
140
|
// set a crop or paste a video URL and watch it vanish on save.
|
|
139
141
|
media: (values.media ?? []).map((item) => ({
|
|
142
|
+
...extensionRowValues('seller.product.media', item),
|
|
140
143
|
id: item.id,
|
|
141
144
|
signed_id: item.signed_id ?? undefined,
|
|
142
145
|
poster_signed_id: item.poster_signed_id ?? undefined,
|
|
@@ -149,7 +152,7 @@ export function ProductPage({ mode }: { mode: 'new' | 'edit' }) {
|
|
|
149
152
|
variant_ids: item.variant_ids,
|
|
150
153
|
})),
|
|
151
154
|
variants: (values.variants ?? []).map((variant, index) =>
|
|
152
|
-
variantToWirePayload(variant, index),
|
|
155
|
+
variantToWirePayload(variant, index, 'seller.product'),
|
|
153
156
|
) as ProductCreateParams['variants'],
|
|
154
157
|
}
|
|
155
158
|
|
|
@@ -181,7 +184,7 @@ export function ProductPage({ mode }: { mode: 'new' | 'edit' }) {
|
|
|
181
184
|
// Raw form state, not `values`: the Zod parse strips keys the schema
|
|
182
185
|
// doesn't know, which is every field a slot widget registered.
|
|
183
186
|
await save.mutateAsync({
|
|
184
|
-
values,
|
|
187
|
+
values: withExtensionRowValues('seller.product', values, form.getValues()),
|
|
185
188
|
extensionValues: extensionSubmitValues('seller.product', form),
|
|
186
189
|
})
|
|
187
190
|
} catch (err) {
|
|
@@ -236,8 +239,13 @@ export function ProductPage({ mode }: { mode: 'new' | 'edit' }) {
|
|
|
236
239
|
main={
|
|
237
240
|
<>
|
|
238
241
|
<GeneralCard form={form} />
|
|
239
|
-
<VariantsCard form={form} />
|
|
240
|
-
<MediaCard
|
|
242
|
+
<VariantsCard form={form} formKey="seller.product" />
|
|
243
|
+
<MediaCard
|
|
244
|
+
productId={productId}
|
|
245
|
+
variants={product?.variants ?? []}
|
|
246
|
+
form={form}
|
|
247
|
+
formKey="seller.product"
|
|
248
|
+
/>
|
|
241
249
|
<PricesCard
|
|
242
250
|
form={form}
|
|
243
251
|
productName={product?.name ?? ''}
|
|
@@ -245,6 +253,7 @@ export function ProductPage({ mode }: { mode: 'new' | 'edit' }) {
|
|
|
245
253
|
defaultCurrency={profile?.default_currency}
|
|
246
254
|
/>
|
|
247
255
|
<InventoryCard form={form} />
|
|
256
|
+
<Slot name="seller.product.form_main" context={{ product, mode }} />
|
|
248
257
|
</>
|
|
249
258
|
}
|
|
250
259
|
sidebar={
|
package/src/pages/products.tsx
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { PRODUCT_STATUSES, subsetOf } from '@spree/core'
|
|
1
2
|
import type {
|
|
2
3
|
BulkAction,
|
|
3
4
|
BulkActionFormProps,
|
|
@@ -40,7 +41,7 @@ import '../tables/products'
|
|
|
40
41
|
* approves it, so the only moves offered here are the two a seller makes
|
|
41
42
|
* alone (docs/plans/6.0-seller-product-submission.md).
|
|
42
43
|
*/
|
|
43
|
-
const BULK_STATUSES = ['draft', 'archived']
|
|
44
|
+
const BULK_STATUSES = subsetOf(PRODUCT_STATUSES, ['draft', 'archived'])
|
|
44
45
|
|
|
45
46
|
type BulkStatus = (typeof BULK_STATUSES)[number]
|
|
46
47
|
type StatusFormValues = { status: BulkStatus }
|
|
@@ -17,5 +17,5 @@ export const Route = createFileRoute('/_authenticated/$sellerId/settings/package
|
|
|
17
17
|
function PackageTypesRoute() {
|
|
18
18
|
const search = Route.useSearch() as z.infer<typeof packageTypesSearchSchema>
|
|
19
19
|
|
|
20
|
-
return <PackageTypesPage search={search} />
|
|
20
|
+
return <PackageTypesPage search={search} formKey="seller.package_type" />
|
|
21
21
|
}
|
|
@@ -18,5 +18,5 @@ export const Route = createFileRoute('/_authenticated/$sellerId/settings/stock-l
|
|
|
18
18
|
function StockLocationsRoute() {
|
|
19
19
|
const search = Route.useSearch() as z.infer<typeof stockLocationsSearchSchema>
|
|
20
20
|
|
|
21
|
-
return <StockLocationsPage search={search} />
|
|
21
|
+
return <StockLocationsPage search={search} formKey="seller.stock_location" />
|
|
22
22
|
}
|
package/src/tables/orders.tsx
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ORDER_PAYMENT_STATUSES } from '@spree/core'
|
|
2
|
+
import {
|
|
3
|
+
defineTable,
|
|
4
|
+
FILTERABLE_ORDER_FULFILLMENT_STATUSES,
|
|
5
|
+
formatMoney,
|
|
6
|
+
formatStoreDateTime,
|
|
7
|
+
} from '@spree/dashboard-core'
|
|
2
8
|
import { ResourceNameCell, StatusBadge } from '@spree/dashboard-ui'
|
|
3
9
|
import { PackageIcon } from '@spree/dashboard-ui/icons'
|
|
4
10
|
import type { Order } from '@spree/seller-sdk'
|
|
@@ -17,26 +23,6 @@ function OrderDate({ iso }: { iso: string }) {
|
|
|
17
23
|
return <>{formatStoreDateTime(iso, timezone)}</>
|
|
18
24
|
}
|
|
19
25
|
|
|
20
|
-
/** Mirrors the operator dashboard's order status vocabularies. */
|
|
21
|
-
const FULFILLMENT_STATUSES = [
|
|
22
|
-
'unfulfilled',
|
|
23
|
-
'backorder',
|
|
24
|
-
'partial',
|
|
25
|
-
'fulfilled',
|
|
26
|
-
'delivered',
|
|
27
|
-
'canceled',
|
|
28
|
-
] as const
|
|
29
|
-
const PAYMENT_STATUSES = [
|
|
30
|
-
'none',
|
|
31
|
-
'authorized',
|
|
32
|
-
'partially_paid',
|
|
33
|
-
'paid',
|
|
34
|
-
'partially_refunded',
|
|
35
|
-
'refunded',
|
|
36
|
-
'overcharged',
|
|
37
|
-
'voided',
|
|
38
|
-
] as const
|
|
39
|
-
|
|
40
26
|
defineTable<Order>('seller-orders', {
|
|
41
27
|
title: i18n.t('orders.title'),
|
|
42
28
|
searchParam: 'number_cont',
|
|
@@ -69,7 +55,7 @@ defineTable<Order>('seller-orders', {
|
|
|
69
55
|
label: i18n.t('orders.columns.fulfillment'),
|
|
70
56
|
filterable: true,
|
|
71
57
|
filterType: 'enum',
|
|
72
|
-
filterOptions:
|
|
58
|
+
filterOptions: FILTERABLE_ORDER_FULFILLMENT_STATUSES.map((status) => ({
|
|
73
59
|
value: status,
|
|
74
60
|
label: i18n.t(`orders.fulfillment_statuses.${status}`),
|
|
75
61
|
})),
|
|
@@ -90,7 +76,7 @@ defineTable<Order>('seller-orders', {
|
|
|
90
76
|
label: i18n.t('orders.columns.payment'),
|
|
91
77
|
filterable: true,
|
|
92
78
|
filterType: 'enum',
|
|
93
|
-
filterOptions:
|
|
79
|
+
filterOptions: ORDER_PAYMENT_STATUSES.map((status) => ({
|
|
94
80
|
value: status,
|
|
95
81
|
label: i18n.t(`orders.payment_statuses.${status}`),
|
|
96
82
|
})),
|
package/src/tables/payouts.tsx
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SELLER_PAYOUT_STATUSES } from '@spree/core'
|
|
1
2
|
import { defineTable, formatMoney, formatStoreDateTime } from '@spree/dashboard-core'
|
|
2
3
|
import { ResourceNameCell, StatusBadge } from '@spree/dashboard-ui'
|
|
3
4
|
import { HandCoinsIcon } from '@spree/dashboard-ui/icons'
|
|
@@ -18,8 +19,6 @@ function LedgerDate({ iso }: { iso: string }) {
|
|
|
18
19
|
return <>{formatStoreDateTime(iso, timezone)}</>
|
|
19
20
|
}
|
|
20
21
|
|
|
21
|
-
const STATUSES = ['pending', 'processing', 'completed', 'failed', 'unresolved'] as const
|
|
22
|
-
|
|
23
22
|
defineTable<Payout>('seller-payouts', {
|
|
24
23
|
title: i18n.t('payouts.title'),
|
|
25
24
|
searchParam: 'search',
|
|
@@ -50,7 +49,7 @@ defineTable<Payout>('seller-payouts', {
|
|
|
50
49
|
sortable: true,
|
|
51
50
|
filterable: true,
|
|
52
51
|
filterType: 'enum',
|
|
53
|
-
filterOptions:
|
|
52
|
+
filterOptions: SELLER_PAYOUT_STATUSES.map((status) => ({
|
|
54
53
|
value: status,
|
|
55
54
|
label: i18n.t(`earnings.statuses.${status}`),
|
|
56
55
|
})),
|
package/src/tables/products.tsx
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
|
+
import { PRODUCT_STATUSES } from '@spree/core'
|
|
1
2
|
import { defineTable, formatPrice } from '@spree/dashboard-core'
|
|
2
3
|
import { ResourceNameCell, StatusBadge, Thumbnail } from '@spree/dashboard-ui'
|
|
3
4
|
import { PackageIcon } from '@spree/dashboard-ui/icons'
|
|
4
5
|
import type { Product } from '@spree/seller-sdk'
|
|
5
6
|
import i18n from 'i18next'
|
|
6
7
|
|
|
7
|
-
/** Mirrors the operator dashboard's product statuses. */
|
|
8
|
-
const PRODUCT_STATUSES = ['active', 'draft', 'proposed', 'rejected', 'archived'] as const
|
|
9
|
-
|
|
10
8
|
defineTable<Product>('seller-products', {
|
|
11
9
|
title: i18n.t('products.title'),
|
|
12
10
|
searchParam: 'search',
|
package/src/tables/transfers.tsx
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SELLER_TRANSFER_KINDS, SELLER_TRANSFER_STATUSES } from '@spree/core'
|
|
1
2
|
import { defineTable, formatMoney, formatStoreDateTime, useTenantId } from '@spree/dashboard-core'
|
|
2
3
|
import { StatusBadge } from '@spree/dashboard-ui'
|
|
3
4
|
import { BanknoteIcon } from '@spree/dashboard-ui/icons'
|
|
@@ -43,9 +44,6 @@ function LedgerDate({ iso }: { iso: string }) {
|
|
|
43
44
|
return <>{formatStoreDateTime(iso, timezone)}</>
|
|
44
45
|
}
|
|
45
46
|
|
|
46
|
-
const STATUSES = ['pending', 'processing', 'completed', 'failed', 'unresolved'] as const
|
|
47
|
-
const KINDS = ['earning', 'refund_reversal'] as const
|
|
48
|
-
|
|
49
47
|
defineTable<Transfer>('seller-transfers', {
|
|
50
48
|
title: i18n.t('earnings.transfers.title'),
|
|
51
49
|
// Without this the toolbar sends `name_cont`, which the ledger does not
|
|
@@ -78,7 +76,7 @@ defineTable<Transfer>('seller-transfers', {
|
|
|
78
76
|
label: i18n.t('earnings.columns.kind'),
|
|
79
77
|
filterable: true,
|
|
80
78
|
filterType: 'enum',
|
|
81
|
-
filterOptions:
|
|
79
|
+
filterOptions: SELLER_TRANSFER_KINDS.map((kind) => ({
|
|
82
80
|
value: kind,
|
|
83
81
|
label: i18n.t(`earnings.kinds.${kind}`),
|
|
84
82
|
})),
|
|
@@ -93,7 +91,7 @@ defineTable<Transfer>('seller-transfers', {
|
|
|
93
91
|
sortable: true,
|
|
94
92
|
filterable: true,
|
|
95
93
|
filterType: 'enum',
|
|
96
|
-
filterOptions:
|
|
94
|
+
filterOptions: SELLER_TRANSFER_STATUSES.map((status) => ({
|
|
97
95
|
value: status,
|
|
98
96
|
label: i18n.t(`earnings.statuses.${status}`),
|
|
99
97
|
})),
|