cryp2-1 / index.html
FAROU71's picture
Add 2 files
4b18f33 verified
Raw
History Blame Contribute Delete
75.9 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>DevVision | Developer Dashboard</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
/* Enhanced styles for better UX */
.gradient-bg {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.code-editor {
background: #1e293b;
border-radius: 0.5rem;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
}
.editor-header {
background: #0f172a;
border-top-left-radius: 0.5rem;
border-top-right-radius: 0.5rem;
}
.editor-dot {
width: 12px;
height: 12px;
border-radius: 50%;
display: inline-block;
margin-right: 6px;
}
.terminal {
background: #0f172a;
font-family: 'Courier New', monospace;
color: #4ade80;
}
.typing-effect::after {
content: '|';
animation: blink 1s step-end infinite;
}
@keyframes blink {
from, to { opacity: 1; }
50% { opacity: 0; }
}
.card-hover:hover {
transform: translateY(-5px);
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
}
.active-nav {
position: relative;
}
.active-nav::after {
content: '';
position: absolute;
bottom: -8px;
left: 0;
width: 100%;
height: 2px;
background: white;
}
.mobile-menu {
max-height: 0;
overflow: hidden;
transition: max-height 0.3s ease-out;
}
.mobile-menu.open {
max-height: 500px;
}
.snippet-code {
background: #1e293b;
color: #e2e8f0;
font-family: 'Courier New', monospace;
border-radius: 0.5rem;
}
.community-post {
transition: transform 0.2s;
}
.community-post:hover {
transform: translateX(5px);
}
/* Animation for route transitions */
.route-transition {
animation: fadeIn 0.3s ease-in-out;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
/* Custom scrollbar */
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-track {
background: #f1f1f1;
}
::-webkit-scrollbar-thumb {
background: #888;
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: #555;
}
</style>
</head>
<body class="bg-gray-100 font-sans antialiased">
<!-- Navigation -->
<nav class="gradient-bg text-white shadow-lg">
<div class="container mx-auto px-4 py-3 flex justify-between items-center">
<div class="flex items-center space-x-2 cursor-pointer" onclick="navigate('dashboard')">
<i class="fas fa-code text-2xl"></i>
<span class="text-xl font-bold">DevVision</span>
</div>
<div class="hidden md:flex space-x-6">
<a href="#" class="hover:text-gray-200 transition active-nav" id="nav-dashboard" onclick="navigate('dashboard')">Dashboard</a>
<a href="#" class="hover:text-gray-200 transition" id="nav-projects" onclick="navigate('projects')">Projects</a>
<a href="#" class="hover:text-gray-200 transition" id="nav-snippets" onclick="navigate('snippets')">Snippets</a>
<a href="#" class="hover:text-gray-200 transition" id="nav-community" onclick="navigate('community')">Community</a>
</div>
<div class="flex items-center space-x-4">
<button class="bg-white text-indigo-600 px-4 py-2 rounded-full font-medium hover:bg-gray-100 transition hidden md:block" onclick="showNewProjectModal()">
<i class="fas fa-plus mr-2"></i> New Project
</button>
<div class="relative cursor-pointer" onclick="toggleProfileMenu()">
<img src="https://randomuser.me/api/portraits/men/32.jpg" alt="Profile" class="w-10 h-10 rounded-full border-2 border-white">
<span class="absolute bottom-0 right-0 w-3 h-3 bg-green-500 rounded-full border-2 border-white"></span>
<div id="profile-menu" class="hidden absolute right-0 mt-2 w-48 bg-white rounded-md shadow-lg z-10">
<div class="py-1">
<a href="#" class="block px-4 py-2 text-gray-800 hover:bg-gray-100" onclick="navigate('profile')">Profile</a>
<a href="#" class="block px-4 py-2 text-gray-800 hover:bg-gray-100" onclick="navigate('settings')">Settings</a>
<a href="#" class="block px-4 py-2 text-gray-800 hover:bg-gray-100" onclick="logout()">Sign out</a>
</div>
</div>
</div>
<button class="md:hidden text-white" onclick="toggleMobileMenu()">
<i class="fas fa-bars text-xl"></i>
</button>
</div>
</div>
<!-- Mobile Menu -->
<div id="mobile-menu" class="mobile-menu md:hidden gradient-bg px-4">
<div class="py-2 space-y-3">
<a href="#" class="block py-2 text-white hover:text-gray-200" onclick="navigate('dashboard')">Dashboard</a>
<a href="#" class="block py-2 text-white hover:text-gray-200" onclick="navigate('projects')">Projects</a>
<a href="#" class="block py-2 text-white hover:text-gray-200" onclick="navigate('snippets')">Snippets</a>
<a href="#" class="block py-2 text-white hover:text-gray-200" onclick="navigate('community')">Community</a>
<button class="w-full bg-white text-indigo-600 px-4 py-2 rounded-full font-medium hover:bg-gray-100 transition mt-2" onclick="showNewProjectModal()">
<i class="fas fa-plus mr-2"></i> New Project
</button>
</div>
</div>
</nav>
<!-- Main Content Container -->
<div class="container mx-auto px-4 py-8">
<!-- Dashboard Content -->
<div id="dashboard-content" class="route-transition">
<!-- Welcome Banner -->
<div class="gradient-bg text-white rounded-xl p-6 mb-8 shadow-lg">
<div class="flex flex-col md:flex-row justify-between items-start md:items-center">
<div>
<h1 class="text-2xl md:text-3xl font-bold mb-2">Welcome back, Alex!</h1>
<p class="opacity-90">You have 3 active projects and 5 pending tasks. Let's make some progress today!</p>
</div>
<button class="mt-4 md:mt-0 bg-white text-indigo-600 px-6 py-2 rounded-full font-medium hover:bg-gray-100 transition flex items-center">
<i class="fas fa-rocket mr-2"></i> Quick Start
</button>
</div>
</div>
<!-- Stats Cards -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
<div class="bg-white rounded-xl p-6 shadow-md transition duration-300 card-hover">
<div class="flex justify-between items-center">
<div>
<p class="text-gray-500">Projects</p>
<h3 class="text-2xl font-bold">12</h3>
</div>
<div class="bg-indigo-100 text-indigo-600 p-3 rounded-full">
<i class="fas fa-folder-open text-xl"></i>
</div>
</div>
<div class="mt-4 pt-4 border-t border-gray-100">
<span class="text-green-500 text-sm font-medium">+2 this week</span>
</div>
</div>
<div class="bg-white rounded-xl p-6 shadow-md transition duration-300 card-hover">
<div class="flex justify-between items-center">
<div>
<p class="text-gray-500">Tasks</p>
<h3 class="text-2xl font-bold">24</h3>
</div>
<div class="bg-blue-100 text-blue-600 p-3 rounded-full">
<i class="fas fa-tasks text-xl"></i>
</div>
</div>
<div class="mt-4 pt-4 border-t border-gray-100">
<span class="text-yellow-500 text-sm font-medium">5 pending</span>
</div>
</div>
<div class="bg-white rounded-xl p-6 shadow-md transition duration-300 card-hover">
<div class="flex justify-between items-center">
<div>
<p class="text-gray-500">Snippets</p>
<h3 class="text-2xl font-bold">47</h3>
</div>
<div class="bg-green-100 text-green-600 p-3 rounded-full">
<i class="fas fa-code text-xl"></i>
</div>
</div>
<div class="mt-4 pt-4 border-t border-gray-100">
<span class="text-green-500 text-sm font-medium">+8 this month</span>
</div>
</div>
<div class="bg-white rounded-xl p-6 shadow-md transition duration-300 card-hover">
<div class="flex justify-between items-center">
<div>
<p class="text-gray-500">Streak</p>
<h3 class="text-2xl font-bold">18 days</h3>
</div>
<div class="bg-purple-100 text-purple-600 p-3 rounded-full">
<i class="fas fa-fire text-xl"></i>
</div>
</div>
<div class="mt-4 pt-4 border-t border-gray-100">
<span class="text-red-500 text-sm font-medium">Don't break it!</span>
</div>
</div>
</div>
<!-- Main Dashboard Content -->
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
<!-- Left Column -->
<div class="lg:col-span-2 space-y-6">
<!-- Code Editor -->
<div class="code-editor p-0 rounded-xl overflow-hidden">
<div class="editor-header px-4 py-3 flex items-center">
<div class="flex space-x-2 mr-4">
<span class="editor-dot bg-red-500"></span>
<span class="editor-dot bg-yellow-500"></span>
<span class="editor-dot bg-green-500"></span>
</div>
<div class="text-gray-300 text-sm">index.js</div>
</div>
<div class="p-4">
<pre class="text-gray-300 font-mono text-sm overflow-x-auto"><code><span class="text-purple-400">import</span> React <span class="text-purple-400">from</span> <span class="text-yellow-300">'react'</span>;
<span class="text-purple-400">import</span> { useState } <span class="text-purple-400">from</span> <span class="text-yellow-300">'react'</span>;
<span class="text-purple-400">function</span> <span class="text-blue-400">Counter</span>() {
<span class="text-purple-400">const</span> [count, setCount] = useState(<span class="text-green-400">0</span>);
<span class="text-purple-400">return</span> (
&lt;div className=<span class="text-yellow-300">"p-4"</span>&gt;
&lt;p&gt;You clicked {count} times&lt;/p&gt;
&lt;button
onClick={<span class="text-purple-400">()</span> <span class="text-purple-400">=></span> setCount(count + <span class="text-green-400">1</span>)}
className=<span class="text-yellow-300">"bg-blue-500 text-white px-4 py-2 rounded"</span>
&gt;
Click me
&lt;/button&gt;
&lt;/div&gt;
);
}
<span class="text-purple-400">export</span> <span class="text-purple-400">default</span> Counter;</code></pre>
</div>
</div>
<!-- Recent Projects -->
<div class="bg-white rounded-xl shadow-md p-6">
<div class="flex justify-between items-center mb-6">
<h2 class="text-xl font-bold">Recent Projects</h2>
<button class="text-indigo-600 hover:text-indigo-800 transition">
<i class="fas fa-ellipsis-h"></i>
</button>
</div>
<div class="space-y-4">
<div class="flex items-center p-3 hover:bg-gray-50 rounded-lg transition cursor-pointer" onclick="viewProject('ecommerce-dashboard')">
<div class="bg-indigo-100 text-indigo-600 p-3 rounded-lg mr-4">
<i class="fas fa-project-diagram"></i>
</div>
<div class="flex-1">
<h4 class="font-medium">E-commerce Dashboard</h4>
<p class="text-gray-500 text-sm">React, Node.js, MongoDB</p>
</div>
<div class="text-gray-500 text-sm">Updated 2h ago</div>
<div class="ml-4">
<i class="fas fa-chevron-right text-gray-400"></i>
</div>
</div>
<div class="flex items-center p-3 hover:bg-gray-50 rounded-lg transition cursor-pointer" onclick="viewProject('fitness-app')">
<div class="bg-blue-100 text-blue-600 p-3 rounded-lg mr-4">
<i class="fas fa-mobile-alt"></i>
</div>
<div class="flex-1">
<h4 class="font-medium">Fitness App</h4>
<p class="text-gray-500 text-sm">React Native, Firebase</p>
</div>
<div class="text-gray-500 text-sm">Updated yesterday</div>
<div class="ml-4">
<i class="fas fa-chevron-right text-gray-400"></i>
</div>
</div>
<div class="flex items-center p-3 hover:bg-gray-50 rounded-lg transition cursor-pointer" onclick="viewProject('portfolio-website')">
<div class="bg-green-100 text-green-600 p-3 rounded-lg mr-4">
<i class="fas fa-globe"></i>
</div>
<div class="flex-1">
<h4 class="font-medium">Portfolio Website</h4>
<p class="text-gray-500 text-sm">Next.js, Tailwind CSS</p>
</div>
<div class="text-gray-500 text-sm">Updated 3 days ago</div>
<div class="ml-4">
<i class="fas fa-chevron-right text-gray-400"></i>
</div>
</div>
</div>
<button class="mt-6 w-full py-2 border border-gray-200 rounded-lg text-indigo-600 hover:bg-gray-50 transition" onclick="navigate('projects')">
View All Projects
</button>
</div>
</div>
<!-- Right Column -->
<div class="space-y-6">
<!-- Quick Actions -->
<div class="bg-white rounded-xl shadow-md p-6">
<h2 class="text-xl font-bold mb-6">Quick Actions</h2>
<div class="grid grid-cols-2 gap-4">
<button class="flex flex-col items-center justify-center p-4 border border-gray-200 rounded-lg hover:bg-gray-50 transition" onclick="showNewSnippetModal()">
<div class="bg-indigo-100 text-indigo-600 p-3 rounded-full mb-2">
<i class="fas fa-file-code text-xl"></i>
</div>
<span class="text-sm">New Snippet</span>
</button>
<button class="flex flex-col items-center justify-center p-4 border border-gray-200 rounded-lg hover:bg-gray-50 transition" onclick="showNewProjectModal()">
<div class="bg-blue-100 text-blue-600 p-3 rounded-full mb-2">
<i class="fas fa-project-diagram text-xl"></i>
</div>
<span class="text-sm">New Project</span>
</button>
<button class="flex flex-col items-center justify-center p-4 border border-gray-200 rounded-lg hover:bg-gray-50 transition" onclick="showNewTaskModal()">
<div class="bg-green-100 text-green-600 p-3 rounded-full mb-2">
<i class="fas fa-tasks text-xl"></i>
</div>
<span class="text-sm">New Task</span>
</button>
<button class="flex flex-col items-center justify-center p-4 border border-gray-200 rounded-lg hover:bg-gray-50 transition" onclick="showTerminalModal()">
<div class="bg-purple-100 text-purple-600 p-3 rounded-full mb-2">
<i class="fas fa-terminal text-xl"></i>
</div>
<span class="text-sm">Run Script</span>
</button>
</div>
</div>
<!-- Terminal -->
<div class="terminal rounded-xl shadow-md overflow-hidden">
<div class="px-4 py-3 bg-gray-900 flex items-center">
<div class="flex space-x-2 mr-4">
<span class="editor-dot bg-red-500"></span>
<span class="editor-dot bg-yellow-500"></span>
<span class="editor-dot bg-green-500"></span>
</div>
<div class="text-gray-300 text-sm">bash</div>
</div>
<div class="p-4">
<div class="mb-2">
<span class="text-blue-400">user@devvision:~$</span> <span class="typing-effect" id="typing"></span>
</div>
<div id="terminal-output" class="text-sm"></div>
</div>
</div>
<!-- Upcoming Tasks -->
<div class="bg-white rounded-xl shadow-md p-6">
<div class="flex justify-between items-center mb-6">
<h2 class="text-xl font-bold">Upcoming Tasks</h2>
<button class="text-indigo-600 hover:text-indigo-800 transition" onclick="showNewTaskModal()">
<i class="fas fa-plus"></i>
</button>
</div>
<div class="space-y-4">
<div class="flex items-start">
<input type="checkbox" class="mt-1 mr-3" checked onclick="toggleTaskCompletion(this, 'task1')">
<div class="flex-1">
<h4 class="font-medium">Fix login bug</h4>
<p class="text-gray-500 text-sm">E-commerce project</p>
</div>
<span class="bg-green-100 text-green-800 text-xs px-2 py-1 rounded">Today</span>
</div>
<div class="flex items-start">
<input type="checkbox" class="mt-1 mr-3" onclick="toggleTaskCompletion(this, 'task2')">
<div class="flex-1">
<h4 class="font-medium">Implement dark mode</h4>
<p class="text-gray-500 text-sm">Portfolio website</p>
</div>
<span class="bg-blue-100 text-blue-800 text-xs px-2 py-1 rounded">Tomorrow</span>
</div>
<div class="flex items-start">
<input type="checkbox" class="mt-1 mr-3" onclick="toggleTaskCompletion(this, 'task3')">
<div class="flex-1">
<h4 class="font-medium">Write API documentation</h4>
<p class="text-gray-500 text-sm">Fitness app</p>
</div>
<span class="bg-yellow-100 text-yellow-800 text-xs px-2 py-1 rounded">Fri</span>
</div>
</div>
<button class="mt-6 w-full py-2 border border-gray-200 rounded-lg text-indigo-600 hover:bg-gray-50 transition" onclick="navigate('projects')">
View All Tasks
</button>
</div>
</div>
</div>
</div>
<!-- Projects Content -->
<div id="projects-content" class="hidden route-transition">
<div class="flex justify-between items-center mb-8">
<h1 class="text-2xl md:text-3xl font-bold">My Projects</h1>
<button class="bg-indigo-600 text-white px-4 py-2 rounded-full font-medium hover:bg-indigo-700 transition flex items-center" onclick="showNewProjectModal()">
<i class="fas fa-plus mr-2"></i> New Project
</button>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
<!-- Project Cards will be loaded dynamically -->
</div>
</div>
<!-- Snippets Content -->
<div id="snippets-content" class="hidden route-transition">
<div class="flex justify-between items-center mb-8">
<h1 class="text-2xl md:text-3xl font-bold">Code Snippets</h1>
<button class="bg-indigo-600 text-white px-4 py-2 rounded-full font-medium hover:bg-indigo-700 transition flex items-center" onclick="showNewSnippetModal()">
<i class="fas fa-plus mr-2"></i> New Snippet
</button>
</div>
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
<!-- Snippet Cards will be loaded dynamically -->
</div>
</div>
<!-- Community Content -->
<div id="community-content" class="hidden route-transition">
<div class="flex justify-between items-center mb-8">
<h1 class="text-2xl md:text-3xl font-bold">Dev Community</h1>
<button class="bg-indigo-600 text-white px-4 py-2 rounded-full font-medium hover:bg-indigo-700 transition flex items-center" onclick="showNewPostModal()">
<i class="fas fa-plus mr-2"></i> New Post
</button>
</div>
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
<!-- Community content will be loaded dynamically -->
</div>
</div>
<!-- Project Detail View -->
<div id="project-detail-content" class="hidden route-transition">
<!-- Project details will be loaded dynamically -->
</div>
<!-- Snippet Detail View -->
<div id="snippet-detail-content" class="hidden route-transition">
<!-- Snippet details will be loaded dynamically -->
</div>
<!-- Community Post Detail View -->
<div id="post-detail-content" class="hidden route-transition">
<!-- Post details will be loaded dynamically -->
</div>
<!-- Profile View -->
<div id="profile-content" class="hidden route-transition">
<!-- Profile content will be loaded dynamically -->
</div>
<!-- Settings View -->
<div id="settings-content" class="hidden route-transition">
<!-- Settings content will be loaded dynamically -->
</div>
</div>
<!-- Modals -->
<!-- New Project Modal -->
<div id="new-project-modal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden">
<div class="bg-white rounded-xl shadow-xl w-full max-w-md mx-4">
<div class="p-6">
<div class="flex justify-between items-center mb-4">
<h3 class="text-xl font-bold">Create New Project</h3>
<button class="text-gray-400 hover:text-gray-500" onclick="hideModal('new-project-modal')">
<i class="fas fa-times"></i>
</button>
</div>
<form id="new-project-form" onsubmit="createProject(event)">
<div class="space-y-4">
<div>
<label for="project-name" class="block text-sm font-medium text-gray-700 mb-1">Project Name</label>
<input type="text" id="project-name" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500" required>
</div>
<div>
<label for="project-description" class="block text-sm font-medium text-gray-700 mb-1">Description</label>
<textarea id="project-description" rows="3" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500"></textarea>
</div>
<div>
<label for="project-tech" class="block text-sm font-medium text-gray-700 mb-1">Technologies</label>
<select id="project-tech" multiple class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500">
<option value="react">React</option>
<option value="vue">Vue.js</option>
<option value="angular">Angular</option>
<option value="node">Node.js</option>
<option value="python">Python</option>
<option value="django">Django</option>
<option value="flask">Flask</option>
<option value="tailwind">Tailwind CSS</option>
</select>
</div>
<div>
<label for="project-template" class="block text-sm font-medium text-gray-700 mb-1">Template</label>
<select id="project-template" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500">
<option value="blank">Blank Project</option>
<option value="react">React Starter</option>
<option value="vue">Vue Starter</option>
<option value="node">Node.js API</option>
<option value="fullstack">Fullstack App</option>
</select>
</div>
</div>
<div class="mt-6 flex justify-end space-x-3">
<button type="button" class="px-4 py-2 border border-gray-300 rounded-lg text-gray-700 hover:bg-gray-50" onclick="hideModal('new-project-modal')">
Cancel
</button>
<button type="submit" class="px-4 py-2 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700">
Create Project
</button>
</div>
</form>
</div>
</div>
</div>
<!-- New Snippet Modal -->
<div id="new-snippet-modal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden">
<div class="bg-white rounded-xl shadow-xl w-full max-w-2xl mx-4">
<div class="p-6">
<div class="flex justify-between items-center mb-4">
<h3 class="text-xl font-bold">Create New Code Snippet</h3>
<button class="text-gray-400 hover:text-gray-500" onclick="hideModal('new-snippet-modal')">
<i class="fas fa-times"></i>
</button>
</div>
<form id="new-snippet-form" onsubmit="createSnippet(event)">
<div class="space-y-4">
<div>
<label for="snippet-title" class="block text-sm font-medium text-gray-700 mb-1">Title</label>
<input type="text" id="snippet-title" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500" required>
</div>
<div>
<label for="snippet-description" class="block text-sm font-medium text-gray-700 mb-1">Description</label>
<textarea id="snippet-description" rows="2" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500"></textarea>
</div>
<div>
<label for="snippet-language" class="block text-sm font-medium text-gray-700 mb-1">Language</label>
<select id="snippet-language" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500">
<option value="javascript">JavaScript</option>
<option value="typescript">TypeScript</option>
<option value="python">Python</option>
<option value="java">Java</option>
<option value="csharp">C#</option>
<option value="php">PHP</option>
<option value="html">HTML</option>
<option value="css">CSS</option>
<option value="sql">SQL</option>
</select>
</div>
<div>
<label for="snippet-code" class="block text-sm font-medium text-gray-700 mb-1">Code</label>
<textarea id="snippet-code" rows="10" class="w-full px-3 py-2 border border-gray-300 rounded-lg font-mono text-sm focus:outline-none focus:ring-2 focus:ring-indigo-500" required></textarea>
</div>
<div>
<label for="snippet-tags" class="block text-sm font-medium text-gray-700 mb-1">Tags</label>
<input type="text" id="snippet-tags" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500" placeholder="react, hooks, api">
</div>
</div>
<div class="mt-6 flex justify-end space-x-3">
<button type="button" class="px-4 py-2 border border-gray-300 rounded-lg text-gray-700 hover:bg-gray-50" onclick="hideModal('new-snippet-modal')">
Cancel
</button>
<button type="submit" class="px-4 py-2 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700">
Save Snippet
</button>
</div>
</form>
</div>
</div>
</div>
<!-- New Task Modal -->
<div id="new-task-modal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden">
<div class="bg-white rounded-xl shadow-xl w-full max-w-md mx-4">
<div class="p-6">
<div class="flex justify-between items-center mb-4">
<h3 class="text-xl font-bold">Add New Task</h3>
<button class="text-gray-400 hover:text-gray-500" onclick="hideModal('new-task-modal')">
<i class="fas fa-times"></i>
</button>
</div>
<form id="new-task-form" onsubmit="createTask(event)">
<div class="space-y-4">
<div>
<label for="task-title" class="block text-sm font-medium text-gray-700 mb-1">Task Title</label>
<input type="text" id="task-title" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500" required>
</div>
<div>
<label for="task-project" class="block text-sm font-medium text-gray-700 mb-1">Project</label>
<select id="task-project" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500">
<option value="">Select Project</option>
<option value="ecommerce-dashboard">E-commerce Dashboard</option>
<option value="fitness-app">Fitness App</option>
<option value="portfolio-website">Portfolio Website</option>
</select>
</div>
<div>
<label for="task-due-date" class="block text-sm font-medium text-gray-700 mb-1">Due Date</label>
<input type="date" id="task-due-date" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500">
</div>
<div>
<label for="task-priority" class="block text-sm font-medium text-gray-700 mb-1">Priority</label>
<select id="task-priority" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500">
<option value="low">Low</option>
<option value="medium">Medium</option>
<option value="high">High</option>
</select>
</div>
<div>
<label for="task-description" class="block text-sm font-medium text-gray-700 mb-1">Description</label>
<textarea id="task-description" rows="3" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500"></textarea>
</div>
</div>
<div class="mt-6 flex justify-end space-x-3">
<button type="button" class="px-4 py-2 border border-gray-300 rounded-lg text-gray-700 hover:bg-gray-50" onclick="hideModal('new-task-modal')">
Cancel
</button>
<button type="submit" class="px-4 py-2 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700">
Add Task
</button>
</div>
</form>
</div>
</div>
</div>
<!-- Terminal Modal -->
<div id="terminal-modal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden">
<div class="bg-gray-900 rounded-xl shadow-xl w-full max-w-4xl mx-4 overflow-hidden">
<div class="px-4 py-3 flex items-center justify-between bg-gray-800">
<div class="flex items-center">
<div class="flex space-x-2 mr-4">
<span class="editor-dot bg-red-500"></span>
<span class="editor-dot bg-yellow-500"></span>
<span class="editor-dot bg-green-500"></span>
</div>
<div class="text-gray-300 text-sm">Terminal</div>
</div>
<button class="text-gray-400 hover:text-gray-500" onclick="hideModal('terminal-modal')">
<i class="fas fa-times"></i>
</button>
</div>
<div class="p-4 h-96 overflow-y-auto">
<div id="terminal-full-output" class="text-sm font-mono text-green-400"></div>
<div class="flex items-center mt-2">
<span class="text-blue-400">user@devvision:~$</span>
<input type="text" id="terminal-input" class="flex-1 bg-transparent border-none text-green-400 outline-none ml-2" autofocus>
</div>
</div>
</div>
</div>
<!-- New Post Modal -->
<div id="new-post-modal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden">
<div class="bg-white rounded-xl shadow-xl w-full max-w-2xl mx-4">
<div class="p-6">
<div class="flex justify-between items-center mb-4">
<h3 class="text-xl font-bold">Create New Post</h3>
<button class="text-gray-400 hover:text-gray-500" onclick="hideModal('new-post-modal')">
<i class="fas fa-times"></i>
</button>
</div>
<form id="new-post-form" onsubmit="createPost(event)">
<div class="space-y-4">
<div>
<label for="post-title" class="block text-sm font-medium text-gray-700 mb-1">Title</label>
<input type="text" id="post-title" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500" required>
</div>
<div>
<label for="post-content" class="block text-sm font-medium text-gray-700 mb-1">Content</label>
<textarea id="post-content" rows="8" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500" required></textarea>
</div>
<div>
<label for="post-tags" class="block text-sm font-medium text-gray-700 mb-1">Tags</label>
<select id="post-tags" multiple class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500">
<option value="react">React</option>
<option value="javascript">JavaScript</option>
<option value="css">CSS</option>
<option value="node">Node.js</option>
<option value="python">Python</option>
<option value="database">Database</option>
<option value="webdev">Web Development</option>
<option value="mobile">Mobile</option>
</select>
</div>
<div>
<label for="post-code" class="block text-sm font-medium text-gray-700 mb-1">Code (optional)</label>
<textarea id="post-code" rows="5" class="w-full px-3 py-2 border border-gray-300 rounded-lg font-mono text-sm focus:outline-none focus:ring-2 focus:ring-indigo-500"></textarea>
</div>
</div>
<div class="mt-6 flex justify-end space-x-3">
<button type="button" class="px-4 py-2 border border-gray-300 rounded-lg text-gray-700 hover:bg-gray-50" onclick="hideModal('new-post-modal')">
Cancel
</button>
<button type="submit" class="px-4 py-2 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700">
Publish Post
</button>
</div>
</form>
</div>
</div>
</div>
<!-- Confirmation Modal -->
<div id="confirmation-modal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden">
<div class="bg-white rounded-xl shadow-xl w-full max-w-md mx-4">
<div class="p-6">
<div class="flex justify-between items-center mb-4">
<h3 class="text-xl font-bold" id="confirmation-title">Confirm Action</h3>
<button class="text-gray-400 hover:text-gray-500" onclick="hideModal('confirmation-modal')">
<i class="fas fa-times"></i>
</button>
</div>
<p class="text-gray-700 mb-6" id="confirmation-message">Are you sure you want to perform this action?</p>
<div class="flex justify-end space-x-3">
<button type="button" class="px-4 py-2 border border-gray-300 rounded-lg text-gray-700 hover:bg-gray-50" onclick="hideModal('confirmation-modal')">
Cancel
</button>
<button type="button" class="px-4 py-2 bg-red-600 text-white rounded-lg hover:bg-red-700" onclick="confirmAction()">
Confirm
</button>
</div>
</div>
</div>
</div>
<!-- Notification Toast -->
<div id="notification-toast" class="fixed bottom-4 right-4 bg-gray-800 text-white px-6 py-3 rounded-lg shadow-lg transform translate-y-10 opacity-0 transition-all duration-300 z-50">
<div class="flex items-center">
<i class="fas fa-check-circle text-green-400 mr-3" id="toast-icon"></i>
<span id="toast-message">Action completed successfully</span>
</div>
</div>
<script>
// State management
const state = {
currentUser: {
id: 1,
name: "Alex Turner",
email: "alex@example.com",
avatar: "https://randomuser.me/api/portraits/men/32.jpg",
role: "developer",
joined: "2022-01-15",
lastActive: "2023-06-20"
},
projects: [
{
id: "ecommerce-dashboard",
name: "E-commerce Dashboard",
description: "Admin dashboard for online store",
technologies: ["React", "Node.js", "MongoDB"],
status: "active",
createdAt: "2023-05-10",
updatedAt: "2023-06-20",
collaborators: [
{ id: 2, name: "Sarah Johnson", avatar: "https://randomuser.me/api/portraits/women/44.jpg" },
{ id: 3, name: "Michael Chen", avatar: "https://randomuser.me/api/portraits/men/75.jpg" }
],
tasks: [
{ id: "task1", title: "Fix login bug", completed: true, dueDate: "2023-06-20", priority: "high" },
{ id: "task2", title: "Add product filters", completed: false, dueDate: "2023-06-25", priority: "medium" }
]
},
{
id: "fitness-app",
name: "Fitness App",
description: "Mobile app for workout tracking",
technologies: ["React Native", "Firebase"],
status: "active",
createdAt: "2023-04-15",
updatedAt: "2023-06-19",
collaborators: [],
tasks: [
{ id: "task3", title: "Implement dark mode", completed: false, dueDate: "2023-06-23", priority: "medium" }
]
},
{
id: "portfolio-website",
name: "Portfolio Website",
description: "Personal portfolio website",
technologies: ["Next.js", "Tailwind CSS"],
status: "active",
createdAt: "2023-03-20",
updatedAt: "2023-06-17",
collaborators: [],
tasks: [
{ id: "task4", title: "Write API documentation", completed: false, dueDate: "2023-06-24", priority: "low" }
]
},
{
id: "blog-platform",
name: "Blog Platform",
description: "Content management system",
technologies: ["Vue.js", "Django"],
status: "paused",
createdAt: "2023-02-05",
updatedAt: "2023-06-10",
collaborators: [
{ id: 4, name: "Emma Wilson", avatar: "https://randomuser.me/api/portraits/women/68.jpg" }
],
tasks: []
},
{
id: "weather-app",
name: "Weather App",
description: "Real-time weather forecasts",
technologies: ["React", "API"],
status: "completed",
createdAt: "2023-01-12",
updatedAt: "2023-05-30",
collaborators: [],
tasks: []
}
],
snippets: [
{
id: "snippet1",
title: "React Hook: useFetch",
description: "Custom hook for API calls",
language: "javascript",
code: `import { useState, useEffect } from 'react';
const useFetch = (url) => {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch(url);
const json = await response.json();
setData(json);
} catch (err) {
setError(err);
} finally {
setLoading(false);
}
};
fetchData();
}, [url]);
return { data, loading, error };
};
export default useFetch;`,
tags: ["react", "hooks", "api"],
createdAt: "2023-06-15",
updatedAt: "2023-06-15"
},
{
id: "snippet2",
title: "Debounce Function",
description: "JavaScript utility function",
language: "javascript",
code: `function debounce(func, wait, immediate) {
let timeout;
return function() {
const context = this;
const args = arguments;
const later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
const callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
}
// Usage:
const myEfficientFn = debounce(function() {
// All the taxing stuff you do
}, 250);
window.addEventListener('resize', myEfficientFn);`,
tags: ["javascript", "utility"],
createdAt: "2023-06-01",
updatedAt: "2023-06-01"
},
{
id: "snippet3",
title: "Tailwind Button",
description: "Reusable button component",
language: "javascript",
code: `import React from 'react';
const Button = ({
children,
variant = 'primary',
size = 'md',
disabled = false,
className = '',
...props
}) => {
const baseClasses = \`rounded-lg font-medium transition-all flex items-center justify-center\`;
const variantClasses = {
primary: \`bg-indigo-600 text-white hover:bg-indigo-700\`,
secondary: \`bg-gray-200 text-gray-800 hover:bg-gray-300\`,
danger: \`bg-red-600 text-white hover:bg-red-700\`,
};
const sizeClasses = {
sm: \`py-1 px-3 text-sm\`,
md: \`py-2 px-4\`,
lg: \`py-3 px-6 text-lg\`,
};
return (
<button
className={\`\${baseClasses} \${variantClasses[variant]} \${sizeClasses[size]} \${className}\`}
disabled={disabled}
{...props}
>
{children}
</button>
);
};
export default Button;`,
tags: ["react", "tailwind", "components"],
createdAt: "2023-05-20",
updatedAt: "2023-05-20"
},
{
id: "snippet4",
title: "LocalStorage Hook",
description: "Persist state with localStorage",
language: "javascript",
code: `import { useState, useEffect } from 'react';
function useLocalStorage(key, initialValue) {
const [storedValue, setStoredValue] = useState(() => {
try {
const item = window.localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
} catch (error) {
console.log(error);
return initialValue;
}
});
const setValue = (value) => {
try {
const valueToStore =
value instanceof Function ? value(storedValue) : value;
setStoredValue(valueToStore);
window.localStorage.setItem(key, JSON.stringify(valueToStore));
} catch (error) {
console.log(error);
}
};
return [storedValue, setValue];
}
export default useLocalStorage;`,
tags: ["react", "hooks", "localstorage"],
createdAt: "2023-05-10",
updatedAt: "2023-05-10"
}
],
communityPosts: [
{
id: "post1",
title: "How to optimize React performance?",
content: "I've been working on a large React application and noticed some performance issues, especially with re-renders. What are some best practices to optimize React performance in 2023?",
author: {
id: 2,
name: "Sarah Johnson",
avatar: "https://randomuser.me/api/portraits/women/44.jpg",
role: "senior developer"
},
tags: ["react", "performance"],
createdAt: "2023-06-20",
updatedAt: "2023-06-20",
comments: 14,
likes: 32,
views: 156
},
{
id: "post2",
title: "Tailwind CSS vs. Traditional CSS",
content: "I'm starting a new project and debating between using Tailwind CSS or writing traditional CSS. For those who have used both, what are the pros and cons of each approach?",
author: {
id: 3,
name: "Michael Chen",
avatar: "https://randomuser.me/api/portraits/men/75.jpg",
role: "frontend lead"
},
tags: ["css", "tailwind"],
createdAt: "2023-06-19",
updatedAt: "2023-06-19",
comments: 27,
likes: 45,
views: 210
},
{
id: "post3",
title: "State management in 2023",
content: "With so many state management options available (Redux, Context API, Zustand, Jotai, etc.), how do you decide which one to use for a new project? What are the current best practices?",
author: {
id: 4,
name: "Emma Wilson",
avatar: "https://randomuser.me/api/portraits/women/68.jpg",
role: "fullstack developer"
},
tags: ["javascript", "react", "state"],
createdAt: "2023-06-18",
updatedAt: "2023-06-18",
comments: 38,
likes: 72,
views: 320
},
{
id: "post4",
title: "Building a full-stack app with Next.js",
content: "I'm documenting my journey building a full-stack application with Next.js, Prisma, and PostgreSQL. Here are some lessons learned and patterns I've found useful...",
author: {
id: 1,
name: "Alex Turner",
avatar: "https://randomuser.me/api/portraits/men/32.jpg",
role: "developer"
},
tags: ["nextjs", "fullstack", "prisma"],
createdAt: "2023-06-17",
updatedAt: "2023-06-17",
comments: 22,
likes: 56,
views: 189
}
],
currentRoute: "dashboard",
pendingAction: null,
terminalHistory: []
};
// DOM Elements
const elements = {
contentContainers: {
dashboard: document.getElementById('dashboard-content'),
projects: document.getElementById('projects-content'),
snippets: document.getElementById('snippets-content'),
community: document.getElementById('community-content'),
projectDetail: document.getElementById('project-detail-content'),
snippetDetail: document.getElementById('snippet-detail-content'),
postDetail: document.getElementById('post-detail-content'),
profile: document.getElementById('profile-content'),
settings: document.getElementById('settings-content')
},
navLinks: {
dashboard: document.getElementById('nav-dashboard'),
projects: document.getElementById('nav-projects'),
snippets: document.getElementById('nav-snippets'),
community: document.getElementById('nav-community')
},
modals: {
newProject: document.getElementById('new-project-modal'),
newSnippet: document.getElementById('new-snippet-modal'),
newTask: document.getElementById('new-task-modal'),
terminal: document.getElementById('terminal-modal'),
newPost: document.getElementById('new-post-modal'),
confirmation: document.getElementById('confirmation-modal')
},
forms: {
newProject: document.getElementById('new-project-form'),
newSnippet: document.getElementById('new-snippet-form'),
newTask: document.getElementById('new-task-form'),
newPost: document.getElementById('new-post-form')
},
terminal: {
input: document.getElementById('terminal-input'),
output: document.getElementById('terminal-output'),
fullOutput: document.getElementById('terminal-full-output')
},
notification: document.getElementById('notification-toast')
};
// Utility functions
function formatDate(dateString) {
const date = new Date(dateString);
const now = new Date();
const diffInDays = Math.floor((now - date) / (1000 * 60 * 60 * 24));
if (diffInDays === 0) return "Today";
if (diffInDays === 1) return "Yesterday";
if (diffInDays < 7) return `${diffInDays} days ago`;
if (diffInDays < 30) return `${Math.floor(diffInDays / 7)} weeks ago`;
return date.toLocaleDateString();
}
function showNotification(message, isSuccess = true) {
const toast = elements.notification;
const icon = document.getElementById('toast-icon');
const toastMessage = document.getElementById('toast-message');
toastMessage.textContent = message;
icon.className = isSuccess ? 'fas fa-check-circle text-green-400 mr-3' : 'fas fa-exclamation-circle text-red-400 mr-3';
toast.classList.remove('translate-y-10', 'opacity-0');
toast.classList.add('translate-y-0', 'opacity-100');
setTimeout(() => {
toast.classList.remove('translate-y-0', 'opacity-100');
toast.classList.add('translate-y-10', 'opacity-0');
}, 3000);
}
function showModal(modalId) {
elements.modals[modalId].classList.remove('hidden');
document.body.classList.add('overflow-hidden');
}
function hideModal(modalId) {
elements.modals[modalId].classList.add('hidden');
document.body.classList.remove('overflow-hidden');
}
function showConfirmation(title, message, action) {
document.getElementById('confirmation-title').textContent = title;
document.getElementById('confirmation-message').textContent = message;
state.pendingAction = action;
showModal('confirmation');
}
function confirmAction() {
if (state.pendingAction) {
state.pendingAction();
state.pendingAction = null;
}
hideModal('confirmation');
}
// Routing functions
function navigate(route, params = {}) {
// Hide all content containers
Object.values(elements.contentContainers).forEach(container => {
container.classList.add('hidden');
});
// Update active nav link
Object.values(elements.navLinks).forEach(link => {
link.classList.remove('active-nav');
});
// Set new route
state.currentRoute = route;
// Show the appropriate content
switch (route) {
case 'dashboard':
elements.navLinks.dashboard.classList.add('active-nav');
elements.contentContainers.dashboard.classList.remove('hidden');
break;
case 'projects':
elements.navLinks.projects.classList.add('active-nav');
elements.contentContainers.projects.classList.remove('hidden');
renderProjects();
break;
case 'snippets':
elements.navLinks.snippets.classList.add('active-nav');
elements.contentContainers.snippets.classList.remove('hidden');
renderSnippets();
break;
case 'community':
elements.navLinks.community.classList.add('active-nav');
elements.contentContainers.community.classList.remove('hidden');
renderCommunity();
break;
case 'project':
elements.contentContainers.projectDetail.classList.remove('hidden');
renderProjectDetail(params.id);
break;
case 'snippet':
elements.contentContainers.snippetDetail.classList.remove('hidden');
renderSnippetDetail(params.id);
break;
case 'post':
elements.contentContainers.postDetail.classList.remove('hidden');
renderPostDetail(params.id);
break;
case 'profile':
elements.contentContainers.profile.classList.remove('hidden');
renderProfile();
break;
case 'settings':
elements.contentContainers.settings.classList.remove('hidden');
renderSettings();
break;
}
}
// Render functions
function renderProjects() {
const container = document.querySelector('#projects-content .grid');
container.innerHTML = '';
state.projects.forEach(project => {
const projectCard = document.createElement('div');
projectCard.className = 'bg-white rounded-xl shadow-md overflow-hidden transition duration-300 card-hover cursor-pointer';
projectCard.onclick = () => navigate('project', { id: project.id });
const statusColors = {
active: 'bg-indigo-600',
paused: 'bg-yellow-600',
completed: 'bg-green-600'
};
projectCard.innerHTML = `
<div class="${statusColors[project.status] || 'bg-indigo-600'} p-4 text-white">
<div class="flex justify-between items-center">
<h3 class="font-bold text-lg">${project.name}</h3>
<div class="flex space-x-2">
${project.technologies.slice(0, 2).map(tech =>
`<span class="bg-white bg-opacity-20 px-2 py-1 rounded-full text-xs">${tech}</span>`
).join('')}
</div>
</div>
<p class="text-sm opacity-90 mt-2">${project.description}</p>
</div>
<div class="p-4">
<div class="flex justify-between items-center text-sm text-gray-500 mb-3">
<span><i class="fas fa-calendar-alt mr-1"></i> Last updated: ${formatDate(project.updatedAt)}</span>
<span><i class="fas fa-code-branch mr-1"></i> main</span>
</div>
<div class="flex justify-between items-center">
<div class="flex -space-x-2">
${project.collaborators.slice(0, 3).map((collab, index) =>
`<img src="${collab.avatar}" class="w-8 h-8 rounded-full border-2 border-white" alt="${collab.name}" title="${collab.name}">`
).join('')}
${project.collaborators.length > 3 ?
`<div class="w-8 h-8 rounded-full border-2 border-white bg-gray-200 flex items-center justify-center text-xs">+${project.collaborators.length - 3}</div>` : ''}
</div>
<div class="text-indigo-600 text-sm font-medium">View Project</div>
</div>
</div>
`;
container.appendChild(projectCard);
});
// Add "New Project" card
const newProjectCard = document.createElement('div');
newProjectCard.className = 'bg-white rounded-xl shadow-md overflow-hidden transition duration-300 card-hover cursor-pointer border-2 border-dashed border-gray-300 flex items-center justify-center';
newProjectCard.onclick = () => showModal('newProject');
newProjectCard.innerHTML = `
<div class="text-center p-6">
<div class="bg-indigo-100 text-indigo-600 p-4 rounded-full inline-block mb-3">
<i class="fas fa-plus text-xl"></i>
</div>
<h3 class="font-bold text-lg text-gray-700">Add New Project</h3>
<p class="text-sm text-gray-500 mt-1">Start a new coding adventure</p>
</div>
`;
container.appendChild(newProjectCard);
}
function renderSnippets() {
const container = document.querySelector('#snippets-content .grid');
container.innerHTML = '';
state.snippets.forEach(snippet => {
const snippetCard = document.createElement('div');
snippetCard.className = 'bg-white rounded-xl shadow-md overflow-hidden';
snippetCard.innerHTML = `
<div class="p-4 border-b border-gray-200">
<div class="flex justify-between items-center">
<h3 class="font-bold text-lg">${snippet.title}</h3>
<div class="flex space-x-2">
<button class="text-gray-400 hover:text-indigo-600" onclick="copySnippet('${snippet.id}')">
<i class="fas fa-copy"></i>
</button>
<button class="text-gray-400 hover:text-red-600" onclick="deleteSnippetPrompt('${snippet.id}')">
<i class="fas fa-trash"></i>
</button>
</div>
</div>
<p class="text-sm text-gray-500 mt-1">${snippet.description}</p>
</div>
<div class="p-4 snippet-code">
<pre class="text-sm overflow-x-auto"><code>${snippet.code}</code></pre>
</div>
<div class="p-4 border-t border-gray-200 text-sm text-gray-500">
<div class="flex justify-between items-center">
<span>Created: ${formatDate(snippet.createdAt)}</span>
<span class="bg-indigo-100 text-indigo-800 px-2 py-1 rounded-full text-xs">${snippet.language}</span>
</div>
</div>
`;
container.appendChild(snippetCard);
});
// Add "New Snippet" card
const newSnippetCard = document.createElement('div');
newSnippetCard.className = 'bg-white rounded-xl shadow-md overflow-hidden transition duration-300 card-hover cursor-pointer border-2 border-dashed border-gray-300 flex items-center justify-center';
newSnippetCard.onclick = () => showModal('newSnippet');
newSnippetCard.innerHTML = `
<div class="text-center p-6">
<div class="bg-indigo-100 text-indigo-600 p-4 rounded-full inline-block mb-3">
<i class="fas fa-plus text-xl"></i>
</div>
<h3 class="font-bold text-lg text-gray-700">Add New Snippet</h3>
<p class="text-sm text-gray-500 mt-1">Save your useful code pieces</p>
</div>
`;
container.appendChild(newSnippetCard);
}
function renderCommunity() {
const mainContainer = document.querySelector('#community-content .lg\\:col-span-2');
const sidebarContainer = document.querySelector('#community-content .lg\\:col-span-1');
// Clear existing content
mainContainer.querySelector('.space-y-4').innerHTML = '';
sidebarContainer.innerHTML = '';
// Render posts
state.communityPosts.forEach(post => {
const postElement = document.createElement('div');
postElement.className = 'bg-white rounded-xl shadow-md p-6 community-post cursor-pointer';
postElement.onclick = () => navigate('post', { id: post.id });
postElement.innerHTML = `
<div class="flex items-start space-x-4">
<img src="${post.author.avatar}" alt="User" class="w-12 h-12 rounded-full">
<div class="flex-1">
<div class="flex justify-between items-start">
<div>
<h3 class="font-bold text-lg">${post.title}</h3>
<p class="text-sm text-gray-500">Posted by ${post.author.name}${formatDate(post.createdAt)}</p>
</div>
<span class="bg-indigo-100 text-indigo-800 px-2 py-1 rounded-full text-xs">${post.tags[0]}</span>
</div>
<p class="mt-2 text-gray-700">${post.content}</p>
<div class="mt-4 flex items-center space-x-6 text-sm text-gray-500">
<span><i class="far fa-comment mr-1"></i> ${post.comments} comments</span>
<span><i class="far fa-heart mr-1"></i> ${post.likes} likes</span>
<span><i class="fas fa-share mr-1"></i> Share</span>
</div>
</div>
</div>
`;
mainContainer.querySelector('.space-y-4').appendChild(postElement);
});
// Render sidebar sections
sidebarContainer.innerHTML = `
<!-- Popular Topics -->
<div class="bg-white rounded-xl shadow-md p-6">
<h3 class="font-bold text-lg mb-4">Popular Topics</h3>
<div class="space-y-3">
<a href="#" class="flex items-center justify-between p-2 hover:bg-gray-50 rounded-lg transition">
<div class="flex items-center space-x-3">
<div class="bg-indigo-100 text-indigo-600 p-2 rounded-lg">
<i class="fab fa-react"></i>
</div>
<span>React</span>
</div>
<span class="bg-gray-100 text-gray-800 px-2 py-1 rounded-full text-xs">142 posts</span>
</a>
<a href="#" class="flex items-center justify-between p-2 hover:bg-gray-50 rounded-lg transition">
<div class="flex items-center space-x-3">
<div class="bg-blue-100 text-blue-600 p-2 rounded-lg">
<i class="fab fa-js"></i>
</div>
<span>JavaScript</span>
</div>
<span class="bg-gray-100 text-gray-800 px-2 py-1 rounded-full text-xs">98 posts</span>
</a>
<a href="#" class="flex items-center justify-between p-2 hover:bg-gray-50 rounded-lg transition">
<div class="flex items-center space-x-3">
<div class="bg-green-100 text-green-600 p-2 rounded-lg">
<i class="fab fa-css3-alt"></i>
</div>
<span>CSS</span>
</div>
<span class="bg-gray-100 text-gray-800 px-2 py-1 rounded-full text-xs">76 posts</span>
</a>
<a href="#" class="flex items-center justify-between p-2 hover:bg-gray-50 rounded-lg transition">
<div class="flex items-center space-x-3">
<div class="bg-purple-100 text-purple-600 p-2 rounded-lg">
<i class="fab fa-node-js"></i>
</div>
<span>Node.js</span>
</div>
<span class="bg-gray-100 text-gray-800 px-2 py-1 rounded-full text-xs">64 posts</span>
</a>
<a href="#" class="flex items-center justify-between p-2 hover:bg-gray-50 rounded-lg transition">
<div class="flex items-center space-x-3">
<div class="bg-yellow-100 text-yellow-600 p-2 rounded-lg">
<i class="fas fa-database"></i>
</div>
<span>Database</span>
</div>
<span class="bg-gray-100 text-gray-800 px-2 py-1 rounded-full text-xs">52 posts</span>
</a>
</div>
</div>
<!-- Top Contributors -->
<div class="bg-white rounded-xl shadow-md p-6 mt-6">
<h3 class="font-bold text-lg mb-4">Top Contributors</h3>
<div class="space-y-4">
<div class="flex items-center space-x-3">
<img src="https://randomuser.me/api/portraits/women/44.jpg" alt="User" class="w-10 h-10 rounded-full">
<div class="flex-1">
<h4 class="font-medium">Sarah Johnson</h4>
<p class="text-sm text-gray-500">React Expert</p>
</div>
<
</html>