135 lines
4.2 KiB
TypeScript
135 lines
4.2 KiB
TypeScript
import { useState } from "react";
|
|
import { submitReport, type ContentReportCreate } from "../api/public-client";
|
|
|
|
interface ReportIssueModalProps {
|
|
contentType: string;
|
|
contentId?: string | null;
|
|
contentTitle?: string | null;
|
|
onClose: () => void;
|
|
}
|
|
|
|
const REPORT_TYPES = [
|
|
{ value: "inaccurate", label: "Inaccurate content" },
|
|
{ value: "missing_info", label: "Missing information" },
|
|
{ value: "wrong_attribution", label: "Wrong attribution" },
|
|
{ value: "formatting", label: "Formatting issue" },
|
|
{ value: "other", label: "Other" },
|
|
];
|
|
|
|
export default function ReportIssueModal({
|
|
contentType,
|
|
contentId,
|
|
contentTitle,
|
|
onClose,
|
|
}: ReportIssueModalProps) {
|
|
const [reportType, setReportType] = useState("inaccurate");
|
|
const [description, setDescription] = useState("");
|
|
const [submitting, setSubmitting] = useState(false);
|
|
const [submitted, setSubmitted] = useState(false);
|
|
const [error, setError] = useState<string | null>(null);
|
|
|
|
const handleSubmit = async (e: React.FormEvent) => {
|
|
e.preventDefault();
|
|
if (description.trim().length < 10) {
|
|
setError("Please provide at least 10 characters describing the issue.");
|
|
return;
|
|
}
|
|
|
|
setSubmitting(true);
|
|
setError(null);
|
|
|
|
try {
|
|
const body: ContentReportCreate = {
|
|
content_type: contentType,
|
|
content_id: contentId ?? null,
|
|
content_title: contentTitle ?? null,
|
|
report_type: reportType,
|
|
description: description.trim(),
|
|
page_url: window.location.href,
|
|
};
|
|
await submitReport(body);
|
|
setSubmitted(true);
|
|
} catch (err) {
|
|
setError(
|
|
err instanceof Error ? err.message : "Failed to submit report",
|
|
);
|
|
} finally {
|
|
setSubmitting(false);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="modal-overlay" onClick={onClose}>
|
|
<div className="modal-content report-modal" onClick={(e) => e.stopPropagation()}>
|
|
{submitted ? (
|
|
<>
|
|
<h3 className="report-modal__title">Thank you</h3>
|
|
<p className="report-modal__success">
|
|
Your report has been submitted. We'll review it shortly.
|
|
</p>
|
|
<button className="btn btn--primary" onClick={onClose}>
|
|
Close
|
|
</button>
|
|
</>
|
|
) : (
|
|
<>
|
|
<h3 className="report-modal__title">Report an issue</h3>
|
|
{contentTitle && (
|
|
<p className="report-modal__context">
|
|
About: <strong>{contentTitle}</strong>
|
|
</p>
|
|
)}
|
|
<form onSubmit={handleSubmit}>
|
|
<label className="report-modal__label">
|
|
Issue type
|
|
<select
|
|
className="report-modal__select"
|
|
value={reportType}
|
|
onChange={(e) => setReportType(e.target.value)}
|
|
>
|
|
{REPORT_TYPES.map((t) => (
|
|
<option key={t.value} value={t.value}>
|
|
{t.label}
|
|
</option>
|
|
))}
|
|
</select>
|
|
</label>
|
|
|
|
<label className="report-modal__label">
|
|
Description
|
|
<textarea
|
|
className="report-modal__textarea"
|
|
value={description}
|
|
onChange={(e) => setDescription(e.target.value)}
|
|
placeholder="Describe the issue…"
|
|
rows={4}
|
|
maxLength={2000}
|
|
/>
|
|
</label>
|
|
|
|
{error && <p className="report-modal__error">{error}</p>}
|
|
|
|
<div className="report-modal__actions">
|
|
<button
|
|
type="button"
|
|
className="btn btn--secondary"
|
|
onClick={onClose}
|
|
disabled={submitting}
|
|
>
|
|
Cancel
|
|
</button>
|
|
<button
|
|
type="submit"
|
|
className="btn btn--primary"
|
|
disabled={submitting || description.trim().length < 10}
|
|
>
|
|
{submitting ? "Submitting…" : "Submit report"}
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|