mirror of
https://github.com/Snigdha-OS/Snigdha-OS.github.io.git
synced 2025-09-17 01:55:03 +02:00
Prepare for GitHub Pages deployment
This commit is contained in:
39
src/pages/About.tsx
Normal file
39
src/pages/About.tsx
Normal 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
84
src/pages/Developers.tsx
Normal 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
58
src/pages/Donate.tsx
Normal 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
95
src/pages/Download.tsx
Normal 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
64
src/pages/Features.tsx
Normal 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
46
src/pages/Gallery.tsx
Normal 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
84
src/pages/Home.tsx
Normal 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>
|
||||
);
|
||||
}
|
Reference in New Issue
Block a user