Files
techzaa-frontend/src/components/ContactSection.tsx
T

259 lines
10 KiB
TypeScript
Raw Normal View History

2026-03-30 20:20:21 +06:00
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
import { motion, useInView } from "framer-motion";
import { CheckCircle, Mail, MapPin, Phone, Send } from "lucide-react";
import { useRef, useState } from "react";
const contactInfo = [
{ icon: Mail, label: "Email", value: "techzaa.alpha@gmail.com" },
{ icon: Phone, label: "Phone", value: "+880 19623-21487" },
{ icon: MapPin, label: "Location", value: "Rangpur, Bangladesh" },
];
export default function ContactSection() {
const ref = useRef<HTMLElement>(null);
const isInView = useInView(ref, { once: true, margin: "-100px" });
const [formData, setFormData] = useState({
name: "",
email: "",
subject: "",
message: "",
});
const [isSubmitting, setIsSubmitting] = useState(false);
const [isSuccess, setIsSuccess] = useState(false);
2026-04-30 22:36:40 +06:00
const [mousePositions, setMousePositions] = useState<
Record<number, { x: number; y: number }>
>({});
const handleMouseMove = (
index: number,
e: React.MouseEvent<HTMLDivElement>,
) => {
const rect = e.currentTarget.getBoundingClientRect();
const x = ((e.clientX - rect.left) / rect.width) * 100;
const y = ((e.clientY - rect.top) / rect.height) * 100;
setMousePositions((prev) => ({ ...prev, [index]: { x, y } }));
};
2026-03-30 20:20:21 +06:00
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setIsSubmitting(true);
await new Promise((resolve) => setTimeout(resolve, 1500));
setIsSubmitting(false);
setIsSuccess(true);
setTimeout(() => {
setIsSuccess(false);
setFormData({ name: "", email: "", subject: "", message: "" });
}, 3000);
};
const handleChange = (
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
) => {
setFormData((prev) => ({
...prev,
[e.target.name]: e.target.value,
}));
};
return (
2026-04-30 22:36:40 +06:00
<section id="contact" ref={ref} className="relative overflow-hidden pb-20">
<div className="absolute inset-0 opacity-40 pointer-events-none">
<motion.div
animate={{
x: [0, 30, 0],
y: [0, -40, 0],
}}
transition={{ duration: 25, repeat: Infinity, ease: "linear" }}
className="absolute bottom-10 left-1/4 w-96 h-96 bg-primary/10 rounded-full blur-[140px]"
/>
<motion.div
animate={{
x: [0, -50, 0],
y: [0, 30, 0],
}}
transition={{ duration: 30, repeat: Infinity, ease: "linear" }}
className="absolute top-20 right-1/4 w-80 h-80 bg-neon-purple/10 rounded-full blur-[130px]"
/>
2026-03-30 20:20:21 +06:00
</div>
<div className="container mx-auto px-4 relative z-10">
{/* Section Header */}
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={isInView ? { opacity: 1, y: 0 } : {}}
2026-04-30 22:36:40 +06:00
transition={{ duration: 0.7 }}
className="text-center mb-20"
2026-03-30 20:20:21 +06:00
>
2026-04-30 22:36:40 +06:00
<span className="inline-block px-5 py-2 rounded-full glass text-sm font-medium text-primary mb-4 tracking-widest">
LET'S CONNECT
2026-03-30 20:20:21 +06:00
</span>
2026-04-30 22:36:40 +06:00
<h2 className="text-4xl md:text-5xl lg:text-6xl font-bold mb-6">
2026-03-30 20:20:21 +06:00
Get In <span className="text-primary neon-text-glow">Touch</span>
</h2>
<p className="text-muted-foreground max-w-2xl mx-auto text-lg">
2026-04-30 22:36:40 +06:00
Ready to bring your vision to life? Drop us a message.
2026-03-30 20:20:21 +06:00
</p>
</motion.div>
<div className="grid lg:grid-cols-2 gap-12 max-w-6xl mx-auto">
2026-04-30 22:36:40 +06:00
{/* Interactive Contact Info */}
2026-03-30 20:20:21 +06:00
<motion.div
2026-04-30 22:36:40 +06:00
initial={{ opacity: 0, x: -40 }}
2026-03-30 20:20:21 +06:00
animate={isInView ? { opacity: 1, x: 0 } : {}}
2026-04-30 22:36:40 +06:00
transition={{ duration: 0.7 }}
className="space-y-6"
2026-03-30 20:20:21 +06:00
>
2026-04-30 22:36:40 +06:00
<div className="mb-8">
<h3 className="text-3xl font-bold mb-3">Contact Information</h3>
<p className="text-muted-foreground text-lg">
Our team typically responds within 24 hours.
2026-03-30 20:20:21 +06:00
</p>
</div>
2026-04-30 22:36:40 +06:00
<div className="space-y-6">
{contactInfo.map((item, index) => {
const pos = mousePositions[index] || { x: 50, y: 50 };
return (
<motion.div
key={item.label}
initial={{ opacity: 0, y: 30 }}
animate={isInView ? { opacity: 1, y: 0 } : {}}
transition={{ delay: 0.1 * index }}
onMouseMove={(e) => handleMouseMove(index, e)}
onMouseLeave={() => {
setMousePositions((prev) => ({
...prev,
[index]: { x: 50, y: 50 },
}));
}}
whileHover={{ scale: 1.02 }}
className="group relative rounded-xl overflow-hidden cursor-pointer h-full"
>
<div
className="relative p-4 rounded-xl border transition-all duration-300"
style={{
transform: `perspective(800px) rotateX(${(50 - pos.y) * 0.08}deg) rotateY(${(pos.x - 50) * 0.1}deg)`,
}}
>
<div className="flex items-start gap-6">
<div className="w-16 h-16 rounded-2xl bg-primary/10 flex items-center justify-center group-hover:bg-primary/20 transition-all group-hover:neon-glow">
<item.icon className="w-7 h-7 text-primary" />
</div>
<div className="pt-1">
<p className="text-sm text-muted-foreground mb-1">
{item.label}
</p>
<p className="text-xl font-medium group-hover:text-primary transition-colors">
{item.value}
</p>
</div>
</div>
</div>
</motion.div>
);
})}
2026-03-30 20:20:21 +06:00
</div>
</motion.div>
2026-04-30 22:36:40 +06:00
{/* Interactive Contact Form */}
2026-03-30 20:20:21 +06:00
<motion.div
2026-04-30 22:36:40 +06:00
initial={{ opacity: 0, x: 40 }}
2026-03-30 20:20:21 +06:00
animate={isInView ? { opacity: 1, x: 0 } : {}}
2026-04-30 22:36:40 +06:00
transition={{ duration: 0.7, delay: 0.1 }}
2026-03-30 20:20:21 +06:00
>
2026-04-30 22:36:40 +06:00
<div className="p-10 rounded-3xl border backdrop-blur-2xl relative overflow-hidden">
{/* Subtle moving gradient */}
<div className="absolute -top-32 -right-32 w-64 h-64 bg-primary/10 rounded-full blur-3xl" />
2026-03-30 20:20:21 +06:00
{isSuccess ? (
<motion.div
2026-04-30 22:36:40 +06:00
initial={{ opacity: 0, scale: 0.9 }}
2026-03-30 20:20:21 +06:00
animate={{ opacity: 1, scale: 1 }}
2026-04-30 22:36:40 +06:00
className="text-center py-16"
2026-03-30 20:20:21 +06:00
>
2026-04-30 22:36:40 +06:00
<CheckCircle className="w-24 h-24 text-primary mx-auto mb-6 neon-text-glow" />
<h3 className="text-3xl font-bold mb-3">
Message Sent Successfully!
</h3>
<p className="text-muted-foreground text-lg">
Thank you! We'll get back to you very soon.
2026-03-30 20:20:21 +06:00
</p>
</motion.div>
) : (
<form
onSubmit={handleSubmit}
2026-04-30 22:36:40 +06:00
className="space-y-6 relative z-10"
2026-03-30 20:20:21 +06:00
>
2026-04-30 22:36:40 +06:00
<div className="grid sm:grid-cols-2 gap-6">
2026-03-30 20:20:21 +06:00
<Input
2026-04-30 22:36:40 +06:00
name="name"
placeholder="Your Name"
value={formData.name}
2026-03-30 20:20:21 +06:00
onChange={handleChange}
required
2026-04-30 22:36:40 +06:00
className="h-14 focus:border-primary focus:ring-2 focus:ring-primary/30 transition-all text-base"
2026-03-30 20:20:21 +06:00
/>
2026-04-30 22:36:40 +06:00
<Input
name="email"
type="email"
placeholder="Your Email"
value={formData.email}
2026-03-30 20:20:21 +06:00
onChange={handleChange}
required
2026-04-30 22:36:40 +06:00
className="h-14 focus:border-primary focus:ring-2 focus:ring-primary/30 transition-all text-base"
2026-03-30 20:20:21 +06:00
/>
2026-04-30 22:36:40 +06:00
</div>
2026-03-30 20:20:21 +06:00
2026-04-30 22:36:40 +06:00
<Input
name="subject"
placeholder="Subject"
value={formData.subject}
onChange={handleChange}
required
className="h-14 focus:border-primary focus:ring-2 focus:ring-primary/30 transition-all text-base"
/>
<Textarea
name="message"
placeholder="Tell us about your project..."
value={formData.message}
onChange={handleChange}
required
rows={6}
className=" focus:border-primary focus:ring-2 focus:ring-primary/30 transition-all resize-none text-base"
/>
<Button
type="submit"
disabled={isSubmitting}
className="w-full h-14 bg-primary hover:bg-primary/90 text-lg font-semibold rounded-2xl neon-glow hover:neon-glow-strong transition-all group"
2026-03-30 20:20:21 +06:00
>
2026-04-30 22:36:40 +06:00
{isSubmitting ? (
<div className="flex items-center gap-3">
<div className="w-5 h-5 border-2 border-white/30 border-t-white rounded-full animate-spin" />
Sending...
</div>
) : (
<div className="flex items-center justify-center gap-3">
Send Message
<Send className="w-5 h-5 group-hover:translate-x-1 transition-transform" />
</div>
)}
</Button>
2026-03-30 20:20:21 +06:00
</form>
)}
</div>
</motion.div>
</div>
</div>
</section>
);
}