feat:added the privacy page with clean ui

This commit is contained in:
sanjidaRimi023
2026-04-19 21:58:53 +06:00
parent e5e7089645
commit a11da78a42
9 changed files with 354 additions and 122 deletions
+11 -6
View File
@@ -1,17 +1,19 @@
import { Toaster } from "@/components/ui/toaster";
import { Toaster as Sonner } from "@/components/ui/sonner";
import { Toaster } from "@/components/ui/toaster";
import { TooltipProvider } from "@/components/ui/tooltip";
import { BrowserRouter, Routes, Route, useLocation } from "react-router-dom";
import { ThemeProvider } from "@/contexts/ThemeContext";
import { AnimatePresence } from "framer-motion";
import Index from "./pages/Index";
import Projects from "./pages/Projects";
import ProjectDetails from "./pages/ProjectDetails";
import { BrowserRouter, Route, Routes, useLocation } from "react-router-dom";
import Footer from "./components/Footer";
import Navbar from "./components/Navbar";
import Blog from "./pages/Blog";
import BlogArticle from "./pages/BlogArticle";
import Index from "./pages/Index";
import NotFound from "./pages/NotFound";
import ProjectDetails from "./pages/ProjectDetails";
import Projects from "./pages/Projects";
import { QueryProvider } from "./provider/QueryProvider";
import { PrivacyPolicy } from "./pages/PrivacyPolicy";
function AnimatedRoutes() {
const location = useLocation();
@@ -26,6 +28,7 @@ function AnimatedRoutes() {
<Route path="/blog/:id" element={<BlogArticle />} />
{/* ADD ALL CUSTOM ROUTES ABOVE THE CATCH-ALL "*" ROUTE */}
<Route path="*" element={<NotFound />} />
<Route path="/privacy" element={<PrivacyPolicy />} />
</Routes>
</AnimatePresence>
);
@@ -38,7 +41,9 @@ const App = () => (
<Toaster />
<Sonner />
<BrowserRouter>
<Navbar />
<AnimatedRoutes />
<Footer />
</BrowserRouter>
</TooltipProvider>
</ThemeProvider>
+52 -31
View File
@@ -1,15 +1,23 @@
import { useRef, useEffect, useState } from 'react';
import { motion, useInView } from 'framer-motion';
import { Zap, Users, Rocket, Award } from 'lucide-react';
import { motion, useInView } from "framer-motion";
import { Award, Rocket, Users, Zap } from "lucide-react";
import { useEffect, useRef, useState } from "react";
const stats = [
{ icon: Zap, value: 10, suffix: '+', label: 'Years Experience' },
{ icon: Rocket, value: 500, suffix: '+', label: 'Projects Completed' },
{ icon: Users, value: 200, suffix: '+', label: 'Happy Clients' },
{ icon: Award, value: 50, suffix: '+', label: 'Awards Won' },
{ icon: Zap, value: 10, suffix: "+", label: "Years Experience" },
{ icon: Rocket, value: 500, suffix: "+", label: "Projects Completed" },
{ icon: Users, value: 200, suffix: "+", label: "Happy Clients" },
{ icon: Award, value: 50, suffix: "+", label: "Awards Won" },
];
function AnimatedCounter({ value, suffix, isInView }: { value: number; suffix: string; isInView: boolean }) {
function AnimatedCounter({
value,
suffix,
isInView,
}: {
value: number;
suffix: string;
isInView: boolean;
}) {
const [count, setCount] = useState(0);
useEffect(() => {
@@ -34,17 +42,22 @@ function AnimatedCounter({ value, suffix, isInView }: { value: number; suffix: s
return (
<span className="text-4xl md:text-5xl font-bold text-primary neon-text-glow">
{count}{suffix}
{count}
{suffix}
</span>
);
}
export default function AboutSection() {
const ref = useRef<HTMLElement>(null);
const isInView = useInView(ref, { once: true, margin: '-100px' });
const isInView = useInView(ref, { once: true, margin: "-100px" });
return (
<section id="about" ref={ref} className="py-24 relative overflow-hidden bg-secondary/30">
<section
id="about"
ref={ref}
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]" />
@@ -66,33 +79,35 @@ export default function AboutSection() {
</h2>
<div className="space-y-4 text-muted-foreground text-lg">
<p>
Founded with a passion for innovation, TechZaa is a leading technology
company dedicated to transforming businesses through cutting-edge
digital solutions.
Founded with a passion for innovation, TechZaa is a leading
technology company dedicated to transforming businesses through
cutting-edge digital solutions.
</p>
<p>
Our team of expert developers, designers, and strategists work
collaboratively to deliver exceptional results that exceed expectations.
We believe in the power of technology to solve complex problems and
create meaningful impact.
Our team of expert developers, designers, and strategists work
collaboratively to deliver exceptional results that exceed
expectations. We believe in the power of technology to solve
complex problems and create meaningful impact.
</p>
<p>
From startups to enterprises, we've helped hundreds of clients
achieve their digital transformation goals with our innovative
From startups to enterprises, we've helped hundreds of clients
achieve their digital transformation goals with our innovative
approach and commitment to excellence.
</p>
</div>
{/* Values */}
<div className="mt-8 flex flex-wrap gap-3">
{['Innovation', 'Quality', 'Integrity', 'Excellence'].map((value) => (
<span
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"
>
{value}
</span>
))}
{["Innovation", "Quality", "Integrity", "Excellence"].map(
(value) => (
<span
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"
>
{value}
</span>
),
)}
</div>
</motion.div>
@@ -110,7 +125,7 @@ export default function AboutSection() {
animate={isInView ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.5, delay: 0.3 + index * 0.1 }}
whileHover={{ y: -5, scale: 1.02 }}
className="p-6 rounded-2xl glass border border-border/50 hover:border-primary/50 transition-all text-center group"
className="p-6 rounded-2xl glass hover:border-primary/50 transition-all text-center group"
>
{/* 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">
@@ -118,10 +133,16 @@ export default function AboutSection() {
</div>
{/* Counter */}
<AnimatedCounter value={stat.value} suffix={stat.suffix} isInView={isInView} />
<AnimatedCounter
value={stat.value}
suffix={stat.suffix}
isInView={isInView}
/>
{/* Label */}
<p className="text-muted-foreground text-sm mt-2">{stat.label}</p>
<p className="text-muted-foreground text-sm mt-2">
{stat.label}
</p>
</motion.div>
))}
</motion.div>
+16 -14
View File
@@ -1,8 +1,8 @@
import { motion } from 'framer-motion';
import { Calendar, Clock, ArrowRight, User } from 'lucide-react';
import { Link } from 'react-router-dom';
import { Button } from '@/components/ui/button';
import { useBlogs } from '@/hooks/queires/useBlogs';
import { Button } from "@/components/ui/button";
import { useBlogs } from "@/hooks/queires/useBlogs";
import { motion } from "framer-motion";
import { ArrowRight, Calendar, Clock, User } from "lucide-react";
import { Link } from "react-router-dom";
const containerVariants = {
hidden: { opacity: 0 },
@@ -19,21 +19,19 @@ const itemVariants = {
visible: {
opacity: 1,
y: 0,
transition: { duration: 0.6, ease: 'easeOut' as const },
transition: { duration: 0.6, ease: "easeOut" as const },
},
};
export default function BlogSection() {
const {data} = useBlogs()
const { data } = useBlogs();
const blogPosts = data?.data.result;
return (
<section id="blog" className="py-24 relative overflow-hidden">
<section id="blog" className=" pt-20 relative overflow-hidden">
{/* Background elements */}
<div className="absolute inset-0 bg-gradient-to-b from-transparent via-primary/5 to-transparent" />
<div className="container mx-auto px-4 relative z-10">
{/* Section Header */}
<motion.div
@@ -50,7 +48,8 @@ export default function BlogSection() {
News & <span className="text-primary neon-text-glow">Blog</span>
</h2>
<p className="text-muted-foreground max-w-2xl mx-auto text-lg">
Stay updated with the latest trends, insights, and thought leadership from our team of experts.
Stay updated with the latest trends, insights, and thought
leadership from our team of experts.
</p>
</motion.div>
@@ -98,7 +97,10 @@ export default function BlogSection() {
</span>
<span className="flex items-center gap-1">
<Calendar className="w-3 h-3" />
{new Date(post.date).toLocaleDateString('en-US', { month: 'short', day: 'numeric' })}
{new Date(post.date).toLocaleDateString("en-US", {
month: "short",
day: "numeric",
})}
</span>
<span className="flex items-center gap-1">
<Clock className="w-3 h-3" />
@@ -130,7 +132,7 @@ export default function BlogSection() {
<Link to="/blog">
<Button
variant="outline"
className="rounded-full px-8 py-6 glass border-primary/30 hover:neon-glow group"
className="font-semibold px-8 py-6 text-lg rounded-full border-primary bg-primary/10 transition-all"
>
View All Articles
<ArrowRight className="w-4 h-4 ml-2 transition-transform group-hover:translate-x-1" />
+2 -34
View File
@@ -50,7 +50,7 @@ export default function ContactSection() {
};
return (
<section id="contact" ref={ref} className="py-24 relative overflow-hidden">
<section id="contact" ref={ref} className="relative overflow-hidden pb-24">
{/* 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]" />
@@ -65,7 +65,7 @@ export default function ContactSection() {
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">
<span className="inline-block px-4 py-1.5 rounded-full 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">
@@ -116,38 +116,6 @@ export default function ContactSection() {
</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 */}
+2 -2
View File
@@ -30,7 +30,7 @@ const socials = [
export default function Footer() {
return (
<footer className="relative overflow-hidden bg-secondary/50 pt-20 pb-8">
<footer className="relative overflow-hidden bg-secondary/50 py-20">
{/* Animated gradient divider */}
<div className="absolute top-0 left-0 right-0 h-1 gradient-primary-animated" />
@@ -191,7 +191,7 @@ export default function Footer() {
© {new Date().getFullYear()} TechZaa. All rights reserved.
</p>
<div className="flex items-center gap-6 text-sm text-muted-foreground">
<a href="#" className="hover:text-primary transition-colors">
<a href="/privacy" className="hover:text-primary transition-colors">
Privacy Policy
</a>
<a href="#" className="hover:text-primary transition-colors">
+24 -21
View File
@@ -1,7 +1,7 @@
import { useEffect, useRef } from 'react';
import { motion } from 'framer-motion';
import { ArrowRight, ChevronDown } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Button } from "@/components/ui/button";
import { motion } from "framer-motion";
import { ArrowRight, ChevronDown } from "lucide-react";
import { useEffect, useRef } from "react";
export default function HeroSection() {
const containerRef = useRef<HTMLDivElement>(null);
@@ -14,13 +14,13 @@ export default function HeroSection() {
const { innerWidth, innerHeight } = window;
const x = (clientX / innerWidth - 0.5) * 20;
const y = (clientY / innerHeight - 0.5) * 20;
containerRef.current.style.setProperty('--mouse-x', `${x}px`);
containerRef.current.style.setProperty('--mouse-y', `${y}px`);
containerRef.current.style.setProperty("--mouse-x", `${x}px`);
containerRef.current.style.setProperty("--mouse-y", `${y}px`);
};
window.addEventListener('mousemove', handleMouseMove);
return () => window.removeEventListener('mousemove', handleMouseMove);
window.addEventListener("mousemove", handleMouseMove);
return () => window.removeEventListener("mousemove", handleMouseMove);
}, []);
return (
@@ -31,7 +31,7 @@ export default function HeroSection() {
>
{/* Animated gradient background */}
<div className="absolute inset-0 gradient-primary-animated opacity-10" />
{/* Particle dots */}
<div className="absolute inset-0 overflow-hidden">
{[...Array(50)].map((_, i) => (
@@ -59,29 +59,32 @@ export default function HeroSection() {
<motion.div
className="absolute top-1/4 left-[10%] w-32 h-32 border-2 border-primary/30 rounded-full"
style={{
transform: 'translate(calc(var(--mouse-x, 0) * -1), calc(var(--mouse-y, 0) * -1))',
transform:
"translate(calc(var(--mouse-x, 0) * -1), calc(var(--mouse-y, 0) * -1))",
}}
animate={{ rotate: 360 }}
transition={{ duration: 20, repeat: Infinity, ease: 'linear' }}
transition={{ duration: 20, repeat: Infinity, ease: "linear" }}
/>
<motion.div
className="absolute bottom-1/4 right-[15%] w-24 h-24 border-2 border-neon-purple/30 rotate-45"
style={{
transform: 'translate(calc(var(--mouse-x, 0) * 0.5), calc(var(--mouse-y, 0) * 0.5)) rotate(45deg)',
transform:
"translate(calc(var(--mouse-x, 0) * 0.5), calc(var(--mouse-y, 0) * 0.5)) rotate(45deg)",
}}
animate={{ rotate: [45, 405] }}
transition={{ duration: 25, repeat: Infinity, ease: 'linear' }}
transition={{ duration: 25, repeat: Infinity, ease: "linear" }}
/>
<motion.div
className="absolute top-1/3 right-[25%] w-16 h-16 bg-neon-green/10 rounded-lg"
style={{
transform: 'translate(calc(var(--mouse-x, 0) * 1.5), calc(var(--mouse-y, 0) * 1.5))',
transform:
"translate(calc(var(--mouse-x, 0) * 1.5), calc(var(--mouse-y, 0) * 1.5))",
}}
animate={{
animate={{
y: [-10, 10, -10],
rotate: [0, 180, 360],
}}
transition={{ duration: 8, repeat: Infinity, ease: 'easeInOut' }}
transition={{ duration: 8, repeat: Infinity, ease: "easeInOut" }}
/>
{/* Glowing orbs */}
@@ -135,9 +138,9 @@ export default function HeroSection() {
transition={{ delay: 0.7 }}
className="text-lg md:text-xl text-muted-foreground max-w-2xl mx-auto mb-10"
>
Transforming ideas into powerful digital solutions. We craft innovative
web applications, mobile experiences, and AI-powered systems that drive
growth and redefine possibilities.
Transforming ideas into powerful digital solutions. We craft
innovative web applications, mobile experiences, and AI-powered
systems that drive growth and redefine possibilities.
</motion.p>
{/* CTA Buttons */}
@@ -157,7 +160,7 @@ export default function HeroSection() {
<Button
size="lg"
variant="outline"
className="font-semibold px-8 py-6 text-lg rounded-full glass border-primary/50 hover:border-primary hover:bg-primary/10 transition-all"
className="font-semibold px-8 py-6 text-lg rounded-full border-primary bg-primary/10 transition-all"
>
View Our Work
</Button>
+80
View File
@@ -0,0 +1,80 @@
import {
Cookie,
Database,
Eye,
FileText,
Lock,
Share2,
UserCheck,
} from "lucide-react";
interface PolicySection {
id: string;
title: string;
icon: React.ReactNode;
content: string | string[];
}
export const privacySections: PolicySection[] = [
{
id: "info-collect",
title: "1. Information We Collect",
icon: <Database className="w-5 h-5" />,
content: [
"Personal information (Name, Email, Phone number)",
"Project details you share with us",
"Technical data (IP address, browser type, device info)",
],
},
{
id: "info-use",
title: "2. How We Use Information",
icon: <Eye className="w-5 h-5" />,
content: [
"Provide and manage our services",
"Communicate with you",
"Improve our website and services",
"Ensure security and prevent fraud",
],
},
{
id: "data-sharing",
title: "3. Data Sharing",
icon: <Share2 className="w-5 h-5" />,
content:
"We do not sell your personal data. We may share data with trusted service providers (hosting, analytics) and legal authorities if required by law.",
},
{
id: "security",
title: "4. Data Security",
icon: <Lock className="w-5 h-5" />,
content:
"We implement industry-standard security measures to protect your data from unauthorized access or disclosure.",
},
{
id: "rights",
title: "6. Your Rights",
icon: <UserCheck className="w-5 h-5" />,
content: [
"Access your data",
"Request correction or deletion",
"Withdraw consent",
],
},
];
export const cookieSections: PolicySection[] = [
{
id: "cookie-def",
title: "What Are Cookies?",
icon: <Cookie className="w-5 h-5" />,
content:
"Cookies are small text files stored on your device to improve website functionality and user experience.",
},
{
id: "cookie-types",
title: "Types of Cookies",
icon: <FileText className="w-5 h-5" />,
content: ["Essential Cookies", "Analytics Cookies", "Functional Cookies"],
},
];
+10 -14
View File
@@ -1,21 +1,18 @@
import Navbar from '@/components/Navbar';
import HeroSection from '@/components/HeroSection';
import ServicesSection from '@/components/ServicesSection';
import ProjectsSection from '@/components/ProjectsSection';
import TeamSection from '@/components/TeamSection';
import AboutSection from '@/components/AboutSection';
import TestimonialsSection from '@/components/TestimonialsSection';
import BlogSection from '@/components/BlogSection';
import FAQSection from '@/components/FAQSection';
import ContactSection from '@/components/ContactSection';
import Footer from '@/components/Footer';
import PageTransition from '@/components/PageTransition';
import AboutSection from "@/components/AboutSection";
import BlogSection from "@/components/BlogSection";
import ContactSection from "@/components/ContactSection";
import FAQSection from "@/components/FAQSection";
import HeroSection from "@/components/HeroSection";
import PageTransition from "@/components/PageTransition";
import ProjectsSection from "@/components/ProjectsSection";
import ServicesSection from "@/components/ServicesSection";
import TeamSection from "@/components/TeamSection";
import TestimonialsSection from "@/components/TestimonialsSection";
const Index = () => {
return (
<PageTransition>
<div className="min-h-screen bg-background overflow-x-hidden">
<Navbar />
<HeroSection />
<ServicesSection />
<ProjectsSection />
@@ -25,7 +22,6 @@ const Index = () => {
<BlogSection />
<FAQSection />
<ContactSection />
<Footer />
</div>
</PageTransition>
);
+157
View File
@@ -0,0 +1,157 @@
import { cookieSections, privacySections } from "@/data/privacyData";
import { ChevronRight, Cookie, Shield } from "lucide-react";
import { useState } from "react";
export const PrivacyPolicy: React.FC = () => {
const [activeSection, setActiveSection] = useState("info-collect");
const allSections = [...privacySections, ...cookieSections];
const handleScroll = (id: string) => {
setActiveSection(id);
document
.getElementById(id)
?.scrollIntoView({ behavior: "smooth", block: "start" });
};
return (
<section className="mx-auto w-full container px-4 sm:px-6 lg:px-8 py-24">
{/* HEADER */}
<header className="max-w-3xl mb-12">
<div className="flex items-center gap-4 mb-4">
<div className="p-3 rounded-xl bg-primary/30">
<Shield className="w-6 h-6 " aria-hidden="true" />
</div>
<h1 className="text-3xl sm:text-4xl font-bold">Privacy Policy</h1>
</div>
<p className="text-sm text-muted-foreground mb-3">
Last Updated: April 19, 2026
</p>
<p className="text-base sm:text-lg text-muted-foreground leading-relaxed">
This page explains what data we collect, why we collect it, and how we
handle it.
</p>
</header>
<div className="flex flex-col lg:flex-row gap-8">
{/* SIDEBAR */}
<aside className="lg:w-1/4">
<nav
className="bg-accent/10 border border-primary/10 rounded-2xl p-4 space-y-2 lg:sticky lg:top-24"
aria-label="Privacy policy sections"
>
<p className="text-xs font-semibold uppercase tracking-wide text-muted-foreground mb-2 px-2">
Contents
</p>
{allSections.map((section) => (
<button
key={section.id}
onClick={() => handleScroll(section.id)}
aria-current={activeSection === section.id ? "true" : undefined}
className={`w-full text-left flex items-center justify-between px-3 py-2.5 rounded-lg text-sm transition-all focus:outline-none focus:ring-2 focus:ring-[hsl(var(--accent-neon))] ${
activeSection === section.id
? "bg-[hsl(var(--accent-neon)/0.15)] text-primary"
: "text-muted-foreground hover:bg-[hsl(var(--accent-neon)/0.08)]"
}`}
>
<span className="truncate">{section.title}</span>
<ChevronRight
className="w-4 h-4 opacity-60"
aria-hidden="true"
/>
</button>
))}
</nav>
</aside>
{/* MAIN */}
<main className="lg:w-3/4 space-y-8">
{/* PRIVACY */}
{privacySections.map((section) => (
<section
key={section.id}
id={section.id}
className="bg-accent/10 border border-primary/10 rounded-2xl p-6 sm:p-8 transition hover:neon-glow"
>
<div className="flex items-center gap-3 mb-4">
<div className="p-2 rounded-lg bg-[hsl(var(--accent-neon)/0.2)]">
{section.icon}
</div>
<h2 className="text-lg sm:text-xl font-semibold">
{section.title}
</h2>
</div>
{Array.isArray(section.content) ? (
<ul className="space-y-2 ml-5">
{section.content.map((item, idx) => (
<li key={idx} className="flex gap-2 text-muted-foreground">
<span className="mt-2 w-1.5 h-1.5 bg-secondary rounded-full" />
{item}
</li>
))}
</ul>
) : (
<p className="ml-5 text-muted-foreground leading-relaxed">
{section.content}
</p>
)}
</section>
))}
{/* COOKIES */}
<section className="space-y-6">
<div className="flex items-center gap-3">
<div className="p-3 rounded-xl bg-primary/10">
<Cookie className="w-6 h-6 " />
</div>
<h2 className="text-2xl sm:text-3xl font-bold ">
Cookies Policy
</h2>
</div>
{cookieSections.map((section) => (
<section
key={section.id}
id={section.id}
className="bg-accent/10 border border-primary/10 rounded-2xl p-6 sm:p-8 transition hover:neon-glow"
>
<div className="flex items-center gap-2 mb-3">
{section.icon}
<h3 className="text-lg font-semibold">{section.title}</h3>
</div>
{Array.isArray(section.content) ? (
<ul className="space-y-2 ml-5">
{section.content.map((item, idx) => (
<li
key={idx}
className="flex gap-2 text-muted-foreground"
>
<span className="mt-2 w-1.5 h-1.5 bg-[hsl(var(--accent-neon))] rounded-full" />
{item}
</li>
))}
</ul>
) : (
<p className="ml-5 text-muted-foreground">
{section.content}
</p>
)}
</section>
))}
</section>
{/* FOOTER */}
<footer className="bg-accent/10 border border-primary/10 rounded-2xl p-5 text-sm text-muted-foreground">
You can disable cookies in your browser settings. Continued use of
this site means you accept this policy.
</footer>
</main>
</div>
</section>
);
};