From 3f3e773d3d9470e71f231dce51240fa9e8a12b4f Mon Sep 17 00:00:00 2001 From: Rajyadav999 Date: Sun, 3 May 2026 11:37:12 +0530 Subject: [PATCH] fix: resolve duplicate scripts, null refs, chatbot 404, and missing offline.html --- frontend/js/chatbot.js | 7 +- frontend/js/home.js | 75 +----- frontend/js/pr-generator.js | 53 ++-- frontend/js/pwa.js | 18 +- frontend/js/theme.js | 14 +- index.html | 480 ++++++------------------------------ index.js | 23 +- offline.html | 133 ++++++++++ 8 files changed, 287 insertions(+), 516 deletions(-) create mode 100644 offline.html diff --git a/frontend/js/chatbot.js b/frontend/js/chatbot.js index 5d73c32b..1b01c653 100644 --- a/frontend/js/chatbot.js +++ b/frontend/js/chatbot.js @@ -129,7 +129,10 @@ restoreChatHistory(); // Load data // Note: This path assumes index.html is in /pages/ and data is in /data/ - fetch('../data/chatbot_data.json') + // Resolve path relative to root regardless of current page depth + const isPagesDir = window.location.pathname.includes('/pages/'); + const chatbotDataPath = isPagesDir ? '../../frontend/data/chatbot_data.json' : './frontend/data/chatbot_data.json'; + fetch(chatbotDataPath) .then(response => response.json()) .then(data => { intents = data.intents; @@ -342,4 +345,4 @@ function parseMarkdown(text) { return "I'm not sure about that. Try asking about open source programs or guides."; } -}); +}); \ No newline at end of file diff --git a/frontend/js/home.js b/frontend/js/home.js index c896e5b8..711de401 100644 --- a/frontend/js/home.js +++ b/frontend/js/home.js @@ -123,10 +123,12 @@ document.addEventListener('DOMContentLoaded', () => { // =============================== // Scroll Progress Indicator (Top) +// FIX: Renamed variable from 'scrollProgressBar' to 'homeScrollProgressBar' +// to avoid conflict with the same variable name declared in theme.js // =============================== -const scrollProgressBar = document.getElementById('scrollProgress'); +const homeScrollProgressBar = document.getElementById('scrollProgress'); -if (scrollProgressBar) { +if (homeScrollProgressBar) { window.addEventListener( 'scroll', () => { @@ -136,12 +138,12 @@ if (scrollProgressBar) { document.documentElement.clientHeight; if (docHeight <= 0) { - scrollProgressBar.style.width = '0%'; + homeScrollProgressBar.style.width = '0%'; return; } const scrollPercent = (scrollTop / docHeight) * 100; - scrollProgressBar.style.width = `${scrollPercent}%`; + homeScrollProgressBar.style.width = `${scrollPercent}%`; }, { passive: true } ); @@ -190,6 +192,7 @@ if (scrollProgressBar) { cursor.style.opacity = ''; }); })(); + // =============================== // Back to Top Button // =============================== @@ -285,6 +288,9 @@ document.addEventListener("DOMContentLoaded", () => { const counters = document.querySelectorAll(".counter"); const statsSection = document.querySelector(".stats"); + // FIX: Guard against null statsSection + if (!statsSection) return; + let hasAnimated = false; const animateCounter = (counter) => { @@ -334,65 +340,4 @@ document.addEventListener("DOMContentLoaded", () => { }); observer.observe(statsSection); -}); - -function openModal(program) { - const modal = document.getElementById("programModal"); - const title = document.getElementById("modalTitle"); - const basicInfo = document.getElementById("modalBasicInfo"); - const skills = document.getElementById("modalSkills"); - const prepare = document.getElementById("modalPrepare"); - const tips = document.getElementById("modalTips"); - - const data = { - gsoc: { - title: "Google Summer of Code", - basic: ` - πŸ“… Duration: 12 Weeks
- 🌍 Eligibility: Students worldwide
- πŸ’° Stipend: Paid
- ⏳ Timeline: May–Aug - `, - skills: [ - "Strong problem solving", - "Git & GitHub workflow", - "Open source contribution experience" - ], - prepare: [ - "Start contributing early", - "Fix good first issues", - "Interact with mentors", - "Understand project roadmap" - ], - tips: [ - "Write strong proposal", - "Be active in discussions", - "Submit quality PRs", - "Show consistency" - ] - } - }; - - const programData = data[program]; - - title.innerHTML = programData.title; - basicInfo.innerHTML = programData.basic; - - skills.innerHTML = ""; - prepare.innerHTML = ""; - tips.innerHTML = ""; - - modal.style.display = "flex"; -} - -function closeModal() { - document.getElementById("programModal").style.display = "none"; -} - -/* Accordion Toggle */ -document.addEventListener("click", function (e) { - if (e.target.classList.contains("accordion-header")) { - const body = e.target.nextElementSibling; - body.style.display = body.style.display === "block" ? "none" : "block"; - } }); \ No newline at end of file diff --git a/frontend/js/pr-generator.js b/frontend/js/pr-generator.js index 8e4d7f3a..a162ccda 100644 --- a/frontend/js/pr-generator.js +++ b/frontend/js/pr-generator.js @@ -6,6 +6,18 @@ * Includes AI Assist Controls for fine-grained PR generation. */ +// FIX: Declare aiAssistState on window to avoid re-declaration SyntaxError +// if this script is loaded more than once across pages +if (typeof window.aiAssistState === 'undefined') { + window.aiAssistState = { + creativity: 50, + strictness: 'best-practice', + autoSummarize: true, + autoDetectType: true, + rewriteInput: false, + }; +} + document.addEventListener('DOMContentLoaded', () => { const existingForm = document.getElementById('prGeneratorForm'); @@ -111,17 +123,6 @@ function getStructureSettings() { }; } -// ========================================== -// AI Assist State -// ========================================== -const aiAssistState = { - creativity: 50, - strictness: 'best-practice', - autoSummarize: true, - autoDetectType: true, - rewriteInput: false, -}; - function getCreativityLabel(value) { if (value <= 20) return 'Low'; if (value <= 40) return 'Medium-Low'; @@ -151,7 +152,7 @@ function setupAIAssistControls() { if (slider && valueLabel) { const updateSlider = () => { const val = parseInt(slider.value); - aiAssistState.creativity = val; + window.aiAssistState.creativity = val; valueLabel.textContent = getCreativityLabel(val); // Update slider track gradient @@ -170,7 +171,7 @@ function setupAIAssistControls() { btn.addEventListener('click', () => { btns.forEach(b => b.classList.remove('active')); btn.classList.add('active'); - aiAssistState.strictness = btn.dataset.value; + window.aiAssistState.strictness = btn.dataset.value; }); }); } @@ -180,9 +181,9 @@ function setupAIAssistControls() { const autoDetect = document.getElementById('autoDetectTypeToggle'); const rewriteInput = document.getElementById('rewriteInputToggle'); - if (autoSummarize) autoSummarize.addEventListener('change', () => { aiAssistState.autoSummarize = autoSummarize.checked; }); - if (autoDetect) autoDetect.addEventListener('change', () => { aiAssistState.autoDetectType = autoDetect.checked; }); - if (rewriteInput) rewriteInput.addEventListener('change', () => { aiAssistState.rewriteInput = rewriteInput.checked; }); + if (autoSummarize) autoSummarize.addEventListener('change', () => { window.aiAssistState.autoSummarize = autoSummarize.checked; }); + if (autoDetect) autoDetect.addEventListener('change', () => { window.aiAssistState.autoDetectType = autoDetect.checked; }); + if (rewriteInput) rewriteInput.addEventListener('change', () => { window.aiAssistState.rewriteInput = rewriteInput.checked; }); // Per-field AI assist buttons const assistBtns = document.querySelectorAll('.ai-field-assist-btn'); @@ -219,8 +220,8 @@ async function handleFieldImprove(btn) { body: JSON.stringify({ text, fieldName: targetId, - creativity: aiAssistState.creativity, - strictness: aiAssistState.strictness, + creativity: window.aiAssistState.creativity, + strictness: window.aiAssistState.strictness, }), }); @@ -353,11 +354,11 @@ async function handlePRGeneration(submitBtn, previewSection, textarea) { structureSettings, // AI Assist parameters aiAssist: { - creativity: aiAssistState.creativity, - strictness: aiAssistState.strictness, - autoSummarize: aiAssistState.autoSummarize, - autoDetectType: aiAssistState.autoDetectType, - rewriteInput: aiAssistState.rewriteInput, + creativity: window.aiAssistState.creativity, + strictness: window.aiAssistState.strictness, + autoSummarize: window.aiAssistState.autoSummarize, + autoDetectType: window.aiAssistState.autoDetectType, + rewriteInput: window.aiAssistState.rewriteInput, }, }), }); @@ -661,15 +662,15 @@ async function analyzePRStatus() { if (data.merged) { statusBadge = `Merged`; statusText = "This Pull Request has been successfully merged."; - } + } else if (data.state === "open" && data.draft) { statusBadge = `Draft`; statusText = "This PR is currently in draft state."; - } + } else if (data.state === "open") { statusBadge = `Open`; statusText = "This PR is open and under review."; - } + } else { statusBadge = `Closed`; statusText = "This PR is closed without merge."; diff --git a/frontend/js/pwa.js b/frontend/js/pwa.js index 22307ff8..98950a41 100644 --- a/frontend/js/pwa.js +++ b/frontend/js/pwa.js @@ -48,11 +48,15 @@ if ('serviceWorker' in navigator) { }); } -let deferredPrompt; +// FIX: Use window.deferredPrompt to avoid re-declaration errors +// if this script is ever executed more than once +if (typeof window.deferredPrompt === 'undefined') { + window.deferredPrompt = null; +} window.addEventListener('beforeinstallprompt', (e) => { e.preventDefault(); - deferredPrompt = e; + window.deferredPrompt = e; const showButton = () => { const btn = document.getElementById('pwa-install-btn'); @@ -60,14 +64,14 @@ window.addEventListener('beforeinstallprompt', (e) => { btn.style.display = 'inline-flex'; btn.addEventListener('click', () => { btn.style.display = 'none'; - deferredPrompt.prompt(); - deferredPrompt.userChoice.then((choiceResult) => { + window.deferredPrompt.prompt(); + window.deferredPrompt.userChoice.then((choiceResult) => { if (choiceResult.outcome === 'accepted') { console.log('User accepted the install prompt'); } else { console.log('User dismissed the install prompt'); } - deferredPrompt = null; + window.deferredPrompt = null; }); }); } else { @@ -78,6 +82,6 @@ window.addEventListener('beforeinstallprompt', (e) => { }); window.addEventListener('appinstalled', () => { - deferredPrompt = null; + window.deferredPrompt = null; console.log('PWA was installed'); -}); +}); \ No newline at end of file diff --git a/frontend/js/theme.js b/frontend/js/theme.js index 539c68a3..76619216 100644 --- a/frontend/js/theme.js +++ b/frontend/js/theme.js @@ -77,17 +77,19 @@ function updateThemeIcon(isDark) { /* =============================== CURSOR HIGHLIGHT + FIX: Renamed variable from 'cursor' to 'themeCursor' to avoid + conflict with the 'cursor' variable declared in home.js ================================ */ -const cursor = document.getElementById('cursor-highlight'); +const themeCursor = document.getElementById('cursor-highlight'); -if (cursor) { +if (themeCursor) { document.addEventListener('mousemove', (e) => { - cursor.style.transform = `translate(${e.clientX}px, ${e.clientY}px)`; - cursor.style.opacity = '1'; + themeCursor.style.transform = `translate(${e.clientX}px, ${e.clientY}px)`; + themeCursor.style.opacity = '1'; }); document.addEventListener('mouseleave', () => { - cursor.style.opacity = '0'; + themeCursor.style.opacity = '0'; }); -} +} \ No newline at end of file diff --git a/index.html b/index.html index 4c0fb979..08e37a3a 100644 --- a/index.html +++ b/index.html @@ -110,8 +110,6 @@

- - @@ -169,229 +167,34 @@

πŸŽ₯ Video for Beginners

"> - -
-

Open Source Programs

-

- Explore ongoing and upcoming open-source programs with timelines, - prerequisites, and official resources. -

- -
- -
-
-

Google Summer of Code

-

- A global program focused on bringing new contributors into open - source software development. -

-
- - - - Explore - -
+ +
+
- -
-
-

GSSoC

-

- GirlScript Summer of Code is a three-month-long Open Source program - by GirlScript Foundation. -

-
- - - - Explore - -
-
- -
-
-

Hacktoberfest

-

- A month-long celebration of open-source software run by - DigitalOcean. -

- -
- - - - Explore - -
-
- - -
-
-

Social Winter of Code

-

Beginner-focused winter open-source program.

- -
- - - - Explore - -
-
- - -
-
-

Linux Foundation

-

- Explore various mentorship opportunities within the massive Linux - ecosystem. -

-
- - - - Explore - -
-
- - -
-
-

Outreachy

-

- Provides internships to people subject to systemic bias and - underrepresented in tech. -

-
- - - - Explore - -
-
- - -
-
-

MLH Fellowship

-

- A remote internship-like open source program where you collaborate in pods - on real-world projects with mentorship. -

-
- - - - Explore - -
-
- - - -
-
-

Season of KDE

-

- A mentorship program by KDE that allows contributors to work on open - source desktop and Qt-based projects. -

-
- - - - Explore - -
-
- - -
-
-

Hyperledger Mentorship

-

- A blockchain-focused mentorship program under the Hyperledger open source - ecosystem with guided project contributions. -

-
- + +
+

Open Source Programs

+

+ Explore ongoing and upcoming open-source programs with timelines, + prerequisites, and official resources. +

- - Explore - -
-
+
+ +
+
+

Google Summer of Code

+

+ A global program focused on bringing new contributors into open + source software development. +

+
+ + + Explore + +
@@ -402,14 +205,12 @@

GSSoC

GirlScript Summer of Code is a three-month-long Open Source program by GirlScript Foundation.

- - - + Explore - - + +
@@ -420,14 +221,12 @@

Hacktoberfest

A month-long celebration of open-source software run by DigitalOcean.

- - - + Explore - - + + @@ -435,14 +234,12 @@

Hacktoberfest

Social Winter of Code

Beginner-focused winter open-source program.

- - - + Explore - - + + @@ -453,14 +250,12 @@

Linux Foundation

Explore various mentorship opportunities within the massive Linux ecosystem.

- - - + Explore - - + + @@ -471,14 +266,12 @@

Outreachy

Provides internships to people subject to systemic bias and underrepresented in tech.

- - - + Explore - - + + @@ -489,17 +282,14 @@

MLH Fellowship

A remote internship-like open source program where you collaborate in pods on real-world projects with mentorship.

- - - + Explore - - + + -
@@ -508,14 +298,12 @@

Season of KDE

A mentorship program by KDE that allows contributors to work on open source desktop and Qt-based projects.

- - - + Explore - - + +
@@ -526,14 +314,12 @@

Hyperledger Mentorship

A blockchain-focused mentorship program under the Hyperledger open source ecosystem with guided project contributions.

- - - + Explore - - + + @@ -567,36 +353,10 @@

Start with Strong Foundations

Grow with Mentorship

- Learn alongside maintainers and contributors who’ve already - walked the path you’re starting today. + Learn alongside maintainers and contributors who've already + walked the path you're starting today.

- - - -
- - - - - - - -
- -
- - - - - - - - - - + \ No newline at end of file diff --git a/index.js b/index.js index 4c8dc054..2c2d799d 100644 --- a/index.js +++ b/index.js @@ -5,7 +5,7 @@ const revealOnScroll = () => { revealElements.forEach(element => { const elementTop = element.getBoundingClientRect().top; const elementVisible = 150; - + if (elementTop < window.innerHeight - elementVisible) { element.classList.add('active'); } @@ -42,10 +42,14 @@ const animateCounter = (element) => { }; // Trigger counters when stats section is visible -const statsSection = document.querySelector('.stats-section'); +// FIX: Use '.stats' instead of '.stats-section' to match the actual HTML class +const statsSection = document.querySelector('.stats'); let counterTriggered = false; const checkStatsVisible = () => { + // FIX: Guard against null statsSection before calling getBoundingClientRect + if (!statsSection) return; + if (!counterTriggered) { const sectionTop = statsSection.getBoundingClientRect().top; if (sectionTop < window.innerHeight - 200) { @@ -61,10 +65,13 @@ window.addEventListener('scroll', checkStatsVisible); checkStatsVisible(); // Newsletter form +// FIX: Guard against null newsletterForm before adding event listener const newsletterForm = document.querySelector('.newsletter-form'); -newsletterForm.addEventListener('submit', (e) => { - e.preventDefault(); - const email = e.target.querySelector('input').value; - alert(`Thank you for subscribing! We'll send updates to ${email}`); - e.target.reset(); -}); +if (newsletterForm) { + newsletterForm.addEventListener('submit', (e) => { + e.preventDefault(); + const email = e.target.querySelector('input').value; + alert(`Thank you for subscribing! We'll send updates to ${email}`); + e.target.reset(); + }); +} \ No newline at end of file diff --git a/offline.html b/offline.html new file mode 100644 index 00000000..15159a28 --- /dev/null +++ b/offline.html @@ -0,0 +1,133 @@ + + + + + You're Offline - OpenSource Compass + + + + + + + +
+ + +
+ +
+ +

You're Offline

+

It looks like you've lost your internet connection. Check your network and try again to continue your open source journey.

+ + + +
← Back to Home +
+ + \ No newline at end of file