init: init repo with existing code
This commit is contained in:
@@ -0,0 +1,291 @@
|
||||
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);
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
setIsSubmitting(true);
|
||||
|
||||
// Simulate form submission
|
||||
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 (
|
||||
<section id="contact" ref={ref} className="py-24 relative overflow-hidden">
|
||||
{/* Background */}
|
||||
<div className="absolute inset-0 opacity-30">
|
||||
<div className="absolute bottom-0 left-1/4 w-96 h-96 bg-primary/10 rounded-full blur-[150px]" />
|
||||
<div className="absolute top-1/4 right-1/4 w-72 h-72 bg-neon-purple/10 rounded-full blur-[120px]" />
|
||||
</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 } : {}}
|
||||
transition={{ duration: 0.6 }}
|
||||
className="text-center mb-16"
|
||||
>
|
||||
<span className="inline-block px-4 py-1.5 rounded-full glass text-sm font-medium text-primary mb-4">
|
||||
Let's Connect
|
||||
</span>
|
||||
<h2 className="text-3xl md:text-4xl lg:text-5xl font-bold mb-4">
|
||||
Get In <span className="text-primary neon-text-glow">Touch</span>
|
||||
</h2>
|
||||
<p className="text-muted-foreground max-w-2xl mx-auto text-lg">
|
||||
Ready to start your next project? We'd love to hear from you. Send
|
||||
us a message and we'll respond as soon as possible.
|
||||
</p>
|
||||
</motion.div>
|
||||
|
||||
<div className="grid lg:grid-cols-2 gap-12 max-w-6xl mx-auto">
|
||||
{/* Contact Info */}
|
||||
<motion.div
|
||||
initial={{ opacity: 0, x: -30 }}
|
||||
animate={isInView ? { opacity: 1, x: 0 } : {}}
|
||||
transition={{ duration: 0.6 }}
|
||||
className="space-y-8"
|
||||
>
|
||||
<div>
|
||||
<h3 className="text-2xl font-bold mb-4">Contact Information</h3>
|
||||
<p className="text-muted-foreground">
|
||||
Fill out the form and our team will get back to you within 24
|
||||
hours.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Contact cards */}
|
||||
<div className="space-y-4">
|
||||
{contactInfo.map((item, index) => (
|
||||
<motion.div
|
||||
key={item.label}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={isInView ? { opacity: 1, y: 0 } : {}}
|
||||
transition={{ duration: 0.5, delay: 0.2 + index * 0.1 }}
|
||||
whileHover={{ x: 5 }}
|
||||
className="flex items-center gap-4 p-4 rounded-xl glass border border-border/50 hover:border-primary/50 transition-all group"
|
||||
>
|
||||
<div className="w-12 h-12 rounded-xl bg-primary/10 flex items-center justify-center group-hover:neon-glow transition-all">
|
||||
<item.icon className="w-5 h-5 text-primary" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{item.label}
|
||||
</p>
|
||||
<p className="font-medium">{item.value}</p>
|
||||
</div>
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Decorative illustration */}
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={isInView ? { opacity: 1 } : {}}
|
||||
transition={{ duration: 0.8, delay: 0.5 }}
|
||||
className="hidden lg:block relative h-48"
|
||||
>
|
||||
<div className="absolute inset-0 flex items-center justify-center">
|
||||
<div className="relative">
|
||||
{[...Array(3)].map((_, i) => (
|
||||
<motion.div
|
||||
key={i}
|
||||
className="absolute w-32 h-32 rounded-full border-2 border-primary/20"
|
||||
style={{
|
||||
left: i * 20,
|
||||
top: i * 10,
|
||||
}}
|
||||
animate={{
|
||||
scale: [1, 1.1, 1],
|
||||
opacity: [0.3, 0.6, 0.3],
|
||||
}}
|
||||
transition={{
|
||||
duration: 3,
|
||||
repeat: Infinity,
|
||||
delay: i * 0.5,
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
|
||||
{/* Contact Form */}
|
||||
<motion.div
|
||||
initial={{ opacity: 0, x: 30 }}
|
||||
animate={isInView ? { opacity: 1, x: 0 } : {}}
|
||||
transition={{ duration: 0.6, delay: 0.2 }}
|
||||
className="relative"
|
||||
>
|
||||
<div className="p-8 rounded-3xl glass border border-border/50 relative overflow-hidden">
|
||||
{/* Decorative gradient */}
|
||||
<div className="absolute -top-20 -right-20 w-40 h-40 rounded-full gradient-primary opacity-20 blur-3xl" />
|
||||
|
||||
{isSuccess ? (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, scale: 0.8 }}
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
className="text-center py-12"
|
||||
>
|
||||
<motion.div
|
||||
initial={{ scale: 0 }}
|
||||
animate={{ scale: 1 }}
|
||||
transition={{
|
||||
type: "spring",
|
||||
damping: 15,
|
||||
stiffness: 300,
|
||||
delay: 0.2,
|
||||
}}
|
||||
>
|
||||
<CheckCircle className="w-20 h-20 text-primary mx-auto mb-4 neon-text-glow" />
|
||||
</motion.div>
|
||||
<h3 className="text-2xl font-bold mb-2">Message Sent!</h3>
|
||||
<p className="text-muted-foreground">
|
||||
Thank you for reaching out. We'll get back to you soon.
|
||||
</p>
|
||||
</motion.div>
|
||||
) : (
|
||||
<form
|
||||
onSubmit={handleSubmit}
|
||||
className="space-y-5 relative z-10"
|
||||
>
|
||||
<div className="grid sm:grid-cols-2 gap-5">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
animate={isInView ? { opacity: 1, y: 0 } : {}}
|
||||
transition={{ delay: 0.3 }}
|
||||
>
|
||||
<Input
|
||||
name="name"
|
||||
placeholder="Your Name"
|
||||
value={formData.name}
|
||||
onChange={handleChange}
|
||||
required
|
||||
className="glass border-border/50 focus:border-primary focus:neon-glow transition-all h-12"
|
||||
/>
|
||||
</motion.div>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
animate={isInView ? { opacity: 1, y: 0 } : {}}
|
||||
transition={{ delay: 0.35 }}
|
||||
>
|
||||
<Input
|
||||
name="email"
|
||||
type="email"
|
||||
placeholder="Your Email"
|
||||
value={formData.email}
|
||||
onChange={handleChange}
|
||||
required
|
||||
className="glass border-border/50 focus:border-primary focus:neon-glow transition-all h-12"
|
||||
/>
|
||||
</motion.div>
|
||||
</div>
|
||||
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
animate={isInView ? { opacity: 1, y: 0 } : {}}
|
||||
transition={{ delay: 0.4 }}
|
||||
>
|
||||
<Input
|
||||
name="subject"
|
||||
placeholder="Subject"
|
||||
value={formData.subject}
|
||||
onChange={handleChange}
|
||||
required
|
||||
className="glass border-border/50 focus:border-primary focus:neon-glow transition-all h-12"
|
||||
/>
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
animate={isInView ? { opacity: 1, y: 0 } : {}}
|
||||
transition={{ delay: 0.45 }}
|
||||
>
|
||||
<Textarea
|
||||
name="message"
|
||||
placeholder="Your Message"
|
||||
value={formData.message}
|
||||
onChange={handleChange}
|
||||
required
|
||||
rows={5}
|
||||
className="glass border-border/50 focus:border-primary focus:neon-glow transition-all resize-none"
|
||||
/>
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
animate={isInView ? { opacity: 1, y: 0 } : {}}
|
||||
transition={{ delay: 0.5 }}
|
||||
>
|
||||
<Button
|
||||
type="submit"
|
||||
disabled={isSubmitting}
|
||||
className="w-full bg-primary text-primary-foreground font-semibold py-6 rounded-full neon-glow hover:neon-glow-strong transition-all group"
|
||||
>
|
||||
{isSubmitting ? (
|
||||
<motion.div
|
||||
animate={{ rotate: 360 }}
|
||||
transition={{
|
||||
duration: 1,
|
||||
repeat: Infinity,
|
||||
ease: "linear",
|
||||
}}
|
||||
className="w-5 h-5 border-2 border-primary-foreground/30 border-t-primary-foreground rounded-full"
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
Send Message
|
||||
<Send className="w-5 h-5 ml-2 group-hover:translate-x-1 transition-transform" />
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
</motion.div>
|
||||
</form>
|
||||
)}
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user