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
92 lines
3.3 KiB
JavaScript
92 lines
3.3 KiB
JavaScript
import './assets/main.css'
|
||
import { createApp } from 'vue'
|
||
import { createPinia } from 'pinia'
|
||
import App from './App.vue'
|
||
import router from './router'
|
||
import {useSettingsStore} from "@/stores/settings.js";
|
||
import PrimeVue from 'primevue/config';
|
||
import Aura from '@primeuix/themes/aura';
|
||
import ToastService from 'primevue/toastservice';
|
||
import {definePreset} from "@primeuix/themes";
|
||
import Tooltip from 'primevue/tooltip';
|
||
import ConfirmationService from 'primevue/confirmationservice';
|
||
import { plugin, defaultConfig } from '@formkit/vue';
|
||
import { ru } from '@formkit/i18n';
|
||
import config from './formkit.config.js'
|
||
|
||
const MyPreset = definePreset(Aura, {
|
||
|
||
});
|
||
|
||
function onReady(fn) {
|
||
if (document.readyState === 'loading') {
|
||
document.addEventListener('DOMContentLoaded', fn);
|
||
} else {
|
||
fn();
|
||
}
|
||
}
|
||
|
||
onReady(async () => {
|
||
const app = createApp(App);
|
||
app.use(createPinia());
|
||
app.use(router);
|
||
app.use(PrimeVue, {
|
||
theme: {
|
||
preset: MyPreset,
|
||
options: {
|
||
cssLayer: false, // если используешь Tailwind, отключает layering
|
||
},
|
||
},
|
||
locale: {
|
||
startsWith: 'Начинается с',
|
||
contains: 'Содержит',
|
||
notContains: 'Не содержит',
|
||
endsWith: 'Заканчивается на',
|
||
equals: 'Равно',
|
||
notEquals: 'Не равно',
|
||
noFilter: 'Без фильтра',
|
||
lt: 'Меньше чем',
|
||
lte: 'Меньше или равно',
|
||
gt: 'Больше чем',
|
||
gte: 'Больше или равно',
|
||
dateIs: 'Дата равна',
|
||
dateIsNot: 'Дата не равна',
|
||
dateBefore: 'Дата до',
|
||
dateAfter: 'Дата после',
|
||
clear: 'Очистить',
|
||
apply: 'Применить',
|
||
matchAll: 'Совпадает со всеми',
|
||
matchAny: 'Совпадает с любым',
|
||
addRule: 'Добавить правило',
|
||
removeRule: 'Удалить правило',
|
||
accept: 'Да',
|
||
reject: 'Нет',
|
||
choose: 'Выбрать',
|
||
upload: 'Загрузить',
|
||
cancel: 'Отмена',
|
||
dayNames: ['Воскресенье', 'Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота'],
|
||
dayNamesShort: ['Вс', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб'],
|
||
dayNamesMin: ['Вс', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб'],
|
||
monthNames: ['Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'],
|
||
monthNamesShort: ['Янв', 'Фев', 'Мар', 'Апр', 'Май', 'Июн', 'Июл', 'Авг', 'Сен', 'Окт', 'Ноя', 'Дек'],
|
||
today: 'Сегодня',
|
||
weekHeader: 'Неделя',
|
||
firstDayOfWeek: 1,
|
||
dateFormat: 'dd.mm.yy',
|
||
weak: 'Слабый',
|
||
medium: 'Средний',
|
||
strong: 'Сильный',
|
||
passwordPrompt: 'Введите пароль',
|
||
emptyMessage: 'Нет доступных записей',
|
||
emptyFilterMessage: 'Нет доступных записей'
|
||
}
|
||
});
|
||
app.use(ToastService);
|
||
app.directive('tooltip', Tooltip);
|
||
app.use(ConfirmationService);
|
||
app.use(plugin, defaultConfig(config));
|
||
|
||
app.mount('#app');
|
||
await useSettingsStore().fetchSettings();
|
||
});
|