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:
AmirReza Jamali
2025-10-27 11:33:18 +03:30
parent ca911091f4
commit 645b397396
6 changed files with 284 additions and 40 deletions
+2 -2
View File
@@ -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>
);
};
+20
View File
@@ -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;
+61
View File
@@ -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;