remove unused files
This commit is contained in:
@@ -165,12 +165,13 @@ export function Hero() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right Column: Dominant Purple Scooter Rider (Overlapping) */}
|
||||
<div className="hero-bike select-none pointer-events-none">
|
||||
<div className="relative w-full h-full flex items-end">
|
||||
{/* Right Column: Dominant delivery image (Overlapping) */}
|
||||
<div className="hero-visual-layer select-none pointer-events-none">
|
||||
<div className="hero-visual-panel" />
|
||||
<div className="hero-visual-image">
|
||||
<Image
|
||||
src="/images/slider-courier-mask-purple-v4.png"
|
||||
alt="Nearle Delivery Courier"
|
||||
src="/nearlenewlogo.png"
|
||||
alt="Nearle delivery"
|
||||
fill
|
||||
sizes="(max-width: 768px) 95vw, 48vw"
|
||||
className="object-contain object-bottom drop-shadow-2xl"
|
||||
@@ -181,7 +182,7 @@ export function Hero() {
|
||||
</div>
|
||||
|
||||
{/* Overlapping Quick Category Links (Anchored at the bottom edge) */}
|
||||
<div className="hero-cards absolute bottom-0 left-0 right-0 transform translate-y-[50%] z-20">
|
||||
<div className="hero-cards">
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6">
|
||||
{QUICK_LINKS.map((item) => (
|
||||
<div
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
"use client";
|
||||
|
||||
import Link from "next/link";
|
||||
import Image from "next/image";
|
||||
import { usePathname } from "next/navigation";
|
||||
import React, { useState } from "react";
|
||||
import { MaterialIcon } from "@/components/ui/MaterialIcon";
|
||||
|
||||
const COMPANY = [
|
||||
@@ -23,11 +27,104 @@ 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 === "/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);
|
||||
};
|
||||
|
||||
return (
|
||||
<footer className="relative bg-brand-dark text-white border-t border-white/5 pt-28 pb-12 w-full mt-24">
|
||||
<footer className="relative z-10 bg-brand-dark text-white border-t border-white/5 pt-24 pb-6 w-full mt-24">
|
||||
{/* Overlapping Contact Helpdesk Card */}
|
||||
<div className="absolute top-0 left-0 right-0 transform -translate-y-1/2 z-20 max-w-container-max mx-auto px-margin-mobile md:px-margin-desktop">
|
||||
<div className="absolute -top-20 md:-top-14 left-0 right-0 z-20 max-w-[1380px] mx-auto px-margin-mobile md:px-margin-desktop">
|
||||
<div className="bg-brand-accent p-6 md:p-8 rounded-[2.5rem] flex flex-col md:flex-row justify-between items-center gap-6 shadow-2xl border border-brand-accent/20">
|
||||
<div className="flex items-center gap-4 text-brand-dark">
|
||||
<div className="w-12 h-12 rounded-full bg-brand-dark text-brand-accent flex items-center justify-center shadow-lg">
|
||||
@@ -50,25 +147,30 @@ export function Footer() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="max-w-container-max mx-auto px-margin-mobile md:px-margin-desktop">
|
||||
{/* Footer Link Grid */}
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-gutter mb-16 pt-4">
|
||||
<div className="max-w-[1380px] mx-auto px-margin-mobile md:px-margin-desktop">
|
||||
|
||||
{/* Main content grid: aligned on the same top baseline */}
|
||||
<div className={`grid grid-cols-1 md:grid-cols-2 lg:items-start gap-y-10 gap-x-6 lg:gap-x-12 mb-12 ${
|
||||
isContactPage
|
||||
? "lg:grid-cols-[220px_170px_190px_150px]"
|
||||
: "lg:grid-cols-[220px_170px_190px_150px_minmax(360px,480px)]"
|
||||
}`}>
|
||||
{/* Brand Column */}
|
||||
<div className="col-span-2 md:col-span-1">
|
||||
<div className="col-span-1 md:col-span-2 lg:col-span-1">
|
||||
<Link
|
||||
href="/"
|
||||
className="hover:scale-[1.02] transition-transform active:scale-95 duration-200 mb-6 inline-block"
|
||||
className="hover:scale-[1.02] transition-transform active:scale-95 duration-200 mb-4 inline-block"
|
||||
>
|
||||
<Image
|
||||
src="/logo-v2.png"
|
||||
alt="Nearle"
|
||||
width={140}
|
||||
height={23}
|
||||
width={220}
|
||||
height={36}
|
||||
style={{ height: "auto" }}
|
||||
className="h-7 w-auto object-contain"
|
||||
className="h-9 w-auto object-contain"
|
||||
/>
|
||||
</Link>
|
||||
<p className="text-body-sm text-white/60 max-w-xs mb-8 leading-relaxed">
|
||||
<p className="text-body-sm text-white/60 max-w-xs mb-4 leading-relaxed">
|
||||
India's leading hyperlocal neighborhood network, empowering communities and verified local businesses within 2km.
|
||||
</p>
|
||||
{/* Social Links */}
|
||||
@@ -91,18 +193,143 @@ export function Footer() {
|
||||
</div>
|
||||
|
||||
{/* Company Links */}
|
||||
<FooterCol title="Company" links={COMPANY} />
|
||||
|
||||
<div className="col-span-1">
|
||||
<FooterCol title="Company" links={COMPANY} />
|
||||
</div>
|
||||
|
||||
{/* Partnerships Links */}
|
||||
<FooterCol title="Partnerships" links={PARTNERSHIPS} />
|
||||
|
||||
<div className="col-span-1">
|
||||
<FooterCol title="Partnerships" links={PARTNERSHIPS} />
|
||||
</div>
|
||||
|
||||
{/* Legal Links */}
|
||||
<FooterCol title="Legal" links={LEGAL} />
|
||||
<div className="col-span-1">
|
||||
<FooterCol title="Legal" links={LEGAL} />
|
||||
</div>
|
||||
|
||||
{/* Contact Form Card */}
|
||||
{!isContactPage && (
|
||||
<div className="col-span-1 md:col-span-2 lg:col-span-1 bg-white text-brand-dark rounded-3xl p-5 md:p-6 shadow-2xl border border-outline-variant/15 relative overflow-hidden w-full lg:max-w-none lg:-translate-x-16 lg:translate-y-2">
|
||||
{/* 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="text-xl font-display font-black text-brand-dark tracking-tight">
|
||||
Send us a Message
|
||||
</h3>
|
||||
<p className="text-[11px] text-on-surface-variant mt-1 mb-6">
|
||||
We shall guide you through our Neighbourhood Experts.
|
||||
</p>
|
||||
|
||||
<form onSubmit={handleSubmit} className="space-y-4">
|
||||
{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="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-1 xl:grid-cols-2 gap-4">
|
||||
<div className="flex flex-col text-left">
|
||||
<input
|
||||
type="text"
|
||||
name="name"
|
||||
value={formData.name}
|
||||
onChange={handleInputChange}
|
||||
placeholder="Your Name..."
|
||||
className={`w-full bg-surface border ${
|
||||
errors.name ? "border-error focus:ring-error/20" : "border-outline-variant/30 focus:ring-primary/20"
|
||||
} text-body-sm text-on-surface placeholder:text-on-surface-variant/45 rounded-xl px-4 py-2.5 focus:outline-none focus:ring-2 focus:border-primary transition-all`}
|
||||
/>
|
||||
{errors.name && (
|
||||
<span className="text-[9px] text-error font-bold mt-1 pl-1 flex items-center gap-0.5">
|
||||
<MaterialIcon icon="error" size={10} />
|
||||
{errors.name}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex flex-col text-left">
|
||||
<input
|
||||
type="text"
|
||||
name="phone"
|
||||
value={formData.phone}
|
||||
onChange={handleInputChange}
|
||||
placeholder="Your Phone..."
|
||||
className={`w-full bg-surface border ${
|
||||
errors.phone ? "border-error focus:ring-error/20" : "border-outline-variant/30 focus:ring-primary/20"
|
||||
} text-body-sm text-on-surface placeholder:text-on-surface-variant/45 rounded-xl px-4 py-2.5 focus:outline-none focus:ring-2 focus:border-primary transition-all`}
|
||||
/>
|
||||
{errors.phone && (
|
||||
<span className="text-[9px] text-error font-bold mt-1 pl-1 flex items-center gap-0.5">
|
||||
<MaterialIcon icon="error" size={10} />
|
||||
{errors.phone}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col text-left">
|
||||
<input
|
||||
type="email"
|
||||
name="email"
|
||||
value={formData.email}
|
||||
onChange={handleInputChange}
|
||||
placeholder="Your Email Address..."
|
||||
className={`w-full bg-surface border ${
|
||||
errors.email ? "border-error focus:ring-error/20" : "border-outline-variant/30 focus:ring-primary/20"
|
||||
} text-body-sm text-on-surface placeholder:text-on-surface-variant/45 rounded-xl px-4 py-2.5 focus:outline-none focus:ring-2 focus:border-primary transition-all`}
|
||||
/>
|
||||
{errors.email && (
|
||||
<span className="text-[9px] text-error font-bold mt-1 pl-1 flex items-center gap-0.5">
|
||||
<MaterialIcon icon="error" size={10} />
|
||||
{errors.email}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col text-left">
|
||||
<textarea
|
||||
name="message"
|
||||
value={formData.message}
|
||||
onChange={handleInputChange}
|
||||
placeholder="Your Message..."
|
||||
rows={3}
|
||||
className={`w-full bg-surface border ${
|
||||
errors.message ? "border-error focus:ring-error/20" : "border-outline-variant/30 focus:ring-primary/20"
|
||||
} text-body-sm text-on-surface placeholder:text-on-surface-variant/45 rounded-xl px-4 py-2.5 focus:outline-none focus:ring-2 focus:border-primary transition-all resize-none`}
|
||||
/>
|
||||
{errors.message && (
|
||||
<span className="text-[9px] text-error font-bold mt-1 pl-1 flex items-center gap-0.5">
|
||||
<MaterialIcon icon="error" size={10} />
|
||||
{errors.message}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
disabled={isSubmitting}
|
||||
className="w-full bg-primary hover:bg-primary-container disabled:bg-primary/50 text-on-primary font-black px-6 py-3 rounded-xl text-label-md shadow-md active:scale-95 duration-200 transition-all flex items-center justify-center gap-2 cursor-pointer"
|
||||
>
|
||||
{isSubmitting ? (
|
||||
<>
|
||||
<span className="w-4 h-4 border-2 border-white/30 border-t-white rounded-full animate-spin" />
|
||||
<span>SUBMITTING...</span>
|
||||
</>
|
||||
) : (
|
||||
<span>SUBMIT</span>
|
||||
)}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Bottom Bar */}
|
||||
<div className="border-t border-white/10 pt-8 flex flex-col md:flex-row justify-between items-center gap-4">
|
||||
<p className="text-body-sm text-white/40">
|
||||
<div className="border-t border-white/10 pt-7 flex flex-col md:flex-row justify-between items-center gap-4">
|
||||
<p className="text-body-sm text-white/40 lg:pl-20">
|
||||
© {new Date().getFullYear()} Nearle. All rights reserved.
|
||||
</p>
|
||||
<div className="flex items-center gap-2 text-white/40 text-body-sm">
|
||||
|
||||
@@ -28,10 +28,10 @@ export function Navbar() {
|
||||
<Image
|
||||
src="/logo-purple-v2.png"
|
||||
alt="Nearle"
|
||||
width={140}
|
||||
height={23}
|
||||
width={220}
|
||||
height={50}
|
||||
style={{ height: "auto" }}
|
||||
className="h-7 w-auto object-contain"
|
||||
className="h-9 w-auto object-contain"
|
||||
priority
|
||||
/>
|
||||
</Link>
|
||||
|
||||
Reference in New Issue
Block a user