@viur/shop-components 0.0.1-dev.8 → 0.1.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.
Files changed (56) 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 +23 -11
  7. package/src/Shop.vue +232 -0
  8. package/src/ShopOrderStepper.vue +114 -0
  9. package/src/ShopSummary.vue +196 -0
  10. package/src/Steps/ShopCart.vue +57 -0
  11. package/src/Steps/ShopOrderComplete.vue +32 -0
  12. package/src/Steps/ShopOrderConfirm.vue +300 -0
  13. package/src/Steps/ShopPaymentProvider.vue +56 -0
  14. package/src/Steps/ShopShippingMethod.vue +67 -0
  15. package/src/Steps/ShopUserDataGuest.vue +82 -0
  16. package/src/Steps/index.js +15 -0
  17. package/src/components/AddressForm.vue +95 -0
  18. package/src/components/AddressFormLayout.vue +107 -0
  19. package/src/components/CardSelector.vue +68 -0
  20. package/src/components/CartItem.vue +353 -0
  21. package/src/components/CartItemSmall.vue +257 -0
  22. package/src/components/DiscountInput.vue +91 -0
  23. package/src/components/LoadingHandler.vue +76 -0
  24. package/src/components/PaymentOption.vue +78 -0
  25. package/src/components/PaymentProviderUnzer.vue +201 -0
  26. package/src/components/PaymentSelector.vue +55 -0
  27. package/src/components/ShopAlert.vue +30 -0
  28. package/src/components/StepperTab.vue +132 -0
  29. package/src/components/dialogButton.vue +49 -0
  30. package/src/composables/address.js +95 -0
  31. package/src/composables/cart.js +189 -0
  32. package/src/composables/order.js +80 -0
  33. package/src/composables/payment.js +75 -0
  34. package/src/composables/shipping.js +40 -0
  35. package/src/main.js +44 -0
  36. package/src/shop.js +252 -0
  37. package/src/translations/de.js +36 -0
  38. package/src/translations/en.js +5 -0
  39. package/src/utils.js +56 -0
  40. package/vite.config.js +51 -0
  41. package/src/components/cart/CartView.vue +0 -693
  42. package/src/components/cart/ConfirmView.vue +0 -314
  43. package/src/components/order/category/CategoryList.vue +0 -83
  44. package/src/components/order/category/CategoryView.vue +0 -143
  45. package/src/components/order/information/UserInfoMulti.vue +0 -427
  46. package/src/components/order/information/UserInformation.vue +0 -332
  47. package/src/components/order/information/adress/ShippingAdress.vue +0 -143
  48. package/src/components/order/item/ItemCard.vue +0 -168
  49. package/src/components/order/item/ItemView.vue +0 -233
  50. package/src/components/order/process/ExampleUsage.vue +0 -100
  51. package/src/components/order/process/OrderComplete.vue +0 -41
  52. package/src/components/order/process/OrderTabHeader.vue +0 -7
  53. package/src/components/order/process/OrderView.vue +0 -210
  54. package/src/router/index.js +0 -103
  55. package/src/stores/cart.js +0 -118
  56. package/src/views/ViewMissing.vue +0 -20
@@ -0,0 +1,67 @@
1
+ <template>
2
+ <loading-handler :isLoading="shippingState.isLoading" :hasError="shippingState.hasError" :errorMessage="shippingState.errorMessage">
3
+
4
+ <card-selector :options="shippingState.shippingData"
5
+ v-model:selection="state.selectedShippingMethod"
6
+ @change="updateShippingMethod"
7
+ >
8
+ <template v-slot="{option, index}">
9
+ <img slot="image">
10
+
11
+ <sl-format-number lang="de" type="currency" currency="EUR" :value=" option['dest']['shipping_cost']" v-if="option['dest']['shipping_cost']">
12
+ </sl-format-number>
13
+ <span v-else>{{ $t('shop.free_shipping') }}</span>
14
+ {{ option['dest']['name'] }} - {{$t('shop.deliverytime')}}: {{ option['dest']['delivery_time_range'] }} {{ $t('shop.day',option['dest']['delivery_time_max'] - option['dest']['delivery_time_min']) }}
15
+ </template>
16
+ </card-selector>
17
+ </loading-handler>
18
+
19
+ <slot name="template_shippingmethod">
20
+ </slot>
21
+
22
+ <slot
23
+ nextName="weiter"
24
+ :activefunction="()=>shopStore.state.cartRoot?.['shipping']"
25
+ :nextfunction="()=>nextStep"
26
+ >
27
+ </slot>
28
+ </template>
29
+ <script setup>
30
+ import {reactive,onBeforeMount} from "vue";
31
+ import CardSelector from "../components/CardSelector.vue";
32
+ import LoadingHandler from "../../old/components/generic/loadinghandler.vue";
33
+ import {useShipping} from "../composables/shipping";
34
+ import {useCart} from "../composables/cart";
35
+ import { useOrder } from "../composables/order";
36
+ import {useViurShopStore} from "../shop";
37
+
38
+ const shopStore = useViurShopStore();
39
+ const {updateCart} = useCart();
40
+ const {fetchOrder} = useOrder();
41
+ const {state: shippingState,fetchShippingData} = useShipping();
42
+
43
+ const state = reactive({
44
+ selectedShippingMethod: null
45
+ })
46
+
47
+ function updateShippingMethod(selection){
48
+ shopStore.state.cartRoot['shipping'] = null
49
+ if (selection){
50
+ updateCart({shipping_key:selection['dest']['key']})
51
+ }
52
+ }
53
+
54
+ async function nextStep(){
55
+ await fetchOrder(shopStore.state.orderKey)
56
+ }
57
+
58
+ onBeforeMount(()=>{
59
+ fetchShippingData()
60
+ state.selectedShippingMethod = shopStore.state.cartRoot?.['shipping']
61
+ })
62
+ </script>
63
+
64
+
65
+ <style scoped>
66
+
67
+ </style>
@@ -0,0 +1,82 @@
1
+ <template>
2
+ <div class="viur-shop-cart-address-headline">
3
+ {{ $t("skeleton.address.address_type.shipping") }}
4
+ </div>
5
+
6
+ <address-form :formtype="addressState.billingIsShipping?'both':'shipping'">
7
+ </address-form>
8
+ <div>
9
+ <sl-switch :checked="addressState.billingIsShipping" @sl-change="switchAddresses">{{ $t('shop.use_shipping_as_billing_address') }}</sl-switch>
10
+ </div>
11
+
12
+ <div v-show="!addressState.billingIsShipping">
13
+ <div class="viur-shop-cart-address-headline">
14
+ {{ $t("skeleton.address.address_type.billing") }}
15
+ </div>
16
+ <address-form formtype="billing" ></address-form>
17
+ </div>
18
+
19
+ <slot name="template_userdata">
20
+ </slot>
21
+
22
+ <slot
23
+ nextName="weiter"
24
+ :activefunction="()=>true"
25
+ :nextfunction="nextStep"
26
+ :hint="$t('messages.order_check_later')"
27
+ >
28
+ </slot>
29
+ </template>
30
+
31
+
32
+
33
+ <script setup>
34
+ import {reactive, onBeforeMount, watch} from 'vue'
35
+ import AddressForm from '../components/AddressForm.vue'
36
+ import {useAddress} from "../composables/address";
37
+ import {useViurShopStore} from "../shop";
38
+ const shopStore = useViurShopStore();
39
+ const {state:addressState,saveAddresses} = useAddress()
40
+
41
+ const state = reactive({
42
+ })
43
+
44
+ function switchAddresses(event){
45
+ addressState.billingIsShipping=event.target.checked
46
+ }
47
+
48
+ onBeforeMount(()=>{
49
+ if (shopStore.state.cartRoot?.['shipping_address']?.['dest']?.['address_type']?.includes('billing') || !shopStore.state.cartRoot?.['shipping_address']?.['dest']){
50
+ addressState.billingIsShipping = true
51
+ }else{
52
+ addressState.billingIsShipping = false
53
+ }
54
+ })
55
+
56
+
57
+ async function nextStep(){
58
+ // form is only valid if the action field ends with Success
59
+ try{
60
+ let result = await saveAddresses(addressState.billingIsShipping)
61
+ if (result['action'] && result['action'].endsWith('Success')){
62
+ return true
63
+ }
64
+ return false
65
+ } catch(error){
66
+ return false
67
+ }
68
+ }
69
+
70
+ </script>
71
+
72
+ <style scoped>
73
+ .viur-shop-cart-address-headline {
74
+ display: flex;
75
+ flex-direction: row;
76
+ flex-wrap: nowrap;
77
+ align-items: center;
78
+ justify-content: space-between;
79
+ font-weight: 600;
80
+ margin-bottom: var(--sl-spacing-medium);
81
+ }
82
+ </style>
@@ -0,0 +1,15 @@
1
+ import ShopCart from './ShopCart.vue'
2
+ import ShopUserDataGuest from './ShopUserDataGuest.vue'
3
+ import ShopShippingMethod from './ShopShippingMethod.vue'
4
+ import ShopPaymentProvider from './ShopPaymentProvider.vue'
5
+ import ShopOrderConfirm from './ShopOrderConfirm.vue'
6
+ import ShopOrderComplete from './ShopOrderComplete.vue'
7
+
8
+ export {
9
+ ShopCart,
10
+ ShopUserDataGuest,
11
+ ShopShippingMethod,
12
+ ShopPaymentProvider,
13
+ ShopOrderConfirm,
14
+ ShopOrderComplete
15
+ }
@@ -0,0 +1,95 @@
1
+ <template>
2
+ <LoadingHandler :is-loading="addressState[`${state.formtype}IsLoading`]"></LoadingHandler>
3
+ <ViForm
4
+ :ref="(el)=>{addressState[`${state.formtype}Form`]=el; return el}"
5
+ :module="`${shopStore.state.moduleName}/address`"
6
+ :action="state.action"
7
+ :skelkey="state.skelkey"
8
+ :values="{'address_type':state.address_type, 'customer_type':'private'}"
9
+ :useCategories="false"
10
+ :layout="AddressFormLayout"
11
+ @change="formChange"
12
+ :default-language="state.language"
13
+ error-style="decent"
14
+ >
15
+ </ViForm>
16
+ </template>
17
+
18
+ <script setup>
19
+ import {computed, reactive, watch} from 'vue'
20
+ import LoadingHandler from './LoadingHandler.vue';
21
+ import AddressFormLayout from './AddressFormLayout.vue';
22
+ import ViForm from "@viur/vue-utils/forms/ViForm.vue";
23
+ import {useViurShopStore} from "../shop";
24
+ import {useAddress} from "../composables/address";
25
+
26
+ const shopStore = useViurShopStore();
27
+ const {state:addressState} = useAddress();
28
+
29
+ const props = defineProps({
30
+ formtype:{
31
+ type:String,
32
+ default:"shipping" // formtype: shipping, billing, both
33
+ }
34
+ })
35
+
36
+ const state = reactive({
37
+ formtype:computed(()=>{
38
+ if (['shipping','both'].includes(props.formtype)){
39
+ return "shipping"
40
+ }
41
+ return 'billing'
42
+ }),
43
+
44
+ action: computed(()=>{
45
+ if (state.formtype ==='shipping' && shopStore.state.cartRoot?.['shipping_address']){
46
+ return 'edit'
47
+ } else if (props.formtype === 'billing' && shopStore.state.order?.['billing_address']){
48
+ return 'edit'
49
+ } else {
50
+ return 'add'
51
+ }
52
+ }),
53
+
54
+ skelkey:computed(()=>{
55
+ if (state.formtype === 'shipping' && shopStore.state.cartRoot?.['shipping_address']){
56
+ return shopStore.state.cartRoot['shipping_address']?.['dest']?.['key']
57
+ } else if (props.formtype === 'billing' && shopStore.state.order?.['billing_address']){
58
+ return shopStore.state.order?.['billing_address']?.['dest']?.['key']
59
+ }
60
+ return null
61
+
62
+ }),
63
+ address_type:computed(()=>{
64
+ if (props.formtype === 'both'){
65
+ return ["shipping",'billing']
66
+ }
67
+ return [state.formtype]
68
+ }),
69
+ language: "de"
70
+ })
71
+
72
+ function formChange(data){
73
+ if (data.name === "country"){
74
+ state.language = data.value
75
+ }
76
+ }
77
+
78
+
79
+ watch(()=>addressState.billingIsShipping, (newVal,oldVal)=>{
80
+ if(oldVal && !newVal){
81
+ if(shopStore.state.order?.['billing_address']){
82
+ shopStore.state.order['billing_address'] = null
83
+ }
84
+
85
+ addressState[`billingForm`].state.skel = {'address_type':state.address_type, 'customer_type':'private'}
86
+
87
+ }
88
+
89
+ })
90
+
91
+ </script>
92
+
93
+ <style scoped>
94
+
95
+ </style>
@@ -0,0 +1,107 @@
1
+ <template>
2
+ <div class="vi-shop-cart-form-wrap" v-if="Object.keys(formState.structure).length > 0">
3
+ <slot
4
+ boneName="salutation"
5
+ :widget="getBoneWidget(formState.structure['salutation']['type'])"
6
+ label="placeholder"
7
+ >
8
+ </slot>
9
+
10
+ <slot boneName="firstname"
11
+ :widget="getBoneWidget(formState.structure['firstname']['type'])"
12
+ label="placeholder">
13
+ </slot>
14
+
15
+ <slot boneName="lastname"
16
+ :widget="getBoneWidget(formState.structure['lastname']['type'])"
17
+ label="placeholder">
18
+ </slot>
19
+
20
+ <slot boneName="street_name"
21
+ :widget="getBoneWidget(formState.structure['street_name']['type'])"
22
+ label="placeholder">
23
+ </slot>
24
+
25
+ <slot boneName="street_number"
26
+ :widget="getBoneWidget(formState.structure['street_number']['type'])"
27
+ label="placeholder">
28
+ </slot>
29
+
30
+ <slot
31
+ boneName="zip_code"
32
+ :widget="getBoneWidget(formState.structure['zip_code']['type'])"
33
+ placeholder="placeholder"
34
+ label="placeholder"
35
+ >
36
+ </slot>
37
+
38
+ <slot boneName="city"
39
+ :widget="getBoneWidget(formState.structure['city']['type'])"
40
+ label="placeholder">
41
+ </slot>
42
+
43
+
44
+ <slot boneName="country"
45
+ :widget="getBoneWidget(formState.structure['country']['type'])"
46
+ label="placeholder">
47
+ </slot>
48
+
49
+ </div>
50
+ </template>
51
+ <script setup>
52
+ import { inject } from "vue";
53
+ import { getBoneWidget } from "@viur/vue-utils/bones/edit";
54
+
55
+ const formState = inject("formState");
56
+ const formUpdate = inject("formUpdate");
57
+ </script>
58
+ <style scoped>
59
+
60
+ .vi-shop-cart-form-wrap{
61
+ display: grid;
62
+ grid-template-columns: repeat(4, minmax(0, 1fr));
63
+ gap: var(--sl-spacing-small);
64
+ margin-bottom: var(--sl-spacing-medium);
65
+ }
66
+
67
+ :deep(.bone-wrapper){
68
+ margin: 0;
69
+ }
70
+
71
+ :deep(.wrapper-bone-firstname){
72
+ grid-column: 1 / span 2;
73
+ }
74
+
75
+ :deep(.wrapper-bone-lastname){
76
+ grid-column: 3 / span 2;
77
+ }
78
+
79
+ :deep(.wrapper-bone-street_name){
80
+ grid-column: 1 / span 3;
81
+ }
82
+
83
+ :deep(.wrapper-bone-street_number){
84
+ grid-column: 4 / span 1;
85
+ }
86
+
87
+ :deep(.wrapper-bone-zip_code){
88
+ grid-column: 1 / span 2;
89
+ }
90
+
91
+ :deep(.wrapper-bone-city){
92
+ grid-column: 3 / span 2;
93
+ }
94
+
95
+ :deep(.wrapper-bone-country){
96
+ grid-column: 1 / span 4;
97
+ }
98
+
99
+ :deep(.wrapper-bone-is_default){
100
+ padding: var(--sl-spacing-x-small) 0;
101
+ grid-column: 1 / span 4;
102
+ }
103
+
104
+
105
+
106
+
107
+ </style>
@@ -0,0 +1,68 @@
1
+ <template>
2
+ <sl-radio-group :value="state.currentSelection">
3
+ <template v-for="(option,i) in options">
4
+ <sl-card selectable @sl-change="changeSelection(i)" :selected="i===state.currentSelection" horizontal>
5
+ <slot :option="option" :index="i">
6
+ {{i}}: {{ option }}
7
+ </slot>
8
+ <sl-radio :value="i"></sl-radio>
9
+ </sl-card>
10
+ </template>
11
+ </sl-radio-group>
12
+ </template>
13
+
14
+ <script setup>
15
+ import {onMounted, reactive, watch} from 'vue'
16
+
17
+ const selection = defineModel("selection")
18
+
19
+ const emits = defineEmits(['change'])
20
+
21
+ const props = defineProps({
22
+ options:{
23
+ type: Array,
24
+ default:[]
25
+ },
26
+ })
27
+
28
+ const state = reactive({
29
+ currentSelection:null
30
+ })
31
+
32
+ function changeSelection(i){
33
+ if (state.currentSelection === i){
34
+ state.currentSelection = null
35
+ selection.value = null
36
+ }else{
37
+ state.currentSelection = i
38
+ selection.value = props.options[i]
39
+ }
40
+ emits("change", selection.value)
41
+ }
42
+
43
+ onMounted(()=>{
44
+ if (selection){
45
+ state.currentSelection = props.options.findIndex((option)=>option['dest']['key']===selection.value?.['dest']?.['key'])
46
+ }
47
+
48
+ })
49
+
50
+ </script>
51
+
52
+ <style scoped>
53
+ sl-card{
54
+ width: 100%;
55
+ &[selected]::part(base){
56
+ border:1px solid var(--sl-color-primary-500);
57
+ box-shadow: 0 0 0 var(--sl-focus-ring-width) var(--sl-input-focus-ring-color);
58
+ }
59
+
60
+ &::part(body){
61
+ display:flex;
62
+ flex-direction: row;
63
+ justify-content: space-between;
64
+ align-items: center;
65
+ }
66
+ }
67
+
68
+ </style>