${post.username} ${post.caption}
document.addEventListener('DOMContentLoaded', () => { 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.querySelector('span'); const helperText = document.querySelector('.signup-link'); const toggleLink = document.querySelector('.signup-link a'); const title = document.querySelector('.brand-section h1'); const subtitle = document.querySelector('.brand-section p'); let isLoginMode = true; // Toggle between Login and Signup if (toggleLink) { toggleLink.addEventListener('click', (e) => { e.preventDefault(); isLoginMode = !isLoginMode; updateUI(); }); } function updateUI() { if (isLoginMode) { title.innerText = 'Welcome Back'; subtitle.innerText = 'Enter your details below'; btnText.innerText = 'Sign In'; helperText.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'; helperText.innerHTML = 'Already have an account? Sign In'; confirmPasswordGroup.classList.remove('hidden'); confirmPasswordInput.required = true; } // Re-attach listener to the new link element const newLink = document.querySelector('.signup-link a'); newLink.addEventListener('click', (e) => { e.preventDefault(); isLoginMode = !isLoginMode; updateUI(); }); // Reset form and styles loginForm.reset(); resetButton(); } function resetButton() { submitBtn.style.background = ''; submitBtn.style.transform = ''; btnText.innerText = isLoginMode ? 'Sign In' : 'Sign Up'; } function showFeedback(isSuccess, message) { btnText.innerText = message; if (isSuccess) { submitBtn.style.background = 'linear-gradient(135deg, #10B981 0%, #059669 100%)'; // Success Green } else { submitBtn.style.background = 'linear-gradient(135deg, #EF4444 0%, #B91C1C 100%)'; // Error Red 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) { // Fade out login loginContainer.style.opacity = '0'; setTimeout(() => { loginContainer.classList.add('hidden'); loginContainer.style.display = 'none'; // Ensure it's gone // Show Feed feedView.classList.remove('hidden'); // Trigger reflow void feedView.offsetWidth; feedView.classList.add('fade-in'); // Load persisted state for posts loadPostState(); // Remove fade-in class after animation to fix fixed positioning context setTimeout(() => { feedView.classList.remove('fade-in'); }, 600); }, 600); // Wait for transition } } 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(); // Get existing users const existingUsers = JSON.parse(localStorage.getItem('socialAppUsers') || '[]'); if (isLoginMode) { // --- LOGIN LOGIC --- const user = existingUsers.find(u => u.email === email && u.password === password); if (user) { console.log('Login Successful:', user); showFeedback(true, 'Success!'); setTimeout(navigateToFeed, 1000); } else { console.warn('Login Failed: Invalid credentials'); showFeedback(false, 'Incorrect details'); } } else { // --- SIGNUP LOGIC --- // 1. Check if user already exists if (existingUsers.some(u => u.email === email)) { showFeedback(false, 'User exists'); return; } // 2. Validate Password Match 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)); console.log('New User Registered:', newUser); showFeedback(true, 'Account Created!'); // Switch to login mode after success setTimeout(() => { isLoginMode = true; updateUI(); setTimeout(navigateToFeed, 1000); }, 1500); } }); } // --- PERSISTENCE LOGIC --- function getPostState() { return JSON.parse(localStorage.getItem('socialAppPostState') || '{}'); } function savePostState(state) { localStorage.setItem('socialAppPostState', JSON.stringify(state)); } function loadPostState() { const state = getPostState(); const posts = document.querySelectorAll('.post-card'); posts.forEach(card => { const id = card.getAttribute('data-post-id'); if (id && state[id]) { const data = state[id]; // Restore Likes const likeIcon = card.querySelector('.heart-icon'); const likesText = card.querySelector('.likes'); 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'); commentsContainer.innerHTML = ''; // Clear existing to prevent dupes on re-run 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); }); } } }); } // --- FEED INTERACTIONS --- if (feedView) { feedView.addEventListener('click', (e) => { const target = e.target; // 1. LIKE ACTION const likeBtn = target.closest('.heart-icon')?.closest('.icon-btn'); if (likeBtn) { const icon = likeBtn.querySelector('.heart-icon'); const postCard = likeBtn.closest('.post-card'); const likesText = postCard.querySelector('.likes'); const postId = postCard.getAttribute('data-post-id'); // Toggle State icon.classList.toggle('liked'); // Update Count (Simple parsing) let count = parseInt(likesText.innerText); let isLiked = false; if (icon.classList.contains('liked')) { icon.style.fill = '#EF4444'; icon.style.stroke = '#EF4444'; count++; isLiked = true; } else { icon.style.fill = 'none'; icon.style.stroke = 'white'; count--; isLiked = false; } likesText.innerText = count + ' likes'; // Save State if (postId) { const state = getPostState(); if (!state[postId]) state[postId] = { comments: [] }; state[postId].liked = isLiked; state[postId].likesCount = count; // Preserve existing comments if we didn't just load them if (!state[postId].comments) state[postId].comments = []; savePostState(state); } return; } // 2. COMMENT TOGGLE ACTION const commentBtn = target.closest('.icon-btn'); if (commentBtn && !commentBtn.querySelector('.heart-icon')) { // Check if it's the comment button (has specific path) const path = commentBtn.querySelector('path'); if (path && (path.getAttribute('d').startsWith('M21 11.5') || path.closest('svg')?.innerHTML.includes('M21 11.5'))) { const postCard = commentBtn.closest('.post-card'); const commentSection = postCard.querySelector('.comment-section'); commentSection.classList.toggle('active'); if (commentSection.classList.contains('active')) { commentSection.querySelector('input').focus(); } return; } } // 3. POST COMMENT ACTION if (target.classList.contains('post-btn')) { const wrapper = target.closest('.comment-input-wrapper'); const input = wrapper.querySelector('.comment-input'); const text = input.value.trim(); const postCard = wrapper.closest('.post-card'); const postId = postCard.getAttribute('data-post-id'); if (text) { addComment(wrapper.closest('.comment-section'), text); if (postId) { const state = getPostState(); if (!state[postId]) state[postId] = { liked: false, likesCount: parseInt(postCard.querySelector('.likes').innerText) || 0, comments: [] }; if (!state[postId].comments) state[postId].comments = []; state[postId].comments.push(text); savePostState(state); } input.value = ''; } } }); // Enter key for comments feedView.addEventListener('keydown', (e) => { if (e.key === 'Enter' && e.target.classList.contains('comment-input')) { const text = e.target.value.trim(); const wrapper = e.target.closest('.comment-input-wrapper'); const postCard = wrapper.closest('.post-card'); const postId = postCard.getAttribute('data-post-id'); if (text) { addComment(e.target.closest('.comment-section'), text); if (postId) { const state = getPostState(); if (!state[postId]) state[postId] = { liked: false, likesCount: parseInt(postCard.querySelector('.likes').innerText) || 0, comments: [] }; if (!state[postId].comments) state[postId].comments = []; state[postId].comments.push(text); savePostState(state); } e.target.value = ''; } } }); } function addComment(section, text) { const container = section.querySelector('.added-comments'); const commentEl = document.createElement('div'); commentEl.classList.add('comment-item'); commentEl.innerHTML = `you ${text}`; container.appendChild(commentEl); } // --- CREATE POST LOGIC --- 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)'); // Center Post Button const navHomeBtn = document.querySelector('.nav-btn:first-child'); // 1. Navigation if (navPostBtn) { navPostBtn.addEventListener('click', () => { feedView.classList.add('hidden'); createPostView.classList.remove('hidden'); createPostView.classList.add('fade-in'); }); } if (cancelPostBtn) { cancelPostBtn.addEventListener('click', () => { resetPostForm(); createPostView.classList.add('hidden'); feedView.classList.remove('hidden'); }); } if (navHomeBtn && feedView.classList.contains('hidden') && !createPostView.classList.contains('hidden')) { // Logic handled by cancel mostly, but good to have explicit nav navHomeBtn.addEventListener('click', () => { if (!createPostView.classList.contains('hidden')) { resetPostForm(); createPostView.classList.add('hidden'); feedView.classList.remove('hidden'); } }); } // 2. Image Selection if (uploadTrigger) { uploadTrigger.addEventListener('click', () => imageInput.click()); } if (imageInput) { imageInput.addEventListener('change', (e) => { const file = e.target.files[0]; if (file) { const reader = new FileReader(); reader.onload = (e) => { imagePreview.src = e.target.result; imagePreview.classList.remove('hidden'); document.querySelector('.upload-placeholder').classList.add('hidden'); }; reader.readAsDataURL(file); } }); } // 3. Share Post if (sharePostBtn) { sharePostBtn.addEventListener('click', () => { if (!imagePreview.src || imagePreview.classList.contains('hidden')) { alert('Please select an image first.'); return; } const caption = captionInput.value.trim(); const imageSrc = imagePreview.src; const id = 'post_' + Date.now(); const newPost = { id, imageSrc, caption, timestamp: new Date().toISOString(), username: 'you', // Mock user likes: 0 }; // Save to LocalStorage const userPosts = JSON.parse(localStorage.getItem('socialAppUserPosts') || '[]'); userPosts.unshift(newPost); // Add to top localStorage.setItem('socialAppUserPosts', JSON.stringify(userPosts)); // Render to Feed renderPost(newPost, true); // true = prepend // Reset and Go Back resetPostForm(); createPostView.classList.add('hidden'); feedView.classList.remove('hidden'); // Re-bind listeners isn't needed strictly due to delegation, but state refresh might be loadPostState(); }); } function resetPostForm() { imageInput.value = ''; captionInput.value = ''; imagePreview.src = ''; imagePreview.classList.add('hidden'); document.querySelector('.upload-placeholder').classList.remove('hidden'); } 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); article.innerHTML = `
${post.username} ${post.caption}