@ozdao/martyrs 0.2.524 → 0.2.526
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/_virtual/index.cjs +4 -4
- package/dist/_virtual/index.js +4 -4
- package/dist/_virtual/index2.cjs +4 -4
- package/dist/_virtual/index2.js +4 -4
- package/dist/community.server.cjs +1 -1
- package/dist/community.server.js +1 -1
- package/dist/{crud-CC6k6yY5.cjs → crud-DGM6Xa1R.cjs} +1 -1
- package/dist/{crud-BIFl1W1i.js → crud-Ed3dcRsC.js} +1 -1
- package/dist/events.server.cjs +1 -1
- package/dist/events.server.js +1 -1
- package/dist/gallery.server.cjs +1 -1
- package/dist/gallery.server.js +1 -1
- package/dist/{globals.verifier-DFqKQ7hK.js → globals.verifier-BhqUrneb.js} +31 -1
- package/dist/{globals.verifier-C0zj_LLo.cjs → globals.verifier-CJ1lr-NW.cjs} +31 -1
- package/dist/inventory.server.cjs +3 -3
- package/dist/inventory.server.js +3 -3
- package/dist/{main-BM3GslOO.cjs → main-4KvvKtzH.cjs} +6 -6
- package/dist/{main-Qcn7YlTx.js → main-Bk4xq-K0.js} +45 -37
- package/dist/martyrs/src/components/Feed/Feed.vue.cjs +1 -1
- package/dist/martyrs/src/components/Feed/Feed.vue.cjs.map +1 -1
- package/dist/martyrs/src/components/Feed/Feed.vue.js +1 -1
- package/dist/martyrs/src/components/Feed/Feed.vue.js.map +1 -1
- package/dist/martyrs/src/components/FieldTags/FieldTags.vue.cjs +1 -1
- package/dist/martyrs/src/components/FieldTags/FieldTags.vue.js +1 -1
- package/dist/martyrs/src/components/Tree/Tree.vue.cjs +19 -33
- package/dist/martyrs/src/components/Tree/Tree.vue.cjs.map +1 -1
- package/dist/martyrs/src/components/Tree/Tree.vue.js +19 -33
- package/dist/martyrs/src/components/Tree/Tree.vue.js.map +1 -1
- package/dist/martyrs/src/modules/community/components/pages/CreateBlogPost.vue.cjs +1 -1
- package/dist/martyrs/src/modules/community/components/pages/CreateBlogPost.vue.js +1 -1
- package/dist/martyrs/src/modules/globals/views/classes/globals.i18n.cjs +1 -1
- package/dist/martyrs/src/modules/globals/views/classes/globals.i18n.js +1 -1
- package/dist/martyrs/src/modules/globals/views/components/blocks/PopupDateSelector.vue.cjs +1 -1
- package/dist/martyrs/src/modules/globals/views/components/blocks/PopupDateSelector.vue.cjs.map +1 -1
- package/dist/martyrs/src/modules/globals/views/components/blocks/PopupDateSelector.vue.js +1 -1
- package/dist/martyrs/src/modules/globals/views/components/blocks/PopupDateSelector.vue.js.map +1 -1
- package/dist/martyrs/src/modules/globals/views/store/globals.cjs +14 -2
- package/dist/martyrs/src/modules/globals/views/store/globals.cjs.map +1 -1
- package/dist/martyrs/src/modules/globals/views/store/globals.js +14 -2
- package/dist/martyrs/src/modules/globals/views/store/globals.js.map +1 -1
- package/dist/martyrs/src/modules/notifications/notifications.client.cjs +25 -5
- package/dist/martyrs/src/modules/notifications/notifications.client.cjs.map +1 -1
- package/dist/martyrs/src/modules/notifications/notifications.client.js +25 -5
- package/dist/martyrs/src/modules/notifications/notifications.client.js.map +1 -1
- package/dist/martyrs/src/modules/notifications/store/notifications.store.cjs +6 -1
- package/dist/martyrs/src/modules/notifications/store/notifications.store.cjs.map +1 -1
- package/dist/martyrs/src/modules/notifications/store/notifications.store.js +6 -1
- package/dist/martyrs/src/modules/notifications/store/notifications.store.js.map +1 -1
- package/dist/martyrs/src/modules/products/components/pages/Categories.vue.cjs +27 -19
- package/dist/martyrs/src/modules/products/components/pages/Categories.vue.cjs.map +1 -1
- package/dist/martyrs/src/modules/products/components/pages/Categories.vue.js +27 -19
- package/dist/martyrs/src/modules/products/components/pages/Categories.vue.js.map +1 -1
- package/dist/martyrs/src/modules/products/components/pages/ProductEdit.vue.cjs +76 -44
- package/dist/martyrs/src/modules/products/components/pages/ProductEdit.vue.cjs.map +1 -1
- package/dist/martyrs/src/modules/products/components/pages/ProductEdit.vue.js +76 -44
- package/dist/martyrs/src/modules/products/components/pages/ProductEdit.vue.js.map +1 -1
- package/dist/martyrs/src/modules/products/components/pages/Products.vue.cjs +0 -1
- package/dist/martyrs/src/modules/products/components/pages/Products.vue.cjs.map +1 -1
- package/dist/martyrs/src/modules/products/components/pages/Products.vue.js +0 -1
- package/dist/martyrs/src/modules/products/components/pages/Products.vue.js.map +1 -1
- package/dist/martyrs/src/modules/products/store/products.cjs +12 -2
- package/dist/martyrs/src/modules/products/store/products.cjs.map +1 -1
- package/dist/martyrs/src/modules/products/store/products.js +12 -2
- package/dist/martyrs/src/modules/products/store/products.js.map +1 -1
- package/dist/martyrs.cjs.js +1 -1
- package/dist/martyrs.es.js +1 -1
- package/dist/music.server.cjs +2 -2
- package/dist/music.server.js +2 -2
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/utils.cjs +1 -1
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/utils.js +1 -1
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/renderer/utils.cjs +1 -1
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/renderer/utils.js +1 -1
- package/dist/notifications.server.cjs +8 -3
- package/dist/notifications.server.js +8 -3
- package/dist/orders.server.cjs +3 -3
- package/dist/orders.server.js +3 -3
- package/dist/organizations.server.cjs +2 -2
- package/dist/organizations.server.js +2 -2
- package/dist/products.server.cjs +34 -22
- package/dist/products.server.js +34 -22
- package/dist/{queryProcessor-B_X680wC.cjs → queryProcessor-DMSc5-r6.cjs} +17 -20
- package/dist/{queryProcessor-CVcLPEnv.js → queryProcessor-rukV_SBd.js} +17 -20
- package/dist/rents.server.cjs +2 -2
- package/dist/rents.server.js +2 -2
- package/dist/spots.server.cjs +1 -1
- package/dist/spots.server.js +1 -1
- package/dist/{web-DVR8m2fm.js → web-BS-4Xl3x.js} +1 -1
- package/dist/{web-B0cfxzgu.cjs → web-CjndIDjT.cjs} +1 -1
- package/package.json +1 -1
- package/src/components/Feed/Feed.vue +1 -1
- package/src/components/Tree/Tree.vue +27 -15
- package/src/modules/globals/controllers/classes/globals.validator.js +32 -1
- package/src/modules/globals/controllers/utils/queryProcessor.js +27 -20
- package/src/modules/globals/views/components/blocks/PopupDateSelector.vue +1 -1
- package/src/modules/globals/views/store/globals.js +19 -2
- package/src/modules/notifications/controllers/notifications.controller.js +14 -6
- package/src/modules/notifications/notifications.client.js +27 -6
- package/src/modules/notifications/store/notifications.store.js +6 -1
- package/src/modules/products/components/pages/Categories.vue +41 -26
- package/src/modules/products/components/pages/ProductEdit.vue +45 -21
- package/src/modules/products/components/pages/Products.vue +0 -1
- package/src/modules/products/controllers/categories.controller.js +3 -17
- package/src/modules/products/controllers/products.controller.js +34 -1
- package/src/modules/products/middlewares/categories.verifier.js +1 -1
- package/src/modules/products/middlewares/variants.verifier.js +2 -2
- package/src/modules/products/store/products.js +10 -0
- package/src/modules/products/TASKS.MD +0 -1
|
@@ -41,8 +41,9 @@ const _hoisted_11 = {
|
|
|
41
41
|
class: "t-small t-transp"
|
|
42
42
|
};
|
|
43
43
|
const _hoisted_12 = { class: "mn-b-thin flex-nowrap flex gap-thin" };
|
|
44
|
-
const _hoisted_13 = { class: "
|
|
45
|
-
const _hoisted_14 = { class: "flex-
|
|
44
|
+
const _hoisted_13 = { class: "flex gap-thin mn-b-thin" };
|
|
45
|
+
const _hoisted_14 = { class: "radius-small pd-small flex-center flex aspect-1x1 bg-red cursor-pointer hover-scale-1" };
|
|
46
|
+
const _hoisted_15 = { class: "flex-nowrap flex gap-thin" };
|
|
46
47
|
const _sfc_main = {
|
|
47
48
|
__name: "ProductEdit",
|
|
48
49
|
emits: ["page-loading", "page-loaded"],
|
|
@@ -58,39 +59,32 @@ const _sfc_main = {
|
|
|
58
59
|
if (route.params.product) {
|
|
59
60
|
await products.actions.read({ _id: route.params.product, lookup: ["variants", "categories", "recommended"] });
|
|
60
61
|
} else {
|
|
61
|
-
if (!products.state.current.
|
|
62
|
-
products.state.current.
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
62
|
+
if (!products.state.current.translations) {
|
|
63
|
+
products.state.current.translations = [];
|
|
64
|
+
}
|
|
65
|
+
if (!products.state.current.recommended) {
|
|
66
|
+
products.state.current.recommended = [];
|
|
67
|
+
}
|
|
68
|
+
if (!products.state.current.discounts) {
|
|
69
|
+
products.state.current.discounts = [];
|
|
70
|
+
}
|
|
71
|
+
if (!products.state.current.defaultVariant) {
|
|
72
|
+
products.state.current.defaultVariant = {
|
|
73
|
+
price: null,
|
|
68
74
|
quantity: 1,
|
|
69
|
-
unit: "pcs"
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
75
|
+
unit: "pcs"
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
try {
|
|
79
|
+
categories.state.all = await categories.actions.read({
|
|
80
|
+
user: auth.state.user._id,
|
|
81
|
+
rootOnly: true,
|
|
82
|
+
excludeChildren: false,
|
|
83
|
+
limit: 100
|
|
84
|
+
});
|
|
85
|
+
} catch (error) {
|
|
86
|
+
console.error("error loading categories:", error);
|
|
74
87
|
}
|
|
75
|
-
}
|
|
76
|
-
if (!products.state.current.translations) {
|
|
77
|
-
products.state.current.translations = [];
|
|
78
|
-
}
|
|
79
|
-
if (!products.state.current.recommended) {
|
|
80
|
-
products.state.current.recommended = [];
|
|
81
|
-
}
|
|
82
|
-
if (!products.state.current.discounts) {
|
|
83
|
-
products.state.current.discounts = [];
|
|
84
|
-
}
|
|
85
|
-
try {
|
|
86
|
-
categories.state.all = await categories.actions.read({
|
|
87
|
-
user: auth.state.user._id,
|
|
88
|
-
rootOnly: true,
|
|
89
|
-
excludeChildren: false,
|
|
90
|
-
limit: 100
|
|
91
|
-
});
|
|
92
|
-
} catch (error) {
|
|
93
|
-
console.error("error loading categories:", error);
|
|
94
88
|
}
|
|
95
89
|
emits("page-loaded");
|
|
96
90
|
isPageLoaded.value = true;
|
|
@@ -109,7 +103,11 @@ const _sfc_main = {
|
|
|
109
103
|
type: "user",
|
|
110
104
|
hidden: false
|
|
111
105
|
};
|
|
112
|
-
|
|
106
|
+
const productData = {
|
|
107
|
+
...products.state.current,
|
|
108
|
+
defaultVariant: products.state.current.defaultVariant
|
|
109
|
+
};
|
|
110
|
+
await products.actions.create(productData);
|
|
113
111
|
}
|
|
114
112
|
redirectTo();
|
|
115
113
|
} catch (error) {
|
|
@@ -140,7 +138,7 @@ const _sfc_main = {
|
|
|
140
138
|
callback: redirectTo,
|
|
141
139
|
class: "w-10 w-max-20r w-min-8r bg-red"
|
|
142
140
|
}, {
|
|
143
|
-
default: vue.withCtx(() => _cache[
|
|
141
|
+
default: vue.withCtx(() => _cache[15] || (_cache[15] = [
|
|
144
142
|
vue.createTextVNode(" Delete ")
|
|
145
143
|
])),
|
|
146
144
|
_: 1
|
|
@@ -150,7 +148,7 @@ const _sfc_main = {
|
|
|
150
148
|
callback: redirectTo,
|
|
151
149
|
class: "w-10 w-max-20r w-min-8r bg-main"
|
|
152
150
|
}, {
|
|
153
|
-
default: vue.withCtx(() => _cache[
|
|
151
|
+
default: vue.withCtx(() => _cache[16] || (_cache[16] = [
|
|
154
152
|
vue.createTextVNode(" Save ")
|
|
155
153
|
])),
|
|
156
154
|
_: 1
|
|
@@ -312,25 +310,59 @@ const _sfc_main = {
|
|
|
312
310
|
]),
|
|
313
311
|
_: 1
|
|
314
312
|
}),
|
|
313
|
+
!vue.unref(route).params.product ? (vue.openBlock(), vue.createBlock(Block.default, {
|
|
314
|
+
key: 0,
|
|
315
|
+
title: "Price"
|
|
316
|
+
}, {
|
|
317
|
+
default: vue.withCtx(() => [
|
|
318
|
+
vue.createElementVNode("div", _hoisted_13, [
|
|
319
|
+
vue.createVNode(Field.default, {
|
|
320
|
+
field: products.state.current.defaultVariant.price,
|
|
321
|
+
"onUpdate:field": _cache[8] || (_cache[8] = ($event) => products.state.current.defaultVariant.price = $event),
|
|
322
|
+
label: "Price",
|
|
323
|
+
type: "number",
|
|
324
|
+
placeholder: "Enter price",
|
|
325
|
+
class: "w-100 bg-white radius-small pd-medium"
|
|
326
|
+
}, null, 8, ["field"]),
|
|
327
|
+
vue.createVNode(Field.default, {
|
|
328
|
+
field: products.state.current.defaultVariant.quantity,
|
|
329
|
+
"onUpdate:field": _cache[9] || (_cache[9] = ($event) => products.state.current.defaultVariant.quantity = $event),
|
|
330
|
+
label: "Quantity",
|
|
331
|
+
type: "number",
|
|
332
|
+
placeholder: "Enter quantity",
|
|
333
|
+
class: "w-100 bg-white radius-small pd-medium"
|
|
334
|
+
}, null, 8, ["field"]),
|
|
335
|
+
vue.createVNode(Select.default, {
|
|
336
|
+
select: products.state.current.defaultVariant.unit,
|
|
337
|
+
"onUpdate:select": _cache[10] || (_cache[10] = ($event) => products.state.current.defaultVariant.unit = $event),
|
|
338
|
+
label: "Unit",
|
|
339
|
+
options: ["pcs", "g", "kg", "ml", "l", "oz"],
|
|
340
|
+
placeholder: "Select unit",
|
|
341
|
+
class: "w-100 bg-white radius-small pd-medium"
|
|
342
|
+
}, null, 8, ["select"])
|
|
343
|
+
])
|
|
344
|
+
]),
|
|
345
|
+
_: 1
|
|
346
|
+
})) : vue.createCommentVNode("", true),
|
|
315
347
|
vue.createVNode(EditAttributes.default, {
|
|
316
348
|
attributes: products.state.current.attributes,
|
|
317
|
-
"onUpdate:attributes": _cache[
|
|
349
|
+
"onUpdate:attributes": _cache[11] || (_cache[11] = ($event) => products.state.current.attributes = $event)
|
|
318
350
|
}, null, 8, ["attributes"])
|
|
319
351
|
])) : vue.createCommentVNode("", true),
|
|
320
352
|
vue.unref(activeTab) === "variants" ? (vue.openBlock(), vue.createBlock(EditVariants.default, {
|
|
321
353
|
key: 3,
|
|
322
354
|
variants: products.state.current.variants,
|
|
323
|
-
"onUpdate:variants": _cache[
|
|
355
|
+
"onUpdate:variants": _cache[12] || (_cache[12] = ($event) => products.state.current.variants = $event)
|
|
324
356
|
}, null, 8, ["variants"])) : vue.createCommentVNode("", true),
|
|
325
357
|
vue.unref(activeTab) === "discounts" ? (vue.openBlock(), vue.createBlock(EditDiscounts.default, {
|
|
326
358
|
key: 4,
|
|
327
359
|
discounts: products.state.current.discounts,
|
|
328
|
-
"onUpdate:discounts": _cache[
|
|
360
|
+
"onUpdate:discounts": _cache[13] || (_cache[13] = ($event) => products.state.current.discounts = $event)
|
|
329
361
|
}, null, 8, ["discounts"])) : vue.createCommentVNode("", true),
|
|
330
362
|
vue.unref(activeTab) === "recommended" ? (vue.openBlock(), vue.createBlock(EditRecommended.default, {
|
|
331
363
|
key: 5,
|
|
332
364
|
recommended: products.state.current.recommended,
|
|
333
|
-
"onUpdate:recommended": _cache[
|
|
365
|
+
"onUpdate:recommended": _cache[14] || (_cache[14] = ($event) => products.state.current.recommended = $event),
|
|
334
366
|
class: "cols-1 gap-thin"
|
|
335
367
|
}, null, 8, ["recommended"])) : vue.createCommentVNode("", true),
|
|
336
368
|
vue.unref(activeTab) === "localization" ? (vue.openBlock(), vue.createBlock(Block.default, {
|
|
@@ -366,7 +398,7 @@ const _sfc_main = {
|
|
|
366
398
|
placeholder: "Product description",
|
|
367
399
|
class: "w-100 bg-white radius-small pd-medium"
|
|
368
400
|
}, null, 8, ["field", "onUpdate:field"]),
|
|
369
|
-
vue.createElementVNode("div",
|
|
401
|
+
vue.createElementVNode("div", _hoisted_14, [
|
|
370
402
|
vue.createVNode(IconDelete.default, {
|
|
371
403
|
onClick: () => products.state.current.translations.splice(index, 1),
|
|
372
404
|
class: "i-medium"
|
|
@@ -377,13 +409,13 @@ const _sfc_main = {
|
|
|
377
409
|
]),
|
|
378
410
|
_: 1
|
|
379
411
|
}, 8, ["actions"])) : vue.createCommentVNode("", true),
|
|
380
|
-
vue.createElementVNode("div",
|
|
412
|
+
vue.createElementVNode("div", _hoisted_15, [
|
|
381
413
|
vue.unref(route).params.product ? (vue.openBlock(), vue.createBlock(Button.default, {
|
|
382
414
|
key: 0,
|
|
383
415
|
submit: onDelete,
|
|
384
416
|
class: "bg-red t-white w-100"
|
|
385
417
|
}, {
|
|
386
|
-
default: vue.withCtx(() => _cache[
|
|
418
|
+
default: vue.withCtx(() => _cache[17] || (_cache[17] = [
|
|
387
419
|
vue.createTextVNode(" Delete ")
|
|
388
420
|
])),
|
|
389
421
|
_: 1
|
|
@@ -392,7 +424,7 @@ const _sfc_main = {
|
|
|
392
424
|
submit: onSubmit,
|
|
393
425
|
class: "w-100 bg-main"
|
|
394
426
|
}, {
|
|
395
|
-
default: vue.withCtx(() => _cache[
|
|
427
|
+
default: vue.withCtx(() => _cache[18] || (_cache[18] = [
|
|
396
428
|
vue.createTextVNode(" Save ")
|
|
397
429
|
])),
|
|
398
430
|
_: 1
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProductEdit.vue.cjs","sources":["../../../../../../../src/modules/products/components/pages/ProductEdit.vue"],"sourcesContent":["<template>\n <div v-if=\"isPageLoaded\" class=\"w-100 bg-white pd-thin gap-thin\">\n \n <Block v-if=\"!MOBILE_APP\" class=\"flex-nowrap mn-b-thin gap-thin flex-v-center flex\">\n <h2 class=\"t-truncate mn-r-auto\">\n {{ route.params.product ? products.state.current.name : 'Create Product' }}\n </h2>\n\n <Button \n v-if=\"route.params.product\"\n :submit=\"onDelete\" \n :callback=\"redirectTo\"\n class=\"w-10 w-max-20r w-min-8r bg-red\"\n >\n Delete \n </Button>\n\n <Button \n :submit=\"onSubmit\" \n :callback=\"redirectTo\"\n class=\"w-10 w-max-20r w-min-8r bg-main\"\n >\n Save\n </Button>\n </Block>\n\n <!-- Tab Navigation -->\n <Tab\n v-model:selected=\"activeTab\"\n v-if=\"route.params.product\"\n :tabs=\"[\n { label: 'Details', value: 'details' },\n { label: 'Variants', value: 'variants' },\n { label: 'Discounts', value: 'discounts' },\n { label: 'Recommended', value: 'recommended' },\n { label: 'Localization', value: 'localization' }\n ]\"\n class=\"flex-child-default gap-micro scroll-hide bg-light radius-medium h-max pd-thin mn-b-thin o-x-scroll\"\n classTab=\"bg-white\"\n />\n\n <!-- Tab Content -->\n <div v-if=\"activeTab === 'details'\" class=\"cols-1 gap-thin\">\n <!-- Product Images -->\n <Block\n placeholder=\"The product doesn't have any images yet.\"\n class=\"h-min\"\n >\n <EditImages \n :images=\"products.state.current.images\"\n :uploadPath=\"'photos'\" \n @update:images=\"(imagesNew) => { products.state.current.images = imagesNew }\" \n />\n </Block>\n\n <Block title=\"Categories\">\n <BlockMultiselect\n v-model=\"products.state.current.category\"\n placeholder=\"Search categories...\"\n :multiple=\"true\"\n :transform=\"(item) => ({ _id: item._id, name: item.name })\"\n :store=\"{\n read: (options) => categories.actions.read(options),\n state: categories.state\n }\"\n :options=\"{\n rootOnly: false,\n excludeChildren: false,\n limit: 50\n }\"\n :skeleton=\"{\n hide: false,\n horizontal: true,\n class: 'radius-small',\n structure: [{ \n block: 'text', size: 'large'\n }]\n }\"\n :states=\"{\n empty: {\n title: 'No categories found',\n description: 'Try different search terms or create a new category',\n class: 'radius-small'\n }\n }\"\n key=\"_id\"\n :label=\"item => item.name\"\n classSearch=\"bg-white radius-small\"\n classSelected=\"bg-white pd-small radius-small\"\n classDropdown=\"bg-white pd-small radius-medium bs-small\"\n classItem=\"pd-small radius-small hover-bg-light cursor-pointer\"\n classFeed=\"h-max-30r gap-thin flex-column flex o-scroll\"\n >\n <!-- Слот для выбранных категорий -->\n <template #selected=\"{ item, clear }\">\n <div class=\"flex-nowrap flex-v-center flex gap-thin\">\n <span class=\"t-medium\">{{ item?.name || item }}</span>\n <button \n @click.stop=\"clear\"\n class=\"i-small pd-micro bg-red radius-extra flex-center flex aspect-1x1 hover-scale-1\"\n >\n <IconCross class=\"i-micro fill-white\" />\n </button>\n </div>\n </template>\n \n <!-- Слот для элементов в списке -->\n <template #item=\"{ item }\">\n <div class=\"flex-nowrap flex-v-center flex\">\n <img \n v-if=\"item.photo\" \n :src=\"(FILE_SERVER_URL || '') + item.photo\"\n class=\"i-medium radius-small object-fit-cover mn-r-thin\"\n />\n <div class=\"w-100\">\n <p class=\"t-medium\">{{ item.name }}</p>\n <p v-if=\"item.description\" class=\"t-small t-transp\">{{ item.description }}</p>\n </div>\n </div>\n </template>\n </BlockMultiselect>\n </Block>\n\n <!-- Product Profile -->\n <Block title=\"Profile\">\n <div class=\"mn-b-thin flex-nowrap flex gap-thin\">\n <Select \n v-model:select=\"products.state.current.status\"\n label=\"Status\"\n :options=\"[\n 'draft', \n 'published',\n 'featured',\n 'archived',\n 'removed'\n ]\"\n placeholder=\"Display product\"\n class=\"pos-relative w-100 bg-white radius-small pd-medium\"\n />\n <Select \n v-model:select=\"products.state.current.listing\"\n label=\"Type\"\n :options=\"[\n 'sale', \n 'rent',\n ]\"\n placeholder=\"Type of listing\"\n class=\"pos-relative w-100 bg-white radius-small pd-medium\"\n />\n </div>\n\n <Field \n v-model:field=\"products.state.current.name\" \n placeholder=\"Enter product name\"\n class=\"w-100 mn-b-thin bg-white radius-small pd-medium\"\n />\n <Field\n v-model:field=\"products.state.current.description\" \n placeholder=\"Enter product description\" \n class=\"w-100 bg-white radius-small mn-b-thin pd-medium\"\n style=\"resize: vertical\"\n type=\"textarea\"\n />\n <Field\n v-model:field=\"products.state.current.included\" \n placeholder=\"Enter what's inside\" \n class=\"w-100 bg-white radius-small pd-medium\"\n style=\"resize: vertical\"\n type=\"textarea\"\n />\n </Block>\n <!-- Categories -->\n \n\n\n <!-- Attributes -->\n <EditAttributes \n v-model:attributes=\"products.state.current.attributes\" \n />\n </div>\n\n <!-- Variants Tab -->\n <EditVariants\n\t\t\tv-if=\"activeTab === 'variants'\"\n v-model:variants=\"products.state.current.variants\" \n />\n\n <!-- Discounts Tab -->\n <EditDiscounts\n\t\t\tv-if=\"activeTab === 'discounts'\"\n v-model:discounts=\"products.state.current.discounts\"\n />\n <EditRecommended \n v-if=\"activeTab === 'recommended'\" \n v-model:recommended=\"products.state.current.recommended\"\n class=\"cols-1 gap-thin\"\n />\n\n <!-- Localization Tab -->\n <Block\n\t\t v-if=\"activeTab === 'localization'\"\n title=\"Localization\"\n placeholder=\"No localizations added yet\"\n :actions=\"[{\n label: '+',\n function: () => products.state.current.translations.push({locale: '', name: '', description: ''})\n }]\"\n >\n <div \n class=\"gap-thin mn-b-thin flex-nowrap flex\" \n v-for=\"(item, index) in products.state.current.translations\" \n :key=\"index\"\n > \n <Field\n v-model:field=\"item.locale\"\n placeholder=\"Locale (en, ru, etc.)\"\n class=\"w-30 bg-white radius-small pd-medium\"\n /> \n <Field\n v-model:field=\"item.name\"\n placeholder=\"Product name\"\n class=\"w-100 bg-white radius-small pd-medium\"\n />\n <Field\n v-model:field=\"item.description\"\n placeholder=\"Product description\"\n class=\"w-100 bg-white radius-small pd-medium\"\n />\n <div class=\"radius-small pd-small flex-center flex aspect-1x1 bg-red cursor-pointer hover-scale-1\">\n <IconDelete \n @click=\"() => products.state.current.translations.splice(index, 1)\" \n class=\"i-medium\"\n />\n </div>\n </div>\n </Block>\n\n <!-- Bottom Action Buttons -->\n <div class=\"flex-nowrap flex gap-thin\">\n <Button \n v-if=\"route.params.product\"\n :submit=\"onDelete\" \n class=\"bg-red t-white w-100\"\n >\n Delete \n </Button>\n\n <Button \n :submit=\"onSubmit\" \n class=\"w-100 bg-main\"\n >\n Save\n </Button>\n </div>\n </div>\n</template>\n\n<script setup>\n// Import libs\nimport { reactive, computed, onMounted, ref } from 'vue'\nimport { useRoute, useRouter } from 'vue-router'\n\n// Import components\nimport Block from '@martyrs/src/components/Block/Block.vue';\nimport Tab from \"@martyrs/src/components/Tab/Tab.vue\";\nimport Field from \"@martyrs/src/components/Field/Field.vue\";\nimport Select from '@martyrs/src/components/Select/Select.vue';\nimport Checkbox from \"@martyrs/src/components/Checkbox/Checkbox.vue\";\nimport Button from \"@martyrs/src/components/Button/Button.vue\";\nimport Tree from \"@martyrs/src/components/Tree/Tree.vue\";\nimport EditImages from '@martyrs/src/components/EditImages/EditImages.vue';\n\nimport BlockMultiselect from '@martyrs/src/modules/globals/views/components/blocks/BlockMultiselect.vue';\nimport IconCross from '@martyrs/src/modules/icons/navigation/IconCross.vue';\nimport IconDelete from '@martyrs/src/modules/icons/navigation/IconDelete.vue';\n\nimport EditVariants from '@martyrs/src/modules/products/components/sections/EditVariants.vue';\nimport EditAttributes from '@martyrs/src/modules/products/components/sections/EditAttributes.vue';\nimport EditDiscounts from '@martyrs/src/modules/products/components/sections/EditDiscounts.vue';\nimport EditCategories from '@martyrs/src/modules/products/components/sections/EditCategories.vue';\nimport EditRecommended from '@martyrs/src/modules/products/components/sections/EditRecommended.vue';\n\n// Accessing router and store\nimport * as globals from '@martyrs/src/modules/globals/views/store/globals.js';\nimport * as auth from '@martyrs/src/modules/auth/views/store/auth.js';\nimport * as products from '@martyrs/src/modules/products/store/products.js';\nimport * as categories from '@martyrs/src/modules/products/store/categories.js';\n\nimport { setError } from '@martyrs/src/modules/globals/views/store/globals.js'\n\nconst route = useRoute()\nconst router = useRouter()\nconst emits = defineEmits(['page-loading', 'page-loaded']);\n\nlet isPageLoaded = ref(false)\nlet activeTab = ref('details')\n\nonMounted(async() => { \n emits('page-loading');\n\n products.mutations.resetProduct();\n\n if (route.params.product) {\n await products.actions.read({ _id: route.params.product, lookup: ['variants','categories','recommended'] });\n } else {\n // Создаем дефолтный вариант для нового товара\n if (!products.state.current.variants || products.state.current.variants.length === 0) {\n products.state.current.variants = [{\n name: 'Default',\n sku: '',\n images: [],\n price: 0,\n cost: 0,\n quantity: 1,\n unit: 'pcs',\n available: 0,\n ingredients: [],\n attributes: []\n }];\n }\n }\n\n // Убедимся, что массивы инициализированы\n if (!products.state.current.translations) {\n products.state.current.translations = []\n }\n // Убедимся, что массивы инициализированы\n if (!products.state.current.recommended) {\n products.state.current.recommended = []\n }\n if (!products.state.current.discounts) {\n products.state.current.discounts = []\n }\n\n try {\n // Data prefetching\n categories.state.all = await categories.actions.read({\n user: auth.state.user._id,\n rootOnly: true,\n excludeChildren: false,\n limit: 100\n })\n } catch (error) {\n console.error('error loading categories:', error);\n }\n\n emits('page-loaded');\n isPageLoaded.value = true\n})\n\nasync function onSubmit() {\n try {\n if (route.params.product) {\n await products.actions.update(route.params.product, products.state.current)\n } else {\n products.state.current.owner = {\n target: route.params._id || auth.state.user._id,\n type: route.params._id ? 'organization' : 'user'\n }\n products.state.current.creator = {\n target: auth.state.user._id,\n type: 'user',\n hidden: false\n }\n await products.actions.create(products.state.current)\n }\n \n redirectTo()\n } catch (error) {\n setError({ response: { data: { errorCode: \"PRODUCT_NOT_CREATED\" }} })\n console.error('Product creation error:', error)\n }\n}\n\nfunction onDelete() {\n products.actions.deleteProduct(products.state.current._id)\n}\n\nfunction redirectTo() {\n router.push({\n name: route.params._id ? 'Organization' : 'Products', \n params: route.params._id ? { _id: route.params._id } : {}\n })\n}\n</script>"],"names":["useRoute","useRouter","ref","onMounted","products.mutations","products.actions","products.state","categories.state","categories.actions","auth.state","setError"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ProductEdit.vue.cjs","sources":["../../../../../../../src/modules/products/components/pages/ProductEdit.vue"],"sourcesContent":["<template>\n <div v-if=\"isPageLoaded\" class=\"w-100 bg-white pd-thin gap-thin\">\n \n <Block v-if=\"!MOBILE_APP\" class=\"flex-nowrap mn-b-thin gap-thin flex-v-center flex\">\n <h2 class=\"t-truncate mn-r-auto\">\n {{ route.params.product ? products.state.current.name : 'Create Product' }}\n </h2>\n\n <Button \n v-if=\"route.params.product\"\n :submit=\"onDelete\" \n :callback=\"redirectTo\"\n class=\"w-10 w-max-20r w-min-8r bg-red\"\n >\n Delete \n </Button>\n\n <Button \n :submit=\"onSubmit\" \n :callback=\"redirectTo\"\n class=\"w-10 w-max-20r w-min-8r bg-main\"\n >\n Save\n </Button>\n </Block>\n\n <!-- Tab Navigation -->\n <Tab\n v-model:selected=\"activeTab\"\n v-if=\"route.params.product\"\n :tabs=\"[\n { label: 'Details', value: 'details' },\n { label: 'Variants', value: 'variants' },\n { label: 'Discounts', value: 'discounts' },\n { label: 'Recommended', value: 'recommended' },\n { label: 'Localization', value: 'localization' }\n ]\"\n class=\"flex-child-default gap-micro scroll-hide bg-light radius-medium h-max pd-thin mn-b-thin o-x-scroll\"\n classTab=\"bg-white\"\n />\n\n <!-- Tab Content -->\n <div v-if=\"activeTab === 'details'\" class=\"cols-1 gap-thin\">\n <!-- Product Images -->\n <Block\n placeholder=\"The product doesn't have any images yet.\"\n class=\"h-min\"\n >\n <EditImages \n :images=\"products.state.current.images\"\n :uploadPath=\"'photos'\" \n @update:images=\"(imagesNew) => { products.state.current.images = imagesNew }\" \n />\n </Block>\n\n <Block title=\"Categories\">\n <BlockMultiselect\n v-model=\"products.state.current.category\"\n placeholder=\"Search categories...\"\n :multiple=\"true\"\n :transform=\"(item) => ({ _id: item._id, name: item.name })\"\n :store=\"{\n read: (options) => categories.actions.read(options),\n state: categories.state\n }\"\n :options=\"{\n rootOnly: false,\n excludeChildren: false,\n limit: 50\n }\"\n :skeleton=\"{\n hide: false,\n horizontal: true,\n class: 'radius-small',\n structure: [{ \n block: 'text', size: 'large'\n }]\n }\"\n :states=\"{\n empty: {\n title: 'No categories found',\n description: 'Try different search terms or create a new category',\n class: 'radius-small'\n }\n }\"\n key=\"_id\"\n :label=\"item => item.name\"\n classSearch=\"bg-white radius-small\"\n classSelected=\"bg-white pd-small radius-small\"\n classDropdown=\"bg-white pd-small radius-medium bs-small\"\n classItem=\"pd-small radius-small hover-bg-light cursor-pointer\"\n classFeed=\"h-max-30r gap-thin flex-column flex o-scroll\"\n >\n <!-- Слот для выбранных категорий -->\n <template #selected=\"{ item, clear }\">\n <div class=\"flex-nowrap flex-v-center flex gap-thin\">\n <span class=\"t-medium\">{{ item?.name || item }}</span>\n <button \n @click.stop=\"clear\"\n class=\"i-small pd-micro bg-red radius-extra flex-center flex aspect-1x1 hover-scale-1\"\n >\n <IconCross class=\"i-micro fill-white\" />\n </button>\n </div>\n </template>\n \n <!-- Слот для элементов в списке -->\n <template #item=\"{ item }\">\n <div class=\"flex-nowrap flex-v-center flex\">\n <img \n v-if=\"item.photo\" \n :src=\"(FILE_SERVER_URL || '') + item.photo\"\n class=\"i-medium radius-small object-fit-cover mn-r-thin\"\n />\n <div class=\"w-100\">\n <p class=\"t-medium\">{{ item.name }}</p>\n <p v-if=\"item.description\" class=\"t-small t-transp\">{{ item.description }}</p>\n </div>\n </div>\n </template>\n </BlockMultiselect>\n </Block>\n\n <!-- Product Profile -->\n <Block title=\"Profile\">\n <div class=\"mn-b-thin flex-nowrap flex gap-thin\">\n <Select \n v-model:select=\"products.state.current.status\"\n label=\"Status\"\n :options=\"[\n 'draft', \n 'published',\n 'featured',\n 'archived',\n 'removed'\n ]\"\n placeholder=\"Display product\"\n class=\"pos-relative w-100 bg-white radius-small pd-medium\"\n />\n <Select \n v-model:select=\"products.state.current.listing\"\n label=\"Type\"\n :options=\"[\n 'sale', \n 'rent',\n ]\"\n placeholder=\"Type of listing\"\n class=\"pos-relative w-100 bg-white radius-small pd-medium\"\n />\n </div>\n\n <Field \n v-model:field=\"products.state.current.name\" \n placeholder=\"Enter product name\"\n class=\"w-100 mn-b-thin bg-white radius-small pd-medium\"\n />\n <Field\n v-model:field=\"products.state.current.description\" \n placeholder=\"Enter product description\" \n class=\"w-100 bg-white radius-small mn-b-thin pd-medium\"\n style=\"resize: vertical\"\n type=\"textarea\"\n />\n <Field\n v-model:field=\"products.state.current.included\" \n placeholder=\"Enter what's inside\" \n class=\"w-100 bg-white radius-small pd-medium\"\n style=\"resize: vertical\"\n type=\"textarea\"\n />\n </Block>\n\n <!-- Price Block (only for new products) -->\n <Block v-if=\"!route.params.product\" title=\"Price\">\n <div class=\"flex gap-thin mn-b-thin\">\n <Field\n v-model:field=\"products.state.current.defaultVariant.price\"\n label=\"Price\"\n type=\"number\"\n placeholder=\"Enter price\"\n class=\"w-100 bg-white radius-small pd-medium\"\n />\n <Field\n v-model:field=\"products.state.current.defaultVariant.quantity\"\n label=\"Quantity\"\n type=\"number\"\n placeholder=\"Enter quantity\"\n class=\"w-100 bg-white radius-small pd-medium\"\n />\n <Select\n v-model:select=\"products.state.current.defaultVariant.unit\"\n label=\"Unit\"\n :options=\"['pcs', 'g', 'kg', 'ml', 'l', 'oz']\"\n placeholder=\"Select unit\"\n class=\"w-100 bg-white radius-small pd-medium\"\n />\n </div>\n </Block>\n\n <!-- Attributes -->\n <EditAttributes \n v-model:attributes=\"products.state.current.attributes\" \n />\n </div>\n\n <!-- Variants Tab -->\n <EditVariants\n\t\t\tv-if=\"activeTab === 'variants'\"\n v-model:variants=\"products.state.current.variants\" \n />\n\n <!-- Discounts Tab -->\n <EditDiscounts\n\t\t\tv-if=\"activeTab === 'discounts'\"\n v-model:discounts=\"products.state.current.discounts\"\n />\n <EditRecommended \n v-if=\"activeTab === 'recommended'\" \n v-model:recommended=\"products.state.current.recommended\"\n class=\"cols-1 gap-thin\"\n />\n\n <!-- Localization Tab -->\n <Block\n\t\t v-if=\"activeTab === 'localization'\"\n title=\"Localization\"\n placeholder=\"No localizations added yet\"\n :actions=\"[{\n label: '+',\n function: () => products.state.current.translations.push({locale: '', name: '', description: ''})\n }]\"\n >\n <div \n class=\"gap-thin mn-b-thin flex-nowrap flex\" \n v-for=\"(item, index) in products.state.current.translations\" \n :key=\"index\"\n > \n <Field\n v-model:field=\"item.locale\"\n placeholder=\"Locale (en, ru, etc.)\"\n class=\"w-30 bg-white radius-small pd-medium\"\n /> \n <Field\n v-model:field=\"item.name\"\n placeholder=\"Product name\"\n class=\"w-100 bg-white radius-small pd-medium\"\n />\n <Field\n v-model:field=\"item.description\"\n placeholder=\"Product description\"\n class=\"w-100 bg-white radius-small pd-medium\"\n />\n <div class=\"radius-small pd-small flex-center flex aspect-1x1 bg-red cursor-pointer hover-scale-1\">\n <IconDelete \n @click=\"() => products.state.current.translations.splice(index, 1)\" \n class=\"i-medium\"\n />\n </div>\n </div>\n </Block>\n\n <!-- Bottom Action Buttons -->\n <div class=\"flex-nowrap flex gap-thin\">\n <Button \n v-if=\"route.params.product\"\n :submit=\"onDelete\" \n class=\"bg-red t-white w-100\"\n >\n Delete \n </Button>\n\n <Button \n :submit=\"onSubmit\" \n class=\"w-100 bg-main\"\n >\n Save\n </Button>\n </div>\n </div>\n</template>\n\n<script setup>\n// Import libs\nimport { reactive, computed, onMounted, ref } from 'vue'\nimport { useRoute, useRouter } from 'vue-router'\n\n// Import components\nimport Block from '@martyrs/src/components/Block/Block.vue';\nimport Tab from \"@martyrs/src/components/Tab/Tab.vue\";\nimport Field from \"@martyrs/src/components/Field/Field.vue\";\nimport Select from '@martyrs/src/components/Select/Select.vue';\nimport Checkbox from \"@martyrs/src/components/Checkbox/Checkbox.vue\";\nimport Button from \"@martyrs/src/components/Button/Button.vue\";\nimport Tree from \"@martyrs/src/components/Tree/Tree.vue\";\nimport EditImages from '@martyrs/src/components/EditImages/EditImages.vue';\n\nimport BlockMultiselect from '@martyrs/src/modules/globals/views/components/blocks/BlockMultiselect.vue';\nimport IconCross from '@martyrs/src/modules/icons/navigation/IconCross.vue';\nimport IconDelete from '@martyrs/src/modules/icons/navigation/IconDelete.vue';\n\nimport EditVariants from '@martyrs/src/modules/products/components/sections/EditVariants.vue';\nimport EditAttributes from '@martyrs/src/modules/products/components/sections/EditAttributes.vue';\nimport EditDiscounts from '@martyrs/src/modules/products/components/sections/EditDiscounts.vue';\nimport EditCategories from '@martyrs/src/modules/products/components/sections/EditCategories.vue';\nimport EditRecommended from '@martyrs/src/modules/products/components/sections/EditRecommended.vue';\n\n// Accessing router and store\nimport * as globals from '@martyrs/src/modules/globals/views/store/globals.js';\nimport * as auth from '@martyrs/src/modules/auth/views/store/auth.js';\nimport * as products from '@martyrs/src/modules/products/store/products.js';\nimport * as categories from '@martyrs/src/modules/products/store/categories.js';\n\nimport { setError } from '@martyrs/src/modules/globals/views/store/globals.js'\n\nconst route = useRoute()\nconst router = useRouter()\nconst emits = defineEmits(['page-loading', 'page-loaded']);\n\nlet isPageLoaded = ref(false)\nlet activeTab = ref('details')\n\nonMounted(async() => { \n emits('page-loading');\n\n products.mutations.resetProduct();\n\n if (route.params.product) {\n await products.actions.read({ _id: route.params.product, lookup: ['variants','categories','recommended'] });\n } else {\n // Убедимся, что массивы инициализированы\n if (!products.state.current.translations) {\n products.state.current.translations = []\n }\n // Убедимся, что массивы инициализированы\n if (!products.state.current.recommended) {\n products.state.current.recommended = []\n }\n if (!products.state.current.discounts) {\n products.state.current.discounts = []\n }\n // Инициализируем defaultVariant для нового продукта\n if (!products.state.current.defaultVariant) {\n products.state.current.defaultVariant = {\n price: null,\n quantity: 1,\n unit: 'pcs'\n }\n }\n\n try {\n // Data prefetching\n categories.state.all = await categories.actions.read({\n user: auth.state.user._id,\n rootOnly: true,\n excludeChildren: false,\n limit: 100\n })\n } catch (error) {\n console.error('error loading categories:', error);\n }\n\n }\n\n emits('page-loaded');\n isPageLoaded.value = true\n})\n\nasync function onSubmit() {\n try {\n if (route.params.product) {\n await products.actions.update(route.params.product, products.state.current)\n } else {\n products.state.current.owner = {\n target: route.params._id || auth.state.user._id,\n type: route.params._id ? 'organization' : 'user'\n }\n products.state.current.creator = {\n target: auth.state.user._id,\n type: 'user',\n hidden: false\n }\n \n // Передаем defaultVariant на бекенд при создании\n const productData = {\n ...products.state.current,\n defaultVariant: products.state.current.defaultVariant\n }\n \n await products.actions.create(productData)\n }\n \n redirectTo()\n } catch (error) {\n setError({ response: { data: { errorCode: \"PRODUCT_NOT_CREATED\" }} })\n console.error('Product creation error:', error)\n }\n}\n\nfunction onDelete() {\n products.actions.deleteProduct(products.state.current._id)\n}\n\nfunction redirectTo() {\n router.push({\n name: route.params._id ? 'Organization' : 'Products', \n params: route.params._id ? { _id: route.params._id } : {}\n })\n}\n</script>"],"names":["useRoute","useRouter","ref","onMounted","products.mutations","products.actions","products.state","categories.state","categories.actions","auth.state","setError"],"mappings":"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"}
|
|
@@ -39,8 +39,9 @@ const _hoisted_11 = {
|
|
|
39
39
|
class: "t-small t-transp"
|
|
40
40
|
};
|
|
41
41
|
const _hoisted_12 = { class: "mn-b-thin flex-nowrap flex gap-thin" };
|
|
42
|
-
const _hoisted_13 = { class: "
|
|
43
|
-
const _hoisted_14 = { class: "flex-
|
|
42
|
+
const _hoisted_13 = { class: "flex gap-thin mn-b-thin" };
|
|
43
|
+
const _hoisted_14 = { class: "radius-small pd-small flex-center flex aspect-1x1 bg-red cursor-pointer hover-scale-1" };
|
|
44
|
+
const _hoisted_15 = { class: "flex-nowrap flex gap-thin" };
|
|
44
45
|
const _sfc_main = {
|
|
45
46
|
__name: "ProductEdit",
|
|
46
47
|
emits: ["page-loading", "page-loaded"],
|
|
@@ -56,39 +57,32 @@ const _sfc_main = {
|
|
|
56
57
|
if (route.params.product) {
|
|
57
58
|
await actions.read({ _id: route.params.product, lookup: ["variants", "categories", "recommended"] });
|
|
58
59
|
} else {
|
|
59
|
-
if (!state.current.
|
|
60
|
-
state.current.
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
60
|
+
if (!state.current.translations) {
|
|
61
|
+
state.current.translations = [];
|
|
62
|
+
}
|
|
63
|
+
if (!state.current.recommended) {
|
|
64
|
+
state.current.recommended = [];
|
|
65
|
+
}
|
|
66
|
+
if (!state.current.discounts) {
|
|
67
|
+
state.current.discounts = [];
|
|
68
|
+
}
|
|
69
|
+
if (!state.current.defaultVariant) {
|
|
70
|
+
state.current.defaultVariant = {
|
|
71
|
+
price: null,
|
|
66
72
|
quantity: 1,
|
|
67
|
-
unit: "pcs"
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
73
|
+
unit: "pcs"
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
try {
|
|
77
|
+
state$1.all = await actions$1.read({
|
|
78
|
+
user: state$2.user._id,
|
|
79
|
+
rootOnly: true,
|
|
80
|
+
excludeChildren: false,
|
|
81
|
+
limit: 100
|
|
82
|
+
});
|
|
83
|
+
} catch (error) {
|
|
84
|
+
console.error("error loading categories:", error);
|
|
72
85
|
}
|
|
73
|
-
}
|
|
74
|
-
if (!state.current.translations) {
|
|
75
|
-
state.current.translations = [];
|
|
76
|
-
}
|
|
77
|
-
if (!state.current.recommended) {
|
|
78
|
-
state.current.recommended = [];
|
|
79
|
-
}
|
|
80
|
-
if (!state.current.discounts) {
|
|
81
|
-
state.current.discounts = [];
|
|
82
|
-
}
|
|
83
|
-
try {
|
|
84
|
-
state$1.all = await actions$1.read({
|
|
85
|
-
user: state$2.user._id,
|
|
86
|
-
rootOnly: true,
|
|
87
|
-
excludeChildren: false,
|
|
88
|
-
limit: 100
|
|
89
|
-
});
|
|
90
|
-
} catch (error) {
|
|
91
|
-
console.error("error loading categories:", error);
|
|
92
86
|
}
|
|
93
87
|
emits("page-loaded");
|
|
94
88
|
isPageLoaded.value = true;
|
|
@@ -107,7 +101,11 @@ const _sfc_main = {
|
|
|
107
101
|
type: "user",
|
|
108
102
|
hidden: false
|
|
109
103
|
};
|
|
110
|
-
|
|
104
|
+
const productData = {
|
|
105
|
+
...state.current,
|
|
106
|
+
defaultVariant: state.current.defaultVariant
|
|
107
|
+
};
|
|
108
|
+
await actions.create(productData);
|
|
111
109
|
}
|
|
112
110
|
redirectTo();
|
|
113
111
|
} catch (error) {
|
|
@@ -138,7 +136,7 @@ const _sfc_main = {
|
|
|
138
136
|
callback: redirectTo,
|
|
139
137
|
class: "w-10 w-max-20r w-min-8r bg-red"
|
|
140
138
|
}, {
|
|
141
|
-
default: withCtx(() => _cache[
|
|
139
|
+
default: withCtx(() => _cache[15] || (_cache[15] = [
|
|
142
140
|
createTextVNode(" Delete ")
|
|
143
141
|
])),
|
|
144
142
|
_: 1
|
|
@@ -148,7 +146,7 @@ const _sfc_main = {
|
|
|
148
146
|
callback: redirectTo,
|
|
149
147
|
class: "w-10 w-max-20r w-min-8r bg-main"
|
|
150
148
|
}, {
|
|
151
|
-
default: withCtx(() => _cache[
|
|
149
|
+
default: withCtx(() => _cache[16] || (_cache[16] = [
|
|
152
150
|
createTextVNode(" Save ")
|
|
153
151
|
])),
|
|
154
152
|
_: 1
|
|
@@ -310,25 +308,59 @@ const _sfc_main = {
|
|
|
310
308
|
]),
|
|
311
309
|
_: 1
|
|
312
310
|
}),
|
|
311
|
+
!unref(route).params.product ? (openBlock(), createBlock(_sfc_main$1, {
|
|
312
|
+
key: 0,
|
|
313
|
+
title: "Price"
|
|
314
|
+
}, {
|
|
315
|
+
default: withCtx(() => [
|
|
316
|
+
createElementVNode("div", _hoisted_13, [
|
|
317
|
+
createVNode(Field, {
|
|
318
|
+
field: state.current.defaultVariant.price,
|
|
319
|
+
"onUpdate:field": _cache[8] || (_cache[8] = ($event) => state.current.defaultVariant.price = $event),
|
|
320
|
+
label: "Price",
|
|
321
|
+
type: "number",
|
|
322
|
+
placeholder: "Enter price",
|
|
323
|
+
class: "w-100 bg-white radius-small pd-medium"
|
|
324
|
+
}, null, 8, ["field"]),
|
|
325
|
+
createVNode(Field, {
|
|
326
|
+
field: state.current.defaultVariant.quantity,
|
|
327
|
+
"onUpdate:field": _cache[9] || (_cache[9] = ($event) => state.current.defaultVariant.quantity = $event),
|
|
328
|
+
label: "Quantity",
|
|
329
|
+
type: "number",
|
|
330
|
+
placeholder: "Enter quantity",
|
|
331
|
+
class: "w-100 bg-white radius-small pd-medium"
|
|
332
|
+
}, null, 8, ["field"]),
|
|
333
|
+
createVNode(Select, {
|
|
334
|
+
select: state.current.defaultVariant.unit,
|
|
335
|
+
"onUpdate:select": _cache[10] || (_cache[10] = ($event) => state.current.defaultVariant.unit = $event),
|
|
336
|
+
label: "Unit",
|
|
337
|
+
options: ["pcs", "g", "kg", "ml", "l", "oz"],
|
|
338
|
+
placeholder: "Select unit",
|
|
339
|
+
class: "w-100 bg-white radius-small pd-medium"
|
|
340
|
+
}, null, 8, ["select"])
|
|
341
|
+
])
|
|
342
|
+
]),
|
|
343
|
+
_: 1
|
|
344
|
+
})) : createCommentVNode("", true),
|
|
313
345
|
createVNode(_sfc_main$6, {
|
|
314
346
|
attributes: state.current.attributes,
|
|
315
|
-
"onUpdate:attributes": _cache[
|
|
347
|
+
"onUpdate:attributes": _cache[11] || (_cache[11] = ($event) => state.current.attributes = $event)
|
|
316
348
|
}, null, 8, ["attributes"])
|
|
317
349
|
])) : createCommentVNode("", true),
|
|
318
350
|
unref(activeTab) === "variants" ? (openBlock(), createBlock(_sfc_main$7, {
|
|
319
351
|
key: 3,
|
|
320
352
|
variants: state.current.variants,
|
|
321
|
-
"onUpdate:variants": _cache[
|
|
353
|
+
"onUpdate:variants": _cache[12] || (_cache[12] = ($event) => state.current.variants = $event)
|
|
322
354
|
}, null, 8, ["variants"])) : createCommentVNode("", true),
|
|
323
355
|
unref(activeTab) === "discounts" ? (openBlock(), createBlock(_sfc_main$8, {
|
|
324
356
|
key: 4,
|
|
325
357
|
discounts: state.current.discounts,
|
|
326
|
-
"onUpdate:discounts": _cache[
|
|
358
|
+
"onUpdate:discounts": _cache[13] || (_cache[13] = ($event) => state.current.discounts = $event)
|
|
327
359
|
}, null, 8, ["discounts"])) : createCommentVNode("", true),
|
|
328
360
|
unref(activeTab) === "recommended" ? (openBlock(), createBlock(_sfc_main$9, {
|
|
329
361
|
key: 5,
|
|
330
362
|
recommended: state.current.recommended,
|
|
331
|
-
"onUpdate:recommended": _cache[
|
|
363
|
+
"onUpdate:recommended": _cache[14] || (_cache[14] = ($event) => state.current.recommended = $event),
|
|
332
364
|
class: "cols-1 gap-thin"
|
|
333
365
|
}, null, 8, ["recommended"])) : createCommentVNode("", true),
|
|
334
366
|
unref(activeTab) === "localization" ? (openBlock(), createBlock(_sfc_main$1, {
|
|
@@ -364,7 +396,7 @@ const _sfc_main = {
|
|
|
364
396
|
placeholder: "Product description",
|
|
365
397
|
class: "w-100 bg-white radius-small pd-medium"
|
|
366
398
|
}, null, 8, ["field", "onUpdate:field"]),
|
|
367
|
-
createElementVNode("div",
|
|
399
|
+
createElementVNode("div", _hoisted_14, [
|
|
368
400
|
createVNode(_sfc_main$a, {
|
|
369
401
|
onClick: () => state.current.translations.splice(index, 1),
|
|
370
402
|
class: "i-medium"
|
|
@@ -375,13 +407,13 @@ const _sfc_main = {
|
|
|
375
407
|
]),
|
|
376
408
|
_: 1
|
|
377
409
|
}, 8, ["actions"])) : createCommentVNode("", true),
|
|
378
|
-
createElementVNode("div",
|
|
410
|
+
createElementVNode("div", _hoisted_15, [
|
|
379
411
|
unref(route).params.product ? (openBlock(), createBlock(_sfc_main$2, {
|
|
380
412
|
key: 0,
|
|
381
413
|
submit: onDelete,
|
|
382
414
|
class: "bg-red t-white w-100"
|
|
383
415
|
}, {
|
|
384
|
-
default: withCtx(() => _cache[
|
|
416
|
+
default: withCtx(() => _cache[17] || (_cache[17] = [
|
|
385
417
|
createTextVNode(" Delete ")
|
|
386
418
|
])),
|
|
387
419
|
_: 1
|
|
@@ -390,7 +422,7 @@ const _sfc_main = {
|
|
|
390
422
|
submit: onSubmit,
|
|
391
423
|
class: "w-100 bg-main"
|
|
392
424
|
}, {
|
|
393
|
-
default: withCtx(() => _cache[
|
|
425
|
+
default: withCtx(() => _cache[18] || (_cache[18] = [
|
|
394
426
|
createTextVNode(" Save ")
|
|
395
427
|
])),
|
|
396
428
|
_: 1
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProductEdit.vue.js","sources":["../../../../../../../src/modules/products/components/pages/ProductEdit.vue"],"sourcesContent":["<template>\n <div v-if=\"isPageLoaded\" class=\"w-100 bg-white pd-thin gap-thin\">\n \n <Block v-if=\"!MOBILE_APP\" class=\"flex-nowrap mn-b-thin gap-thin flex-v-center flex\">\n <h2 class=\"t-truncate mn-r-auto\">\n {{ route.params.product ? products.state.current.name : 'Create Product' }}\n </h2>\n\n <Button \n v-if=\"route.params.product\"\n :submit=\"onDelete\" \n :callback=\"redirectTo\"\n class=\"w-10 w-max-20r w-min-8r bg-red\"\n >\n Delete \n </Button>\n\n <Button \n :submit=\"onSubmit\" \n :callback=\"redirectTo\"\n class=\"w-10 w-max-20r w-min-8r bg-main\"\n >\n Save\n </Button>\n </Block>\n\n <!-- Tab Navigation -->\n <Tab\n v-model:selected=\"activeTab\"\n v-if=\"route.params.product\"\n :tabs=\"[\n { label: 'Details', value: 'details' },\n { label: 'Variants', value: 'variants' },\n { label: 'Discounts', value: 'discounts' },\n { label: 'Recommended', value: 'recommended' },\n { label: 'Localization', value: 'localization' }\n ]\"\n class=\"flex-child-default gap-micro scroll-hide bg-light radius-medium h-max pd-thin mn-b-thin o-x-scroll\"\n classTab=\"bg-white\"\n />\n\n <!-- Tab Content -->\n <div v-if=\"activeTab === 'details'\" class=\"cols-1 gap-thin\">\n <!-- Product Images -->\n <Block\n placeholder=\"The product doesn't have any images yet.\"\n class=\"h-min\"\n >\n <EditImages \n :images=\"products.state.current.images\"\n :uploadPath=\"'photos'\" \n @update:images=\"(imagesNew) => { products.state.current.images = imagesNew }\" \n />\n </Block>\n\n <Block title=\"Categories\">\n <BlockMultiselect\n v-model=\"products.state.current.category\"\n placeholder=\"Search categories...\"\n :multiple=\"true\"\n :transform=\"(item) => ({ _id: item._id, name: item.name })\"\n :store=\"{\n read: (options) => categories.actions.read(options),\n state: categories.state\n }\"\n :options=\"{\n rootOnly: false,\n excludeChildren: false,\n limit: 50\n }\"\n :skeleton=\"{\n hide: false,\n horizontal: true,\n class: 'radius-small',\n structure: [{ \n block: 'text', size: 'large'\n }]\n }\"\n :states=\"{\n empty: {\n title: 'No categories found',\n description: 'Try different search terms or create a new category',\n class: 'radius-small'\n }\n }\"\n key=\"_id\"\n :label=\"item => item.name\"\n classSearch=\"bg-white radius-small\"\n classSelected=\"bg-white pd-small radius-small\"\n classDropdown=\"bg-white pd-small radius-medium bs-small\"\n classItem=\"pd-small radius-small hover-bg-light cursor-pointer\"\n classFeed=\"h-max-30r gap-thin flex-column flex o-scroll\"\n >\n <!-- Слот для выбранных категорий -->\n <template #selected=\"{ item, clear }\">\n <div class=\"flex-nowrap flex-v-center flex gap-thin\">\n <span class=\"t-medium\">{{ item?.name || item }}</span>\n <button \n @click.stop=\"clear\"\n class=\"i-small pd-micro bg-red radius-extra flex-center flex aspect-1x1 hover-scale-1\"\n >\n <IconCross class=\"i-micro fill-white\" />\n </button>\n </div>\n </template>\n \n <!-- Слот для элементов в списке -->\n <template #item=\"{ item }\">\n <div class=\"flex-nowrap flex-v-center flex\">\n <img \n v-if=\"item.photo\" \n :src=\"(FILE_SERVER_URL || '') + item.photo\"\n class=\"i-medium radius-small object-fit-cover mn-r-thin\"\n />\n <div class=\"w-100\">\n <p class=\"t-medium\">{{ item.name }}</p>\n <p v-if=\"item.description\" class=\"t-small t-transp\">{{ item.description }}</p>\n </div>\n </div>\n </template>\n </BlockMultiselect>\n </Block>\n\n <!-- Product Profile -->\n <Block title=\"Profile\">\n <div class=\"mn-b-thin flex-nowrap flex gap-thin\">\n <Select \n v-model:select=\"products.state.current.status\"\n label=\"Status\"\n :options=\"[\n 'draft', \n 'published',\n 'featured',\n 'archived',\n 'removed'\n ]\"\n placeholder=\"Display product\"\n class=\"pos-relative w-100 bg-white radius-small pd-medium\"\n />\n <Select \n v-model:select=\"products.state.current.listing\"\n label=\"Type\"\n :options=\"[\n 'sale', \n 'rent',\n ]\"\n placeholder=\"Type of listing\"\n class=\"pos-relative w-100 bg-white radius-small pd-medium\"\n />\n </div>\n\n <Field \n v-model:field=\"products.state.current.name\" \n placeholder=\"Enter product name\"\n class=\"w-100 mn-b-thin bg-white radius-small pd-medium\"\n />\n <Field\n v-model:field=\"products.state.current.description\" \n placeholder=\"Enter product description\" \n class=\"w-100 bg-white radius-small mn-b-thin pd-medium\"\n style=\"resize: vertical\"\n type=\"textarea\"\n />\n <Field\n v-model:field=\"products.state.current.included\" \n placeholder=\"Enter what's inside\" \n class=\"w-100 bg-white radius-small pd-medium\"\n style=\"resize: vertical\"\n type=\"textarea\"\n />\n </Block>\n <!-- Categories -->\n \n\n\n <!-- Attributes -->\n <EditAttributes \n v-model:attributes=\"products.state.current.attributes\" \n />\n </div>\n\n <!-- Variants Tab -->\n <EditVariants\n\t\t\tv-if=\"activeTab === 'variants'\"\n v-model:variants=\"products.state.current.variants\" \n />\n\n <!-- Discounts Tab -->\n <EditDiscounts\n\t\t\tv-if=\"activeTab === 'discounts'\"\n v-model:discounts=\"products.state.current.discounts\"\n />\n <EditRecommended \n v-if=\"activeTab === 'recommended'\" \n v-model:recommended=\"products.state.current.recommended\"\n class=\"cols-1 gap-thin\"\n />\n\n <!-- Localization Tab -->\n <Block\n\t\t v-if=\"activeTab === 'localization'\"\n title=\"Localization\"\n placeholder=\"No localizations added yet\"\n :actions=\"[{\n label: '+',\n function: () => products.state.current.translations.push({locale: '', name: '', description: ''})\n }]\"\n >\n <div \n class=\"gap-thin mn-b-thin flex-nowrap flex\" \n v-for=\"(item, index) in products.state.current.translations\" \n :key=\"index\"\n > \n <Field\n v-model:field=\"item.locale\"\n placeholder=\"Locale (en, ru, etc.)\"\n class=\"w-30 bg-white radius-small pd-medium\"\n /> \n <Field\n v-model:field=\"item.name\"\n placeholder=\"Product name\"\n class=\"w-100 bg-white radius-small pd-medium\"\n />\n <Field\n v-model:field=\"item.description\"\n placeholder=\"Product description\"\n class=\"w-100 bg-white radius-small pd-medium\"\n />\n <div class=\"radius-small pd-small flex-center flex aspect-1x1 bg-red cursor-pointer hover-scale-1\">\n <IconDelete \n @click=\"() => products.state.current.translations.splice(index, 1)\" \n class=\"i-medium\"\n />\n </div>\n </div>\n </Block>\n\n <!-- Bottom Action Buttons -->\n <div class=\"flex-nowrap flex gap-thin\">\n <Button \n v-if=\"route.params.product\"\n :submit=\"onDelete\" \n class=\"bg-red t-white w-100\"\n >\n Delete \n </Button>\n\n <Button \n :submit=\"onSubmit\" \n class=\"w-100 bg-main\"\n >\n Save\n </Button>\n </div>\n </div>\n</template>\n\n<script setup>\n// Import libs\nimport { reactive, computed, onMounted, ref } from 'vue'\nimport { useRoute, useRouter } from 'vue-router'\n\n// Import components\nimport Block from '@martyrs/src/components/Block/Block.vue';\nimport Tab from \"@martyrs/src/components/Tab/Tab.vue\";\nimport Field from \"@martyrs/src/components/Field/Field.vue\";\nimport Select from '@martyrs/src/components/Select/Select.vue';\nimport Checkbox from \"@martyrs/src/components/Checkbox/Checkbox.vue\";\nimport Button from \"@martyrs/src/components/Button/Button.vue\";\nimport Tree from \"@martyrs/src/components/Tree/Tree.vue\";\nimport EditImages from '@martyrs/src/components/EditImages/EditImages.vue';\n\nimport BlockMultiselect from '@martyrs/src/modules/globals/views/components/blocks/BlockMultiselect.vue';\nimport IconCross from '@martyrs/src/modules/icons/navigation/IconCross.vue';\nimport IconDelete from '@martyrs/src/modules/icons/navigation/IconDelete.vue';\n\nimport EditVariants from '@martyrs/src/modules/products/components/sections/EditVariants.vue';\nimport EditAttributes from '@martyrs/src/modules/products/components/sections/EditAttributes.vue';\nimport EditDiscounts from '@martyrs/src/modules/products/components/sections/EditDiscounts.vue';\nimport EditCategories from '@martyrs/src/modules/products/components/sections/EditCategories.vue';\nimport EditRecommended from '@martyrs/src/modules/products/components/sections/EditRecommended.vue';\n\n// Accessing router and store\nimport * as globals from '@martyrs/src/modules/globals/views/store/globals.js';\nimport * as auth from '@martyrs/src/modules/auth/views/store/auth.js';\nimport * as products from '@martyrs/src/modules/products/store/products.js';\nimport * as categories from '@martyrs/src/modules/products/store/categories.js';\n\nimport { setError } from '@martyrs/src/modules/globals/views/store/globals.js'\n\nconst route = useRoute()\nconst router = useRouter()\nconst emits = defineEmits(['page-loading', 'page-loaded']);\n\nlet isPageLoaded = ref(false)\nlet activeTab = ref('details')\n\nonMounted(async() => { \n emits('page-loading');\n\n products.mutations.resetProduct();\n\n if (route.params.product) {\n await products.actions.read({ _id: route.params.product, lookup: ['variants','categories','recommended'] });\n } else {\n // Создаем дефолтный вариант для нового товара\n if (!products.state.current.variants || products.state.current.variants.length === 0) {\n products.state.current.variants = [{\n name: 'Default',\n sku: '',\n images: [],\n price: 0,\n cost: 0,\n quantity: 1,\n unit: 'pcs',\n available: 0,\n ingredients: [],\n attributes: []\n }];\n }\n }\n\n // Убедимся, что массивы инициализированы\n if (!products.state.current.translations) {\n products.state.current.translations = []\n }\n // Убедимся, что массивы инициализированы\n if (!products.state.current.recommended) {\n products.state.current.recommended = []\n }\n if (!products.state.current.discounts) {\n products.state.current.discounts = []\n }\n\n try {\n // Data prefetching\n categories.state.all = await categories.actions.read({\n user: auth.state.user._id,\n rootOnly: true,\n excludeChildren: false,\n limit: 100\n })\n } catch (error) {\n console.error('error loading categories:', error);\n }\n\n emits('page-loaded');\n isPageLoaded.value = true\n})\n\nasync function onSubmit() {\n try {\n if (route.params.product) {\n await products.actions.update(route.params.product, products.state.current)\n } else {\n products.state.current.owner = {\n target: route.params._id || auth.state.user._id,\n type: route.params._id ? 'organization' : 'user'\n }\n products.state.current.creator = {\n target: auth.state.user._id,\n type: 'user',\n hidden: false\n }\n await products.actions.create(products.state.current)\n }\n \n redirectTo()\n } catch (error) {\n setError({ response: { data: { errorCode: \"PRODUCT_NOT_CREATED\" }} })\n console.error('Product creation error:', error)\n }\n}\n\nfunction onDelete() {\n products.actions.deleteProduct(products.state.current._id)\n}\n\nfunction redirectTo() {\n router.push({\n name: route.params._id ? 'Organization' : 'Products', \n params: route.params._id ? { _id: route.params._id } : {}\n })\n}\n</script>"],"names":["products.mutations","products.actions","products.state","categories.state","categories.actions","auth.state"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ProductEdit.vue.js","sources":["../../../../../../../src/modules/products/components/pages/ProductEdit.vue"],"sourcesContent":["<template>\n <div v-if=\"isPageLoaded\" class=\"w-100 bg-white pd-thin gap-thin\">\n \n <Block v-if=\"!MOBILE_APP\" class=\"flex-nowrap mn-b-thin gap-thin flex-v-center flex\">\n <h2 class=\"t-truncate mn-r-auto\">\n {{ route.params.product ? products.state.current.name : 'Create Product' }}\n </h2>\n\n <Button \n v-if=\"route.params.product\"\n :submit=\"onDelete\" \n :callback=\"redirectTo\"\n class=\"w-10 w-max-20r w-min-8r bg-red\"\n >\n Delete \n </Button>\n\n <Button \n :submit=\"onSubmit\" \n :callback=\"redirectTo\"\n class=\"w-10 w-max-20r w-min-8r bg-main\"\n >\n Save\n </Button>\n </Block>\n\n <!-- Tab Navigation -->\n <Tab\n v-model:selected=\"activeTab\"\n v-if=\"route.params.product\"\n :tabs=\"[\n { label: 'Details', value: 'details' },\n { label: 'Variants', value: 'variants' },\n { label: 'Discounts', value: 'discounts' },\n { label: 'Recommended', value: 'recommended' },\n { label: 'Localization', value: 'localization' }\n ]\"\n class=\"flex-child-default gap-micro scroll-hide bg-light radius-medium h-max pd-thin mn-b-thin o-x-scroll\"\n classTab=\"bg-white\"\n />\n\n <!-- Tab Content -->\n <div v-if=\"activeTab === 'details'\" class=\"cols-1 gap-thin\">\n <!-- Product Images -->\n <Block\n placeholder=\"The product doesn't have any images yet.\"\n class=\"h-min\"\n >\n <EditImages \n :images=\"products.state.current.images\"\n :uploadPath=\"'photos'\" \n @update:images=\"(imagesNew) => { products.state.current.images = imagesNew }\" \n />\n </Block>\n\n <Block title=\"Categories\">\n <BlockMultiselect\n v-model=\"products.state.current.category\"\n placeholder=\"Search categories...\"\n :multiple=\"true\"\n :transform=\"(item) => ({ _id: item._id, name: item.name })\"\n :store=\"{\n read: (options) => categories.actions.read(options),\n state: categories.state\n }\"\n :options=\"{\n rootOnly: false,\n excludeChildren: false,\n limit: 50\n }\"\n :skeleton=\"{\n hide: false,\n horizontal: true,\n class: 'radius-small',\n structure: [{ \n block: 'text', size: 'large'\n }]\n }\"\n :states=\"{\n empty: {\n title: 'No categories found',\n description: 'Try different search terms or create a new category',\n class: 'radius-small'\n }\n }\"\n key=\"_id\"\n :label=\"item => item.name\"\n classSearch=\"bg-white radius-small\"\n classSelected=\"bg-white pd-small radius-small\"\n classDropdown=\"bg-white pd-small radius-medium bs-small\"\n classItem=\"pd-small radius-small hover-bg-light cursor-pointer\"\n classFeed=\"h-max-30r gap-thin flex-column flex o-scroll\"\n >\n <!-- Слот для выбранных категорий -->\n <template #selected=\"{ item, clear }\">\n <div class=\"flex-nowrap flex-v-center flex gap-thin\">\n <span class=\"t-medium\">{{ item?.name || item }}</span>\n <button \n @click.stop=\"clear\"\n class=\"i-small pd-micro bg-red radius-extra flex-center flex aspect-1x1 hover-scale-1\"\n >\n <IconCross class=\"i-micro fill-white\" />\n </button>\n </div>\n </template>\n \n <!-- Слот для элементов в списке -->\n <template #item=\"{ item }\">\n <div class=\"flex-nowrap flex-v-center flex\">\n <img \n v-if=\"item.photo\" \n :src=\"(FILE_SERVER_URL || '') + item.photo\"\n class=\"i-medium radius-small object-fit-cover mn-r-thin\"\n />\n <div class=\"w-100\">\n <p class=\"t-medium\">{{ item.name }}</p>\n <p v-if=\"item.description\" class=\"t-small t-transp\">{{ item.description }}</p>\n </div>\n </div>\n </template>\n </BlockMultiselect>\n </Block>\n\n <!-- Product Profile -->\n <Block title=\"Profile\">\n <div class=\"mn-b-thin flex-nowrap flex gap-thin\">\n <Select \n v-model:select=\"products.state.current.status\"\n label=\"Status\"\n :options=\"[\n 'draft', \n 'published',\n 'featured',\n 'archived',\n 'removed'\n ]\"\n placeholder=\"Display product\"\n class=\"pos-relative w-100 bg-white radius-small pd-medium\"\n />\n <Select \n v-model:select=\"products.state.current.listing\"\n label=\"Type\"\n :options=\"[\n 'sale', \n 'rent',\n ]\"\n placeholder=\"Type of listing\"\n class=\"pos-relative w-100 bg-white radius-small pd-medium\"\n />\n </div>\n\n <Field \n v-model:field=\"products.state.current.name\" \n placeholder=\"Enter product name\"\n class=\"w-100 mn-b-thin bg-white radius-small pd-medium\"\n />\n <Field\n v-model:field=\"products.state.current.description\" \n placeholder=\"Enter product description\" \n class=\"w-100 bg-white radius-small mn-b-thin pd-medium\"\n style=\"resize: vertical\"\n type=\"textarea\"\n />\n <Field\n v-model:field=\"products.state.current.included\" \n placeholder=\"Enter what's inside\" \n class=\"w-100 bg-white radius-small pd-medium\"\n style=\"resize: vertical\"\n type=\"textarea\"\n />\n </Block>\n\n <!-- Price Block (only for new products) -->\n <Block v-if=\"!route.params.product\" title=\"Price\">\n <div class=\"flex gap-thin mn-b-thin\">\n <Field\n v-model:field=\"products.state.current.defaultVariant.price\"\n label=\"Price\"\n type=\"number\"\n placeholder=\"Enter price\"\n class=\"w-100 bg-white radius-small pd-medium\"\n />\n <Field\n v-model:field=\"products.state.current.defaultVariant.quantity\"\n label=\"Quantity\"\n type=\"number\"\n placeholder=\"Enter quantity\"\n class=\"w-100 bg-white radius-small pd-medium\"\n />\n <Select\n v-model:select=\"products.state.current.defaultVariant.unit\"\n label=\"Unit\"\n :options=\"['pcs', 'g', 'kg', 'ml', 'l', 'oz']\"\n placeholder=\"Select unit\"\n class=\"w-100 bg-white radius-small pd-medium\"\n />\n </div>\n </Block>\n\n <!-- Attributes -->\n <EditAttributes \n v-model:attributes=\"products.state.current.attributes\" \n />\n </div>\n\n <!-- Variants Tab -->\n <EditVariants\n\t\t\tv-if=\"activeTab === 'variants'\"\n v-model:variants=\"products.state.current.variants\" \n />\n\n <!-- Discounts Tab -->\n <EditDiscounts\n\t\t\tv-if=\"activeTab === 'discounts'\"\n v-model:discounts=\"products.state.current.discounts\"\n />\n <EditRecommended \n v-if=\"activeTab === 'recommended'\" \n v-model:recommended=\"products.state.current.recommended\"\n class=\"cols-1 gap-thin\"\n />\n\n <!-- Localization Tab -->\n <Block\n\t\t v-if=\"activeTab === 'localization'\"\n title=\"Localization\"\n placeholder=\"No localizations added yet\"\n :actions=\"[{\n label: '+',\n function: () => products.state.current.translations.push({locale: '', name: '', description: ''})\n }]\"\n >\n <div \n class=\"gap-thin mn-b-thin flex-nowrap flex\" \n v-for=\"(item, index) in products.state.current.translations\" \n :key=\"index\"\n > \n <Field\n v-model:field=\"item.locale\"\n placeholder=\"Locale (en, ru, etc.)\"\n class=\"w-30 bg-white radius-small pd-medium\"\n /> \n <Field\n v-model:field=\"item.name\"\n placeholder=\"Product name\"\n class=\"w-100 bg-white radius-small pd-medium\"\n />\n <Field\n v-model:field=\"item.description\"\n placeholder=\"Product description\"\n class=\"w-100 bg-white radius-small pd-medium\"\n />\n <div class=\"radius-small pd-small flex-center flex aspect-1x1 bg-red cursor-pointer hover-scale-1\">\n <IconDelete \n @click=\"() => products.state.current.translations.splice(index, 1)\" \n class=\"i-medium\"\n />\n </div>\n </div>\n </Block>\n\n <!-- Bottom Action Buttons -->\n <div class=\"flex-nowrap flex gap-thin\">\n <Button \n v-if=\"route.params.product\"\n :submit=\"onDelete\" \n class=\"bg-red t-white w-100\"\n >\n Delete \n </Button>\n\n <Button \n :submit=\"onSubmit\" \n class=\"w-100 bg-main\"\n >\n Save\n </Button>\n </div>\n </div>\n</template>\n\n<script setup>\n// Import libs\nimport { reactive, computed, onMounted, ref } from 'vue'\nimport { useRoute, useRouter } from 'vue-router'\n\n// Import components\nimport Block from '@martyrs/src/components/Block/Block.vue';\nimport Tab from \"@martyrs/src/components/Tab/Tab.vue\";\nimport Field from \"@martyrs/src/components/Field/Field.vue\";\nimport Select from '@martyrs/src/components/Select/Select.vue';\nimport Checkbox from \"@martyrs/src/components/Checkbox/Checkbox.vue\";\nimport Button from \"@martyrs/src/components/Button/Button.vue\";\nimport Tree from \"@martyrs/src/components/Tree/Tree.vue\";\nimport EditImages from '@martyrs/src/components/EditImages/EditImages.vue';\n\nimport BlockMultiselect from '@martyrs/src/modules/globals/views/components/blocks/BlockMultiselect.vue';\nimport IconCross from '@martyrs/src/modules/icons/navigation/IconCross.vue';\nimport IconDelete from '@martyrs/src/modules/icons/navigation/IconDelete.vue';\n\nimport EditVariants from '@martyrs/src/modules/products/components/sections/EditVariants.vue';\nimport EditAttributes from '@martyrs/src/modules/products/components/sections/EditAttributes.vue';\nimport EditDiscounts from '@martyrs/src/modules/products/components/sections/EditDiscounts.vue';\nimport EditCategories from '@martyrs/src/modules/products/components/sections/EditCategories.vue';\nimport EditRecommended from '@martyrs/src/modules/products/components/sections/EditRecommended.vue';\n\n// Accessing router and store\nimport * as globals from '@martyrs/src/modules/globals/views/store/globals.js';\nimport * as auth from '@martyrs/src/modules/auth/views/store/auth.js';\nimport * as products from '@martyrs/src/modules/products/store/products.js';\nimport * as categories from '@martyrs/src/modules/products/store/categories.js';\n\nimport { setError } from '@martyrs/src/modules/globals/views/store/globals.js'\n\nconst route = useRoute()\nconst router = useRouter()\nconst emits = defineEmits(['page-loading', 'page-loaded']);\n\nlet isPageLoaded = ref(false)\nlet activeTab = ref('details')\n\nonMounted(async() => { \n emits('page-loading');\n\n products.mutations.resetProduct();\n\n if (route.params.product) {\n await products.actions.read({ _id: route.params.product, lookup: ['variants','categories','recommended'] });\n } else {\n // Убедимся, что массивы инициализированы\n if (!products.state.current.translations) {\n products.state.current.translations = []\n }\n // Убедимся, что массивы инициализированы\n if (!products.state.current.recommended) {\n products.state.current.recommended = []\n }\n if (!products.state.current.discounts) {\n products.state.current.discounts = []\n }\n // Инициализируем defaultVariant для нового продукта\n if (!products.state.current.defaultVariant) {\n products.state.current.defaultVariant = {\n price: null,\n quantity: 1,\n unit: 'pcs'\n }\n }\n\n try {\n // Data prefetching\n categories.state.all = await categories.actions.read({\n user: auth.state.user._id,\n rootOnly: true,\n excludeChildren: false,\n limit: 100\n })\n } catch (error) {\n console.error('error loading categories:', error);\n }\n\n }\n\n emits('page-loaded');\n isPageLoaded.value = true\n})\n\nasync function onSubmit() {\n try {\n if (route.params.product) {\n await products.actions.update(route.params.product, products.state.current)\n } else {\n products.state.current.owner = {\n target: route.params._id || auth.state.user._id,\n type: route.params._id ? 'organization' : 'user'\n }\n products.state.current.creator = {\n target: auth.state.user._id,\n type: 'user',\n hidden: false\n }\n \n // Передаем defaultVariant на бекенд при создании\n const productData = {\n ...products.state.current,\n defaultVariant: products.state.current.defaultVariant\n }\n \n await products.actions.create(productData)\n }\n \n redirectTo()\n } catch (error) {\n setError({ response: { data: { errorCode: \"PRODUCT_NOT_CREATED\" }} })\n console.error('Product creation error:', error)\n }\n}\n\nfunction onDelete() {\n products.actions.deleteProduct(products.state.current._id)\n}\n\nfunction redirectTo() {\n router.push({\n name: route.params._id ? 'Organization' : 'Products', \n params: route.params._id ? { _id: route.params._id } : {}\n })\n}\n</script>"],"names":["products.mutations","products.actions","products.state","categories.state","categories.actions","auth.state"],"mappings":"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"}
|
|
@@ -372,7 +372,6 @@ const _sfc_main = {
|
|
|
372
372
|
options: {
|
|
373
373
|
limit: 16,
|
|
374
374
|
owner: vue.unref(route).name?.includes("Organization") ? vue.unref(route).params._id : null,
|
|
375
|
-
search: vue.unref(route).query.search,
|
|
376
375
|
lookup: ["variants", "rents", "inventory"],
|
|
377
376
|
categories: vue.unref(route).params.categoryPath ? `/${vue.unref(route).params.categoryPath}` : null,
|
|
378
377
|
filters: processedFilters.value,
|