// Calendar.jsx — Monthly calendar with tasks
(function () {
const { useState } = React;
const MONTHS = ['Styczeń','Luty','Marzec','Kwiecień','Maj','Czerwiec','Lipiec','Sierpień','Wrzesień','Październik','Listopad','Grudzień'];
const DOW = ['Pn','Wt','Śr','Cz','Pt','Sb','Nd'];
const priorityColor = { high:'#EF4444', medium:'#F59E0B', low:'#22C55E' };
window.Calendar = function Calendar({ tasks, setTasks }) {
const [year, setYear] = useState(2026);
const [month, setMonth] = useState(6); // lipiec
const [selDay, setSelDay] = useState(21);
const [gcalConnected, setGcalConnected] = useState(false);
const [gcalSyncing, setGcalSyncing] = useState(false);
const connectGcal = () => {
if (gcalConnected) { setGcalConnected(false); return; }
setGcalSyncing(true);
setTimeout(() => { setGcalSyncing(false); setGcalConnected(true); }, 1200);
};
const firstDow = (new Date(year, month, 1).getDay() + 6) % 7; // Mon=0
const daysInMon = new Date(year, month + 1, 0).getDate();
const today = { y:2026, m:6, d:21 };
const prevMonth = () => { if (month===0){setYear(y=>y-1);setMonth(11);}else setMonth(m=>m-1); };
const nextMonth = () => { if (month===11){setYear(y=>y+1);setMonth(0);}else setMonth(m=>m+1); };
const pad = n => String(n).padStart(2,'0');
const dateStr = d => `${year}-${pad(month+1)}-${pad(d)}`;
const tasksForDay = d => tasks.filter(t => t.due === dateStr(d));
const selDateStr = dateStr(selDay);
const selTasks = tasks.filter(t => t.due === selDateStr);
const toggle = id => setTasks(p => p.map(t => t.id===id ? {...t,done:!t.done} : t));
const monthPrefix = `${year}-${pad(month+1)}`;
const todayStr = `${today.y}-${pad(today.m+1)}-${pad(today.d)}`;
const cells = [...Array(firstDow).fill(null), ...Array.from({length:daysInMon},(_,i)=>i+1)];
return (
{/* ── Calendar grid ── */}
{/* Google Calendar sync bar */}
{gcalSyncing ? 'Łączenie z Kalendarzem Google…' : gcalConnected ? 'Zsynchronizowano z Kalendarzem Google' : 'Kalendarz Google niepołączony'}
{gcalConnected ? 'Rozłącz' : 'Połącz z Google'}
{/* Nav */}
e.currentTarget.style.background='var(--bg2)'}
onMouseLeave={e=>e.currentTarget.style.background='var(--bg1)'}
>‹
e.currentTarget.style.background='var(--bg2)'}
onMouseLeave={e=>e.currentTarget.style.background='var(--bg1)'}
>›
{/* DOW headers */}
{/* Day cells */}
{cells.map((day, i) => {
if (!day) return
;
const dt = tasksForDay(day);
const isToday = day===today.d && month===today.m && year===today.y;
const isSel = day===selDay;
const hasTasks = dt.length > 0;
return (
setSelDay(day)} style={{
aspectRatio:'1',borderRadius:12,cursor:'pointer',
display:'flex',flexDirection:'column',alignItems:'center',justifyContent:'center',gap:4,
background: isSel ? 'linear-gradient(135deg,rgba(124,92,255,.3),rgba(77,163,255,.2))' : isToday ? 'rgba(124,92,255,.12)' : 'transparent',
border: isSel ? '1.5px solid rgba(124,92,255,.55)' : isToday ? '1.5px solid rgba(124,92,255,.28)' : '1.5px solid transparent',
boxShadow: isSel ? '0 0 16px rgba(124,92,255,.2)' : 'none',
transition:'all .15s',
}}
onMouseEnter={e=>{ if(!isSel) e.currentTarget.style.background='var(--bg-hover)'; }}
onMouseLeave={e=>{ if(!isSel) e.currentTarget.style.background=isToday?'rgba(124,92,255,.12)':'transparent'; }}
>
{day}
{hasTasks && (
{dt.slice(0,3).map((t,ti) => (
))}
)}
);
})}
{/* ── Right panel ── */}
{/* Selected day header */}
{selDay} {MONTHS[month]} {year}
{gcalConnected && Google ✓ }
{selTasks.length===0 ? 'Brak zadań tego dnia' : `${selTasks.length} ${selTasks.length===1?'zadanie':selTasks.length<5?'zadania':'zadań'}`}
{selTasks.length===0 ? (
) : (
{selTasks.map(t => {
const pc = priorityColor[t.priority];
return (
toggle(t.id)} style={{
display:'flex',alignItems:'flex-start',gap:10,padding:'10px 12px',
borderRadius:10,cursor:'pointer',transition:'background .15s',
background:'var(--bg1)',border:'1px solid var(--bdr)',
borderLeft:`3px solid ${t.done?'var(--bdr)':pc}`,
opacity:t.done?0.5:1,
}}
onMouseEnter={e=>e.currentTarget.style.background='var(--bg2)'}
onMouseLeave={e=>e.currentTarget.style.background='var(--bg1)'}
>
{t.text}
);
})}
)}
{/* Month summary */}
Podsumowanie miesiąca
{[
{ label:'Zaplanowane', val: tasks.filter(t=>t.due.startsWith(monthPrefix)).length, color:'#7C5CFF' },
{ label:'Ukończone', val: tasks.filter(t=>t.due.startsWith(monthPrefix)&&t.done).length, color:'#22C55E' },
{ label:'Zaległe', val: tasks.filter(t=>t.due
(
))}
{/* Upcoming this week */}
Najbliższe 7 dni
{tasks.filter(t => {
const d = new Date(t.due); const today7 = new Date('2026-07-21'); today7.setDate(today7.getDate()+7);
return d >= new Date('2026-07-21') && d <= today7 && !t.done;
}).slice(0,4).map((t,i,a) => (
{t.text}
{t.due.slice(8)}.{t.due.slice(5,7)}
))}
);
};
})();