Files
interview-demo-code/frontend/spa/src/stores/CheckoutStore.js
Nikita Kiselev 3cc82e45f0
Some checks are pending
Telegram Mini App Shop Builder / Compute version metadata (push) Waiting to run
Telegram Mini App Shop Builder / Run Frontend tests (push) Waiting to run
Telegram Mini App Shop Builder / Run Backend tests (push) Waiting to run
Telegram Mini App Shop Builder / Run PHP_CodeSniffer (push) Waiting to run
Telegram Mini App Shop Builder / Build module. (push) Blocked by required conditions
Telegram Mini App Shop Builder / release (push) Blocked by required conditions
Squashed commit message
2026-03-11 23:02:54 +03:00

158 lines
6.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import {defineStore} from "pinia";
import {isNotEmpty} from "@/helpers.js";
import {storeOrder} from "@/utils/ftch.js";
import {useCartStore} from "@/stores/CartStore.js";
import {YA_METRIKA_GOAL} from "@/constants/yaMetrikaGoals.js";
import {useYaMetrikaStore} from "@/stores/yaMetrikaStore.js";
import {useSettingsStore} from "@/stores/SettingsStore.js";
import {usePulseStore} from "@/stores/Pulse.js";
import {TC_PULSE_EVENTS} from "@/constants/tPulseEvents.js";
import {nextTick} from "vue";
/**
* Helper функция для получения haptic feedback (можно использовать в store)
* @returns {object} Объект с методами haptic feedback
*/
function getHapticFeedback() {
const settings = useSettingsStore();
const haptic = window.Telegram?.WebApp?.HapticFeedback;
// Возвращаем обёртку с методами, которые проверяют настройку при каждом вызове
return {
impactOccurred: (style) => {
const isHapticEnabled = settings.haptic_enabled !== false;
if (!haptic || !isHapticEnabled || !haptic.impactOccurred) {
return;
}
haptic.impactOccurred(style);
},
selectionChanged: () => {
const isHapticEnabled = settings.haptic_enabled !== false;
if (!haptic || !isHapticEnabled || !haptic.selectionChanged) {
return;
}
haptic.selectionChanged();
},
notificationOccurred: (type) => {
const isHapticEnabled = settings.haptic_enabled !== false;
if (!haptic || !isHapticEnabled || !haptic.notificationOccurred) {
return;
}
haptic.notificationOccurred(type);
},
};
}
export const useCheckoutStore = defineStore('checkout', {
state: () => ({
form: {},
order: null,
isLoading: false,
validationErrors: {},
errorMessage: '',
}),
getters: {
hasError: (state) => {
return (field) => isNotEmpty(state.validationErrors[field]);
},
},
actions: {
async makeOrder() {
try {
this.errorMessage = '';
this.isLoading = true;
const data = window.Telegram.WebApp.initDataUnsafe;
console.log("Allows write to PM: ", data.user.allows_write_to_pm);
if (!data.user.allows_write_to_pm) {
console.log("Sending request");
const granted = await new Promise(resolve => {
window.Telegram.WebApp.requestWriteAccess((granted) => {
resolve(granted);
});
});
if (granted) {
data.user.allows_write_to_pm = true;
console.log('Пользователь разрешил отправку сообщений');
} else {
alert('Вы не дали разрешение — бот не сможет отправлять вам уведомления');
}
}
const response = await storeOrder({
...this.form,
tgData: data,
});
this.order = response.data;
if (!this.order.id) {
console.debug(response.data);
throw new Error('Ошибка создания заказа.');
}
const yaMetrika = useYaMetrikaStore();
const pulse = usePulseStore();
await nextTick(() => {
pulse.ingest(TC_PULSE_EVENTS.ORDER_CREATED, {
order_id: this.order.id,
revenue: this.order?.final_total_numeric,
currency: this.order?.currency,
});
yaMetrika.reachGoal(YA_METRIKA_GOAL.ORDER_CREATED_SUCCESS, {
price: this.order?.final_total_numeric,
currency: this.order?.currency,
});
yaMetrika.dataLayerPush({
"ecommerce": {
"currencyCode": useSettingsStore().currency_code,
"purchase": {
"actionField": {
"id": this.order.id,
'revenue': this.order?.final_total_numeric,
},
"products": this.order.products ? this.order.products.map((product, index) => {
return {
id: product.product_id,
name: product.name,
price: product.total_numeric,
position: index,
quantity: product.quantity,
};
}) : [],
}
}
});
});
const haptic = getHapticFeedback();
await haptic.notificationOccurred('success');
await useCartStore().getProducts();
} catch (error) {
if (error.response?.status === 422) {
this.validationErrors = error.response._data.data;
} else {
console.error('Server error', error);
}
const haptic = getHapticFeedback();
haptic.notificationOccurred('error');
this.errorMessage = 'Возникла ошибка при создании заказа.';
throw error;
} finally {
this.isLoading = false;
}
},
clearError(field) {
this.validationErrors[field] = null;
},
},
});