update redesign

This commit is contained in:
2026-06-24 18:31:06 +05:30
parent 6ddfc57217
commit d3c7d93cef
23 changed files with 1756 additions and 1518 deletions

View File

@@ -2,8 +2,7 @@
import Link from "next/link";
import Image from "next/image";
import { usePathname } from "next/navigation";
import React, { useState } from "react";
import React from "react";
import { MaterialIcon } from "@/components/ui/MaterialIcon";
const COMPANY = [
@@ -27,392 +26,131 @@ const LEGAL = [
{ label: "Sitemap", href: "#" },
];
type FooterFormData = {
name: string;
phone: string;
email: string;
message: string;
};
type FooterFormErrors = {
name?: string;
phone?: string;
email?: string;
message?: string;
};
export function Footer() {
const pathname = usePathname();
const isContactPage = pathname?.startsWith("/contact");
// Form states
const [formData, setFormData] = useState<FooterFormData>({
name: "",
phone: "",
email: "",
message: "",
});
const [errors, setErrors] = useState<FooterFormErrors>({});
const [isSubmitting, setIsSubmitting] = useState(false);
const [submitSuccess, setSubmitSuccess] = useState(false);
const handleInputChange = (
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
) => {
const { name, value } = e.target;
setFormData((prev) => ({
...prev,
[name]: value,
}));
if (errors[name as keyof FooterFormErrors]) {
setErrors((prev) => ({
...prev,
[name]: undefined,
}));
}
};
const validateForm = (): boolean => {
const tempErrors: FooterFormErrors = {};
let isValid = true;
if (!formData.name.trim()) {
tempErrors.name = "Name is required";
isValid = false;
}
if (!formData.phone.trim()) {
tempErrors.phone = "Phone is required";
isValid = false;
}
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!formData.email.trim()) {
tempErrors.email = "Email is required";
isValid = false;
} else if (!emailRegex.test(formData.email)) {
tempErrors.email = "Please enter a valid email address";
isValid = false;
}
if (!formData.message.trim()) {
tempErrors.message = "Message is required";
isValid = false;
}
setErrors(tempErrors);
return isValid;
};
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (!validateForm()) return;
setIsSubmitting(true);
// Simulate API delay
await new Promise((resolve) => setTimeout(resolve, 1000));
setIsSubmitting(false);
setSubmitSuccess(true);
setFormData({ name: "", phone: "", email: "", message: "" });
// Hide success alert after 5 seconds
setTimeout(() => {
setSubmitSuccess(false);
}, 5000);
};
const brandCol = (
<div className="footer-brand min-w-0 self-start">
<Link href="/" className="mb-4 inline-block">
<Image
src="/logo-v2.png"
alt="Nearle"
width={220}
height={36}
style={{ width: "210px", height: "auto" }}
className="object-contain"
/>
</Link>
<p className="footer-desc mb-4 text-white/80">
India&apos;s leading hyperlocal neighborhood network, empowering
communities and verified local businesses within 2km.
</p>
{/* Social Links */}
<div className="flex gap-4">
<a href="#" className="footer-social-link" aria-label="Share">
<MaterialIcon icon="share" size={24} />
</a>
<a href="#" className="footer-social-link" aria-label="Website">
<MaterialIcon icon="public" size={24} />
</a>
</div>
</div>
);
return (
<footer className="bg-[#E6D7EA] px-3 sm:px-4 md:px-5 lg:px-6 xl:px-8 pb-0 w-full mt-3 md:mt-4">
<div className="mx-auto" style={{ maxWidth: "min(100% - 48px, 1520px)" }}>
<div className="bg-[#120217] rounded-[1.5rem] md:rounded-[2rem] lg:rounded-[2.5rem] overflow-hidden border border-white/10 shadow-[0_18px_45px_rgba(20,0,30,0.28)]">
{/* Top Helpdesk Bar */}
<div className="bg-[#2A0838] border-b border-white/10 px-5 py-4 md:px-8 md:py-5 flex flex-col md:flex-row justify-between items-center gap-6">
<div className="flex items-center gap-4 text-white">
<div className="w-12 h-12 rounded-full bg-brand-accent text-brand-dark flex items-center justify-center shadow-lg shrink-0">
<MaterialIcon icon="headset_mic" size={24} />
</div>
<div className="text-left">
<h4 className="text-headline-md font-black text-white">
24/7 Neighborhood Helpdesk
</h4>
<p className="text-sm font-semibold text-white/70 mt-0.5">
Need immediate assistance with an order or local service?
</p>
<footer className="bg-[#E6D7EA] px-3 sm:px-4 md:px-6 lg:px-8 xl:px-10 2xl:px-12 pb-6 md:pb-8 lg:pb-10 w-full mt-4">
<div className="mx-auto w-full max-w-[1920px]">
<div className="section-card-dark p-8 md:p-12 lg:p-14 text-white relative">
{/* Background ambient glowing details */}
<div className="absolute right-[-10%] top-[-10%] w-[50%] h-[50%] rounded-full bg-brand-accent/5 blur-[120px] pointer-events-none" />
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-10 lg:gap-12 relative z-10 items-start text-left">
{/* Col 1: Brand info */}
<div className="flex flex-col gap-4">
<Link href="/" className="inline-block">
<Image
src="/logo-light.png"
alt="Nearle"
width={220}
height={36}
style={{ width: "160px", height: "auto" }}
className="object-contain"
/>
</Link>
<p className="text-sm leading-relaxed text-white/70">
India&apos;s leading hyperlocal neighborhood network, empowering
communities and verified local businesses within 2km.
</p>
{/* Social Links */}
<div className="flex gap-3 mt-2">
<a href="#" className="w-10 h-10 rounded-full bg-white/5 border border-white/10 flex items-center justify-center text-white hover:bg-[#E6D7EA] hover:text-[#17001F] transition-all duration-300" aria-label="Share">
<MaterialIcon icon="share" size={20} />
</a>
<a href="#" className="w-10 h-10 rounded-full bg-white/5 border border-white/10 flex items-center justify-center text-white hover:bg-[#E6D7EA] hover:text-[#17001F] transition-all duration-300" aria-label="Website">
<MaterialIcon icon="public" size={20} />
</a>
</div>
</div>
{/* Col 2: Company Links */}
<div>
<h5 className="text-sm font-bold uppercase tracking-wider text-white/50 mb-6">Company</h5>
<ul className="flex flex-col gap-3">
{COMPANY.map((l) => (
<li key={l.label}>
<Link href={l.href} className="text-sm text-white/70 hover:text-[#E6D7EA] hover:translate-x-1 transition-all inline-block">
{l.label}
</Link>
</li>
))}
</ul>
</div>
{/* Col 3: Partnerships */}
<div>
<h5 className="text-sm font-bold uppercase tracking-wider text-white/50 mb-6">Partnerships</h5>
<ul className="flex flex-col gap-3">
{PARTNERSHIPS.map((l) => (
<li key={l.label}>
<Link href={l.href} className="text-sm text-white/70 hover:text-[#E6D7EA] hover:translate-x-1 transition-all inline-block">
{l.label}
</Link>
</li>
))}
</ul>
</div>
{/* Col 4: Support / Legal */}
<div>
<h5 className="text-sm font-bold uppercase tracking-wider text-white/50 mb-6">Support & Legal</h5>
<ul className="flex flex-col gap-3">
{LEGAL.map((l) => (
<li key={l.label}>
<Link href={l.href} className="text-sm text-white/70 hover:text-[#E6D7EA] hover:translate-x-1 transition-all inline-block">
{l.label}
</Link>
</li>
))}
</ul>
</div>
{/* Col 5: HQ Address & Helpdesk */}
<div className="flex flex-col gap-4">
<div>
<h5 className="text-sm font-bold uppercase tracking-wider text-white/50 mb-4">Visit Nearle HQ</h5>
<p className="text-xs leading-relaxed text-white/60">
424, Diwan Bahadur Rd,<br />
Opposite to Sri Krishna Sweets,<br />
R.S. Puram, Coimbatore,<br />
Tamil Nadu 641002
</p>
<a
href="https://maps.google.com/?q=424,+Diwan+Bahadur+Rd,+Opposite+To+Sri+Krishna+Sweets,+R.S.+Puram,+Coimbatore,+Tamil+Nadu+641002"
target="_blank"
rel="noopener noreferrer"
className="mt-3 inline-flex items-center gap-1.5 px-3.5 py-1.5 rounded-xl border border-white/10 hover:border-[#E6D7EA]/50 text-white/80 hover:text-[#E6D7EA] text-xs font-bold transition-all duration-300"
>
<MaterialIcon icon="location_on" size={14} />
<span>Get Directions</span>
</a>
</div>
<div className="border-t border-white/10 pt-4 flex flex-col gap-2">
<p className="text-[10px] font-bold text-white/40 uppercase tracking-widest">Neighborhood Helpdesk</p>
<a
href="tel:+918049123456"
className="flex items-center gap-2 text-white hover:text-[#E6D7EA] transition-all"
>
<MaterialIcon icon="phone" size={16} className="text-[#E6D7EA] shrink-0" />
<span className="text-sm font-black tracking-tight">+91 80 4912 3456</span>
</a>
</div>
</div>
<a
href="tel:+918049123456"
className="flex items-center gap-3 bg-brand-accent hover:bg-brand-accent-light text-brand-dark font-black px-6 py-3 rounded-full text-base shadow-lg transition-all duration-300 hover:-translate-y-0.5 shrink-0"
>
<MaterialIcon
icon="phone"
size={20}
className="animate-pulse-subtle"
/>
<span>+91 80 4912 3456</span>
</a>
</div>
{/* Main Footer Content */}
<div className="px-5 pt-10 pb-8 md:px-8 md:pt-12 md:pb-10 lg:px-12 lg:pt-12 lg:pb-10 text-white">
<div
className={
isContactPage
? "grid grid-cols-1 sm:grid-cols-3 gap-8 lg:gap-10"
: "grid grid-cols-1 lg:grid-cols-[minmax(0,1fr)_minmax(500px,560px)] gap-10 xl:gap-14 items-start"
}
>
{isContactPage ? (
<>
{/* Brand Column */}
{brandCol}
{/* Company Links */}
<div className="footer-company min-w-0 self-start">
<FooterCol title="Company" links={COMPANY} />
</div>
{/* Partnerships Links */}
<div className="footer-partnerships min-w-0 self-start">
<FooterCol title="Partnerships" links={PARTNERSHIPS} />
</div>
</>
) : (
<>
<div className="flex flex-col self-start w-full">
<div className="grid grid-cols-1 sm:grid-cols-3 gap-8 lg:gap-10">
{/* Brand Column */}
{brandCol}
{/* Company Links */}
<div className="footer-company min-w-0 self-start">
<FooterCol title="Company" links={COMPANY} />
</div>
{/* Partnerships Links */}
<div className="footer-partnerships min-w-0 self-start">
<FooterCol title="Partnerships" links={PARTNERSHIPS} />
</div>
</div>
{/* HQ Office Location & Directions block */}
<div className="mt-8 border-t border-white/10 pt-7 max-w-[520px] text-left">
<p className="text-[11px] font-black uppercase tracking-[0.18em] text-brand-accent">
VISIT NEARLE HQ
</p>
<h4 className="mt-2 font-display text-xl md:text-2xl font-black text-white">
Meet the team behind your neighbourhood.
</h4>
<p className="mt-3 text-sm leading-6 text-white/60">
424, Diwan Bahadur Rd,
<br />
Opposite to Sri Krishna Sweets,
<br />
R.S. Puram, Coimbatore,
<br />
Tamil Nadu 641002
</p>
<a
href="https://maps.google.com/?q=424,+Diwan+Bahadur+Rd,+Opposite+To+Sri+Krishna+Sweets,+R.S.+Puram,+Coimbatore,+Tamil+Nadu+641002"
target="_blank"
rel="noopener noreferrer"
className="mt-4 inline-flex items-center gap-2 px-4 py-2 rounded-xl border border-white/15 hover:border-brand-accent/50 text-white hover:text-brand-accent text-xs md:text-sm font-black transition-all duration-300"
>
<MaterialIcon icon="location_on" size={16} />
<span>Get Directions</span>
</a>
</div>
</div>
{/* Contact Form Card */}
<div className="footer-contact-wrap w-full self-start">
<div className="footer-contact-card bg-white text-brand-dark shadow-2xl border border-outline-variant/15 relative overflow-hidden w-full max-w-[540px] lg:ml-auto p-7 md:p-8 lg:p-9">
{/* Background Glow Decors */}
<div className="absolute top-0 right-0 w-24 h-24 bg-primary/5 rounded-full blur-2xl" />
<div className="absolute bottom-0 left-0 w-24 h-24 bg-secondary/5 rounded-full blur-2xl" />
<div className="relative z-10 text-center lg:text-left">
<h3 className="footer-contact-title font-display text-2xl md:text-3xl font-black text-brand-dark tracking-tight">
Send us a Message
</h3>
<p className="footer-contact-subtitle text-sm md:text-base mt-1 mb-5">
We shall guide you through our Neighbourhood Experts.
</p>
<form onSubmit={handleSubmit} className="space-y-3">
{submitSuccess && (
<div className="p-3 bg-secondary/10 border border-secondary/20 text-secondary text-body-sm font-bold rounded-xl flex items-center justify-center gap-1.5 animate-bounce-subtle">
<MaterialIcon icon="check_circle" size={16} />
<span>Message sent successfully!</span>
</div>
)}
<div className="footer-form-row grid grid-cols-1 sm:grid-cols-2 gap-4">
<div className="flex flex-col text-left">
<label
htmlFor="footer-field-name"
className="text-xs font-black text-brand-dark/70 mb-1.5"
>
Your Name
</label>
<input
type="text"
id="footer-field-name"
name="name"
value={formData.name}
onChange={handleInputChange}
placeholder="Your Name..."
className={`footer-input h-12 md:h-13 ${errors.name ? "has-error" : ""}`}
/>
{errors.name && (
<span className="footer-error-text">
<MaterialIcon icon="error" size={16} />
{errors.name}
</span>
)}
</div>
<div className="flex flex-col text-left">
<label
htmlFor="footer-field-phone"
className="text-xs font-black text-brand-dark/70 mb-1.5"
>
Your Phone
</label>
<input
type="text"
id="footer-field-phone"
name="phone"
value={formData.phone}
onChange={handleInputChange}
placeholder="Your Phone..."
className={`footer-input h-12 md:h-13 ${errors.phone ? "has-error" : ""}`}
/>
{errors.phone && (
<span className="footer-error-text">
<MaterialIcon icon="error" size={16} />
{errors.phone}
</span>
)}
</div>
</div>
<div className="flex flex-col text-left">
<label
htmlFor="footer-field-email"
className="text-xs font-black text-brand-dark/70 mb-1.5"
>
Your Email Address
</label>
<input
type="email"
id="footer-field-email"
name="email"
value={formData.email}
onChange={handleInputChange}
placeholder="Your Email Address..."
className={`footer-input h-12 md:h-13 ${errors.email ? "has-error" : ""}`}
/>
{errors.email && (
<span className="footer-error-text">
<MaterialIcon icon="error" size={16} />
{errors.email}
</span>
)}
</div>
<div className="flex flex-col text-left">
<label
htmlFor="footer-field-message"
className="text-xs font-black text-brand-dark/70 mb-1.5"
>
Your Message
</label>
<textarea
id="footer-field-message"
name="message"
value={formData.message}
onChange={handleInputChange}
placeholder="Your Message..."
className={`footer-textarea min-h-[120px] md:min-h-[130px] ${errors.message ? "has-error" : ""}`}
/>
{errors.message && (
<span className="footer-error-text">
<MaterialIcon icon="error" size={16} />
{errors.message}
</span>
)}
</div>
<button
type="submit"
disabled={isSubmitting}
className="footer-submit-btn h-12 md:h-13"
>
{isSubmitting ? (
<>
<span className="w-5 h-5 border-2 border-white/30 border-t-white rounded-full animate-spin" />
<span>SUBMITTING...</span>
</>
) : (
<span>SUBMIT</span>
)}
</button>
</form>
</div>
</div>
</div>
</>
)}
</div>
{/* Footer Bottom Bar */}
<div className="mt-8 border-t border-white/10 pt-5 text-xs text-white/45">
<div className="flex flex-col md:flex-row justify-between items-start md:items-center gap-4">
<p>© {new Date().getFullYear()} Nearle. All rights reserved.</p>
<div className="flex flex-col md:flex-row gap-2 md:gap-6 text-left">
{LEGAL.map((link) => (
<Link
key={link.label}
href={link.href}
className="hover:text-[#e0c8f7] transition-colors"
>
{link.label}
</Link>
))}
</div>
</div>
{/* Bottom Copyright Divider & Bar */}
<div className="mt-12 pt-6 border-t border-white/10 relative z-10 flex flex-col sm:flex-row justify-between items-center gap-4 text-xs text-white/40">
<p>© {new Date().getFullYear()} Nearle. All rights reserved.</p>
<div className="flex flex-wrap gap-x-6 gap-y-2 justify-center">
{LEGAL.map((link) => (
<Link
key={link.label}
href={link.href}
className="hover:text-[#E6D7EA] transition-colors"
>
{link.label}
</Link>
))}
</div>
</div>
</div>
@@ -421,28 +159,4 @@ export function Footer() {
);
}
// Ensure default export is also available for Next.js app router client components if needed
export default Footer;
function FooterCol({
title,
links,
}: {
title: string;
links: { label: string; href: string }[];
}) {
return (
<div>
<h5 className="footer-column-title">{title}</h5>
<ul className="footer-links-list">
{links.map((l) => (
<li key={l.label}>
<Link href={l.href} className="footer-link inline-block">
{l.label}
</Link>
</li>
))}
</ul>
</div>
);
}