diff --git a/client/src/App.css b/client/src/App.css index e8fcbec..3421dd9 100644 --- a/client/src/App.css +++ b/client/src/App.css @@ -443,6 +443,16 @@ html.scheme-dark .themed-select-option.is-selected { gap: 16px; } +.feedback-form__honeypot { + position: absolute; + left: -9999px; + width: 1px; + height: 1px; + overflow: hidden; + opacity: 0; + pointer-events: none; +} + .feedback-form__field { display: flex; flex-direction: column; diff --git a/client/src/components/FeedbackModal.tsx b/client/src/components/FeedbackModal.tsx index d0deee5..fb7f56e 100644 --- a/client/src/components/FeedbackModal.tsx +++ b/client/src/components/FeedbackModal.tsx @@ -26,9 +26,11 @@ export default function FeedbackModal({ const [category, setCategory] = useState('general') const [contactEmail, setContactEmail] = useState('') const [message, setMessage] = useState('') + const [website, setWebsite] = useState('') const [submitState, setSubmitState] = useState('idle') const [statusMessage, setStatusMessage] = useState(null) const closeTimerRef = useRef(null) + const openedAtRef = useRef(Date.now()) const isBusy = submitState === 'submitting' || submitState === 'success' @@ -58,9 +60,12 @@ export default function FeedbackModal({ setCategory('general') setContactEmail('') setMessage('') + setWebsite('') setSubmitState('idle') setStatusMessage(null) + return } + openedAtRef.current = Date.now() }, [open]) const handleSubmit = async (event: React.FormEvent) => { @@ -76,7 +81,9 @@ export default function FeedbackModal({ message: message.trim(), contactEmail: contactEmail.trim() || undefined, logbookId, - logbookTitle + logbookTitle, + openedAt: openedAtRef.current, + website }) setSubmitState('success') setStatusMessage(t('feedback.success')) @@ -91,7 +98,11 @@ export default function FeedbackModal({ ? t('feedback.error_not_configured') : error instanceof FeedbackApiError && error.code === 'INVALID_EMAIL' ? t('feedback.error_invalid_email') - : t('feedback.error_send') + : error instanceof FeedbackApiError && error.code === 'RATE_LIMITED' + ? t('feedback.error_rate_limited') + : error instanceof FeedbackApiError && error.code === 'SPAM_DETECTED' + ? t('feedback.error_spam') + : t('feedback.error_send') ) } } @@ -139,6 +150,18 @@ export default function FeedbackModal({ )}
+ +