@deenruv/admin-dashboard 1.0.5 → 1.0.9
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/DeenruvAdminPanel.js +5 -4
- package/dist/DeenruvDeveloperIndicator.js +1 -1
- package/dist/components/ContentAreaSkeleton.js +5 -0
- package/dist/components/Menu/LanguagesDropdown.js +4 -3
- package/dist/components/Menu/Navigation.js +10 -9
- package/dist/components/Menu/Notifications.js +2 -1
- package/dist/components/Menu/flag-icons.js +16 -0
- package/dist/components/Menu/index.js +3 -2
- package/dist/pages/Custom404.js +16 -2
- package/dist/pages/Root.js +2 -2
- package/dist/pages/admins/Detail.js +7 -7
- package/dist/pages/admins/_components/AdminDetailView.js +17 -9
- package/dist/pages/channels/Detail.js +12 -12
- package/dist/pages/channels/_components/ChannelDetailView.js +25 -17
- package/dist/pages/collections/Detail.js +8 -7
- package/dist/pages/collections/List.js +1 -2
- package/dist/pages/collections/_components/CollectionDetailView.js +65 -22
- package/dist/pages/collections/_components/CollectionProductVariantsDrawer.js +1 -1
- package/dist/pages/countries/Detail.js +5 -5
- package/dist/pages/countries/_components/CountryDetailView.js +15 -8
- package/dist/pages/customer-groups/Detail.js +3 -3
- package/dist/pages/customer-groups/_components/CustomerGroupsDetailView.js +4 -4
- package/dist/pages/customers/Detail.js +6 -8
- package/dist/pages/customers/_components/AddressForm.js +48 -60
- package/dist/pages/customers/_components/AddressesCard.js +1 -1
- package/dist/pages/customers/_components/CustomerDetailView.js +9 -9
- package/dist/pages/dashboard/Dashboard.js +3 -2
- package/dist/pages/extensions/Extensions.js +12 -13
- package/dist/pages/facets/Detail.js +6 -6
- package/dist/pages/facets/_components/AddFacetValueDialog.js +39 -39
- package/dist/pages/facets/_components/FacetDetailView.js +19 -12
- package/dist/pages/global-settings/GlobalSettingsComponent.js +9 -8
- package/dist/pages/global-settings/index.js +4 -4
- package/dist/pages/orders/List.js +2 -1
- package/dist/pages/orders/_components/AddressCard.js +123 -78
- package/dist/pages/orders/_components/CustomerSelectCard.js +38 -43
- package/dist/pages/orders/_components/FulfillmentModal.js +47 -28
- package/dist/pages/orders/_components/ModifyingCard.js +30 -13
- package/dist/pages/orders/_components/OrderLineCustomFields.js +2 -1
- package/dist/pages/orders/_components/PossibleOrderStates.js +2 -1
- package/dist/pages/orders/_components/ProductsCard.js +2 -1
- package/dist/pages/orders/_components/SurchargeCard.js +58 -60
- package/dist/pages/orders/_components/TopActions.js +2 -1
- package/dist/pages/payment-methods/Detail.js +8 -7
- package/dist/pages/payment-methods/_components/PaymentMethodDetailView.js +22 -14
- package/dist/pages/products/Detail.js +9 -7
- package/dist/pages/products/_components/AddOptionGroupDialog.js +36 -14
- package/dist/pages/products/_components/BasicFieldsCard.js +5 -2
- package/dist/pages/products/_components/OptionValueCard.js +25 -23
- package/dist/pages/products/_components/ProductDetailSidebar.js +15 -7
- package/dist/pages/products/_components/ProductDetailView.js +51 -17
- package/dist/pages/products/_components/Variant.js +105 -57
- package/dist/pages/promotions/Detail.js +13 -11
- package/dist/pages/promotions/_components/OptionsCard.js +1 -1
- package/dist/pages/promotions/_components/PromotionDetailSidebar.js +9 -6
- package/dist/pages/promotions/_components/PromotionDetailView.js +26 -20
- package/dist/pages/roles/Detail.js +5 -5
- package/dist/pages/roles/_components/RoleDetailView.js +13 -8
- package/dist/pages/sellers/Detail.js +4 -4
- package/dist/pages/sellers/_components/SellerDetailView.js +4 -4
- package/dist/pages/shipping-methods/Detail.js +14 -12
- package/dist/pages/shipping-methods/_components/Lines.js +1 -1
- package/dist/pages/shipping-methods/_components/ShippingMethodDetailView.js +26 -13
- package/dist/pages/shipping-methods/_components/TestCard.js +67 -21
- package/dist/pages/status/_components/Health.js +2 -1
- package/dist/pages/status/_components/Jobs.js +2 -6
- package/dist/pages/stock-locations/Detail.js +4 -4
- package/dist/pages/stock-locations/_components/StockLocationDetailView.js +5 -5
- package/dist/pages/tax-categories/Detail.js +4 -4
- package/dist/pages/tax-categories/_components/TaxCategoryDetailView.js +7 -7
- package/dist/pages/tax-rates/Detail.js +8 -8
- package/dist/pages/tax-rates/_components/TaxRateDetailView.js +13 -9
- package/dist/pages/zones/Detail.js +4 -4
- package/dist/pages/zones/_components/ZoneDetailView.js +8 -7
- package/dist/version.js +1 -1
- package/package.json +79 -78
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useDetailView, DetailViewMarker, useSettings, setInArrayBy, EntityCustomFields, } from '@deenruv/react-ui-devkit';
|
|
3
|
-
import { useCallback, useEffect, useMemo } from 'react';
|
|
2
|
+
import { useDetailView, DetailViewMarker, useSettings, setInArrayBy, EntityCustomFields, normalizeString, } from '@deenruv/react-ui-devkit';
|
|
3
|
+
import { useCallback, useEffect, useMemo, useRef } from 'react';
|
|
4
4
|
import { BasicFieldsCard } from './BasicFieldsCard';
|
|
5
5
|
import { AssetsCard } from './AssetsCard';
|
|
6
6
|
export const PRODUCT_FORM_KEYS = [
|
|
@@ -16,39 +16,73 @@ export const ProductDetailView = () => {
|
|
|
16
16
|
const contentLng = useSettings((p) => p.translationsLanguage);
|
|
17
17
|
const selectedChannel = useSettings((p) => p.selectedChannel);
|
|
18
18
|
const { entity, id, form, loading, fetchEntity } = useDetailView('products-detail-view', ...PRODUCT_FORM_KEYS);
|
|
19
|
-
const { base
|
|
19
|
+
const { base } = form;
|
|
20
|
+
// --- Slug auto-generation ---
|
|
21
|
+
// Track whether the user has manually edited the slug for the current language.
|
|
22
|
+
// Using a ref avoids extra re-renders; keyed per-language so switching tabs resets.
|
|
23
|
+
const slugManuallyEditedRef = useRef({});
|
|
24
|
+
// Reset manual-edit flag when switching to a language whose slug is still empty
|
|
25
|
+
// (so auto-gen kicks in for new translations).
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
if (!contentLng)
|
|
28
|
+
return;
|
|
29
|
+
const current = slugManuallyEditedRef.current[contentLng];
|
|
30
|
+
if (current === undefined) {
|
|
31
|
+
slugManuallyEditedRef.current[contentLng] = false;
|
|
32
|
+
}
|
|
33
|
+
}, [contentLng]);
|
|
20
34
|
useEffect(() => {
|
|
21
35
|
(async () => {
|
|
22
36
|
const res = await fetchEntity();
|
|
23
37
|
if (!res)
|
|
24
38
|
return;
|
|
25
|
-
setField('translations', res.translations);
|
|
26
|
-
setField('assetIds', res.assets.map((a) => a.id));
|
|
27
|
-
setField('featuredAssetId', res.featuredAsset?.id);
|
|
39
|
+
base.setField('translations', res.translations);
|
|
40
|
+
base.setField('assetIds', res.assets.map((a) => a.id));
|
|
41
|
+
base.setField('featuredAssetId', res.featuredAsset?.id);
|
|
28
42
|
})();
|
|
29
43
|
}, [selectedChannel?.id, contentLng]);
|
|
30
|
-
const translations =
|
|
44
|
+
const translations = base.watch('translations') || [];
|
|
31
45
|
const currentTranslationValue = useMemo(() => {
|
|
32
46
|
return translations.find((v) => v.languageCode === contentLng);
|
|
33
47
|
}, [translations, contentLng]);
|
|
34
48
|
const setTranslationField = useCallback((field, e) => {
|
|
35
|
-
|
|
49
|
+
const updatedTranslation = {
|
|
36
50
|
...currentTranslationValue,
|
|
37
51
|
[field]: e,
|
|
38
52
|
languageCode: contentLng,
|
|
39
|
-
}
|
|
40
|
-
|
|
53
|
+
};
|
|
54
|
+
// Auto-generate slug when name changes
|
|
55
|
+
if (field === 'name') {
|
|
56
|
+
const isCreate = id === undefined;
|
|
57
|
+
const existingSlug = currentTranslationValue?.slug;
|
|
58
|
+
const slugWasManuallyEdited = slugManuallyEditedRef.current[contentLng ?? ''];
|
|
59
|
+
// Auto-fill slug when:
|
|
60
|
+
// 1. Create mode: always, unless user manually edited slug
|
|
61
|
+
// 2. Edit mode: only if the existing slug is empty/missing
|
|
62
|
+
if (!slugWasManuallyEdited && (isCreate || !existingSlug)) {
|
|
63
|
+
updatedTranslation.slug = normalizeString(e, '-');
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
base.setField('translations', setInArrayBy(translations, (t) => t.languageCode === contentLng, updatedTranslation));
|
|
67
|
+
}, [contentLng, translations, currentTranslationValue, id]);
|
|
68
|
+
const handleSlugManualEdit = useCallback(() => {
|
|
69
|
+
if (contentLng) {
|
|
70
|
+
slugManuallyEditedRef.current[contentLng] = true;
|
|
71
|
+
}
|
|
72
|
+
}, [contentLng]);
|
|
41
73
|
const handleAddAsset = useCallback((newId) => {
|
|
42
74
|
if (!newId)
|
|
43
75
|
return;
|
|
44
|
-
const currentIds =
|
|
45
|
-
setField('assetIds', [...currentIds, newId]);
|
|
46
|
-
}, [
|
|
47
|
-
return (_jsx("div", { children: _jsxs("div", { className: "flex w-full flex-col gap-4", children: [_jsx(BasicFieldsCard, { currentTranslationValue: currentTranslationValue, onChange: setTranslationField,
|
|
48
|
-
|
|
76
|
+
const currentIds = base.watch('assetIds') || [];
|
|
77
|
+
base.setField('assetIds', [...currentIds, newId]);
|
|
78
|
+
}, [base, base.setField]);
|
|
79
|
+
return (_jsx("div", { children: _jsxs("div", { className: "flex w-full flex-col gap-4", children: [_jsx(BasicFieldsCard, { currentTranslationValue: currentTranslationValue, onChange: setTranslationField, onSlugManualEdit: handleSlugManualEdit, errors: base.formState.errors?.translations?.message
|
|
80
|
+
? [base.formState.errors.translations.message]
|
|
81
|
+
: undefined }), _jsx(DetailViewMarker, { position: 'products-detail-view' }), _jsx(EntityCustomFields, { id: id, entityName: "product", hideButton: true, onChange: (customFields, translations) => {
|
|
82
|
+
base.setField('customFields', customFields);
|
|
49
83
|
if (translations)
|
|
50
|
-
setField('translations', translations);
|
|
84
|
+
base.setField('translations', translations);
|
|
51
85
|
}, initialValues: entity && 'customFields' in entity
|
|
52
86
|
? { customFields: entity.customFields, translations: entity.translations }
|
|
53
|
-
: { customFields: {} } }), _jsx(AssetsCard, { onAddAsset: handleAddAsset, featuredAssetId:
|
|
87
|
+
: { customFields: {} } }), _jsx(AssetsCard, { onAddAsset: handleAddAsset, featuredAssetId: base.watch('featuredAssetId'), assetsIds: base.watch('assetIds'), onFeaturedAssetChange: (id) => base.setField('featuredAssetId', id), onAssetsChange: (ids) => base.setField('assetIds', ids) })] }) }));
|
|
54
88
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Button, CardIcons, ConfirmationDialog, CustomCard, Input, apiClient, setInArrayBy,
|
|
2
|
+
import { Button, CardIcons, ConfirmationDialog, CustomCard, Input, apiClient, setInArrayBy, useDeenruvForm, z, EntityCustomFields, useTranslation, EntityChannelManager, } from '@deenruv/react-ui-devkit';
|
|
3
3
|
import { CurrencyCode } from '@deenruv/admin-types';
|
|
4
4
|
import { useCallback, useEffect } from 'react';
|
|
5
5
|
import { toast } from 'sonner';
|
|
@@ -10,49 +10,89 @@ import { OptionsCard } from "./OptionsCard";
|
|
|
10
10
|
import { FacetValuesCard } from "./FacetValuesCard";
|
|
11
11
|
export const Variant = ({ variant, currentTranslationLng, onActionCompleted, productId }) => {
|
|
12
12
|
const { t } = useTranslation('products');
|
|
13
|
-
const
|
|
14
|
-
|
|
13
|
+
const variantSchema = z.object({
|
|
14
|
+
translations: z.array(z.any()).default([]),
|
|
15
|
+
price: z.any().optional(),
|
|
16
|
+
prices: z.any().optional(),
|
|
17
|
+
sku: z.any().optional(),
|
|
18
|
+
assetIds: z.array(z.string()).default([]),
|
|
19
|
+
featuredAssetId: z.string().nullable().optional(),
|
|
20
|
+
taxCategoryId: z.string().optional(),
|
|
21
|
+
stockLevels: z.array(z.any()).default([]),
|
|
22
|
+
stockOnHand: z.number().optional(),
|
|
23
|
+
outOfStockThreshold: z.number().optional(),
|
|
24
|
+
useGlobalOutOfStockThreshold: z.boolean().optional(),
|
|
25
|
+
trackInventory: z.any().optional(),
|
|
26
|
+
facetValueIds: z.array(z.string()).default([]),
|
|
27
|
+
optionIds: z.array(z.string()).default([]),
|
|
28
|
+
customFields: z.record(z.string(), z.unknown()).default({}),
|
|
29
|
+
});
|
|
30
|
+
const form = useDeenruvForm({
|
|
31
|
+
schema: variantSchema,
|
|
32
|
+
defaultValues: {
|
|
33
|
+
translations: [],
|
|
34
|
+
price: undefined,
|
|
35
|
+
prices: undefined,
|
|
36
|
+
sku: undefined,
|
|
37
|
+
assetIds: [],
|
|
38
|
+
featuredAssetId: undefined,
|
|
39
|
+
taxCategoryId: undefined,
|
|
40
|
+
stockLevels: [],
|
|
41
|
+
stockOnHand: undefined,
|
|
42
|
+
outOfStockThreshold: undefined,
|
|
43
|
+
useGlobalOutOfStockThreshold: undefined,
|
|
44
|
+
trackInventory: undefined,
|
|
45
|
+
facetValueIds: [],
|
|
46
|
+
optionIds: [],
|
|
47
|
+
customFields: {},
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
const formValues = form.watch();
|
|
51
|
+
const translations = formValues.translations || [];
|
|
15
52
|
const currentTranslationValue = translations.find((v) => v.languageCode === currentTranslationLng);
|
|
16
53
|
useEffect(() => {
|
|
17
54
|
if (!variant)
|
|
18
55
|
return;
|
|
19
|
-
setField('sku', variant.sku);
|
|
20
|
-
setField('price', variant.price);
|
|
21
|
-
setField('prices', variant.prices);
|
|
22
|
-
setField('translations', variant.translations);
|
|
23
|
-
setField('assetIds', variant.assets.map((a) => a.id));
|
|
24
|
-
setField('featuredAssetId', variant.featuredAsset?.id);
|
|
25
|
-
setField('taxCategoryId', variant.taxCategory.id);
|
|
26
|
-
setField('stockLevels', variant.stockLevels.map((sL) => ({ stockLocationId: sL.stockLocationId, stockOnHand: sL.stockOnHand })));
|
|
27
|
-
setField('stockOnHand', variant.stockOnHand);
|
|
28
|
-
setField('outOfStockThreshold', variant.outOfStockThreshold);
|
|
29
|
-
setField('useGlobalOutOfStockThreshold', variant.useGlobalOutOfStockThreshold);
|
|
30
|
-
setField('trackInventory', variant.trackInventory);
|
|
31
|
-
setField('facetValueIds', variant.facetValues.map((f) => f.id));
|
|
56
|
+
form.setField('sku', variant.sku);
|
|
57
|
+
form.setField('price', variant.price);
|
|
58
|
+
form.setField('prices', variant.prices);
|
|
59
|
+
form.setField('translations', variant.translations);
|
|
60
|
+
form.setField('assetIds', variant.assets.map((a) => a.id));
|
|
61
|
+
form.setField('featuredAssetId', variant.featuredAsset?.id);
|
|
62
|
+
form.setField('taxCategoryId', variant.taxCategory.id);
|
|
63
|
+
form.setField('stockLevels', variant.stockLevels.map((sL) => ({ stockLocationId: sL.stockLocationId, stockOnHand: sL.stockOnHand })));
|
|
64
|
+
form.setField('stockOnHand', variant.stockOnHand);
|
|
65
|
+
form.setField('outOfStockThreshold', variant.outOfStockThreshold);
|
|
66
|
+
form.setField('useGlobalOutOfStockThreshold', variant.useGlobalOutOfStockThreshold);
|
|
67
|
+
form.setField('trackInventory', variant.trackInventory);
|
|
68
|
+
form.setField('facetValueIds', variant.facetValues.map((f) => f.id));
|
|
32
69
|
}, [variant]);
|
|
33
70
|
const createVariant = useCallback(() => {
|
|
34
|
-
|
|
71
|
+
const values = form.getValues();
|
|
72
|
+
if (productId && values.sku && values.translations)
|
|
35
73
|
return apiClient('mutation')({
|
|
36
74
|
createProductVariants: [
|
|
37
75
|
{
|
|
38
76
|
input: [
|
|
39
77
|
{
|
|
40
78
|
productId,
|
|
41
|
-
translations:
|
|
42
|
-
// price: +
|
|
43
|
-
prices:
|
|
44
|
-
sku:
|
|
45
|
-
assetIds:
|
|
46
|
-
featuredAssetId:
|
|
47
|
-
outOfStockThreshold:
|
|
48
|
-
stockOnHand:
|
|
49
|
-
trackInventory:
|
|
50
|
-
taxCategoryId:
|
|
51
|
-
useGlobalOutOfStockThreshold:
|
|
52
|
-
stockLevels:
|
|
53
|
-
facetValueIds:
|
|
54
|
-
optionIds:
|
|
55
|
-
...(
|
|
79
|
+
translations: values.translations,
|
|
80
|
+
// price: +values.price,
|
|
81
|
+
prices: values.prices,
|
|
82
|
+
sku: values.sku,
|
|
83
|
+
assetIds: values.assetIds,
|
|
84
|
+
featuredAssetId: values.featuredAssetId,
|
|
85
|
+
outOfStockThreshold: values.outOfStockThreshold,
|
|
86
|
+
stockOnHand: values.stockOnHand,
|
|
87
|
+
trackInventory: values.trackInventory,
|
|
88
|
+
taxCategoryId: values.taxCategoryId,
|
|
89
|
+
useGlobalOutOfStockThreshold: values.useGlobalOutOfStockThreshold,
|
|
90
|
+
stockLevels: values.stockLevels,
|
|
91
|
+
facetValueIds: values.facetValueIds,
|
|
92
|
+
optionIds: values.optionIds,
|
|
93
|
+
...(values.customFields && Object.keys(values.customFields).length > 0
|
|
94
|
+
? { customFields: values.customFields }
|
|
95
|
+
: {}),
|
|
56
96
|
},
|
|
57
97
|
],
|
|
58
98
|
},
|
|
@@ -68,30 +108,33 @@ export const Variant = ({ variant, currentTranslationLng, onActionCompleted, pro
|
|
|
68
108
|
.catch(() => {
|
|
69
109
|
toast(t('toasts.createProductVariantErrorToast'));
|
|
70
110
|
});
|
|
71
|
-
}, [
|
|
111
|
+
}, [form, productId, onActionCompleted, t]);
|
|
72
112
|
const updateVariant = useCallback(() => {
|
|
73
113
|
if (!variant)
|
|
74
114
|
return;
|
|
115
|
+
const values = form.getValues();
|
|
75
116
|
apiClient('mutation')({
|
|
76
117
|
updateProductVariants: [
|
|
77
118
|
{
|
|
78
119
|
input: [
|
|
79
120
|
{
|
|
80
121
|
id: variant.id,
|
|
81
|
-
translations:
|
|
82
|
-
// price: +
|
|
83
|
-
prices:
|
|
84
|
-
sku:
|
|
85
|
-
assetIds:
|
|
86
|
-
featuredAssetId:
|
|
87
|
-
outOfStockThreshold:
|
|
88
|
-
stockOnHand:
|
|
89
|
-
trackInventory:
|
|
90
|
-
taxCategoryId:
|
|
91
|
-
useGlobalOutOfStockThreshold:
|
|
92
|
-
stockLevels:
|
|
93
|
-
facetValueIds:
|
|
94
|
-
...(
|
|
122
|
+
translations: values.translations,
|
|
123
|
+
// price: +values.price,
|
|
124
|
+
prices: values.prices,
|
|
125
|
+
sku: values.sku,
|
|
126
|
+
assetIds: values.assetIds,
|
|
127
|
+
featuredAssetId: values.featuredAssetId,
|
|
128
|
+
outOfStockThreshold: values.outOfStockThreshold,
|
|
129
|
+
stockOnHand: values.stockOnHand,
|
|
130
|
+
trackInventory: values.trackInventory,
|
|
131
|
+
taxCategoryId: values.taxCategoryId,
|
|
132
|
+
useGlobalOutOfStockThreshold: values.useGlobalOutOfStockThreshold,
|
|
133
|
+
stockLevels: values.stockLevels,
|
|
134
|
+
facetValueIds: values.facetValueIds,
|
|
135
|
+
...(values.customFields && Object.keys(values.customFields).length > 0
|
|
136
|
+
? { customFields: values.customFields }
|
|
137
|
+
: {}),
|
|
95
138
|
},
|
|
96
139
|
],
|
|
97
140
|
},
|
|
@@ -105,7 +148,7 @@ export const Variant = ({ variant, currentTranslationLng, onActionCompleted, pro
|
|
|
105
148
|
});
|
|
106
149
|
})
|
|
107
150
|
.catch(() => toast.error(t('toasts.updateProductErrorToast')));
|
|
108
|
-
}, [
|
|
151
|
+
}, [form, variant]);
|
|
109
152
|
const deleteVariant = useCallback(() => {
|
|
110
153
|
if (!variant)
|
|
111
154
|
return;
|
|
@@ -121,7 +164,13 @@ export const Variant = ({ variant, currentTranslationLng, onActionCompleted, pro
|
|
|
121
164
|
.catch(() => toast.error(t('toasts.deleteProductVariantErrorToast')));
|
|
122
165
|
}, [variant]);
|
|
123
166
|
const setTranslationField = useCallback((field, e) => {
|
|
124
|
-
|
|
167
|
+
const currentValue = translations.find((t) => t.languageCode === currentTranslationLng);
|
|
168
|
+
const baseTranslation = currentValue ?? {
|
|
169
|
+
languageCode: currentTranslationLng,
|
|
170
|
+
name: '',
|
|
171
|
+
};
|
|
172
|
+
form.setField('translations', setInArrayBy(translations, (t) => t.languageCode === currentTranslationLng, {
|
|
173
|
+
...baseTranslation,
|
|
125
174
|
[field]: e.target.value,
|
|
126
175
|
languageCode: currentTranslationLng,
|
|
127
176
|
}));
|
|
@@ -129,21 +178,20 @@ export const Variant = ({ variant, currentTranslationLng, onActionCompleted, pro
|
|
|
129
178
|
const handleAddAsset = (id) => {
|
|
130
179
|
if (!id)
|
|
131
180
|
return;
|
|
132
|
-
const newIds =
|
|
181
|
+
const newIds = formValues.assetIds || [];
|
|
133
182
|
if (newIds?.includes(id))
|
|
134
183
|
return;
|
|
135
|
-
newIds
|
|
136
|
-
setField('assetIds', newIds);
|
|
184
|
+
form.setField('assetIds', [...newIds, id]);
|
|
137
185
|
};
|
|
138
|
-
return (_jsxs("div", { className: "mt-4 flex flex-col gap-4", children: [_jsx("div", { className: "flex gap-3 self-end", children: variant ? (_jsxs(_Fragment, { children: [_jsx(ConfirmationDialog, { onConfirm: deleteVariant, children: _jsx(Button, { variant: 'destructive', children: t('forms.removeVariant') }) }), _jsx(Button, { onClick: updateVariant, children: t('forms.updateVariant') })] })) : (_jsx(Button, { onClick: createVariant, children: t('addVariantDialog.add') })) }), _jsxs("div", { className: "flex gap-4", children: [_jsxs("div", { className: "flex w-2/3 flex-col gap-4", children: [!!variant && (_jsx(StockCard, { priceValue:
|
|
139
|
-
setField('customFields', customFields);
|
|
186
|
+
return (_jsxs("div", { className: "mt-4 flex flex-col gap-4", children: [_jsx("div", { className: "flex gap-3 self-end", children: variant ? (_jsxs(_Fragment, { children: [_jsx(ConfirmationDialog, { onConfirm: deleteVariant, children: _jsx(Button, { variant: 'destructive', children: t('forms.removeVariant') }) }), _jsx(Button, { onClick: updateVariant, children: t('forms.updateVariant') })] })) : (_jsx(Button, { onClick: createVariant, children: t('addVariantDialog.add') })) }), _jsxs("div", { className: "flex gap-4", children: [_jsxs("div", { className: "flex w-2/3 flex-col gap-4", children: [!!variant && (_jsx(StockCard, { priceValue: formValues.price, taxRateValue: formValues.taxCategoryId, outOfStockThresholdValue: formValues.outOfStockThreshold, stockLevelsValue: formValues.stockLevels, stockOnHandValue: formValues.stockOnHand, useGlobalOutOfStockThresholdValue: formValues.useGlobalOutOfStockThreshold, onThresholdChange: (e) => form.setField('outOfStockThreshold', +e.target.value), onUseGlobalChange: (e) => form.setField('useGlobalOutOfStockThreshold', e), onTrackInventoryChange: (e) => form.setField('trackInventory', e), onStockOnHandChange: (e) => form.setField('stockOnHand', +e.target.value), onStockLocationsChange: (e) => form.setField('stockLevels', e), allStockLocations: variant?.stockLevels, stockAllocated: variant?.stockAllocated, trackInventoryValue: formValues.trackInventory })), _jsx(PriceCard, { currencyCode: variant?.currencyCode || CurrencyCode.PLN, priceValue: formValues.prices, onPriceChange: (e) => form.setField('prices', e), taxRateValue: formValues.taxCategoryId ?? undefined, onTaxRateChange: (id) => form.setField('taxCategoryId', id) }), _jsx(AssetsCard, { onAddAsset: handleAddAsset, featuredAssetId: formValues.featuredAssetId, assetsIds: formValues.assetIds, onFeaturedAssetChange: (id) => form.setField('featuredAssetId', id), onAssetsChange: (ids) => form.setField('assetIds', ids) }), _jsx(EntityCustomFields, { entityName: "productVariant", id: variant?.id, hideButton: true, onChange: (customFields, translations) => {
|
|
187
|
+
form.setField('customFields', customFields);
|
|
140
188
|
if (translations)
|
|
141
|
-
setField('translations', translations);
|
|
189
|
+
form.setField('translations', translations);
|
|
142
190
|
}, initialValues: variant && 'customFields' in variant
|
|
143
191
|
? { customFields: variant.customFields, translations: variant.translations }
|
|
144
|
-
: { customFields: {} } })] }), _jsxs("div", { className: "flex w-1/3 flex-col gap-4", children: [_jsx(CustomCard, { title: t('name'), icon: _jsx(CardIcons.basic, {}), color: "purple", children: _jsxs("div", { className: "flex flex-col gap-y-4", children: [_jsx(Input, { label: t('sku'), placeholder: t('sku'), value:
|
|
192
|
+
: { customFields: {} } })] }), _jsxs("div", { className: "flex w-1/3 flex-col gap-4", children: [_jsx(CustomCard, { title: t('name'), icon: _jsx(CardIcons.basic, {}), color: "purple", children: _jsxs("div", { className: "flex flex-col gap-y-4", children: [_jsx(Input, { label: t('sku'), placeholder: t('sku'), value: formValues.sku ?? undefined, onChange: (e) => form.setField('sku', e.target.value) }), _jsx(Input, { label: t('name'), placeholder: t('name'), value: currentTranslationValue?.name ?? undefined, onChange: (e) => setTranslationField('name', e) })] }) }), _jsx(EntityChannelManager, { entity: "productVariant", entityId: variant?.id, entityChannels: variant?.channels ?? [], onRemoveSuccess: onActionCompleted, entityName: variant?.name, entityVariantList: {
|
|
145
193
|
items: [
|
|
146
194
|
{ price: variant?.price, priceWithTax: variant?.priceWithTax, currencyCode: variant?.currencyCode },
|
|
147
195
|
],
|
|
148
|
-
} }), _jsx(OptionsCard, { optionGroups: variant?.options || [], productId: productId, optionIds:
|
|
196
|
+
} }), _jsx(OptionsCard, { optionGroups: variant?.options || [], productId: productId, optionIds: formValues.optionIds ?? undefined, onChange: (e) => form.setField('optionIds', e), createMode: !variant }), !!variant && (_jsx(FacetValuesCard, { facetValuesIds: formValues.facetValueIds ?? undefined, onChange: (e) => form.setField('facetValueIds', e) }))] })] })] }));
|
|
149
197
|
};
|
|
@@ -48,22 +48,24 @@ export const PromotionsDetailPage = () => {
|
|
|
48
48
|
onSubmitted: (data) => {
|
|
49
49
|
if (!data.translations || !data.actions || !data.conditions)
|
|
50
50
|
throw new Error('Fill required fields.');
|
|
51
|
+
const conditions = data.conditions;
|
|
52
|
+
const actions = data.actions;
|
|
51
53
|
const input = {
|
|
52
|
-
translations: data.translations
|
|
53
|
-
enabled: data.enabled
|
|
54
|
-
actions
|
|
55
|
-
conditions:
|
|
54
|
+
translations: data.translations,
|
|
55
|
+
enabled: data.enabled || false,
|
|
56
|
+
actions,
|
|
57
|
+
conditions: conditions?.map((el) => ({
|
|
56
58
|
...el,
|
|
57
59
|
arguments: el.arguments.map((arg) => ({ ...arg, value: arg.value.toString() })),
|
|
58
60
|
})),
|
|
59
|
-
couponCode: data.couponCode
|
|
60
|
-
endsAt: data.endsAt
|
|
61
|
-
startsAt: data.startsAt
|
|
62
|
-
perCustomerUsageLimit: data.perCustomerUsageLimit
|
|
63
|
-
usageLimit: data.usageLimit
|
|
64
|
-
...(data.customFields
|
|
61
|
+
couponCode: data.couponCode,
|
|
62
|
+
endsAt: data.endsAt,
|
|
63
|
+
startsAt: data.startsAt,
|
|
64
|
+
perCustomerUsageLimit: data.perCustomerUsageLimit,
|
|
65
|
+
usageLimit: data.usageLimit,
|
|
66
|
+
...(data.customFields ? { customFields: data.customFields } : {}),
|
|
65
67
|
};
|
|
66
|
-
return id ? update({ input: { id, ...input } }) : create({ input });
|
|
68
|
+
return id ? update({ input: { id, ...input } }) : create({ input: input });
|
|
67
69
|
},
|
|
68
70
|
onDeleted: () => {
|
|
69
71
|
if (id)
|
|
@@ -2,5 +2,5 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { Input, CustomCard, CardIcons, useTranslation, DateTimePicker } from '@deenruv/react-ui-devkit';
|
|
3
3
|
export const OptionsCard = ({ startsAt, endsAt, couponCode, perCustomerUsageLimit, usageLimit, setField, }) => {
|
|
4
4
|
const { t } = useTranslation('promotions');
|
|
5
|
-
return (_jsx(CustomCard, { title: t('options.header'), color: "orange", icon: _jsx(CardIcons.options, {}), children: _jsxs("div", { className: "flex flex-1 flex-col gap-y-4", children: [_jsxs("div", { className: "flex gap-3", children: [_jsx(DateTimePicker, { value: startsAt ? new Date(startsAt) : undefined, onChange: (date) => setField('startsAt', date ? date.toISOString() : ''), min: new Date(), max: endsAt ? new Date(endsAt) : undefined }), _jsx(DateTimePicker, { value: endsAt ? new Date(endsAt) : undefined, onChange: (date) => setField('endsAt', date ? date.toISOString() : ''), min: startsAt ? new Date(startsAt) : undefined, max: new Date(new Date().getFullYear() + 10, 11, 31) })] }), _jsxs("div", { className: "flex gap-3", children: [_jsx(Input, { label: t('options.couponCode'), placeholder: t('options.couponCode'), value: couponCode, onChange: (e) => setField('couponCode', e.target.value) }), _jsx(Input, { label: t('options.usageLimit'), placeholder: t('options.usageLimit'), value: usageLimit, type: "number", onChange: (e) => setField('usageLimit', +e.target.value) }), _jsx(Input, { label: t('options.perCustomerUsageLimit'), placeholder: t('options.perCustomerUsageLimit'), value: perCustomerUsageLimit, type: "number", onChange: (e) => setField('perCustomerUsageLimit', +e.target.value) })] })] }) }));
|
|
5
|
+
return (_jsx(CustomCard, { title: t('options.header'), color: "orange", icon: _jsx(CardIcons.options, {}), children: _jsxs("div", { className: "flex flex-1 flex-col gap-y-4", children: [_jsxs("div", { className: "flex gap-3", children: [_jsx(DateTimePicker, { value: startsAt ? new Date(startsAt) : undefined, onChange: (date) => setField('startsAt', date ? date.toISOString() : ''), min: new Date(), max: endsAt ? new Date(endsAt) : undefined }), _jsx(DateTimePicker, { value: endsAt ? new Date(endsAt) : undefined, onChange: (date) => setField('endsAt', date ? date.toISOString() : ''), min: startsAt ? new Date(startsAt) : undefined, max: new Date(new Date().getFullYear() + 10, 11, 31) })] }), _jsxs("div", { className: "flex gap-3", children: [_jsx(Input, { label: t('options.couponCode'), placeholder: t('options.couponCode'), value: couponCode ?? '', onChange: (e) => setField('couponCode', e.target.value) }), _jsx(Input, { label: t('options.usageLimit'), placeholder: t('options.usageLimit'), value: usageLimit ?? '', type: "number", onChange: (e) => setField('usageLimit', +e.target.value) }), _jsx(Input, { label: t('options.perCustomerUsageLimit'), placeholder: t('options.perCustomerUsageLimit'), value: perCustomerUsageLimit ?? '', type: "number", onChange: (e) => setField('perCustomerUsageLimit', +e.target.value) })] })] }) }));
|
|
6
6
|
};
|
|
@@ -5,11 +5,14 @@ import { useDetailView, useQuery } from '@deenruv/react-ui-devkit';
|
|
|
5
5
|
import { useEffect } from 'react';
|
|
6
6
|
export const PromotionDetailSidebar = () => {
|
|
7
7
|
const { id, form } = useDetailView('promotions-detail-view', 'CreatePromotionInput', 'enabled');
|
|
8
|
-
const { base
|
|
9
|
-
|
|
8
|
+
const { base } = form;
|
|
9
|
+
// Always call useQuery unconditionally to preserve hook order.
|
|
10
|
+
// Pass a placeholder id when none exists; the result will simply be ignored.
|
|
11
|
+
const { data } = useQuery(PromotionQuery, { initialVariables: { id: id ?? '' } });
|
|
10
12
|
useEffect(() => {
|
|
11
|
-
if (data)
|
|
12
|
-
setField('enabled', data.promotion.enabled);
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
if (id && data?.promotion) {
|
|
14
|
+
base.setField('enabled', data.promotion.enabled);
|
|
15
|
+
}
|
|
16
|
+
}, [data, id]);
|
|
17
|
+
return (_jsx("div", { className: "flex w-full flex-col gap-4", children: _jsx(EnabledCard, { enabledValue: base.watch('enabled'), onEnabledChange: (e) => base.setField('enabled', e) }) }));
|
|
15
18
|
};
|
|
@@ -28,39 +28,45 @@ export const PromotionQuery = typedGql('query', { scalars })({
|
|
|
28
28
|
export const PromotionDetailView = () => {
|
|
29
29
|
const contentLng = useSettings((p) => p.translationsLanguage);
|
|
30
30
|
const { form, entity, fetchEntity, id } = useDetailView('promotions-detail-view', ...PROMOTION_FORM_KEYS);
|
|
31
|
-
const { base
|
|
32
|
-
// const { data } = useQuery(ConditionsQuery);
|
|
33
|
-
// const availableConditions = useMemo(() => {
|
|
34
|
-
// return data?.promotionConditions.filter((c) => !state.conditions?.value?.some((v) => v.code === c.code)) || [];
|
|
35
|
-
// }, [data, state.conditions?.value]);
|
|
31
|
+
const { base } = form;
|
|
36
32
|
useEffect(() => {
|
|
37
33
|
(async () => {
|
|
38
34
|
const res = await fetchEntity();
|
|
39
35
|
if (!res)
|
|
40
36
|
return;
|
|
41
|
-
setField('translations', res.translations);
|
|
42
|
-
setField('endsAt', res.endsAt);
|
|
43
|
-
setField('startsAt', res.startsAt);
|
|
44
|
-
setField('couponCode', res.couponCode);
|
|
45
|
-
setField('usageLimit', res.usageLimit);
|
|
46
|
-
setField('perCustomerUsageLimit', res.perCustomerUsageLimit);
|
|
47
|
-
setField('conditions', res.conditions.map((c) => ({ code: c.code, arguments: c.args })));
|
|
48
|
-
setField('actions', res.actions.map((a) => ({ code: a.code, arguments: a.args })));
|
|
37
|
+
base.setField('translations', res.translations);
|
|
38
|
+
base.setField('endsAt', res.endsAt);
|
|
39
|
+
base.setField('startsAt', res.startsAt);
|
|
40
|
+
base.setField('couponCode', res.couponCode);
|
|
41
|
+
base.setField('usageLimit', res.usageLimit);
|
|
42
|
+
base.setField('perCustomerUsageLimit', res.perCustomerUsageLimit);
|
|
43
|
+
base.setField('conditions', res.conditions.map((c) => ({ code: c.code, arguments: c.args })));
|
|
44
|
+
base.setField('actions', res.actions.map((a) => ({ code: a.code, arguments: a.args })));
|
|
49
45
|
})();
|
|
50
46
|
}, [contentLng]);
|
|
51
|
-
const translations = useMemo(() =>
|
|
47
|
+
const translations = useMemo(() => base.watch('translations') || [], [base.watch('translations')]);
|
|
52
48
|
const currentTranslationValue = useMemo(() => translations.find((v) => v.languageCode === contentLng), [translations, contentLng]);
|
|
53
49
|
const setTranslationField = useCallback((field, e) => {
|
|
54
|
-
|
|
50
|
+
const baseTranslation = currentTranslationValue ?? {
|
|
51
|
+
languageCode: contentLng,
|
|
52
|
+
name: '',
|
|
53
|
+
description: '',
|
|
54
|
+
};
|
|
55
|
+
base.setField('translations', setInArrayBy(translations, (t) => t.languageCode === contentLng, {
|
|
56
|
+
...baseTranslation,
|
|
55
57
|
[field]: e,
|
|
56
58
|
languageCode: contentLng,
|
|
57
59
|
}));
|
|
58
|
-
}, [contentLng, translations]);
|
|
59
|
-
return (_jsx("div", { children: _jsxs("form", { className: "flex flex-col gap-4", children: [_jsx(BasicFieldsCard, { currentTranslationValue: currentTranslationValue ?? undefined, onChange: setTranslationField, errors:
|
|
60
|
-
|
|
60
|
+
}, [contentLng, translations, currentTranslationValue]);
|
|
61
|
+
return (_jsx("div", { children: _jsxs("form", { className: "flex flex-col gap-4", children: [_jsx(BasicFieldsCard, { currentTranslationValue: currentTranslationValue ?? undefined, onChange: setTranslationField, errors: base.formState.errors?.translations?.message
|
|
62
|
+
? [base.formState.errors.translations.message]
|
|
63
|
+
: undefined }), _jsx(OptionsCard, { endsAt: base.watch('endsAt'), startsAt: base.watch('startsAt'), couponCode: base.watch('couponCode') ?? undefined, usageLimit: base.watch('usageLimit') ?? undefined, perCustomerUsageLimit: base.watch('perCustomerUsageLimit') ?? undefined, setField: base.setField }), _jsx(DetailViewMarker, { position: 'promotions-detail-view' }), _jsx(EntityCustomFields, { entityName: "promotion", id: id, hideButton: true, onChange: (customFields, translations) => {
|
|
64
|
+
base.setField('customFields', customFields);
|
|
61
65
|
if (translations)
|
|
62
|
-
setField('translations', translations);
|
|
66
|
+
base.setField('translations', translations);
|
|
63
67
|
}, initialValues: entity && 'customFields' in entity
|
|
64
68
|
? { customFields: entity.customFields, translations: entity.translations }
|
|
65
|
-
: { customFields: {} } }), _jsx(ConditionsCard, { value:
|
|
69
|
+
: { customFields: {} } }), _jsx(ConditionsCard, { value: base.watch('conditions'), onChange: base.setField, errors: base.formState.errors?.conditions?.message
|
|
70
|
+
? [base.formState.errors.conditions.message]
|
|
71
|
+
: undefined }), _jsx(ActionsCard, { value: base.watch('actions'), onChange: base.setField, errors: base.formState.errors?.actions?.message ? [base.formState.errors.actions.message] : undefined })] }) }));
|
|
66
72
|
};
|
|
@@ -15,14 +15,14 @@ export const RolesDetailPage = () => {
|
|
|
15
15
|
const { t } = useTranslation('roles');
|
|
16
16
|
const { nameValidator } = useValidators();
|
|
17
17
|
const onSubmitHandler = useCallback((data) => {
|
|
18
|
-
if (!data.code
|
|
18
|
+
if (!data.code) {
|
|
19
19
|
throw new Error('Name is required.');
|
|
20
20
|
}
|
|
21
21
|
const inputData = {
|
|
22
|
-
code: data.code
|
|
23
|
-
channelIds: data.channelIds
|
|
24
|
-
description: data.description
|
|
25
|
-
permissions: data.permissions
|
|
22
|
+
code: data.code,
|
|
23
|
+
channelIds: data.channelIds,
|
|
24
|
+
description: data.description,
|
|
25
|
+
permissions: data.permissions,
|
|
26
26
|
};
|
|
27
27
|
if (id) {
|
|
28
28
|
return update({
|
|
@@ -5,15 +5,16 @@ import { PermissionsCard } from "./PermissionsCard";
|
|
|
5
5
|
const ROLE_FORM_KEYS = ['CreateRoleInput', 'code', 'description', 'channelIds', 'permissions'];
|
|
6
6
|
export const RoleDetailView = () => {
|
|
7
7
|
const { form, fetchEntity, id } = useDetailView('roles-detail-view', ...ROLE_FORM_KEYS);
|
|
8
|
-
const { base
|
|
8
|
+
const { base } = form;
|
|
9
9
|
const { t } = useTranslation('roles');
|
|
10
10
|
const [allChannelOptions, setAllChannelOptions] = useState([]);
|
|
11
|
+
const channelIds = base.watch('channelIds');
|
|
11
12
|
const currentChannelOptions = useMemo(() => {
|
|
12
13
|
if (!allChannelOptions)
|
|
13
14
|
return undefined;
|
|
14
15
|
else
|
|
15
|
-
return
|
|
16
|
-
}, [allChannelOptions,
|
|
16
|
+
return channelIds?.map((id) => allChannelOptions.find((o) => o.value === id) || { value: id, label: id });
|
|
17
|
+
}, [allChannelOptions, channelIds]);
|
|
17
18
|
const fetchChannels = useCallback(async () => {
|
|
18
19
|
const response = await apiClient('query')({
|
|
19
20
|
channels: [
|
|
@@ -39,11 +40,15 @@ export const RoleDetailView = () => {
|
|
|
39
40
|
const res = await fetchEntity();
|
|
40
41
|
if (!res)
|
|
41
42
|
return;
|
|
42
|
-
setField('code', res.code);
|
|
43
|
-
setField('description', res.description);
|
|
44
|
-
setField('channelIds', res.channels.map((ch) => ch.id));
|
|
45
|
-
setField('permissions', res.permissions);
|
|
43
|
+
base.setField('code', res.code);
|
|
44
|
+
base.setField('description', res.description);
|
|
45
|
+
base.setField('channelIds', res.channels.map((ch) => ch.id));
|
|
46
|
+
base.setField('permissions', res.permissions);
|
|
46
47
|
})();
|
|
47
48
|
}, []);
|
|
48
|
-
return (_jsx("main", { className: "my-4", children: _jsxs("div", { className: "flex flex-col gap-3", children: [_jsx(CustomCard, { title: t('details.basic.title'), icon: _jsx(CardIcons.basic, {}), color: "green", children: _jsxs("div", { className: "flex flex-wrap items-start gap-4 p-0 pt-4 xl:flex-nowrap", children: [_jsx("div", { className: "flex basis-full md:basis-1/2 xl:basis-1/4", children: _jsx(Input, { label: t('details.basic.description'), value:
|
|
49
|
+
return (_jsx("main", { className: "my-4", children: _jsxs("div", { className: "flex flex-col gap-3", children: [_jsx(CustomCard, { title: t('details.basic.title'), icon: _jsx(CardIcons.basic, {}), color: "green", children: _jsxs("div", { className: "flex flex-wrap items-start gap-4 p-0 pt-4 xl:flex-nowrap", children: [_jsx("div", { className: "flex basis-full md:basis-1/2 xl:basis-1/4", children: _jsx(Input, { label: t('details.basic.description'), value: base.watch('description') ?? undefined, onChange: (e) => base.setField('description', e.target.value), errors: base.formState.errors?.description?.message
|
|
50
|
+
? [base.formState.errors.description.message]
|
|
51
|
+
: undefined, required: true }) }), _jsx("div", { className: "flex basis-full md:basis-1/2 xl:basis-1/4", children: _jsx(Input, { label: t('details.basic.code'), value: base.watch('code') ?? undefined, onChange: (e) => base.setField('code', e.target.value), errors: base.formState.errors?.code?.message ? [base.formState.errors.code.message] : undefined, required: true }) }), _jsxs("div", { className: "flex basis-full flex-col gap-[6px] xl:basis-1/2", children: [_jsx(Label, { children: t('details.basic.channels') }), _jsx(MultipleSelector, { options: allChannelOptions, value: currentChannelOptions, placeholder: t('details.basic.channelsPlaceholder'), onChange: (channelsOptions) => base.setField('channelIds', channelsOptions.map((o) => o.value)), hideClearAllButton: true })] })] }) }), _jsx(DetailViewMarker, { position: 'roles-detail-view' }), _jsx(PermissionsCard, { currentPermissions: base.watch('permissions') ?? undefined, onPermissionsChange: (e) => base.setField('permissions', e), errors: base.formState.errors?.permissions?.message
|
|
52
|
+
? [base.formState.errors.permissions.message]
|
|
53
|
+
: undefined })] }) }));
|
|
49
54
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { useCallback } from 'react';
|
|
3
3
|
import { useParams } from 'react-router';
|
|
4
|
-
import { useValidators, getMutation, useMutation, DetailView, createDeenruvForm
|
|
4
|
+
import { useValidators, getMutation, useMutation, DetailView, createDeenruvForm } from '@deenruv/react-ui-devkit';
|
|
5
5
|
import { SellerDetailView } from "./_components/SellerDetailView.js";
|
|
6
6
|
const CreateSellerMutation = getMutation('createSeller');
|
|
7
7
|
const EditSellerMutation = getMutation('updateSeller');
|
|
@@ -13,12 +13,12 @@ export const SellersDetailPage = () => {
|
|
|
13
13
|
const [remove] = useMutation(DeleteSellerMutation);
|
|
14
14
|
const { nameValidator } = useValidators();
|
|
15
15
|
const onSubmitHandler = useCallback((data) => {
|
|
16
|
-
if (!data.name
|
|
16
|
+
if (!data.name) {
|
|
17
17
|
throw new Error('Name is required.');
|
|
18
18
|
}
|
|
19
19
|
const inputData = {
|
|
20
|
-
name: data.name
|
|
21
|
-
...(data.customFields
|
|
20
|
+
name: data.name,
|
|
21
|
+
...(data.customFields ? { customFields: data.customFields } : {}),
|
|
22
22
|
};
|
|
23
23
|
if (id) {
|
|
24
24
|
return update({ input: { id, ...inputData } });
|
|
@@ -4,17 +4,17 @@ import { Card, CardContent, CardHeader, CardTitle, DetailViewMarker, Input, useD
|
|
|
4
4
|
export const SELLER_FORM_KEYS = ['CreateSellerInput', 'name', 'customFields'];
|
|
5
5
|
export const SellerDetailView = () => {
|
|
6
6
|
const { form, fetchEntity, entity, id } = useDetailView('sellers-detail-view', ...SELLER_FORM_KEYS);
|
|
7
|
-
const { base
|
|
7
|
+
const { base } = form;
|
|
8
8
|
const { t } = useTranslation('sellers');
|
|
9
9
|
useEffect(() => {
|
|
10
10
|
(async () => {
|
|
11
11
|
const res = await fetchEntity();
|
|
12
12
|
if (!res)
|
|
13
13
|
return;
|
|
14
|
-
setField('name', res.name);
|
|
14
|
+
base.setField('name', res.name);
|
|
15
15
|
})();
|
|
16
16
|
}, []);
|
|
17
|
-
return (_jsx("main", { className: "my-4 min-h-96", children: _jsxs("div", { className: "flex flex-col gap-3", children: [_jsx(Card, { children: _jsxs(CardHeader, { children: [_jsx(CardTitle, { className: "flex flex-row justify-between text-base", children: t('details.basic.title') }), _jsx(CardContent, { className: "flex flex-col gap-4 p-0 pt-4", children: _jsx("div", { className: "flex flex-col gap-3", children: _jsx(Input, { className: "w-1/2", label: t('details.basic.name'), value:
|
|
18
|
-
setField('customFields', customFields);
|
|
17
|
+
return (_jsx("main", { className: "my-4 min-h-96", children: _jsxs("div", { className: "flex flex-col gap-3", children: [_jsx(Card, { children: _jsxs(CardHeader, { children: [_jsx(CardTitle, { className: "flex flex-row justify-between text-base", children: t('details.basic.title') }), _jsx(CardContent, { className: "flex flex-col gap-4 p-0 pt-4", children: _jsx("div", { className: "flex flex-col gap-3", children: _jsx(Input, { className: "w-1/2", label: t('details.basic.name'), value: base.watch('name'), onChange: (e) => base.setField('name', e.target.value), errors: base.formState.errors?.name?.message ? [base.formState.errors.name.message] : undefined, required: true }) }) })] }) }), _jsx(DetailViewMarker, { position: 'sellers-detail-view' }), _jsx(EntityCustomFields, { entityName: "seller", id: id, hideButton: true, onChange: (customFields) => {
|
|
18
|
+
base.setField('customFields', customFields);
|
|
19
19
|
}, initialValues: entity && 'customFields' in entity ? { customFields: entity.customFields } : { customFields: {} } })] }) }));
|
|
20
20
|
};
|