// Gantt view: horizontal timeline of all projects & tasks const GTIcons = window.Icons; const { parseDateKey: gtDate, toDateKey: gtDateKey, relativeDate: gtRel } = window.PMStore; const ZOOM_OPTS = [ { id: 'week', label: '2 Hafta', days: 14 }, { id: 'month', label: '1 Ay', days: 30 }, { id: 'quarter', label: '3 Ay', days: 90 }, ]; function addDaysGT(d, n) { const r = new Date(d); r.setDate(r.getDate() + n); return r; } function startOfDayGT(d) { const r = new Date(d); r.setHours(0,0,0,0); return r; } function sameMonthYear(d) { return d.toLocaleDateString('tr-TR', { month: 'short', year: '2-digit' }); } function GanttView({ state, onSelectTask }) { const [zoom, setZoom] = React.useState('month'); const [projectFilter, setPF] = React.useState('all'); const [showCompleted, setShowComp] = React.useState(false); const [offset, setOffset] = React.useState(0); // day offset for panning const zoomCfg = ZOOM_OPTS.find(z => z.id === zoom) || ZOOM_OPTS[1]; const today = startOfDayGT(new Date()); const rangeStart = addDaysGT(today, -Math.round(zoomCfg.days * 0.3) + offset); const rangeEnd = addDaysGT(rangeStart, zoomCfg.days); const totalDays = zoomCfg.days; const projects = (state.projects || []).filter(p => !p.archived && (projectFilter === 'all' || p.id === projectFilter)); const allTasks = state.tasks || []; const dayPct = (d) => Math.max(0, Math.min(100, ((startOfDayGT(d) - rangeStart) / (1000 * 60 * 60 * 24 * totalDays)) * 100)); // Day column headers const dayHeaders = React.useMemo(() => { const headers = []; let prev = ''; for (let i = 0; i <= totalDays; i++) { const d = addDaysGT(rangeStart, i); const label = d.getDate() === 1 || i === 0 ? sameMonthYear(d) : ''; headers.push({ d, label, isToday: startOfDayGT(d).getTime() === today.getTime() }); } return headers; }, [zoom, offset]); const todayPct = dayPct(today); return (