Files
negin-dental-clinic/app/contact-us/ContactForm.js
T
alireza-hassaniandClaude Sonnet 5 f16b47966b Initial commit: Negin Dental Clinic website
Next.js (App Router) clone of negindentalclinic.ir, wired to the
Meshkee Website API (blog, contact form, favicon), with on-page SEO
and a scroll-reveal animation sequence on the homepage.

See context.md for full project context.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-04 18:28:54 +03:30

132 lines
3.8 KiB
JavaScript

"use client";
import { useEffect, useRef, useState } from "react";
import { submitContact } from "@/lib/meshkee";
import styles from "./contact.module.css";
const EMPTY = { name: "", email: "", phone: "", subject: "", message: "" };
export default function ContactForm() {
const [values, setValues] = useState(EMPTY);
const [status, setStatus] = useState("idle"); // idle | sending | error
const [error, setError] = useState("");
const [toast, setToast] = useState(null); // { text, kind } | null
const toastTimer = useRef(null);
useEffect(() => () => clearTimeout(toastTimer.current), []);
const showToast = (text, kind = "success") => {
setToast({ text, kind });
clearTimeout(toastTimer.current);
toastTimer.current = setTimeout(() => setToast(null), 4500);
};
const onChange = (e) =>
setValues((v) => ({ ...v, [e.target.name]: e.target.value }));
const onSubmit = async (e) => {
e.preventDefault();
setStatus("sending");
setError("");
try {
await submitContact({
title: values.subject,
name: values.name,
text: values.message,
email: values.email || undefined,
cellNumber: values.phone || undefined,
});
setValues(EMPTY);
setStatus("idle");
showToast("پیام شما با موفقیت ارسال شد. همکاران ما در اسرع وقت با شما تماس خواهند گرفت.");
} catch (err) {
setStatus("error");
setError(err.message || "ارسال پیام با خطا مواجه شد. لطفاً دوباره تلاش کنید.");
showToast("ارسال پیام ناموفق بود. لطفاً دوباره تلاش کنید.", "error");
}
};
return (
<>
<form className={styles.form} onSubmit={onSubmit} noValidate>
<div className={styles.row}>
<label>
<span>نام و نام خانوادگی</span>
<input
name="name"
value={values.name}
onChange={onChange}
required
autoComplete="name"
/>
</label>
<label>
<span>آدرس الکترونیکی</span>
<input
type="email"
name="email"
value={values.email}
onChange={onChange}
autoComplete="email"
dir="ltr"
/>
</label>
</div>
<div className={styles.row}>
<label>
<span>شماره تماس</span>
<input
name="phone"
value={values.phone}
onChange={onChange}
autoComplete="tel"
inputMode="tel"
dir="ltr"
/>
</label>
<label>
<span>موضوع</span>
<input
name="subject"
value={values.subject}
onChange={onChange}
required
/>
</label>
</div>
<label>
<span>پیام شما</span>
<textarea
name="message"
rows={6}
value={values.message}
onChange={onChange}
required
/>
</label>
<button type="submit" className="btn" disabled={status === "sending"}>
{status === "sending" ? "در حال ارسال…" : "ارسال پیام"}
</button>
{status === "error" && error ? (
<p className={styles.formError} role="alert">
{error}
</p>
) : null}
</form>
{toast ? (
<div
className={`${styles.toast} ${toast.kind === "error" ? styles.toastError : ""}`}
role="status"
>
{toast.text}
</div>
) : null}
</>
);
}