Files
Magent/frontend/app/feedback/page.tsx
T
Assclaw f852e7c941
Magent CI/CD / verify (push) Failing after 9m34s
Magent CI/CD / deploy-beta (push) Skipped
chore: standardize security and quality foundations
2026-09-17 20:03:47 +12:00

114 lines
3.5 KiB
TypeScript

"use client";
import PageHeading from "../ui/PageHeading";
import { useEffect, useState } from "react";
import { useRouter } from "next/navigation";
import { authFetchOrThrow, getApiBase, getToken, UnauthorizedError } from "../lib/auth";
type Profile = {
username?: string;
};
export default function FeedbackPage() {
const router = useRouter();
const [profile, setProfile] = useState<Profile | null>(null);
const [category, setCategory] = useState("bug");
const [message, setMessage] = useState("");
const [status, setStatus] = useState<string | null>(null);
const [submitting, setSubmitting] = useState(false);
useEffect(() => {
if (!getToken()) {
router.push("/login");
return;
}
const load = async () => {
try {
const baseUrl = getApiBase();
const response = await authFetchOrThrow(`${baseUrl}/auth/me`);
if (!response.ok) {
throw new Error("Could not load profile.");
}
const data = await response.json();
setProfile({ username: data?.username });
} catch (error) {
if (error instanceof UnauthorizedError) {
router.push("/login");
return;
}
console.error(error);
}
};
void load();
}, [router]);
const submit = async (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
setStatus(null);
if (!message.trim()) {
setStatus("Please write a short message before sending.");
return;
}
setSubmitting(true);
try {
const baseUrl = getApiBase();
const response = await authFetchOrThrow(`${baseUrl}/feedback`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
type: category,
message: message.trim(),
}),
});
if (!response.ok) {
const text = await response.text();
throw new Error(text || `Request failed: ${response.status}`);
}
setMessage("");
setStatus("Thanks! Your message has been sent.");
} catch (error) {
if (error instanceof UnauthorizedError) {
router.push("/login");
return;
}
console.error(error);
setStatus("That did not send. Please try again.");
} finally {
setSubmitting(false);
}
};
return (
<main className="card feedback-page">
<PageHeading title="Feedback" description="Share an idea or tell us what could work better." />
<form className="account-panel account-form feedback-form" onSubmit={submit}>
<label htmlFor="feedback-user">Your username</label>
<input id="feedback-user" value={profile?.username ?? ""} readOnly />
<label htmlFor="feedback-type">What is this about?</label>
<select id="feedback-type" value={category} onChange={(event) => setCategory(event.target.value)}>
<option value="bug">Bug (something is broken)</option>
<option value="feature">Feature idea (new option)</option>
</select>
<label htmlFor="feedback-message">Tell us what happened</label>
<textarea
id="feedback-message"
rows={6}
value={message}
onChange={(event) => setMessage(event.target.value)}
placeholder="Write the details here..."
/>
{status && <div className="status-banner">{status}</div>}
<button type="submit" disabled={submitting}>
{submitting ? "Sending..." : "Send feedback"}
</button>
</form>
</main>
);
}