LikeandCommentSave

This commit is contained in:
2026-01-28 21:01:03 +11:00
parent 39da3c825f
commit 109e463724
3 changed files with 268 additions and 2 deletions

View File

@@ -108,7 +108,7 @@
<!-- Feed Section -->
<section class="feed-container">
<!-- Post Card -->
<article class="post-card">
<article class="post-card" data-post-id="1">
<div class="post-header">
<div class="post-user">
<img src="https://i.pravatar.cc/150?img=1" alt="User" class="avatar-sm">
@@ -142,10 +142,18 @@
<span class="likes">124 likes</span>
<p><span class="username">sarah_j</span> Exploring the Cinque Terre! 🇮🇹✨</p>
</div>
<!-- Comment Section -->
<div class="comment-section">
<div class="added-comments"></div>
<div class="comment-input-wrapper">
<input type="text" class="comment-input" placeholder="Add a comment...">
<button class="post-btn">Post</button>
</div>
</div>
</article>
<!-- Post Card 2 -->
<article class="post-card">
<article class="post-card" data-post-id="2">
<div class="post-header">
<div class="post-user">
<img src="https://i.pravatar.cc/150?img=2" alt="User" class="avatar-sm">
@@ -179,6 +187,14 @@
<span class="likes">892 likes</span>
<p><span class="username">mike_photo</span> Golden hour in the mountains 🏔️</p>
</div>
<!-- Comment Section -->
<div class="comment-section">
<div class="added-comments"></div>
<div class="comment-input-wrapper">
<input type="text" class="comment-input" placeholder="Add a comment...">
<button class="post-btn">Post</button>
</div>
</div>
</article>
<!-- Spacer for bottom nav -->

168
script.js
View File

@@ -96,6 +96,9 @@ document.addEventListener('DOMContentLoaded', () => {
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');
@@ -159,4 +162,169 @@ document.addEventListener('DOMContentLoaded', () => {
}
});
}
// --- 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 = `<span class="comment-user">you</span> ${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 = `<span class="comment-user">you</span> ${text}`;
container.appendChild(commentEl);
}
});

View File

@@ -518,6 +518,88 @@ p {
color: var(--text-main);
}
/* Feed Interactions */
.icon-btn .heart-icon.liked {
fill: #EF4444;
stroke: #EF4444;
animation: likeBounce 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}
@keyframes likeBounce {
0% {
transform: scale(1);
}
50% {
transform: scale(1.3);
}
100% {
transform: scale(1);
}
}
/* Comment Section */
.comment-section {
padding: 0 15px 15px;
display: none;
/* Hidden by default */
}
.comment-section.active {
display: block;
animation: fadeIn 0.3s ease-out;
}
.comment-input-wrapper {
display: flex;
gap: 10px;
margin-top: 10px;
}
.comment-input {
flex: 1;
background: rgba(255, 255, 255, 0.05);
border: 1px solid var(--glass-border);
border-radius: var(--radius-full);
padding: 8px 15px;
color: var(--text-main);
font-size: 13px;
outline: none;
}
.comment-input:focus {
border-color: var(--text-muted);
}
.post-btn {
background: none;
border: none;
color: #3B82F6;
/* Blue accent */
font-weight: 600;
font-size: 13px;
cursor: pointer;
}
.added-comments {
margin-top: 10px;
font-size: 13px;
color: var(--text-main);
display: flex;
flex-direction: column;
gap: 6px;
}
.comment-item {
line-height: 1.4;
}
.comment-user {
font-weight: 600;
margin-right: 5px;
}
/* Bottom Navigation */
.bottom-nav {
position: fixed;