feat(form): enhance and refactor contact form to inquiries form
This commit refactors the contact form into a more robust inquiries form, relocating it from `/contact-us` to a new `/inquires` route. Key changes include: - Renamed and moved the component from `ContactUs` to `Inquires`. - Updated form fields: removed "Company Name", added "Message", and renamed "Work Email" and "Phone Number" for clarity. - Implemented comprehensive client-side validation for all fields using `react-hook-form`. - Added a loading state to the submit button to provide user feedback during submission. - The form now automatically resets upon successful submission. - Introduced new reusable `TextareaGroup` and `Loading` components to support the enhanced form functionality.
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
import ContactUs from "../_contact-us/page";
|
||||
import Inquires from "../_inquires/page";
|
||||
|
||||
const FooterForm = () => {
|
||||
return (
|
||||
<div className="absolute w-full -top-[420px] lg:-top-72 z-10">
|
||||
<ContactUs />
|
||||
<Inquires />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
function Loading({ size = "md" }: { size?: "sm" | "md" | "lg" }) {
|
||||
const sizeClasses = {
|
||||
sm: "w-4 h-4 border-2",
|
||||
md: "w-8 h-8 border-3",
|
||||
lg: "w-12 h-12 border-4",
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="inline-block">
|
||||
<div
|
||||
className={`${sizeClasses[size]} border-gray-200 border-t-blue-600 rounded-full animate-spin`}
|
||||
role="status"
|
||||
aria-label="Loading">
|
||||
<span className="sr-only">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Loading;
|
||||
@@ -0,0 +1,61 @@
|
||||
"use client";
|
||||
import { useState } from "react";
|
||||
import { RegisterOptions, UseFormRegister } from "react-hook-form";
|
||||
|
||||
function TextareaGroup({
|
||||
id,
|
||||
label,
|
||||
register,
|
||||
validation,
|
||||
error,
|
||||
}: {
|
||||
label: string;
|
||||
id: string;
|
||||
register: UseFormRegister<any>;
|
||||
validation?: RegisterOptions;
|
||||
error?: string;
|
||||
}) {
|
||||
const [isFocused, setIsFocused] = useState(false);
|
||||
const [hasValue, setHasValue] = useState(false);
|
||||
|
||||
const { onChange, ...rest } = register(id, validation);
|
||||
|
||||
const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
|
||||
setHasValue(e.target.value !== "");
|
||||
onChange(e);
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="relative w-full my-3">
|
||||
<textarea
|
||||
className={`border ${
|
||||
error
|
||||
? "border-red-500"
|
||||
: isFocused
|
||||
? "border-(--primary)"
|
||||
: "border-gray-200"
|
||||
} p-2 py-3 rounded-lg w-full outline-none resize-vertical min-h-[100px]`}
|
||||
id={id}
|
||||
{...rest}
|
||||
onChange={handleChange}
|
||||
onFocus={() => setIsFocused(true)}
|
||||
onBlur={() => setIsFocused(false)}
|
||||
/>
|
||||
<label
|
||||
htmlFor={id}
|
||||
className={`absolute left-3 transition-all duration-200 pointer-events-none bg-white px-1 ${
|
||||
isFocused || hasValue
|
||||
? "-top-2 text-xs text-gray-600"
|
||||
: "top-3 text-base text-gray-400"
|
||||
}`}>
|
||||
{label}
|
||||
<span className="text-red-400">*</span>
|
||||
</label>
|
||||
</div>
|
||||
{error && <p className="text-red-500 text-sm my-3">{error}</p>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default TextareaGroup;
|
||||
Reference in New Issue
Block a user