@monkeyplus/payscope 1.0.1 → 1.0.3

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.
@@ -1,34 +1,13 @@
1
1
  <!-- eslint-disable ts/ban-ts-comment -->
2
2
  <script lang="ts" setup>
3
3
  import type { ProductStore, ProductStoreStocks } from '@monkeyplus/e-schema/models';
4
- import { useEventBus } from '@vueuse/core';
4
+ import { useAsyncState, useEventBus } from '@vueuse/core';
5
5
  import { ofetch } from 'ofetch';
6
6
  import { computed, inject, onMounted, reactive, ref } from 'vue';
7
7
  import { useCartStore } from '../stores.ts';
8
8
  import AddProductNumber from './AddProductNumber.vue';
9
- // import { useCrud, useShoppingCart, useTheProduct } from '../../helpers';
10
- // import { EButton, InputNumber } from '../shared/exports';
11
9
  import AddProductVariant from './AddProductVariant.vue';
12
- // const props = defineProps({
13
- // to: {
14
- // type: String,
15
- // },
16
- // omitStock: {
17
- // type: Boolean,
18
- // default: false,
19
- // },
20
- // hideWhistlist: {
21
- // type: Boolean,
22
- // default: false,
23
- // },
24
- // maxQuantity: {
25
- // type: Number,
26
- // },
27
- // messageMax: {
28
- // type: String,
29
- // },
30
- // product:
31
- // });
10
+
32
11
  const props = defineProps<{
33
12
  to?: string
34
13
  omitStock?: boolean
@@ -41,8 +20,6 @@ const emit = defineEmits(['stock']);
41
20
 
42
21
  const { product } = props;
43
22
 
44
- // const product = useTheProduct();
45
- // const { store } = useShoppingCart();
46
23
  const settings = reactive({
47
24
  omitStock: props.omitStock || product.noVariants,
48
25
  hideWhistlist: props.hideWhistlist,
@@ -52,19 +29,9 @@ type Selections = Record<string, string>;
52
29
 
53
30
  const busImages = useEventBus('busGalleryImages');
54
31
  const busCart = useEventBus('busCart');
55
- // const { crud: CrudCart } = useCrud('cart');
56
32
  const cartStore = useCartStore();
57
- const loading = ref(false);
58
- const { options, variants, id, uid, price, sku } = product;
59
-
60
- // const { state, uid: userId, user } = useIdentify();
61
-
62
- // const {} = useCustomer();
63
- // const whislist = useCrud('account/wishlist');
64
-
65
- // const addToCart = ()=>{
33
+ const { options, variants, id, price, sku } = product;
66
34
 
67
- // }
68
35
  const firstVariant = variants[0];
69
36
  const initValues = firstVariant.selectedOptions.reduce((acc, current) => {
70
37
  return {
@@ -75,28 +42,23 @@ const initValues = firstVariant.selectedOptions.reduce((acc, current) => {
75
42
 
76
43
  const quantity = ref(1);
77
44
  const selections = ref<Selections>(initValues);
78
- const stock = ref({} as ProductStoreStocks);
79
- // Initial images
80
45
  busImages.emit(selections.value);
81
46
 
82
- async function verifyStock() {
83
- try {
84
- loading.value = true;
85
- const stocks = await ofetch<ProductStoreStocks>(`/storefront/cache/products/${product.id}/stock`);
86
- stock.value = stocks;
87
- emit('stock', stocks);
88
- }
89
- catch (error) {
90
- console.warn(error);
91
- }
92
- finally {
93
- loading.value = false;
94
- }
95
- }
47
+ const { state: stock, isLoading: loading, executeImmediate: verifyStock } = useAsyncState(async () => {
48
+ // loading.value = true;
49
+ const stocks = await ofetch<ProductStoreStocks>(`/storefront/cache/products/${product.id}/stock`);
50
+ // stock.value = stocks;
51
+ emit('stock', stocks);
52
+ return stocks;
53
+ }, {} as ProductStoreStocks, {
54
+ immediate: false,
55
+ onError(e) {
56
+ console.error(e);
57
+ },
58
+ });
96
59
 
97
60
  if (!settings.omitStock)
98
61
  verifyStock();
99
- // console.log(selections.value);
100
62
 
101
63
  const selected = computed(() => {
102
64
  return variants.find((variant) => {
@@ -105,46 +67,46 @@ const selected = computed(() => {
105
67
  return variant.selectedOptions.every(el => selections.value[el.name] === el.value);
106
68
  });
107
69
  });
108
- const loadingAdd = ref(false);
109
70
  const loadingWhislist = ref(false);
110
71
 
72
+ const alertModal = reactive({
73
+ isOpen: false,
74
+ title: '',
75
+ description: '',
76
+ });
77
+
78
+ function showAlert(title: string, description: string) {
79
+ alertModal.title = title;
80
+ alertModal.description = description;
81
+ alertModal.isOpen = true;
82
+ }
83
+
111
84
  const addToCartOmit = inject('addToCartOmit', (_id: any, _selected: any, _items: any) => true);
112
85
  // const verify
113
86
  async function addToCart(): Promise<void> {
114
- loadingAdd.value = true;
115
-
116
- try {
117
- if (!addToCartOmit(`${id}:${selected.value?.id}`, selected.value, cartStore.items)) {
118
- return;
119
- }
120
- // console.log(selected.value);
121
- if (!settings.omitStock) {
122
- const r = await ofetch(`/storefront/cache/products/${encodeURIComponent(`${uid! || product.id}`)}/verify?selectedOptions=${JSON.stringify(selected.value?.selectedOptions || {})}`, {
123
- });
124
-
125
- if (!r.ok)
126
- return alert('Sin stock disponible');
127
- }
128
- const el = await cartStore.addToCart({
129
- id: `${id}:${selected.value?.id}`,
130
- quantity: quantity.value,
131
- });
132
- busCart.emit({
133
- action: 'create',
134
- payload: { ...el, product },
135
- });
87
+ if (!addToCartOmit(`${id}:${selected.value?.id}`, selected.value, cartStore.items)) {
88
+ return;
89
+ }
136
90
 
137
- if (!props.to)
138
- busCart.emit({ action: 'toogle' });
139
- else
140
- location.href = `${props.to}${props.to.includes('?') ? '&' : '?'}items=${el?.lineItems?.length}`;
91
+ const el = await cartStore.addToCart({
92
+ id: `${id}:${selected.value?.id}`,
93
+ quantity: quantity.value,
94
+ });
95
+ if (el.error && el.error === 'stock') {
96
+ showAlert('Aviso', 'Sin stock disponible');
97
+ return;
141
98
  }
142
- catch (error) {
143
- console.warn(error);
144
- alert('Error agregando');
99
+ busCart.emit({
100
+ action: 'create',
101
+ payload: { ...el, product },
102
+ });
103
+
104
+ if (!props.to) {
105
+ cartStore.open = true;
106
+ // console.log({ cartStore });
145
107
  }
146
- finally {
147
- loadingAdd.value = false;
108
+ else {
109
+ location.href = `${props.to}${props.to.includes('?') ? '&' : '?'}items=${el?.lineItems?.length}`;
148
110
  }
149
111
  }
150
112
  async function addToWhislist() {
@@ -211,9 +173,6 @@ const isMax = computed(() => {
211
173
  return false;
212
174
  return quantity.value > props.maxQuantity;
213
175
  });
214
- // const disabledSelect = computed(() => {
215
- // return !variantStock.item || !selected || loadingAdd;
216
- // });
217
176
  </script>
218
177
 
219
178
  <template>
@@ -228,7 +187,6 @@ const isMax = computed(() => {
228
187
  </div>
229
188
  </div>
230
189
  <teleport v-if="teleports.price" to="#price">
231
- <!-- {{ selected?. }} -->
232
190
  {{ thePrice }}
233
191
  </teleport>
234
192
  <div v-if="!product.noVariants" class="mb-2 space-y-1">
@@ -257,40 +215,29 @@ const isMax = computed(() => {
257
215
  </div>
258
216
  </div>
259
217
  <div class=" space-y-3">
260
- <!-- <el-input-number
261
- v-model="quantity"
262
- :min="1"
263
- :max="8"
264
- size="medium"
265
- class="w-32"
266
- /> -->
267
218
  <div class="p-1px">
268
219
  <AddProductNumber v-model="quantity" :min="1" :max="variantStock.itemStock" size="large" class="w-[8rem]" />
269
220
  </div>
270
221
  <UButton
271
-
272
- :disabled="!variantStock.item || !selected || loadingAdd || isMax"
273
- :loading="loadingAdd"
222
+ :disabled="!variantStock.item || !selected || cartStore.loadingAdd || isMax"
223
+ :loading="cartStore.loadingAdd"
274
224
  icon="i-bytesize-cart"
275
225
  size="xl"
276
226
  block
277
227
  @click="addToCart"
278
228
  >
279
- <!-- <i-bytesize-cart class="relative -left-3 text-xl dark:text-white" /> -->
280
229
  <span class="text-white font-medium uppercase "> {{ !variantStock.item ? 'Sin existencias' : 'Agregar al carrito' }} </span>
281
230
  </UButton>
282
231
  <div v-if="!settings.hideWhistlist">
283
232
  <UButton
284
- :disabled=" !selected || loadingAdd || loadingWhislist "
233
+ :disabled=" !selected || cartStore.loadingAdd || loadingWhislist "
285
234
  :loading="loadingWhislist"
286
235
  icon="i-mdi-heart-outline"
287
236
  size="lg"
288
237
  variant="subtle"
289
238
  @click="addToWhislist"
290
239
  >
291
- <!-- <i-mdi-heart-outline class="relative -left-3 text-xl" /> -->
292
240
  <span class=" font-medium uppercase"> Añadir a deseos
293
- <!-- {{ state.isAuth }} -->
294
241
  </span>
295
242
  </UButton>
296
243
  </div>
@@ -299,5 +246,42 @@ const isMax = computed(() => {
299
246
  {{ messageMax }}
300
247
  </div>
301
248
  <slot :id="id" :quantity="quantity" :sku="sku" />
249
+
250
+ <UModal v-model:open="alertModal.isOpen">
251
+ <template #content>
252
+ <div class="p-6 flex flex-col items-center text-center">
253
+ <div class="relative flex items-center justify-center mb-8 mt-4">
254
+ <!-- Anillos pulsantes en color Rojo/Rosa -->
255
+ <div class="absolute inset-0 rounded-full bg-rose-500/20 animate-ping" style="animation-duration: 2.5s;" />
256
+ <div class="absolute inset-[-1.5rem] rounded-full bg-rose-500/10 animate-pulse" style="animation-duration: 3s;" />
257
+
258
+ <!-- Icono central -->
259
+ <div class="relative z-10 w-24 h-24 bg-gradient-to-br from-rose-400 to-rose-600 rounded-full flex items-center justify-center shadow-lg shadow-rose-500/30">
260
+ <i-mdi-close-circle class="text-white text-5xl" />
261
+ </div>
262
+ </div>
263
+
264
+ <span class="text-xs font-bold px-4 py-1.5 bg-rose-50 text-rose-600 border border-rose-100 rounded-full uppercase tracking-wider mb-3">
265
+ Aviso
266
+ </span>
267
+
268
+ <h2 class="text-2xl font-bold text-gray-800 tracking-tight mb-2">
269
+ {{ alertModal.title }}
270
+ </h2>
271
+ <p class="text-sm text-gray-500 max-w-sm mx-auto mb-6 leading-relaxed">
272
+ {{ alertModal.description }}
273
+ </p>
274
+
275
+ <div class="pt-4 w-full">
276
+ <button
277
+ class="w-full bg-gradient-to-r from-slate-800 to-slate-900 hover:from-slate-900 hover:to-slate-950 text-white font-bold px-8 py-3.5 rounded-xl uppercase tracking-wider text-xs shadow-md hover:shadow-lg transition-all duration-300 transform hover:-translate-y-0.5 active:translate-y-0"
278
+ @click="alertModal.isOpen = false"
279
+ >
280
+ Cerrar
281
+ </button>
282
+ </div>
283
+ </div>
284
+ </template>
285
+ </UModal>
302
286
  </div>
303
287
  </template>
File without changes
@@ -3,9 +3,12 @@ import { ofetch } from 'ofetch';
3
3
  import { createPinia, defineStore } from 'pinia';
4
4
  import { type App, computed, ref } from 'vue';
5
5
 
6
+ if (typeof window !== 'undefined' && !(window as any)?.sharedPinia) {
7
+ (window as any).sharedPinia = createPinia();
8
+ }
6
9
  export function registerPinia(app: App) {
7
- if (!(window as any)?.sharedPinia) {
8
- (window as any).sharedPinia = createPinia();
10
+ if (typeof window === 'undefined') {
11
+ return;
9
12
  }
10
13
  app.use((window as any).sharedPinia);
11
14
  }
@@ -15,8 +18,26 @@ export const useCartStore = defineStore('cart', () => {
15
18
  return r.lineItems as any[];
16
19
  }, [] as any[]);
17
20
 
21
+ interface ProductAdd {
22
+
23
+ id: any
24
+ quantity: number
25
+ verifyStock?: boolean
26
+ selectedOptions?: any
27
+
28
+ }
18
29
  const { executeImmediate: addToCart, isLoading: loadingAdd } = useAsyncState(
19
- async (body: { id: any, quantity: number }) => {
30
+ async (body: ProductAdd) => {
31
+ if (body.verifyStock) {
32
+ const stock = await ofetch(`/storefront/cache/products/${encodeURIComponent(`${body.id}`)}/verify?selectedOptions=${JSON.stringify(body.selectedOptions)}`, {
33
+ });
34
+
35
+ if (!stock.ok) {
36
+ return {
37
+ error: 'stock',
38
+ };
39
+ }
40
+ }
20
41
  const r = await ofetch('/storefront/cart', {
21
42
  method: 'POST',
22
43
  body,
@@ -33,16 +54,17 @@ export const useCartStore = defineStore('cart', () => {
33
54
  const total = computed(() => {
34
55
  return items.value.reduce((acc: number, item: any) => acc + (item.variant?.price * item.quantity), 0).toFixed(2);
35
56
  });
36
- const drawer = ref(false);
57
+ const open = ref(false);
37
58
  const loading = computed(() => {
38
59
  return loadingInit.value || loadingAdd.value;
39
60
  });
40
61
  return {
41
62
  addToCart,
42
63
  items,
43
- drawer,
64
+ open,
44
65
  total,
45
66
  loading,
67
+ loadingAdd,
46
68
  };
47
69
  });
48
70