Sunscreen SPF Recommendation Tool

Sunscreen SPF Recommendation Tool

Get a personalized sun protection plan based on your skin type and activities.

1. Select Your Skin Type (Fitzpatrick Scale)

2. Plan Your Day

Your Personalized Sun Protection Plan

Recommended SPF

SPF 30

Sunscreen Type

Broad Spectrum

Key Recommendations:

${st.name}

${st.description}

`; skinTypeSelector.appendChild(div); }); }; const calculateRecommendation = () => { const selectedSkinType = document.querySelector('input[name="skin-type"]:checked'); const duration = parseFloat(durationInput.value); if (!selectedSkinType) { alert('Please select your skin type.'); return; } if (isNaN(duration) || duration <= 0) { alert('Please enter a valid outdoor duration.'); return; } const skinType = parseInt(selectedSkinType.value); const isWater = waterActivityCheckbox.checked; const isSweat = sweatActivityCheckbox.checked; // --- Recommendation Logic --- let baseSpf = 15; if (UV_INDEX >= 3 && UV_INDEX <= 5) baseSpf = 30; // Moderate UV if (UV_INDEX >= 6 && UV_INDEX <= 7) baseSpf = 50; // High UV if (UV_INDEX >= 8) baseSpf = 50; // Very High UV // Adjust for skin type if (skinType <= 2) baseSpf = Math.max(baseSpf, 30); if (skinType === 1) baseSpf = Math.max(baseSpf, 50); // Adjust for duration if (duration > 2) baseSpf = Math.max(baseSpf, 30); if (duration > 4) baseSpf = 50; let finalSpf = baseSpf; let notes = []; let sunscreenType = "Broad Spectrum"; if (isWater || isSweat) { notes.push('Use a **water-resistant** sunscreen.'); } notes.push(`Apply sunscreen **15-30 minutes before** sun exposure.`); notes.push(`Reapply every **2 hours**, or more often after swimming, sweating, or towel drying.`); notes.push(`Don't forget sensitive areas like ears, neck, feet, and hands.`); if (UV_INDEX >= 3) { notes.push(`Seek shade during peak sun hours (10 a.m. to 4 p.m.).`); } recommendationData = { skinType: skinTypes.find(st => st.type === skinType), duration, isWater, isSweat, uvIndex: UV_INDEX, spf: `SPF ${finalSpf}`, type: sunscreenType, notes }; // --- Display Results --- spfRecommendationEl.textContent = recommendationData.spf; typeRecommendationEl.textContent = recommendationData.type; notesListEl.innerHTML = ''; recommendationData.notes.forEach(note => { const li = document.createElement('li'); li.innerHTML = note.replace(/\*\*(.*?)\*\*/g, '$1'); notesListEl.appendChild(li); }); resultsContainer.style.display = 'block'; }; const generatePdf = () => { if (Object.keys(recommendationData).length === 0) { alert('Please generate a recommendation first.'); return; } const { jsPDF } = window.jspdf; const pdf = new jsPDF('p', 'mm', 'a4'); const pageW = pdf.internal.pageSize.getWidth(); const margin = 15; let y = 0; // --- PDF Styling --- const primaryColor = '#d97706'; // amber-600 const secondaryColor = '#f59e0b'; // amber-500 const textColor = '#422006'; // amber-900 const lightTextColor = '#78350f'; // amber-800 const borderColor = '#fef3c7'; // amber-100 // --- Header --- pdf.setFillColor(primaryColor); pdf.rect(0, 0, pageW, 30, 'F'); pdf.setFontSize(22); pdf.setFont('helvetica', 'bold'); pdf.setTextColor('#FFFFFF'); pdf.text('Personalized Sun Protection Plan', pageW / 2, 18, { align: 'center' }); y = 40; // --- Profile Section --- pdf.setFontSize(14); pdf.setFont('helvetica', 'bold'); pdf.setTextColor(textColor); pdf.text('Your Profile & Conditions', margin, y); y += 8; pdf.setFontSize(11); pdf.setFont('helvetica', 'normal'); pdf.text(`Skin Type:`, margin, y); pdf.text(`${recommendationData.skinType.name} (${recommendationData.skinType.description})`, pageW - margin, y, { align: 'right' }); y += 7; pdf.text(`Outdoor Duration:`, margin, y); pdf.text(`${recommendationData.duration} hours`, pageW - margin, y, { align: 'right' }); y += 7; pdf.text(`Local UV Index:`, margin, y); pdf.text(`${recommendationData.uvIndex} (Moderate)`, pageW - margin, y, { align: 'right' }); y += 10; pdf.setDrawColor(borderColor); pdf.line(margin, y, pageW - margin, y); y += 12; // --- Recommendation Section --- pdf.setFontSize(14); pdf.setFont('helvetica', 'bold'); pdf.text('Your Sunscreen Recommendation', margin, y); y += 10; const boxWidth = (pageW - margin * 3) / 2; pdf.setFillColor('#fffbeb'); pdf.setDrawColor(borderColor); pdf.roundedRect(margin, y, boxWidth, 30, 3, 3, 'FD'); pdf.roundedRect(margin * 2 + boxWidth, y, boxWidth, 30, 3, 3, 'FD'); pdf.setFontSize(10); pdf.setTextColor(lightTextColor); pdf.text('Recommended SPF', margin + boxWidth/2, y + 8, {align: 'center'}); pdf.text('Sunscreen Type', margin * 2 + boxWidth * 1.5, y + 8, {align: 'center'}); pdf.setFontSize(22); pdf.setFont('helvetica', 'bold'); pdf.setTextColor(secondaryColor); pdf.text(recommendationData.spf, margin + boxWidth/2, y + 20, {align: 'center'}); pdf.text(recommendationData.type, margin * 2 + boxWidth * 1.5, y + 20, {align: 'center'}); y += 45; // --- Key Actions Section --- pdf.setFontSize(14); pdf.setFont('helvetica', 'bold'); pdf.setTextColor(textColor); pdf.text('Key Protective Actions', margin, y); y += 8; pdf.setFontSize(10); pdf.setFont('helvetica', 'normal'); recommendationData.notes.forEach(note => { if (y > 260) { pdf.addPage(); y = 20; } pdf.text("•", margin, y); const noteText = note.replace(/\*\*/g, ''); // Remove bold markdown for PDF const noteLines = pdf.splitTextToSize(noteText, pageW - margin * 2 - 5); pdf.text(noteLines, margin + 5, y); y += noteLines.length * 5 + 2; }); // --- Footer --- const finalY = pdf.internal.pageSize.getHeight() - 15; pdf.setDrawColor(borderColor); pdf.line(margin, finalY, pageW - margin, finalY); pdf.setFontSize(8); pdf.setTextColor(lightTextColor); pdf.text('This tool provides general recommendations. Consult a dermatologist for personal advice.', pageW / 2, finalY + 5, { align: 'center' }); pdf.text(`Generated on ${new Date().toLocaleDateString()}`, pageW - margin, finalY + 10, { align: 'right' }); pdf.save('Sunscreen-Recommendation-Plan.pdf'); }; // --- EVENT LISTENERS --- calculateBtn.addEventListener('click', calculateRecommendation); downloadPdfBtn.addEventListener('click', generatePdf); // --- INITIALIZATION --- renderSkinTypes(); });
Scroll to Top