const newLinkInput = document.getElementById('newLinkInput'); const addLinkBtn = document.getElementById('addLinkBtn'); const newLinksContainer = document.getElementById('newLinksContainer'); const watchedLinksContainer = document.getElementById('watchedLinksContainer'); let linksData = []; // Fetch all links from the server function loadLinks() { fetch('/api/links/') .then(res => res.json()) .then(data => { linksData = data; // store in a global variable renderLinks(); }) .catch(err => console.error(err)); } // Render the links into the two tabs function renderLinks() { // separate them const newLinks = linksData.filter(link => !link.watched); const watchedLinks = linksData.filter(link => link.watched); const newRow = document.createElement('div'); newRow.className = 'row gy-4'; // Render "New" links newLinksContainer.innerHTML = ''; newLinks.forEach(link => { const col = document.createElement('div'); col.className = 'col-12 col-sm-6 col-md-4 col-lg-3'; // responsive columns col.appendChild(createLinkElement(link, false)); newRow.appendChild(col); }); newLinksContainer.appendChild(newRow); const watchedRow = document.createElement('div'); watchedRow.className = 'row gy-4'; // Render "Watched" links watchedLinksContainer.innerHTML = ''; watchedLinks.forEach(link => { const col = document.createElement('div'); col.className = 'col-12 col-sm-6 col-md-4 col-lg-3'; col.appendChild(createLinkElement(link, true)); watchedRow.appendChild(col); }); watchedLinksContainer.appendChild(watchedRow); reinitializeInstagramEmbeds(); } // Create a DOM element for a single link function createLinkElement(link, isWatched) { const wrapper = document.createElement('div'); wrapper.className = 'mb-3'; // Instagram embed blockquote const blockquote = document.createElement('blockquote'); blockquote.className = 'instagram-media'; blockquote.setAttribute('data-instgrm-permalink', link.url); blockquote.style.background = '#FFF'; const p = document.createElement('p'); p.innerText = 'Loading Instagram...'; blockquote.appendChild(p); wrapper.appendChild(blockquote); // Button to mark watched if it's not watched if (!isWatched) { const watchButton = document.createElement('button'); watchButton.className = 'btn btn-sm btn-secondary'; watchButton.innerText = 'Mark Watched'; watchButton.onclick = () => markLinkWatched(link.id); wrapper.appendChild(watchButton); } // Delete button const deleteButton = document.createElement('button'); deleteButton.innerText = 'Delete'; deleteButton.className = 'btn btn-sm btn-danger'; deleteButton.onclick = () => deleteLink(link.id); wrapper.appendChild(deleteButton); return wrapper; } function deleteLink(linkId) { fetch(`/api/links/${linkId}/delete/`, { method: 'DELETE' }) .then(res => { if (res.ok) { linksData = linksData.filter(link => link.id !== linkId); renderLinks(); reinitializeInstagramEmbeds(); } }) .catch(err => console.error(err)); } // Re-run the Instagram embed script after we’ve injected new blockquotes function reinitializeInstagramEmbeds() { if (window.instgrm) { window.instgrm.Embeds.process(); } } // Mark a link as watched function markLinkWatched(linkId) { fetch(`/api/links/${linkId}/watched/`, { method: 'PATCH' }) .then(res => res.json()) .then(updatedLink => { // Update the local array const idx = linksData.findIndex(l => l.id === updatedLink.id); if (idx !== -1) { linksData[idx] = updatedLink; } renderLinks(); reinitializeInstagramEmbeds(); }) .catch(err => console.error(err)); } // Add new link addLinkBtn.addEventListener('click', () => { const newUrl = newLinkInput.value.trim(); if (!newUrl) return; fetch('/api/links/add/', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ url: newUrl }) }) .then(res => res.json()) .then(addedLink => { // update local data linksData.push(addedLink); newLinkInput.value = ''; renderLinks(); reinitializeInstagramEmbeds(); }) .catch(err => console.error(err)); }); // On page load loadLinks();