Files
interview-demo-code/frontend/spa/src/utils/ftch.js
Nikita Kiselev 9a93cc7342 feat: add Telegram customers management system with admin panel
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
2025-11-23 21:30:51 +03:00

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;