teg/frontend/src/components/Feedback.tsx
2026-05-22 14:11:18 +02:00

111 lines
3.4 KiB
TypeScript

// frontend/src/pages/Feedback.tsx
import { useState, type FormEvent } from 'react'
import Textarea from '../components/Textarea'
const API_URL = import.meta.env.VITE_API_URL ?? 'http://localhost:8080'
export default function Feedback() {
const [message, setMessage] = useState('')
const [isSubmitting, setIsSubmitting] = useState(false)
const [error, setError] = useState<string | null>(null)
const [successMessage, setSuccessMessage] = useState<string | null>(null)
async function handleSubmit(event: FormEvent<HTMLFormElement>) {
event.preventDefault()
const trimmedMessage = message.trim()
if (!trimmedMessage) {
setError('Bitte gib dein Feedback ein.')
setSuccessMessage(null)
return
}
setIsSubmitting(true)
setError(null)
setSuccessMessage(null)
try {
const response = await fetch(`${API_URL}/feedback`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
credentials: 'include',
body: JSON.stringify({
message: trimmedMessage,
}),
})
if (!response.ok) {
const errorData = await response.json().catch(() => null)
throw new Error(errorData?.error ?? 'Feedback konnte nicht gesendet werden')
}
setMessage('')
setSuccessMessage('Danke, dein Feedback wurde gespeichert.')
} catch (error) {
setError(
error instanceof Error
? error.message
: 'Feedback konnte nicht gesendet werden',
)
} finally {
setIsSubmitting(false)
}
}
return (
<div className="h-full min-h-0 overflow-y-auto px-4 py-10 sm:px-6 lg:px-8 [scrollbar-gutter:stable]">
<div className="mx-auto max-w-3xl">
<div>
<h1 className="text-2xl font-semibold text-gray-900 dark:text-white">
Feedback
</h1>
<p className="mt-2 text-sm text-gray-500 dark:text-gray-400">
Teile uns mit, wenn dir etwas auffällt, etwas nicht funktioniert oder du eine Idee zur Verbesserung hast.
Beim Absenden wird automatisch ein technisches Log mit deinem Benutzerkonto angehängt.
</p>
</div>
{successMessage && (
<div className="mt-6 rounded-md bg-green-50 p-4 text-sm text-green-700 dark:bg-green-900/30 dark:text-green-300">
{successMessage}
</div>
)}
{error && (
<div className="mt-6 rounded-md bg-red-50 p-4 text-sm text-red-700 dark:bg-red-900/30 dark:text-red-300">
{error}
</div>
)}
<form
onSubmit={handleSubmit}
className="mt-8 rounded-lg border border-gray-200 bg-white p-6 shadow-xs dark:border-white/10 dark:bg-gray-900"
>
<Textarea
id="feedback"
name="feedback"
label="Dein Feedback"
placeholder="Beschreibe möglichst genau, was passiert ist oder was verbessert werden soll..."
variant="avatar-actions"
rows={8}
value={message}
maxLength={5000}
disabled={isSubmitting}
submitLabel="Feedback senden"
showAttachButton={false}
onChange={(event) => setMessage(event.target.value)}
/>
<div className="mt-2 text-right text-xs text-gray-500 dark:text-gray-400">
{message.length} / 5000 Zeichen
</div>
</form>
</div>
</div>
)
}