111 lines
3.4 KiB
TypeScript
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>
|
|
)
|
|
} |