';
var w=window.open('','_blank');
if(!w){alert('Popups are blocked. Please allow popups in your browser settings and try again.');return;}
w.document.write(html);w.document.close();
w.onload=function(){w.print();};
toast('🖨️ Print window opened!');
}function renderChart(){
var sel=document.getElementById('chartYear');
var years=getYears();var curVal=sel.value;
sel.innerHTML=years.map(function(y){return '';}).join('');
var year=sel.value||years[0];
var monthly=Array(12).fill(0);
data.forEach(function(e){if(e.date.slice(0,4)===year){var m=parseInt(e.date.slice(5,7))-1;monthly[m]+=parseInt(e.stars);}});
var max=Math.max.apply(null,monthly)||1;
document.getElementById('chartContainer').innerHTML='
'+monthly.map(function(v,i){
var h=Math.round((v/max)*180);
return '
'+(v||'')+'
'+monthNames[i]+'
';
}).join('')+'
';
}function renderMonthly(){
var year=document.getElementById('chartYear').value||new Date().getFullYear().toString();
var rows=[];
for(var m=0;m<12;m++){
var mStr=year+'-'+(m<9?'0':'')+(m+1);
var entries=data.filter(function(e){return e.date.slice(0,7)===mStr;});
if(!entries.length)continue;
var total=entries.reduce(function(s,e){return s+parseInt(e.stars);},0);
var ss=getSenderStats(entries);
rows.push('
';
}function getYears(){
var years=new Set();
data.forEach(function(e){years.add(e.date.slice(0,4));});
if(!years.size)years.add(new Date().getFullYear().toString());
return Array.from(years).sort().reverse();
}document.getElementById('chartYear').addEventListener('change',function(){renderChart();renderMonthly();});// ========== PDF EXPORT ==========
function buildPDFWindow(htmlContent, title){
var w = window.open('', '_blank');
if(!w){
alert('Popups are blocked. Please allow popups in your browser settings, then try again.');
return null;
}
var fullHtml = ''+title+'';
fullHtml += '';
fullHtml += '
';
fullHtml += '💖 To save as PDF: Click the button below or press Ctrl+P → Select Save as PDF';
fullHtml += '';
fullHtml += '
';
fullHtml += htmlContent;
fullHtml += '';
fullHtml += '';
w.document.write(fullHtml);
w.document.close();
return w;
}function exportFullPDF(){
if(!data.length){alert('No data found! Please add some star entries first using the ➕ Add Stars tab.');return;}
var stats = getSenderStats(data);
var totalStars = data.reduce(function(s,e){return s+parseInt(e.stars);},0);
var todayStars = filterData('today').reduce(function(s,e){return s+parseInt(e.stars);},0);
var monthStars = filterData('month').reduce(function(s,e){return s+parseInt(e.stars);},0);
var now = new Date().toLocaleDateString();
var html = '';// Header
html += '
💖 Facebook Stars Tracker — Full Report
';
html += '
Generated: '+now+' • Total Entries: '+data.length+'
';// Summary stats
html += '
';
html += '
⭐ '+totalStars+'
Total Stars
';
html += '
'+todayStars+'
Today
';
html += '
'+monthStars+'
This Month
';
html += '
'+stats.length+'
Members
';
html += '
'+data.length+'
Entries
';
html += '
';// Top 3 podium
if(stats.length >= 1){
html += '
';
stats.forEach(function(s,i){
var net=s.sent-s.received;
var medal=i===0?'🥇':i===1?'🥈':i===2?'🥉':(i+1)+'.';
var netColor=net>0?'color:#e91e8c':net<0?'color:#9333ea':'color:#888';
html+='
'+medal+'
'+esc(s.name)+'
⭐ '+s.sent+'
📩 '+s.received+'
'+(net>0?'+':'')+net+'
';
});
html += '
';// Monthly summary
var monthNames=['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
var year = new Date().getFullYear().toString();
var hasMonthly = false;
var monthlyHtml = '
Month
Total Stars
Entries
Top Sender
';
for(var m=0;m<12;m++){
var mStr=year+'-'+(m<9?'0':'')+(m+1);
var entries=data.filter(function(e){return e.date.slice(0,7)===mStr;});
if(!entries.length)continue;
hasMonthly=true;
var total=entries.reduce(function(s,e){return s+parseInt(e.stars);},0);
var ss=getSenderStats(entries);
monthlyHtml+='
';
html += monthlyHtml;
}// Complete history
html += '
📋 Complete History ('+data.length+' entries)
';
html += '
#
Sender
Receiver
Stars
Date
Note
';
var sorted = data.slice().sort(function(a,b){return b.id-a.id;});
sorted.forEach(function(e,i){
html+='
'+(i+1)+'
'+esc(e.sender)+'
'+esc(e.receiver)+'
⭐ '+e.stars+'
'+e.date+'
'+(e.note||'—')+'
';
});
html += '
';buildPDFWindow(html, 'Stars Tracker — Full Report');
toast('📄 PDF report opened! Press Ctrl+P to save.');
}function exportMyStatsPDF(){
var name = localStorage.getItem('fbMyName')||'';
if(!name){
name = prompt('Enter your name to generate your personal PDF report:');
if(!name) return;
}
if(!data.length){alert('No data found! Please add some star entries first.');return;}var sentEntries = data.filter(function(e){return e.sender.toLowerCase()===name.toLowerCase();}).sort(function(a,b){return b.id-a.id;});
var recvEntries = data.filter(function(e){return e.receiver.toLowerCase()===name.toLowerCase();}).sort(function(a,b){return b.id-a.id;});
var totalSent = sentEntries.reduce(function(s,e){return s+parseInt(e.stars);},0);
var totalRecv = recvEntries.reduce(function(s,e){return s+parseInt(e.stars);},0);
var net = totalSent - totalRecv;
var allStats = getSenderStats(data);
var myRank = allStats.findIndex(function(s){return s.name.toLowerCase()===name.toLowerCase();});
myRank = myRank >= 0 ? (myRank+1) : '—';var html = '';
html += '
📤 Stars I Sent ('+sentEntries.length+' entries • Total: ⭐ '+totalSent+')
';
if(!sentEntries.length){
html += '
No stars sent yet.
';
} else {
html += '
#
Sent To
Stars
Date
Note
';
sentEntries.forEach(function(e,i){html+='
'+(i+1)+'
'+esc(e.receiver)+'
⭐ '+e.stars+'
'+e.date+'
'+(e.note||'—')+'
';});
html += '
';
}// Stars received
html += '
📩 Stars I Received ('+recvEntries.length+' entries • Total: 📩 '+totalRecv+')
';
if(!recvEntries.length){
html += '
No stars received yet.
';
} else {
html += '
#
Received From
Stars
Date
Note
';
recvEntries.forEach(function(e,i){html+='
'+(i+1)+'
'+esc(e.sender)+'
📩 '+e.stars+'
'+e.date+'
'+(e.note||'—')+'
';});
html += '
';
}// Exchange per person
var exchange={};
sentEntries.forEach(function(e){var k=e.receiver;if(!exchange[k])exchange[k]={name:k,iSent:0,theySent:0};exchange[k].iSent+=parseInt(e.stars);});
recvEntries.forEach(function(e){var k=e.sender;if(!exchange[k])exchange[k]={name:k,iSent:0,theySent:0};exchange[k].theySent+=parseInt(e.stars);});
var exArr=Object.values(exchange).sort(function(a,b){return(b.iSent+b.theySent)-(a.iSent+a.theySent);});
if(exArr.length){
html += '
🤝 Stars Exchange Per Person
';
html += '
Person
I Sent
They Sent Me
Balance
';
exArr.forEach(function(p){
var bal=p.iSent-p.theySent;
var bc=bal>0?'color:#e91e8c':bal<0?'color:#9333ea':'color:#888';
html+='
'+esc(p.name)+'
⭐ '+p.iSent+'
📩 '+p.theySent+'
'+(bal>0?'+':'')+bal+'
';
});
html += '
';
}buildPDFWindow(html, 'My Stars Report — '+name);
toast('📄 Your personal PDF opened! Press Ctrl+P to save.');
}function toast(msg,type){
var t=document.getElementById('toast');
t.textContent=msg;t.style.background=type==='error'?'#ef4444':'#22c55e';
t.classList.add('show');setTimeout(function(){t.classList.remove('show');},3000);
}function esc(str){return String(str||'').replace(/&/g,'&').replace(//g,'>').replace(/"/g,'"');}