Update README.md to provide a comprehensive overview of the ScriptShare platform, including features, tech stack, setup instructions, admin capabilities, and contribution guidelines.
This commit is contained in:
34
src/pages/About.tsx
Normal file
34
src/pages/About.tsx
Normal file
@ -0,0 +1,34 @@
|
||||
import { Header } from '@/components/Header';
|
||||
import { Footer } from '@/components/Footer';
|
||||
import { Card, CardContent } from '@/components/ui/card';
|
||||
import { Code2 } from 'lucide-react';
|
||||
|
||||
export default function About() {
|
||||
return (
|
||||
<div className="min-h-screen flex flex-col bg-gradient-to-br from-background via-background to-primary/5">
|
||||
<Header onSearch={() => {}} />
|
||||
|
||||
<main className="flex-1 container mx-auto px-4 py-16">
|
||||
<div className="max-w-4xl mx-auto space-y-12">
|
||||
<div className="text-center space-y-6">
|
||||
<Code2 className="h-20 w-20 text-primary mx-auto" />
|
||||
<h1 className="text-5xl font-bold">About ScriptShare</h1>
|
||||
<p className="text-xl text-muted-foreground max-w-3xl mx-auto">
|
||||
A community-driven platform for discovering, sharing, and collaborating on powerful bash scripts.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Card>
|
||||
<CardContent className="p-8">
|
||||
<p className="text-muted-foreground text-center">
|
||||
About page content coming soon! This will include our mission, team, and community information.
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
}
|
165
src/pages/AdminPanel.tsx
Normal file
165
src/pages/AdminPanel.tsx
Normal file
@ -0,0 +1,165 @@
|
||||
import { useState } from 'react';
|
||||
import { Header } from '@/components/Header';
|
||||
import { Footer } from '@/components/Footer';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Shield, Users, BarChart3, FileText, ArrowLeft } from 'lucide-react';
|
||||
import { AdminDashboard } from '@/components/admin/AdminDashboard';
|
||||
import { CreateAdminForm } from '@/components/admin/CreateAdminForm';
|
||||
import { AdminUsersList } from '@/components/admin/AdminUsersList';
|
||||
import { useAuth } from '@/contexts/AuthContext';
|
||||
|
||||
type AdminView = 'dashboard' | 'create-user' | 'users' | 'scripts' | 'analytics';
|
||||
|
||||
export default function AdminPanel() {
|
||||
const { user } = useAuth();
|
||||
const [currentView, setCurrentView] = useState<AdminView>('dashboard');
|
||||
|
||||
// Check if user has admin access
|
||||
if (!user?.isAdmin) {
|
||||
return (
|
||||
<div className="min-h-screen flex flex-col bg-gradient-to-br from-background via-background to-primary/5">
|
||||
<Header onSearch={() => {}} />
|
||||
|
||||
<main className="flex-1 container mx-auto px-4 py-16">
|
||||
<div className="max-w-2xl mx-auto text-center space-y-6">
|
||||
<Shield className="h-16 w-16 text-muted-foreground mx-auto" />
|
||||
<h1 className="text-4xl font-bold">Access Denied</h1>
|
||||
<p className="text-xl text-muted-foreground">
|
||||
You don't have permission to access the admin panel.
|
||||
</p>
|
||||
<Button onClick={() => window.history.back()}>
|
||||
Go Back
|
||||
</Button>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const renderView = () => {
|
||||
switch (currentView) {
|
||||
case 'dashboard':
|
||||
return (
|
||||
<AdminDashboard
|
||||
onCreateUser={() => setCurrentView('create-user')}
|
||||
onViewScripts={() => setCurrentView('scripts')}
|
||||
onViewAnalytics={() => setCurrentView('analytics')}
|
||||
/>
|
||||
);
|
||||
case 'create-user':
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<div className="flex items-center gap-4">
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => setCurrentView('dashboard')}
|
||||
className="flex items-center gap-2"
|
||||
>
|
||||
<ArrowLeft className="h-4 w-4" />
|
||||
Back to Dashboard
|
||||
</Button>
|
||||
</div>
|
||||
<CreateAdminForm onSuccess={() => setCurrentView('users')} />
|
||||
</div>
|
||||
);
|
||||
case 'users':
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-4">
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => setCurrentView('dashboard')}
|
||||
className="flex items-center gap-2"
|
||||
>
|
||||
<ArrowLeft className="h-4 w-4" />
|
||||
Back to Dashboard
|
||||
</Button>
|
||||
</div>
|
||||
<Button onClick={() => setCurrentView('create-user')}>
|
||||
<Users className="h-4 w-4 mr-2" />
|
||||
Create Admin User
|
||||
</Button>
|
||||
</div>
|
||||
<AdminUsersList />
|
||||
</div>
|
||||
);
|
||||
case 'scripts':
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<div className="flex items-center gap-4">
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => setCurrentView('dashboard')}
|
||||
className="flex items-center gap-2"
|
||||
>
|
||||
<ArrowLeft className="h-4 w-4" />
|
||||
Back to Dashboard
|
||||
</Button>
|
||||
</div>
|
||||
<div className="text-center py-12">
|
||||
<FileText className="h-16 w-16 text-muted-foreground mx-auto mb-4" />
|
||||
<h2 className="text-2xl font-bold mb-2">Script Review</h2>
|
||||
<p className="text-muted-foreground">
|
||||
Script review functionality coming soon!
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
case 'analytics':
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<div className="flex items-center gap-4">
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => setCurrentView('dashboard')}
|
||||
className="flex items-center gap-2"
|
||||
>
|
||||
<ArrowLeft className="h-4 w-4" />
|
||||
Back to Dashboard
|
||||
</Button>
|
||||
</div>
|
||||
<div className="text-center py-12">
|
||||
<BarChart3 className="h-16 w-16 text-muted-foreground mx-auto mb-4" />
|
||||
<h2 className="text-2xl font-bold mb-2">Analytics Dashboard</h2>
|
||||
<p className="text-muted-foreground">
|
||||
Analytics functionality coming soon!
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="min-h-screen flex flex-col bg-gradient-to-br from-background via-background to-primary/5">
|
||||
<Header onSearch={() => {}} />
|
||||
|
||||
<main className="flex-1 container mx-auto px-4 py-16">
|
||||
<div className="max-w-6xl mx-auto space-y-8">
|
||||
<div className="text-center space-y-4">
|
||||
<Shield className="h-16 w-16 text-primary mx-auto" />
|
||||
<h1 className="text-4xl font-bold">Admin Panel</h1>
|
||||
<p className="text-xl text-muted-foreground">
|
||||
Manage the platform and moderate content.
|
||||
</p>
|
||||
{user.isSuperUser && (
|
||||
<div className="inline-flex items-center gap-2 px-3 py-1 bg-amber-100 dark:bg-amber-900/30 text-amber-800 dark:text-amber-200 rounded-full text-sm font-medium">
|
||||
<Shield className="h-4 w-4" />
|
||||
Super User Access
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{renderView()}
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
}
|
34
src/pages/AdminScriptReview.tsx
Normal file
34
src/pages/AdminScriptReview.tsx
Normal file
@ -0,0 +1,34 @@
|
||||
import { Header } from '@/components/Header';
|
||||
import { Footer } from '@/components/Footer';
|
||||
import { Card, CardContent } from '@/components/ui/card';
|
||||
import { FileCheck } from 'lucide-react';
|
||||
|
||||
export default function AdminScriptReview() {
|
||||
return (
|
||||
<div className="min-h-screen flex flex-col bg-gradient-to-br from-background via-background to-primary/5">
|
||||
<Header onSearch={() => {}} />
|
||||
|
||||
<main className="flex-1 container mx-auto px-4 py-16">
|
||||
<div className="max-w-4xl mx-auto space-y-8">
|
||||
<div className="text-center space-y-4">
|
||||
<FileCheck className="h-16 w-16 text-primary mx-auto" />
|
||||
<h1 className="text-4xl font-bold">Script Review</h1>
|
||||
<p className="text-xl text-muted-foreground">
|
||||
Review and approve submitted scripts.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Card>
|
||||
<CardContent className="p-8">
|
||||
<p className="text-muted-foreground text-center">
|
||||
Script Review functionality coming soon! This will include script evaluation, approval/rejection, and feedback.
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
}
|
34
src/pages/Dashboard.tsx
Normal file
34
src/pages/Dashboard.tsx
Normal file
@ -0,0 +1,34 @@
|
||||
import { Header } from '@/components/Header';
|
||||
import { Footer } from '@/components/Footer';
|
||||
import { Card, CardContent } from '@/components/ui/card';
|
||||
import { BarChart3 } from 'lucide-react';
|
||||
|
||||
export default function Dashboard() {
|
||||
return (
|
||||
<div className="min-h-screen flex flex-col bg-gradient-to-br from-background via-background to-primary/5">
|
||||
<Header onSearch={() => {}} />
|
||||
|
||||
<main className="flex-1 container mx-auto px-4 py-16">
|
||||
<div className="max-w-6xl mx-auto space-y-8">
|
||||
<div className="text-center space-y-4">
|
||||
<BarChart3 className="h-16 w-16 text-primary mx-auto" />
|
||||
<h1 className="text-4xl font-bold">Dashboard</h1>
|
||||
<p className="text-xl text-muted-foreground">
|
||||
Manage your scripts and track your contributions.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Card>
|
||||
<CardContent className="p-8">
|
||||
<p className="text-muted-foreground text-center">
|
||||
Dashboard functionality coming soon! This will include user statistics, script management, and analytics.
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
}
|
34
src/pages/EditScript.tsx
Normal file
34
src/pages/EditScript.tsx
Normal file
@ -0,0 +1,34 @@
|
||||
import { Header } from '@/components/Header';
|
||||
import { Footer } from '@/components/Footer';
|
||||
import { Card, CardContent } from '@/components/ui/card';
|
||||
import { Edit } from 'lucide-react';
|
||||
|
||||
export default function EditScript() {
|
||||
return (
|
||||
<div className="min-h-screen flex flex-col bg-gradient-to-br from-background via-background to-primary/5">
|
||||
<Header onSearch={() => {}} />
|
||||
|
||||
<main className="flex-1 container mx-auto px-4 py-16">
|
||||
<div className="max-w-4xl mx-auto space-y-8">
|
||||
<div className="text-center space-y-4">
|
||||
<Edit className="h-16 w-16 text-primary mx-auto" />
|
||||
<h1 className="text-4xl font-bold">Edit Script</h1>
|
||||
<p className="text-xl text-muted-foreground">
|
||||
Update your script content and metadata.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Card>
|
||||
<CardContent className="p-8">
|
||||
<p className="text-muted-foreground text-center">
|
||||
Edit Script functionality coming soon! This will include script editing forms and version management.
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
}
|
349
src/pages/Index.tsx
Normal file
349
src/pages/Index.tsx
Normal file
@ -0,0 +1,349 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { Header } from '@/components/Header';
|
||||
import { Footer } from '@/components/Footer';
|
||||
import { ScriptFilters, FilterOptions } from '@/components/ScriptFilters';
|
||||
import { ScriptGrid } from '@/components/ScriptGrid';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Card, CardContent } from '@/components/ui/card';
|
||||
import { Script } from '@/components/ScriptCard';
|
||||
import { showError } from '@/utils/toast';
|
||||
import { Code2, Users, FileText, Star, ArrowRight, Sparkles, Zap, Shield } from 'lucide-react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
// Mock data for development
|
||||
const mockScripts: Script[] = [
|
||||
{
|
||||
id: '1',
|
||||
name: 'System Backup Automation',
|
||||
description: 'Automated backup script for Linux systems with compression and encryption support.',
|
||||
compatible_os: ['Linux', 'Ubuntu', 'CentOS'],
|
||||
categories: ['System Administration', 'Backup'],
|
||||
git_repository_url: 'https://github.com/user/backup-script',
|
||||
author_name: 'John Doe',
|
||||
view_count: 1250,
|
||||
created_at: '2024-01-15T10:00:00Z',
|
||||
updated_at: '2024-01-20T14:30:00Z',
|
||||
is_approved: true,
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
name: 'Docker Cleanup Utility',
|
||||
description: 'Clean up unused Docker containers, images, and volumes to free up disk space.',
|
||||
compatible_os: ['Linux', 'macOS', 'Windows'],
|
||||
categories: ['DevOps', 'Docker'],
|
||||
git_repository_url: 'https://github.com/user/docker-cleanup',
|
||||
author_name: 'Jane Smith',
|
||||
view_count: 890,
|
||||
created_at: '2024-01-10T09:00:00Z',
|
||||
updated_at: '2024-01-18T16:45:00Z',
|
||||
is_approved: true,
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
name: 'Git Repository Manager',
|
||||
description: 'Manage multiple Git repositories with status checking and batch operations.',
|
||||
compatible_os: ['Linux', 'macOS', 'Windows'],
|
||||
categories: ['Development', 'Git'],
|
||||
git_repository_url: 'https://github.com/user/git-manager',
|
||||
author_name: 'Mike Johnson',
|
||||
view_count: 567,
|
||||
created_at: '2024-01-05T11:00:00Z',
|
||||
updated_at: '2024-01-12T13:20:00Z',
|
||||
is_approved: true,
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
name: 'Network Monitor',
|
||||
description: 'Monitor network connectivity and performance with detailed reporting.',
|
||||
compatible_os: ['Linux', 'Ubuntu'],
|
||||
categories: ['Networking', 'Monitoring'],
|
||||
git_repository_url: 'https://github.com/user/network-monitor',
|
||||
author_name: 'Sarah Wilson',
|
||||
view_count: 432,
|
||||
created_at: '2024-01-01T08:00:00Z',
|
||||
updated_at: '2024-01-08T10:15:00Z',
|
||||
is_approved: true,
|
||||
},
|
||||
];
|
||||
|
||||
const Index = () => {
|
||||
const navigate = useNavigate();
|
||||
const [scripts, setScripts] = useState<Script[]>([]);
|
||||
const [filteredScripts, setFilteredScripts] = useState<Script[]>([]);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
// Load mock data on mount
|
||||
useEffect(() => {
|
||||
console.log('📜 Index component mounted at:', new Date().toISOString());
|
||||
loadScripts();
|
||||
}, []);
|
||||
|
||||
const loadScripts = async () => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
setError(null);
|
||||
|
||||
// Simulate API call delay
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
|
||||
console.log('✅ Successfully loaded scripts:', mockScripts.length);
|
||||
setScripts(mockScripts);
|
||||
setFilteredScripts(mockScripts);
|
||||
setError(null);
|
||||
} catch (error: any) {
|
||||
console.error('❌ Error in loadScripts:', error);
|
||||
const errorMessage = error.message || 'Failed to load scripts';
|
||||
setError(errorMessage);
|
||||
showError(`Failed to load scripts: ${errorMessage}`);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleFiltersChange = (filters: FilterOptions) => {
|
||||
console.log('🔍 Applying filters:', filters);
|
||||
let filtered = [...scripts];
|
||||
|
||||
// Apply search query
|
||||
if (searchQuery) {
|
||||
filtered = filtered.filter(script =>
|
||||
script.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
||||
script.description.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
||||
script.author_name.toLowerCase().includes(searchQuery.toLowerCase())
|
||||
);
|
||||
}
|
||||
|
||||
// Apply OS filter
|
||||
if (filters.os.length > 0) {
|
||||
filtered = filtered.filter(script =>
|
||||
filters.os.some(os => script.compatible_os.includes(os))
|
||||
);
|
||||
}
|
||||
|
||||
// Apply category filter
|
||||
if (filters.categories.length > 0) {
|
||||
filtered = filtered.filter(script =>
|
||||
filters.categories.some(category => script.categories.includes(category))
|
||||
);
|
||||
}
|
||||
|
||||
// Apply date filters
|
||||
const now = new Date();
|
||||
if (filters.dateAdded !== 'all') {
|
||||
const days = getDateFilterDays(filters.dateAdded);
|
||||
const cutoff = new Date(now.getTime() - days * 24 * 60 * 60 * 1000);
|
||||
filtered = filtered.filter(script => new Date(script.created_at) >= cutoff);
|
||||
}
|
||||
|
||||
if (filters.recentlyUpdated !== 'all') {
|
||||
const days = getDateFilterDays(filters.recentlyUpdated);
|
||||
const cutoff = new Date(now.getTime() - days * 24 * 60 * 60 * 1000);
|
||||
filtered = filtered.filter(script => new Date(script.updated_at) >= cutoff);
|
||||
}
|
||||
|
||||
console.log('🔍 Filtered scripts:', filtered.length);
|
||||
setFilteredScripts(filtered);
|
||||
};
|
||||
|
||||
const getDateFilterDays = (filter: string): number => {
|
||||
switch (filter) {
|
||||
case '1d': return 1;
|
||||
case '1w': return 7;
|
||||
case '1m': return 30;
|
||||
case '1y': return 365;
|
||||
default: return 0;
|
||||
}
|
||||
};
|
||||
|
||||
const handleSearch = (query: string) => {
|
||||
console.log('🔍 Search query:', query);
|
||||
setSearchQuery(query);
|
||||
// Re-apply filters with new search query
|
||||
handleFiltersChange({
|
||||
os: [],
|
||||
categories: [],
|
||||
dateAdded: 'all',
|
||||
recentlyUpdated: 'all',
|
||||
});
|
||||
};
|
||||
|
||||
const totalViews = scripts.reduce((sum, script) => sum + script.view_count, 0);
|
||||
const totalAuthors = new Set(scripts.map(script => script.author_name)).size;
|
||||
|
||||
return (
|
||||
<div className="min-h-screen flex flex-col bg-gradient-to-br from-background via-background to-primary/5">
|
||||
<Header onSearch={handleSearch} />
|
||||
|
||||
<main className="flex-1">
|
||||
{/* Hero Section */}
|
||||
<section className="relative overflow-hidden">
|
||||
{/* Animated background elements */}
|
||||
<div className="absolute inset-0 overflow-hidden">
|
||||
<div className="absolute -top-40 -right-40 w-80 h-80 bg-gradient-to-br from-primary/20 to-accent/20 rounded-full blur-3xl animate-pulse" />
|
||||
<div className="absolute -bottom-40 -left-40 w-80 h-80 bg-gradient-to-tr from-accent/20 to-primary/20 rounded-full blur-3xl animate-pulse delay-1000" />
|
||||
</div>
|
||||
|
||||
<div className="container mx-auto px-4 py-16 relative z-10">
|
||||
<div className="text-center space-y-8 max-w-4xl mx-auto">
|
||||
{/* Main heading with enhanced styling */}
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center justify-center gap-2 mb-4">
|
||||
<Sparkles className="h-6 w-6 text-accent animate-pulse" />
|
||||
<span className="text-sm font-semibold text-muted-foreground tracking-wider uppercase">
|
||||
Community Driven
|
||||
</span>
|
||||
<Sparkles className="h-6 w-6 text-primary animate-pulse delay-500" />
|
||||
</div>
|
||||
|
||||
<h1 className="text-5xl md:text-7xl font-bold bg-gradient-to-r from-primary via-accent to-primary bg-clip-text text-transparent animate-gradient-x leading-tight">
|
||||
Bash Script Library
|
||||
</h1>
|
||||
|
||||
<p className="text-xl md:text-2xl text-muted-foreground max-w-3xl mx-auto leading-relaxed">
|
||||
Discover, share, and collaborate on powerful bash scripts for
|
||||
<span className="text-primary font-semibold"> system administration</span>,
|
||||
<span className="text-accent font-semibold"> automation</span>, and
|
||||
<span className="text-primary font-semibold"> development</span>.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* CTA Buttons */}
|
||||
<div className="flex flex-col sm:flex-row gap-4 justify-center items-center">
|
||||
<Button
|
||||
size="lg"
|
||||
className="bg-gradient-to-r from-primary to-accent hover:from-primary/90 hover:to-accent/90 text-white shadow-2xl hover:shadow-primary/30 transition-all duration-300 rounded-xl px-8 py-3 text-lg font-semibold group"
|
||||
onClick={() => navigate('/search')}
|
||||
>
|
||||
Explore Scripts
|
||||
<ArrowRight className="ml-2 h-5 w-5 group-hover:translate-x-1 transition-transform duration-200" />
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
size="lg"
|
||||
variant="outline"
|
||||
className="border-primary/30 hover:border-primary hover:bg-gradient-to-r hover:from-primary/10 hover:to-accent/10 transition-all duration-300 rounded-xl px-8 py-3 text-lg font-semibold shadow-lg"
|
||||
onClick={() => navigate('/submit')}
|
||||
>
|
||||
<Code2 className="mr-2 h-5 w-5" />
|
||||
Share Your Script
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* Stats Cards */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 mt-16">
|
||||
<Card className="bg-gradient-to-br from-card/80 to-card/40 backdrop-blur-sm border-primary/20 hover:border-primary/40 transition-all duration-300 hover:scale-105">
|
||||
<CardContent className="p-6 text-center">
|
||||
<div className="inline-flex items-center justify-center w-12 h-12 bg-gradient-to-r from-primary/20 to-primary/30 rounded-full mb-4">
|
||||
<FileText className="h-6 w-6 text-primary" />
|
||||
</div>
|
||||
<div className="text-3xl font-bold bg-gradient-to-r from-primary to-accent bg-clip-text text-transparent">
|
||||
{scripts.length}
|
||||
</div>
|
||||
<div className="text-muted-foreground font-medium">Quality Scripts</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="bg-gradient-to-br from-card/80 to-card/40 backdrop-blur-sm border-accent/20 hover:border-accent/40 transition-all duration-300 hover:scale-105">
|
||||
<CardContent className="p-6 text-center">
|
||||
<div className="inline-flex items-center justify-center w-12 h-12 bg-gradient-to-r from-accent/20 to-accent/30 rounded-full mb-4">
|
||||
<Users className="h-6 w-6 text-accent" />
|
||||
</div>
|
||||
<div className="text-3xl font-bold bg-gradient-to-r from-accent to-primary bg-clip-text text-transparent">
|
||||
{totalAuthors}
|
||||
</div>
|
||||
<div className="text-muted-foreground font-medium">Contributors</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="bg-gradient-to-br from-card/80 to-card/40 backdrop-blur-sm border-primary/20 hover:border-primary/40 transition-all duration-300 hover:scale-105">
|
||||
<CardContent className="p-6 text-center">
|
||||
<div className="inline-flex items-center justify-center w-12 h-12 bg-gradient-to-r from-primary/20 to-accent/20 rounded-full mb-4">
|
||||
<Star className="h-6 w-6 text-primary" />
|
||||
</div>
|
||||
<div className="text-3xl font-bold bg-gradient-to-r from-primary to-accent bg-clip-text text-transparent">
|
||||
{totalViews.toLocaleString()}
|
||||
</div>
|
||||
<div className="text-muted-foreground font-medium">Total Views</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
{/* Feature highlights */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-8 mt-16">
|
||||
<div className="text-center space-y-4">
|
||||
<div className="inline-flex items-center justify-center w-16 h-16 bg-gradient-to-r from-primary/10 to-primary/20 rounded-2xl">
|
||||
<Zap className="h-8 w-8 text-primary" />
|
||||
</div>
|
||||
<h3 className="text-xl font-bold">Lightning Fast</h3>
|
||||
<p className="text-muted-foreground">
|
||||
Find the perfect script in seconds with our advanced search and filtering system.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="text-center space-y-4">
|
||||
<div className="inline-flex items-center justify-center w-16 h-16 bg-gradient-to-r from-accent/10 to-accent/20 rounded-2xl">
|
||||
<Shield className="h-8 w-8 text-accent" />
|
||||
</div>
|
||||
<h3 className="text-xl font-bold">Community Reviewed</h3>
|
||||
<p className="text-muted-foreground">
|
||||
All scripts are reviewed by our community to ensure quality and security.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="text-center space-y-4">
|
||||
<div className="inline-flex items-center justify-center w-16 h-16 bg-gradient-to-r from-primary/10 to-accent/10 rounded-2xl">
|
||||
<Code2 className="h-8 w-8 text-primary" />
|
||||
</div>
|
||||
<h3 className="text-xl font-bold">Ready to Use</h3>
|
||||
<p className="text-muted-foreground">
|
||||
Copy, download, or fork scripts directly. No setup required.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Scripts Section */}
|
||||
<section className="container mx-auto px-4 py-16 space-y-8">
|
||||
<div className="text-center space-y-4">
|
||||
<h2 className="text-3xl font-bold bg-gradient-to-r from-primary to-accent bg-clip-text text-transparent">
|
||||
Featured Scripts
|
||||
</h2>
|
||||
<p className="text-muted-foreground text-lg max-w-2xl mx-auto">
|
||||
Explore our curated collection of bash scripts, crafted by developers for developers.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Error Display */}
|
||||
{error && (
|
||||
<Card className="border-red-200 bg-red-50 dark:border-red-800 dark:bg-red-950">
|
||||
<CardContent className="p-4">
|
||||
<div className="text-red-800 dark:text-red-200">
|
||||
<strong>Error loading scripts:</strong> {error}
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={loadScripts}
|
||||
className="ml-4"
|
||||
>
|
||||
Retry
|
||||
</Button>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
<ScriptFilters onFiltersChange={handleFiltersChange} />
|
||||
<ScriptGrid scripts={filteredScripts} isLoading={isLoading} />
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Index;
|
34
src/pages/Login.tsx
Normal file
34
src/pages/Login.tsx
Normal file
@ -0,0 +1,34 @@
|
||||
import { Header } from '@/components/Header';
|
||||
import { Footer } from '@/components/Footer';
|
||||
import { Card, CardContent } from '@/components/ui/card';
|
||||
import { LogIn } from 'lucide-react';
|
||||
|
||||
export default function Login() {
|
||||
return (
|
||||
<div className="min-h-screen flex flex-col bg-gradient-to-br from-background via-background to-primary/5">
|
||||
<Header onSearch={() => {}} />
|
||||
|
||||
<main className="flex-1 container mx-auto px-4 py-16">
|
||||
<div className="max-w-md mx-auto space-y-8">
|
||||
<div className="text-center space-y-4">
|
||||
<LogIn className="h-16 w-16 text-primary mx-auto" />
|
||||
<h1 className="text-3xl font-bold">Sign In</h1>
|
||||
<p className="text-muted-foreground">
|
||||
Access your account to manage scripts and contribute to the community.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Card>
|
||||
<CardContent className="p-6">
|
||||
<p className="text-muted-foreground text-center">
|
||||
Login functionality coming soon! This will include authentication forms and user management.
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
}
|
34
src/pages/MyScripts.tsx
Normal file
34
src/pages/MyScripts.tsx
Normal file
@ -0,0 +1,34 @@
|
||||
import { Header } from '@/components/Header';
|
||||
import { Footer } from '@/components/Footer';
|
||||
import { Card, CardContent } from '@/components/ui/card';
|
||||
import { FolderOpen } from 'lucide-react';
|
||||
|
||||
export default function MyScripts() {
|
||||
return (
|
||||
<div className="min-h-screen flex flex-col bg-gradient-to-br from-background via-background to-primary/5">
|
||||
<Header onSearch={() => {}} />
|
||||
|
||||
<main className="flex-1 container mx-auto px-4 py-16">
|
||||
<div className="max-w-6xl mx-auto space-y-8">
|
||||
<div className="text-center space-y-4">
|
||||
<FolderOpen className="h-16 w-16 text-primary mx-auto" />
|
||||
<h1 className="text-4xl font-bold">My Scripts</h1>
|
||||
<p className="text-xl text-muted-foreground">
|
||||
Manage and track your submitted scripts.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Card>
|
||||
<CardContent className="p-8">
|
||||
<p className="text-muted-foreground text-center">
|
||||
My Scripts functionality coming soon! This will include script management, editing, and status tracking.
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
}
|
37
src/pages/NotFound.tsx
Normal file
37
src/pages/NotFound.tsx
Normal file
@ -0,0 +1,37 @@
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Code2, Home, ArrowLeft } from 'lucide-react';
|
||||
|
||||
export default function NotFound() {
|
||||
return (
|
||||
<div className="min-h-screen flex items-center justify-center bg-gradient-to-br from-background via-background to-primary/5">
|
||||
<div className="text-center space-y-6 max-w-md mx-auto px-4">
|
||||
<div className="flex justify-center">
|
||||
<Code2 className="h-24 w-24 text-primary/50" />
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<h1 className="text-6xl font-bold text-muted-foreground">404</h1>
|
||||
<h2 className="text-2xl font-semibold">Page Not Found</h2>
|
||||
<p className="text-muted-foreground">
|
||||
The page you're looking for doesn't exist or has been moved.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col sm:flex-row gap-3 justify-center">
|
||||
<Button asChild>
|
||||
<Link to="/">
|
||||
<Home className="mr-2 h-4 w-4" />
|
||||
Go Home
|
||||
</Link>
|
||||
</Button>
|
||||
|
||||
<Button variant="outline" onClick={() => window.history.back()}>
|
||||
<ArrowLeft className="mr-2 h-4 w-4" />
|
||||
Go Back
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
34
src/pages/Privacy.tsx
Normal file
34
src/pages/Privacy.tsx
Normal file
@ -0,0 +1,34 @@
|
||||
import { Header } from '@/components/Header';
|
||||
import { Footer } from '@/components/Footer';
|
||||
import { Card, CardContent } from '@/components/ui/card';
|
||||
import { Shield } from 'lucide-react';
|
||||
|
||||
export default function Privacy() {
|
||||
return (
|
||||
<div className="min-h-screen flex flex-col bg-gradient-to-br from-background via-background to-primary/5">
|
||||
<Header onSearch={() => {}} />
|
||||
|
||||
<main className="flex-1 container mx-auto px-4 py-16">
|
||||
<div className="max-w-4xl mx-auto space-y-8">
|
||||
<div className="text-center space-y-4">
|
||||
<Shield className="h-16 w-16 text-primary mx-auto" />
|
||||
<h1 className="text-4xl font-bold">Privacy Policy</h1>
|
||||
<p className="text-xl text-muted-foreground">
|
||||
How we protect and handle your data.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Card>
|
||||
<CardContent className="p-8">
|
||||
<p className="text-muted-foreground text-center">
|
||||
Privacy Policy content coming soon! This will include detailed information about data handling and privacy practices.
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
}
|
34
src/pages/Profile.tsx
Normal file
34
src/pages/Profile.tsx
Normal file
@ -0,0 +1,34 @@
|
||||
import { Header } from '@/components/Header';
|
||||
import { Footer } from '@/components/Footer';
|
||||
import { Card, CardContent } from '@/components/ui/card';
|
||||
import { User } from 'lucide-react';
|
||||
|
||||
export default function Profile() {
|
||||
return (
|
||||
<div className="min-h-screen flex flex-col bg-gradient-to-br from-background via-background to-primary/5">
|
||||
<Header onSearch={() => {}} />
|
||||
|
||||
<main className="flex-1 container mx-auto px-4 py-16">
|
||||
<div className="max-w-4xl mx-auto space-y-8">
|
||||
<div className="text-center space-y-4">
|
||||
<User className="h-16 w-16 text-primary mx-auto" />
|
||||
<h1 className="text-4xl font-bold">Profile</h1>
|
||||
<p className="text-xl text-muted-foreground">
|
||||
Manage your account settings and preferences.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Card>
|
||||
<CardContent className="p-8">
|
||||
<p className="text-muted-foreground text-center">
|
||||
Profile functionality coming soon! This will include user settings, account management, and preferences.
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
}
|
34
src/pages/ScriptDetail.tsx
Normal file
34
src/pages/ScriptDetail.tsx
Normal file
@ -0,0 +1,34 @@
|
||||
import { Header } from '@/components/Header';
|
||||
import { Footer } from '@/components/Footer';
|
||||
import { Card, CardContent } from '@/components/ui/card';
|
||||
import { FileCode } from 'lucide-react';
|
||||
|
||||
export default function ScriptDetail() {
|
||||
return (
|
||||
<div className="min-h-screen flex flex-col bg-gradient-to-br from-background via-background to-primary/5">
|
||||
<Header onSearch={() => {}} />
|
||||
|
||||
<main className="flex-1 container mx-auto px-4 py-16">
|
||||
<div className="max-w-4xl mx-auto space-y-8">
|
||||
<div className="text-center space-y-4">
|
||||
<FileCode className="h-16 w-16 text-primary mx-auto" />
|
||||
<h1 className="text-4xl font-bold">Script Details</h1>
|
||||
<p className="text-xl text-muted-foreground">
|
||||
View and interact with bash scripts.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Card>
|
||||
<CardContent className="p-8">
|
||||
<p className="text-muted-foreground text-center">
|
||||
Script detail functionality coming soon! This will include script content, comments, ratings, and download options.
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
}
|
34
src/pages/Search.tsx
Normal file
34
src/pages/Search.tsx
Normal file
@ -0,0 +1,34 @@
|
||||
import { Header } from '@/components/Header';
|
||||
import { Footer } from '@/components/Footer';
|
||||
import { Card, CardContent } from '@/components/ui/card';
|
||||
import { Search as SearchIcon } from 'lucide-react';
|
||||
|
||||
export default function Search() {
|
||||
return (
|
||||
<div className="min-h-screen flex flex-col bg-gradient-to-br from-background via-background to-primary/5">
|
||||
<Header onSearch={() => {}} />
|
||||
|
||||
<main className="flex-1 container mx-auto px-4 py-16">
|
||||
<div className="text-center space-y-8">
|
||||
<div className="space-y-4">
|
||||
<SearchIcon className="h-16 w-16 text-primary mx-auto" />
|
||||
<h1 className="text-4xl font-bold">Search Scripts</h1>
|
||||
<p className="text-xl text-muted-foreground max-w-2xl mx-auto">
|
||||
Find the perfect bash script for your needs using our advanced search and filtering system.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Card className="max-w-2xl mx-auto">
|
||||
<CardContent className="p-8 text-center">
|
||||
<p className="text-muted-foreground">
|
||||
Search functionality coming soon! This page will include advanced search, filters, and results.
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
}
|
34
src/pages/SubmitScript.tsx
Normal file
34
src/pages/SubmitScript.tsx
Normal file
@ -0,0 +1,34 @@
|
||||
import { Header } from '@/components/Header';
|
||||
import { Footer } from '@/components/Footer';
|
||||
import { Card, CardContent } from '@/components/ui/card';
|
||||
import { Upload } from 'lucide-react';
|
||||
|
||||
export default function SubmitScript() {
|
||||
return (
|
||||
<div className="min-h-screen flex flex-col bg-gradient-to-br from-background via-background to-primary/5">
|
||||
<Header onSearch={() => {}} />
|
||||
|
||||
<main className="flex-1 container mx-auto px-4 py-16">
|
||||
<div className="max-w-4xl mx-auto space-y-8">
|
||||
<div className="text-center space-y-4">
|
||||
<Upload className="h-16 w-16 text-primary mx-auto" />
|
||||
<h1 className="text-4xl font-bold">Submit Script</h1>
|
||||
<p className="text-xl text-muted-foreground">
|
||||
Share your bash script with the community.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Card>
|
||||
<CardContent className="p-8">
|
||||
<p className="text-muted-foreground text-center">
|
||||
Script submission functionality coming soon! This will include forms for script details, content, and metadata.
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
}
|
34
src/pages/Terms.tsx
Normal file
34
src/pages/Terms.tsx
Normal file
@ -0,0 +1,34 @@
|
||||
import { Header } from '@/components/Header';
|
||||
import { Footer } from '@/components/Footer';
|
||||
import { Card, CardContent } from '@/components/ui/card';
|
||||
import { FileText } from 'lucide-react';
|
||||
|
||||
export default function Terms() {
|
||||
return (
|
||||
<div className="min-h-screen flex flex-col bg-gradient-to-br from-background via-background to-primary/5">
|
||||
<Header onSearch={() => {}} />
|
||||
|
||||
<main className="flex-1 container mx-auto px-4 py-16">
|
||||
<div className="max-w-4xl mx-auto space-y-8">
|
||||
<div className="text-center space-y-4">
|
||||
<FileText className="h-16 w-16 text-primary mx-auto" />
|
||||
<h1 className="text-4xl font-bold">Terms of Service</h1>
|
||||
<p className="text-xl text-muted-foreground">
|
||||
Our terms and conditions for using the platform.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Card>
|
||||
<CardContent className="p-8">
|
||||
<p className="text-muted-foreground text-center">
|
||||
Terms of Service content coming soon! This will include detailed terms and conditions for platform usage.
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
}
|
Reference in New Issue
Block a user