@wilshop/dashboard 3.5.5 → 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 +92 -17
- 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
|
@@ -44,6 +44,7 @@ export function FulfillOrderDialog({ order, onSuccess }: Readonly<FulfillOrderDi
|
|
|
44
44
|
const [fulfillmentQuantities, setFulfillmentQuantities] = useState<{
|
|
45
45
|
[lineId: string]: FulfillmentQuantity;
|
|
46
46
|
}>({});
|
|
47
|
+
const [handlerArgsValid, setHandlerArgsValid] = useState(true);
|
|
47
48
|
|
|
48
49
|
// Get fulfillment handlers
|
|
49
50
|
const { data: fulfillmentHandlersData } = useQuery({
|
|
@@ -161,7 +162,7 @@ export function FulfillOrderDialog({ order, onSuccess }: Readonly<FulfillOrderDi
|
|
|
161
162
|
({ fulfillCount, max }) => fulfillCount <= max && fulfillCount >= 0,
|
|
162
163
|
);
|
|
163
164
|
const formIsValid = form.formState.isValid;
|
|
164
|
-
return formIsValid && totalCount > 0 && fulfillmentQuantityIsValid;
|
|
165
|
+
return formIsValid && totalCount > 0 && fulfillmentQuantityIsValid && handlerArgsValid;
|
|
165
166
|
};
|
|
166
167
|
|
|
167
168
|
const handleSubmit = async (data: FormData) => {
|
|
@@ -195,6 +196,7 @@ export function FulfillOrderDialog({ order, onSuccess }: Readonly<FulfillOrderDi
|
|
|
195
196
|
const handleCancel = () => {
|
|
196
197
|
form.reset();
|
|
197
198
|
setFulfillmentQuantities({});
|
|
199
|
+
setHandlerArgsValid(true);
|
|
198
200
|
setOpen(false);
|
|
199
201
|
};
|
|
200
202
|
|
|
@@ -218,8 +220,8 @@ export function FulfillOrderDialog({ order, onSuccess }: Readonly<FulfillOrderDi
|
|
|
218
220
|
>
|
|
219
221
|
<Trans>Fulfill order</Trans>
|
|
220
222
|
</Button>
|
|
221
|
-
<Dialog open={open}>
|
|
222
|
-
<DialogContent className="sm:max-w-[600px]">
|
|
223
|
+
<Dialog open={open} onOpenChange={setOpen}>
|
|
224
|
+
<DialogContent className="sm:max-w-[600px] max-h-[90vh] overflow-hidden flex flex-col">
|
|
223
225
|
<DialogHeader>
|
|
224
226
|
<DialogTitle>
|
|
225
227
|
<Trans>Fulfill order</Trans>
|
|
@@ -234,9 +236,9 @@ export function FulfillOrderDialog({ order, onSuccess }: Readonly<FulfillOrderDi
|
|
|
234
236
|
e.stopPropagation();
|
|
235
237
|
form.handleSubmit(handleSubmit)(e);
|
|
236
238
|
}}
|
|
237
|
-
className="space-y-4"
|
|
239
|
+
className="space-y-4 flex-1 overflow-hidden flex flex-col"
|
|
238
240
|
>
|
|
239
|
-
<div className="space-y-4">
|
|
241
|
+
<div className="space-y-4 flex-1 overflow-y-auto">
|
|
240
242
|
<div className="font-medium">
|
|
241
243
|
<Trans>Order lines</Trans>
|
|
242
244
|
</div>
|
|
@@ -294,6 +296,7 @@ export function FulfillOrderDialog({ order, onSuccess }: Readonly<FulfillOrderDi
|
|
|
294
296
|
onChange={field.onChange}
|
|
295
297
|
readonly={false}
|
|
296
298
|
removable={false}
|
|
299
|
+
onValidityChange={setHandlerArgsValid}
|
|
297
300
|
/>
|
|
298
301
|
)}
|
|
299
302
|
/>
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
PageLayout,
|
|
12
12
|
PageTitle,
|
|
13
13
|
} from '@/vdb/framework/layout-engine/page-layout.js';
|
|
14
|
-
import {
|
|
14
|
+
import { useDetailPage } from '@/vdb/framework/page/use-detail-page.js';
|
|
15
15
|
import { api } from '@/vdb/graphql/api.js';
|
|
16
16
|
import { useCustomFieldConfig } from '@/vdb/hooks/use-custom-field-config.js';
|
|
17
17
|
import { useDynamicTranslations } from '@/vdb/hooks/use-dynamic-translations.js';
|
|
@@ -19,15 +19,17 @@ import { Trans, useLingui } from '@lingui/react/macro';
|
|
|
19
19
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
|
20
20
|
import { Link, useNavigate } from '@tanstack/react-router';
|
|
21
21
|
import { ResultOf } from 'gql.tada';
|
|
22
|
-
import { Pencil, User } from 'lucide-react';
|
|
23
|
-
import { useMemo } from 'react';
|
|
22
|
+
import { Pencil, RotateCcw, User } from 'lucide-react';
|
|
23
|
+
import { useCallback, useMemo, useRef } from 'react';
|
|
24
24
|
import { toast } from 'sonner';
|
|
25
|
+
|
|
25
26
|
import {
|
|
26
27
|
orderDetailDocument,
|
|
27
28
|
setOrderCustomFieldsDocument,
|
|
28
29
|
transitionOrderToStateDocument,
|
|
29
30
|
} from '../orders.graphql.js';
|
|
30
|
-
import { canAddFulfillment, shouldShowAddManualPaymentButton } from '../utils/order-utils.js';
|
|
31
|
+
import { canAddFulfillment, canRefundOrder, shouldShowAddManualPaymentButton } from '../utils/order-utils.js';
|
|
32
|
+
|
|
31
33
|
import { AddManualPaymentDialog } from './add-manual-payment-dialog.js';
|
|
32
34
|
import { FulfillOrderDialog } from './fulfill-order-dialog.js';
|
|
33
35
|
import { FulfillmentDetails } from './fulfillment-details.js';
|
|
@@ -37,6 +39,7 @@ import { orderHistoryQueryKey } from './order-history/use-order-history.js';
|
|
|
37
39
|
import { OrderTable } from './order-table.js';
|
|
38
40
|
import { OrderTaxSummary } from './order-tax-summary.js';
|
|
39
41
|
import { PaymentDetails } from './payment-details.js';
|
|
42
|
+
import { RefundOrderDialog, RefundOrderDialogRef } from './refund-order-dialog.js';
|
|
40
43
|
import { getTypeForState, StateTransitionControl } from './state-transition-control.js';
|
|
41
44
|
import { useTransitionOrderToState } from './use-transition-order-to-state.js';
|
|
42
45
|
|
|
@@ -101,58 +104,84 @@ export function OrderDetailShared({
|
|
|
101
104
|
});
|
|
102
105
|
|
|
103
106
|
const customFieldConfig = useCustomFieldConfig('Order');
|
|
107
|
+
const refundDialogRef = useRef<RefundOrderDialogRef>(null);
|
|
108
|
+
|
|
109
|
+
const refreshPage = useCallback(async () => {
|
|
110
|
+
if (!entity) return;
|
|
111
|
+
await Promise.all([
|
|
112
|
+
refreshEntity(),
|
|
113
|
+
queryClient.refetchQueries({ queryKey: orderHistoryQueryKey(entity.id) }),
|
|
114
|
+
]);
|
|
115
|
+
}, [refreshEntity, entity, queryClient]);
|
|
104
116
|
|
|
105
117
|
const stateTransitionActions = useMemo(() => {
|
|
106
118
|
if (!entity) {
|
|
107
119
|
return [];
|
|
108
120
|
}
|
|
109
|
-
return entity.nextStates
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
121
|
+
return entity.nextStates
|
|
122
|
+
.filter((state: string) => state !== 'Modifying')
|
|
123
|
+
.map((state: string) => ({
|
|
124
|
+
label: t`Transition to ${getTranslatedOrderState(state)}`,
|
|
125
|
+
type: getTypeForState(state),
|
|
126
|
+
onClick: async () => {
|
|
127
|
+
const transitionError = await transitionToState(state);
|
|
128
|
+
if (transitionError) {
|
|
129
|
+
toast(t`Failed to transition order to state`, {
|
|
130
|
+
description: transitionError,
|
|
131
|
+
});
|
|
132
|
+
} else {
|
|
133
|
+
void refreshPage();
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
}));
|
|
137
|
+
}, [entity, transitionToState, t, refreshPage]);
|
|
124
138
|
|
|
125
|
-
|
|
126
|
-
return
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
const handleModifyClick = async () => {
|
|
139
|
+
const handleModifyClick = useCallback(async () => {
|
|
140
|
+
if (!entity) return;
|
|
130
141
|
try {
|
|
131
142
|
await transitionOrderToStateMutation.mutateAsync({
|
|
132
143
|
id: entity.id,
|
|
133
144
|
state: 'Modifying',
|
|
134
145
|
});
|
|
135
|
-
|
|
136
|
-
await queryClient.invalidateQueries({ queryKey });
|
|
146
|
+
await refreshPage();
|
|
137
147
|
await navigate({ to: `/orders/$id/modify`, params: { id: entity.id } });
|
|
138
148
|
} catch (error) {
|
|
139
149
|
toast(t`Failed to modify order`, {
|
|
140
150
|
description: error instanceof Error ? error.message : 'Unknown error',
|
|
141
151
|
});
|
|
142
152
|
}
|
|
143
|
-
};
|
|
153
|
+
}, [entity, transitionOrderToStateMutation, refreshPage, navigate, t]);
|
|
154
|
+
|
|
155
|
+
const ModifyMenuItem = useCallback(
|
|
156
|
+
() => (
|
|
157
|
+
<DropdownMenuItem onClick={handleModifyClick}>
|
|
158
|
+
<Pencil className="w-4 h-4" />
|
|
159
|
+
<Trans>Modify</Trans>
|
|
160
|
+
</DropdownMenuItem>
|
|
161
|
+
),
|
|
162
|
+
[handleModifyClick],
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
const RefundMenuItem = useCallback(
|
|
166
|
+
() => (
|
|
167
|
+
<PermissionGuard requires={['UpdateOrder']}>
|
|
168
|
+
<DropdownMenuItem onClick={() => refundDialogRef.current?.open()}>
|
|
169
|
+
<RotateCcw className="w-4 h-4" />
|
|
170
|
+
<Trans>Refund & Cancel</Trans>
|
|
171
|
+
</DropdownMenuItem>
|
|
172
|
+
</PermissionGuard>
|
|
173
|
+
),
|
|
174
|
+
[],
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
if (!entity) {
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
144
180
|
|
|
145
181
|
const nextStates = entity.nextStates;
|
|
146
182
|
const showAddPaymentButton = shouldShowAddManualPaymentButton(entity);
|
|
147
183
|
const showFulfillButton = canAddFulfillment(entity);
|
|
148
|
-
|
|
149
|
-
async function refreshOrderAndHistory() {
|
|
150
|
-
if (entity) {
|
|
151
|
-
const queryKey = getDetailQueryOptions(orderDetailDocument, { id: entity.id }).queryKey;
|
|
152
|
-
await queryClient.invalidateQueries({ queryKey });
|
|
153
|
-
queryClient.refetchQueries({ queryKey: orderHistoryQueryKey(entity.id) });
|
|
154
|
-
}
|
|
155
|
-
}
|
|
184
|
+
const showRefundOption = canRefundOrder(entity);
|
|
156
185
|
|
|
157
186
|
return (
|
|
158
187
|
<Page pageId={pageId} form={form} submitHandler={submitHandler} entity={entity}>
|
|
@@ -160,18 +189,8 @@ export function OrderDetailShared({
|
|
|
160
189
|
<PageActionBar>
|
|
161
190
|
<PageActionBarRight
|
|
162
191
|
dropdownMenuItems={[
|
|
163
|
-
...(nextStates.includes('Modifying')
|
|
164
|
-
|
|
165
|
-
{
|
|
166
|
-
component: () => (
|
|
167
|
-
<DropdownMenuItem onClick={handleModifyClick}>
|
|
168
|
-
<Pencil className="w-4 h-4" />
|
|
169
|
-
<Trans>Modify</Trans>
|
|
170
|
-
</DropdownMenuItem>
|
|
171
|
-
),
|
|
172
|
-
},
|
|
173
|
-
]
|
|
174
|
-
: []),
|
|
192
|
+
...(nextStates.includes('Modifying') ? [{ component: ModifyMenuItem }] : []),
|
|
193
|
+
...(showRefundOption ? [{ component: RefundMenuItem }] : []),
|
|
175
194
|
]}
|
|
176
195
|
>
|
|
177
196
|
{showAddPaymentButton && (
|
|
@@ -179,7 +198,7 @@ export function OrderDetailShared({
|
|
|
179
198
|
<AddManualPaymentDialog
|
|
180
199
|
order={entity}
|
|
181
200
|
onSuccess={() => {
|
|
182
|
-
|
|
201
|
+
void refreshPage();
|
|
183
202
|
}}
|
|
184
203
|
/>
|
|
185
204
|
</PermissionGuard>
|
|
@@ -189,13 +208,22 @@ export function OrderDetailShared({
|
|
|
189
208
|
<FulfillOrderDialog
|
|
190
209
|
order={entity}
|
|
191
210
|
onSuccess={() => {
|
|
192
|
-
|
|
211
|
+
void refreshPage();
|
|
193
212
|
}}
|
|
194
213
|
/>
|
|
195
214
|
</PermissionGuard>
|
|
196
215
|
)}
|
|
197
216
|
</PageActionBarRight>
|
|
198
217
|
</PageActionBar>
|
|
218
|
+
{showRefundOption && (
|
|
219
|
+
<RefundOrderDialog
|
|
220
|
+
ref={refundDialogRef}
|
|
221
|
+
order={entity}
|
|
222
|
+
onSuccess={() => {
|
|
223
|
+
void refreshPage();
|
|
224
|
+
}}
|
|
225
|
+
/>
|
|
226
|
+
)}
|
|
199
227
|
<PageLayout>
|
|
200
228
|
{/* Main Column Blocks */}
|
|
201
229
|
{beforeOrderTable?.(entity)}
|
|
@@ -225,7 +253,7 @@ export function OrderDetailShared({
|
|
|
225
253
|
key={payment.id}
|
|
226
254
|
payment={payment}
|
|
227
255
|
currencyCode={entity.currencyCode}
|
|
228
|
-
onSuccess={
|
|
256
|
+
onSuccess={refreshPage}
|
|
229
257
|
/>
|
|
230
258
|
))}
|
|
231
259
|
</div>
|
|
@@ -287,10 +315,7 @@ export function OrderDetailShared({
|
|
|
287
315
|
order={entity}
|
|
288
316
|
fulfillment={fulfillment}
|
|
289
317
|
onSuccess={() => {
|
|
290
|
-
|
|
291
|
-
queryClient.refetchQueries({
|
|
292
|
-
queryKey: orderHistoryQueryKey(entity.id),
|
|
293
|
-
});
|
|
318
|
+
void refreshPage();
|
|
294
319
|
}}
|
|
295
320
|
/>
|
|
296
321
|
))}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { HistoryEntry, HistoryEntryProps } from '@/vdb/framework/history-entry/history-entry.js';
|
|
2
|
+
import { useDynamicTranslations } from '@/vdb/hooks/use-dynamic-translations.js';
|
|
2
3
|
import { Trans } from '@lingui/react/macro';
|
|
4
|
+
import { uiConfig } from 'virtual:vendure-ui-config';
|
|
3
5
|
|
|
4
6
|
export function OrderStateTransitionComponent(props: Readonly<HistoryEntryProps>) {
|
|
5
7
|
const { entry } = props;
|
|
@@ -88,11 +90,49 @@ export function OrderCustomerUpdatedComponent(props: Readonly<HistoryEntryProps>
|
|
|
88
90
|
}
|
|
89
91
|
|
|
90
92
|
export function OrderCancellationComponent(props: Readonly<HistoryEntryProps>) {
|
|
93
|
+
const { entry } = props;
|
|
94
|
+
const { getTranslatedRefundReason } = useDynamicTranslations();
|
|
95
|
+
|
|
96
|
+
const lines = entry.data.lines as Array<{ orderLineId: string; quantity: number }> | undefined;
|
|
97
|
+
const reason = entry.data.reason as string | undefined;
|
|
98
|
+
const shippingCancelled = entry.data.shippingCancelled as boolean | undefined;
|
|
99
|
+
|
|
100
|
+
const totalQuantity = lines?.reduce((sum, line) => sum + line.quantity, 0) ?? 0;
|
|
101
|
+
const hasDetails = totalQuantity > 0 || shippingCancelled || reason;
|
|
102
|
+
|
|
103
|
+
const getTranslatedReason = (reasonValue: string) => {
|
|
104
|
+
const { refundReasons } = uiConfig.orders;
|
|
105
|
+
const reasonConfig = refundReasons.find(r => r.value === reasonValue);
|
|
106
|
+
if (reasonConfig) {
|
|
107
|
+
return getTranslatedRefundReason(reasonConfig.label);
|
|
108
|
+
}
|
|
109
|
+
return reasonValue;
|
|
110
|
+
};
|
|
111
|
+
|
|
91
112
|
return (
|
|
92
113
|
<HistoryEntry {...props}>
|
|
93
|
-
<
|
|
94
|
-
|
|
95
|
-
|
|
114
|
+
<div className="text-xs text-muted-foreground space-y-1">
|
|
115
|
+
{totalQuantity > 0 && (
|
|
116
|
+
<p>
|
|
117
|
+
<Trans>{totalQuantity} item(s) refunded</Trans>
|
|
118
|
+
</p>
|
|
119
|
+
)}
|
|
120
|
+
{shippingCancelled && (
|
|
121
|
+
<p>
|
|
122
|
+
<Trans>Shipping refunded</Trans>
|
|
123
|
+
</p>
|
|
124
|
+
)}
|
|
125
|
+
{reason && (
|
|
126
|
+
<p>
|
|
127
|
+
<Trans>Reason:</Trans> {getTranslatedReason(reason)}
|
|
128
|
+
</p>
|
|
129
|
+
)}
|
|
130
|
+
{!hasDetails && (
|
|
131
|
+
<p>
|
|
132
|
+
<Trans>Order cancelled</Trans>
|
|
133
|
+
</p>
|
|
134
|
+
)}
|
|
135
|
+
</div>
|
|
96
136
|
</HistoryEntry>
|
|
97
137
|
);
|
|
98
138
|
}
|
package/src/app/routes/_authenticated/_orders/components/order-history/order-history-utils.tsx
CHANGED
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
CheckIcon,
|
|
7
7
|
CreditCardIcon,
|
|
8
8
|
Edit3,
|
|
9
|
+
RotateCcw,
|
|
9
10
|
SquarePen,
|
|
10
11
|
Truck,
|
|
11
12
|
UserX,
|
|
@@ -40,8 +41,14 @@ export function orderHistoryUtils(order: OrderHistoryOrderDetail) {
|
|
|
40
41
|
return <Edit3 className="h-4 w-4" />;
|
|
41
42
|
case 'ORDER_CUSTOMER_UPDATED':
|
|
42
43
|
return <UserX className="h-4 w-4" />;
|
|
43
|
-
case 'ORDER_CANCELLATION':
|
|
44
|
+
case 'ORDER_CANCELLATION': {
|
|
45
|
+
const lines = entry.data.lines as Array<{ orderLineId: string; quantity: number }> | undefined;
|
|
46
|
+
const hasRefundData = (lines && lines.length > 0) || entry.data.reason;
|
|
47
|
+
if (hasRefundData) {
|
|
48
|
+
return <RotateCcw className="h-4 w-4" />;
|
|
49
|
+
}
|
|
44
50
|
return <Ban className="h-4 w-4" />;
|
|
51
|
+
}
|
|
45
52
|
default:
|
|
46
53
|
return <CheckIcon className="h-4 w-4" />;
|
|
47
54
|
}
|
|
@@ -96,8 +103,14 @@ export function orderHistoryUtils(order: OrderHistoryOrderDetail) {
|
|
|
96
103
|
return <Trans>Order modified</Trans>;
|
|
97
104
|
case 'ORDER_CUSTOMER_UPDATED':
|
|
98
105
|
return <Trans>Customer updated</Trans>;
|
|
99
|
-
case 'ORDER_CANCELLATION':
|
|
106
|
+
case 'ORDER_CANCELLATION': {
|
|
107
|
+
const lines = entry.data.lines as Array<{ orderLineId: string; quantity: number }> | undefined;
|
|
108
|
+
const hasPartialCancellation = lines && lines.length > 0;
|
|
109
|
+
if (hasPartialCancellation || entry.data.reason) {
|
|
110
|
+
return <Trans>Items refunded</Trans>;
|
|
111
|
+
}
|
|
100
112
|
return <Trans>Order cancelled</Trans>;
|
|
113
|
+
}
|
|
101
114
|
default:
|
|
102
115
|
return <Trans>{entry.type.replace(/_/g, ' ').toLowerCase()}</Trans>;
|
|
103
116
|
}
|
|
@@ -106,6 +119,7 @@ export function orderHistoryUtils(order: OrderHistoryOrderDetail) {
|
|
|
106
119
|
const getIconColor = ({ type, data }: HistoryEntryItem) => {
|
|
107
120
|
const success = 'bg-success text-success-foreground';
|
|
108
121
|
const destructive = 'bg-destructive text-destructive-foreground';
|
|
122
|
+
const warning = 'bg-yellow-400 text-yellow-950 dark:bg-yellow-600 dark:text-yellow-50';
|
|
109
123
|
const regular = 'bg-muted text-muted-foreground';
|
|
110
124
|
|
|
111
125
|
if (type === 'ORDER_PAYMENT_TRANSITION' && data.to === 'Settled') {
|
|
@@ -118,7 +132,9 @@ export function orderHistoryUtils(order: OrderHistoryOrderDetail) {
|
|
|
118
132
|
return success;
|
|
119
133
|
}
|
|
120
134
|
if (type === 'ORDER_CANCELLATION') {
|
|
121
|
-
|
|
135
|
+
const lines = data.lines as Array<{ orderLineId: string; quantity: number }> | undefined;
|
|
136
|
+
const hasRefundData = (lines && lines.length > 0) || data.reason;
|
|
137
|
+
return hasRefundData ? warning : destructive;
|
|
122
138
|
}
|
|
123
139
|
if (type === 'ORDER_STATE_TRANSITION' && data.to === 'Cancelled') {
|
|
124
140
|
return destructive;
|
|
@@ -175,6 +175,7 @@ export function OrderTable({ order, pageId }: Readonly<OrderTableProps>) {
|
|
|
175
175
|
columns={columns as any}
|
|
176
176
|
data={data as any}
|
|
177
177
|
totalItems={data.length}
|
|
178
|
+
itemsPerPage={data.length}
|
|
178
179
|
disableViewOptions={false}
|
|
179
180
|
defaultColumnVisibility={columnVisibility}
|
|
180
181
|
onColumnVisibilityChange={(_, columnVisibility) => {
|