Files
interview-demo-code/frontend/admin/src/assets/main.css
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

77 lines
1.6 KiB
CSS

@layer theme, base, components, utilities;
@import "tailwindcss/theme.css" layer(theme) prefix(tw);
@import "tailwindcss/utilities.css" layer(utilities) prefix(tw);
@layer components {
.tw\:d-toggle {
width: calc((var(--d-size) * 2) - (var(--border) + var(--d-toggle-p)) * 2) !important;
height: var(--d-size) !important;
border: var(--border) solid currentColor !important;
color: var(--d-input-color) !important;
border-radius: calc(var(--radius-selector) + min(var(--d-toggle-p), var(--radius-selector-max)) + min(var(--border), var(--radius-selector-max))) !important;
padding: var(--d-toggle-p) !important;
}
.tw\:d-toggle:after {
all: unset !important;
}
}
html {
font-size: 14px;
}
.p-toast .p-toast-message-success {
color: #3c763d;
background-color: #dff0d8;
border-color: #d6e9c6;
}
.p-toggleswitch > input[type="checkbox"] {
position: absolute;
width: 100%;
height: 100%;
border: none;
border-radius: unset;
margin: 0;
}
legend.p-fieldset-legend {
font-size: 14px;
line-height: inherit;
width: auto;
margin-bottom: 0;
}
.telecart-admin-app {
color: var(--color-slate-700);
}
.blueprint-bg {
background-color: #efefef;
opacity: 0.7;
background-image: radial-gradient(#989898 0.65px, #efefef 0.65px);
background-size: 13px 13px;
}
ul.formkit-options {
padding: 0;
margin-bottom: 0;
list-style: none;
}
ul.formkit-options label {
display: inline-flex;
}
ul.formkit-options input[type="radio"] {
position: absolute;
}
input.p-checkbox-input {
position: absolute;
}
label {
margin-bottom: 0;
}