forked from UKSOURCE/hailearning.edu.vn
refactor: merge code and update main.css, delete file css in component
This commit is contained in:
@@ -1,237 +1,13 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useEffect, FormEvent } from "react";
|
||||
import { ContactData } from "./types";
|
||||
import Breadcrumb from "../components/Breadcrumb";
|
||||
|
||||
export default function ContactPage() {
|
||||
const [contactData, setContactData] = useState<ContactData | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [formData, setFormData] = useState({
|
||||
name: "",
|
||||
email: "",
|
||||
phone: "",
|
||||
address: "",
|
||||
date: "",
|
||||
message: "",
|
||||
});
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
const [submitStatus, setSubmitStatus] = useState<{
|
||||
type: "success" | "error" | null;
|
||||
message: string;
|
||||
}>({ type: null, message: "" });
|
||||
|
||||
const apiUrl = process.env.NEXT_PUBLIC_API_URL || "http://localhost:3001";
|
||||
|
||||
// Fetch contact data from CMS
|
||||
useEffect(() => {
|
||||
const fetchContactData = async () => {
|
||||
try {
|
||||
const response = await fetch(`${apiUrl}/api/contact`, { cache: 'no-store' });
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
setContactData(data);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching contact data:", error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchContactData();
|
||||
}, [apiUrl]);
|
||||
|
||||
const handleChange = (
|
||||
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
|
||||
) => {
|
||||
const { name, value } = e.target;
|
||||
setFormData((prev) => ({ ...prev, [name]: value }));
|
||||
};
|
||||
|
||||
const handleSubmit = async (e: FormEvent) => {
|
||||
e.preventDefault();
|
||||
setIsSubmitting(true);
|
||||
setSubmitStatus({ type: null, message: "" });
|
||||
|
||||
try {
|
||||
const response = await fetch(`${apiUrl}/api/contact/submit`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(formData),
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (response.ok && data.success) {
|
||||
setSubmitStatus({
|
||||
type: "success",
|
||||
message: data.message || "Thank you! We will contact you soon.",
|
||||
});
|
||||
setFormData({
|
||||
name: "",
|
||||
email: "",
|
||||
phone: "",
|
||||
address: "",
|
||||
date: "",
|
||||
message: "",
|
||||
});
|
||||
} else {
|
||||
setSubmitStatus({
|
||||
type: "error",
|
||||
message: data.error || "Something went wrong. Please try again.",
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Submit error:", error);
|
||||
setSubmitStatus({
|
||||
type: "error",
|
||||
message: "Network error. Please check your connection and try again.",
|
||||
});
|
||||
} finally {
|
||||
setIsSubmitting(false);
|
||||
}
|
||||
};
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="loading-wrapper" style={{ minHeight: "100vh", display: "flex", alignItems: "center", justifyContent: "center" }}>
|
||||
<p>Loading...</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Default values if API fails
|
||||
const hero = contactData?.hero || { title: "Contact Us", backgroundImage: "/assets/img/inner-page/breadcrumb.jpg" };
|
||||
const contactCards = contactData?.contactCards || [];
|
||||
const map = contactData?.map || { embedUrl: "" };
|
||||
const form = contactData?.form || {
|
||||
heading: "Send Us Message",
|
||||
description: "Have questions? Send us a message today.",
|
||||
fields: [],
|
||||
submitButton: { text: "SEND MESSAGE", icon: "fa-solid fa-arrow-right", buttonClass: "theme-btn style-2" }
|
||||
};
|
||||
import ContactHero from "../components/contact/ContactHero";
|
||||
import DepartmentDirectory from "../components/contact/DepartmentDirectory";
|
||||
import ContactSplit from "../components/contact/ContactSplit";
|
||||
|
||||
export default function ContactUsPage() {
|
||||
return (
|
||||
<>
|
||||
{/* Breadcrumb-Wrapper Section Start */}
|
||||
<Breadcrumb title={hero.title} current={hero.title} />
|
||||
|
||||
{/* Contact Icon Section Start */}
|
||||
<section className="contact-us-section-3 section-padding fix">
|
||||
<div className="container">
|
||||
<div className="row g-4">
|
||||
{contactCards.map((card, index) => (
|
||||
<div className="col-xl-4 col-lg-6 col-md-6" key={index}>
|
||||
<div className="contact-icon-item">
|
||||
<div className="icon">
|
||||
<i className={card.iconType}></i>
|
||||
</div>
|
||||
<div className="content">
|
||||
<p>{card.title}</p>
|
||||
<h6>
|
||||
{card.content.map((line, i) => (
|
||||
<span key={i}>
|
||||
{card.type === "email" ? (
|
||||
<a href={`mailto:${line}`}>{line}</a>
|
||||
) : card.type === "phone" ? (
|
||||
<a href={`tel:${line.replace(/\s/g, "")}`}>{line}</a>
|
||||
) : (
|
||||
line
|
||||
)}
|
||||
{i < card.content.length - 1 && <br />}
|
||||
</span>
|
||||
))}
|
||||
</h6>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Contact Section Start */}
|
||||
<section className="contact-section-3 section-padding fix pt-0">
|
||||
<div className="container">
|
||||
<div className="contact-from-wrapper">
|
||||
<h5 className="text-center">{form.heading}</h5>
|
||||
<p className="text-center mt-3 mb-5">"{form.description}"</p>
|
||||
|
||||
{/* Status Message */}
|
||||
{submitStatus.type && (
|
||||
<div
|
||||
className={`alert ${submitStatus.type === "success" ? "alert-success" : "alert-danger"
|
||||
} text-center mb-4`}
|
||||
>
|
||||
{submitStatus.message}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="row g-4">
|
||||
<div className="col-xl-12">
|
||||
<form onSubmit={handleSubmit} className="contact-form-items">
|
||||
<div className="row g-4">
|
||||
{form.fields.map((field, index) => (
|
||||
<div className={field.colClass || "col-lg-12"} key={index}>
|
||||
<div className="form-clt">
|
||||
<span>{field.label}{field.required && " *"}</span>
|
||||
{field.type === "textarea" ? (
|
||||
<textarea
|
||||
name={field.name}
|
||||
value={formData[field.name as keyof typeof formData] || ""}
|
||||
onChange={handleChange}
|
||||
placeholder={field.placeholder}
|
||||
required={field.required}
|
||||
></textarea>
|
||||
) : (
|
||||
<input
|
||||
type={field.type}
|
||||
name={field.name}
|
||||
value={formData[field.name as keyof typeof formData] || ""}
|
||||
onChange={handleChange}
|
||||
placeholder={field.placeholder}
|
||||
required={field.required}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
<div className="col-lg-4">
|
||||
<button
|
||||
type="submit"
|
||||
className={form.submitButton.buttonClass}
|
||||
disabled={isSubmitting}
|
||||
>
|
||||
{isSubmitting ? "SENDING..." : form.submitButton.text}
|
||||
<i className={form.submitButton.icon}></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Map Section Start */}
|
||||
{map.embedUrl && (
|
||||
<div className="map-section section-padding pt-0">
|
||||
<div className="map-items">
|
||||
<div className="googpemap">
|
||||
<iframe
|
||||
src={map.embedUrl}
|
||||
style={{ border: 0 }}
|
||||
allowFullScreen
|
||||
loading="lazy"
|
||||
></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
<main className="contact-page min-h-screen bg-gray-50 pb-20">
|
||||
<ContactHero />
|
||||
<DepartmentDirectory />
|
||||
<ContactSplit />
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user