Personalized Vision Health Plan

Personalized Vision Health Plan

Get actionable tips to support your eye health.

Your Daily Habits

4. Which of these eye-healthy foods do you eat regularly?

Your Vision Concerns

Select any symptoms you experience on a regular basis.

${c.name}

`).join(''); }; // --- EVENT LISTENERS --- const attachEventListeners = () => { tabs.forEach(tab => tab.addEventListener('click', () => switchTab(tab.dataset.tab))); prevBtn.addEventListener('click', navigatePrev); nextBtn.addEventListener('click', navigateNext); getPlanBtn.addEventListener('click', handleGetPlan); downloadPdfBtn.addEventListener('click', handleDownloadPdf); // Lifestyle inputs screenTimeSelect.addEventListener('change', (e) => userState.lifestyle.screenTime = e.target.value); outdoorTimeSelect.addEventListener('change', (e) => userState.lifestyle.outdoorTime = e.target.value); smokingSelect.addEventListener('change', (e) => userState.lifestyle.smoking = e.target.value); dietListContainer.addEventListener('change', (e) => { if (e.target.classList.contains('diet-checkbox')) { const food = e.target.dataset.food; if (e.target.checked) { userState.lifestyle.diet.push(food); } else { userState.lifestyle.diet = userState.lifestyle.diet.filter(f => f !== food); } } }); concernsListContainer.addEventListener('click', (e) => { const card = e.target.closest('.selectable-card'); if (card) { const concernId = card.dataset.concernId; card.classList.toggle('selected'); if (card.classList.contains('selected')) { userState.concerns.push(concernId); } else { userState.concerns = userState.concerns.filter(c => c !== concernId); } } }); }; // --- NAVIGATION --- const switchTab = (targetTab) => { tabs.forEach(tab => tab.classList.toggle('active', tab.dataset.tab === targetTab)); tabContents.forEach(content => content.classList.toggle('active', content.id === targetTab)); updateNavButtons(); }; const updateNavButtons = () => { const activeTabIndex = Array.from(tabs).findIndex(tab => tab.classList.contains('active')); prevBtn.style.visibility = activeTabIndex === 0 ? 'hidden' : 'visible'; nextBtn.style.visibility = activeTabIndex === tabs.length - 1 ? 'hidden' : 'visible'; }; const navigatePrev = () => { const activeTabIndex = Array.from(tabs).findIndex(tab => tab.classList.contains('active')); if (activeTabIndex > 0) switchTab(tabs[activeTabIndex - 1].dataset.tab); }; const navigateNext = () => { const activeTabIndex = Array.from(tabs).findIndex(tab => tab.classList.contains('active')); if (activeTabIndex < tabs.length - 1) switchTab(tabs[activeTabIndex + 1].dataset.tab); }; // --- API & RESULTS LOGIC --- const handleGetPlan = async () => { resultsLoader.classList.remove('hidden'); resultsOutput.classList.add('hidden'); getPlanBtn.style.display = 'none'; const prompt = buildPrompt(); const insightsText = await callGeminiApi(prompt); renderSummary(insightsText); resultsLoader.classList.add('hidden'); resultsOutput.classList.remove('hidden'); }; const buildPrompt = () => { const concernsText = userState.concerns.map(id => CONCERNS.find(c => c.id === id).name).join(', ') || 'None reported'; return ` As a health and wellness AI assistant (not a medical professional), create a personalized vision health plan based on the user's profile. **User's Profile:** - Daily Screen Time: ${userState.lifestyle.screenTime} - Daily Outdoor Time: ${userState.lifestyle.outdoorTime} - Smoker: ${userState.lifestyle.smoking} - Regularly Eats: ${userState.lifestyle.diet.join(', ') || 'Not specified'} - Reported Vision Concerns: ${concernsText} **Task:** Generate a supportive and actionable plan. Structure your response into the following sections using the exact headings: ### Understanding Your Vision Profile Briefly summarize how the user's lifestyle factors might relate to their concerns. For example, connect high screen time to eye strain, or smoking to long-term eye health risks. ### Your Personalized Action Plan Provide 3-5 specific, non-medical tips tailored to the user's inputs. - If screen time is high and they report eye strain, strongly recommend the 20-20-20 rule. - If diet is lacking, suggest specific foods to incorporate. - If outdoor time is low, explain the benefits of natural light for eye health. - If they smoke, gently mention it's one of the most significant controllable risk factors for eye diseases. - If they report dry eyes, suggest conscious blinking and staying hydrated. ### General Eye Health Best Practices Include 2-3 universal tips, such as wearing sunglasses with UV protection and the importance of regular comprehensive eye exams. **IMPORTANT:** Conclude the entire response with a clear, bolded disclaimer: **Disclaimer: This plan provides general wellness tips and is not a substitute for professional medical advice. Consult with an eye care professional for any vision problems or before making significant lifestyle changes.** `; }; const callGeminiApi = async (prompt) => { const apiKey = ""; // Provided by environment const apiUrl = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-preview-05-20:generateContent?key=${apiKey}`; const payload = { contents: [{ role: "user", parts: [{ text: prompt }] }] }; try { const response = await fetch(apiUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); if (!response.ok) throw new Error(`API Error: ${response.status}`); const data = await response.json(); return data.candidates[0].content.parts[0].text; } catch (error) { console.error("Gemini API Error:", error); return "## Error\nCould not generate your plan. Please try again later.\n\n**Disclaimer:** This is not medical advice."; } }; const renderSummary = (insightsText) => { document.getElementById('summary-date').textContent = `Plan generated on ${new Date().toLocaleDateString('en-US')}`; const summaryHtml = `

Your Profile Summary

  • Screen Time: ${userState.lifestyle.screenTime} per day
  • Outdoor Time: ${userState.lifestyle.outdoorTime} per day
  • Smoker: ${userState.lifestyle.smoking}
  • Regularly Eats: ${userState.lifestyle.diet.join(', ') || 'None specified'}
  • Reported Concerns: ${userState.concerns.map(id => CONCERNS.find(c => c.id === id).name).join(', ') || 'None'}
`; const insightsHtml = insightsText .replace(/### (.*?)\n/g, '

$1

') .replace(/\n\n/g, '

') .replace(/\n- /g, '
  • ') .replace(/(\n- .*?)+/g, (match) => match.replace(/\n- /g, '
  • ') + '
') .replace(/
  • /,'') .replace(/\*\*(.*?)\*\*/g, '$1'); summaryContentContainer.innerHTML = summaryHtml + insightsHtml; }; // --- PDF GENERATION --- const handleDownloadPdf = () => { const content = document.getElementById('pdf-content'); if (!content) return; html2canvas(content, { scale: 2, useCORS: true, backgroundColor: '#ffffff' }) .then(canvas => { const imgData = canvas.toDataURL('image/png'); const pdf = new jsPDF({ orientation: 'p', unit: 'mm', format: 'a4' }); const pdfWidth = pdf.internal.pageSize.getWidth(); const ratio = canvas.width / canvas.height; const imgWidth = pdfWidth - 20; let imgHeight = imgWidth / ratio; let heightLeft = imgHeight; let position = 10; pdf.addImage(imgData, 'PNG', 10, position, imgWidth, imgHeight); heightLeft -= (pdf.internal.pageSize.getHeight() - 20); while (heightLeft > 0) { position = -heightLeft - 10; pdf.addPage(); pdf.addImage(imgData, 'PNG', 10, position, imgWidth, imgHeight); heightLeft -= (pdf.internal.pageSize.getHeight() - 20); } pdf.save('My-Vision-Health-Plan.pdf'); }) .catch(err => console.error("PDF Generation Error:", err)); }; // --- START THE APP --- initialize(); });
  • Scroll to Top