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

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 (135) hide show
  1. package/old/client/HttpClient.js +111 -0
  2. package/old/client/ViURShopClient.js +472 -0
  3. package/old/client/index.js +23 -0
  4. package/old/client/types.js +10 -0
  5. package/old/components/ExampleUsage.vue +95 -0
  6. package/old/components/ShopCart.vue +91 -0
  7. package/old/components/ShopOrderConfirm.vue +311 -0
  8. package/{src → old}/components/ShopOrderStepper.vue +111 -23
  9. package/old/components/ShopPaymentProvider.vue +113 -0
  10. package/old/components/ShopShippingMethod.vue +52 -0
  11. package/{src/components/ui → old/components}/ShopSummary.vue +28 -35
  12. package/{src → old}/components/ShopUserData.vue +51 -65
  13. package/{src → old}/components/cart/CartLeafModel.vue +24 -16
  14. package/{src → old}/components/cart/CartNode.vue +1 -0
  15. package/{src → old}/components/cart/CartTree.vue +13 -0
  16. package/old/components/cart/CartView.vue +82 -0
  17. package/{src → old}/components/cart/Discount.vue +8 -8
  18. package/old/components/generic/loadinghandler.vue +76 -0
  19. package/old/components/paymentProvider/prepayment.vue +0 -0
  20. package/old/components/paymentProvider/unzerPayment.vue +140 -0
  21. package/old/components/simple/ShopUserData.vue +161 -0
  22. package/old/components/simple/SimpleDefaultLayout.vue +116 -0
  23. package/old/components/ui/generic/CardSelector.vue +52 -0
  24. package/old/components/ui/generic/CartList.vue +69 -0
  25. package/old/components/ui/generic/ShippingInfo.vue +56 -0
  26. package/old/components/ui/generic/alerts/ShopAlert.vue +30 -0
  27. package/old/components/ui/payment/PaymentOption.vue +79 -0
  28. package/old/components/ui/payment/PaymentSelector.vue +158 -0
  29. package/old/components/ui/stepper/StepperItem.vue +90 -0
  30. package/{src → old}/components/ui/stepper/StepperTab.vue +30 -2
  31. package/old/components/ui/stepper/StepperTrigger.vue +69 -0
  32. package/old/components/ui/userdata/AddForm.vue +160 -0
  33. package/old/components/ui/userdata/AddressBox.vue +137 -0
  34. package/{src → old}/components/ui/userdata/BaseLayout.vue +15 -32
  35. package/old/stores/address.js +122 -0
  36. package/old/stores/cart.js +266 -0
  37. package/old/stores/message.js +21 -0
  38. package/old/stores/order.js +202 -0
  39. package/old/stores/payment.js +79 -0
  40. package/old/stores/shipping.js +78 -0
  41. package/package.json +3 -5
  42. package/src/Shop.vue +212 -0
  43. package/src/ShopOrderStepper.vue +89 -0
  44. package/src/ShopSummary.vue +170 -0
  45. package/src/Steps/ShopCart.vue +60 -0
  46. package/src/Steps/ShopOrderComplete.vue +24 -0
  47. package/src/Steps/ShopOrderConfirm.vue +295 -0
  48. package/src/Steps/ShopPaymentProvider.vue +53 -0
  49. package/src/Steps/ShopShippingMethod.vue +53 -0
  50. package/src/Steps/ShopUserDataGuest.vue +78 -0
  51. package/src/Steps/index.js +15 -0
  52. package/src/components/AddressForm.vue +84 -0
  53. package/src/components/AddressFormLayout.vue +107 -0
  54. package/src/components/CardSelector.vue +68 -0
  55. package/src/components/CartItem.vue +325 -0
  56. package/src/components/CartItemSmall.vue +257 -0
  57. package/src/components/LoadingHandler.vue +76 -0
  58. package/src/components/PaymentOption.vue +78 -0
  59. package/src/components/PaymentProviderUnzer.vue +201 -0
  60. package/src/components/PaymentSelector.vue +55 -0
  61. package/src/components/ShopAlert.vue +30 -0
  62. package/src/components/StepperTab.vue +132 -0
  63. package/src/components/dialogButton.vue +49 -0
  64. package/src/composables/address.js +95 -0
  65. package/src/composables/cart.js +132 -0
  66. package/src/composables/order.js +80 -0
  67. package/src/composables/payment.js +75 -0
  68. package/src/composables/shipping.js +32 -0
  69. package/src/main.js +32 -38
  70. package/src/shop.js +251 -0
  71. package/src/translations/de.js +15 -0
  72. package/src/translations/en.js +5 -0
  73. package/src/utils.js +49 -0
  74. package/vite.config.js +0 -2
  75. package/src/components/ShopCart.vue +0 -512
  76. package/src/components/ShopOrderConfirm.vue +0 -291
  77. package/src/components/cart/CartView.vue +0 -723
  78. package/src/components/order/OrderSidebar.vue +0 -102
  79. package/src/components/order/category/CategoryList.vue +0 -83
  80. package/src/components/order/category/CategoryView.vue +0 -143
  81. package/src/components/order/information/adress/ShippingAdress.vue +0 -143
  82. package/src/components/order/item/ItemCard.vue +0 -168
  83. package/src/components/order/item/ItemView.vue +0 -232
  84. package/src/components/order/process/ConfirmView.vue +0 -312
  85. package/src/components/order/process/ExampleUsage.vue +0 -113
  86. package/src/components/order/process/OrderTabHeader.vue +0 -16
  87. package/src/components/order/process/SelectPaymentProvider.vue +0 -62
  88. package/src/components/order/process/Shipping.vue +0 -46
  89. package/src/components/ui/generic/ArticleList.vue +0 -222
  90. package/src/components/ui/generic/ExamplePagination.vue +0 -236
  91. package/src/components/ui/generic/alerts/ShopAlert.vue +0 -19
  92. package/src/components/ui/generic/makeData.js +0 -39
  93. package/src/components/ui/stepper/StepperItem.vue +0 -39
  94. package/src/components/ui/stepper/StepperTrigger.vue +0 -35
  95. package/src/components/ui/userdata/AddForm.vue +0 -125
  96. package/src/components/ui/userdata/AddressBox.vue +0 -117
  97. package/src/router/index.js +0 -103
  98. package/src/stores/cart.js +0 -336
  99. package/src/views/ViewMissing.vue +0 -20
  100. /package/{src → old}/components/ShopOrderComplete.vue +0 -0
  101. /package/{src → old}/components/cart/CartLeaf.vue +0 -0
  102. /package/{src → old}/components/cart/CartTreeWrapper.vue +0 -0
  103. /package/{src/components/lib/utils.js → old/components/paymentProvider/paypalplus.vue} +0 -0
  104. /package/{src → old}/components/ui/generic/ShopPriceFormatter.vue +0 -0
  105. /package/{src → old}/components/ui/userdata/CustomBooleanBone.vue +0 -0
  106. /package/{src → old}/components/ui/userdata/CustomSelectBone.vue +0 -0
  107. /package/{src → old}/components/ui/userdata/CustomStringBone.vue +0 -0
  108. /package/{src → old}/components/ui/userdata/DefaultLayout.vue +0 -0
  109. /package/{src → old}/components/ui/userdata/SelectAddress.vue +0 -0
  110. /package/{src → old}/components/ui/userdata/multi/ActionBar.vue +0 -0
  111. /package/{src → old}/components/ui/userdata/multi/CartSelection.vue +0 -0
  112. /package/{src/style → old}/ignite/.editorconfig +0 -0
  113. /package/{src/style → old}/ignite/.github/workflows/ignite.yml +0 -0
  114. /package/{src/style → old}/ignite/.github/workflows/node.yml +0 -0
  115. /package/{src/style → old}/ignite/.postcssrc.cjs +0 -0
  116. /package/{src/style → old}/ignite/CHANGELOG.md +0 -0
  117. /package/{src/style → old}/ignite/LICENSE +0 -0
  118. /package/{src/style → old}/ignite/README.md +0 -0
  119. /package/{src/style → old}/ignite/dist/ignite.css +0 -0
  120. /package/{src/style → old}/ignite/dist/ignite.min.css +0 -0
  121. /package/{src/style → old}/ignite/foundation/basic.css +0 -0
  122. /package/{src/style → old}/ignite/foundation/color.css +0 -0
  123. /package/{src/style → old}/ignite/foundation/config.css +0 -0
  124. /package/{src/style → old}/ignite/foundation/grid.css +0 -0
  125. /package/{src/style → old}/ignite/foundation/mediaqueries.css +0 -0
  126. /package/{src/style → old}/ignite/foundation/reset.css +0 -0
  127. /package/{src/style → old}/ignite/ignite.css +0 -0
  128. /package/{src/style → old}/ignite/ignite.css.map +0 -0
  129. /package/{src/style → old}/ignite/package-lock.json +0 -0
  130. /package/{src/style → old}/ignite/package.json +0 -0
  131. /package/{src/style → old}/ignite/shoelace.css +0 -0
  132. /package/{src/style → old}/ignite/themes/dark.css +0 -0
  133. /package/{src/style → old}/ignite/themes/light.css +0 -0
  134. /package/{src/style → old}/ignite/utilities/shoelace.css +0 -0
  135. /package/{src/style → old}/ignite/utilities/utilities.css +0 -0
@@ -0,0 +1,56 @@
1
+ <template>
2
+ <div class="viur-shop-cart-sidebar-shipping">
3
+ <div class="viur-shop-cart-shipping-item">
4
+ <slot name="custom"></slot>
5
+ </div>
6
+ <div class="viur-shop-cart-shipping-item">
7
+ <span>Versandkosten </span>
8
+ <sl-format-number
9
+ type="currency"
10
+ currency="EUR"
11
+ :value="shippingCost"
12
+ lang="de"
13
+ >
14
+ </sl-format-number>
15
+ </div>
16
+ <div class="viur-shop-cart-shipping-item">
17
+ <span>Lieferzeit </span>
18
+ {{ deliveryTime === 1 ? deliveryTime + " Tag" : deliveryTime + " Tage" }}
19
+ </div>
20
+ </div>
21
+ </template>
22
+ <script setup>
23
+ import { useShippingStore } from "../../../stores/shipping";
24
+ import { computed } from "vue";
25
+
26
+ const shippingStore = useShippingStore();
27
+
28
+ const shippingCost = computed(() => {
29
+ return shippingStore.state.selectedShippingMethod?.dest.shipping_cost
30
+ ? shippingStore.state.selectedShippingMethod.dest.shipping_cost
31
+ : 0;
32
+ });
33
+
34
+ const deliveryTime = computed(() => {
35
+ return shippingStore.state.selectedShippingMethod?.dest.delivery_time_max
36
+ ? shippingStore.state.selectedShippingMethod.dest.delivery_time_max
37
+ : 0;
38
+ });
39
+ </script>
40
+
41
+ <style scoped>
42
+ .viur-shop-cart-sidebar-shipping {
43
+ width: 100%;
44
+ display: flex;
45
+ flex-direction: column;
46
+ align-items: center;
47
+ justify-content: flex-start;
48
+ flex-wrap: nowrap;
49
+ margin: var(--sl-spacing-2x-small) 0;
50
+ }
51
+ .viur-shop-cart-shipping-item {
52
+ width: 100%;
53
+ display: flex;
54
+ justify-content: space-between;
55
+ }
56
+ </style>
@@ -0,0 +1,30 @@
1
+ <template>
2
+ <sl-alert :variant="variant" open :closable="closeable" :duration="duration" @sl-hide="onHide">
3
+ <slot name="icon">
4
+ <sl-icon slot="icon" :name="iconName"></sl-icon>
5
+ </slot>
6
+ <slot name="alertMsg">{{ msg }}</slot>
7
+ </sl-alert>
8
+ </template>
9
+
10
+ <script setup>
11
+ const props = defineProps({
12
+ variant: { type: String, default: "primary" },
13
+ iconName: { type: String, default: "info-circle" },
14
+ closeable:{
15
+ type:Boolean,
16
+ default:true
17
+ },
18
+ duration:{
19
+ type: [Number, String],
20
+ default: 3000 // use "Infinity" for fix message
21
+ },
22
+ msg: { type: String, default: "ALERT!" },
23
+ });
24
+
25
+ const emit = defineEmits(["onHide"]);
26
+
27
+ function onHide() {
28
+ emit("onHide");
29
+ }
30
+ </script>
@@ -0,0 +1,79 @@
1
+ <template>
2
+ <sl-details :class="{
3
+ simple:widget==='simple'
4
+ }"
5
+ @sl-show="selection" >
6
+ <div slot="summary" class="payment-selection">
7
+ <div class="start">
8
+ <sl-icon :name="icon"></sl-icon>
9
+ {{ name }}
10
+ </div>
11
+ <sl-radio :value="paymenttype" ></sl-radio>
12
+ </div>
13
+ <slot>
14
+ {{description}}
15
+ </slot>
16
+
17
+ <template v-if="widget==='simple'">
18
+ <div slot="expand-icon" style="width:1em"></div>
19
+ <div slot="collapse-icon" style="width:1em"></div>
20
+ </template>
21
+ </sl-details>
22
+ </template>
23
+
24
+ <script setup>
25
+ const emits = defineEmits(['change'])
26
+ const props = defineProps({
27
+ paymenttype: {
28
+ type: String,
29
+ default: 'prepayment'
30
+ },
31
+ name: {
32
+ type: String,
33
+ default: 'Paymentname'
34
+ },
35
+ icon: {
36
+ type: String,
37
+ default: 'currency-euro'
38
+ },
39
+ description: {
40
+ type: String,
41
+ default: 'Payment description'
42
+ },
43
+ widget:{
44
+ type:String,
45
+ default:'default' //simple
46
+ }
47
+ })
48
+
49
+ function selection(){
50
+ console.log("FFF")
51
+ emits('change',props.paymenttype)
52
+ }
53
+
54
+
55
+
56
+ </script>
57
+
58
+ <style scoped>
59
+ .payment-selection{
60
+ display: flex;
61
+ align-items: center;
62
+ flex-wrap: nowrap;
63
+ flex-direction: row;
64
+ align-content: center;
65
+ justify-content: space-between;
66
+ width: 100%;
67
+
68
+ .start{
69
+ display: flex;
70
+ align-items: center;
71
+ flex-wrap: nowrap;
72
+ gap:10px;
73
+ }
74
+ }
75
+
76
+ .simple::part(content){
77
+ display:none;
78
+ }
79
+ </style>
@@ -0,0 +1,158 @@
1
+ <template>
2
+ <sl-radio-group :value="state.selection">
3
+ <sl-details-group>
4
+
5
+ <payment-option v-for="option in options" :key="option.id"
6
+ :paymenttype="option.paymenttype"
7
+ :name="option.name"
8
+ :icon="option.icon"
9
+ :widget="option.widget"
10
+ :description="option.description"
11
+ @change="optionChanged"
12
+
13
+ >
14
+ <template v-if="option.paymenttype.startsWith('unzer-')">
15
+ <form class="unzerUI form" ref="unzerform">
16
+ <template v-if="option.paymenttype === 'unzer-card'">
17
+ <div class="field">
18
+ <div id="card-element-id-number" class="unzerInput">
19
+ <!-- Card number UI Element is inserted here. -->
20
+ </div>
21
+ </div>
22
+ <div class="two fields">
23
+ <div class="field ten wide">
24
+ <div id="card-element-id-expiry" class="unzerInput">
25
+ <!-- Card expiry date UI Element is inserted here. -->
26
+ </div>
27
+ </div>
28
+ <div class="field six wide">
29
+ <div id="card-element-id-cvc" class="unzerInput">
30
+ <!-- Card CVC UI Element is inserted here. -->
31
+ </div>
32
+ </div>
33
+ </div>
34
+ </template>
35
+
36
+ <template v-else-if="option.paymenttype === 'unzer-paypal'">
37
+ <div id="paypal-element" class="field"></div>
38
+ </template>
39
+
40
+ <template v-else-if="option.paymenttype === 'unzer-ideal'">
41
+ <div id="ideal-element" class="field"></div>
42
+ </template>
43
+ </form>
44
+ </template>
45
+ </payment-option>
46
+
47
+ </sl-details-group>
48
+ </sl-radio-group>
49
+
50
+ </template>
51
+
52
+ <script setup>
53
+ import {usePaymentStore} from "../../../stores/payment"
54
+ import PaymentOption from "./PaymentOption.vue"
55
+ import {computed, reactive, ref} from 'vue'
56
+ import {Request} from "@viur/vue-utils";
57
+
58
+ const paymentStore = usePaymentStore()
59
+
60
+ const unzerform = ref(null)
61
+
62
+ const props = defineProps({
63
+ selection: {
64
+ type: String,
65
+ default: null
66
+ },
67
+ options: {
68
+ type: Array,
69
+ default: () => []
70
+ }
71
+ })
72
+
73
+ const state = reactive({
74
+ unzer: computed(()=>{
75
+ //if (!orderStore.state.checkout) return null
76
+ return new unzer(orderStore.state.checkout.payment.public_key, {locale: 'de-DE'})
77
+ }),
78
+ selection:null,
79
+ hasError:false
80
+ })
81
+
82
+ function initUnzerForm(){
83
+ //Unzer field definition
84
+ if (state.selection === 'unzer-card' && !paymentStore.state.paymentHandler['unzer-card']) {
85
+ const card = state.unzer.Card();
86
+ // Rendering input field card number
87
+ card.create('number', {
88
+ containerId: 'card-element-id-number',
89
+ onlyIframe: false,
90
+ });
91
+ // Rendering input field card expiry
92
+ card.create('expiry', {
93
+ containerId: 'card-element-id-expiry',
94
+ onlyIframe: false,
95
+ });
96
+ // Rendering input field card cvc
97
+ card.create('cvc', {
98
+ containerId: 'card-element-id-cvc',
99
+ onlyIframe: false,
100
+ });
101
+
102
+ paymentStore.state.paymentHandler['unzer-card'] = card
103
+ } else if (state.selection === 'unzer-paypal' && !paymentStore.state.paymentHandler['unzer-paypal']) {
104
+ // Creating a PayPal instance
105
+ const paypal = state.unzer.Paypal()
106
+ // Rendering input field
107
+ //paypal.create('email', {
108
+ // containerId: 'paypal-element',
109
+ //});
110
+ paymentStore.state.paymentHandler['unzer-paypal']= paypal;
111
+ } else if (state.selection === 'unzer-sofort' && !paymentStore.state.paymentHandler['unzer-sofort']) {
112
+ const sofort = state.unzer.Sofort()
113
+ paymentStore.state.paymentHandler['unzer-sofort'] = sofort;
114
+ } else if (state.selection=== 'unzer-ideal' && !paymentStore.state.paymentHandler['unzer-ideal']) {
115
+ const ideal = state.unzer.Ideal()
116
+ ideal.create('ideal', {
117
+ containerId: 'ideal-element',
118
+ });
119
+ paymentStore.state.paymentHandler['unzer-ideal'] = ideal;
120
+ }
121
+ }
122
+
123
+
124
+ function submitFormToUnzer(){
125
+ let paymenttarget = paymentStore.state.paymentSelection[0].split("-")[1]
126
+ //send to unzer
127
+ state.handler.createResource().then((result)=>{
128
+ Request.post(`/${orderStore.state.shopClient.shop_module}/pp_unzer_${paymenttarget}/save_type`, {dataObj:{
129
+ order_key: orderStore.state.currentOrderkey,
130
+ type_id: result.id,
131
+ }}).then(async (resp)=>{
132
+ let data = await resp.json()
133
+ orderStore.state.currentOrder = data
134
+ await orderStore.startCheckout()
135
+ }).catch(error => {
136
+ console.log(error)
137
+ })
138
+ }).catch((error)=> {
139
+ // handle errors
140
+ console.error(error)
141
+ })
142
+ }
143
+
144
+ function optionChanged(type){
145
+ console.log(state)
146
+ console.log(paymentStore)
147
+ console.log(unzerform)
148
+ state.selection=type
149
+ initUnzerForm()
150
+ paymentStore.state.paymentSelection = state.selection
151
+ }
152
+
153
+
154
+ </script>
155
+
156
+ <style scoped>
157
+
158
+ </style>
@@ -0,0 +1,90 @@
1
+ <template>
2
+ <sl-tab-panel class="viur-shop-order-tab-panel" :name="tab">
3
+ <div v-if="!tabs[tab]?.['loaded']"></div>
4
+ <component
5
+ :is="tabs[tab].component"
6
+ v-bind="tabs[tab].props ? tabs[tab].props : ''"
7
+ @valid="emit('valid', $event)"
8
+ v-else
9
+ >
10
+ </component>
11
+ </sl-tab-panel>
12
+ </template>
13
+
14
+ <script setup>
15
+ import {watch, onBeforeMount} from 'vue'
16
+
17
+ const props = defineProps({
18
+ tab: {
19
+ type: String,
20
+ required: true,
21
+ },
22
+ tabs: {
23
+ type: Object,
24
+ required: true,
25
+ },
26
+ currentTab: {
27
+ type: String,
28
+ required: true,
29
+ },
30
+ });
31
+
32
+ const emit = defineEmits(["goToStart", "editAddress", 'valid']);
33
+
34
+ function goToStart() {
35
+ emit("goToStart");
36
+ }
37
+
38
+ function goToUserData(e) {
39
+ emit("editAddress", e);
40
+ }
41
+
42
+ watch(()=>props.currentTab === props.tab, (newVal,oldVal)=>{
43
+ if (newVal){
44
+ props.tabs[props.tab]['loaded'] = true
45
+ }
46
+ })
47
+
48
+ onBeforeMount(()=>{
49
+ if (props.currentTab === props.tab){
50
+ props.tabs[props.tab]['loaded'] = true
51
+ }
52
+ })
53
+
54
+ </script>
55
+
56
+ <style scoped>
57
+ .viur-shop-order-tab-panel {
58
+ }
59
+
60
+ .skeleton-overview header {
61
+ display: flex;
62
+ align-items: center;
63
+ margin-bottom: 1rem;
64
+ }
65
+
66
+ .skeleton-overview header sl-skeleton:last-child {
67
+ flex: 0 0 auto;
68
+ width: 30%;
69
+ }
70
+
71
+ .skeleton-overview sl-skeleton {
72
+ margin-bottom: 1rem;
73
+ }
74
+
75
+ .skeleton-overview sl-skeleton:nth-child(1) {
76
+ float: left;
77
+ width: 3rem;
78
+ height: 3rem;
79
+ margin-right: 1rem;
80
+ vertical-align: middle;
81
+ }
82
+
83
+ .skeleton-overview sl-skeleton:nth-child(3) {
84
+ width: 95%;
85
+ }
86
+
87
+ .skeleton-overview sl-skeleton:nth-child(4) {
88
+ width: 80%;
89
+ }
90
+ </style>
@@ -3,7 +3,7 @@
3
3
  class="viur-shop-order-tab"
4
4
  slot="nav"
5
5
  :panel="tab"
6
- :disabled="tabs[tab].disabled"
6
+ :disabled="false"
7
7
  >
8
8
  <div class="viur-shop-order-step">
9
9
  <sl-icon
@@ -32,6 +32,8 @@
32
32
  </template>
33
33
 
34
34
  <script setup>
35
+ import { watch, onBeforeMount, inject } from "vue";
36
+
35
37
  const props = defineProps({
36
38
  tab: {
37
39
  type: String,
@@ -49,7 +51,33 @@ const props = defineProps({
49
51
  type: Object,
50
52
  required: true,
51
53
  },
54
+ currentTab: {
55
+ type: String,
56
+ required: true,
57
+ },
58
+ disabled: {
59
+ type: Boolean,
60
+ default: true,
61
+ },
52
62
  });
63
+
64
+ const stepperState = inject("stepperState");
65
+
66
+ // watch(()=>props.tabs[props.tab]['valid'],(newVal, oldVal)=>{
67
+ // let nextTab = stepperState.tabNames?.[props.tabIdx+1]
68
+ // if (!nextTab) return
69
+
70
+ // props.tabs[nextTab]['disabled'] = false //enable nextTab
71
+ // })
72
+
73
+ // onBeforeMount(()=>{
74
+ // props.tabs[props.tab]['disabled'] = true //default all tabs disabled
75
+
76
+ // if (props.currentTab === props.tab){
77
+ // props.tabs[props.tab]['disabled'] = false //activate the first one
78
+ // }
79
+
80
+ // })
53
81
  </script>
54
82
 
55
83
  <style scoped>
@@ -114,7 +142,7 @@ const props = defineProps({
114
142
  }
115
143
 
116
144
  .viur-shop-order-status-text {
117
- font-size: 0.8em;
145
+ font-size: 1em;
118
146
  color: inherit;
119
147
  text-align: center;
120
148
  white-space: initial;
@@ -0,0 +1,69 @@
1
+ <template>
2
+ <sl-button
3
+ type="submit"
4
+ v-show="index !== 0 && state.showPrev"
5
+ @click="prevTab()"
6
+ >
7
+ Zurück
8
+ <!-- TODO: $t(i18n referenz) -->
9
+ </sl-button>
10
+
11
+ <sl-button
12
+ type="submit"
13
+ variant="primary"
14
+ @click="nextTab()"
15
+ v-show="state.showNext"
16
+ :disabled="!tabs[tab].valid"
17
+ >
18
+ Weiter
19
+ <!-- TODO: $t(i18n referenz) -->
20
+ </sl-button>
21
+ </template>
22
+
23
+ <script setup>
24
+ import { computed, reactive } from "vue";
25
+
26
+ const props = defineProps({
27
+ index: {
28
+ type: Number,
29
+ required: true,
30
+ },
31
+ tab: {
32
+ type: String,
33
+ required: true,
34
+ },
35
+ tabs: {
36
+ type: Object,
37
+ required: true,
38
+ },
39
+ });
40
+ const state = reactive({
41
+ showPrev: computed(() => {
42
+ if (props.tabs[props.tab]["showPrev"] !== undefined) {
43
+ return !!props.tabs[props.tab]["showPrev"];
44
+ }
45
+ return true;
46
+ }),
47
+ showNext: computed(() => {
48
+ if (props.tabs[props.tab]["showNext"] !== undefined) {
49
+ return !!props.tabs[props.tab]["showNext"];
50
+ }
51
+ return true;
52
+ }),
53
+ });
54
+ const emit = defineEmits({ prevTab: null, nextTab: null });
55
+
56
+ function prevTab() {
57
+ emit("prevTab");
58
+ }
59
+
60
+ function nextTab() {
61
+ emit("nextTab");
62
+ }
63
+ </script>
64
+
65
+ <style scoped>
66
+ .sticky {
67
+ position: sticky;
68
+ }
69
+ </style>
@@ -0,0 +1,160 @@
1
+ <template>
2
+ <sl-spinner v-if="state.isLoading"></sl-spinner>
3
+ <ViForm
4
+ ref="addForm"
5
+ :module="`${cartStore.state.shopModuleName}/address`"
6
+ action="add"
7
+ :useCategories="false"
8
+ :layout="layout ? layout : DefaultLayout"
9
+ :values="modelValue"
10
+ :skel="
11
+ type === 'billing'
12
+ ? addressStore.state.active.billing
13
+ : addressStore.state.active.shipping
14
+ "
15
+ @change="updateValues"
16
+ >
17
+ </ViForm>
18
+
19
+ <!-- BUTTON NUR PLATZHALTER FÜR TESTS -->
20
+ <sl-bar>
21
+ <div slot="left">
22
+ <sl-button
23
+ variant="success"
24
+ @click.stop.prevent="sendForm"
25
+ :loading="state.isSending"
26
+ >
27
+ <sl-icon name="floppy2" slot="prefix"></sl-icon>
28
+ {{
29
+ $t("actions.add").charAt(0).toUpperCase() + $t("actions.add").slice(1)
30
+ }}
31
+ </sl-button>
32
+ </div>
33
+ </sl-bar>
34
+ </template>
35
+
36
+ <script setup>
37
+ import { reactive, ref, computed, onMounted } from "vue";
38
+ import ViForm from "@viur/vue-utils/forms/ViForm.vue";
39
+ import DefaultLayout from "./DefaultLayout.vue";
40
+ import { useCartStore } from "../../../stores/cart";
41
+ import { useAddressStore } from "../../../stores/address";
42
+ import { useOrderStore } from "../../../main";
43
+
44
+ const props = defineProps({
45
+ layout: { required: false },
46
+ customer: { type: Object, required: true },
47
+ type: { type: String, default: "billing" },
48
+ modelValue: { type: Object },
49
+ });
50
+
51
+ const emit = defineEmits(["update:modelValue", "addSuccess", "valid"]);
52
+
53
+ const cartStore = useCartStore();
54
+ const addressStore = useAddressStore();
55
+ const orderStore = useOrderStore();
56
+
57
+ const addForm = ref(null);
58
+
59
+ const state = reactive({
60
+ isLoading: computed(() => (addForm.value ? addForm.value.loading : true)),
61
+ isSending: false,
62
+ wasSuccess: false,
63
+ user: {},
64
+ });
65
+
66
+ function sendForm() {
67
+ const isValid = validate(addForm.value.state.skel);
68
+
69
+ if (isValid) {
70
+ state.isSending = true;
71
+
72
+ addForm.value.sendData().then(async (resp) => {
73
+ let data = await resp.json();
74
+
75
+ state.isSending = false;
76
+
77
+ if (data["action"] === "addSuccess") {
78
+ addForm.value.state.skel = data.values;
79
+
80
+ if (props.type === "billing") {
81
+ addressStore.state.active.billing = addForm.value.state.skel;
82
+
83
+ orderStore.updateParams({
84
+ billing_address_key: addressStore.state.active.billing.key,
85
+ });
86
+
87
+ if (addressStore.state.clone) {
88
+ cartStore.update({
89
+ key: orderStore.state.currentOrder.cart.dest.key,
90
+ shippingAddress: addressStore.state.active.shipping.key,
91
+ });
92
+ }
93
+ } else {
94
+ addressStore.state.active.shipping = addForm.value.state.skel;
95
+
96
+ cartStore.update({
97
+ key: orderStore.state.currentOrder.cart.dest.key,
98
+ shippingAddress: addressStore.state.active.shipping.key,
99
+ });
100
+ }
101
+
102
+ emit("addSuccess", {
103
+ show: true,
104
+ msg: "Erfolg!",
105
+ variant: "success",
106
+ icon: "check2-circle",
107
+ });
108
+
109
+ emit("valid", true);
110
+ } else {
111
+ emit("valid", false);
112
+ }
113
+ });
114
+ }
115
+ }
116
+
117
+ // TODO: needs a real validation solution with logics used in backend configuration
118
+ function validate(formData) {
119
+ const structure = addressStore.state.structure;
120
+ let total = 0;
121
+ let valid = 0;
122
+
123
+ // TODO: will be deleted when backend address module is set up properly
124
+ structure.firstname.required = true;
125
+ structure.lastname.required = true;
126
+ structure.street_name.required = true;
127
+ structure.street_number.required = true;
128
+ structure.zip_code.required = true;
129
+ structure.city.required = true;
130
+ structure.country.required = true;
131
+
132
+ for (let key of Object.keys(structure)) {
133
+ if (structure[key].required) {
134
+ total += 1;
135
+ }
136
+ }
137
+
138
+ for (let [key, value] of Object.entries(formData)) {
139
+ if (structure[key].required && value) {
140
+ valid += 1;
141
+ }
142
+ }
143
+
144
+ if (valid === total) {
145
+ return true;
146
+ }
147
+
148
+ return false;
149
+ }
150
+
151
+ function updateValues() {
152
+ emit("update:modelValue", addForm.value.state.skel);
153
+ }
154
+
155
+ onMounted(() => {
156
+ addressStore.getStructure();
157
+ });
158
+ </script>
159
+
160
+ <style scoped></style>