additional fetaure buildout for footer and footer links
This commit is contained in:
121
frontend/src/pages/support/Support.jsx
Normal file
121
frontend/src/pages/support/Support.jsx
Normal file
@@ -0,0 +1,121 @@
|
||||
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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user