class AppFeed extends HTMLElement {
constructor() {
super();
this.posts = [];
}
connectedCallback() {
this.attachShadow({ mode: 'open' });
// Initial Skeleton
this.shadowRoot.innerHTML = `
`;
this.fetchPosts();
}
async fetchPosts() {
try {
// Fetch dummy text data
const response = await fetch('https://jsonplaceholder.typicode.com/posts?_limit=5');
const data = await response.json();
// Fetch dummy users for avatars
const usersResponse = await fetch('https://jsonplaceholder.typicode.com/users?_limit=5');
const users = await usersResponse.json();
this.posts = data.map((post, index) => ({
id: post.id,
title: post.title,
body: post.body,
user: users[index] || { name: 'Facebook User', id: 1 },
likes: Math.floor(Math.random() * 50) + 1,
imageSeed: Math.floor(Math.random() * 1000)
}));
this.renderFeed();
} catch (error) {
console.error("Error fetching posts:", error);
this.shadowRoot.getElementById('feed-container').innerHTML = 'Error loading feed.
';
}
}
renderFeed() {
const container = this.shadowRoot.getElementById('feed-container');
container.innerHTML = '';
this.posts.forEach(post => {
const card = document.createElement('div');
card.className = 'post-card';
card.innerHTML = `
${Math.random() > 0.5 ? `
` : ''}
`;
container.appendChild(card);
});
// Re-initialize icons for the new content
if (window.feather) {
feather.replace();
}
// Add event listeners for like buttons
const likeBtns = this.shadowRoot.querySelectorAll('.like-btn');
likeBtns.forEach(btn => {
btn.addEventListener('click', (e) => {
const icon = btn.querySelector('i');
// Simple toggle visual
if (btn.style.color === 'rgb(66, 103, 178)') {
btn.style.color = '#b0b3b8';
icon.style.fill = 'none';
} else {
btn.style.color = '#4267B2'; // FB Blue
icon.style.fill = '#4267B2';
// Dispatch event
this.dispatchEvent(new CustomEvent('post-liked', {
detail: { id: btn.dataset.id },
bubbles: true,
composed: true
}));
}
});
});
}
}
customElements.define('app-feed', AppFeed);