${post.username} ${post.caption}
document.addEventListener('DOMContentLoaded', () => { // --- QUERY SELECTORS --- const loginForm = document.querySelector('.login-form'); const loginContainer = document.querySelector('.login-container'); const feedView = document.getElementById('feed-view'); const emailInput = document.getElementById('email'); const passwordInput = document.getElementById('password'); const confirmPasswordInput = document.getElementById('confirm-password'); const confirmPasswordGroup = document.getElementById('confirm-password-group'); const submitBtn = document.querySelector('.btn-primary'); const btnText = submitBtn ? submitBtn.querySelector('span') : null; const toggleLink = document.querySelector('.signup-link a'); const title = document.querySelector('.brand-section h1'); const subtitle = document.querySelector('.brand-section p'); // Post Creation Elements const createPostView = document.getElementById('create-post-view'); const cancelPostBtn = document.getElementById('cancel-post-btn'); const sharePostBtn = document.getElementById('share-post-btn'); const uploadTrigger = document.getElementById('upload-trigger'); const imageInput = document.getElementById('post-image-input'); const imagePreview = document.getElementById('image-preview'); const captionInput = document.getElementById('post-caption-input'); const navPostBtn = document.querySelector('.nav-btn:nth-child(2)'); const navHomeBtn = document.querySelector('.nav-btn:first-child'); let isLoginMode = true; // --- AUTH LOGIC --- if (toggleLink) { toggleLink.addEventListener('click', (e) => { e.preventDefault(); isLoginMode = !isLoginMode; updateUI(); }); } function updateUI() { if (!title || !subtitle || !btnText || !confirmPasswordGroup) return; if (isLoginMode) { title.innerText = 'Welcome Back'; subtitle.innerText = 'Enter your details below'; btnText.innerText = 'Sign In'; const helper = document.querySelector('.signup-link'); if (helper) helper.innerHTML = 'Don\'t have an account? Create One'; confirmPasswordGroup.classList.add('hidden'); confirmPasswordInput.required = false; } else { title.innerText = 'Create Account'; subtitle.innerText = 'Start your journey with us'; btnText.innerText = 'Sign Up'; const helper = document.querySelector('.signup-link'); if (helper) helper.innerHTML = 'Already have an account? Sign In'; confirmPasswordGroup.classList.remove('hidden'); confirmPasswordInput.required = true; } const newLink = document.querySelector('.signup-link a'); if (newLink) { newLink.addEventListener('click', (e) => { e.preventDefault(); isLoginMode = !isLoginMode; updateUI(); }); } if (loginForm) loginForm.reset(); resetButton(); } function resetButton() { if (!submitBtn || !btnText) return; submitBtn.style.background = ''; submitBtn.style.transform = ''; btnText.innerText = isLoginMode ? 'Sign In' : 'Sign Up'; } function showFeedback(isSuccess, message) { if (!btnText || !submitBtn) return; btnText.innerText = message; if (isSuccess) { submitBtn.style.background = 'linear-gradient(135deg, #10B981 0%, #059669 100%)'; } else { submitBtn.style.background = 'linear-gradient(135deg, #EF4444 0%, #B91C1C 100%)'; submitBtn.animate([ { transform: 'translateX(0)' }, { transform: 'translateX(-5px)' }, { transform: 'translateX(5px)' }, { transform: 'translateX(0)' } ], { duration: 300 }); } setTimeout(() => { if (!message.includes('Success')) { resetButton(); } }, 2000); } function navigateToFeed() { if (loginContainer && feedView) { loginContainer.style.opacity = '0'; setTimeout(() => { loginContainer.classList.add('hidden'); loginContainer.style.display = 'none'; feedView.classList.remove('hidden'); void feedView.offsetWidth; // Reflow feedView.classList.add('fade-in'); loadPostState(); // Load data setTimeout(() => { feedView.classList.remove('fade-in'); }, 600); }, 600); } } if (loginForm) { loginForm.addEventListener('submit', (e) => { e.preventDefault(); const email = emailInput.value.trim(); const password = passwordInput.value.trim(); const confirmPassword = confirmPasswordInput.value.trim(); const timestamp = new Date().toISOString(); const existingUsers = JSON.parse(localStorage.getItem('socialAppUsers') || '[]'); if (isLoginMode) { const user = existingUsers.find(u => u.email === email && u.password === password); if (user) { showFeedback(true, 'Success!'); setTimeout(navigateToFeed, 1000); } else { showFeedback(false, 'Incorrect details'); } } else { if (existingUsers.some(u => u.email === email)) { showFeedback(false, 'User exists'); return; } if (password !== confirmPassword) { showFeedback(false, 'Passwords do not match'); return; } const newUser = { email, password, joinedAt: timestamp }; existingUsers.push(newUser); localStorage.setItem('socialAppUsers', JSON.stringify(existingUsers)); showFeedback(true, 'Account Created!'); setTimeout(() => { isLoginMode = true; updateUI(); setTimeout(navigateToFeed, 1000); }, 1500); } }); } // --- DATA HELPERS --- function getPostState() { return JSON.parse(localStorage.getItem('socialAppPostState') || '{}'); } function savePostState(state) { localStorage.setItem('socialAppPostState', JSON.stringify(state)); } function isPostDeleted(id) { const deletedPosts = JSON.parse(localStorage.getItem('socialAppDeletedPosts') || '[]'); return deletedPosts.includes(id); } function loadPostState() { const state = getPostState(); // 1. Remove deleted static posts document.querySelectorAll('.post-card').forEach(card => { const id = card.getAttribute('data-post-id'); if (id && isPostDeleted(id)) { card.remove(); } else if (id && state[id]) { // Restore Likes/Comments const data = state[id]; const likeIcon = card.querySelector('.heart-icon'); const likesText = card.querySelector('.likes'); if (likeIcon && likesText) { if (data.liked) { likeIcon.classList.add('liked'); likeIcon.style.fill = '#EF4444'; likeIcon.style.stroke = '#EF4444'; } else { likeIcon.classList.remove('liked'); likeIcon.style.fill = 'none'; likeIcon.style.stroke = 'white'; } likesText.innerText = data.likesCount + ' likes'; } // Restore Comments const commentsContainer = card.querySelector('.added-comments'); if (commentsContainer) { commentsContainer.innerHTML = ''; if (data.comments && data.comments.length > 0) { data.comments.forEach(text => { const commentEl = document.createElement('div'); commentEl.classList.add('comment-item'); commentEl.innerHTML = `you ${text}`; commentsContainer.appendChild(commentEl); }); } } } }); // 2. Render User Posts (if not already present) const savedUserPosts = JSON.parse(localStorage.getItem('socialAppUserPosts') || '[]'); // We iterate correctly to put newest on top [...savedUserPosts].reverse().forEach(post => { if (!isPostDeleted(post.id) && !document.querySelector(`[data-post-id="${post.id}"]`)) { renderPost(post, true); // Re-apply state if needed? create function handles it mostly, // but checking `state` for these dynamic posts is also good practice if we tracked likes on them. // For now, let's assume they load fresh or we'd need to run the state logic on them too. // Actually, logic is: render then apply state. } }); // Re-run state application for newly added dynamic posts // Optimization: splitting this logic explicitly would be better, but re-querying all is fine for small apps. // Let's just do a second pass for dynamic posts to support likes on them? // Existing loop `document.querySelectorAll` covers them if they are in DOM. // So this order (Filter Static -> Render Dynamic -> (Ideally re-check state on all)) is slightly off. // Better: Render Dynamic First, THEN apply state to ALL. } // Improve Load Flow function initFeed() { const savedUserPosts = JSON.parse(localStorage.getItem('socialAppUserPosts') || '[]'); [...savedUserPosts].reverse().forEach(post => { if (!isPostDeleted(post.id) && !document.querySelector(`[data-post-id="${post.id}"]`)) { renderPost(post, true); } }); const state = getPostState(); document.querySelectorAll('.post-card').forEach(card => { const id = card.getAttribute('data-post-id'); if (id && isPostDeleted(id)) { card.remove(); return; } if (id && state[id]) { const data = state[id]; const likeIcon = card.querySelector('.heart-icon'); const likesText = card.querySelector('.likes'); if (likeIcon && likesText) { if (data.liked) { likeIcon.classList.add('liked'); likeIcon.style.fill = '#EF4444'; likeIcon.style.stroke = '#EF4444'; } likesText.innerText = data.likesCount + ' likes'; } const commentsContainer = card.querySelector('.added-comments'); if (commentsContainer) { commentsContainer.innerHTML = ''; if (data.comments) { data.comments.forEach(text => { const el = document.createElement('div'); el.classList.add('comment-item'); el.innerHTML = `you ${text}`; commentsContainer.appendChild(el); }); } } } }); } // --- RENDER POST --- function renderPost(post, prepend = false) { const feedContainer = document.querySelector('.feed-container'); const article = document.createElement('article'); article.className = 'post-card'; article.setAttribute('data-post-id', post.id); const isUserPost = post.id && post.id.startsWith('post_'); const optionsHTML = isUserPost ? `
` : ``; article.innerHTML = `${post.username} ${post.caption}