Merge pull request #18 from BEDOLAGA-DEV/dev

Dev
This commit is contained in:
Egor
2026-01-18 07:08:17 +03:00
committed by GitHub
3 changed files with 39 additions and 7 deletions

View File

@@ -727,7 +727,8 @@
"checkIntervalDesc": "How often to check for overdue tickets (30-600 seconds)", "checkIntervalDesc": "How often to check for overdue tickets (30-600 seconds)",
"reminderCooldown": "Reminder interval (minutes)", "reminderCooldown": "Reminder interval (minutes)",
"reminderCooldownDesc": "Minimum time between reminders (1-120 minutes)", "reminderCooldownDesc": "Minimum time between reminders (1-120 minutes)",
"settingsUpdateError": "Error saving settings" "settingsUpdateError": "Error saving settings",
"copyTelegramId": "Click to copy Telegram ID"
}, },
"tariffs": { "tariffs": {
"title": "Tariff Management", "title": "Tariff Management",

View File

@@ -727,7 +727,8 @@
"checkIntervalDesc": "Как часто проверять просроченные тикеты (30-600 секунд)", "checkIntervalDesc": "Как часто проверять просроченные тикеты (30-600 секунд)",
"reminderCooldown": "Интервал напоминаний (минуты)", "reminderCooldown": "Интервал напоминаний (минуты)",
"reminderCooldownDesc": "Минимальное время между напоминаниями (1-120 минут)", "reminderCooldownDesc": "Минимальное время между напоминаниями (1-120 минут)",
"settingsUpdateError": "Ошибка сохранения настроек" "settingsUpdateError": "Ошибка сохранения настроек",
"copyTelegramId": "Нажмите чтобы скопировать Telegram ID"
}, },
"tariffs": { "tariffs": {
"title": "Управление тарифами", "title": "Управление тарифами",

View File

@@ -155,10 +155,21 @@ export default function AdminTickets() {
const formatUser = (ticket: AdminTicket | AdminTicketDetail) => { const formatUser = (ticket: AdminTicket | AdminTicketDetail) => {
if (!ticket.user) return 'Unknown' if (!ticket.user) return 'Unknown'
const { first_name, last_name, username, telegram_id } = ticket.user const { first_name, last_name, username } = ticket.user
if (first_name || last_name) return `${first_name || ''} ${last_name || ''}`.trim() if (first_name || last_name) return `${first_name || ''} ${last_name || ''}`.trim()
if (username) return `@${username}` if (username) return `@${username}`
return `ID: ${telegram_id}` return 'User'
}
const copyToClipboard = (text: string) => {
navigator.clipboard.writeText(text).catch(() => {
const textarea = document.createElement('textarea')
textarea.value = text
document.body.appendChild(textarea)
textarea.select()
document.execCommand('copy')
document.body.removeChild(textarea)
})
} }
return ( return (
@@ -248,7 +259,17 @@ export default function AdminTickets() {
</span> </span>
</div> </div>
<div className="text-xs text-dark-500"> <div className="text-xs text-dark-500">
{formatUser(ticket)} | {new Date(ticket.updated_at).toLocaleDateString()} {formatUser(ticket)}
{ticket.user?.telegram_id && (
<button
onClick={(e) => { e.stopPropagation(); copyToClipboard(String(ticket.user!.telegram_id)) }}
className="ml-1 text-dark-600 hover:text-accent-400 transition-colors"
title={t('admin.tickets.copyTelegramId')}
>
(TG: {ticket.user!.telegram_id})
</button>
)}
{' '}| {new Date(ticket.updated_at).toLocaleDateString()}
</div> </div>
{ticket.last_message && ( {ticket.last_message && (
<div className="text-xs text-dark-600 mt-1 truncate"> <div className="text-xs text-dark-600 mt-1 truncate">
@@ -315,8 +336,17 @@ export default function AdminTickets() {
</div> </div>
</div> </div>
<div className="text-sm text-dark-500 mb-4"> <div className="text-sm text-dark-500 mb-4">
{t('admin.tickets.from')}: {formatUser(selectedTicket)} |{' '} {t('admin.tickets.from')}: {formatUser(selectedTicket)}
{t('admin.tickets.created')}: {new Date(selectedTicket.created_at).toLocaleString()} {selectedTicket.user?.telegram_id && (
<button
onClick={() => copyToClipboard(String(selectedTicket.user!.telegram_id))}
className="ml-1 px-2 py-0.5 text-xs bg-dark-700 hover:bg-dark-600 rounded transition-colors"
title={t('admin.tickets.copyTelegramId')}
>
TG: {selectedTicket.user!.telegram_id}
</button>
)}
{' '}| {t('admin.tickets.created')}: {new Date(selectedTicket.created_at).toLocaleString()}
</div> </div>
<div className="flex flex-wrap gap-2"> <div className="flex flex-wrap gap-2">
{['open', 'pending', 'answered', 'closed'].map((s) => ( {['open', 'pending', 'answered', 'closed'].map((s) => (