Implement comprehensive Telegram customers storage and management functionality: Backend: - Add database migration for telecart_customers table with indexes - Create TelegramCustomer model with CRUD operations - Implement TelegramCustomerService for business logic - Add TelegramCustomerHandler for API endpoint (saveOrUpdate) - Add TelegramCustomersHandler for admin API (getCustomers with pagination, filtering, sorting) - Add SendMessageHandler for sending messages to customers via Telegram - Create custom exceptions: TelegramCustomerNotFoundException, TelegramCustomerWriteNotAllowedException - Refactor TelegramInitDataDecoder to separate decoding logic - Add TelegramHeader enum for header constants - Update SignatureValidator to use TelegramInitDataDecoder - Register new routes in bastion/routes.php and src/routes.php Frontend (Admin): - Add CustomersView.vue component with PrimeVue DataTable - Implement advanced filtering (text, date, boolean filters) - Add column visibility toggle functionality - Add global search with debounce - Implement message sending dialog with validation - Add Russian locale for PrimeVue components - Add navigation link in App.vue - Register route in router Frontend (SPA): - Add saveTelegramCustomer utility function - Integrate automatic customer data saving on app initialization - Extract user data from Telegram.WebApp.initDataUnsafe The system automatically saves/updates customer data when users access the Telegram Mini App, and provides admin interface for viewing, filtering, and messaging customers. BREAKING CHANGE: None
111 lines
2.9 KiB
JavaScript
111 lines
2.9 KiB
JavaScript
import {ofetch} from "ofetch";
|
|
|
|
const BASE_URL = '/';
|
|
|
|
function encodeBase64Unicode(str) {
|
|
return btoa(new TextEncoder().encode(str).reduce((data, byte) => data + String.fromCharCode(byte), ''));
|
|
}
|
|
|
|
export const apiFetch = ofetch.create({
|
|
throwHttpErrors: true,
|
|
onRequest({request, options}) {
|
|
const data = window.Telegram?.WebApp?.initData;
|
|
|
|
if (data) {
|
|
const encoded = encodeBase64Unicode(data);
|
|
options.headers = {
|
|
...options.headers,
|
|
'X-Telegram-InitData': encoded,
|
|
};
|
|
}
|
|
},
|
|
});
|
|
|
|
async function ftch(action, query = null, json = null) {
|
|
const options = {
|
|
method: json ? 'POST' : 'GET',
|
|
};
|
|
if (query) options.query = query;
|
|
if (json) options.body = json;
|
|
|
|
return await apiFetch(`${BASE_URL}index.php?route=extension/tgshop/handle&api_action=${action}`, options);
|
|
}
|
|
|
|
export async function storeOrder(data) {
|
|
return await apiFetch(`${BASE_URL}index.php?route=extension/tgshop/handle&api_action=storeOrder`, {
|
|
method: 'POST',
|
|
body: data,
|
|
});
|
|
}
|
|
|
|
export async function getCart() {
|
|
return await ftch('getCart');
|
|
}
|
|
|
|
export async function addToCart(data) {
|
|
return await apiFetch(`${BASE_URL}index.php?route=checkout/cart/add`, {
|
|
method: 'POST',
|
|
body: data,
|
|
});
|
|
}
|
|
|
|
export async function cartRemoveItem(data) {
|
|
return await apiFetch(`${BASE_URL}index.php?route=checkout/cart/remove`, {
|
|
method: 'POST',
|
|
body: data,
|
|
});
|
|
}
|
|
|
|
export async function cartEditItem(data) {
|
|
return await apiFetch(`${BASE_URL}index.php?route=checkout/cart/edit`, {
|
|
redirect: 'manual',
|
|
method: 'POST',
|
|
body: data,
|
|
});
|
|
}
|
|
|
|
export async function fetchSettings() {
|
|
return await ftch('settings');
|
|
}
|
|
|
|
export async function getFiltersForMainPage() {
|
|
return await ftch('filtersForMainPage');
|
|
}
|
|
|
|
export async function setCoupon(coupon) {
|
|
const formData = new FormData();
|
|
formData.append('coupon', coupon);
|
|
|
|
return await apiFetch(`${BASE_URL}index.php?route=extension/total/coupon/coupon`, {
|
|
method: 'POST',
|
|
body: formData,
|
|
});
|
|
}
|
|
|
|
export async function setVoucher(voucher) {
|
|
const formData = new FormData();
|
|
formData.append('voucher', voucher);
|
|
|
|
return await apiFetch(`${BASE_URL}index.php?route=extension/total/voucher/voucher`, {
|
|
method: 'POST',
|
|
body: formData,
|
|
});
|
|
}
|
|
|
|
export async function processBlock(block) {
|
|
return await ftch('processBlock', null, block);
|
|
}
|
|
|
|
/**
|
|
* Сохранить или обновить данные Telegram-пользователя
|
|
* @param {Object} userData - Данные пользователя из Telegram.WebApp.initDataUnsafe.user
|
|
* @returns {Promise}
|
|
*/
|
|
export async function saveTelegramCustomer(userData) {
|
|
return await ftch('saveTelegramCustomer', null, {
|
|
user: userData,
|
|
});
|
|
}
|
|
|
|
export default ftch;
|