diff --git a/index.html b/index.html index 0c12c92..5cb9d9a 100644 --- a/index.html +++ b/index.html @@ -721,8 +721,8 @@

event Upcoming Deadlines

-

MAR 31, 2026

Proposal Submission Deadline

Ensure your final proposals are submitted by 18:00 UTC.

-

APR 21, 2026

Review Period Starts

Mentors begin ranking of proposals.

+

MAR 31, 2026

Proposal Submission Deadline

Ensure your final proposals are submitted by 18:00 UTC.

+

APR 21, 2026

Review Period Starts

Mentors begin ranking of proposals.

@@ -1971,6 +1971,24 @@

{ + if (!(key in entry.checklist)) entry.checklist[key] = defaults[key]; + }); + } + if (typeof entry.notes !== 'string') entry.notes = ''; + if (typeof entry.progress !== 'number' || isNaN(entry.progress)) entry.progress = 0; + } + return meta[orgName]; + } + + function updateChecklistItem(orgName, key, value) { + const meta = loadWatchlistMeta(); + const entry = getOrgMeta(meta, orgName); + entry.checklist[key] = value; + entry.progress = Math.round(Object.values(entry.checklist).filter(Boolean).length / Object.keys(entry.checklist).length * 100); + entry.updatedAt = new Date().toISOString(); + saveWatchlistMeta(meta); + renderWatchlist(); + } + + function updateOrgNotes(orgName, notes) { + const meta = loadWatchlistMeta(); + const entry = getOrgMeta(meta, orgName); + // Enforce length limit (200 chars) in case browser enforcement is bypassed + entry.notes = String(notes || '').slice(0, 200); + entry.updatedAt = new Date().toISOString(); + saveWatchlistMeta(meta); + } + function refreshOrgGridPreservingVisibleCount() { const previousVisibleCount = visibleCount; const grid = document.getElementById('orgGrid'); @@ -2125,9 +2207,15 @@

{ + const meta = getOrgMeta(watchlistMeta, org.name); + const checklistItems = Object.entries(meta.checklist).map(([k, v]) => `
  • ${k.replace(/_/g, ' ')}
  • `).join(''); + const progressPct = meta.progress || 0; + const item = document.createElement('div'); - item.className = 'bg-white rounded-2xl p-6 border border-zinc-100 flex flex-col sm:flex-row gap-4 items-start hover:shadow-lg transition-all animate-fade-up'; + item.className = 'bg-white rounded-2xl p-6 border border-zinc-100 grid md:grid-cols-[1fr,240px] gap-4 hover:shadow-lg hover:border-primary/30 transition-all'; item.innerHTML = ` -
    - psychology -
    -
    -
    -

    ${escapeHtml(org.name)}

    - Watchlisted +
    +
    +
    +

    ${escapeHtml(org.name)}

    +

    ${escapeHtml(org.cat)} • ${escapeHtml(org.competition)} • ${org.years}y

    +
    + watchlisted +
    +

    ${escapeHtml(org.desc)}

    +
    + ⭐ ${org.years}y veteran + 📊 ${escapeHtml(org.competition)} + 🔧 ${escapeHtml(org.codebase)}
    -

    ${escapeHtml(org.desc)}

    -
    - code ${escapeHtml(org.github)} - bar_chart ${escapeHtml(org.competition)} - +
    + ${org.tags.slice(0, 4).map(t => `${escapeHtml(t)}`).join('')} + ${org.tags.length > 4 ? `+${org.tags.length - 4}` : ''}
    + `; container.appendChild(item); attachOrgCardListeners(item); }); - // Data-driven AI Insight + // Personalized AI insights based on watchlist const allTags = bookmarks.flatMap(o => o.tags); const topTag = [...new Set(allTags)].sort((a,b) => allTags.filter(t => t===b).length - allTags.filter(t => t===a).length)[0]; - const skillFocus = topTag ? `Focus on mastering **${escapeHtml(topTag)}**` : "Start contributing to Good First Issues"; - const safeTopTag = topTag ? escapeHtml(topTag) : null; + const avgProgress = bookmarks.length > 0 + ? Math.round(bookmarks.reduce((sum, org) => sum + (watchlistMeta[org.name]?.progress || 0), 0) / bookmarks.length) + : 0; + const insight = avgProgress < 40 + ? `Keep momentum! ${avgProgress}% progress. Pick one org and read its ideas list this week.` + : `Nice start! ${avgProgress}% progress. Consider drafting a proposal for your top-fit org.`; document.getElementById('aiInsightText').innerHTML = ` - sparkles - Insight: Your watchlist highlights a strong interest in ${safeTopTag || 'diverse stacks'}. ${skillFocus} to increase your acceptance odds for GSoC 2026. + lightbulb + Watching: ${bookmarks.length} org${bookmarks.length !== 1 ? 's' : ''}. Top skill: ${escapeHtml(topTag || 'diverse')}. ${insight} `; }