@monkeyplus/payscope 1.0.2 → 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.
@@ -0,0 +1,93 @@
1
+ <script setup lang="ts">
2
+ import { reactive, ref } from 'vue';
3
+
4
+ const props = defineProps<{
5
+ step: number;
6
+ isActive: boolean;
7
+ }>();
8
+
9
+ const emit = defineEmits(['next', 'edit']);
10
+
11
+ const form = reactive({
12
+ street: '',
13
+ city: '',
14
+ zip: '',
15
+ state: '',
16
+ country: 'México',
17
+ reference: ''
18
+ });
19
+
20
+ const isComplete = ref(false);
21
+
22
+ function submit() {
23
+ if (form.street && form.city && form.zip) {
24
+ isComplete.value = true;
25
+ emit('next');
26
+ }
27
+ }
28
+ </script>
29
+
30
+ <template>
31
+ <div class="bg-white p-6 rounded-xl border shadow-sm transition-colors duration-300" :class="isActive ? 'border-primary' : 'border-gray-100'">
32
+ <div class="flex items-center justify-between mb-2">
33
+ <div class="flex items-center space-x-3">
34
+ <div class="w-8 h-8 rounded-full flex items-center justify-center font-bold text-sm transition-colors" :class="isActive ? 'bg-primary text-white' : (isComplete ? 'bg-green-500 text-white' : 'bg-slate-100 text-slate-600')">
35
+ <i-mdi-check v-if="!isActive && isComplete" class="text-lg" />
36
+ <span v-else>{{ step }}</span>
37
+ </div>
38
+ <h3 class="text-xl font-bold text-gray-800">
39
+ Dirección de Envío
40
+ </h3>
41
+ </div>
42
+ <UButton v-if="!isActive && isComplete" variant="ghost" color="gray" icon="i-heroicons-pencil-square" size="sm" @click="$emit('edit')">Editar</UButton>
43
+ </div>
44
+
45
+ <div class="pl-11 pt-2 transition-all">
46
+ <div v-if="isActive" class="animate-fade-in">
47
+ <form @submit.prevent="submit" class="space-y-4">
48
+ <UFormField label="Calle y Número" required>
49
+ <UInput v-model="form.street" placeholder="Ej. Av. Principal 123" />
50
+ </UFormField>
51
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
52
+ <UFormField label="Ciudad" required>
53
+ <UInput v-model="form.city" placeholder="Ciudad" />
54
+ </UFormField>
55
+ <UFormField label="Estado / Provincia" required>
56
+ <UInput v-model="form.state" placeholder="Estado" />
57
+ </UFormField>
58
+ </div>
59
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
60
+ <UFormField label="Código Postal" required>
61
+ <UInput v-model="form.zip" placeholder="12345" />
62
+ </UFormField>
63
+ <UFormField label="País">
64
+ <UInput v-model="form.country" placeholder="País" />
65
+ </UFormField>
66
+ </div>
67
+ <UFormField label="Referencia (Opcional)">
68
+ <UInput v-model="form.reference" placeholder="Ej. Casa de dos pisos con reja blanca" />
69
+ </UFormField>
70
+
71
+ <div class="pt-4 flex justify-end">
72
+ <UButton type="submit" size="lg">Guardar y Continuar</UButton>
73
+ </div>
74
+ </form>
75
+ </div>
76
+ <div v-else-if="isComplete" class="text-sm text-gray-600 space-y-1 animate-fade-in">
77
+ <p class="font-medium text-gray-900">{{ form.street }}</p>
78
+ <p>{{ form.city }}, {{ form.state }}, {{ form.zip }}</p>
79
+ <p>{{ form.country }}</p>
80
+ </div>
81
+ </div>
82
+ </div>
83
+ </template>
84
+
85
+ <style scoped>
86
+ .animate-fade-in {
87
+ animation: fadeIn 0.3s ease-in-out;
88
+ }
89
+ @keyframes fadeIn {
90
+ from { opacity: 0; transform: translateY(-5px); }
91
+ to { opacity: 1; transform: translateY(0); }
92
+ }
93
+ </style>
@@ -0,0 +1,63 @@
1
+ <script setup lang="ts">
2
+ import { useCheckoutStore } from '../../../stores.ts';
3
+
4
+ const checkout = useCheckoutStore();
5
+ </script>
6
+
7
+ <template>
8
+ <div class="bg-gray-50 p-6 rounded-xl border border-gray-100 shadow-sm">
9
+ <h3 class="text-xl font-bold mb-4 text-gray-800">
10
+ Resumen de tu pedido
11
+ </h3>
12
+ <div class="space-y-4 mb-6">
13
+ <div v-for="item in checkout.items" :key="item.id" class="flex gap-4">
14
+ <div class="w-16 h-16 rounded-md overflow-hidden bg-white border border-gray-200 flex-shrink-0">
15
+ <img v-if="item.image" :src="item.image" class="w-full h-full object-cover">
16
+ <div v-else class="w-full h-full flex items-center justify-center text-gray-400">
17
+ <i-mdi-image-outline class="text-2xl" />
18
+ </div>
19
+ </div>
20
+ <div class="flex-1 flex justify-between">
21
+ <div>
22
+ <div class="font-medium text-gray-800 text-sm leading-tight">
23
+ {{ item.title }}
24
+ </div>
25
+ <div v-if="item.subtitle" class="text-xs text-gray-500 mt-1">
26
+ {{ item.subtitle }}
27
+ </div>
28
+ <div class="text-xs text-gray-400 mt-1">
29
+ Cant: {{ item.quantity }}
30
+ </div>
31
+ </div>
32
+ <div class="font-bold text-gray-800 text-sm">
33
+ ${{ item.total }}
34
+ </div>
35
+ </div>
36
+ </div>
37
+ </div>
38
+ <hr class="border-gray-200 mb-4">
39
+ <div class="space-y-2 text-sm">
40
+ <div class="flex justify-between">
41
+ <span class="text-gray-500">Subtotal</span>
42
+ <span class="font-medium">${{ checkout.totals.subtotal }}</span>
43
+ </div>
44
+ <div v-if="Number(checkout.totals.discount) > 0" class="flex justify-between">
45
+ <span class="text-gray-500">Descuentos</span>
46
+ <span class="font-medium text-emerald-600">-${{ checkout.totals.discount }}</span>
47
+ </div>
48
+ <div class="flex justify-between">
49
+ <span class="text-gray-500">Impuestos</span>
50
+ <span class="font-medium">${{ checkout.totals.totalTax }}</span>
51
+ </div>
52
+ <div class="flex justify-between">
53
+ <span class="text-gray-500">Envío</span>
54
+ <span class="font-medium">${{ checkout.totals.shipping }}</span>
55
+ </div>
56
+ </div>
57
+ <hr class="border-gray-200 my-4">
58
+ <div class="flex justify-between items-center text-lg font-bold">
59
+ <span class="text-gray-800">Total</span>
60
+ <span class="text-gray-900">${{ checkout.totals.total }}</span>
61
+ </div>
62
+ </div>
63
+ </template>
@@ -0,0 +1,82 @@
1
+ <script setup lang="ts">
2
+ import { computed, ref } from 'vue';
3
+ import { useCheckoutStore } from '../../stores.ts';
4
+ import BasicBillingForm from './Basic/BasicBillingForm.vue';
5
+ import BasicCustomerForm from './Basic/BasicCustomerForm.vue';
6
+ import BasicShippingForm from './Basic/BasicShippingForm.vue';
7
+ import BasicSummary from './Basic/BasicSummary.vue';
8
+ import PaymentForms from './Pay/PayForms.vue';
9
+
10
+ const checkout = useCheckoutStore();
11
+
12
+ const activeStep = ref(1);
13
+
14
+ const requiresShipping = computed(() => {
15
+ if (!checkout.checkout?.lineItems?.length)
16
+ return false;
17
+ return true;
18
+ });
19
+
20
+ // Dinamical step calculation
21
+ const customerStep = 1;
22
+ const shippingStep = computed(() => requiresShipping.value ? 2 : -1);
23
+ const billingStep = computed(() => requiresShipping.value ? 3 : 2);
24
+ const paymentStep = computed(() => requiresShipping.value ? 4 : 3);
25
+ </script>
26
+
27
+ <template>
28
+ <div class="max-w-7xl mx-auto mt-6 px-4 pb-12">
29
+ <!-- Header -->
30
+ <div class="mb-8 border-b border-gray-100 pb-4">
31
+ <h1 class="text-3xl font-extrabold text-gray-900 tracking-tight">
32
+ Checkout
33
+ </h1>
34
+ <p class="text-gray-500 mt-1">
35
+ Completa tu información para finalizar la compra
36
+ </p>
37
+ </div>
38
+
39
+ <!-- Left Column: Forms Flow -->
40
+ <div class="lg:col-span-7 xl:col-span-8 space-y-6">
41
+ <!-- Paso 1: Info de Contacto -->
42
+ <BasicCustomerForm
43
+ :step="customerStep"
44
+ :is-active="activeStep === customerStep"
45
+ @next="activeStep = shippingStep !== -1 ? shippingStep : billingStep"
46
+ @edit="activeStep = customerStep"
47
+ />
48
+
49
+ <!-- Paso 2: Envío (Condicional) -->
50
+ <BasicShippingForm
51
+ v-if="requiresShipping"
52
+ :step="shippingStep"
53
+ :is-active="activeStep === shippingStep"
54
+ @next="activeStep = billingStep"
55
+ @edit="activeStep = shippingStep"
56
+ />
57
+
58
+ <!-- Paso 3: Facturación -->
59
+ <BasicBillingForm
60
+ :step="billingStep"
61
+ :is-active="activeStep === billingStep"
62
+ @next="activeStep = paymentStep"
63
+ @edit="activeStep = billingStep"
64
+ />
65
+
66
+ <!-- Paso 4: Pago -->
67
+ <div class="bg-white p-6 rounded-xl border border-gray-100 shadow-sm transition-opacity duration-300" :class="{ 'opacity-50 pointer-events-none': activeStep !== paymentStep }">
68
+ <div class="flex items-center space-x-3 mb-2">
69
+ <div class="w-8 h-8 rounded-full flex items-center justify-center font-bold text-sm transition-colors duration-300" :class="activeStep === paymentStep ? 'bg-primary text-white' : 'bg-slate-100 text-slate-600'">
70
+ {{ paymentStep }}
71
+ </div>
72
+ <h3 class="text-xl font-bold text-gray-800">
73
+ Método de Pago
74
+ </h3>
75
+ </div>
76
+ <div v-if="activeStep === paymentStep" class="pl-11">
77
+ <PaymentForms />
78
+ </div>
79
+ </div>
80
+ </div>
81
+ </div>
82
+ </template>
@@ -1,10 +1,9 @@
1
1
  <script setup lang="ts">
2
- import type { TabsItem } from '@nuxt/ui';
3
2
  import { computed, ref, watch } from 'vue';
4
- import { useRoute, useRouter } from 'vue-router';
5
3
  import { useAccountStore, useCheckoutStore } from '../../../stores.ts';
6
4
  import { useNavigation } from '../../composables.ts';
7
5
  import StepInfo from '../StepInfo.vue';
6
+ import PayForms from './PayForms.vue';
8
7
 
9
8
  const account = useAccountStore();
10
9
  const checkout = useCheckoutStore();
@@ -31,45 +30,6 @@ watch(select, (v) => {
31
30
  const _a = account.billings.find((a: any) => a.id === v);
32
31
  checkout.setBilling(_a);
33
32
  });
34
- const tabs = ref<TabsItem[]>([
35
- {
36
- label: 'Paypal',
37
- value: 'paypal',
38
- },
39
- {
40
- label: 'Placetopay',
41
- value: 'placetopay',
42
- },
43
- {
44
- label: 'Pagomedios',
45
- value: 'placetopay',
46
-
47
- },
48
- {
49
- label: 'Datafast',
50
- value: 'placetopay',
51
-
52
- },
53
- {
54
- label: 'Cybersource',
55
- value: 'placetopay',
56
-
57
- },
58
- ]);
59
- const route = useRoute();
60
- const router = useRouter();
61
-
62
- const tabPay = computed({
63
- get() {
64
- return (route.name as string) || 'me';
65
- },
66
- set(tab) {
67
- // Hash is specified here to prevent the page from scrolling to the top
68
- router.push({
69
- name: tab,
70
- });
71
- },
72
- });
73
33
  </script>
74
34
 
75
35
  <template>
@@ -90,15 +50,8 @@ const tabPay = computed({
90
50
  :items="items"
91
51
  />
92
52
  </div>
93
- <div class="text-2xl font-bold leading-0 pt-3">
94
- Formas de pago
95
- </div>
96
- <div>
97
- <UTabs v-model="tabPay" variant="pill" :content="false" :items="tabs" class="w-full" />
98
- </div>
99
- <div>
100
- <router-view />
101
- </div>
53
+ <PayForms />
54
+
102
55
  <div class="flex items-center pt-4">
103
56
  <!-- -->
104
57
  <div class="flex-auto" />
@@ -0,0 +1,55 @@
1
+ <script setup lang="ts">
2
+ import type { TabsItem } from '@nuxt/ui';
3
+ import { useRoute, useRouter } from 'vue-router';
4
+
5
+ const route = useRoute();
6
+ const router = useRouter();
7
+ const tabs = ref<TabsItem[]>([
8
+ {
9
+ label: 'Paypal',
10
+ value: 'paypal',
11
+ },
12
+ {
13
+ label: 'Placetopay',
14
+ value: 'placetopay',
15
+ },
16
+ {
17
+ label: 'Pagomedios',
18
+ value: 'placetopay',
19
+
20
+ },
21
+ {
22
+ label: 'Datafast',
23
+ value: 'placetopay',
24
+
25
+ },
26
+ {
27
+ label: 'Cybersource',
28
+ value: 'placetopay',
29
+
30
+ },
31
+ ]);
32
+ const tabPay = computed({
33
+ get() {
34
+ return (route.name as string) || 'me';
35
+ },
36
+ set(tab) {
37
+ // Hash is specified here to prevent the page from scrolling to the top
38
+ router.push({
39
+ name: tab,
40
+ });
41
+ },
42
+ });
43
+ </script>
44
+
45
+ <template>
46
+ <div class="text-2xl font-bold pt-3">
47
+ Formas de pago
48
+ </div>
49
+ <div>
50
+ <UTabs v-model="tabPay" variant="pill" :content="false" :items="tabs" class="w-full" />
51
+ </div>
52
+ <div>
53
+ <router-view />
54
+ </div>
55
+ </template>
@@ -1,6 +1,6 @@
1
1
  <script lang="ts" setup>
2
2
  import { onBeforeMount } from 'vue';
3
- import { useState } from './composable';
3
+ import { useState } from './composable.ts';
4
4
  import PaymentStatus from './PaymentStatus.vue';
5
5
 
6
6
  const { getState, status, response, uid, provider } = useState();
@@ -1,59 +1,69 @@
1
1
  import { createRouter, createWebHistory } from 'vue-router';
2
2
 
3
3
  console.log('createCheckout');
4
+ const payMethods = [
5
+ {
6
+ path: 'paypal',
7
+ component: () => import('./pages/Pay/Providers/Paypal/Paypal.vue'),
8
+ name: 'paypal',
9
+ },
10
+ {
11
+ path: 'placetopay',
12
+ component: () => import('./pages/Pay/Providers/Placetopay/Placetopay.vue'),
13
+ name: 'placetopay',
14
+ },
15
+ {
16
+ path: 'pagomedios',
17
+ component: () => import('./pages/Pay/Providers/Pagomedios/Pagomedios.vue'),
18
+ name: 'pagomedios',
19
+ },
20
+ {
21
+ path: 'datafast',
22
+ component: () => import('./pages/Pay/Providers/Datafast/Datafast.vue'),
23
+ name: 'datafast',
24
+ },
25
+ {
26
+ path: 'cybersource',
27
+ component: () => import('./pages/Pay/Providers/Cybersource/Cybersource.vue'),
28
+ name: 'cybersource',
29
+ },
30
+ ];
4
31
  export const router = createRouter({
5
32
  history: createWebHistory('/checkout'),
6
33
  routes: [
7
34
  {
8
- path: '/',
9
- redirect: '/address',
10
- },
11
- {
12
- path: '/address',
13
- name: 'address',
14
- component: () => import('./pages/Address/Address.vue'),
15
- },
16
- {
17
- path: '/shipping',
18
- name: 'shipping',
19
- component: () => import('./pages/Shipping/Shipping.vue'),
20
- },
21
- {
22
- path: '/payment',
23
- name: 'payment',
24
- component: () => import('./pages/Payment/Payment.vue'),
25
- },
26
- {
27
- path: '/pay',
28
- component: () => import('./pages/Pay/Pay.vue'),
29
- name: 'pay',
35
+ path: '/auth',
36
+ // redirect: '/address',
37
+ component: () => import('./pages/Auth.vue'),
30
38
  children: [
31
39
  {
32
- path: 'paypal',
33
- component: () => import('./pages/Pay/Providers/Paypal/Paypal.vue'),
34
- name: 'paypal',
35
- },
36
- {
37
- path: 'placetopay',
38
- component: () => import('./pages/Pay/Providers/Placetopay/Placetopay.vue'),
39
- name: 'placetopay',
40
+ path: 'address',
41
+ name: 'address',
42
+ component: () => import('./pages/Address/Address.vue'),
40
43
  },
41
44
  {
42
- path: 'pagomedios',
43
- component: () => import('./pages/Pay/Providers/Pagomedios/Pagomedios.vue'),
44
- name: 'pagomedios',
45
+ path: 'shipping',
46
+ name: 'shipping',
47
+ component: () => import('./pages/Shipping/Shipping.vue'),
45
48
  },
46
49
  {
47
- path: 'datafast',
48
- component: () => import('./pages/Pay/Providers/Datafast/Datafast.vue'),
49
- name: 'datafast',
50
+ path: 'payment',
51
+ name: 'payment',
52
+ component: () => import('./pages/Payment/Payment.vue'),
50
53
  },
51
54
  {
52
- path: 'cybersource',
53
- component: () => import('./pages/Pay/Providers/Cybersource/Cybersource.vue'),
54
- name: 'cybersource',
55
+ path: 'pay',
56
+ component: () => import('./pages/Pay/Pay.vue'),
57
+ name: 'pay',
58
+ children: payMethods,
55
59
  },
56
60
  ],
57
61
  },
62
+ {
63
+ path: '/basic',
64
+ component: () => import('./pages/Basic.vue'),
65
+ children: payMethods,
66
+ },
67
+
58
68
  ],
59
69
  });