const feedEl = document.getElementById('feed');
const sortSelect = document.getElementById('sort-select');
const userFilter = document.getElementById('user-filter');
const cookieName = 'linklog-feed-preferences';
function readPreferences() {
const cookie = document.cookie
.split('; ')
.find((row) => row.startsWith(`${cookieName}=`));
if (!cookie) {
return { sort: 'newest', user: '' };
}
try {
return JSON.parse(decodeURIComponent(cookie.split('=')[1]));
} catch (error) {
return { sort: 'newest', user: '' };
}
}
function writePreferences(pref) {
const value = encodeURIComponent(JSON.stringify(pref));
document.cookie = `${cookieName}=${value}; path=/; max-age=31536000`;
}
function renderFeed(items) {
feedEl.innerHTML = '';
if (!items.length) {
feedEl.innerHTML = '
';
return;
}
items.forEach((item) => {
const article = document.createElement('article');
article.className = 'link-item';
const header = document.createElement('div');
header.className = 'link-header';
const avatar = document.createElement('div');
avatar.className = 'avatar';
avatar.textContent = (item.user?.username || 'U').slice(0, 1).toUpperCase();
const userName = document.createElement('div');
userName.className = 'user-name';
userName.textContent = item.user?.username || 'unknown';
header.appendChild(avatar);
header.appendChild(userName);
const title = document.createElement('h2');
const link = document.createElement('a');
link.href = item.url;
link.target = '_blank';
link.rel = 'noopener noreferrer';
link.textContent = item.title || item.url;
title.appendChild(link);
const comment = document.createElement('div');
comment.className = 'comment';
comment.textContent = item.comment || 'No comment provided';
const meta = document.createElement('div');
meta.className = 'meta';
meta.textContent = item.created_at || 'updated recently';
article.appendChild(header);
article.appendChild(title);
article.appendChild(comment);
article.appendChild(meta);
feedEl.appendChild(article);
});
}
async function loadFeed() {
const routeUser = document.body.dataset.userFilter;
const endpoint = routeUser
? `/api/public/feed/${encodeURIComponent(routeUser)}`
: '/api/public/feed';
const response = await fetch(endpoint);
const data = await response.json();
let items = data || [];
const pref = readPreferences();
if (pref.user && !routeUser) {
items = items.filter((item) => (item.user?.username || '').toLowerCase() === pref.user.toLowerCase());
}
if (pref.sort === 'oldest') {
items = [...items].reverse();
}
renderFeed(items);
}
function syncPreferences() {
const pref = readPreferences();
sortSelect.value = pref.sort;
userFilter.value = pref.user;
sortSelect.addEventListener('change', (event) => {
const next = { ...readPreferences(), sort: event.target.value };
writePreferences(next);
loadFeed();
});
userFilter.addEventListener('input', (event) => {
const next = { ...readPreferences(), user: event.target.value.trim() };
writePreferences(next);
loadFeed();
});
}
syncPreferences();
loadFeed();