Files
koin_ping_0.2.0/frontend/src/pages/support/Support.jsx

122 lines
3.5 KiB
JavaScript

import { useEffect, useState } from "react";
import { useAuth } from "../../contexts/AuthContext";
import Input from "../../components/Input";
import Button from "../../components/Button";
import { submitSupportRequest } from "../../api/support";
import "./Support.css";
const EMAIL_MAX = 320;
const DESCRIPTION_MAX = 8000;
const DESCRIPTION_PATTERN = /^[a-zA-Z0-9\s]+$/;
function validateEmail(value) {
const v = value.trim();
if (!v) return "Email is required.";
if (v.length > EMAIL_MAX) return "Email is too long.";
const ok =
/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+$/.test(
v,
);
if (!ok) return "Enter a valid email address.";
return null;
}
function validateDescription(value) {
const t = value.trim();
if (!t) return "Description of issue is required.";
if (t.length > DESCRIPTION_MAX) return "Description is too long.";
if (!DESCRIPTION_PATTERN.test(t)) {
return "Use only letters, numbers, and spaces (no special characters).";
}
return null;
}
export default function Support() {
const { currentUser } = useAuth();
const [email, setEmail] = useState("");
const [description, setDescription] = useState("");
const [error, setError] = useState(null);
const [success, setSuccess] = useState(false);
const [sending, setSending] = useState(false);
useEffect(() => {
if (currentUser?.email) {
setEmail(currentUser.email);
}
}, [currentUser?.email]);
async function handleSubmit(e) {
e.preventDefault();
setError(null);
setSuccess(false);
const emailErr = validateEmail(email);
if (emailErr) {
setError(emailErr);
return;
}
const descErr = validateDescription(description);
if (descErr) {
setError(descErr);
return;
}
setSending(true);
try {
await submitSupportRequest({
email: email.trim(),
description: description.trim(),
});
setSuccess(true);
setDescription("");
} catch (err) {
setError(err.message || "Something went wrong.");
} finally {
setSending(false);
}
}
return (
<div className="support-page page">
<h1 className="support-page__title">Contact support</h1>
<p className="support-page__intro">
Describe your issue below. We will reply to the email address you
provide.
</p>
{error && <div className="alert alert--error support-page__alert">{error}</div>}
{success && (
<div className="alert alert--success support-page__alert">
Your message was sent. Thank you.
</div>
)}
<form className="support-form" onSubmit={handleSubmit} noValidate>
<Input
label="Email"
type="email"
value={email}
onChange={setEmail}
autoComplete="email"
required
/>
<label className="form-field support-form__description">
<div className="input__label">Description of Issue</div>
<textarea
className="form-control support-form__textarea"
value={description}
onChange={(e) => setDescription(e.target.value)}
rows={8}
maxLength={DESCRIPTION_MAX}
placeholder="Letters, numbers, and spaces only"
aria-required="true"
/>
</label>
<Button type="submit" disabled={sending} className="support-form__submit">
{sending ? "Sending…" : "Send"}
</Button>
</form>
</div>
);
}