@wilshop/dashboard 3.5.6 → 3.5.7
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/dist/plugin/dashboard.plugin.d.ts +1 -1
- package/dist/plugin/dashboard.plugin.js +1 -1
- package/dist/vite/utils/compiler.js +50 -24
- package/dist/vite/utils/path-transformer.d.ts +20 -0
- package/dist/vite/utils/path-transformer.js +116 -0
- package/dist/vite/utils/plugin-discovery.js +3 -2
- package/dist/vite/utils/ui-config.js +15 -1
- package/dist/vite/vite-plugin-lingui-babel.d.ts +15 -2
- package/dist/vite/vite-plugin-lingui-babel.js +90 -8
- package/dist/vite/vite-plugin-translations.js +2 -2
- package/dist/vite/vite-plugin-ui-config.d.ts +31 -0
- package/package.json +10 -6
- package/src/app/common/delete-bulk-action.tsx +1 -1
- package/src/app/common/duplicate-bulk-action.tsx +1 -1
- package/src/app/routes/_authenticated/_collections/collections.graphql.ts +1 -3
- package/src/app/routes/_authenticated/_collections/collections.tsx +169 -48
- package/src/app/routes/_authenticated/_collections/collections_.$id.tsx +36 -5
- package/src/app/routes/_authenticated/_collections/components/collection-bulk-actions.tsx +1 -1
- package/src/app/routes/_authenticated/_collections/components/collection-filters-selector.tsx +7 -1
- package/src/app/routes/_authenticated/_customers/components/customer-history/default-customer-history-components.tsx +31 -29
- package/src/app/routes/_authenticated/_customers/customers.graphql.ts +1 -0
- package/src/app/routes/_authenticated/_customers/customers.tsx +3 -0
- package/src/app/routes/_authenticated/_global-settings/global-settings.tsx +1 -1
- package/src/app/routes/_authenticated/_orders/components/draft-order-status.tsx +48 -0
- package/src/app/routes/_authenticated/_orders/components/fulfill-order-dialog.tsx +8 -5
- package/src/app/routes/_authenticated/_orders/components/order-detail-shared.tsx +79 -54
- package/src/app/routes/_authenticated/_orders/components/order-history/default-order-history-components.tsx +43 -3
- package/src/app/routes/_authenticated/_orders/components/order-history/order-history-utils.tsx +19 -3
- package/src/app/routes/_authenticated/_orders/components/order-table.tsx +1 -0
- package/src/app/routes/_authenticated/_orders/components/refund-order-dialog.tsx +372 -0
- package/src/app/routes/_authenticated/_orders/hooks/use-refund-order.ts +345 -0
- package/src/app/routes/_authenticated/_orders/orders.graphql.ts +41 -0
- package/src/app/routes/_authenticated/_orders/orders_.draft.$id.tsx +22 -6
- package/src/app/routes/_authenticated/_orders/utils/order-utils.ts +51 -0
- package/src/app/routes/_authenticated/_orders/utils/refund-utils.ts +100 -0
- package/src/app/routes/_authenticated/_orders/utils/use-modify-order.ts +1 -1
- package/src/app/routes/_authenticated/_payment-methods/components/payment-eligibility-checker-selector.tsx +4 -1
- package/src/app/routes/_authenticated/_payment-methods/components/payment-handler-selector.tsx +7 -1
- package/src/app/routes/_authenticated/_payment-methods/payment-methods_.$id.tsx +18 -2
- package/src/app/routes/_authenticated/_product-variants/components/product-variant-bulk-actions.tsx +1 -1
- package/src/app/routes/_authenticated/_product-variants/components/variant-price-detail.tsx +6 -2
- package/src/app/routes/_authenticated/_product-variants/product-variants.graphql.ts +9 -3
- package/src/app/routes/_authenticated/_product-variants/product-variants_.$id.tsx +49 -30
- package/src/app/routes/_authenticated/_products/components/product-bulk-actions.tsx +1 -1
- package/src/app/routes/_authenticated/_profile/profile.graphql.ts +7 -0
- package/src/app/routes/_authenticated/_profile/profile.tsx +25 -1
- package/src/app/routes/_authenticated/_promotions/components/promotion-actions-selector.tsx +7 -1
- package/src/app/routes/_authenticated/_promotions/components/promotion-conditions-selector.tsx +7 -1
- package/src/app/routes/_authenticated/_promotions/promotions_.$id.tsx +18 -2
- package/src/app/routes/_authenticated/_shipping-methods/components/shipping-calculator-selector.tsx +7 -1
- package/src/app/routes/_authenticated/_shipping-methods/components/shipping-eligibility-checker-selector.tsx +4 -1
- package/src/app/routes/_authenticated/_shipping-methods/shipping-methods_.$id.tsx +14 -2
- package/src/i18n/common-strings.ts +7 -0
- package/src/i18n/locales/ar.po +669 -399
- package/src/i18n/locales/bg.po +1889 -46
- package/src/i18n/locales/cs.po +676 -406
- package/src/i18n/locales/de.po +676 -406
- package/src/i18n/locales/en.po +669 -399
- package/src/i18n/locales/es.po +676 -406
- package/src/i18n/locales/fa.po +676 -406
- package/src/i18n/locales/fr.po +676 -406
- package/src/i18n/locales/he.po +676 -406
- package/src/i18n/locales/hr.po +676 -406
- package/src/i18n/locales/it.po +676 -406
- package/src/i18n/locales/ja.po +676 -406
- package/src/i18n/locales/nb.po +676 -406
- package/src/i18n/locales/ne.po +676 -406
- package/src/i18n/locales/pl.po +676 -406
- package/src/i18n/locales/pt_BR.po +676 -406
- package/src/i18n/locales/pt_PT.po +676 -406
- package/src/i18n/locales/ru.po +676 -406
- package/src/i18n/locales/sv.po +676 -406
- package/src/i18n/locales/tr.po +676 -406
- package/src/i18n/locales/uk.po +676 -406
- package/src/i18n/locales/zh_Hans.po +676 -406
- package/src/i18n/locales/zh_Hant.po +676 -406
- package/src/lib/components/data-input/facet-value-input.tsx +2 -2
- package/src/lib/components/data-input/index.ts +1 -0
- package/src/lib/components/data-input/select-with-options.tsx +23 -7
- package/src/lib/components/data-input/struct-form-input.tsx +53 -21
- package/src/lib/components/data-input/text-input.tsx +1 -1
- package/src/lib/components/data-table/data-table-bulk-actions.tsx +2 -1
- package/src/lib/components/data-table/data-table-context.tsx +2 -10
- package/src/lib/components/data-table/data-table-utils.ts +34 -12
- package/src/lib/components/data-table/data-table.tsx +68 -30
- package/src/lib/components/data-table/global-views-bar.tsx +1 -1
- package/src/lib/components/data-table/my-views-button.tsx +1 -1
- package/src/lib/components/data-table/save-view-button.tsx +1 -1
- package/src/lib/components/data-table/use-generated-columns.tsx +9 -2
- package/src/lib/components/data-table/views-sheet.tsx +1 -1
- package/src/lib/components/layout/channel-switcher.tsx +16 -17
- package/src/lib/components/layout/manage-languages-dialog.tsx +1 -1
- package/src/lib/components/shared/assign-to-channel-bulk-action.tsx +1 -1
- package/src/lib/components/shared/configurable-operation-input.tsx +23 -0
- package/src/lib/components/shared/configurable-operation-multi-selector.tsx +45 -0
- package/src/lib/components/shared/configurable-operation-selector.tsx +5 -0
- package/src/lib/components/shared/paginated-list-context.ts +10 -0
- package/src/lib/components/shared/paginated-list-data-table.tsx +6 -32
- package/src/lib/components/shared/remove-from-channel-bulk-action.tsx +1 -1
- package/src/lib/components/ui/alert.tsx +2 -0
- package/src/lib/constants.ts +7 -319
- package/src/lib/framework/dashboard-widget/base-widget.tsx +3 -12
- package/src/lib/framework/dashboard-widget/latest-orders-widget/index.tsx +1 -1
- package/src/lib/framework/dashboard-widget/metrics-widget/chart.tsx +1 -1
- package/src/lib/framework/dashboard-widget/metrics-widget/index.tsx +1 -1
- package/src/lib/framework/dashboard-widget/orders-summary/index.tsx +1 -1
- package/src/lib/framework/dashboard-widget/widget-filters-context.tsx +2 -20
- package/src/lib/framework/extension-api/input-component-extensions.tsx +4 -0
- package/src/lib/framework/form-engine/custom-form-component.tsx +13 -3
- package/src/lib/framework/form-engine/form-engine-types.ts +3 -5
- package/src/lib/framework/form-engine/form-schema-tools.ts +4 -1
- package/src/lib/framework/form-engine/use-generated-form.tsx +6 -2
- package/src/lib/framework/form-engine/utils.spec.ts +129 -2
- package/src/lib/framework/form-engine/utils.ts +36 -9
- package/src/lib/framework/form-engine/value-transformers.ts +6 -0
- package/src/lib/framework/page/detail-page-route-loader.tsx +6 -4
- package/src/lib/framework/page/detail-page.tsx +22 -37
- package/src/lib/framework/page/list-page.stories.tsx +41 -2
- package/src/lib/framework/page/list-page.tsx +8 -0
- package/src/lib/graphql/graphql-env.d.ts +33 -16
- package/src/lib/graphql/schema-enums.ts +13 -0
- package/src/lib/hooks/use-alerts-context.ts +10 -0
- package/src/lib/hooks/use-alerts.ts +1 -1
- package/src/lib/hooks/use-data-table-context.ts +11 -0
- package/src/lib/hooks/use-dynamic-translations.ts +7 -0
- package/src/lib/hooks/use-job-queue-polling.ts +160 -0
- package/src/lib/hooks/use-paginated-list.ts +28 -0
- package/src/lib/hooks/use-widget-dimensions.ts +12 -0
- package/src/lib/hooks/use-widget-filters.ts +21 -0
- package/src/lib/index.ts +12 -0
- package/src/lib/providers/alerts-provider.tsx +3 -11
- package/src/lib/virtual.d.ts +5 -0
- package/src/lib/utils/global-languages.ts +0 -268
|
@@ -21,6 +21,7 @@ import { detailPageRouteLoader } from '@/vdb/framework/page/detail-page-route-lo
|
|
|
21
21
|
import { useDetailPage } from '@/vdb/framework/page/use-detail-page.js';
|
|
22
22
|
import { Trans, useLingui } from '@lingui/react/macro';
|
|
23
23
|
import { createFileRoute, useNavigate } from '@tanstack/react-router';
|
|
24
|
+
import { useState } from 'react';
|
|
24
25
|
import { toast } from 'sonner';
|
|
25
26
|
import { PaymentEligibilityCheckerSelector } from './components/payment-eligibility-checker-selector.js';
|
|
26
27
|
import { PaymentHandlerSelector } from './components/payment-handler-selector.js';
|
|
@@ -82,6 +83,7 @@ function PaymentMethodDetailPage() {
|
|
|
82
83
|
languageCode: translation.languageCode,
|
|
83
84
|
name: translation.name,
|
|
84
85
|
description: translation.description,
|
|
86
|
+
customFields: (translation as any).customFields,
|
|
85
87
|
})),
|
|
86
88
|
customFields: entity.customFields,
|
|
87
89
|
};
|
|
@@ -115,6 +117,9 @@ function PaymentMethodDetailPage() {
|
|
|
115
117
|
},
|
|
116
118
|
});
|
|
117
119
|
|
|
120
|
+
const [checkerArgsValid, setCheckerArgsValid] = useState(true);
|
|
121
|
+
const [handlerArgsValid, setHandlerArgsValid] = useState(true);
|
|
122
|
+
|
|
118
123
|
return (
|
|
119
124
|
<Page pageId={pageId} form={form} submitHandler={submitHandler} entity={entity}>
|
|
120
125
|
<PageTitle>
|
|
@@ -125,7 +130,13 @@ function PaymentMethodDetailPage() {
|
|
|
125
130
|
<PermissionGuard requires={['UpdatePaymentMethod']}>
|
|
126
131
|
<Button
|
|
127
132
|
type="submit"
|
|
128
|
-
disabled={
|
|
133
|
+
disabled={
|
|
134
|
+
!form.formState.isDirty ||
|
|
135
|
+
!form.formState.isValid ||
|
|
136
|
+
isPending ||
|
|
137
|
+
!checkerArgsValid ||
|
|
138
|
+
!handlerArgsValid
|
|
139
|
+
}
|
|
129
140
|
>
|
|
130
141
|
{creatingNewEntity ? <Trans>Create</Trans> : <Trans>Update</Trans>}
|
|
131
142
|
</Button>
|
|
@@ -178,6 +189,7 @@ function PaymentMethodDetailPage() {
|
|
|
178
189
|
<PaymentEligibilityCheckerSelector
|
|
179
190
|
value={field.value}
|
|
180
191
|
onChange={field.onChange}
|
|
192
|
+
onValidityChange={setCheckerArgsValid}
|
|
181
193
|
/>
|
|
182
194
|
)}
|
|
183
195
|
/>
|
|
@@ -187,7 +199,11 @@ function PaymentMethodDetailPage() {
|
|
|
187
199
|
control={form.control}
|
|
188
200
|
name="handler"
|
|
189
201
|
render={({ field }) => (
|
|
190
|
-
<PaymentHandlerSelector
|
|
202
|
+
<PaymentHandlerSelector
|
|
203
|
+
value={field.value}
|
|
204
|
+
onChange={field.onChange}
|
|
205
|
+
onValidityChange={setHandlerArgsValid}
|
|
206
|
+
/>
|
|
191
207
|
)}
|
|
192
208
|
/>
|
|
193
209
|
</PageBlock>
|
package/src/app/routes/_authenticated/_product-variants/components/product-variant-bulk-actions.tsx
CHANGED
|
@@ -4,7 +4,7 @@ import { useState } from 'react';
|
|
|
4
4
|
import { DataTableBulkActionItem } from '@/vdb/components/data-table/data-table-bulk-action-item.js';
|
|
5
5
|
import { AssignToChannelBulkAction } from '@/vdb/components/shared/assign-to-channel-bulk-action.js';
|
|
6
6
|
import { usePriceFactor } from '@/vdb/components/shared/assign-to-channel-dialog.js';
|
|
7
|
-
import { usePaginatedList } from '@/vdb/
|
|
7
|
+
import { usePaginatedList } from '@/vdb/hooks/use-paginated-list.js';
|
|
8
8
|
import { RemoveFromChannelBulkAction } from '@/vdb/components/shared/remove-from-channel-bulk-action.js';
|
|
9
9
|
import { BulkActionComponent } from '@/vdb/framework/extension-api/types/data-table.js';
|
|
10
10
|
import { api } from '@/vdb/graphql/api.js';
|
|
@@ -70,8 +70,12 @@ export function VariantPriceDetail({
|
|
|
70
70
|
}, [taxRatesData, activeChannel, taxCategoryId]);
|
|
71
71
|
|
|
72
72
|
useEffect(() => {
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
if (priceIncludesTax) {
|
|
74
|
+
setGrossPrice(price ?? 0);
|
|
75
|
+
} else {
|
|
76
|
+
setGrossPrice(Math.round((price ?? 0) * ((100 + taxRate) / 100)));
|
|
77
|
+
}
|
|
78
|
+
}, [price, taxRate, priceIncludesTax]);
|
|
75
79
|
|
|
76
80
|
return (
|
|
77
81
|
<div className="space-y-1">
|
|
@@ -32,6 +32,13 @@ export const productVariantListDocument = graphql(
|
|
|
32
32
|
[assetFragment],
|
|
33
33
|
);
|
|
34
34
|
|
|
35
|
+
export const productVariantPriceFragment = graphql(`
|
|
36
|
+
fragment ProductVariantPrice on ProductVariantPrice {
|
|
37
|
+
currencyCode
|
|
38
|
+
price
|
|
39
|
+
}
|
|
40
|
+
`);
|
|
41
|
+
|
|
35
42
|
export const productVariantDetailDocument = graphql(
|
|
36
43
|
`
|
|
37
44
|
query ProductVariantDetail($id: ID!) {
|
|
@@ -86,8 +93,7 @@ export const productVariantDetailDocument = graphql(
|
|
|
86
93
|
price
|
|
87
94
|
priceWithTax
|
|
88
95
|
prices {
|
|
89
|
-
|
|
90
|
-
price
|
|
96
|
+
...ProductVariantPrice
|
|
91
97
|
}
|
|
92
98
|
trackInventory
|
|
93
99
|
outOfStockThreshold
|
|
@@ -105,7 +111,7 @@ export const productVariantDetailDocument = graphql(
|
|
|
105
111
|
}
|
|
106
112
|
}
|
|
107
113
|
`,
|
|
108
|
-
[assetFragment],
|
|
114
|
+
[assetFragment, productVariantPriceFragment],
|
|
109
115
|
);
|
|
110
116
|
|
|
111
117
|
export const createProductVariantDocument = graphql(`
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { MoneyInput } from '@/vdb/components/data-input/money-input.js';
|
|
2
2
|
import { NumberInput } from '@/vdb/components/data-input/number-input.js';
|
|
3
3
|
import { AssignedFacetValues } from '@/vdb/components/shared/assigned-facet-values.js';
|
|
4
|
+
import { CustomFieldsForm } from '@/vdb/components/shared/custom-fields-form.js';
|
|
4
5
|
import { DetailPageButton } from '@/vdb/components/shared/detail-page-button.js';
|
|
5
6
|
import { EntityAssets } from '@/vdb/components/shared/entity-assets.js';
|
|
6
7
|
import { ErrorPage } from '@/vdb/components/shared/error-page.js';
|
|
@@ -12,8 +13,10 @@ import { Button } from '@/vdb/components/ui/button.js';
|
|
|
12
13
|
import { FormControl, FormDescription, FormItem, FormLabel, FormMessage } from '@/vdb/components/ui/form.js';
|
|
13
14
|
import { Input } from '@/vdb/components/ui/input.js';
|
|
14
15
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/vdb/components/ui/select.js';
|
|
16
|
+
import { Separator } from '@/vdb/components/ui/separator.js';
|
|
15
17
|
import { Switch } from '@/vdb/components/ui/switch.js';
|
|
16
18
|
import { NEW_ENTITY_PATH } from '@/vdb/constants.js';
|
|
19
|
+
import { addCustomFields } from '@/vdb/framework/document-introspection/add-custom-fields.js';
|
|
17
20
|
import {
|
|
18
21
|
CustomFieldsPageBlock,
|
|
19
22
|
DetailFormGrid,
|
|
@@ -34,6 +37,7 @@ import { createFileRoute, useNavigate } from '@tanstack/react-router';
|
|
|
34
37
|
import { VariablesOf } from 'gql.tada';
|
|
35
38
|
import { Trash } from 'lucide-react';
|
|
36
39
|
import { toast } from 'sonner';
|
|
40
|
+
|
|
37
41
|
import { AddCurrencyDropdown } from './components/add-currency-dropdown.js';
|
|
38
42
|
import { AddStockLocationDropdown } from './components/add-stock-location-dropdown.js';
|
|
39
43
|
import { VariantPriceDetail } from './components/variant-price-detail.js';
|
|
@@ -50,7 +54,10 @@ export const Route = createFileRoute('/_authenticated/_product-variants/product-
|
|
|
50
54
|
component: ProductVariantDetailPage,
|
|
51
55
|
loader: detailPageRouteLoader({
|
|
52
56
|
pageId,
|
|
53
|
-
queryDocument:
|
|
57
|
+
queryDocument: () =>
|
|
58
|
+
addCustomFields(productVariantDetailDocument, {
|
|
59
|
+
includeNestedFragments: ['ProductVariantPrice'],
|
|
60
|
+
}),
|
|
54
61
|
breadcrumb(_isNew, entity, location) {
|
|
55
62
|
if ((location.search as any).from === 'product') {
|
|
56
63
|
return [
|
|
@@ -81,7 +88,9 @@ function ProductVariantDetailPage() {
|
|
|
81
88
|
|
|
82
89
|
const { form, submitHandler, entity, isPending, resetForm } = useDetailPage({
|
|
83
90
|
pageId,
|
|
84
|
-
queryDocument: productVariantDetailDocument,
|
|
91
|
+
queryDocument: addCustomFields(productVariantDetailDocument, {
|
|
92
|
+
includeNestedFragments: ['ProductVariantPrice'],
|
|
93
|
+
}),
|
|
85
94
|
createDocument: createProductVariantDocument,
|
|
86
95
|
updateDocument: updateProductVariantDocument,
|
|
87
96
|
setValuesForUpdate: entity => {
|
|
@@ -169,6 +178,7 @@ function ProductVariantDetailPage() {
|
|
|
169
178
|
currencyCode,
|
|
170
179
|
price: 0,
|
|
171
180
|
delete: false,
|
|
181
|
+
customFields: {},
|
|
172
182
|
} as PriceInput;
|
|
173
183
|
form.setValue('prices', [...currentPrices, newPrice], {
|
|
174
184
|
shouldDirty: true,
|
|
@@ -274,37 +284,46 @@ function ProductVariantDetailPage() {
|
|
|
274
284
|
</div>
|
|
275
285
|
);
|
|
276
286
|
return (
|
|
277
|
-
<
|
|
278
|
-
<
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
287
|
+
<div key={price.currencyCode} className="space-y-6">
|
|
288
|
+
{displayIndex > 0 && <Separator className="my-4" />}
|
|
289
|
+
<DetailFormGrid key={price.currencyCode}>
|
|
290
|
+
<div className="flex gap-1 items-end">
|
|
291
|
+
<FormFieldWrapper
|
|
292
|
+
control={form.control}
|
|
293
|
+
name={`prices.${actualIndex}.price`}
|
|
294
|
+
label={priceLabel}
|
|
295
|
+
render={({ field }) => (
|
|
296
|
+
<MoneyInput {...field} currency={price.currencyCode} />
|
|
297
|
+
)}
|
|
298
|
+
/>
|
|
299
|
+
{activePrices.length > 1 && (
|
|
300
|
+
<Button
|
|
301
|
+
type="button"
|
|
302
|
+
variant="ghost"
|
|
303
|
+
size="sm"
|
|
304
|
+
onClick={() => handleRemoveCurrency(actualIndex)}
|
|
305
|
+
className="h-6 w-6 p-0 mb-2 hover:text-destructive hover:bg-destructive-100"
|
|
306
|
+
>
|
|
307
|
+
<Trash className="size-4" />
|
|
308
|
+
</Button>
|
|
285
309
|
)}
|
|
310
|
+
</div>
|
|
311
|
+
<VariantPriceDetail
|
|
312
|
+
priceIncludesTax={activeChannel?.pricesIncludeTax ?? false}
|
|
313
|
+
price={price.price}
|
|
314
|
+
currencyCode={
|
|
315
|
+
price.currencyCode ?? activeChannel?.defaultCurrencyCode ?? ''
|
|
316
|
+
}
|
|
317
|
+
taxCategoryId={taxCategoryId}
|
|
286
318
|
/>
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
className="h-6 w-6 p-0 mb-2 hover:text-destructive hover:bg-destructive-100"
|
|
294
|
-
>
|
|
295
|
-
<Trash className="size-4" />
|
|
296
|
-
</Button>
|
|
297
|
-
)}
|
|
298
|
-
</div>
|
|
299
|
-
<VariantPriceDetail
|
|
300
|
-
priceIncludesTax={activeChannel?.pricesIncludeTax ?? false}
|
|
301
|
-
price={price.price}
|
|
302
|
-
currencyCode={
|
|
303
|
-
price.currencyCode ?? activeChannel?.defaultCurrencyCode ?? ''
|
|
304
|
-
}
|
|
305
|
-
taxCategoryId={taxCategoryId}
|
|
319
|
+
</DetailFormGrid>
|
|
320
|
+
{/* Custom fields for ProductVariantPrice */}
|
|
321
|
+
<CustomFieldsForm
|
|
322
|
+
entityType="ProductVariantPrice"
|
|
323
|
+
control={form.control}
|
|
324
|
+
formPathPrefix={`prices.${actualIndex}`}
|
|
306
325
|
/>
|
|
307
|
-
</
|
|
326
|
+
</div>
|
|
308
327
|
);
|
|
309
328
|
})}
|
|
310
329
|
{unusedCurrencies.length ? (
|
|
@@ -4,7 +4,7 @@ import { useState } from 'react';
|
|
|
4
4
|
import { DataTableBulkActionItem } from '@/vdb/components/data-table/data-table-bulk-action-item.js';
|
|
5
5
|
import { AssignToChannelBulkAction } from '@/vdb/components/shared/assign-to-channel-bulk-action.js';
|
|
6
6
|
import { usePriceFactor } from '@/vdb/components/shared/assign-to-channel-dialog.js';
|
|
7
|
-
import { usePaginatedList } from '@/vdb/
|
|
7
|
+
import { usePaginatedList } from '@/vdb/hooks/use-paginated-list.js';
|
|
8
8
|
import { RemoveFromChannelBulkAction } from '@/vdb/components/shared/remove-from-channel-bulk-action.js';
|
|
9
9
|
import { BulkActionComponent } from '@/vdb/framework/extension-api/types/data-table.js';
|
|
10
10
|
import { api } from '@/vdb/graphql/api.js';
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ErrorPage } from '@/vdb/components/shared/error-page.js';
|
|
2
2
|
import { FormFieldWrapper } from '@/vdb/components/shared/form-field-wrapper.js';
|
|
3
|
+
import { Badge } from '@/vdb/components/ui/badge.js';
|
|
3
4
|
import { Button } from '@/vdb/components/ui/button.js';
|
|
4
5
|
import { Input } from '@/vdb/components/ui/input.js';
|
|
5
6
|
import {
|
|
@@ -14,6 +15,7 @@ import {
|
|
|
14
15
|
} from '@/vdb/framework/layout-engine/page-layout.js';
|
|
15
16
|
import { useDetailPage } from '@/vdb/framework/page/use-detail-page.js';
|
|
16
17
|
import { api } from '@/vdb/graphql/api.js';
|
|
18
|
+
import { useLocalFormat } from '@/vdb/hooks/use-local-format.js';
|
|
17
19
|
import { Trans, useLingui } from '@lingui/react/macro';
|
|
18
20
|
import { createFileRoute } from '@tanstack/react-router';
|
|
19
21
|
import { toast } from 'sonner';
|
|
@@ -35,8 +37,9 @@ export const Route = createFileRoute('/_authenticated/_profile/profile')({
|
|
|
35
37
|
|
|
36
38
|
function ProfilePage() {
|
|
37
39
|
const { t } = useLingui();
|
|
40
|
+
const { formatDate } = useLocalFormat();
|
|
38
41
|
|
|
39
|
-
const { form, submitHandler, isPending } = useDetailPage({
|
|
42
|
+
const { form, submitHandler, isPending, entity } = useDetailPage({
|
|
40
43
|
queryDocument: activeAdministratorDocument,
|
|
41
44
|
entityField: 'activeAdministrator',
|
|
42
45
|
updateDocument: updateAdministratorDocument,
|
|
@@ -112,6 +115,27 @@ function ProfilePage() {
|
|
|
112
115
|
/>
|
|
113
116
|
</DetailFormGrid>
|
|
114
117
|
</PageBlock>
|
|
118
|
+
<PageBlock
|
|
119
|
+
column="side"
|
|
120
|
+
blockId="auth-methods"
|
|
121
|
+
title={<Trans>Authentication methods</Trans>}
|
|
122
|
+
>
|
|
123
|
+
<div className="space-y-2">
|
|
124
|
+
{entity?.user?.authenticationMethods.map(method => (
|
|
125
|
+
<div
|
|
126
|
+
key={method.id}
|
|
127
|
+
className="flex items-center justify-between py-2 border-b last:border-b-0"
|
|
128
|
+
>
|
|
129
|
+
<Badge variant="secondary">
|
|
130
|
+
{method.strategy === 'native' ? t`Password` : method.strategy}
|
|
131
|
+
</Badge>
|
|
132
|
+
<span className="text-sm text-muted-foreground">
|
|
133
|
+
<Trans>Added</Trans> {formatDate(method.createdAt)}
|
|
134
|
+
</span>
|
|
135
|
+
</div>
|
|
136
|
+
))}
|
|
137
|
+
</div>
|
|
138
|
+
</PageBlock>
|
|
115
139
|
<CustomFieldsPageBlock column="main" entityType="Administrator" control={form.control} />
|
|
116
140
|
</PageLayout>
|
|
117
141
|
</Page>
|
|
@@ -17,9 +17,14 @@ export const promotionActionsDocument = graphql(
|
|
|
17
17
|
interface PromotionActionsSelectorProps {
|
|
18
18
|
value: ConfigurableOperationInputType[];
|
|
19
19
|
onChange: (value: ConfigurableOperationInputType[]) => void;
|
|
20
|
+
onValidityChange?: (isValid: boolean) => void;
|
|
20
21
|
}
|
|
21
22
|
|
|
22
|
-
export function PromotionActionsSelector({
|
|
23
|
+
export function PromotionActionsSelector({
|
|
24
|
+
value,
|
|
25
|
+
onChange,
|
|
26
|
+
onValidityChange,
|
|
27
|
+
}: Readonly<PromotionActionsSelectorProps>) {
|
|
23
28
|
return (
|
|
24
29
|
<ConfigurableOperationMultiSelector
|
|
25
30
|
value={value}
|
|
@@ -30,6 +35,7 @@ export function PromotionActionsSelector({ value, onChange }: Readonly<Promotion
|
|
|
30
35
|
buttonText="Add action"
|
|
31
36
|
dropdownTitle="Available Actions"
|
|
32
37
|
showEnhancedDropdown={true}
|
|
38
|
+
onValidityChange={onValidityChange}
|
|
33
39
|
/>
|
|
34
40
|
);
|
|
35
41
|
}
|
package/src/app/routes/_authenticated/_promotions/components/promotion-conditions-selector.tsx
CHANGED
|
@@ -17,9 +17,14 @@ export const promotionConditionsDocument = graphql(
|
|
|
17
17
|
interface PromotionConditionsSelectorProps {
|
|
18
18
|
value: ConfigurableOperationInputType[];
|
|
19
19
|
onChange: (value: ConfigurableOperationInputType[]) => void;
|
|
20
|
+
onValidityChange?: (isValid: boolean) => void;
|
|
20
21
|
}
|
|
21
22
|
|
|
22
|
-
export function PromotionConditionsSelector({
|
|
23
|
+
export function PromotionConditionsSelector({
|
|
24
|
+
value,
|
|
25
|
+
onChange,
|
|
26
|
+
onValidityChange,
|
|
27
|
+
}: Readonly<PromotionConditionsSelectorProps>) {
|
|
23
28
|
return (
|
|
24
29
|
<ConfigurableOperationMultiSelector
|
|
25
30
|
value={value}
|
|
@@ -30,6 +35,7 @@ export function PromotionConditionsSelector({ value, onChange }: Readonly<Promot
|
|
|
30
35
|
buttonText="Add condition"
|
|
31
36
|
dropdownTitle="Available Conditions"
|
|
32
37
|
showEnhancedDropdown={true}
|
|
38
|
+
onValidityChange={onValidityChange}
|
|
33
39
|
/>
|
|
34
40
|
);
|
|
35
41
|
}
|
|
@@ -23,6 +23,7 @@ import { detailPageRouteLoader } from '@/vdb/framework/page/detail-page-route-lo
|
|
|
23
23
|
import { useDetailPage } from '@/vdb/framework/page/use-detail-page.js';
|
|
24
24
|
import { Trans, useLingui } from '@lingui/react/macro';
|
|
25
25
|
import { createFileRoute, useNavigate } from '@tanstack/react-router';
|
|
26
|
+
import { useState } from 'react';
|
|
26
27
|
import { toast } from 'sonner';
|
|
27
28
|
import { PromotionActionsSelector } from './components/promotion-actions-selector.js';
|
|
28
29
|
import { PromotionConditionsSelector } from './components/promotion-conditions-selector.js';
|
|
@@ -93,6 +94,7 @@ function PromotionDetailPage() {
|
|
|
93
94
|
languageCode: translation.languageCode,
|
|
94
95
|
name: translation.name,
|
|
95
96
|
description: translation.description,
|
|
97
|
+
customFields: (translation as any).customFields,
|
|
96
98
|
})),
|
|
97
99
|
customFields: entity.customFields,
|
|
98
100
|
};
|
|
@@ -123,6 +125,9 @@ function PromotionDetailPage() {
|
|
|
123
125
|
},
|
|
124
126
|
});
|
|
125
127
|
|
|
128
|
+
const [conditionsArgsValid, setConditionsArgsValid] = useState(true);
|
|
129
|
+
const [actionsArgsValid, setActionsArgsValid] = useState(true);
|
|
130
|
+
|
|
126
131
|
return (
|
|
127
132
|
<Page pageId={pageId} form={form} submitHandler={submitHandler} entity={entity}>
|
|
128
133
|
<PageTitle>{creatingNewEntity ? <Trans>New promotion</Trans> : (entity?.name ?? '')}</PageTitle>
|
|
@@ -131,7 +136,13 @@ function PromotionDetailPage() {
|
|
|
131
136
|
<PermissionGuard requires={['UpdatePromotion']}>
|
|
132
137
|
<Button
|
|
133
138
|
type="submit"
|
|
134
|
-
disabled={
|
|
139
|
+
disabled={
|
|
140
|
+
!form.formState.isDirty ||
|
|
141
|
+
!form.formState.isValid ||
|
|
142
|
+
isPending ||
|
|
143
|
+
!conditionsArgsValid ||
|
|
144
|
+
!actionsArgsValid
|
|
145
|
+
}
|
|
135
146
|
>
|
|
136
147
|
{creatingNewEntity ? <Trans>Create</Trans> : <Trans>Update</Trans>}
|
|
137
148
|
</Button>
|
|
@@ -226,6 +237,7 @@ function PromotionDetailPage() {
|
|
|
226
237
|
<PromotionConditionsSelector
|
|
227
238
|
value={field.value ?? []}
|
|
228
239
|
onChange={field.onChange}
|
|
240
|
+
onValidityChange={setConditionsArgsValid}
|
|
229
241
|
/>
|
|
230
242
|
)}
|
|
231
243
|
/>
|
|
@@ -235,7 +247,11 @@ function PromotionDetailPage() {
|
|
|
235
247
|
control={form.control}
|
|
236
248
|
name="actions"
|
|
237
249
|
render={({ field }) => (
|
|
238
|
-
<PromotionActionsSelector
|
|
250
|
+
<PromotionActionsSelector
|
|
251
|
+
value={field.value ?? []}
|
|
252
|
+
onChange={field.onChange}
|
|
253
|
+
onValidityChange={setActionsArgsValid}
|
|
254
|
+
/>
|
|
239
255
|
)}
|
|
240
256
|
/>
|
|
241
257
|
</PageBlock>
|
package/src/app/routes/_authenticated/_shipping-methods/components/shipping-calculator-selector.tsx
CHANGED
|
@@ -17,9 +17,14 @@ export const shippingCalculatorsDocument = graphql(
|
|
|
17
17
|
interface ShippingCalculatorSelectorProps {
|
|
18
18
|
value: ConfigurableOperationInputType | undefined;
|
|
19
19
|
onChange: (value: ConfigurableOperationInputType | undefined) => void;
|
|
20
|
+
onValidityChange?: (isValid: boolean) => void;
|
|
20
21
|
}
|
|
21
22
|
|
|
22
|
-
export function ShippingCalculatorSelector({
|
|
23
|
+
export function ShippingCalculatorSelector({
|
|
24
|
+
value,
|
|
25
|
+
onChange,
|
|
26
|
+
onValidityChange,
|
|
27
|
+
}: Readonly<ShippingCalculatorSelectorProps>) {
|
|
23
28
|
return (
|
|
24
29
|
<ConfigurableOperationSelector
|
|
25
30
|
value={value}
|
|
@@ -28,6 +33,7 @@ export function ShippingCalculatorSelector({ value, onChange }: Readonly<Shippin
|
|
|
28
33
|
queryKey="shippingCalculators"
|
|
29
34
|
dataPath="shippingCalculators"
|
|
30
35
|
buttonText="Select Shipping Calculator"
|
|
36
|
+
onValidityChange={onValidityChange}
|
|
31
37
|
/>
|
|
32
38
|
);
|
|
33
39
|
}
|
|
@@ -17,12 +17,14 @@ export const shippingEligibilityCheckersDocument = graphql(
|
|
|
17
17
|
interface ShippingEligibilityCheckerSelectorProps {
|
|
18
18
|
value: ConfigurableOperationInputType | undefined;
|
|
19
19
|
onChange: (value: ConfigurableOperationInputType | undefined) => void;
|
|
20
|
+
onValidityChange?: (isValid: boolean) => void;
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
export function ShippingEligibilityCheckerSelector({
|
|
23
24
|
value,
|
|
24
25
|
onChange,
|
|
25
|
-
|
|
26
|
+
onValidityChange,
|
|
27
|
+
}: Readonly<ShippingEligibilityCheckerSelectorProps>) {
|
|
26
28
|
return (
|
|
27
29
|
<ConfigurableOperationSelector
|
|
28
30
|
value={value}
|
|
@@ -31,6 +33,7 @@ export function ShippingEligibilityCheckerSelector({
|
|
|
31
33
|
queryKey="shippingEligibilityCheckers"
|
|
32
34
|
dataPath="shippingEligibilityCheckers"
|
|
33
35
|
buttonText="Select Shipping Eligibility Checker"
|
|
36
|
+
onValidityChange={onValidityChange}
|
|
34
37
|
/>
|
|
35
38
|
);
|
|
36
39
|
}
|
|
@@ -20,6 +20,7 @@ import { detailPageRouteLoader } from '@/vdb/framework/page/detail-page-route-lo
|
|
|
20
20
|
import { useDetailPage } from '@/vdb/framework/page/use-detail-page.js';
|
|
21
21
|
import { Trans, useLingui } from '@lingui/react/macro';
|
|
22
22
|
import { createFileRoute, useNavigate } from '@tanstack/react-router';
|
|
23
|
+
import { useState } from 'react';
|
|
23
24
|
import { toast } from 'sonner';
|
|
24
25
|
import { FulfillmentHandlerSelector } from './components/fulfillment-handler-selector.js';
|
|
25
26
|
import { ShippingCalculatorSelector } from './components/shipping-calculator-selector.js';
|
|
@@ -79,6 +80,7 @@ function ShippingMethodDetailPage() {
|
|
|
79
80
|
languageCode: translation.languageCode,
|
|
80
81
|
name: translation.name,
|
|
81
82
|
description: translation.description,
|
|
83
|
+
customFields: (translation as any).customFields,
|
|
82
84
|
})),
|
|
83
85
|
customFields: entity.customFields,
|
|
84
86
|
};
|
|
@@ -108,6 +110,9 @@ function ShippingMethodDetailPage() {
|
|
|
108
110
|
const checker = form.watch('checker');
|
|
109
111
|
const calculator = form.watch('calculator');
|
|
110
112
|
|
|
113
|
+
const [checkerArgsValid, setCheckerArgsValid] = useState(true);
|
|
114
|
+
const [calculatorArgsValid, setCalculatorArgsValid] = useState(true);
|
|
115
|
+
|
|
111
116
|
return (
|
|
112
117
|
<Page pageId={pageId} form={form} submitHandler={submitHandler} entity={entity}>
|
|
113
118
|
<PageTitle>
|
|
@@ -126,7 +131,9 @@ function ShippingMethodDetailPage() {
|
|
|
126
131
|
!form.formState.isValid ||
|
|
127
132
|
isPending ||
|
|
128
133
|
!checker?.code ||
|
|
129
|
-
!calculator?.code
|
|
134
|
+
!calculator?.code ||
|
|
135
|
+
!checkerArgsValid ||
|
|
136
|
+
!calculatorArgsValid
|
|
130
137
|
}
|
|
131
138
|
>
|
|
132
139
|
{creatingNewEntity ? <Trans>Create</Trans> : <Trans>Update</Trans>}
|
|
@@ -178,6 +185,7 @@ function ShippingMethodDetailPage() {
|
|
|
178
185
|
<ShippingEligibilityCheckerSelector
|
|
179
186
|
value={field.value}
|
|
180
187
|
onChange={field.onChange}
|
|
188
|
+
onValidityChange={setCheckerArgsValid}
|
|
181
189
|
/>
|
|
182
190
|
)}
|
|
183
191
|
/>
|
|
@@ -187,7 +195,11 @@ function ShippingMethodDetailPage() {
|
|
|
187
195
|
control={form.control}
|
|
188
196
|
name="calculator"
|
|
189
197
|
render={({ field }) => (
|
|
190
|
-
<ShippingCalculatorSelector
|
|
198
|
+
<ShippingCalculatorSelector
|
|
199
|
+
value={field.value}
|
|
200
|
+
onChange={field.onChange}
|
|
201
|
+
onValidityChange={setCalculatorArgsValid}
|
|
202
|
+
/>
|
|
191
203
|
)}
|
|
192
204
|
/>
|
|
193
205
|
</PageBlock>
|
|
@@ -39,6 +39,13 @@ const commonI18nString = {
|
|
|
39
39
|
/* i18n*/ 'orderState.Modifying',
|
|
40
40
|
/* i18n*/ 'orderState.ArrangingAdditionalPayment',
|
|
41
41
|
],
|
|
42
|
+
refundReason: [
|
|
43
|
+
/* i18n*/ 'refundReason.CustomerRequest',
|
|
44
|
+
/* i18n*/ 'refundReason.NotAvailable',
|
|
45
|
+
/* i18n*/ 'refundReason.DamagedInShipping',
|
|
46
|
+
/* i18n*/ 'refundReason.WrongItem',
|
|
47
|
+
/* i18n*/ 'refundReason.Other',
|
|
48
|
+
],
|
|
42
49
|
fieldName: [
|
|
43
50
|
/* i18n*/ 'fieldName.attempts',
|
|
44
51
|
/* i18n*/ 'fieldName.availableCurrencyCodes',
|