@viur/shop-components 0.0.1-dev.58 → 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 (86) 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 +19 -32
  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 +723 -0
  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/category/CategoryList.vue +83 -0
  22. package/src/components/order/category/CategoryView.vue +143 -0
  23. package/src/components/order/information/adress/ShippingAdress.vue +143 -0
  24. package/src/components/order/item/ItemCard.vue +168 -0
  25. package/src/components/order/item/ItemView.vue +232 -0
  26. package/src/components/order/process/ConfirmView.vue +312 -0
  27. package/src/components/order/process/ExampleUsage.vue +113 -0
  28. package/src/components/order/process/OrderTabHeader.vue +16 -0
  29. package/src/components/order/process/SelectPaymentProvider.vue +62 -0
  30. package/src/components/order/process/Shipping.vue +46 -0
  31. package/src/components/ui/ShopSummary.vue +145 -0
  32. package/src/components/ui/generic/ArticleList.vue +222 -0
  33. package/src/components/ui/generic/ExamplePagination.vue +236 -0
  34. package/src/components/ui/generic/ShopPriceFormatter.vue +41 -0
  35. package/src/components/ui/generic/alerts/ShopAlert.vue +19 -0
  36. package/src/components/ui/generic/makeData.js +39 -0
  37. package/src/components/ui/stepper/StepperItem.vue +39 -0
  38. package/src/components/ui/stepper/StepperTab.vue +133 -0
  39. package/src/components/ui/stepper/StepperTrigger.vue +35 -0
  40. package/src/components/ui/userdata/AddForm.vue +125 -0
  41. package/src/components/ui/userdata/AddressBox.vue +117 -0
  42. package/src/components/ui/userdata/BaseLayout.vue +94 -0
  43. package/src/components/ui/userdata/CustomBooleanBone.vue +58 -0
  44. package/src/components/ui/userdata/CustomSelectBone.vue +91 -0
  45. package/src/components/ui/userdata/CustomStringBone.vue +71 -0
  46. package/src/components/ui/userdata/DefaultLayout.vue +126 -0
  47. package/src/components/ui/userdata/SelectAddress.vue +21 -0
  48. package/src/components/ui/userdata/multi/ActionBar.vue +38 -0
  49. package/src/components/ui/userdata/multi/CartSelection.vue +42 -0
  50. package/src/main.js +50 -0
  51. package/src/router/index.js +103 -0
  52. package/src/stores/cart.js +336 -0
  53. package/src/style/ignite/.editorconfig +20 -0
  54. package/src/style/ignite/.github/workflows/ignite.yml +64 -0
  55. package/src/style/ignite/.github/workflows/node.yml +30 -0
  56. package/src/style/ignite/.postcssrc.cjs +25 -0
  57. package/src/style/ignite/CHANGELOG.md +244 -0
  58. package/src/style/ignite/LICENSE +21 -0
  59. package/src/style/ignite/README.md +92 -0
  60. package/src/style/ignite/dist/ignite.css +2019 -0
  61. package/src/style/ignite/dist/ignite.min.css +4 -0
  62. package/src/style/ignite/foundation/basic.css +371 -0
  63. package/src/style/ignite/foundation/color.css +323 -0
  64. package/src/style/ignite/foundation/config.css +188 -0
  65. package/src/style/ignite/foundation/grid.css +78 -0
  66. package/src/style/ignite/foundation/mediaqueries.css +71 -0
  67. package/src/style/ignite/foundation/reset.css +261 -0
  68. package/src/style/ignite/ignite.css +29 -0
  69. package/src/style/ignite/ignite.css.map +1 -0
  70. package/src/style/ignite/package-lock.json +5530 -0
  71. package/src/style/ignite/package.json +58 -0
  72. package/src/style/ignite/shoelace.css +19 -0
  73. package/src/style/ignite/themes/dark.css +12 -0
  74. package/src/style/ignite/themes/light.css +11 -0
  75. package/src/style/ignite/utilities/shoelace.css +537 -0
  76. package/src/style/ignite/utilities/utilities.css +24 -0
  77. package/src/views/ViewMissing.vue +20 -0
  78. package/vite.config.js +53 -0
  79. package/dist/CategoryView-Z-tCFNv1.mjs +0 -60
  80. package/dist/ItemCard-CVfih_bz.mjs +0 -64
  81. package/dist/ItemView-cjeQBSTR.mjs +0 -1848
  82. package/dist/ItemView.css +0 -1
  83. package/dist/main-CZfMYx-A.mjs +0 -3167
  84. package/dist/main.css +0 -1
  85. package/dist/viur-shop-components.es.js +0 -10
  86. package/dist/viur-shop-components.umd.js +0 -417
@@ -0,0 +1,232 @@
1
+ <template>
2
+ <shop-alert
3
+ v-if="state.alert.show"
4
+ :variant="state.alert.variant"
5
+ :iconName="state.alert.iconName"
6
+ @on-hide="resetAlert()"
7
+ >
8
+ <template #alertMsg> {{ state.alert.msg }} </template>
9
+ </shop-alert>
10
+
11
+ <div class="viur-shop-multi-address-wrap">
12
+ <div class="viur-shop-multi-adress-box" v-for="n in state.amount" :key="n">
13
+ <BaseLayout
14
+ :customer="state.customer"
15
+ :custom-address="!state.customAddress['grp' + n]"
16
+ @edit-billing="state.editBilling = $event"
17
+ @edit-shipping="state.editShipping = $event"
18
+ >
19
+ <template #cart-selection v-if="multiMode">
20
+ <CartSelection
21
+ :carts="reduce(carts, n)"
22
+ @cart-selected="onCartSelect($event, n)"
23
+ >
24
+ </CartSelection>
25
+ </template>
26
+ <template #mode-switch>
27
+ <sl-checkbox
28
+ :checked="true"
29
+ :ref="
30
+ (el) => {
31
+ if (el === null) return;
32
+
33
+ state.customAddress['grp' + n] = el.checked;
34
+ }
35
+ "
36
+ @sl-change="onCustomBillingAddress($event, n)"
37
+ class="viur-shop-form-bill-check"
38
+ v-html="$t('viur.shop.userdata.shipping_to_billaddress')"
39
+ >
40
+ </sl-checkbox>
41
+ </template>
42
+ <template
43
+ #shipping-address
44
+ v-if="
45
+ (state.editShipping && !state.customAddress['grp' + n]) ||
46
+ (!state.hasShippingAddress && !state.customAddress['grp' + n]) ||
47
+ cartStore.state.billingAddressList.length === 1
48
+ "
49
+ >
50
+ <UserDataForm
51
+ :customer="state.customer"
52
+ v-model="cartStore.state.activeShippingAddress"
53
+ @add-success="state.alert = $event"
54
+ :layout="layout"
55
+ >
56
+ </UserDataForm>
57
+ </template>
58
+ <template
59
+ #billing-address
60
+ v-if="
61
+ state.editBilling ||
62
+ !state.hasBillingAddress ||
63
+ cartStore.state.billingAddressList.length === 1
64
+ "
65
+ >
66
+ <UserDataForm
67
+ :customer="state.customer"
68
+ :mode="'billing'"
69
+ v-model="cartStore.state.activeBillingAddress"
70
+ @add-success="state.alert = $event"
71
+ :layout="layout"
72
+ >
73
+ </UserDataForm>
74
+ </template>
75
+ </BaseLayout>
76
+ </div>
77
+
78
+ <ActionBar
79
+ @on-address-add="addAddress"
80
+ @on-address-remove="removeAddress"
81
+ v-if="multiMode"
82
+ >
83
+ </ActionBar>
84
+ </div>
85
+ </template>
86
+
87
+ <script setup>
88
+ import { ref, reactive, computed, onBeforeMount, watch } from "vue";
89
+ import UserDataForm from "./ui/userdata/AddForm.vue";
90
+ import CartSelection from "./ui/userdata/multi/CartSelection.vue";
91
+ import ActionBar from "./ui/userdata/multi/ActionBar.vue";
92
+ import ShopAlert from "./ui/generic/alerts/ShopAlert.vue";
93
+ import { useCartStore } from "../stores/cart";
94
+ import BaseLayout from "./ui/userdata/BaseLayout.vue";
95
+
96
+ const props = defineProps({
97
+ multiMode: {
98
+ type: Boolean,
99
+ default: true,
100
+ },
101
+ layout: {
102
+ default: null,
103
+ },
104
+ });
105
+
106
+ const cartStore = useCartStore();
107
+
108
+ const state = reactive({
109
+ selection: {},
110
+ customer: computed(() => cartStore.state.customer),
111
+ alert: {
112
+ show: false,
113
+ msg: "",
114
+ variant: "",
115
+ iconName: "",
116
+ },
117
+ amount: 1,
118
+ maxAmount: computed(() => {
119
+ return state.remainingCarts.length;
120
+ }),
121
+ remainingCarts: computed(() => {
122
+ const r = carts.value.filter((cart) => {
123
+ return !selection().includes(cart.key);
124
+ });
125
+ return r;
126
+ }),
127
+ customAddress: {},
128
+ hasBillingAddress: computed(() => cartStore.state.billingAddressList.length),
129
+ hasShippingAddress: computed(
130
+ () => cartStore.state.shippingAddressList.length,
131
+ ),
132
+ editBilling: false,
133
+ editShipping: false,
134
+ billingData: {},
135
+ shippingData: {},
136
+ });
137
+
138
+ const carts = ref(
139
+ cartStore.state.childrenByNode?.[cartStore.state.basketRootNode.key]
140
+ ? cartStore.state.childrenByNode?.[
141
+ cartStore.state.basketRootNode.key
142
+ ].filter((cart) => cart.skel_type === "node")
143
+ : [
144
+ { name: "Warenkorb1", key: "213123123123" },
145
+ { name: "Warenkorb2", key: "2131231232131233123" },
146
+ ],
147
+ );
148
+
149
+ function selection() {
150
+ let result = [];
151
+ Object.values(state.selection).forEach((selection) => {
152
+ result.push(...selection);
153
+ });
154
+ return result;
155
+ }
156
+
157
+ function onCartSelect(e, grp) {
158
+ state.selection["grp" + grp] = e;
159
+ }
160
+
161
+ function resetAlert() {
162
+ state.alert.show = false;
163
+ state.alert.msg = "";
164
+ state.alert.variant = "";
165
+ state.alert.iconName = "";
166
+ }
167
+
168
+ function addAddress() {
169
+ if (state.maxAmount > 0) state.amount += 1;
170
+ else {
171
+ state.alert.variant = "danger";
172
+ state.alert.show = true;
173
+ state.alert.iconName = "exclamation-octagon";
174
+ state.alert.msg =
175
+ "Keine weiteren Warenkörbe zum zuweisen von Adressen vorhanden.";
176
+ }
177
+ }
178
+
179
+ function removeAddress() {
180
+ if (state.amount === 1) {
181
+ state.alert.variant = "danger";
182
+ state.alert.show = true;
183
+ state.alert.iconName = "exclamation-octagon";
184
+ state.alert.msg = "Mindestens eine Adresse muss angegeben werden.";
185
+ return;
186
+ }
187
+ if (Object.keys(state.selection).includes("grp" + state.amount)) {
188
+ delete state.selection["grp" + state.amount];
189
+ }
190
+ if (Object.keys(state.customAddress).includes("grp" + state.amount)) {
191
+ delete state.customAddress["grp" + state.amount];
192
+ }
193
+ state.amount -= 1;
194
+ }
195
+
196
+ function reduce(arr, grp) {
197
+ let result = [];
198
+ let temp = [];
199
+
200
+ Object.entries(state.selection).forEach(([key, value]) => {
201
+ if (key === "grp" + grp) return;
202
+ temp.push(...value);
203
+ });
204
+
205
+ result = arr.filter((item) => !temp.includes(item.key));
206
+ return result;
207
+ }
208
+
209
+ function onCustomBillingAddress(e, grp) {
210
+ state.customAddress["grp" + grp] = e.target.checked;
211
+ cartStore.state.cloneBilling = e.target.checked;
212
+ }
213
+
214
+ onBeforeMount(() => {});
215
+ </script>
216
+
217
+ <style scoped>
218
+ .viur-shop-form-bill-check {
219
+ margin: var(--sl-spacing-medium) 0;
220
+ }
221
+
222
+ .viur-shop-custom-billing-address-wrap {
223
+ display: flex;
224
+ flex-direction: row;
225
+ }
226
+ .viur-shop-cart-address-wrap {
227
+ display: grid;
228
+ grid-template-columns: 1fr 1fr;
229
+ gap: var(--sl-spacing-x-large);
230
+ margin-bottom: var(--sl-spacing-x-large);
231
+ }
232
+ </style>
@@ -0,0 +1,277 @@
1
+ <template>
2
+ <!-- Debugging -->
3
+ <!-- <pre>{{ state.leaf.article.dest.key }}</pre>
4
+ <pre>{{ state.leaf.article.dest.article }}</pre> -->
5
+
6
+
7
+ <sl-card horizontal class="viur-shop-cart-leaf">
8
+ <img
9
+ class="viur-shop-cart-leaf-image"
10
+ slot="image"
11
+ :src="
12
+ getImage(
13
+ state.leaf.article.dest.shop_image
14
+ ? state.leaf.article.dest.shop_image
15
+ : undefined,
16
+ )
17
+ "
18
+ />
19
+ <h4
20
+ class="viur-shop-cart-leaf-headline headline"
21
+ v-html="state.leaf.article.dest.shop_name"
22
+ ></h4>
23
+ <h5 class="viur-shop-cart-leaf-artno">
24
+ {{ state.leaf.article.dest.shop_art_no_or_gtin }}
25
+ </h5>
26
+ <div
27
+ class="viur-shop-cart-leaf-description"
28
+ v-html="state.leaf.article.dest.shop_description"
29
+ ></div>
30
+ <div class="viur-shop-cart-leaf-quantity">
31
+ <sl-input
32
+ class="viur-shop-cart-leaf-value viur-shop-cart-leaf-value--quantity"
33
+ type="number"
34
+ label="Anzahl"
35
+ placeholder="Number"
36
+ min="0"
37
+ v-model="state.leaf.quantity"
38
+ @input="
39
+ updateItem(
40
+ state.leaf,
41
+ state.leaf.article.dest.key,
42
+ node,
43
+ state.leaf.quantity,
44
+ )
45
+ "
46
+ >
47
+ </sl-input>
48
+ </div>
49
+ <div class="viur-shop-cart-leaf-unitprice">
50
+ <div class="viur-shop-cart-leaf-label">Stückpreis</div>
51
+ <sl-format-number
52
+ class="viur-shop-cart-leaf-value viur-shop-cart-leaf-value--unitprice"
53
+ lang="de"
54
+ type="currency"
55
+ currency="EUR"
56
+ :value="leaf.shop_price_retail"
57
+ >
58
+ </sl-format-number>
59
+ </div>
60
+
61
+ <div class="viur-shop-cart-leaf-actions">
62
+ <!--<sl-button
63
+ size="small"
64
+ outline
65
+ class="viur-shop-cart-leaf-add-to-favourites-btn"
66
+ variant="primary"
67
+ title="Add to favourites"
68
+ >
69
+ <sl-icon name="heart" slot="prefix"></sl-icon>
70
+ </sl-button>-->
71
+ <sl-button
72
+ size="small"
73
+ outline
74
+ class="viur-shop-cart-leaf-delete-btn"
75
+ variant="default"
76
+ :title="$t('viur.shop.cart_leaf.delete')"
77
+ @click="removeItem(state.leaf, state.leaf.article.dest.key, node)"
78
+ >
79
+ <sl-icon name="trash" slot="prefix"></sl-icon>
80
+ </sl-button>
81
+ </div>
82
+
83
+ <div class="viur-shop-cart-leaf-price">
84
+ <div class="viur-shop-cart-leaf-label">Gesamtpreis</div>
85
+ <sl-format-number
86
+ class="viur-shop-cart-leaf-value viur-shop-cart-leaf-value--price"
87
+ lang="de"
88
+ type="currency"
89
+ currency="EUR"
90
+ :value="leaf.shop_price_retail * leaf.quantity"
91
+ >
92
+ </sl-format-number>
93
+ </div>
94
+ <!-- TODO: Some customer needs an availability indicator ("in stock" etc.) here -->
95
+ </sl-card>
96
+ </template>
97
+
98
+ <script setup>
99
+ import { computed, onBeforeMount, reactive } from "vue";
100
+ import { Request } from "@viur/vue-utils";
101
+ import ShopPriceFormatter from "../ui/generic/ShopPriceFormatter.vue";
102
+
103
+ const props = defineProps({
104
+ leaf: { type: Object, required: true },
105
+ node: { type: Object, required: true },
106
+ placeholder: { type: String, required: true },
107
+ });
108
+
109
+ const emit = defineEmits(["updateItem", "removeItem"]);
110
+
111
+ const state = reactive({
112
+ leaf: {},
113
+ });
114
+
115
+ function getImage(image) {
116
+ if (image !== undefined) return Request.downloadUrlFor(image);
117
+
118
+ return props.placeholder;
119
+ }
120
+
121
+ function updateItem(item, articleKey, node, quantity) {
122
+ emit("updateItem", {
123
+ item: item,
124
+ articleKey: articleKey,
125
+ node: node,
126
+ quantity: quantity,
127
+ });
128
+ }
129
+
130
+ function removeItem(item, articleKey, node) {
131
+ emit("removeItem", { item: item, articleKey: articleKey, node: node });
132
+ }
133
+
134
+ onBeforeMount(() => {
135
+ state.leaf = props.leaf;
136
+ });
137
+ </script>
138
+
139
+ <style scoped>
140
+ @layer foundation.shop {
141
+ .viur-shop-cart-leaf {
142
+ --shop-leaf-label-color: var(--ignt-color-primary);
143
+ --shop-leaf-label-font-weight: 600;
144
+ --shop-leaf-label-font-size: 1em;
145
+ --shop-leaf-price-font-size: 1em;
146
+ --shop-leaf-headline-font-size: 1.3em;
147
+
148
+ margin-bottom: var(--ignt-spacing-x-large);
149
+
150
+ &::part(base) {
151
+ display: flex;
152
+ position: relative;
153
+ }
154
+
155
+ &::part(header) {
156
+ border-bottom: none;
157
+ padding-top: 0;
158
+ padding-right: 0;
159
+ }
160
+
161
+ &::part(image) {
162
+ aspect-ratio: 1;
163
+ }
164
+
165
+ &::part(body) {
166
+ display: grid;
167
+ grid-template-columns: repeat(5, minmax(0, 1fr));
168
+ gap: var(--sl-spacing-medium);
169
+ padding: var(--sl-spacing-large);
170
+ height: 100%;
171
+ }
172
+
173
+ &::part(group) {
174
+ padding: 0;
175
+ }
176
+
177
+ @media (max-width: 600px) {
178
+ &::part(body) {
179
+ grid-template-columns: repeat(2, minmax(0, 1fr));
180
+ gap: var(--sl-spacing-medium);
181
+ padding: var(--sl-spacing-large);
182
+ height: 100%;
183
+ }
184
+
185
+ &::part(image) {
186
+ border-radius: var(--border-radius);
187
+ align-self: baseline;
188
+ }
189
+ }
190
+ }
191
+
192
+ .viur-shop-cart-leaf-image {
193
+ aspect-ratio: 1;
194
+ }
195
+
196
+ .viur-shop-cart-leaf-headline {
197
+ grid-column: 1 / span 4;
198
+ order: -2;
199
+ margin: 0;
200
+ font-size: var(--shop-leaf-headline-font-size);
201
+
202
+ @media (max-width: 600px) {
203
+ grid-column: 1 / span 2;
204
+ }
205
+ }
206
+
207
+ .viur-shop-cart-leaf-artno {
208
+ grid-column: 1 / span 5;
209
+ margin: 0;
210
+
211
+ @media (max-width: 600px) {
212
+ grid-column: 1 / span 2;
213
+ }
214
+ }
215
+
216
+ .viur-shop-cart-leaf-actions {
217
+ display: flex;
218
+ justify-content: start;
219
+ gap: var(--sl-spacing-x-small);
220
+
221
+ @media (min-width: 600px) {
222
+ grid-column: 5 / span 1;
223
+ order: -1;
224
+ justify-content: end;
225
+ align-items: end;
226
+ }
227
+ }
228
+
229
+ .viur-shop-cart-leaf-description {
230
+ grid-column: 1 / span 5;
231
+ margin-bottom: var(--ignt-spacing-small);
232
+ display: -webkit-box;
233
+ -webkit-line-clamp: 3;
234
+ -webkit-box-orient: vertical;
235
+ overflow: hidden;
236
+
237
+ &:deep(*) {
238
+ margin: 0;
239
+ }
240
+
241
+ @media (max-width: 600px) {
242
+ grid-column: span 2;
243
+ }
244
+
245
+ @media (max-width: 500px) {
246
+ display: none;
247
+ }
248
+ }
249
+
250
+ .viur-shop-cart-leaf-price {
251
+ align-self: flex-end;
252
+ text-align: right;
253
+ font-size: var(--shop-leaf-price-font-size);
254
+ }
255
+
256
+ .viur-shop-cart-leaf-quantity {
257
+ align-self: flex-end;
258
+ }
259
+
260
+ .viur-shop-cart-leaf-unitprice {
261
+ align-self: flex-end;
262
+
263
+ @media (max-width: 600px) {
264
+ text-align: right;
265
+ }
266
+ }
267
+
268
+ .viur-shop-cart-leaf-label,
269
+ .viur-shop-cart-leaf-value--quantity::part(form-control-label) {
270
+ color: var(--shop-leaf-label-color);
271
+ font-weight: var(--shop-leaf-label-font-weight);
272
+ font-size: var(--shop-leaf-label-font-size);
273
+ margin-bottom: var(--ignt-spacing-x-small);
274
+ }
275
+ }
276
+
277
+ </style>