@tower_74/cms-plugin-commerce 0.2.4 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tower_74/cms-plugin-commerce",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Front-end of the Base CMS commerce plugin (ADR-0026): storefront, cart, checkout + product/order admin pages. Ships source; exports a CmsPlugin.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "proprietary",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { Button, Input, Select } from '@tower_74/cms-ui';
|
|
2
|
+
import { Button, Input, MediaPicker, type MediaItem, type MediaSelection, Select } from '@tower_74/cms-ui';
|
|
3
3
|
|
|
4
4
|
interface Option {
|
|
5
5
|
name: string;
|
|
@@ -10,17 +10,19 @@ interface Variant {
|
|
|
10
10
|
price: string;
|
|
11
11
|
stock: number | string;
|
|
12
12
|
options: Record<string, string>;
|
|
13
|
+
image_media_id?: number | null;
|
|
14
|
+
image?: MediaSelection | null;
|
|
13
15
|
}
|
|
14
16
|
|
|
15
|
-
const props = defineProps<{ modelValue: Variant[]; options: Option[]; currencySymbol: string }>();
|
|
16
|
-
const emit = defineEmits<{ 'update:modelValue': [value: Variant[]] }>();
|
|
17
|
+
const props = defineProps<{ modelValue: Variant[]; options: Option[]; currencySymbol: string; mediaItems: MediaItem[] }>();
|
|
18
|
+
const emit = defineEmits<{ 'update:modelValue': [value: Variant[]]; upload: [file: File] }>();
|
|
17
19
|
|
|
18
20
|
const commit = (variants: Variant[]) => emit('update:modelValue', variants);
|
|
19
21
|
|
|
20
22
|
const add = () => {
|
|
21
23
|
const options: Record<string, string> = {};
|
|
22
24
|
props.options.forEach((o) => (options[o.name] = o.values[0] ?? ''));
|
|
23
|
-
commit([...props.modelValue, { sku: '', price: '', stock: 0, options }]);
|
|
25
|
+
commit([...props.modelValue, { sku: '', price: '', stock: 0, options, image_media_id: null, image: null }]);
|
|
24
26
|
};
|
|
25
27
|
const remove = (i: number) => {
|
|
26
28
|
const variants = [...props.modelValue];
|
|
@@ -37,6 +39,12 @@ const setOption = (i: number, name: string, value: string) => {
|
|
|
37
39
|
variants[i] = { ...variants[i], options: { ...variants[i].options, [name]: value } };
|
|
38
40
|
commit(variants);
|
|
39
41
|
};
|
|
42
|
+
const setImage = (i: number, value: MediaSelection | MediaSelection[] | null) => {
|
|
43
|
+
const selection = (value as MediaSelection | null) ?? null;
|
|
44
|
+
const variants = [...props.modelValue];
|
|
45
|
+
variants[i] = { ...variants[i], image: selection, image_media_id: selection?.id ?? null };
|
|
46
|
+
commit(variants);
|
|
47
|
+
};
|
|
40
48
|
const optionsFor = (option: Option) => option.values.map((v) => ({ label: v, value: v }));
|
|
41
49
|
</script>
|
|
42
50
|
|
|
@@ -63,6 +71,16 @@ const optionsFor = (option: Option) => option.values.map((v) => ({ label: v, val
|
|
|
63
71
|
<label class="mb-1 block text-xs font-medium text-muted">Stock</label>
|
|
64
72
|
<Input :model-value="String(variant.stock)" type="number" @update:model-value="setField(i, 'stock', $event)" />
|
|
65
73
|
</div>
|
|
74
|
+
<div class="w-40">
|
|
75
|
+
<label class="mb-1 block text-xs font-medium text-muted">Image</label>
|
|
76
|
+
<MediaPicker
|
|
77
|
+
:model-value="variant.image ?? null"
|
|
78
|
+
:items="mediaItems"
|
|
79
|
+
@update:model-value="setImage(i, $event)"
|
|
80
|
+
@upload="emit('upload', $event)"
|
|
81
|
+
/>
|
|
82
|
+
<p class="mt-1 text-xs text-muted">Falls back to the product image.</p>
|
|
83
|
+
</div>
|
|
66
84
|
<Button type="button" variant="danger" size="sm" @click="remove(i)">✕</Button>
|
|
67
85
|
</div>
|
|
68
86
|
|
|
@@ -17,6 +17,8 @@ interface Variant {
|
|
|
17
17
|
price: string;
|
|
18
18
|
stock: number | string;
|
|
19
19
|
options: Record<string, string>;
|
|
20
|
+
image_media_id?: number | null;
|
|
21
|
+
image?: MediaSelection | null;
|
|
20
22
|
}
|
|
21
23
|
interface Block {
|
|
22
24
|
type: string;
|
|
@@ -148,7 +150,7 @@ const submit = () => {
|
|
|
148
150
|
<div class="mt-8">
|
|
149
151
|
<h3 class="mb-3 text-base font-semibold">Variants</h3>
|
|
150
152
|
<p v-if="form.errors.variants" class="mb-2 text-sm text-danger">{{ form.errors.variants }}</p>
|
|
151
|
-
<VariantsEditor v-model="variantsModel" :options="form.options" :currency-symbol="currencySymbol" />
|
|
153
|
+
<VariantsEditor v-model="variantsModel" :options="form.options" :currency-symbol="currencySymbol" :media-items="mediaItems" @upload="onUpload" />
|
|
152
154
|
</div>
|
|
153
155
|
|
|
154
156
|
<div class="mt-8">
|
|
@@ -11,7 +11,7 @@ interface ProductData {
|
|
|
11
11
|
image: { src: string; alt?: string } | null;
|
|
12
12
|
blocks: Block[];
|
|
13
13
|
options: Array<{ name: string; values: string[] }>;
|
|
14
|
-
variants: Array<{ id: number; options: Record<string, string>; price: string; available: boolean }>;
|
|
14
|
+
variants: Array<{ id: number; options: Record<string, string>; price: string; available: boolean; image: { src: string; alt?: string } | null }>;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
defineProps<{
|