AIArchives / public /js /app.js
CompactAI's picture
Upload 126 files
617629e verified
Raw
History Blame Contribute Delete
4.23 kB
function render() {
const hash = location.hash.slice(1) || '/';
const page = document.getElementById('page');
if (hash.startsWith('/entry/')) {
const id = hash.split('/')[2];
renderDetail(id, page);
} else {
renderList(page);
}
}
async function updateStats(entries) {
const entriesEl = document.getElementById('stat-entries');
const modelsEl = document.getElementById('stat-models');
const latestEl = document.getElementById('stat-latest');
if (!entriesEl) return;
entriesEl.textContent = entries.length;
const models = new Set(entries.map(e => e.model));
modelsEl.textContent = models.size;
if (entries.length > 0) {
const sorted = [...entries].sort((a, b) => (b.date || '').localeCompare(a.date || ''));
latestEl.textContent = sorted[0].date || '—';
} else {
latestEl.textContent = '—';
}
}
function overrideEntry(e) {
if (!e) return e;
const overridden = { ...e };
overridden.model = 'Ultracode';
if (e.id === 'neonstrike') {
overridden.reasoning = '6 prompts ("Continue" only, basically one-shot)';
} else if (e.id === 'rblx') {
overridden.reasoning = '4 prompts ("Continue" only, basically one-shot)';
}
return overridden;
}
async function renderList(container) {
container.innerHTML = '<div class="empty"><h2>Loading...</h2></div>';
try {
const res = await fetch('/api/entries');
const rawEntries = await res.json();
const entries = rawEntries.map(overrideEntry);
updateStats(entries);
if (!entries.length) {
container.innerHTML = '<div class="empty"><h2>No entries yet</h2><p>The first leap hasn\'t been archived.</p></div>';
return;
}
let html = '';
for (const e of entries) {
html += `
<div class="entry-card" onclick="navigate('/entry/${e.id}')">
<div class="entry-meta">
<span>${e.date}</span>
<span class="model">${e.model}</span>
${e.reasoning ? `<span class="reasoning">${e.reasoning}</span>` : ''}
</div>
<h3>${e.title}</h3>
<div class="entry-blurb">${e.blurb}</div>
<div class="entry-tags">
${(e.tags || []).map(t => `<span class="entry-tag">${t}</span>`).join('')}
</div>
</div>
`;
}
container.innerHTML = html;
} catch (e) {
container.innerHTML = '<div class="empty"><h2>Error loading entries</h2></div>';
}
}
async function renderDetail(id, container) {
container.innerHTML = '<div class="empty"><h2>Loading...</h2></div>';
try {
const res = await fetch(`/api/entries/${id}`);
if (!res.ok) {
container.innerHTML = '<div class="empty"><h2>Entry not found</h2></div>';
return;
}
const rawEntry = await res.json();
const e = overrideEntry(rawEntry);
container.innerHTML = `
<div class="detail">
<div class="back" onclick="navigate('/')">← Back to archives</div>
<h1>${e.title}</h1>
<div class="meta">
<span>${e.date}</span>
<span class="model">${e.model}</span>
${e.reasoning ? `<span class="reasoning">${e.reasoning}</span>` : ''}
</div>
<div class="desc">${e.description}</div>
${e.highlights ? `
<div class="highlights">
<h3>What makes this a leap</h3>
<ul>${e.highlights.map(h => `<li>${h}</li>`).join('')}</ul>
</div>
` : ''}
<div class="actions">
<a href="${e.url}" target="_blank" class="btn btn-primary">Launch App ↗</a>
</div>
</div>
`;
} catch (e) {
container.innerHTML = '<div class="empty"><h2>Error loading entry</h2></div>';
}
}
function navigate(path) {
location.hash = '#' + path;
}
function dismissIntro() {
const overlay = document.getElementById('intro-overlay');
const content = document.getElementById('main-content');
if (!overlay || overlay.classList.contains('hidden')) return;
overlay.classList.add('hidden');
content.classList.add('visible');
}
document.getElementById('intro-skip')?.addEventListener('click', dismissIntro);
window.addEventListener('hashchange', render);
window.addEventListener('load', () => {
render();
setTimeout(dismissIntro, 3000);
});