@viur/shop-components 0.0.1-dev.6 → 0.0.1-dev.60

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.
Files changed (77) hide show
  1. package/.editorconfig +16 -0
  2. package/.github/workflows/npm-publish.yml +42 -0
  3. package/.gitmodules +3 -0
  4. package/LICENSE +21 -0
  5. package/README.md +13 -2
  6. package/package.json +25 -23
  7. package/src/components/ShopCart.vue +512 -0
  8. package/src/components/ShopOrderComplete.vue +73 -0
  9. package/src/components/ShopOrderConfirm.vue +291 -0
  10. package/src/components/ShopOrderStepper.vue +264 -0
  11. package/src/components/ShopUserData.vue +232 -0
  12. package/src/components/cart/CartLeaf.vue +277 -0
  13. package/src/components/cart/CartLeafModel.vue +304 -0
  14. package/src/components/cart/CartNode.vue +25 -0
  15. package/src/components/cart/CartTree.vue +54 -0
  16. package/src/components/cart/CartTreeWrapper.vue +73 -0
  17. package/src/components/cart/CartView.vue +205 -174
  18. package/src/components/cart/Discount.vue +91 -0
  19. package/src/components/lib/utils.js +0 -0
  20. package/src/components/order/OrderSidebar.vue +102 -0
  21. package/src/components/order/item/ItemView.vue +0 -1
  22. package/src/components/{cart → order/process}/ConfirmView.vue +94 -96
  23. package/src/components/order/process/ExampleUsage.vue +79 -66
  24. package/src/components/order/process/OrderTabHeader.vue +10 -1
  25. package/src/components/order/process/SelectPaymentProvider.vue +62 -0
  26. package/src/components/order/process/Shipping.vue +46 -0
  27. package/src/components/ui/ShopSummary.vue +145 -0
  28. package/src/components/ui/generic/ArticleList.vue +222 -0
  29. package/src/components/ui/generic/ExamplePagination.vue +236 -0
  30. package/src/components/ui/generic/ShopPriceFormatter.vue +41 -0
  31. package/src/components/ui/generic/alerts/ShopAlert.vue +19 -0
  32. package/src/components/ui/generic/makeData.js +39 -0
  33. package/src/components/ui/stepper/StepperItem.vue +39 -0
  34. package/src/components/ui/stepper/StepperTab.vue +133 -0
  35. package/src/components/ui/stepper/StepperTrigger.vue +35 -0
  36. package/src/components/ui/userdata/AddForm.vue +125 -0
  37. package/src/components/ui/userdata/AddressBox.vue +117 -0
  38. package/src/components/ui/userdata/BaseLayout.vue +94 -0
  39. package/src/components/ui/userdata/CustomBooleanBone.vue +58 -0
  40. package/src/components/ui/userdata/CustomSelectBone.vue +91 -0
  41. package/src/components/ui/userdata/CustomStringBone.vue +71 -0
  42. package/src/components/ui/userdata/DefaultLayout.vue +126 -0
  43. package/src/components/ui/userdata/SelectAddress.vue +21 -0
  44. package/src/components/ui/userdata/multi/ActionBar.vue +38 -0
  45. package/src/components/ui/userdata/multi/CartSelection.vue +42 -0
  46. package/src/main.js +50 -0
  47. package/src/router/index.js +1 -1
  48. package/src/stores/cart.js +267 -42
  49. package/src/style/ignite/.editorconfig +20 -0
  50. package/src/style/ignite/.github/workflows/ignite.yml +64 -0
  51. package/src/style/ignite/.github/workflows/node.yml +30 -0
  52. package/src/style/ignite/.postcssrc.cjs +25 -0
  53. package/src/style/ignite/CHANGELOG.md +244 -0
  54. package/src/style/ignite/LICENSE +21 -0
  55. package/src/style/ignite/README.md +92 -0
  56. package/src/style/ignite/dist/ignite.css +2019 -0
  57. package/src/style/ignite/dist/ignite.min.css +4 -0
  58. package/src/style/ignite/foundation/basic.css +371 -0
  59. package/src/style/ignite/foundation/color.css +323 -0
  60. package/src/style/ignite/foundation/config.css +188 -0
  61. package/src/style/ignite/foundation/grid.css +78 -0
  62. package/src/style/ignite/foundation/mediaqueries.css +71 -0
  63. package/src/style/ignite/foundation/reset.css +261 -0
  64. package/src/style/ignite/ignite.css +29 -0
  65. package/src/style/ignite/ignite.css.map +1 -0
  66. package/src/style/ignite/package-lock.json +5530 -0
  67. package/src/style/ignite/package.json +58 -0
  68. package/src/style/ignite/shoelace.css +19 -0
  69. package/src/style/ignite/themes/dark.css +12 -0
  70. package/src/style/ignite/themes/light.css +11 -0
  71. package/src/style/ignite/utilities/shoelace.css +537 -0
  72. package/src/style/ignite/utilities/utilities.css +24 -0
  73. package/vite.config.js +53 -0
  74. package/src/components/order/information/UserInfoMulti.vue +0 -427
  75. package/src/components/order/information/UserInformation.vue +0 -332
  76. package/src/components/order/process/OrderComplete.vue +0 -41
  77. package/src/components/order/process/OrderView.vue +0 -210
@@ -0,0 +1,304 @@
1
+ <template>
2
+ <!-- Debugging -->
3
+ <!-- <pre>{{ modelValue.leaf.article.dest.key }}</pre>
4
+
5
+ <pre>{{ modelValue }}</pre> -->
6
+
7
+ <sl-dialog no-header ref="confirm" @sl-hide="resetItem">
8
+ <p>Möchten Sie den Artikel wirklich aus dem Warenkorb entfernen?</p>
9
+ <sl-bar>
10
+ <sl-button
11
+ slot="left"
12
+ variant="danger"
13
+ @click="confirm.hide()"
14
+ size="medium"
15
+ >
16
+ Abbrechen
17
+ </sl-button>
18
+ <sl-button
19
+ slot="right"
20
+ variant="success"
21
+ @click="onConfirm"
22
+ size="medium"
23
+ >
24
+ Aus Warenkorb entfernen
25
+ </sl-button>
26
+ </sl-bar>
27
+ </sl-dialog>
28
+
29
+ <div v-if="!modelValue"></div>
30
+ <sl-card horizontal class="viur-shop-cart-leaf" v-else>
31
+ <img
32
+ class="viur-shop-cart-leaf-image"
33
+ slot="image"
34
+ :src="
35
+ getImage(
36
+ modelValue.article.dest.shop_image
37
+ ? modelValue.article.dest.shop_image
38
+ : undefined,
39
+ )
40
+ "
41
+ />
42
+ <h4
43
+ class="viur-shop-cart-leaf-headline headline"
44
+ v-html="modelValue.article.dest.shop_name"
45
+ ></h4>
46
+ <h5 class="viur-shop-cart-leaf-artno">
47
+ {{ modelValue.article.dest.shop_art_no_or_gtin }}
48
+ </h5>
49
+ <div
50
+ class="viur-shop-cart-leaf-description"
51
+ v-html="modelValue.article.dest.shop_description"
52
+ ></div>
53
+ <div class="viur-shop-cart-leaf-quantity">
54
+ <sl-input
55
+ class="viur-shop-cart-leaf-value viur-shop-cart-leaf-value--quantity"
56
+ type="number"
57
+ label="Anzahl"
58
+ placeholder="Number"
59
+ min="0"
60
+ :value="modelValue.quantity"
61
+ @sl-change="updateItem"
62
+ >
63
+ </sl-input>
64
+ </div>
65
+ <div class="viur-shop-cart-leaf-unitprice">
66
+ <div class="viur-shop-cart-leaf-label">Stückpreis</div>
67
+ <sl-format-number
68
+ class="viur-shop-cart-leaf-value viur-shop-cart-leaf-value--unitprice"
69
+ lang="de"
70
+ type="currency"
71
+ currency="EUR"
72
+ :value="modelValue.shop_price_retail"
73
+ >
74
+ </sl-format-number>
75
+ </div>
76
+
77
+ <div class="viur-shop-cart-leaf-actions">
78
+ <!-- <sl-button
79
+ size="small"
80
+ outline
81
+ class="viur-shop-cart-leaf-add-to-favourites-btn"
82
+ variant="primary"
83
+ title="Add to favourites"
84
+ >
85
+ <sl-icon name="heart" slot="prefix"></sl-icon>
86
+ </sl-button> -->
87
+ <sl-button
88
+ size="small"
89
+ outline
90
+ class="viur-shop-cart-leaf-delete-btn"
91
+ variant="primary"
92
+ title="Remove from cart"
93
+ @click="confirm.show()"
94
+ >
95
+ <sl-icon name="trash" slot="prefix"></sl-icon>
96
+ </sl-button>
97
+ </div>
98
+
99
+ <div class="viur-shop-cart-leaf-price">
100
+ <div class="viur-shop-cart-leaf-label">Gesamtpreis</div>
101
+ <sl-format-number
102
+ class="viur-shop-cart-leaf-value viur-shop-cart-leaf-value--price"
103
+ lang="de"
104
+ type="currency"
105
+ currency="EUR"
106
+ :value="modelValue.shop_price_retail * modelValue.quantity"
107
+ >
108
+ </sl-format-number>
109
+ </div>
110
+ <!-- TODO: Some customer needs an availability indicator ("in stock" etc.) here -->
111
+ </sl-card>
112
+ </template>
113
+
114
+ <script setup>
115
+ import { computed, onBeforeMount, reactive, ref } from "vue";
116
+ import { Request } from "@viur/vue-utils";
117
+ import { useCartStore } from "../../stores/cart";
118
+ // import ShopPriceFormatter from "../ui/generic/ShopPriceFormatter.vue";
119
+
120
+ const props = defineProps(["modelValue"]);
121
+ const emit = defineEmits(["update:modelValue"]);
122
+
123
+ const cartStore = useCartStore();
124
+ const confirm = ref(null);
125
+ const isConfirmed = ref(false);
126
+
127
+ function getImage(image) {
128
+ if (image !== undefined) return Request.downloadUrlFor(image);
129
+
130
+ return cartStore.state.placeholder;
131
+ }
132
+
133
+ function updateItem(ev) {
134
+ let newEvent = { ...props.modelValue };
135
+
136
+ newEvent.quantity = ev.target.value;
137
+
138
+ console.log("update", newEvent.quantity);
139
+ if (newEvent.quantity < 1) {
140
+ confirm.value.show();
141
+ } else {
142
+ emit("update:modelValue", newEvent);
143
+ }
144
+ }
145
+
146
+ function removeItem() {
147
+ let newEvent = { ...props.modelValue };
148
+ newEvent.quantity = 0;
149
+ emit("update:modelValue", newEvent);
150
+ }
151
+
152
+ function resetItem() {
153
+ if (!isConfirmed.value) {
154
+ let newEvent = { ...props.modelValue };
155
+ newEvent.quantity = 1;
156
+ emit("update:modelValue", newEvent);
157
+ }
158
+ }
159
+
160
+ async function onConfirm() {
161
+ isConfirmed.value = true;
162
+ confirm.value.hide();
163
+ removeItem();
164
+ }
165
+ </script>
166
+
167
+ <style scoped>
168
+ @layer foundation.shop {
169
+ .viur-shop-cart-leaf {
170
+ --shop-leaf-label-color: var(--ignt-color-primary);
171
+ --shop-leaf-label-font-weight: 600;
172
+ --shop-leaf-label-font-size: 1em;
173
+ --shop-leaf-price-font-size: 1em;
174
+ --shop-leaf-headline-font-size: 1.3em;
175
+
176
+ margin-bottom: var(--ignt-spacing-x-large);
177
+
178
+ &::part(base) {
179
+ display: flex;
180
+ position: relative;
181
+ }
182
+
183
+ &::part(header) {
184
+ border-bottom: none;
185
+ padding-top: 0;
186
+ padding-right: 0;
187
+ }
188
+
189
+ &::part(image) {
190
+ aspect-ratio: 1;
191
+ }
192
+
193
+ &::part(body) {
194
+ display: grid;
195
+ grid-template-columns: repeat(5, minmax(0, 1fr));
196
+ gap: var(--sl-spacing-medium);
197
+ padding: var(--sl-spacing-large);
198
+ height: 100%;
199
+ }
200
+
201
+ &::part(group) {
202
+ padding: 0;
203
+ }
204
+
205
+ @media (max-width: 600px) {
206
+ &::part(body) {
207
+ grid-template-columns: repeat(2, minmax(0, 1fr));
208
+ gap: var(--sl-spacing-medium);
209
+ padding: var(--sl-spacing-large);
210
+ height: 100%;
211
+ }
212
+
213
+ &::part(image) {
214
+ border-radius: var(--border-radius);
215
+ align-self: baseline;
216
+ }
217
+ }
218
+ }
219
+
220
+ .viur-shop-cart-leaf-image {
221
+ aspect-ratio: 1;
222
+ }
223
+
224
+ .viur-shop-cart-leaf-headline {
225
+ grid-column: 1 / span 4;
226
+ order: -2;
227
+ margin: 0;
228
+ font-size: var(--shop-leaf-headline-font-size);
229
+
230
+ @media (max-width: 600px) {
231
+ grid-column: 1 / span 2;
232
+ }
233
+ }
234
+
235
+ .viur-shop-cart-leaf-artno {
236
+ grid-column: 1 / span 5;
237
+ margin: 0;
238
+
239
+ @media (max-width: 600px) {
240
+ grid-column: 1 / span 2;
241
+ }
242
+ }
243
+
244
+ .viur-shop-cart-leaf-actions {
245
+ display: flex;
246
+ justify-content: start;
247
+ gap: var(--sl-spacing-x-small);
248
+
249
+ @media (min-width: 600px) {
250
+ grid-column: 5 / span 1;
251
+ order: -1;
252
+ justify-content: end;
253
+ align-items: end;
254
+ }
255
+ }
256
+
257
+ .viur-shop-cart-leaf-description {
258
+ grid-column: 1 / span 5;
259
+ margin-bottom: var(--ignt-spacing-small);
260
+ display: -webkit-box;
261
+ -webkit-line-clamp: 3;
262
+ -webkit-box-orient: vertical;
263
+ overflow: hidden;
264
+
265
+ &:deep(*) {
266
+ margin: 0;
267
+ }
268
+
269
+ @media (max-width: 600px) {
270
+ grid-column: span 2;
271
+ }
272
+
273
+ @media (max-width: 500px) {
274
+ display: none;
275
+ }
276
+ }
277
+
278
+ .viur-shop-cart-leaf-price {
279
+ align-self: flex-end;
280
+ text-align: right;
281
+ font-size: var(--shop-leaf-price-font-size);
282
+ }
283
+
284
+ .viur-shop-cart-leaf-quantity {
285
+ align-self: flex-end;
286
+ }
287
+
288
+ .viur-shop-cart-leaf-unitprice {
289
+ align-self: flex-end;
290
+
291
+ @media (max-width: 600px) {
292
+ text-align: right;
293
+ }
294
+ }
295
+
296
+ .viur-shop-cart-leaf-label,
297
+ .viur-shop-cart-leaf-value--quantity::part(form-control-label) {
298
+ color: var(--shop-leaf-label-color);
299
+ font-weight: var(--shop-leaf-label-font-weight);
300
+ font-size: var(--shop-leaf-label-font-size);
301
+ margin-bottom: var(--ignt-spacing-x-small);
302
+ }
303
+ }
304
+ </style>
@@ -0,0 +1,25 @@
1
+ <template>
2
+ <sl-details v-if="node.children" :summary="node.name">
3
+ <slot></slot>
4
+ </sl-details>
5
+
6
+ <h1 class="viur-shop-cart-headline" v-else>
7
+ {{ node.name }}
8
+ </h1>
9
+ </template>
10
+
11
+ <script setup>
12
+ import { computed, reactive } from "vue";
13
+ import CartLeaf from "./CartLeaf.vue";
14
+ const props = defineProps({
15
+ node: { type: Object, required: true },
16
+ });
17
+
18
+ const state = reactive({});
19
+ </script>
20
+
21
+ <style scoped>
22
+ .viur-shop-cart-headline {
23
+ font-size: 2rem;
24
+ }
25
+ </style>
@@ -0,0 +1,54 @@
1
+ <template>
2
+ <CartTreeWrapper :tree="state.tree" @update:modelValue="handleChange">
3
+ </CartTreeWrapper>
4
+ </template>
5
+ <script setup>
6
+ import { reactive, watch, computed } from "vue";
7
+ import CartTreeWrapper from "./CartTreeWrapper.vue";
8
+
9
+ const props = defineProps({
10
+ modelValue: { type: Array, required: true },
11
+ });
12
+
13
+ const emits = defineEmits(["update:modelValue"]);
14
+
15
+ const arrayToTree = (arr, parent = null) =>
16
+ arr
17
+ .filter((item) => item.parententry === parent)
18
+ .map((child) => ({ ...child, children: arrayToTree(arr, child.key) }));
19
+
20
+ const state = reactive({
21
+ loading: computed(() => {
22
+ return props.modelValue ? false : true;
23
+ }),
24
+ tree: computed(() => {
25
+ // ! NOTE: it is very important to unpack the prop (copy the array) at this point to avoid prop mutation!!!
26
+ let temp = props.modelValue ? arrayToTree([...props.modelValue]) : [""];
27
+
28
+ return temp[0];
29
+ }),
30
+ });
31
+
32
+ function handleChange(e) {
33
+ // ! NOTE: it is very important to unpack the prop (copy the array) at this point to avoid prop mutation!!!
34
+ let temp = [...props.modelValue];
35
+
36
+ temp.forEach((item, index) => {
37
+ if (item.key === e.key) {
38
+ if (e.quantity < 1) {
39
+ temp.splice(index, 1);
40
+ } else {
41
+ temp[index] = e;
42
+ }
43
+ }
44
+ });
45
+
46
+ emits("update:modelValue", temp);
47
+ }
48
+
49
+ // watch(() => props.modelValue,
50
+ // (oldVal, newVal) => {
51
+ // if(oldVal === )
52
+ // }
53
+ // );
54
+ </script>
@@ -0,0 +1,73 @@
1
+ <template>
2
+ <div v-if="state.loading">keine Einträge im Warenkorb</div>
3
+
4
+ <template v-else-if="tree.is_root_node">
5
+ <template v-for="child in tree.children" :key="child.key">
6
+ <CartLeafModel
7
+ :modelValue="child"
8
+ v-if="child.skel_type === 'leaf'"
9
+ @update:modelValue="handleChange"
10
+ />
11
+
12
+ <CartNode
13
+ :node="child"
14
+ v-else-if="child.children.length && child?.skel_type === 'node'"
15
+ >
16
+ <template v-for="item in child.children" :key="item.key">
17
+ <CartLeafModel
18
+ :modelValue="item"
19
+ v-if="item.skel_type === 'leaf'"
20
+ @update:modelValue="handleChange"
21
+ >
22
+ </CartLeafModel>
23
+ <CartTreeWrapper
24
+ :tree="item"
25
+ @update:modelValue="handleChange"
26
+ v-else
27
+ >
28
+ </CartTreeWrapper>
29
+ </template>
30
+ </CartNode>
31
+ </template>
32
+ </template>
33
+
34
+ <CartNode :node="tree" v-else-if="tree.skel_type === 'node'">
35
+ <template v-for="item in tree.children" :key="item.key">
36
+ <CartLeafModel
37
+ :modelValue="item"
38
+ @update:modelValue="handleChange"
39
+ v-if="item.skel_type === 'leaf'"
40
+ >
41
+ </CartLeafModel>
42
+ <CartTreeWrapper :tree="item" @update:modelValue="handleChange" v-else>
43
+ </CartTreeWrapper>
44
+ </template>
45
+ </CartNode>
46
+ </template>
47
+
48
+ <script setup>
49
+ import { reactive, watch, computed } from "vue";
50
+ import CartLeafModel from "./CartLeafModel.vue";
51
+ import CartNode from "./CartNode.vue";
52
+
53
+ const props = defineProps({
54
+ tree: { type: Object },
55
+ });
56
+
57
+ const emits = defineEmits(["update:modelValue"]);
58
+
59
+ const state = reactive({
60
+ loading: computed(() => {
61
+ if (props.tree) {
62
+ return false;
63
+ }
64
+ return true;
65
+ }),
66
+ });
67
+
68
+ function handleChange(e) {
69
+ emits("update:modelValue", e);
70
+ }
71
+
72
+ watch(() => {});
73
+ </script>