Update Support.tsx

This commit is contained in:
Egor
2026-01-18 06:54:25 +03:00
committed by GitHub
parent 5eeb8aafa3
commit 705f0676e6

View File

@@ -4,6 +4,7 @@ import { useTranslation } from 'react-i18next'
import { ticketsApi } from '../api/tickets' import { ticketsApi } from '../api/tickets'
import { infoApi } from '../api/info' import { infoApi } from '../api/info'
import { logger } from '../utils/logger' import { logger } from '../utils/logger'
import { checkRateLimit, getRateLimitResetTime, RATE_LIMIT_KEYS } from '../utils/rateLimit'
import type { TicketDetail, TicketMessage } from '../types' import type { TicketDetail, TicketMessage } from '../types'
const log = logger.createLogger('Support') const log = logger.createLogger('Support')
@@ -132,6 +133,7 @@ export default function Support() {
const [newTitle, setNewTitle] = useState('') const [newTitle, setNewTitle] = useState('')
const [newMessage, setNewMessage] = useState('') const [newMessage, setNewMessage] = useState('')
const [replyMessage, setReplyMessage] = useState('') const [replyMessage, setReplyMessage] = useState('')
const [rateLimitError, setRateLimitError] = useState<string | null>(null)
// Media attachment states // Media attachment states
const [createAttachment, setCreateAttachment] = useState<MediaAttachment | null>(null) const [createAttachment, setCreateAttachment] = useState<MediaAttachment | null>(null)
@@ -507,6 +509,13 @@ export default function Support() {
<form <form
onSubmit={(e) => { onSubmit={(e) => {
e.preventDefault() e.preventDefault()
setRateLimitError(null)
// Rate limit: max 3 tickets per 60 seconds
if (!checkRateLimit(RATE_LIMIT_KEYS.TICKET_CREATE, 3, 60000)) {
const resetTime = getRateLimitResetTime(RATE_LIMIT_KEYS.TICKET_CREATE)
setRateLimitError(t('support.tooManyRequests', { seconds: resetTime }) || `Слишком много запросов. Подождите ${resetTime} сек.`)
return
}
createMutation.mutate() createMutation.mutate()
}} }}
className="space-y-4" className="space-y-4"
@@ -567,6 +576,12 @@ export default function Support() {
)} )}
</div> </div>
{rateLimitError && (
<div className="bg-error-500/10 border border-error-500/30 text-error-400 p-3 rounded-xl text-sm">
{rateLimitError}
</div>
)}
<div className="flex gap-3"> <div className="flex gap-3">
<button <button
type="submit" type="submit"
@@ -655,6 +670,13 @@ export default function Support() {
<form <form
onSubmit={(e) => { onSubmit={(e) => {
e.preventDefault() e.preventDefault()
setRateLimitError(null)
// Rate limit: max 5 replies per 30 seconds
if (!checkRateLimit(RATE_LIMIT_KEYS.TICKET_REPLY, 5, 30000)) {
const resetTime = getRateLimitResetTime(RATE_LIMIT_KEYS.TICKET_REPLY)
setRateLimitError(t('support.tooManyRequests', { seconds: resetTime }) || `Слишком много запросов. Подождите ${resetTime} сек.`)
return
}
replyMutation.mutate() replyMutation.mutate()
}} }}
className="pt-4 border-t border-dark-800/50" className="pt-4 border-t border-dark-800/50"
@@ -715,6 +737,11 @@ export default function Support() {
)} )}
</button> </button>
</div> </div>
{rateLimitError && (
<div className="mt-2 bg-error-500/10 border border-error-500/30 text-error-400 p-2 rounded-lg text-sm">
{rateLimitError}
</div>
)}
</div> </div>
</form> </form>
)} )}