fix all pages
This commit is contained in:
+2
-2
@@ -24,8 +24,8 @@ function AnimatedRoutes() {
|
|||||||
<Route path="/" element={<Index />} />
|
<Route path="/" element={<Index />} />
|
||||||
<Route path="/projects" element={<Projects />} />
|
<Route path="/projects" element={<Projects />} />
|
||||||
<Route path="/projects/:slug" element={<ProjectDetails />} />
|
<Route path="/projects/:slug" element={<ProjectDetails />} />
|
||||||
<Route path="/blog" element={<Blog />} />
|
{/* <Route path="/blog" element={<Blog />} />
|
||||||
<Route path="/blog/:id" element={<BlogArticle />} />
|
<Route path="/blog/:id" element={<BlogArticle />} /> */}
|
||||||
{/* ADD ALL CUSTOM ROUTES ABOVE THE CATCH-ALL "*" ROUTE */}
|
{/* ADD ALL CUSTOM ROUTES ABOVE THE CATCH-ALL "*" ROUTE */}
|
||||||
<Route path="*" element={<NotFound />} />
|
<Route path="*" element={<NotFound />} />
|
||||||
<Route path="/privacy" element={<PrivacyPolicy />} />
|
<Route path="/privacy" element={<PrivacyPolicy />} />
|
||||||
|
|||||||
@@ -58,11 +58,6 @@ export default function AboutSection() {
|
|||||||
ref={ref}
|
ref={ref}
|
||||||
className="py-24 relative overflow-hidden bg-secondary/30"
|
className="py-24 relative overflow-hidden bg-secondary/30"
|
||||||
>
|
>
|
||||||
{/* Background decoration */}
|
|
||||||
<div className="absolute inset-0">
|
|
||||||
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[800px] h-[800px] bg-primary/5 rounded-full blur-[200px]" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="container mx-auto px-4 relative z-10">
|
<div className="container mx-auto px-4 relative z-10">
|
||||||
<div className="grid lg:grid-cols-2 gap-16 items-center">
|
<div className="grid lg:grid-cols-2 gap-16 items-center">
|
||||||
{/* Content */}
|
{/* Content */}
|
||||||
@@ -102,7 +97,7 @@ export default function AboutSection() {
|
|||||||
(value) => (
|
(value) => (
|
||||||
<span
|
<span
|
||||||
key={value}
|
key={value}
|
||||||
className="px-4 py-2 rounded-full glass border border-primary/30 text-sm font-medium hover:border-primary hover:neon-glow transition-all cursor-default"
|
className="px-4 py-2 rounded-full glass neon-glow text-sm font-medium hover:border-primary border transition-all cursor-default"
|
||||||
>
|
>
|
||||||
{value}
|
{value}
|
||||||
</span>
|
</span>
|
||||||
@@ -124,8 +119,7 @@ export default function AboutSection() {
|
|||||||
initial={{ opacity: 0, y: 20 }}
|
initial={{ opacity: 0, y: 20 }}
|
||||||
animate={isInView ? { opacity: 1, y: 0 } : {}}
|
animate={isInView ? { opacity: 1, y: 0 } : {}}
|
||||||
transition={{ duration: 0.5, delay: 0.3 + index * 0.1 }}
|
transition={{ duration: 0.5, delay: 0.3 + index * 0.1 }}
|
||||||
whileHover={{ y: -5, scale: 1.02 }}
|
className="p-6 rounded-2xl bg-primary/5 hover:neon-glow transition-all text-center group"
|
||||||
className="p-6 rounded-2xl glass hover:border-primary/50 transition-all text-center group"
|
|
||||||
>
|
>
|
||||||
{/* Icon */}
|
{/* Icon */}
|
||||||
<div className="w-12 h-12 rounded-xl bg-primary/10 flex items-center justify-center mx-auto mb-4 group-hover:neon-glow transition-all">
|
<div className="w-12 h-12 rounded-xl bg-primary/10 flex items-center justify-center mx-auto mb-4 group-hover:neon-glow transition-all">
|
||||||
|
|||||||
+154
-155
@@ -24,11 +24,24 @@ export default function ContactSection() {
|
|||||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||||
const [isSuccess, setIsSuccess] = useState(false);
|
const [isSuccess, setIsSuccess] = useState(false);
|
||||||
|
|
||||||
|
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 } }));
|
||||||
|
};
|
||||||
|
|
||||||
const handleSubmit = async (e: React.FormEvent) => {
|
const handleSubmit = async (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setIsSubmitting(true);
|
setIsSubmitting(true);
|
||||||
|
|
||||||
// Simulate form submission
|
|
||||||
await new Promise((resolve) => setTimeout(resolve, 1500));
|
await new Promise((resolve) => setTimeout(resolve, 1500));
|
||||||
|
|
||||||
setIsSubmitting(false);
|
setIsSubmitting(false);
|
||||||
@@ -50,11 +63,24 @@ export default function ContactSection() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section id="contact" ref={ref} className="relative overflow-hidden pb-24">
|
<section id="contact" ref={ref} className="relative overflow-hidden pb-20">
|
||||||
{/* Background */}
|
<div className="absolute inset-0 opacity-40 pointer-events-none">
|
||||||
<div className="absolute inset-0 opacity-30">
|
<motion.div
|
||||||
<div className="absolute bottom-0 left-1/4 w-96 h-96 bg-primary/10 rounded-full blur-[150px]" />
|
animate={{
|
||||||
<div className="absolute top-1/4 right-1/4 w-72 h-72 bg-neon-purple/10 rounded-full blur-[120px]" />
|
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]"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="container mx-auto px-4 relative z-10">
|
<div className="container mx-auto px-4 relative z-10">
|
||||||
@@ -62,192 +88,165 @@ export default function ContactSection() {
|
|||||||
<motion.div
|
<motion.div
|
||||||
initial={{ opacity: 0, y: 20 }}
|
initial={{ opacity: 0, y: 20 }}
|
||||||
animate={isInView ? { opacity: 1, y: 0 } : {}}
|
animate={isInView ? { opacity: 1, y: 0 } : {}}
|
||||||
transition={{ duration: 0.6 }}
|
transition={{ duration: 0.7 }}
|
||||||
className="text-center mb-16"
|
className="text-center mb-20"
|
||||||
>
|
>
|
||||||
<span className="inline-block px-4 py-1.5 rounded-full text-sm font-medium text-primary mb-4">
|
<span className="inline-block px-5 py-2 rounded-full glass text-sm font-medium text-primary mb-4 tracking-widest">
|
||||||
Let's Connect
|
LET'S CONNECT
|
||||||
</span>
|
</span>
|
||||||
<h2 className="text-3xl md:text-4xl lg:text-5xl font-bold mb-4">
|
<h2 className="text-4xl md:text-5xl lg:text-6xl font-bold mb-6">
|
||||||
Get In <span className="text-primary neon-text-glow">Touch</span>
|
Get In <span className="text-primary neon-text-glow">Touch</span>
|
||||||
</h2>
|
</h2>
|
||||||
<p className="text-muted-foreground max-w-2xl mx-auto text-lg">
|
<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
|
Ready to bring your vision to life? Drop us a message.
|
||||||
us a message and we'll respond as soon as possible.
|
|
||||||
</p>
|
</p>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
|
||||||
<div className="grid lg:grid-cols-2 gap-12 max-w-6xl mx-auto">
|
<div className="grid lg:grid-cols-2 gap-12 max-w-6xl mx-auto">
|
||||||
{/* Contact Info */}
|
{/* Interactive Contact Info */}
|
||||||
<motion.div
|
<motion.div
|
||||||
initial={{ opacity: 0, x: -30 }}
|
initial={{ opacity: 0, x: -40 }}
|
||||||
animate={isInView ? { opacity: 1, x: 0 } : {}}
|
animate={isInView ? { opacity: 1, x: 0 } : {}}
|
||||||
transition={{ duration: 0.6 }}
|
transition={{ duration: 0.7 }}
|
||||||
className="space-y-8"
|
className="space-y-6"
|
||||||
>
|
>
|
||||||
<div>
|
<div className="mb-8">
|
||||||
<h3 className="text-2xl font-bold mb-4">Contact Information</h3>
|
<h3 className="text-3xl font-bold mb-3">Contact Information</h3>
|
||||||
<p className="text-muted-foreground">
|
<p className="text-muted-foreground text-lg">
|
||||||
Fill out the form and our team will get back to you within 24
|
Our team typically responds within 24 hours.
|
||||||
hours.
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Contact cards */}
|
<div className="space-y-6">
|
||||||
<div className="space-y-4">
|
{contactInfo.map((item, index) => {
|
||||||
{contactInfo.map((item, index) => (
|
const pos = mousePositions[index] || { x: 50, y: 50 };
|
||||||
<motion.div
|
return (
|
||||||
key={item.label}
|
<motion.div
|
||||||
initial={{ opacity: 0, y: 20 }}
|
key={item.label}
|
||||||
animate={isInView ? { opacity: 1, y: 0 } : {}}
|
initial={{ opacity: 0, y: 30 }}
|
||||||
transition={{ duration: 0.5, delay: 0.2 + index * 0.1 }}
|
animate={isInView ? { opacity: 1, y: 0 } : {}}
|
||||||
whileHover={{ x: 5 }}
|
transition={{ delay: 0.1 * index }}
|
||||||
className="flex items-center gap-4 p-4 rounded-xl glass border border-border/50 hover:border-primary/50 transition-all group"
|
onMouseMove={(e) => handleMouseMove(index, e)}
|
||||||
>
|
onMouseLeave={() => {
|
||||||
<div className="w-12 h-12 rounded-xl bg-primary/10 flex items-center justify-center group-hover:neon-glow transition-all">
|
setMousePositions((prev) => ({
|
||||||
<item.icon className="w-5 h-5 text-primary" />
|
...prev,
|
||||||
</div>
|
[index]: { x: 50, y: 50 },
|
||||||
<div>
|
}));
|
||||||
<p className="text-sm text-muted-foreground">
|
}}
|
||||||
{item.label}
|
whileHover={{ scale: 1.02 }}
|
||||||
</p>
|
className="group relative rounded-xl overflow-hidden cursor-pointer h-full"
|
||||||
<p className="font-medium">{item.value}</p>
|
>
|
||||||
</div>
|
<div
|
||||||
</motion.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>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
|
||||||
{/* Contact Form */}
|
{/* Interactive Contact Form */}
|
||||||
<motion.div
|
<motion.div
|
||||||
initial={{ opacity: 0, x: 30 }}
|
initial={{ opacity: 0, x: 40 }}
|
||||||
animate={isInView ? { opacity: 1, x: 0 } : {}}
|
animate={isInView ? { opacity: 1, x: 0 } : {}}
|
||||||
transition={{ duration: 0.6, delay: 0.2 }}
|
transition={{ duration: 0.7, delay: 0.1 }}
|
||||||
className="relative"
|
|
||||||
>
|
>
|
||||||
<div className="p-8 rounded-3xl glass border border-border/50 relative overflow-hidden">
|
<div className="p-10 rounded-3xl border backdrop-blur-2xl relative overflow-hidden">
|
||||||
{/* Decorative gradient */}
|
{/* Subtle moving gradient */}
|
||||||
<div className="absolute -top-20 -right-20 w-40 h-40 rounded-full gradient-primary opacity-20 blur-3xl" />
|
<div className="absolute -top-32 -right-32 w-64 h-64 bg-primary/10 rounded-full blur-3xl" />
|
||||||
|
|
||||||
{isSuccess ? (
|
{isSuccess ? (
|
||||||
<motion.div
|
<motion.div
|
||||||
initial={{ opacity: 0, scale: 0.8 }}
|
initial={{ opacity: 0, scale: 0.9 }}
|
||||||
animate={{ opacity: 1, scale: 1 }}
|
animate={{ opacity: 1, scale: 1 }}
|
||||||
className="text-center py-12"
|
className="text-center py-16"
|
||||||
>
|
>
|
||||||
<motion.div
|
<CheckCircle className="w-24 h-24 text-primary mx-auto mb-6 neon-text-glow" />
|
||||||
initial={{ scale: 0 }}
|
<h3 className="text-3xl font-bold mb-3">
|
||||||
animate={{ scale: 1 }}
|
Message Sent Successfully!
|
||||||
transition={{
|
</h3>
|
||||||
type: "spring",
|
<p className="text-muted-foreground text-lg">
|
||||||
damping: 15,
|
Thank you! We'll get back to you very soon.
|
||||||
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>
|
</p>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
) : (
|
) : (
|
||||||
<form
|
<form
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
className="space-y-5 relative z-10"
|
className="space-y-6 relative z-10"
|
||||||
>
|
>
|
||||||
<div className="grid sm:grid-cols-2 gap-5">
|
<div className="grid sm:grid-cols-2 gap-6">
|
||||||
<motion.div
|
<Input
|
||||||
initial={{ opacity: 0, y: 10 }}
|
name="name"
|
||||||
animate={isInView ? { opacity: 1, y: 0 } : {}}
|
placeholder="Your Name"
|
||||||
transition={{ delay: 0.3 }}
|
value={formData.name}
|
||||||
>
|
onChange={handleChange}
|
||||||
<Input
|
required
|
||||||
name="name"
|
className="h-14 focus:border-primary focus:ring-2 focus:ring-primary/30 transition-all text-base"
|
||||||
placeholder="Your Name"
|
/>
|
||||||
value={formData.name}
|
<Input
|
||||||
onChange={handleChange}
|
name="email"
|
||||||
required
|
type="email"
|
||||||
className="glass border-border/50 focus:border-primary focus:neon-glow transition-all h-12"
|
placeholder="Your Email"
|
||||||
/>
|
value={formData.email}
|
||||||
</motion.div>
|
onChange={handleChange}
|
||||||
<motion.div
|
required
|
||||||
initial={{ opacity: 0, y: 10 }}
|
className="h-14 focus:border-primary focus:ring-2 focus:ring-primary/30 transition-all text-base"
|
||||||
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>
|
</div>
|
||||||
|
|
||||||
<motion.div
|
<Input
|
||||||
initial={{ opacity: 0, y: 10 }}
|
name="subject"
|
||||||
animate={isInView ? { opacity: 1, y: 0 } : {}}
|
placeholder="Subject"
|
||||||
transition={{ delay: 0.4 }}
|
value={formData.subject}
|
||||||
>
|
onChange={handleChange}
|
||||||
<Input
|
required
|
||||||
name="subject"
|
className="h-14 focus:border-primary focus:ring-2 focus:ring-primary/30 transition-all text-base"
|
||||||
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
|
<Textarea
|
||||||
initial={{ opacity: 0, y: 10 }}
|
name="message"
|
||||||
animate={isInView ? { opacity: 1, y: 0 } : {}}
|
placeholder="Tell us about your project..."
|
||||||
transition={{ delay: 0.45 }}
|
value={formData.message}
|
||||||
>
|
onChange={handleChange}
|
||||||
<Textarea
|
required
|
||||||
name="message"
|
rows={6}
|
||||||
placeholder="Your Message"
|
className=" focus:border-primary focus:ring-2 focus:ring-primary/30 transition-all resize-none text-base"
|
||||||
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
|
<Button
|
||||||
initial={{ opacity: 0, y: 10 }}
|
type="submit"
|
||||||
animate={isInView ? { opacity: 1, y: 0 } : {}}
|
disabled={isSubmitting}
|
||||||
transition={{ delay: 0.5 }}
|
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"
|
||||||
>
|
>
|
||||||
<Button
|
{isSubmitting ? (
|
||||||
type="submit"
|
<div className="flex items-center gap-3">
|
||||||
disabled={isSubmitting}
|
<div className="w-5 h-5 border-2 border-white/30 border-t-white rounded-full animate-spin" />
|
||||||
className="w-full bg-primary text-primary-foreground font-semibold py-6 rounded-full neon-glow hover:neon-glow-strong transition-all group"
|
Sending...
|
||||||
>
|
</div>
|
||||||
{isSubmitting ? (
|
) : (
|
||||||
<motion.div
|
<div className="flex items-center justify-center gap-3">
|
||||||
animate={{ rotate: 360 }}
|
Send Message
|
||||||
transition={{
|
<Send className="w-5 h-5 group-hover:translate-x-1 transition-transform" />
|
||||||
duration: 1,
|
</div>
|
||||||
repeat: Infinity,
|
)}
|
||||||
ease: "linear",
|
</Button>
|
||||||
}}
|
|
||||||
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>
|
</form>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import {
|
|||||||
AccordionTrigger,
|
AccordionTrigger,
|
||||||
} from "@/components/ui/accordion";
|
} from "@/components/ui/accordion";
|
||||||
import { motion, useInView } from "framer-motion";
|
import { motion, useInView } from "framer-motion";
|
||||||
|
import { ArrowRight, Mail } from "lucide-react";
|
||||||
import { useRef } from "react";
|
import { useRef } from "react";
|
||||||
|
|
||||||
const faqs = [
|
const faqs = [
|
||||||
@@ -28,21 +29,11 @@ const faqs = [
|
|||||||
answer:
|
answer:
|
||||||
"Yes! We offer comprehensive maintenance packages that include bug fixes, security updates, performance optimization, and feature enhancements. Our support team is available to ensure your application runs smoothly 24/7.",
|
"Yes! We offer comprehensive maintenance packages that include bug fixes, security updates, performance optimization, and feature enhancements. Our support team is available to ensure your application runs smoothly 24/7.",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
question: "What technologies do you work with?",
|
|
||||||
answer:
|
|
||||||
"Our tech stack includes React, Next.js, Node.js, Python, TypeScript, AWS, Google Cloud, and more. We stay current with industry trends and select the best technologies for each project's specific requirements.",
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
question: "How do you handle project pricing?",
|
question: "How do you handle project pricing?",
|
||||||
answer:
|
answer:
|
||||||
"We offer flexible pricing models including fixed-price projects, time & materials, and dedicated team arrangements. After understanding your requirements, we provide transparent quotes with no hidden costs. Contact us for a free consultation and estimate.",
|
"We offer flexible pricing models including fixed-price projects, time & materials, and dedicated team arrangements. After understanding your requirements, we provide transparent quotes with no hidden costs. Contact us for a free consultation and estimate.",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
question: "Can you work with our existing team?",
|
|
||||||
answer:
|
|
||||||
"Absolutely! We frequently collaborate with in-house teams, providing additional expertise and resources. Whether you need staff augmentation, specialized skills, or full project delivery, we adapt to your working style and processes.",
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
question: "What industries do you serve?",
|
question: "What industries do you serve?",
|
||||||
answer:
|
answer:
|
||||||
@@ -55,64 +46,94 @@ export default function FAQSection() {
|
|||||||
const isInView = useInView(ref, { once: true, margin: "-100px" });
|
const isInView = useInView(ref, { once: true, margin: "-100px" });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section id="faq" ref={ref} className="py-24 relative overflow-hidden">
|
<section
|
||||||
{/* Background decoration */}
|
id="faq"
|
||||||
<div className="absolute inset-0 opacity-30">
|
ref={ref}
|
||||||
<div className="absolute top-1/4 right-0 w-96 h-96 bg-primary/10 rounded-full blur-[150px]" />
|
className="pb-20 relative overflow-hidden bg-background"
|
||||||
<div className="absolute bottom-1/4 left-0 w-80 h-80 bg-neon-purple/10 rounded-full blur-[120px]" />
|
>
|
||||||
</div>
|
{/* Decorative gradients */}
|
||||||
|
<div className="absolute top-0 right-0 w-[500px] h-[500px] bg-primary/5 rounded-full blur-3xl -z-10" />
|
||||||
|
<div className="absolute bottom-0 left-0 w-[500px] h-[500px] bg-secondary/5 rounded-full blur-3xl -z-10" />
|
||||||
|
|
||||||
<div className="container mx-auto px-4 relative z-10">
|
<div className="container mx-auto px-4 relative z-10">
|
||||||
{/* Section Header */}
|
<div className="grid grid-cols-1 lg:grid-cols-[1fr,1.5fr] gap-12 lg:gap-20 items-start">
|
||||||
<motion.div
|
{/* Left Column - Header and CTA */}
|
||||||
initial={{ opacity: 0, y: 20 }}
|
<motion.div
|
||||||
animate={isInView ? { opacity: 1, y: 0 } : {}}
|
initial={{ opacity: 0, x: -30 }}
|
||||||
transition={{ duration: 0.6 }}
|
animate={isInView ? { opacity: 1, x: 0 } : {}}
|
||||||
className="text-center mb-16"
|
transition={{ duration: 0.6 }}
|
||||||
>
|
className="flex flex-col gap-8 lg:sticky lg:top-24"
|
||||||
<span className="inline-block px-4 py-1.5 rounded-full glass text-sm font-medium text-primary mb-4">
|
>
|
||||||
Got Questions?
|
<div>
|
||||||
</span>
|
<span className="inline-flex px-4 py-1.5 rounded-full text-xs font-semibold tracking-wider uppercase bg-primary/10 text-primary mb-4">
|
||||||
<h2 className="text-3xl md:text-4xl lg:text-5xl font-bold mb-4">
|
Got Questions?
|
||||||
Frequently Asked{" "}
|
</span>
|
||||||
<span className="text-primary neon-text-glow">Questions</span>
|
<h2 className="text-4xl md:text-5xl font-bold tracking-tight text-foreground mb-4 leading-[1.15]">
|
||||||
</h2>
|
Frequently Asked <br />
|
||||||
<p className="text-muted-foreground max-w-2xl mx-auto text-lg">
|
<span className="text-primary">Questions</span>
|
||||||
Everything you need to know about working with TechZaa. Can't find
|
</h2>
|
||||||
what you're looking for? Reach out to our team.
|
<p className="text-muted-foreground text-lg leading-relaxed max-w-md">
|
||||||
</p>
|
Everything you need to know about working with TechZaa. Can't
|
||||||
</motion.div>
|
find what you're looking for? Reach out to our team.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* FAQ Accordion */}
|
{/* Support CTA Card */}
|
||||||
<motion.div
|
<div className="p-6 rounded-2xl border border-border/50 bg-card/40 backdrop-blur-sm flex flex-col gap-5 max-w-md shadow-sm">
|
||||||
initial={{ opacity: 0, y: 30 }}
|
<div className="flex items-center gap-4">
|
||||||
animate={isInView ? { opacity: 1, y: 0 } : {}}
|
<div className="w-10 h-10 rounded-full bg-primary/10 flex items-center justify-center text-primary">
|
||||||
transition={{ duration: 0.6, delay: 0.2 }}
|
<Mail className="w-5 h-5" />
|
||||||
className="max-w-3xl mx-auto"
|
</div>
|
||||||
>
|
<div>
|
||||||
<Accordion type="single" collapsible className="space-y-4">
|
<h4 className="font-semibold text-foreground text-sm">
|
||||||
{faqs.map((faq, index) => (
|
Still have questions?
|
||||||
<motion.div
|
</h4>
|
||||||
key={index}
|
<p className="text-muted-foreground text-xs">
|
||||||
initial={{ opacity: 0, y: 20 }}
|
We're here to help you out with any queries.
|
||||||
animate={isInView ? { opacity: 1, y: 0 } : {}}
|
</p>
|
||||||
transition={{ duration: 0.4, delay: 0.1 * index }}
|
</div>
|
||||||
|
</div>
|
||||||
|
<a
|
||||||
|
href="mailto:support@techzaa.com"
|
||||||
|
className="inline-flex items-center justify-center gap-2 text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 bg-primary text-primary-foreground shadow hover:bg-primary/90 h-10 px-4 py-2 rounded-xl w-full group"
|
||||||
>
|
>
|
||||||
<AccordionItem
|
Contact Support
|
||||||
value={`item-${index}`}
|
<ArrowRight className="w-4 h-4 transition-transform group-hover:translate-x-1" />
|
||||||
className="glass border border-border/50 rounded-xl px-6 overflow-hidden data-[state=open]:border-primary/50 transition-colors"
|
</a>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
{/* Right Column - Accordion */}
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, y: 30 }}
|
||||||
|
animate={isInView ? { opacity: 1, y: 0 } : {}}
|
||||||
|
transition={{ duration: 0.6, delay: 0.2 }}
|
||||||
|
className="w-full"
|
||||||
|
>
|
||||||
|
<Accordion type="single" collapsible className="space-y-4">
|
||||||
|
{faqs.map((faq, index) => (
|
||||||
|
<motion.div
|
||||||
|
key={index}
|
||||||
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
animate={isInView ? { opacity: 1, y: 0 } : {}}
|
||||||
|
transition={{ duration: 0.4, delay: 0.06 * index }}
|
||||||
>
|
>
|
||||||
<AccordionTrigger className="text-left hover:no-underline py-5 text-base md:text-lg font-medium hover:text-primary transition-colors">
|
<AccordionItem
|
||||||
{faq.question}
|
value={`item-${index}`}
|
||||||
</AccordionTrigger>
|
className="bg-card/40 border border-border/40 rounded-2xl px-6 py-1 overflow-hidden data-[state=open]:border-primary/50 data-[state=open]:shadow-md transition-all duration-300"
|
||||||
<AccordionContent className="text-muted-foreground pb-5 text-sm md:text-base leading-relaxed">
|
>
|
||||||
{faq.answer}
|
<AccordionTrigger className="text-left hover:no-underline py-5 text-base md:text-lg font-medium text-foreground hover:text-primary transition-colors">
|
||||||
</AccordionContent>
|
{faq.question}
|
||||||
</AccordionItem>
|
</AccordionTrigger>
|
||||||
</motion.div>
|
<AccordionContent className="text-muted-foreground pt-1 pb-5 text-sm md:text-base leading-relaxed">
|
||||||
))}
|
{faq.answer}
|
||||||
</Accordion>
|
</AccordionContent>
|
||||||
</motion.div>
|
</AccordionItem>
|
||||||
|
</motion.div>
|
||||||
|
))}
|
||||||
|
</Accordion>
|
||||||
|
</motion.div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ export default function HeroSection() {
|
|||||||
<section
|
<section
|
||||||
id="home"
|
id="home"
|
||||||
ref={containerRef}
|
ref={containerRef}
|
||||||
className="relative min-h-screen flex items-center justify-center overflow-hidden pt-20"
|
className="relative min-h-screen flex items-center justify-center overflow-hidden pt-10"
|
||||||
>
|
>
|
||||||
{/* Animated gradient background */}
|
{/* Animated gradient background */}
|
||||||
<div className="absolute inset-0 gradient-primary-animated opacity-10" />
|
<div className="absolute inset-0 gradient-primary-animated opacity-10" />
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ export default function Navbar() {
|
|||||||
>
|
>
|
||||||
<div className="container mx-auto px-4 flex items-center justify-between">
|
<div className="container mx-auto px-4 flex items-center justify-between">
|
||||||
{/* Logo */}
|
{/* Logo */}
|
||||||
<Link to="#home" className="flex items-center gap-2">
|
<Link to="/" className="flex items-center gap-2">
|
||||||
<img src={logo} alt="TechZaa" className="h-16 w-auto" />
|
<img src={logo} alt="TechZaa" className="h-16 w-auto" />
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
|
|||||||
@@ -1,43 +1,43 @@
|
|||||||
import { useRef } from 'react';
|
import { Button } from "@/components/ui/button";
|
||||||
import { motion, useInView } from 'framer-motion';
|
import { useProjects } from "@/hooks/queires/useProjects";
|
||||||
import { ArrowRight, ExternalLink } from 'lucide-react';
|
import { motion, useInView } from "framer-motion";
|
||||||
import { Link } from 'react-router-dom';
|
import { ArrowRight, ExternalLink } from "lucide-react";
|
||||||
import { Button } from '@/components/ui/button';
|
import { useRef, useState } from "react";
|
||||||
import { useProjects } from '@/hooks/queires/useProjects';
|
import { Link } from "react-router-dom";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const gradientColors = [
|
const gradientColors = [
|
||||||
"from-neon-blue/80",
|
"from-neon-blue/90",
|
||||||
"from-neon-purple/80",
|
"from-neon-purple/90",
|
||||||
"from-neon-green/80",
|
"from-neon-green/90",
|
||||||
"from-neon-pink/80"
|
"from-neon-pink/90",
|
||||||
];
|
];
|
||||||
|
|
||||||
export default function ProjectsSection() {
|
export default function ProjectsSection() {
|
||||||
|
|
||||||
const { data: projectsData } = useProjects({
|
const { data: projectsData } = useProjects({
|
||||||
fields: "category, title, image",
|
fields: "category, title, image, liveUrl",
|
||||||
limit: 6
|
limit: 6,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const projects = projectsData?.data.data.result || [];
|
||||||
const projects = projectsData?.data.data.result;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const ref = useRef<HTMLElement>(null);
|
const ref = useRef<HTMLElement>(null);
|
||||||
const isInView = useInView(ref, { once: true, margin: '-100px' });
|
const isInView = useInView(ref, { once: true, margin: "-100px" });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section id="projects" ref={ref} className="py-24 relative overflow-hidden bg-secondary/30">
|
<section
|
||||||
{/* Background pattern */}
|
id="projects"
|
||||||
|
ref={ref}
|
||||||
|
className="py-24 relative overflow-hidden bg-secondary/30"
|
||||||
|
>
|
||||||
|
{/* Background Pattern */}
|
||||||
<div className="absolute inset-0 opacity-5">
|
<div className="absolute inset-0 opacity-5">
|
||||||
<div className="absolute inset-0" style={{
|
<div
|
||||||
backgroundImage: `radial-gradient(circle at 1px 1px, currentColor 1px, transparent 0)`,
|
className="absolute inset-0"
|
||||||
backgroundSize: '40px 40px',
|
style={{
|
||||||
}} />
|
backgroundImage: `radial-gradient(circle at 1px 1px, currentColor 1px, transparent 0)`,
|
||||||
|
backgroundSize: "40px 40px",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="container mx-auto px-4 relative z-10">
|
<div className="container mx-auto px-4 relative z-10">
|
||||||
@@ -45,84 +45,52 @@ export default function ProjectsSection() {
|
|||||||
<motion.div
|
<motion.div
|
||||||
initial={{ opacity: 0, y: 20 }}
|
initial={{ opacity: 0, y: 20 }}
|
||||||
animate={isInView ? { opacity: 1, y: 0 } : {}}
|
animate={isInView ? { opacity: 1, y: 0 } : {}}
|
||||||
transition={{ duration: 0.6 }}
|
transition={{ duration: 0.7 }}
|
||||||
className="text-center mb-16"
|
className="text-center mb-20"
|
||||||
>
|
>
|
||||||
<span className="inline-block px-4 py-1.5 rounded-full glass text-sm font-medium text-primary mb-4">
|
<span className="inline-block px-5 py-2 rounded-full glass text-sm font-medium text-primary mb-4 tracking-widest">
|
||||||
Our Portfolio
|
OUR PORTFOLIO
|
||||||
</span>
|
</span>
|
||||||
<h2 className="text-3xl md:text-4xl lg:text-5xl font-bold mb-4">
|
<h2 className="text-4xl md:text-5xl lg:text-6xl font-bold mb-6">
|
||||||
Our <span className="text-primary neon-text-glow">Projects</span>
|
Featured{" "}
|
||||||
|
<span className="text-primary neon-text-glow">Projects</span>
|
||||||
</h2>
|
</h2>
|
||||||
<p className="text-muted-foreground max-w-2xl mx-auto text-lg">
|
<p className="text-muted-foreground max-w-2xl mx-auto text-lg">
|
||||||
Explore our latest work and see how we've helped businesses
|
Crafted with passion. Delivered with excellence.
|
||||||
transform their digital presence.
|
|
||||||
</p>
|
</p>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
|
||||||
{/* Projects Grid */}
|
{/* Projects Grid */}
|
||||||
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6 mb-12">
|
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-8 mb-16">
|
||||||
{projects?.map((project, index) => {
|
{projects.map((project, index) => {
|
||||||
const color = gradientColors[index % gradientColors.length];
|
const color = gradientColors[index % gradientColors.length];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<motion.div
|
<ProjectCard
|
||||||
key={project._id}
|
key={project._id}
|
||||||
initial={{ opacity: 0, y: 30 }}
|
project={project}
|
||||||
animate={isInView ? { opacity: 1, y: 0 } : {}}
|
color={color}
|
||||||
transition={{ duration: 0.5, delay: index * 0.1 }}
|
index={index}
|
||||||
whileHover={{ y: -8 }}
|
isInView={isInView}
|
||||||
className="group relative rounded-2xl overflow-hidden cursor-pointer"
|
/>
|
||||||
>
|
|
||||||
{/* Image */}
|
|
||||||
<div className="aspect-[4/3] overflow-hidden">
|
|
||||||
<img
|
|
||||||
src={project.image}
|
|
||||||
alt={project.title}
|
|
||||||
className="w-full h-full object-cover transition-transform duration-500 group-hover:scale-110"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Overlay */}
|
|
||||||
<div
|
|
||||||
className={`absolute inset-0 bg-gradient-to-t ${color} to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300`}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* Content */}
|
|
||||||
<div className="absolute inset-0 flex flex-col justify-end p-6">
|
|
||||||
<div className="transform translate-y-4 opacity-0 group-hover:translate-y-0 group-hover:opacity-100 transition-all duration-300">
|
|
||||||
<span className="inline-block px-3 py-1 rounded-full bg-background/20 backdrop-blur-sm text-white text-xs font-medium mb-2">
|
|
||||||
{project.category}
|
|
||||||
</span>
|
|
||||||
<h3 className="text-xl font-bold text-white mb-2">{project.title}</h3>
|
|
||||||
<div className="flex items-center gap-2 text-white/80 text-sm">
|
|
||||||
<span>View Project</span>
|
|
||||||
<ExternalLink className="w-4 h-4" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Border glow effect */}
|
|
||||||
<div className="absolute inset-0 rounded-2xl border-2 border-transparent group-hover:border-primary/50 group-hover:neon-glow transition-all duration-300 pointer-events-none" />
|
|
||||||
</motion.div>
|
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* See All Button */}
|
{/* See All Button */}
|
||||||
<motion.div
|
<motion.div
|
||||||
initial={{ opacity: 0, y: 20 }}
|
initial={{ opacity: 0, y: 30 }}
|
||||||
animate={isInView ? { opacity: 1, y: 0 } : {}}
|
animate={isInView ? { opacity: 1, y: 0 } : {}}
|
||||||
transition={{ duration: 0.6, delay: 0.5 }}
|
transition={{ duration: 0.7, delay: 0.3 }}
|
||||||
className="text-center"
|
className="flex justify-center"
|
||||||
>
|
>
|
||||||
<Link to="/projects">
|
<Link to="/projects">
|
||||||
<Button
|
<Button
|
||||||
size="lg"
|
size="lg"
|
||||||
className="bg-primary text-primary-foreground font-semibold px-8 py-6 text-lg rounded-full neon-glow hover:neon-glow-strong transition-all group"
|
className="bg-primary hover:bg-primary/90 text-primary-foreground font-semibold px-10 py-7 text-lg rounded-full neon-glow hover:neon-glow-strong transition-all group flex items-center gap-3"
|
||||||
>
|
>
|
||||||
See All Projects
|
Explore All Projects
|
||||||
<ArrowRight className="ml-2 w-5 h-5 group-hover:translate-x-1 transition-transform" />
|
<ArrowRight className="w-6 h-6 group-hover:translate-x-1 transition-transform" />
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
@@ -130,3 +98,99 @@ export default function ProjectsSection() {
|
|||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function ProjectCard({ project, color, index, isInView }) {
|
||||||
|
const [mousePosition, setMousePosition] = useState({ x: 50, y: 50 });
|
||||||
|
const [isHovered, setIsHovered] = useState(false);
|
||||||
|
|
||||||
|
const handleMouseMove = (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;
|
||||||
|
setMousePosition({ x, y });
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, y: 60, rotateX: 15 }}
|
||||||
|
animate={isInView ? { opacity: 1, y: 0, rotateX: 0 } : {}}
|
||||||
|
transition={{ duration: 0.6, delay: index * 0.08 }}
|
||||||
|
whileHover={{ scale: 1.02 }}
|
||||||
|
className="group relative rounded-3xl overflow-hidden cursor-pointer h-full"
|
||||||
|
onMouseMove={handleMouseMove}
|
||||||
|
onMouseEnter={() => setIsHovered(true)}
|
||||||
|
onMouseLeave={() => {
|
||||||
|
setIsHovered(false);
|
||||||
|
setMousePosition({ x: 50, y: 50 });
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* Main Card Container with 3D Tilt */}
|
||||||
|
<div
|
||||||
|
className="relative h-full rounded-3xl overflow-hidden shadow-2xl transition-transform duration-300"
|
||||||
|
style={{
|
||||||
|
transform: isHovered
|
||||||
|
? `perspective(1000px) rotateX(${(50 - mousePosition.y) * 0.12}deg) rotateY(${(mousePosition.x - 50) * 0.15}deg)`
|
||||||
|
: "perspective(1000px) rotateX(0deg) rotateY(0deg)",
|
||||||
|
transition: isHovered
|
||||||
|
? "transform 0.1s ease-out"
|
||||||
|
: "transform 0.4s ease-out",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* Image Container */}
|
||||||
|
<div className="aspect-[16/13] overflow-hidden relative">
|
||||||
|
<img
|
||||||
|
src={project.image}
|
||||||
|
alt={project.title}
|
||||||
|
className="w-full h-full object-cover transition-transform duration-700 group-hover:scale-110"
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Dynamic Shine Overlay */}
|
||||||
|
<div
|
||||||
|
className="absolute inset-0 opacity-0 group-hover:opacity-30 transition-opacity duration-300 pointer-events-none"
|
||||||
|
style={{
|
||||||
|
background: `radial-gradient(circle at ${mousePosition.x}% ${mousePosition.y}%, rgba(255,255,255,0.8) 0%, transparent 60%)`,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Gradient Overlay */}
|
||||||
|
<div
|
||||||
|
className={`absolute inset-0 bg-gradient-to-t ${color} via-black/40 to-transparent opacity-60 group-hover:opacity-90 transition-all duration-500`}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Content */}
|
||||||
|
<div className="absolute inset-0 flex flex-col justify-end p-8">
|
||||||
|
<div className="space-y-4 transform transition-all duration-500 group-hover:translate-y-0">
|
||||||
|
{/* Category */}
|
||||||
|
<motion.span
|
||||||
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
animate={
|
||||||
|
isHovered ? { opacity: 1, y: 0 } : { opacity: 0.7, y: 10 }
|
||||||
|
}
|
||||||
|
className="inline-block px-4 py-1.5 rounded-full bg-white/10 backdrop-blur-md text-white text-xs font-medium border border-white/20"
|
||||||
|
>
|
||||||
|
{project.category}
|
||||||
|
</motion.span>
|
||||||
|
|
||||||
|
{/* Title */}
|
||||||
|
<h3 className="text-2xl md:text-3xl font-bold text-white leading-tight tracking-tight">
|
||||||
|
{project.title}
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
{/* View Project Link */}
|
||||||
|
<Link
|
||||||
|
to={project.liveUrl}
|
||||||
|
className="flex items-center gap-3 text-white/80 group-hover:text-white transition-colors"
|
||||||
|
>
|
||||||
|
<span className="font-medium text-sm tracking-wider">live</span>
|
||||||
|
<ExternalLink className="w-5 h-5 transition-transform group-hover:rotate-45" />
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Neon Border Glow */}
|
||||||
|
<div className="absolute inset-0 rounded-3xl border-2 border-transparent group-hover:border-primary/60 transition-all duration-500 pointer-events-none neon-glow" />
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ export default function ServicesSection() {
|
|||||||
const isInView = useInView(ref, { once: true, margin: "-100px" });
|
const isInView = useInView(ref, { once: true, margin: "-100px" });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section id="services" ref={ref} className="py-24 relative overflow-hidden">
|
<section id="services" ref={ref} className="py-20 relative overflow-hidden">
|
||||||
{/* Background decoration */}
|
{/* Background decoration */}
|
||||||
<div className="absolute inset-0 opacity-30">
|
<div className="absolute inset-0 opacity-30">
|
||||||
<div className="absolute bottom-1/2 left-0 w-96 h-96 bg-primary rounded-full blur-[200px]" />
|
<div className="absolute bottom-1/2 left-0 w-96 h-96 bg-primary rounded-full blur-[200px]" />
|
||||||
|
|||||||
@@ -1,32 +1,22 @@
|
|||||||
import { motion, useInView } from "framer-motion";
|
import { motion, useInView } from "framer-motion";
|
||||||
import { Github, Linkedin, Twitter } from "lucide-react";
|
import { Github, Linkedin, Twitter } from "lucide-react";
|
||||||
import { useRef } from "react";
|
import { useRef } from "react";
|
||||||
// Import Swiper React components and modules
|
|
||||||
import { Autoplay, Pagination } from "swiper/modules";
|
import { Autoplay, Pagination } from "swiper/modules";
|
||||||
import { Swiper, SwiperSlide } from "swiper/react";
|
import { Swiper, SwiperSlide } from "swiper/react";
|
||||||
|
|
||||||
// Import Swiper styles
|
|
||||||
import "swiper/css";
|
|
||||||
import "swiper/css/pagination";
|
|
||||||
import { useTeam } from "@/hooks/queires/useTeam";
|
import { useTeam } from "@/hooks/queires/useTeam";
|
||||||
|
|
||||||
|
|
||||||
export default function TeamSection() {
|
export default function TeamSection() {
|
||||||
|
const { data: teamdata } = useTeam();
|
||||||
const {data: teamdata} = useTeam();
|
|
||||||
|
|
||||||
const team = teamdata?.data.data;
|
const team = teamdata?.data.data;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const ref = useRef<HTMLElement>(null);
|
const ref = useRef<HTMLElement>(null);
|
||||||
const isInView = useInView(ref, { once: true, margin: "-100px" });
|
const isInView = useInView(ref, { once: true, margin: "-100px" });
|
||||||
const shouldScroll = team?.length >= 5;
|
const shouldScroll = team?.length >= 5;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section id="team" ref={ref} className="py-24 relative overflow-hidden">
|
<section id="team" ref={ref} className="pt-20 1relative overflow-hidden">
|
||||||
{/* Background decoration */}
|
{/* Background decoration */}
|
||||||
<div className="absolute inset-0 opacity-30">
|
<div className="absolute inset-0 opacity-30">
|
||||||
<div className="absolute top-0 right-1/4 w-72 h-72 bg-neon-purple/10 rounded-full blur-[120px]" />
|
<div className="absolute top-0 right-1/4 w-72 h-72 bg-neon-purple/10 rounded-full blur-[120px]" />
|
||||||
|
|||||||
@@ -41,11 +41,7 @@ export default function TestimonialsSection() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<section id="testimonials" className="py-24 relative overflow-hidden">
|
<section id="testimonials" className="py-24 relative overflow-hidden">
|
||||||
{/* Background */}
|
|
||||||
<div className="absolute inset-0">
|
|
||||||
<div className="absolute top-1/4 left-1/4 w-96 h-96 bg-primary/10 rounded-full blur-3xl" />
|
|
||||||
<div className="absolute bottom-1/4 right-1/4 w-96 h-96 bg-neon-purple/10 rounded-full blur-3xl" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="container mx-auto px-4 relative z-10">
|
<div className="container mx-auto px-4 relative z-10">
|
||||||
{/* Section Header */}
|
{/* Section Header */}
|
||||||
@@ -76,7 +72,7 @@ export default function TestimonialsSection() {
|
|||||||
variant="outline"
|
variant="outline"
|
||||||
size="icon"
|
size="icon"
|
||||||
onClick={scrollPrev}
|
onClick={scrollPrev}
|
||||||
className="absolute left-0 top-1/2 -translate-y-1/2 -translate-x-4 z-10 rounded-full glass border-primary/30 hover:neon-glow hidden md:flex"
|
className="absolute left-0 top-1/2 -translate-y-1/2 -translate-x-4 z-10 rounded-full glass neon-glow hidden md:flex"
|
||||||
>
|
>
|
||||||
<ChevronLeft className="w-5 h-5" />
|
<ChevronLeft className="w-5 h-5" />
|
||||||
</Button>
|
</Button>
|
||||||
@@ -84,7 +80,7 @@ export default function TestimonialsSection() {
|
|||||||
variant="outline"
|
variant="outline"
|
||||||
size="icon"
|
size="icon"
|
||||||
onClick={scrollNext}
|
onClick={scrollNext}
|
||||||
className="absolute right-0 top-1/2 -translate-y-1/2 translate-x-4 z-10 rounded-full glass border-primary/30 hover:neon-glow hidden md:flex"
|
className="absolute right-0 top-1/2 -translate-y-1/2 translate-x-4 z-10 rounded-full glass neon-glow hidden md:flex"
|
||||||
>
|
>
|
||||||
<ChevronRight className="w-5 h-5" />
|
<ChevronRight className="w-5 h-5" />
|
||||||
</Button>
|
</Button>
|
||||||
@@ -104,11 +100,13 @@ export default function TestimonialsSection() {
|
|||||||
scale: selectedIndex === index ? 1 : 0.9,
|
scale: selectedIndex === index ? 1 : 0.9,
|
||||||
}}
|
}}
|
||||||
transition={{ duration: 0.4 }}
|
transition={{ duration: 0.4 }}
|
||||||
className="glass-strong rounded-3xl p-8 md:p-10 relative"
|
className="glass-strong rounded-3xl p-8 md:p-10 relative overflow-hidden border dark:border-none"
|
||||||
>
|
>
|
||||||
{/* Quote Icon */}
|
{/* Triangular Quote Corner Tab */}
|
||||||
<div className="absolute -top-4 -left-4 w-12 h-12 rounded-full bg-primary flex items-center justify-center neon-glow">
|
<div className="absolute top-0 right-0 w-20 h-20 bg-gradient-to-bl from-primary/10 to-transparent flex items-start justify-end p-3 rounded-bl-[60px] border-l border-b border-primary/20 pointer-events-none">
|
||||||
<Quote className="w-6 h-6 text-primary-foreground" />
|
<div className="pointer-events-auto flex items-center justify-center neon-glow w-9 h-9 rounded-full bg-primary shadow-lg">
|
||||||
|
<Quote className="w-4 h-4 text-primary-foreground" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Stars */}
|
{/* Stars */}
|
||||||
@@ -121,7 +119,7 @@ export default function TestimonialsSection() {
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Quote */}
|
{/* review */}
|
||||||
<p className="text-lg md:text-xl text-foreground/90 mb-8 leading-relaxed">
|
<p className="text-lg md:text-xl text-foreground/90 mb-8 leading-relaxed">
|
||||||
"{testimonial.review}"
|
"{testimonial.review}"
|
||||||
</p>
|
</p>
|
||||||
@@ -153,7 +151,7 @@ export default function TestimonialsSection() {
|
|||||||
{testimonials?.map((_, index) => (
|
{testimonials?.map((_, index) => (
|
||||||
<button
|
<button
|
||||||
key={index}
|
key={index}
|
||||||
onClick={() => emblaApi?.scrollTo(index)}
|
onClick={() => (emblaApi) => emblaApi?.scrollTo(index)}
|
||||||
className={`w-2 h-2 rounded-full transition-all duration-300 ${
|
className={`w-2 h-2 rounded-full transition-all duration-300 ${
|
||||||
selectedIndex === index
|
selectedIndex === index
|
||||||
? "w-8 bg-primary neon-glow"
|
? "w-8 bg-primary neon-glow"
|
||||||
|
|||||||
+1
-1
@@ -176,7 +176,7 @@
|
|||||||
background: hsl(var(--glass-bg));
|
background: hsl(var(--glass-bg));
|
||||||
backdrop-filter: blur(30px);
|
backdrop-filter: blur(30px);
|
||||||
-webkit-backdrop-filter: blur(30px);
|
-webkit-backdrop-filter: blur(30px);
|
||||||
border: 1px solid hsl(var(--glass-border));
|
/* border: 1px solid hsl(var(--glass-border)); */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Gradient backgrounds */
|
/* Gradient backgrounds */
|
||||||
|
|||||||
+1
-1
@@ -19,7 +19,7 @@ const Index = () => {
|
|||||||
<TeamSection />
|
<TeamSection />
|
||||||
<AboutSection />
|
<AboutSection />
|
||||||
<TestimonialsSection />
|
<TestimonialsSection />
|
||||||
<BlogSection />
|
{/* <BlogSection /> */}
|
||||||
<FAQSection />
|
<FAQSection />
|
||||||
<ContactSection />
|
<ContactSection />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
"files": [],
|
"files": [],
|
||||||
"references": [{ "path": "./tsconfig.app.json" }, { "path": "./tsconfig.node.json" }],
|
"references": [{ "path": "./tsconfig.app.json" }, { "path": "./tsconfig.node.json" }],
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"baseUrl": ".",
|
|
||||||
"paths": {
|
"paths": {
|
||||||
"@/*": ["./src/*"]
|
"@/*": ["./src/*"]
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user