weatherinsight / index.html
Tame342's picture
Add 2 files
8bfb998 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Decentralized Twitter Clone</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>
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
body {
font-family: 'Inter', sans-serif;
background-color: #f0f2f5;
}
.gradient-bg {
background: linear-gradient(135deg, #1DA1F2 0%, #0d8ddb 100%);
}
.post-animation {
transition: all 0.2s ease;
}
.post-animation:hover {
transform: translateY(-2px);
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
}
.like-animation {
transition: all 0.3s ease;
}
.like-animation:hover {
transform: scale(1.1);
}
.active-tab {
border-bottom: 3px solid #1DA1F2;
font-weight: 600;
color: #1DA1F2;
}
/* Custom scrollbar */
::-webkit-scrollbar {
width: 6px;
}
::-webkit-scrollbar-track {
background: #f1f1f1;
}
::-webkit-scrollbar-thumb {
background: #1DA1F2;
border-radius: 3px;
}
::-webkit-scrollbar-thumb:hover {
background: #0d8ddb;
}
</style>
</head>
<body class="min-h-screen">
<div class="flex h-screen overflow-hidden">
<!-- Sidebar -->
<div class="hidden md:flex md:flex-shrink-0">
<div class="flex flex-col w-64 border-r border-gray-200 bg-white">
<div class="flex items-center justify-center h-16 px-4 gradient-bg">
<div class="flex items-center">
<i class="fab fa-twitter text-white text-3xl mr-2"></i>
<span class="text-white text-xl font-bold">Decentralized</span>
</div>
</div>
<div class="flex flex-col flex-grow p-4 overflow-y-auto">
<nav class="flex-1 space-y-2">
<a href="#" class="flex items-center px-4 py-3 text-lg font-medium text-gray-900 rounded-lg hover:bg-blue-50 group">
<i class="fas fa-home mr-3 text-gray-500 group-hover:text-blue-500"></i>
Home
</a>
<a href="#" class="flex items-center px-4 py-3 text-lg font-medium text-gray-900 rounded-lg hover:bg-blue-50 group">
<i class="fas fa-hashtag mr-3 text-gray-500 group-hover:text-blue-500"></i>
Explore
</a>
<a href="#" class="flex items-center px-4 py-3 text-lg font-medium text-gray-900 rounded-lg hover:bg-blue-50 group">
<i class="fas fa-bell mr-3 text-gray-500 group-hover:text-blue-500"></i>
Notifications
</a>
<a href="#" class="flex items-center px-4 py-3 text-lg font-medium text-gray-900 rounded-lg hover:bg-blue-50 group">
<i class="fas fa-envelope mr-3 text-gray-500 group-hover:text-blue-500"></i>
Messages
</a>
<a href="#" class="flex items-center px-4 py-3 text-lg font-medium text-gray-900 rounded-lg hover:bg-blue-50 group">
<i class="fas fa-bookmark mr-3 text-gray-500 group-hover:text-blue-500"></i>
Bookmarks
</a>
<a href="#" class="flex items-center px-4 py-3 text-lg font-medium text-gray-900 rounded-lg hover:bg-blue-50 group">
<i class="fas fa-list-alt mr-3 text-gray-500 group-hover:text-blue-500"></i>
Lists
</a>
<a href="#" class="flex items-center px-4 py-3 text-lg font-medium text-gray-900 rounded-lg hover:bg-blue-50 group">
<i class="fas fa-user mr-3 text-gray-500 group-hover:text-blue-500"></i>
Profile
</a>
<a href="#" class="flex items-center px-4 py-3 text-lg font-medium text-gray-900 rounded-lg hover:bg-blue-50 group">
<i class="fas fa-ellipsis-h mr-3 text-gray-500 group-hover:text-blue-500"></i>
More
</a>
</nav>
<button id="postButton" class="mt-4 w-full bg-blue-500 hover:bg-blue-600 text-white font-bold py-3 px-4 rounded-full transition duration-200">
Post
</button>
<div class="mt-auto mb-4">
<div class="flex items-center p-3 rounded-full hover:bg-gray-100 cursor-pointer">
<img class="w-10 h-10 rounded-full" src="https://randomuser.me/api/portraits/men/32.jpg" alt="Profile">
<div class="ml-3">
<p class="text-sm font-medium text-gray-900">John Doe</p>
<p class="text-xs text-gray-500">@johndoe</p>
</div>
<i class="fas fa-ellipsis-h ml-auto text-gray-500"></i>
</div>
</div>
</div>
</div>
</div>
<!-- Mobile sidebar -->
<div class="md:hidden fixed bottom-0 left-0 right-0 bg-white border-t border-gray-200 z-10">
<div class="flex justify-around">
<a href="#" class="flex flex-col items-center justify-center p-3 text-gray-500 hover:text-blue-500">
<i class="fas fa-home text-xl"></i>
</a>
<a href="#" class="flex flex-col items-center justify-center p-3 text-gray-500 hover:text-blue-500">
<i class="fas fa-hashtag text-xl"></i>
</a>
<a href="#" class="flex flex-col items-center justify-center p-3 text-gray-500 hover:text-blue-500">
<i class="fas fa-bell text-xl"></i>
</a>
<a href="#" class="flex flex-col items-center justify-center p-3 text-gray-500 hover:text-blue-500">
<i class="fas fa-envelope text-xl"></i>
</a>
</div>
</div>
<!-- Main content -->
<div class="flex flex-col flex-1 overflow-hidden">
<!-- Header -->
<div class="flex items-center justify-between border-b border-gray-200 bg-white p-4">
<div class="flex items-center">
<h1 class="text-xl font-bold text-gray-900">Home</h1>
</div>
<div class="flex items-center space-x-4">
<button class="p-2 rounded-full hover:bg-gray-100">
<i class="fas fa-star text-gray-500"></i>
</button>
<button class="p-2 rounded-full hover:bg-gray-100">
<i class="fas fa-cog text-gray-500"></i>
</button>
</div>
</div>
<!-- Tabs -->
<div class="flex border-b border-gray-200 bg-white">
<button id="forYouTab" class="flex-1 py-4 px-4 text-center font-medium text-gray-500 hover:text-gray-900 active-tab">
For You
</button>
<button id="followingTab" class="flex-1 py-4 px-4 text-center font-medium text-gray-500 hover:text-gray-900">
Following
</button>
</div>
<!-- Post composer -->
<div class="border-b border-gray-200 bg-white p-4">
<div class="flex">
<img class="w-12 h-12 rounded-full" src="https://randomuser.me/api/portraits/men/32.jpg" alt="Profile">
<div class="ml-3 flex-1">
<textarea id="postContent" class="w-full px-0 text-gray-900 bg-white border-0 focus:ring-0 resize-none placeholder-gray-500" placeholder="What's happening?" rows="2"></textarea>
<div class="flex items-center justify-between pt-2 border-t border-gray-200">
<div class="flex space-x-4">
<button class="text-blue-500 hover:text-blue-600">
<i class="far fa-image"></i>
</button>
<button class="text-blue-500 hover:text-blue-600">
<i class="fas fa-poll"></i>
</button>
<button class="text-blue-500 hover:text-blue-600">
<i class="far fa-smile"></i>
</button>
<button class="text-blue-500 hover:text-blue-600">
<i class="far fa-calendar-alt"></i>
</button>
<button class="text-blue-500 hover:text-blue-600">
<i class="fas fa-map-marker-alt"></i>
</button>
</div>
<button id="submitPost" class="bg-blue-500 hover:bg-blue-600 text-white font-bold px-4 py-1 rounded-full disabled:opacity-50" disabled>
Post
</button>
</div>
</div>
</div>
</div>
<!-- Posts feed -->
<div id="postsFeed" class="flex-1 overflow-y-auto">
<!-- Posts will be loaded here -->
</div>
</div>
<!-- Right sidebar -->
<div class="hidden lg:block lg:flex-shrink-0 lg:w-80 border-l border-gray-200 bg-white overflow-y-auto">
<div class="p-4">
<!-- Search bar -->
<div class="relative">
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
<i class="fas fa-search text-gray-400"></i>
</div>
<input type="text" class="block w-full pl-10 pr-3 py-2 border border-gray-300 rounded-full bg-gray-100 focus:bg-white focus:border-blue-500 focus:outline-none" placeholder="Search">
</div>
<!-- Trending section -->
<div class="mt-6 bg-gray-50 rounded-xl">
<div class="p-4">
<h2 class="text-xl font-bold text-gray-900">What's happening</h2>
<div class="mt-4 space-y-4">
<div class="hover:bg-gray-100 p-3 rounded-lg cursor-pointer">
<div class="text-xs text-gray-500">Technology · Trending</div>
<div class="font-bold">#DecentralizedSocial</div>
<div class="text-xs text-gray-500">5,432 posts</div>
</div>
<div class="hover:bg-gray-100 p-3 rounded-lg cursor-pointer">
<div class="text-xs text-gray-500">Business & finance · Trending</div>
<div class="font-bold">#Web3</div>
<div class="text-xs text-gray-500">12.5K posts</div>
</div>
<div class="hover:bg-gray-100 p-3 rounded-lg cursor-pointer">
<div class="text-xs text-gray-500">Sports · Trending</div>
<div class="font-bold">#ChampionsLeague</div>
<div class="text-xs text-gray-500">45.2K posts</div>
</div>
</div>
<a href="#" class="block mt-4 text-blue-500 hover:text-blue-600 text-sm">Show more</a>
</div>
</div>
<!-- Who to follow -->
<div class="mt-6 bg-gray-50 rounded-xl">
<div class="p-4">
<h2 class="text-xl font-bold text-gray-900">Who to follow</h2>
<div class="mt-4 space-y-4">
<div class="flex items-center hover:bg-gray-100 p-3 rounded-lg cursor-pointer">
<img class="w-10 h-10 rounded-full" src="https://randomuser.me/api/portraits/women/44.jpg" alt="Profile">
<div class="ml-3">
<div class="font-bold">Jane Smith</div>
<div class="text-xs text-gray-500">@janesmith</div>
</div>
<button class="ml-auto bg-black text-white text-sm font-bold px-4 py-1 rounded-full hover:bg-gray-800">
Follow
</button>
</div>
<div class="flex items-center hover:bg-gray-100 p-3 rounded-lg cursor-pointer">
<img class="w-10 h-10 rounded-full" src="https://randomuser.me/api/portraits/men/75.jpg" alt="Profile">
<div class="ml-3">
<div class="font-bold">Mike Johnson</div>
<div class="text-xs text-gray-500">@mikej</div>
</div>
<button class="ml-auto bg-black text-white text-sm font-bold px-4 py-1 rounded-full hover:bg-gray-800">
Follow
</button>
</div>
<div class="flex items-center hover:bg-gray-100 p-3 rounded-lg cursor-pointer">
<img class="w-10 h-10 rounded-full" src="https://randomuser.me/api/portraits/women/68.jpg" alt="Profile">
<div class="ml-3">
<div class="font-bold">Sarah Williams</div>
<div class="text-xs text-gray-500">@sarahw</div>
</div>
<button class="ml-auto bg-black text-white text-sm font-bold px-4 py-1 rounded-full hover:bg-gray-800">
Follow
</button>
</div>
</div>
<a href="#" class="block mt-4 text-blue-500 hover:text-blue-600 text-sm">Show more</a>
</div>
</div>
<!-- Footer links -->
<div class="mt-4 text-xs text-gray-500">
<div class="flex flex-wrap">
<a href="#" class="mr-2 mb-1 hover:underline">Terms of Service</a>
<a href="#" class="mr-2 mb-1 hover:underline">Privacy Policy</a>
<a href="#" class="mr-2 mb-1 hover:underline">Cookie Policy</a>
<a href="#" class="mr-2 mb-1 hover:underline">Accessibility</a>
<a href="#" class="mr-2 mb-1 hover:underline">Ads info</a>
<a href="#" class="mr-2 mb-1 hover:underline">More</a>
</div>
<div class="mt-2">© 2023 Decentralized Twitter Clone</div>
</div>
</div>
</div>
</div>
<!-- Post modal -->
<div id="postModal" class="fixed inset-0 z-50 hidden">
<div class="flex items-center justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
<div class="absolute inset-0 bg-gray-500 opacity-75"></div>
</div>
<span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">&#8203;</span>
<div class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full">
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
<div class="sm:flex sm:items-start">
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left w-full">
<div class="flex justify-between items-center">
<h3 class="text-lg leading-6 font-medium text-gray-900">Create a post</h3>
<button id="closeModal" class="text-gray-400 hover:text-gray-500">
<i class="fas fa-times"></i>
</button>
</div>
<div class="mt-4">
<textarea id="modalPostContent" class="w-full px-0 text-gray-900 bg-white border-0 focus:ring-0 resize-none placeholder-gray-500" placeholder="What's happening?" rows="4"></textarea>
</div>
</div>
</div>
</div>
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
<button id="submitModalPost" type="button" class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-500 text-base font-medium text-white hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm disabled:opacity-50" disabled>
Post
</button>
<button id="cancelModalPost" type="button" class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm">
Cancel
</button>
</div>
</div>
</div>
</div>
<script>
// Initialize the app
document.addEventListener('DOMContentLoaded', function() {
// Initialize localStorage for decentralized data storage
if (!localStorage.getItem('posts')) {
localStorage.setItem('posts', JSON.stringify([]));
}
if (!localStorage.getItem('users')) {
localStorage.setItem('users', JSON.stringify([
{
id: 1,
name: "John Doe",
username: "@johndoe",
avatar: "https://randomuser.me/api/portraits/men/32.jpg",
bio: "Decentralization enthusiast. Building the future of social media.",
following: [2, 3]
},
{
id: 2,
name: "Jane Smith",
username: "@janesmith",
avatar: "https://randomuser.me/api/portraits/women/44.jpg",
bio: "Web3 developer. Love open source projects.",
following: [1]
},
{
id: 3,
name: "Mike Johnson",
username: "@mikej",
avatar: "https://randomuser.me/api/portraits/men/75.jpg",
bio: "Blockchain architect. Coffee addict.",
following: [1, 2]
}
]));
}
// Load initial posts
loadPosts();
// Event listeners
document.getElementById('postContent').addEventListener('input', function() {
const submitButton = document.getElementById('submitPost');
submitButton.disabled = this.value.trim() === '';
});
document.getElementById('modalPostContent').addEventListener('input', function() {
const submitButton = document.getElementById('submitModalPost');
submitButton.disabled = this.value.trim() === '';
});
document.getElementById('submitPost').addEventListener('click', createPost);
document.getElementById('submitModalPost').addEventListener('click', createPostFromModal);
document.getElementById('postButton').addEventListener('click', openPostModal);
document.getElementById('closeModal').addEventListener('click', closePostModal);
document.getElementById('cancelModalPost').addEventListener('click', closePostModal);
// Tab switching
document.getElementById('forYouTab').addEventListener('click', function() {
this.classList.add('active-tab');
document.getElementById('followingTab').classList.remove('active-tab');
loadPosts('forYou');
});
document.getElementById('followingTab').addEventListener('click', function() {
this.classList.add('active-tab');
document.getElementById('forYouTab').classList.remove('active-tab');
loadPosts('following');
});
});
// Load posts from localStorage
function loadPosts(filter = 'forYou') {
const postsFeed = document.getElementById('postsFeed');
postsFeed.innerHTML = '';
let posts = JSON.parse(localStorage.getItem('posts'));
const users = JSON.parse(localStorage.getItem('users'));
if (filter === 'following') {
// In a real decentralized app, this would filter posts from followed users
// For demo, we'll just show a subset
posts = posts.slice(0, 3);
}
if (posts.length === 0) {
postsFeed.innerHTML = `
<div class="flex flex-col items-center justify-center py-12">
<i class="fas fa-feather-alt text-gray-300 text-5xl mb-4"></i>
<h3 class="text-xl font-bold text-gray-700">No posts yet</h3>
<p class="text-gray-500 mt-2">Be the first to post something!</p>
</div>
`;
return;
}
posts.forEach(post => {
const user = users.find(u => u.id === post.userId) || {
name: "Unknown User",
username: "@unknown",
avatar: "https://randomuser.me/api/portraits/lego/5.jpg"
};
const postElement = document.createElement('div');
postElement.className = 'border-b border-gray-200 bg-white post-animation';
postElement.innerHTML = `
<div class="p-4">
<div class="flex">
<img class="w-12 h-12 rounded-full" src="${user.avatar}" alt="${user.name}">
<div class="ml-3 flex-1">
<div class="flex items-center">
<span class="font-bold">${user.name}</span>
<span class="text-gray-500 ml-2">${user.username}</span>
<span class="text-gray-500 mx-1">·</span>
<span class="text-gray-500">${formatTime(post.timestamp)}</span>
<button class="ml-auto text-gray-400 hover:text-gray-600">
<i class="fas fa-ellipsis-h"></i>
</button>
</div>
<div class="mt-1">
<p class="text-gray-900">${post.content}</p>
</div>
<div class="mt-3 flex justify-between max-w-md">
<button class="text-gray-500 hover:text-blue-500">
<i class="far fa-comment"></i>
<span class="ml-1">${post.comments || 0}</span>
</button>
<button class="text-gray-500 hover:text-green-500">
<i class="fas fa-retweet"></i>
<span class="ml-1">${post.retweets || 0}</span>
</button>
<button class="like-button text-gray-500 hover:text-red-500 like-animation" data-post-id="${post.id}">
<i class="${post.liked ? 'fas' : 'far'} fa-heart ${post.liked ? 'text-red-500' : ''}"></i>
<span class="ml-1">${post.likes || 0}</span>
</button>
<button class="text-gray-500 hover:text-blue-500">
<i class="far fa-share-square"></i>
</button>
</div>
</div>
</div>
</div>
`;
postsFeed.appendChild(postElement);
});
// Add event listeners for like buttons
document.querySelectorAll('.like-button').forEach(button => {
button.addEventListener('click', function() {
const postId = this.getAttribute('data-post-id');
toggleLike(postId);
});
});
}
// Create a new post
function createPost() {
const content = document.getElementById('postContent').value.trim();
if (!content) return;
const posts = JSON.parse(localStorage.getItem('posts'));
const newPost = {
id: Date.now(),
userId: 1, // Current user ID (in a real app, this would be dynamic)
content: content,
timestamp: new Date().toISOString(),
likes: 0,
liked: false,
comments: 0,
retweets: 0
};
posts.unshift(newPost);
localStorage.setItem('posts', JSON.stringify(posts));
document.getElementById('postContent').value = '';
document.getElementById('submitPost').disabled = true;
loadPosts();
}
// Create post from modal
function createPostFromModal() {
const content = document.getElementById('modalPostContent').value.trim();
if (!content) return;
const posts = JSON.parse(localStorage.getItem('posts'));
const newPost = {
id: Date.now(),
userId: 1, // Current user ID
content: content,
timestamp: new Date().toISOString(),
likes: 0,
liked: false,
comments: 0,
retweets: 0
};
posts.unshift(newPost);
localStorage.setItem('posts', JSON.stringify(posts));
document.getElementById('modalPostContent').value = '';
document.getElementById('submitModalPost').disabled = true;
closePostModal();
loadPosts();
}
// Toggle like on a post
function toggleLike(postId) {
const posts = JSON.parse(localStorage.getItem('posts'));
const postIndex = posts.findIndex(p => p.id === parseInt(postId));
if (postIndex !== -1) {
const post = posts[postIndex];
post.liked = !post.liked;
post.likes = post.liked ? (post.likes || 0) + 1 : (post.likes || 0) - 1;
localStorage.setItem('posts', JSON.stringify(posts));
loadPosts();
}
}
// Open post modal
function openPostModal() {
document.getElementById('postModal').classList.remove('hidden');
}
// Close post modal
function closePostModal() {
document.getElementById('postModal').classList.add('hidden');
}
// Format timestamp
function formatTime(timestamp) {
const now = new Date();
const postTime = new Date(timestamp);
const diffInSeconds = Math.floor((now - postTime) / 1000);
if (diffInSeconds < 60) {
return `${diffInSeconds}s`;
} else if (diffInSeconds < 3600) {
return `${Math.floor(diffInSeconds / 60)}m`;
} else if (diffInSeconds < 86400) {
return `${Math.floor(diffInSeconds / 3600)}h`;
} else {
return postTime.toLocaleDateString('en-US', { month: 'short', day: 'numeric' });
}
}
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=Tame342/weatherinsight" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html