Fantasy Sports Draft Planner

Fantasy Sports Draft Planner

This is your current roster. Click any cell (except 'Action') to edit the data. Totals will update automatically.

Player Name Position Team Cost ($) Notes Action
Total Players: 0
Total Cost: $0.00

Click a player from the pool to draft them to your roster. Use the filter to find players by position.

Available Players

Manually add or remove players from the database. This list feeds the 'Player Pool' tab.

Player Database

Player Name Pos Team Cost ($) Action

No players available. Check your filter or add players to the database.

'; return; } availablePlayers.forEach(player => { const div = document.createElement('div'); div.className = 'fdp-player-item'; div.dataset.id = player.id; div.innerHTML = `
${player.name} (${player.pos})
${player.team} - $${player.cost.toFixed(2)}
`; playerPool.appendChild(div); }); }; // Populates Tab 2 (Builder) Filter const populateFilterDropdown = () => { const positions = [...new Set(playerDatabase.map(p => p.pos))]; filterPosition.innerHTML = ''; positions.sort().forEach(pos => { filterPosition.innerHTML += ``; }); }; // --- EVENT HANDLERS (TAB 1 - DASHBOARD) --- logBody.addEventListener('blur', (e) => { if (e.target.isContentEditable) { const id = parseInt(e.target.dataset.id, 10); const prop = e.target.dataset.prop; let newValue = e.target.textContent.trim(); const itemIndex = myRoster.findIndex(item => item.id === id); if (itemIndex > -1 && prop) { if (prop === 'cost') { newValue = parseFloat(newValue) || 0; } myRoster[itemIndex][prop] = newValue; renderRosterTable(); // Re-render and calculate totals } } }, true); // Use capture phase logBody.addEventListener('click', (e) => { if (e.target.classList.contains('fdp-btn-delete')) { const id = parseInt(e.target.dataset.id, 10); myRoster = myRoster.filter(item => item.id !== id); renderRosterTable(); renderPlayerPool(); // Add player back to pool } }); // --- PDF DOWNLOAD FUNCTION (CORRECTED) --- const downloadPDF = () => { // 1. Check if jsPDF is loaded if (typeof jspdf === 'undefined' || typeof jspdf.jsPDF === 'undefined') { console.error('FDP Tool: jsPDF library not loaded. Please check your connection.'); return; // Fail silently in UI } if (typeof jspdf.autoTable === 'undefined') { console.error('FDP Tool: jsPDF-AutoTable plugin not loaded. Please check your connection.'); return; // Fail silently in UI } // 2. Check for empty roster if (myRoster.length === 0) { console.log('FDP Tool: Roster is empty. Nothing to download.'); return; // Don't download an empty PDF } try { const { jsPDF } = jspdf; const doc = new jsPDF(); const head = [['Player Name', 'Position', 'Team', 'Cost ($)', 'Notes']]; const body = myRoster.map(item => [item.name, item.pos, item.team, item.cost.toFixed(2), item.notes || '']); doc.setFontSize(18); doc.text("My Team Roster", 14, 22); jsPDF.autoTable.default(doc, { startY: 30, head: head, body: body, theme: 'grid', headStyles: { fillColor: '#007bff' }, columnStyles: { 3: { halign: 'right' } } }); // Add Summary const finalY = doc.autoTable.previous.finalY; doc.setFontSize(12); doc.setFont('helvetica', 'bold'); doc.text(`Total Players: ${totalPlayers.textContent}`, 14, finalY + 10); doc.text(`Total Cost: ${totalCost.textContent}`, doc.internal.pageSize.width - 14, finalY + 10, { align: 'right' }); doc.save('fantasy-roster.pdf'); } catch (e) { console.error('FDP Tool: Error generating PDF:', e); } }; downloadPdfBtn.addEventListener('click', downloadPDF); // --- EVENT HANDLERS (TAB 2 - BUILDER) --- filterPosition.addEventListener('change', renderPlayerPool); playerPool.addEventListener('click', (e) => { const item = e.target.closest('.fdp-player-item'); if (!item) return; const id = parseInt(item.dataset.id, 10); const player = playerDatabase.find(p => p.id === id); if (!player) return; myRoster.push({ ...player, notes: '' }); // Add a copy with notes renderRosterTable(); renderPlayerPool(); // Will remove player from pool // Switch to dashboard (Spec II.B.4.o) tabs[0].click(); }); // --- EVENT HANDLERS (TAB 3 - CONFIG) --- addPlayerBtn.addEventListener('click', () => { const name = newNameInput.value.trim(); const pos = newPosInput.value.trim().toUpperCase(); const team = newTeamInput.value.trim().toUpperCase(); const cost = parseFloat(newCostInput.value) || 0; if (!name || !pos || !team) { alert('Please fill in Name, Position, and Team.'); // Re-adding alert as it's not in PDF function return; } const newId = (playerDatabase.length > 0 ? Math.max(...playerDatabase.map(p => p.id)) : 0) + 1; playerDatabase.push({ id: newId, name, pos, team, cost }); renderDbTable(); configForm.reset(); }); dbBody.addEventListener('click', (e) => { if (e.target.classList.contains('fdp-btn-delete')) { const id = parseInt(e.target.dataset.id, 10); // Check if player is on roster if (myRoster.some(p => p.id === id)) { alert('Cannot delete player: They are currently on your roster. Remove them from the roster first.'); return; } playerDatabase = playerDatabase.filter(item => item.id !== id); renderDbTable(); } }); // --- INITIALIZATION --- const init = () => { // Initial Renders renderDbTable(); renderRosterTable(); // Set up tabs updateNavButtons(); // Show the first tab on load if (tabs.length > 0) { fdpShowTab('fdp-dashboard-tab', tabs[0]); } }; init(); });
Scroll to Top