socialsphere / script.js
walolorj's picture
make it a social media app
8dbb3cf verified
// User management
let currentUser = null;
const users = JSON.parse(localStorage.getItem('users')) || [];
const posts = JSON.parse(localStorage.getItem('posts')) || [];
// Initialize auth forms
function initAuthForms() {
const loginForm = document.getElementById('login-form');
const registerForm = document.getElementById('register-form');
const showRegister = document.getElementById('show-register');
const showLogin = document.getElementById('show-login');
if (loginForm && registerForm && showRegister && showLogin) {
showRegister.addEventListener('click', (e) => {
e.preventDefault();
loginForm.classList.add('hidden');
registerForm.classList.remove('hidden');
}
function showCommentModal(post) {
const modal = document.createElement('div');
modal.className = 'fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50';
modal.innerHTML = `
<div class="bg-white rounded-lg w-full max-w-lg max-h-[90vh] flex flex-col">
<div class="p-4 border-b flex items-center justify-between">
<h3 class="text-lg font-semibold">Comments</h3>
<button class="text-gray-500 hover:text-gray-700" id="close-comment-modal">
<i data-feather="x"></i>
</button>
</div>
<div class="p-4 border-b">
<div class="flex items-start">
<img src="${post.user.avatar}" class="w-8 h-8 rounded-full">
<div class="ml-3">
<div class="flex items-center">
<span class="font-medium">${post.user.name}</span>
<span class="mx-1 text-gray-500">•</span>
<span class="text-gray-500 text-sm">${post.timestamp}</span>
</div>
<p class="mt-1">${post.content}</p>
</div>
</div>
</div>
<div class="flex-1 overflow-y-auto p-4 space-y-4" id="comments-container">
${post.comments > 0 ? '' : `
<div class="text-center py-8">
<i data-feather="message-circle" class="w-12 h-12 mx-auto text-gray-300"></i>
<p class="mt-2 text-gray-500">No comments yet</p>
<p class="text-sm text-gray-400">Be the first to share your thoughts!</p>
</div>
`}
</div>
<div class="p-4 border-t">
<div class="flex items-center">
<img src="http://static.photos/people/200x200/1" class="w-8 h-8 rounded-full">
<div class="ml-2 flex-1 flex items-center bg-gray-100 rounded-full">
<input type="text" placeholder="Add a comment..." class="flex-1 bg-transparent px-4 py-2 focus:outline-none" id="comment-input">
<button class="text-blue-500 px-3" id="post-comment">
<i data-feather="send" class="w-5 h-5"></i>
</button>
</div>
</div>
</div>
</div>
`;
document.body.appendChild(modal);
feather.replace();
document.getElementById('close-comment-modal').addEventListener('click', () => {
modal.remove();
});
document.getElementById('post-comment').addEventListener('click', () => {
const commentInput = document.getElementById('comment-input');
const comment = commentInput.value.trim();
if (comment) {
// In a real app, you would save the comment
alert(`Comment posted: ${comment}`);
commentInput.value = '';
}
});
}
function showShareOptions(post) {
const modal = document.createElement('div');
modal.className = 'fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50';
modal.innerHTML = `
<div class="bg-white rounded-lg w-full max-w-sm">
<div class="p-4 border-b">
<h3 class="text-lg font-semibold">Share Post</h3>
</div>
<div class="p-4 space-y-2">
<button class="w-full flex items-center px-4 py-3 rounded-lg hover:bg-gray-100">
<div class="w-10 h-10 rounded-full bg-blue-100 flex items-center justify-center text-blue-500">
<i data-feather="user-plus" class="w-5 h-5"></i>
</div>
<div class="ml-4 text-left">
<p class="font-medium">Send in a message</p>
<p class="text-sm text-gray-500">Share privately with friends</p>
</div>
</button>
<button class="w-full flex items-center px-4 py-3 rounded-lg hover:bg-gray-100">
<div class="w-10 h-10 rounded-full bg-green-100 flex items-center justify-center text-green-500">
<i data-feather="twitter" class="w-5 h-5"></i>
</div>
<div class="ml-4 text-left">
<p class="font-medium">Share on Twitter</p>
<p class="text-sm text-gray-500">Post to Twitter</p>
</div>
</button>
<button class="w-full flex items-center px-4 py-3 rounded-lg hover:bg-gray-100">
<div class="w-10 h-10 rounded-full bg-blue-100 flex items-center justify-center text-blue-500">
<i data-feather="facebook" class="w-5 h-5"></i>
</div>
<div class="ml-4 text-left">
<p class="font-medium">Share on Facebook</p>
<p class="text-sm text-gray-500">Post to Facebook</p>
</div>
</button>
<button class="w-full flex items-center px-4 py-3 rounded-lg hover:bg-gray-100">
<div class="w-10 h-10 rounded-full bg-purple-100 flex items-center justify-center text-purple-500">
<i data-feather="link" class="w-5 h-5"></i>
</div>
<div class="ml-4 text-left">
<p class="font-medium">Copy link</p>
<p class="text-sm text-gray-500">Copy post link</p>
</div>
</button>
</div>
<div class="p-4 border-t">
<button id="close-share-modal" class="w-full py-2 text-gray-700 rounded-lg hover:bg-gray-100">
Cancel
</button>
</div>
</div>
`;
document.body.appendChild(modal);
feather.replace();
document.getElementById('close-share-modal').addEventListener('click', () => {
modal.remove();
});
modal.querySelectorAll('button').forEach(btn => {
if (btn.id !== 'close-share-modal') {
btn.addEventListener('click', () => {
alert(`Post shared via ${btn.textContent.trim()}`);
modal.remove();
});
}
});
}
);
showLogin.addEventListener('click', (e) => {
e.preventDefault();
registerForm.classList.add('hidden');
loginForm.classList.remove('hidden');
});
loginForm.addEventListener('submit', (e) => {
e.preventDefault();
const email = document.getElementById('login-email').value;
const password = document.getElementById('login-password').value;
loginUser(email, password);
});
registerForm.addEventListener('submit', (e) => {
e.preventDefault();
const name = document.getElementById('register-name').value;
const username = document.getElementById('register-username').value;
const email = document.getElementById('register-email').value;
const password = document.getElementById('register-password').value;
registerUser(name, username, email, password);
});
}
}
function loginUser(email, password) {
const user = users.find(u => u.email === email && u.password === password);
if (user) {
currentUser = user;
localStorage.setItem('currentUser', JSON.stringify(user));
window.location.href = '/';
} else {
alert('Invalid credentials');
}
}
function registerUser(name, username, email, password) {
if (users.some(u => u.email === email)) {
alert('Email already registered');
return;
}
if (users.some(u => u.username === username)) {
alert('Username already taken');
return;
}
const newUser = {
id: Date.now(),
name,
username,
email,
password,
avatar: `http://static.photos/people/200x200/${Math.floor(Math.random() * 100)}`,
followers: [],
following: []
};
users.push(newUser);
localStorage.setItem('users', JSON.stringify(users));
currentUser = newUser;
localStorage.setItem('currentUser', JSON.stringify(newUser));
window.location.href = '/';
}
function logoutUser() {
currentUser = null;
localStorage.removeItem('currentUser');
window.location.href = '/auth.html';
}
// Post management
function createPost(content, image = null) {
const newPost = {
id: Date.now(),
user: {
name: currentUser.name,
username: currentUser.username,
avatar: currentUser.avatar
},
content,
image,
timestamp: 'Just now',
likes: 0,
comments: 0,
shares: 0,
isLiked: false,
isSaved: false
};
posts.unshift(newPost);
localStorage.setItem('posts', JSON.stringify(posts));
return newPost;
}
// Sample data for posts if none exists
if (posts.length === 0) {
const samplePosts = [
{
id: 1,
user: {
name: "Sarah Johnson",
username: "@sarahj",
avatar: "http://static.photos/people/200x200/4"
},
content: "Just launched my new portfolio website! Built with React and TailwindCSS. Check it out and let me know what you think! 🚀",
image: "http://static.photos/technology/640x360/5",
timestamp: "2 hours ago",
likes: 245,
comments: 32,
shares: 12,
isLiked: false,
isSaved: false
},
{
id: 2,
user: {
name: "Tech Insights",
username: "@techinsights",
avatar: "http://static.photos/technology/200x200/6"
},
content: "Breaking: New AI model achieves human-level performance on complex reasoning tasks. This could revolutionize how we approach problem-solving in tech. #AI #MachineLearning",
timestamp: "4 hours ago",
likes: 1240,
comments: 87,
shares: 210,
isLiked: true,
isSaved: false
},
{
id: 3,
user: {
name: "Design Daily",
username: "@designdaily",
avatar: "http://static.photos/abstract/200x200/7"
},
content: "Color theory tip: Use the 60-30-10 rule for balanced designs. 60% dominant color, 30% secondary, 10% accent. This creates visual harmony without overwhelming the viewer.",
image: "http://static.photos/design/640x360/8",
timestamp: "6 hours ago",
likes: 562,
comments: 24,
shares: 42,
isLiked: false,
isSaved: true
},
{
id: 4,
user: {
name: "Alex Morgan",
username: "@alexmorgan",
avatar: "http://static.photos/people/200x200/1"
},
content: "Working on a new project that combines blockchain with social media. Excited to share more details soon! #Web3 #Blockchain",
timestamp: "1 day ago",
likes: 87,
comments: 15,
shares: 9,
isLiked: true,
isSaved: false
}
];
// Track viewed posts to avoid reshowing
let viewedPosts = new Set();
let currentPosts = [];
// Initialize the feed
document.addEventListener('DOMContentLoaded', function() {
// Initialize auth forms if on auth page
initAuthForms();
// Check if user is logged in
const storedUser = localStorage.getItem('currentUser');
if (storedUser) {
currentUser = JSON.parse(storedUser);
} else if (window.location.pathname !== '/auth.html') {
window.location.href = '/auth.html';
return;
}
// Initialize UI if on main page
if (document.getElementById('feed-container')) {
loadPosts();
// Load more button event
document.getElementById('load-more').addEventListener('click', loadPosts);
// Post creation form
const postForm = document.getElementById('post-form');
if (postForm) {
postForm.addEventListener('submit', (e) => {
e.preventDefault();
const content = document.getElementById('post-content').value;
const image = document.getElementById('post-image').files[0];
if (content.trim() === '') return;
if (image) {
const reader = new FileReader();
reader.onload = (e) => {
const newPost = createPost(content, e.target.result);
prependPost(newPost);
};
reader.readAsDataURL(image);
} else {
const newPost = createPost(content);
prependPost(newPost);
}
postForm.reset();
});
}
// Add logout functionality
const logoutBtn = document.getElementById('logout-btn');
if (logoutBtn) {
logoutBtn.addEventListener('click', logoutUser);
}
}
});
// Load posts into the feed
function loadPosts() {
const feedContainer = document.getElementById('feed-container');
// Get posts from local storage
const storedPosts = JSON.parse(localStorage.getItem('posts')) || [];
// Filter out already viewed posts
const newPosts = storedPosts.filter(post => !viewedPosts.has(post.id));
// If no new posts, show message
if (newPosts.length === 0) {
if (feedContainer.children.length === 0) {
feedContainer.innerHTML = `
<div class="p-8 text-center">
<i data-feather="coffee" class="w-12 h-12 mx-auto text-gray-400"></i>
<h3 class="mt-4 text-lg font-medium">No new posts</h3>
<p class="mt-1 text-gray-500">You've seen all recent posts. Check back later for more!</p>
</div>
`;
feather.replace();
} else {
document.getElementById('load-more').textContent = "No more posts";
document.getElementById('load-more').disabled = true;
}
return;
}
// Take first 2 new posts
const postsToShow = newPosts.slice(0, 2);
postsToShow.forEach(post => {
// Mark as viewed
viewedPosts.add(post.id);
currentPosts.push(post);
// Create post element
const postElement = document.createElement('div');
postElement.className = 'post-card bg-white border-b last:border-b-0 fade-in';
postElement.innerHTML = `
<div class="p-6">
<div class="flex items-start">
<img src="${post.user.avatar}" alt="${post.user.name}" class="w-12 h-12 rounded-full user-avatar">
<div class="ml-4 flex-1">
<div class="flex items-center">
<h3 class="font-bold">${post.user.name}</h3>
<span class="ml-2 text-gray-500 text-sm">${post.user.username}</span>
<span class="mx-2 text-gray-300">•</span>
<span class="text-gray-500 text-sm">${post.timestamp}</span>
</div>
<p class="mt-2 post-content">${post.content}</p>
${post.image ? `<img src="${post.image}" alt="Post image" class="mt-4 rounded-xl w-full">` : ''}
<div class="mt-4 flex space-x-6">
<button class="interaction-btn ${post.isLiked ? 'active' : ''}" data-action="like" data-id="${post.id}">
<i data-feather="heart" class="w-4 h-4"></i>
<span>${post.likes}</span>
</button>
<button class="interaction-btn" data-action="comment" data-id="${post.id}">
<i data-feather="message-circle" class="w-4 h-4"></i>
<span>${post.comments}</span>
</button>
<button class="interaction-btn" data-action="share" data-id="${post.id}">
<i data-feather="share-2" class="w-4 h-4"></i>
<span>${post.shares}</span>
</button>
<button class="interaction-btn ml-auto ${post.isSaved ? 'active' : ''}" data-action="save" data-id="${post.id}">
<i data-feather="bookmark" class="w-4 h-4"></i>
</button>
</div>
</div>
</div>
</div>
`;
feedContainer.appendChild(postElement);
});
// Reinitialize Feather icons
feather.replace();
// Add event listeners to new buttons
document.querySelectorAll('.interaction-btn').forEach(button => {
button.addEventListener('click', handleInteraction);
});
}
// Handle post interactions
function prependPost(post) {
const feedContainer = document.getElementById('feed-container');
const firstChild = feedContainer.firstChild;
const postElement = createPostElement(post);
if (firstChild) {
feedContainer.insertBefore(postElement, firstChild);
} else {
feedContainer.appendChild(postElement);
}
viewedPosts.add(post.id);
currentPosts.unshift(post);
feather.replace();
}
function createPostElement(post) {
const postElement = document.createElement('div');
postElement.className = 'post-card fade-in p-4';
postElement.innerHTML = `
<div class="flex items-start">
<img src="${post.user.avatar}" alt="${post.user.name}" class="w-10 h-10 rounded-full user-avatar">
<div class="ml-3 flex-1">
<div class="flex items-center">
<h3 class="font-bold">${post.user.name}</h3>
<span class="mx-2 text-gray-300">•</span>
<span class="text-gray-500 text-sm">${post.timestamp}</span>
<button class="ml-auto text-gray-400 hover:text-gray-600">
<i data-feather="more-horizontal"></i>
</button>
</div>
<p class="mt-2 post-content">${post.content}</p>
${post.image ? `
<div class="mt-3 rounded-xl overflow-hidden border">
<img src="${post.image}" alt="Post image" class="w-full">
</div>
` : ''}
<div class="flex justify-between mt-3 pt-3 border-t">
<button class="interaction-btn ${post.isLiked ? 'active' : ''}" data-action="like" data-id="${post.id}">
<i data-feather="heart" class="w-5 h-5"></i>
<span>${post.likes}</span>
</button>
<button class="interaction-btn" data-action="comment" data-id="${post.id}">
<i data-feather="message-circle" class="w-5 h-5"></i>
<span>${post.comments}</span>
</button>
<button class="interaction-btn" data-action="share" data-id="${post.id}">
<i data-feather="share-2" class="w-5 h-5"></i>
</button>
<button class="interaction-btn ml-auto ${post.isSaved ? 'active' : ''}" data-action="save" data-id="${post.id}">
<i data-feather="bookmark" class="w-5 h-5"></i>
</button>
</div>
</div>
</div>
`;
return postElement;
}
function handleInteraction(e) {
const button = e.currentTarget;
const action = button.getAttribute('data-action');
const postId = parseInt(button.getAttribute('data-id'));
// Find the post in storage
const storedPosts = JSON.parse(localStorage.getItem('posts')) || [];
const postIndex = storedPosts.findIndex(p => p.id === postId);
if (!post) return;
// Update UI based on action
switch(action) {
case 'like':
if (button.classList.contains('active')) {
button.classList.remove('active');
post.likes--;
post.isLiked = false;
} else {
button.classList.add('active');
post.likes++;
post.isLiked = true;
}
button.querySelector('span').textContent = post.likes;
break;
case 'save':
if (button.classList.contains('active')) {
button.classList.remove('active');
post.isSaved = false;
} else {
button.classList.add('active');
post.isSaved = true;
}
break;
case 'comment':
// In a real app, this would open comment section
// Update storage
storedPosts[postIndex] = post;
localStorage.setItem('posts', JSON.stringify(storedPosts));
// Update current posts
const currentPostIndex = currentPosts.findIndex(p => p.id === postId);
if (currentPostIndex !== -1) {
currentPosts[currentPostIndex] = post;
}
// Show comment modal
showCommentModal(post);
break;
case 'share':
// In a real app, this would open share options
// Update storage
storedPosts[postIndex] = post;
localStorage.setItem('posts', JSON.stringify(storedPosts));
// Show share options
showShareOptions(post);
break;
}
}