@viur/shop-components 0.0.1-dev.9 → 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 -119
  56. package/src/views/ViewMissing.vue +0 -20
@@ -0,0 +1,95 @@
1
+ import {reactive,ref, computed} from 'vue'
2
+ import { useOrder } from '../composables/order';
3
+ import { useCart } from '../composables/cart';
4
+ import { useViurShopStore } from '../shop'
5
+ import { defineStore } from "pinia";
6
+ export const useAddress = defineStore("useAddressStore", () => {
7
+ const shopStore = useViurShopStore()
8
+
9
+ const state = reactive({
10
+ billingIsShipping:true,
11
+ shippingForm:ref(null),
12
+ // for shipping and both mode
13
+ shippingIsLoading:computed(()=>{
14
+ if (!state.shippingForm){
15
+ return true
16
+ }
17
+ return state.shippingForm.state.loading
18
+ }),
19
+ shippingIsUpdating:false, // for shipping and both mode
20
+ shippingData:{},
21
+ shippingValid:computed(()=>{
22
+ if(shopStore.state.cartRoot?.['shipping_address']){
23
+ return true
24
+ }
25
+ return false
26
+ }),
27
+
28
+ billingForm:ref(null),
29
+ billingIsLoading:computed(()=>{
30
+ if (!state.billingForm){
31
+ return true
32
+ }
33
+ return state.billingForm.state.loading
34
+ }),
35
+ billingIsUpdating:false,
36
+ billingData:{},
37
+ billingValid:computed(()=>{
38
+ if( shopStore.state.order?.['billing_address']){
39
+ return true
40
+ }
41
+ return false
42
+ })
43
+
44
+ })
45
+
46
+ function saveForm(type,shippingIsBilling=false){
47
+ state[`${type}IsUpdating`] = true
48
+ return state[`${type}Form`].sendData().then(async (resp)=>{
49
+ let data = await resp.json()
50
+ if (['addSuccess','editSuccess'].includes(data['action'])){
51
+ state[`${type}Data`] = data['values']
52
+ await updateAddresses(type, shippingIsBilling)
53
+ }
54
+ state[`${type}IsUpdating`] = undefined
55
+ return data
56
+ })
57
+ }
58
+
59
+ function saveAddresses(shippingIsBilling=false){
60
+ if (shippingIsBilling) {
61
+ return saveForm('shipping',shippingIsBilling)
62
+ }else{
63
+ return new Promise((resolve, reject) => {
64
+ saveForm('shipping').then(()=>{
65
+ saveForm('billing').then(()=>{
66
+ resolve({'actions':'editSuccess'})
67
+ }).catch((e)=>reject(e))
68
+ }).catch((e)=>reject(e))
69
+ })
70
+ }
71
+ }
72
+
73
+ async function updateAddresses(type, shippingIsBilling=false) {
74
+ let key = state[`${type}Data`]['key']
75
+
76
+ if (type === 'shipping'){
77
+ const {updateCart} = useCart()
78
+ updateCart({shipping_address_key:key})
79
+ if(shippingIsBilling){
80
+ const {addOrUpdateOrder} = useOrder()
81
+ await addOrUpdateOrder({billing_address_key:key})
82
+ }
83
+ }else if (type === 'billing'){
84
+ const {addOrUpdateOrder} = useOrder()
85
+ await addOrUpdateOrder({billing_address_key:key})
86
+ }
87
+ }
88
+
89
+ return {
90
+ state,
91
+ saveForm,
92
+ updateAddresses,
93
+ saveAddresses
94
+ }
95
+ })
@@ -0,0 +1,189 @@
1
+ import {reactive} from 'vue'
2
+ import {Request} from '@viur/vue-utils'
3
+ import { removeUndefinedValues} from '../utils'
4
+
5
+ import { useViurShopStore } from '../shop'
6
+
7
+ export function useCart() {
8
+ const shopStore = useViurShopStore()
9
+ const state = reactive({
10
+ isLoading:false,
11
+ isUpdating:false
12
+ })
13
+
14
+ function getValue(value){
15
+ if (value !== null &&
16
+ typeof value === 'object' &&
17
+ !Array.isArray(value) &&
18
+ Object.keys(value).includes(shopStore.state.language)
19
+ ){
20
+ return value[shopStore.state.language]
21
+ }
22
+ return value
23
+ }
24
+
25
+ function createCart(){
26
+ Request.post(shopStore.state.shopApiUrl+'/cart_add',{dataObj:{
27
+ parent_cart_key:shopStore.state.cartRoot['key'],
28
+ cart_type:"wishlist"
29
+ }}).then(async( resp)=>{
30
+ let data = await resp.json()
31
+ console.log(data)
32
+ })
33
+
34
+
35
+ }
36
+
37
+
38
+ function fetchCart() {
39
+ //first fetch root then fetchItems for this root
40
+ state.isLoading = true;
41
+
42
+ if (shopStore.state.order != null && shopStore.order?.cart?.key.length) {
43
+ shopStore.state.cartRoot = {};
44
+ shopStore.state.cartRoot = shopStore.state.order.cart;
45
+
46
+ return fetchCartItems(shopStore.state.order.cart.key).then(() => {
47
+ state.isLoading = false;
48
+ shopStore.state.cartReady = true;
49
+ });
50
+ }
51
+ return fetchCartRoot().then(() => {
52
+ if (!shopStore.state.cartRoot?.["key"]) return 0;
53
+ fetchCartItems(shopStore.state.cartRoot["key"]).then(() => {
54
+ state.isLoading = false;
55
+ shopStore.state.cartReady = true;
56
+ });
57
+ });
58
+ }
59
+
60
+ function fetchCartRoot(){
61
+ // fetch list of Rootnodes and saves the first one
62
+
63
+ return Request.get(`${shopStore.state.shopUrl}/cart/listRootNodes`).then(async (resp)=>{
64
+ let data = await resp.json()
65
+ shopStore.state.cartRoot = data.filter(i=>i['cart_type']==='basket')?.[0] ? data.filter(i=>i['cart_type']==='basket')[0]:[]
66
+ })
67
+ }
68
+
69
+ function fetchCartItems(key, parentKey=null){
70
+ //fetch cart items
71
+ return Request.get(`${shopStore.state.shopApiUrl}/cart_list`,{dataObj:{
72
+ cart_key:key
73
+ }}).then(async( resp) =>{
74
+ let data = await resp.json()
75
+ shopStore.state.cartList=data
76
+ })
77
+ }
78
+
79
+ function updateCart({
80
+ cart_key,
81
+ cart_type,
82
+ name,
83
+ customer_comment,
84
+ shipping_address_key,
85
+ shipping_key,
86
+ discount_key,
87
+ project_data
88
+ } = {}){
89
+
90
+ let data= {
91
+ cart_type:cart_type?cart_type:shopStore.state.cartRoot['cart_type'],
92
+ name:name?name:shopStore.state.cartRoot['name'],
93
+ customer_comment:customer_comment?customer_comment:shopStore.state.cartRoot['customer_comment'],
94
+ shipping_address_key:shipping_address_key?shipping_address_key:shopStore.state.cartRoot?.['shipping_address']?.['dest']?.['key'],
95
+ shipping_key:shipping_key?shipping_key:shopStore.state.cartRoot?.['shipping']?.['dest']?.['key'],
96
+ discount_key:discount_key?discount_key:shopStore.state.cartRoot?.['discount']?.['dest']?.['key'],
97
+ cart_key:cart_key ? cart_key : shopStore.state.cartRoot['key'],
98
+ }
99
+
100
+ if (project_data) {
101
+ data.project_data = JSON.stringify(project_data)
102
+ }
103
+
104
+ return Request.post(`${shopStore.state.shopApiUrl}/cart_update`, {
105
+ dataObj: removeUndefinedValues(data)
106
+ }).then(async (resp)=>{
107
+ fetchCart()
108
+ })
109
+ }
110
+
111
+ function addItem(key, quantity=1, cart=null, quantity_mode='replace'){
112
+ //add Item to cart
113
+ state.isUpdating = true
114
+ return Request.post(`${shopStore.state.shopApiUrl}/article_add`, {dataObj:{
115
+ article_key: key,
116
+ parent_cart_key:cart?cart:shopStore.state.cartRoot['key'],
117
+ quantity:quantity,
118
+ quantity_mode:quantity_mode
119
+ }}).then(async (resp)=>{
120
+ state.isUpdating=false
121
+ fetchCart()
122
+ })
123
+
124
+ }
125
+ function removeItem(key, cart=null){
126
+ state.isUpdating = true
127
+ return Request.post(`${shopStore.state.shopApiUrl}/article_remove`, {dataObj:{
128
+ article_key: key,
129
+ parent_cart_key:cart?cart:shopStore.state.cartRoot['key']
130
+ }}).then(async (resp)=>{
131
+ state.isUpdating=false
132
+ fetchCart()
133
+ })
134
+ }
135
+
136
+ function addDiscount(code) {
137
+ return new Promise((resolve, reject) => {
138
+ Request.securePost(`${shopStore.state.shopApiUrl}/discount_add`, {
139
+ dataObj: {
140
+ code: code,
141
+ },
142
+ })
143
+ .then(async (resp) => {
144
+ let data = await resp.json();
145
+ fetchCart()
146
+ console.log("discount debug", data);
147
+ resolve()
148
+ })
149
+ .catch((error) => {
150
+ reject(error);
151
+ });
152
+ });
153
+ }
154
+
155
+ function removeDiscount() {
156
+ return new Promise((resolve, reject) => {
157
+ Request.securePost(`${shopStore.state.shopApiUrl}/discount_remove`, {
158
+ dataObj: {
159
+ discount_key: shopStore.state.cartRoot.discount.dest.key,
160
+ },
161
+ })
162
+ .then(async (resp) => {
163
+ let data = await resp.json();
164
+ fetchCart()
165
+ console.log("discount debug", data);
166
+ resolve()
167
+ })
168
+ .catch((error) => {
169
+ reject(error);
170
+ });
171
+ });
172
+ }
173
+
174
+
175
+
176
+ return {
177
+ state,
178
+ fetchCartRoot,
179
+ fetchCartItems,
180
+ fetchCart,
181
+ updateCart,
182
+ addItem,
183
+ removeItem,
184
+ createCart,
185
+ getValue,
186
+ addDiscount,
187
+ removeDiscount
188
+ }
189
+ }
@@ -0,0 +1,80 @@
1
+ import {reactive} from 'vue'
2
+ import {Request} from '@viur/vue-utils'
3
+ import { useViurShopStore } from '../shop'
4
+ import { removeUndefinedValues} from '../utils'
5
+ import { useUrlSearchParams } from '@vueuse/core'
6
+
7
+ export function useOrder() {
8
+ const state = reactive({
9
+ isLoading:false,
10
+ isUpdating:false
11
+ })
12
+ const shopStore = useViurShopStore()
13
+ function updateOrderState(key,data){
14
+ shopStore.state.order = data
15
+ shopStore.state.orderKey = key
16
+
17
+ const params = useUrlSearchParams('hash')
18
+ params['order'] = shopStore.state.orderKey
19
+
20
+ }
21
+ function fetchOrder(key){
22
+ state.isLoading = true
23
+ return Request.post(shopStore.state.shopApiUrl+"/order_view",{dataObj:{
24
+ "order_key": key
25
+ }}).then(async (resp)=>{
26
+ let data = await resp.json()
27
+ updateOrderState(data['skel']['key'], data['skel'])
28
+ shopStore.state.canCheckout = data["can_checkout"]
29
+ shopStore.state.canOrder = data["can_order"]
30
+ state.isLoading = false
31
+ }).catch((error)=>{
32
+ shopStore.state.order = null
33
+ shopStore.state.orderKey = null
34
+ state.isLoading = false
35
+ })
36
+ }
37
+
38
+ function addOrUpdateOrder({
39
+ payment_provider,
40
+ billing_address_key,
41
+ email,
42
+ customer_key,
43
+ state_ordered,
44
+ state_paid,
45
+ state_rts
46
+ }={}){
47
+ state.isUpdating=true
48
+ let url = shopStore.state.shopApiUrl+"/order_add"
49
+ let data = {
50
+ payment_provider:payment_provider?payment_provider:shopStore.state.order?.['payment_provider'],
51
+ billing_address_key:billing_address_key?billing_address_key:shopStore.state.order?.['billing_address_key']?.['dest']?.['key'],
52
+ email:email?email:shopStore.state.order?.['email'],
53
+ customer_key:customer_key?customer_key:shopStore.state.order?.['customer_key']?.['dest']?.['key'],
54
+ state_ordered:state_ordered?state_ordered:shopStore.state.order?.['state_ordered'],
55
+ state_paid:state_paid?state_paid:shopStore.state.order?.['state_paid'],
56
+ state_rts:state_rts?state_rts:shopStore.state.order?.['state_rts']
57
+ }
58
+ if (shopStore.state.orderKey){
59
+ url = shopStore.state.shopApiUrl+"/order_update"
60
+ data["order_key"] = shopStore.state.orderKey
61
+
62
+ }else{
63
+ data["cart_key"] = shopStore.state.cartRoot['key']
64
+ }
65
+ return Request.post(url,{dataObj:removeUndefinedValues(data)}).then(async(resp)=>{
66
+ let data = await resp.json()
67
+ updateOrderState(data['key'], data)
68
+ state.isUpdating=false
69
+ }).then(async ( resp)=>{
70
+ fetchOrder(shopStore.state.orderKey)
71
+ return resp
72
+ })
73
+ }
74
+
75
+ return {
76
+ state,
77
+ fetchOrder,
78
+ addOrUpdateOrder
79
+ }
80
+ }
@@ -0,0 +1,75 @@
1
+ import {reactive} from 'vue'
2
+ import {Request} from '@viur/vue-utils'
3
+ import { removeUndefinedValues} from '../utils'
4
+ import { useViurShopStore } from '../shop'
5
+ import {defineStore} from "pinia";
6
+
7
+ export const usePayment = defineStore("usePaymentStore", () => {
8
+ const shopStore = useViurShopStore()
9
+
10
+ const iconMap = {
11
+ 'prepayment':'currency-euro',
12
+ 'unzer-card':'credit-card-2-back-fill',
13
+ 'unzer-paypal':'paypal',
14
+ 'unzer-ideal':'bank2',
15
+ 'unzer-sofort':'cash-coin'
16
+ }
17
+
18
+ const simpleProviders = [
19
+ 'prepayment',
20
+ 'unzer-paypal',
21
+ 'unzer-sofort'
22
+ ]
23
+
24
+ const state = reactive({
25
+ isLoading:false,
26
+ isUpdating:false,
27
+ paymentData:[]
28
+ })
29
+
30
+ function _convertPayment(paymentProviders){
31
+ paymentProviders = Object.entries(paymentProviders)
32
+ let options = []
33
+ let option = {
34
+ paymenttype:null,
35
+ widget:"default",
36
+ name:null,
37
+ description:null,
38
+ icon:null
39
+
40
+ }
41
+
42
+ for (const provider of paymentProviders){
43
+ let currentOption = {...option}
44
+ currentOption.paymenttype = provider[0]
45
+ currentOption.name = provider[1]['title']
46
+ currentOption.description = provider[1]['descr']
47
+ currentOption.icon = iconMap[provider[0]]
48
+ currentOption.widget = "simple"
49
+ // if (simpleProviders.includes(provider[0])){
50
+ // currentOption.widget = "simple" // payment provider musst be initialized later
51
+ //}
52
+
53
+ options.push(currentOption)
54
+ }
55
+
56
+
57
+ return options
58
+ }
59
+
60
+ function fetchPaymentData() {
61
+ state.isLoading = true
62
+ return Request.get(`${shopStore.state.shopUrl}/order/payment_providers_list`).then(async (resp)=>{
63
+ let data = await resp.json()
64
+ state.paymentData = _convertPayment(data)
65
+ state.isLoading = false
66
+ })
67
+ }
68
+
69
+
70
+ return {
71
+ state,
72
+ fetchPaymentData
73
+
74
+ }
75
+ })
@@ -0,0 +1,40 @@
1
+ import {reactive} from 'vue'
2
+ import {Request} from '@viur/vue-utils'
3
+ import { removeUndefinedValues} from '../utils'
4
+ import { useI18n } from 'vue-i18n'
5
+ import { useViurShopStore } from '../shop'
6
+
7
+ export function useShipping() {
8
+ const i18n = useI18n()
9
+ const shopStore = useViurShopStore()
10
+ const defaultErrorMessage = i18n.t('shop.error_message')
11
+ const state = reactive({
12
+ isLoading:false,
13
+ isUpdating:false,
14
+ hasError:false,
15
+ errorMessage: defaultErrorMessage,
16
+ shippingData:[]
17
+ })
18
+
19
+ function fetchShippingData() {
20
+ state.isLoading = true
21
+ Request.get(`${shopStore.state.shopApiUrl}/shipping_list`,{dataObj:{
22
+ cart_key: shopStore.state.cartRoot['key']
23
+ }}).then(async (resp)=>{
24
+ let data = await resp.json()
25
+ state.shippingData = data
26
+ if (state.shippingData.length===0){
27
+ state.hasError = true
28
+ state.errorMessage = i18n.t("shop.no_valid_shipping_found")
29
+ }
30
+ state.isLoading = false
31
+ })
32
+ }
33
+
34
+
35
+ return {
36
+ state,
37
+ fetchShippingData
38
+
39
+ }
40
+ }
package/src/main.js ADDED
@@ -0,0 +1,44 @@
1
+ // imports
2
+ import { createPinia } from "pinia";
3
+ import { createI18n } from "vue-i18n";
4
+ import { getTranslations } from "./utils";
5
+ import { de_translations, en_translations } from "@viur/vue-utils";
6
+ import en from "./translations/en"
7
+ import de from "./translations/de"
8
+
9
+ export { default as ViurShop } from "./Shop.vue";
10
+
11
+ const ViurShopComponents = {
12
+ async install(app,options) {
13
+
14
+ let defaultLocale = options?.defaultLocale?options.defaultLocale:'de'
15
+ let locale = options?.locale?options.locale:['de']
16
+ let fallback = options?.fallback?options.fallback:'en'
17
+ app.use(createPinia());
18
+
19
+ let messages = {}
20
+ // fetch translations from server
21
+ let data = await getTranslations(locale)
22
+ for(const loc of locale){
23
+ if (loc === 'de'){
24
+ messages[loc] = { ...de_translations, ...de, ...data[loc]}
25
+ }else if (loc === 'en'){
26
+ messages[loc] = {...en_translations, ...en, ...data[loc]}
27
+ }else{
28
+ messages[loc] = {...data[loc]}
29
+ }
30
+ }
31
+
32
+ // server_translations will be overwritten by utils. Both are overwritten by local shop translations
33
+ app.use(
34
+ createI18n({
35
+ locale: defaultLocale,
36
+ fallbackLocale: fallback,
37
+ messages: messages,
38
+ })
39
+ );
40
+ },
41
+ };
42
+
43
+ // Export the plugin as default
44
+ export default ViurShopComponents;