Spaces:
Running
Running
import React, { useState, useEffect } from 'react'; | |
import { Search, User, Calendar, Tag, Heart, MessageCircle, Share2, Filter, Plus, Globe, Users, TrendingUp } from 'lucide-react'; | |
const App = () => { | |
const [posts, setPosts] = useState([]); | |
const [filteredPosts, setFilteredPosts] = useState([]); | |
const [searchTerm, setSearchTerm] = useState(''); | |
const [selectedCategory, setSelectedCategory] = useState('all'); | |
const [showCreateModal, setShowCreateModal] = useState(false); | |
// Mock data for guest posts | |
const mockPosts = [ | |
{ | |
id: 1, | |
title: "The Future of Sustainable Web Development", | |
author: "Sarah Chen", | |
authorAvatar: "https://placehold.co/40x40/6366f1/white?text=SC", | |
category: "Technology", | |
tags: ["Web Dev", "Sustainability", "Green Tech"], | |
excerpt: "Exploring how developers can build more environmentally conscious websites and applications in 2024.", | |
likes: 24, | |
comments: 8, | |
date: "2024-01-15", | |
readTime: "5 min read", | |
featured: true | |
}, | |
{ | |
id: 2, | |
title: "Mindfulness Practices for Remote Teams", | |
author: "Marcus Johnson", | |
authorAvatar: "https://placehold.co/40x40/10b981/white?text=MJ", | |
category: "Lifestyle", | |
tags: ["Remote Work", "Wellness", "Team Building"], | |
excerpt: "Simple mindfulness techniques that can transform your remote work experience and boost team productivity.", | |
likes: 18, | |
comments: 12, | |
date: "2024-01-12", | |
readTime: "4 min read", | |
featured: false | |
}, | |
{ | |
id: 3, | |
title: "The Art of Storytelling in Digital Marketing", | |
author: "Elena Rodriguez", | |
authorAvatar: "https://placehold.co/40x40/f59e0b/white?text=ER", | |
category: "Marketing", | |
tags: ["Storytelling", "Content Marketing", "Brand Building"], | |
excerpt: "How to craft compelling narratives that resonate with your audience and drive engagement.", | |
likes: 31, | |
comments: 15, | |
date: "2024-01-10", | |
readTime: "6 min read", | |
featured: true | |
}, | |
{ | |
id: 4, | |
title: "Building Resilient Microservices Architecture", | |
author: "David Kim", | |
authorAvatar: "https://placehold.co/40x40/ef4444/white?text=DK", | |
category: "Technology", | |
tags: ["Microservices", "Architecture", "DevOps"], | |
excerpt: "Key principles and best practices for designing scalable and fault-tolerant microservices systems.", | |
likes: 27, | |
comments: 9, | |
date: "2024-01-08", | |
readTime: "8 min read", | |
featured: false | |
}, | |
{ | |
id: 5, | |
title: "The Psychology of Color in Brand Design", | |
author: "Amira Hassan", | |
authorAvatar: "https://placehold.co/40x40/8b5cf6/white?text=AH", | |
category: "Design", | |
tags: ["Color Theory", "Branding", "Psychology"], | |
excerpt: "Understanding how color choices impact consumer behavior and brand perception in digital spaces.", | |
likes: 22, | |
comments: 7, | |
date: "2024-01-05", | |
readTime: "5 min read", | |
featured: false | |
}, | |
{ | |
id: 6, | |
title: "Financial Literacy for Young Entrepreneurs", | |
author: "James Wilson", | |
authorAvatar: "https://placehold.co/40x40/06b6d4/white?text=JW", | |
category: "Business", | |
tags: ["Finance", "Entrepreneurship", "Investing"], | |
excerpt: "Essential financial concepts every young business owner should master to build sustainable ventures.", | |
likes: 19, | |
comments: 11, | |
date: "2024-01-03", | |
readTime: "7 min read", | |
featured: false | |
} | |
]; | |
const categories = [ | |
{ id: 'all', name: 'All Categories', icon: Globe }, | |
{ id: 'technology', name: 'Technology', icon: TrendingUp }, | |
{ id: 'design', name: 'Design', icon: TrendingUp }, | |
{ id: 'marketing', name: 'Marketing', icon: TrendingUp }, | |
{ id: 'business', name: 'Business', icon: TrendingUp }, | |
{ id: 'lifestyle', name: 'Lifestyle', icon: TrendingUp } | |
]; | |
useEffect(() => { | |
setPosts(mockPosts); | |
setFilteredPosts(mockPosts); | |
}, []); | |
useEffect(() => { | |
let filtered = posts; | |
if (searchTerm) { | |
filtered = filtered.filter(post => | |
post.title.toLowerCase().includes(searchTerm.toLowerCase()) || | |
post.excerpt.toLowerCase().includes(searchTerm.toLowerCase()) || | |
post.tags.some(tag => tag.toLowerCase().includes(searchTerm.toLowerCase())) | |
); | |
} | |
if (selectedCategory !== 'all') { | |
filtered = filtered.filter(post => | |
post.category.toLowerCase() === selectedCategory.toLowerCase() | |
); | |
} | |
setFilteredPosts(filtered); | |
}, [searchTerm, selectedCategory, posts]); | |
const handleLike = (postId) => { | |
setPosts(posts.map(post => | |
post.id === postId | |
? { ...post, likes: post.likes + 1 } | |
: post | |
)); | |
}; | |
const CreatePostModal = () => ( | |
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4"> | |
<div className="bg-white rounded-2xl max-w-2xl w-full max-h-screen overflow-y-auto"> | |
<div className="p-6"> | |
<div className="flex justify-between items-center mb-6"> | |
<h2 className="text-2xl font-bold text-gray-900">Create Guest Post</h2> | |
<button | |
onClick={() => setShowCreateModal(false)} | |
className="text-gray-400 hover:text-gray-600 text-2xl" | |
> | |
× | |
</button> | |
</div> | |
<form className="space-y-6"> | |
<div> | |
<label className="block text-sm font-medium text-gray-700 mb-2">Post Title</label> | |
<input | |
type="text" | |
className="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-transparent" | |
placeholder="Enter your post title" | |
/> | |
</div> | |
<div> | |
<label className="block text-sm font-medium text-gray-700 mb-2">Category</label> | |
<select className="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-transparent"> | |
<option>Select a category</option> | |
<option>Technology</option> | |
<option>Design</option> | |
<option>Marketing</option> | |
<option>Business</option> | |
<option>Lifestyle</option> | |
</select> | |
</div> | |
<div> | |
<label className="block text-sm font-medium text-gray-700 mb-2">Tags</label> | |
<input | |
type="text" | |
className="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-transparent" | |
placeholder="Enter tags separated by commas" | |
/> | |
</div> | |
<div> | |
<label className="block text-sm font-medium text-gray-700 mb-2">Excerpt</label> | |
<textarea | |
rows="3" | |
className="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-transparent" | |
placeholder="Brief summary of your post" | |
></textarea> | |
</div> | |
<div> | |
<label className="block text-sm font-medium text-gray-700 mb-2">Full Content</label> | |
<textarea | |
rows="8" | |
className="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-transparent" | |
placeholder="Write your full guest post content here..." | |
></textarea> | |
</div> | |
<div className="flex gap-4 pt-4"> | |
<button | |
type="button" | |
onClick={() => setShowCreateModal(false)} | |
className="flex-1 px-6 py-3 border border-gray-300 text-gray-700 rounded-lg hover:bg-gray-50 transition-colors" | |
> | |
Cancel | |
</button> | |
<button | |
type="submit" | |
className="flex-1 px-6 py-3 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700 transition-colors" | |
> | |
Submit for Review | |
</button> | |
</div> | |
</form> | |
</div> | |
</div> | |
</div> | |
); | |
return ( | |
<div className="min-h-screen bg-gray-50"> | |
{/* Header */} | |
<header className="bg-white shadow-sm border-b"> | |
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> | |
<div className="flex justify-between items-center h-16"> | |
<div className="flex items-center"> | |
<div className="flex-shrink-0"> | |
<h1 className="text-2xl font-bold text-indigo-600">GuestPostHub</h1> | |
</div> | |
</div> | |
<nav className="hidden md:flex space-x-8"> | |
<a href="#" className="text-gray-900 hover:text-indigo-600 font-medium">Browse</a> | |
<a href="#" className="text-gray-500 hover:text-indigo-600 font-medium">My Posts</a> | |
<a href="#" className="text-gray-500 hover:text-indigo-600 font-medium">Community</a> | |
</nav> | |
<div className="flex items-center space-x-4"> | |
<button className="p-2 text-gray-400 hover:text-gray-600"> | |
<User className="h-6 w-6" /> | |
</button> | |
<button | |
onClick={() => setShowCreateModal(true)} | |
className="bg-indigo-600 text-white px-4 py-2 rounded-lg hover:bg-indigo-700 transition-colors flex items-center space-x-2" | |
> | |
<Plus className="h-4 w-4" /> | |
<span>Create Post</span> | |
</button> | |
</div> | |
</div> | |
</div> | |
</header> | |
{/* Hero Section */} | |
<section className="bg-gradient-to-r from-indigo-600 to-purple-600 text-white py-16"> | |
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center"> | |
<h1 className="text-4xl md:text-6xl font-bold mb-6">Share Your Voice, Expand Your Reach</h1> | |
<p className="text-xl md:text-2xl mb-8 text-indigo-100">Connect with publishers and writers for quality guest post exchanges</p> | |
<div className="flex flex-col sm:flex-row gap-4 justify-center"> | |
<button className="bg-white text-indigo-600 px-8 py-3 rounded-lg font-semibold hover:bg-gray-100 transition-colors"> | |
Find Guest Posts | |
</button> | |
<button | |
onClick={() => setShowCreateModal(true)} | |
className="border-2 border-white text-white px-8 py-3 rounded-lg font-semibold hover:bg-white hover:text-indigo-600 transition-colors" | |
> | |
Submit Your Post | |
</button> | |
</div> | |
</div> | |
</section> | |
{/* Stats Section */} | |
<section className="py-12 bg-white"> | |
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> | |
<div className="grid grid-cols-1 md:grid-cols-3 gap-8 text-center"> | |
<div className="p-6"> | |
<div className="flex justify-center mb-4"> | |
<Globe className="h-12 w-12 text-indigo-600" /> | |
</div> | |
<h3 className="text-3xl font-bold text-gray-900 mb-2">10K+</h3> | |
<p className="text-gray-600">Active Publishers</p> | |
</div> | |
<div className="p-6"> | |
<div className="flex justify-center mb-4"> | |
<Users className="h-12 w-12 text-indigo-600" /> | |
</div> | |
<h3 className="text-3xl font-bold text-gray-900 mb-2">50K+</h3> | |
<p className="text-gray-600">Writers Community</p> | |
</div> | |
<div className="p-6"> | |
<div className="flex justify-center mb-4"> | |
<TrendingUp className="h-12 w-12 text-indigo-600" /> | |
</div> | |
<h3 className="text-3xl font-bold text-gray-900 mb-2">100K+</h3> | |
<p className="text-gray-600">Posts Published</p> | |
</div> | |
</div> | |
</div> | |
</section> | |
{/* Main Content */} | |
<main className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12"> | |
{/* Search and Filter Bar */} | |
<div className="mb-8"> | |
<div className="flex flex-col lg:flex-row gap-4 items-center justify-between"> | |
<div className="relative flex-1 max-w-2xl"> | |
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 h-5 w-5" /> | |
<input | |
type="text" | |
placeholder="Search guest posts, topics, or authors..." | |
className="w-full pl-10 pr-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-transparent" | |
value={searchTerm} | |
onChange={(e) => setSearchTerm(e.target.value)} | |
/> | |
</div> | |
<div className="flex items-center space-x-4"> | |
<Filter className="h-5 w-5 text-gray-400" /> | |
<select | |
className="px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-transparent" | |
value={selectedCategory} | |
onChange={(e) => setSelectedCategory(e.target.value)} | |
> | |
{categories.map(category => ( | |
<option key={category.id} value={category.id}>{category.name}</option> | |
))} | |
</select> | |
</div> | |
</div> | |
</div> | |
{/* Categories */} | |
<div className="mb-8"> | |
<div className="flex flex-wrap gap-3"> | |
{categories.map(category => { | |
const IconComponent = category.icon; | |
return ( | |
<button | |
key={category.id} | |
onClick={() => setSelectedCategory(category.id)} | |
className={`flex items-center space-x-2 px-4 py-2 rounded-full transition-colors ${ | |
selectedCategory === category.id | |
? 'bg-indigo-600 text-white' | |
: 'bg-white text-gray-700 hover:bg-gray-100 border border-gray-300' | |
}`} | |
> | |
<IconComponent className="h-4 w-4" /> | |
<span>{category.name}</span> | |
</button> | |
); | |
})} | |
</div> | |
</div> | |
{/* Featured Posts */} | |
<section className="mb-12"> | |
<h2 className="text-2xl font-bold text-gray-900 mb-6">Featured Guest Posts</h2> | |
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8"> | |
{filteredPosts.filter(post => post.featured).map(post => ( | |
<div key={post.id} className="bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden hover:shadow-md transition-shadow"> | |
<div className="p-6"> | |
<div className="flex items-center justify-between mb-4"> | |
<span className="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-indigo-100 text-indigo-800"> | |
{post.category} | |
</span> | |
<span className="text-sm text-gray-500">{post.readTime}</span> | |
</div> | |
<h3 className="text-xl font-bold text-gray-900 mb-3">{post.title}</h3> | |
<p className="text-gray-600 mb-4">{post.excerpt}</p> | |
<div className="flex flex-wrap gap-2 mb-4"> | |
{post.tags.map(tag => ( | |
<span key={tag} className="inline-flex items-center px-2 py-1 rounded-md text-xs font-medium bg-gray-100 text-gray-800"> | |
<Tag className="h-3 w-3 mr-1" /> | |
{tag} | |
</span> | |
))} | |
</div> | |
<div className="flex items-center justify-between"> | |
<div className="flex items-center space-x-3"> | |
<img | |
src={post.authorAvatar} | |
alt={post.author} | |
className="h-10 w-10 rounded-full" | |
/> | |
<div> | |
<p className="text-sm font-medium text-gray-900">{post.author}</p> | |
<p className="text-sm text-gray-500">{new Date(post.date).toLocaleDateString()}</p> | |
</div> | |
</div> | |
<div className="flex items-center space-x-4"> | |
<button | |
onClick={() => handleLike(post.id)} | |
className="flex items-center space-x-1 text-gray-500 hover:text-red-500 transition-colors" | |
> | |
<Heart className="h-5 w-5" /> | |
<span className="text-sm">{post.likes}</span> | |
</button> | |
<button className="flex items-center space-x-1 text-gray-500 hover:text-indigo-600 transition-colors"> | |
<MessageCircle className="h-5 w-5" /> | |
<span className="text-sm">{post.comments}</span> | |
</button> | |
<button className="text-gray-500 hover:text-indigo-600 transition-colors"> | |
<Share2 className="h-5 w-5" /> | |
</button> | |
</div> | |
</div> | |
</div> | |
</div> | |
))} | |
</div> | |
</section> | |
{/* All Posts */} | |
<section> | |
<h2 className="text-2xl font-bold text-gray-900 mb-6">All Guest Posts</h2> | |
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"> | |
{filteredPosts.map(post => ( | |
<div key={post.id} className="bg-white rounded-lg shadow-sm border border-gray-200 overflow-hidden hover:shadow-md transition-shadow"> | |
<div className="p-5"> | |
<div className="flex items-center justify-between mb-3"> | |
<span className="inline-flex items-center px-2 py-1 rounded-md text-xs font-medium bg-gray-100 text-gray-800"> | |
{post.category} | |
</span> | |
<span className="text-xs text-gray-500">{post.readTime}</span> | |
</div> | |
<h3 className="text-lg font-semibold text-gray-900 mb-2 line-clamp-2">{post.title}</h3> | |
<p className="text-gray-600 text-sm mb-3 line-clamp-2">{post.excerpt}</p> | |
<div className="flex flex-wrap gap-1 mb-4"> | |
{post.tags.slice(0, 2).map(tag => ( | |
<span key={tag} className="inline-flex items-center px-2 py-1 rounded text-xs bg-gray-50 text-gray-600"> | |
{tag} | |
</span> | |
))} | |
{post.tags.length > 2 && ( | |
<span className="text-xs text-gray-500">+{post.tags.length - 2}</span> | |
)} | |
</div> | |
<div className="flex items-center justify-between"> | |
<div className="flex items-center space-x-2"> | |
<img | |
src={post.authorAvatar} | |
alt={post.author} | |
className="h-8 w-8 rounded-full" | |
/> | |
<div> | |
<p className="text-sm font-medium text-gray-900">{post.author}</p> | |
<p className="text-xs text-gray-500">{new Date(post.date).toLocaleDateString()}</p> | |
</div> | |
</div> | |
<div className="flex items-center space-x-2"> | |
<button | |
onClick={() => handleLike(post.id)} | |
className="flex items-center space-x-1 text-gray-500 hover:text-red-500 transition-colors" | |
> | |
<Heart className="h-4 w-4" /> | |
<span className="text-xs">{post.likes}</span> | |
</button> | |
<button className="flex items-center space-x-1 text-gray-500 hover:text-indigo-600 transition-colors"> | |
<MessageCircle className="h-4 w-4" /> | |
<span className="text-xs">{post.comments}</span> | |
</button> | |
</div> | |
</div> | |
</div> | |
</div> | |
))} | |
</div> | |
</section> | |
{filteredPosts.length === 0 && ( | |
<div className="text-center py-12"> | |
<p className="text-gray-500 text-lg">No guest posts found matching your criteria.</p> | |
</div> | |
)} | |
</main> | |
{/* Footer */} | |
<footer className="bg-gray-900 text-white py-12"> | |
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> | |
<div className="grid grid-cols-1 md:grid-cols-4 gap-8"> | |
<div> | |
<h3 className="text-xl font-bold mb-4">GuestPostHub</h3> | |
<p className="text-gray-400">Connecting writers and publishers for quality guest post exchanges.</p> | |
</div> | |
<div> | |
<h4 className="font-semibold mb-4">For Writers</h4> | |
<ul className="space-y-2 text-gray-400"> | |
<li><a href="#" className="hover:text-white transition-colors">Submit Posts</a></li> | |
<li><a href="#" className="hover:text-white transition-colors">Find Publishers</a></li> | |
<li><a href="#" className="hover:text-white transition-colors">Writing Tips</a></li> | |
</ul> | |
</div> | |
<div> | |
<h4 className="font-semibold mb-4">For Publishers</h4> | |
<ul className="space-y-2 text-gray-400"> | |
<li><a href="#" className="hover:text-white transition-colors">Post Opportunities</a></li> | |
<li><a href="#" className="hover:text-white transition-colors">Find Writers</a></li> | |
<li><a href="#" className="hover:text-white transition-colors">Publishing Guide</a></li> | |
</ul> | |
</div> | |
<div> | |
<h4 className="font-semibold mb-4">Support</h4> | |
<ul className="space-y-2 text-gray-400"> | |
<li><a href="#" className="hover:text-white transition-colors">Help Center</a></li> | |
<li><a href="#" className="hover:text-white transition-colors">Community</a></li> | |
<li><a href="#" className="hover:text-white transition-colors">Contact Us</a></li> | |
</ul> | |
</div> | |
</div> | |
<div className="border-t border-gray-800 mt-8 pt-8 text-center text-gray-400"> | |
<p>© 2024 GuestPostHub. All rights reserved.</p> | |
</div> | |
</div> | |
</footer> | |
{/* Create Post Modal */} | |
{showCreateModal && <CreatePostModal />} | |
</div> | |
); | |
}; | |
export default App; |