Prepare for GitHub Pages deployment

This commit is contained in:
eshanized
2024-12-25 05:00:53 +05:30
parent 2340d0f691
commit 138d4a9d2b
80 changed files with 7421 additions and 0 deletions

39
src/pages/About.tsx Normal file
View File

@@ -0,0 +1,39 @@
import { motion } from 'framer-motion';
import { Timeline } from '@/components/about/Timeline';
import { TeamSection } from '@/components/about/TeamSection';
import { MissionSection } from '@/components/about/MissionSection';
export default function About() {
return (
<div className="py-12">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
className="text-center mb-12"
>
<h1 className="text-4xl font-bold text-gray-900">About Snigdha OS</h1>
<p className="mt-4 text-lg text-gray-600">
The most advanced penetration testing distribution, made for security professionals.
</p>
</motion.div>
<div className="space-y-16">
<section>
<MissionSection />
</section>
<section>
<h2 className="text-2xl font-bold text-gray-900 mb-8">Our Team Structure</h2>
<TeamSection />
</section>
<section>
<h2 className="text-2xl font-bold text-gray-900 mb-8">Release Timeline</h2>
<Timeline />
</section>
</div>
</div>
</div>
);
}

84
src/pages/Developers.tsx Normal file
View File

@@ -0,0 +1,84 @@
import { useQueries, useQuery } from '@tanstack/react-query';
import { motion } from 'framer-motion';
import { Loader2 } from 'lucide-react';
import { TeamMemberCard } from '@/components/developers/TeamMemberCard';
import { RepoCard } from '@/components/developers/RepoCard';
import { fetchGithubUser, fetchOrgRepos } from '@/lib/github';
import { teamMembers } from '@/data/team';
export default function Developers() {
const queries = useQueries({
queries: teamMembers.map(member => ({
queryKey: ['github-user', member.username],
queryFn: () => fetchGithubUser(member.username),
})),
});
const { data: repos, isLoading: loadingRepos, error: reposError } = useQuery({
queryKey: ['github-repos', 'Snigdha-OS'],
queryFn: () => fetchOrgRepos('Snigdha-OS'),
});
const isLoading = queries.some(query => query.isLoading) || loadingRepos;
const isError = queries.some(query => query.isError) || reposError;
if (isLoading) {
return (
<div className="min-h-[50vh] flex items-center justify-center">
<Loader2 className="h-8 w-8 animate-spin text-cornflower-blue" />
</div>
);
}
if (isError) {
return (
<div className="min-h-[50vh] flex items-center justify-center">
<p className="text-red-500">Failed to load data</p>
</div>
);
}
return (
<div className="py-12">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
className="text-center mb-12"
>
<h1 className="text-4xl font-bold text-gray-900">Our Team</h1>
<p className="mt-4 text-lg text-gray-600">
Meet the dedicated team behind Snigdha OS
</p>
</motion.div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 mb-16">
{queries.map((query, index) => (
query.data && (
<TeamMemberCard
key={query.data.login}
user={query.data}
role={teamMembers[index].role}
description={teamMembers[index].description}
/>
)
))}
</div>
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.2 }}
className="mt-16"
>
<h2 className="text-3xl font-bold text-gray-900 mb-8">Our Repositories</h2>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{repos?.map((repo) => (
<RepoCard key={repo.id} repo={repo} />
))}
</div>
</motion.div>
</div>
</div>
);
}

58
src/pages/Donate.tsx Normal file
View File

@@ -0,0 +1,58 @@
import { motion } from 'framer-motion';
import { Heart } from 'lucide-react';
import { GithubSponsorButton } from '@/components/donate/GithubSponsorButton';
import { SponsorshipTiers } from '@/components/donate/SponsorshipTiers';
import { SponsorshipStats } from '@/components/donate/SponsorshipStats';
import { KeySponsors } from '@/components/donate/KeySponsors';
export default function Donate() {
return (
<div className="min-h-screen bg-gradient-to-b from-gray-50 to-white py-12">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
className="text-center mb-12"
>
<Heart className="h-12 w-12 text-red-500 mx-auto mb-4" />
<h1 className="text-4xl font-bold text-gray-900">Support Snigdha OS</h1>
<p className="mt-4 text-lg text-gray-600 max-w-2xl mx-auto">
Your support helps us maintain and improve Snigdha OS, keeping it free and open source for the security community.
</p>
<div className="mt-8">
<GithubSponsorButton />
</div>
</motion.div>
<div className="space-y-16">
<section>
<KeySponsors />
</section>
<section>
<SponsorshipStats />
</section>
<section>
<h2 className="text-2xl font-bold text-gray-900 text-center mb-8">
Choose Your Sponsorship Tier
</h2>
<SponsorshipTiers />
</section>
<section className="max-w-3xl mx-auto text-center bg-cornflower-blue/5 rounded-2xl p-8">
<h2 className="text-2xl font-bold text-gray-900 mb-4">
Why Sponsor Snigdha OS?
</h2>
<p className="text-gray-600">
Your sponsorship directly supports the development of cutting-edge security tools,
maintenance of our infrastructure, and helps us keep Snigdha OS at the forefront
of security testing. Join our community of sponsors and help shape the future of
security testing.
</p>
</section>
</div>
</div>
</div>
);
}

95
src/pages/Download.tsx Normal file
View File

@@ -0,0 +1,95 @@
import { useState } from 'react';
import { motion } from 'framer-motion';
import { Loader2 } from 'lucide-react';
import { DownloadButton } from '@/components/download/DownloadButton';
import { SystemRequirements } from '@/components/download/SystemRequirements';
import { Checksum } from '@/components/download/Checksum';
import { MirrorList } from '@/components/download/MirrorList';
import { NetworkSpeed } from '@/components/download/NetworkSpeed';
import { SuggestedMirror } from '@/components/download/SuggestedMirror';
import { downloads } from '@/data/download';
import { mirrors } from '@/data/mirrors';
import { type Mirror } from '@/types/download';
import { useNetworkSpeed } from '@/hooks/useNetworkSpeed';
import { useLocation } from '@/hooks/useLocation';
export default function Download() {
const latestVersion = downloads[0];
const [selectedMirror, setSelectedMirror] = useState<Mirror | null>(null);
const { speed, isLoading: loadingSpeed } = useNetworkSpeed();
const { location, isLoading: loadingLocation } = useLocation();
const handleMirrorSelect = (mirror: Mirror) => {
setSelectedMirror(mirror);
};
// Sort mirrors by speed and location
const sortedMirrors = [...mirrors].sort((a, b) => {
if (!speed) return 0;
const aDiff = Math.abs(a.speed - speed);
const bDiff = Math.abs(b.speed - speed);
return aDiff - bDiff;
});
// Get suggested mirror based on location and speed
const suggestedMirror = location ? sortedMirrors[0] : null;
if (loadingSpeed || loadingLocation) {
return (
<div className="min-h-[50vh] flex items-center justify-center">
<Loader2 className="h-8 w-8 animate-spin text-cornflower-blue" />
</div>
);
}
return (
<div className="py-12">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
className="text-center mb-12"
>
<h1 className="text-4xl font-bold text-gray-900">Download Snigdha OS</h1>
<p className="mt-4 text-lg text-gray-600">
Get the latest version of the most advanced penetration testing distribution
</p>
</motion.div>
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
<div className="lg:col-span-2 space-y-8">
<DownloadButton {...latestVersion} />
<div>
<h2 className="text-xl font-semibold text-gray-900 mb-4">Download Mirrors</h2>
<p className="text-sm text-gray-600 mb-4">
Mirrors are sorted by compatibility with your connection speed for optimal download performance
</p>
<MirrorList
mirrors={sortedMirrors}
onSelect={handleMirrorSelect}
/>
</div>
<Checksum
sha256={latestVersion.sha256}
gpg={latestVersion.gpg}
/>
</div>
<div className="space-y-6">
{speed !== null && <NetworkSpeed speed={speed} />}
{location && suggestedMirror && (
<SuggestedMirror
mirror={suggestedMirror}
userLocation={location}
onSelect={handleMirrorSelect}
/>
)}
<SystemRequirements />
</div>
</div>
</div>
</div>
);
}

64
src/pages/Features.tsx Normal file
View File

@@ -0,0 +1,64 @@
import { useState, useMemo } from 'react';
import { motion } from 'framer-motion';
import { SearchBar } from '@/components/features/SearchBar';
import { CategoryFilter } from '@/components/features/CategoryFilter';
import { ToolCard } from '@/components/features/ToolCard';
import { tools, categories } from '@/data/tools';
export default function Features() {
const [searchQuery, setSearchQuery] = useState('');
const [selectedCategory, setSelectedCategory] = useState('All');
const filteredTools = useMemo(() => {
return tools.filter((tool) => {
const matchesSearch = tool.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
tool.description.toLowerCase().includes(searchQuery.toLowerCase());
const matchesCategory = selectedCategory === 'All' || tool.category === selectedCategory;
return matchesSearch && matchesCategory;
});
}, [searchQuery, selectedCategory]);
return (
<div className="py-12">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
className="text-center mb-12"
>
<h1 className="text-4xl font-bold text-gray-900">Snigdha OS Tools</h1>
<p className="mt-4 text-lg text-gray-600">
Explore our comprehensive collection of security and penetration testing tools
</p>
</motion.div>
<div className="space-y-8">
<div className="max-w-xl mx-auto">
<SearchBar
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
/>
</div>
<CategoryFilter
categories={categories}
selectedCategory={selectedCategory}
onSelect={setSelectedCategory}
/>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{filteredTools.map((tool) => (
<ToolCard key={tool.id} {...tool} />
))}
</div>
{filteredTools.length === 0 && (
<div className="text-center py-12">
<p className="text-gray-500">No tools found matching your criteria</p>
</div>
)}
</div>
</div>
</div>
);
}

46
src/pages/Gallery.tsx Normal file
View File

@@ -0,0 +1,46 @@
import { useState, useMemo } from 'react';
import { motion } from 'framer-motion';
import { Camera } from 'lucide-react';
import { GalleryImage } from '@/components/gallery/GalleryImage';
import { CategoryFilter } from '@/components/gallery/CategoryFilter';
import { galleryImages, categories } from '@/data/gallery';
export default function Gallery() {
const [selectedCategory, setSelectedCategory] = useState('All');
const filteredImages = useMemo(() => {
return selectedCategory === 'All'
? galleryImages
: galleryImages.filter((image) => image.category === selectedCategory);
}, [selectedCategory]);
return (
<div className="py-12">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
className="text-center mb-12"
>
<Camera className="h-12 w-12 text-cornflower-blue mx-auto mb-4" />
<h1 className="text-4xl font-bold text-gray-900">Gallery</h1>
<p className="mt-4 text-lg text-gray-600">
Explore the visual journey of Snigdha OS
</p>
</motion.div>
<CategoryFilter
categories={categories}
selectedCategory={selectedCategory}
onSelect={setSelectedCategory}
/>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{filteredImages.map((image) => (
<GalleryImage key={image.src} {...image} />
))}
</div>
</div>
</div>
);
}

84
src/pages/Home.tsx Normal file
View File

@@ -0,0 +1,84 @@
import { Shield, Terminal, Cpu } from 'lucide-react';
import { HeroSection } from '@/components/home/HeroSection';
import { FeatureCard } from '@/components/home/FeatureCard';
import { StatsSection } from '@/components/home/StatsSection';
import { ToolsShowcase } from '@/components/home/ToolsShowcase';
import { TestimonialCard } from '@/components/home/TestimonialCard';
import { ComparisonSection } from '@/components/home/ComparisonSection';
import { testimonials } from '@/data/testimonials';
const features = [
{
title: 'Advanced Security Tools',
description: 'Access over 600 pre-installed security and penetration testing tools, ready to use out of the box.',
icon: Shield,
},
{
title: 'Powerful Terminal',
description: 'Enhanced command-line interface with custom tools and utilities for efficient security testing.',
icon: Terminal,
},
{
title: 'Hardware Compatibility',
description: 'Optimized for various hardware configurations with excellent driver support.',
icon: Cpu,
},
];
export default function Home() {
return (
<div className="bg-gray-50">
<HeroSection />
<section className="py-20 bg-gradient-to-b from-gray-900 to-gray-50">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="text-center mb-16">
<h2 className="text-3xl font-bold text-white sm:text-4xl">
Powerful Features
</h2>
<p className="mt-4 text-lg text-gray-300">
Everything you need for professional security testing
</p>
</div>
<div className="grid grid-cols-1 gap-8 sm:grid-cols-2 lg:grid-cols-3">
{features.map((feature, index) => (
<FeatureCard
key={feature.title}
{...feature}
delay={index * 0.2}
/>
))}
</div>
</div>
</section>
<ToolsShowcase />
<ComparisonSection />
<section className="py-20 bg-white">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="text-center mb-12">
<h2 className="text-3xl font-bold text-gray-900">What Users Say</h2>
<p className="mt-4 text-lg text-gray-600">
Trusted by security professionals worldwide
</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
{testimonials.map((testimonial, index) => (
<TestimonialCard
key={testimonial.author}
{...testimonial}
delay={index * 0.2}
/>
))}
</div>
</div>
</section>
<StatsSection />
</div>
);
}