import { useState, useEffect, useCallback } from 'react'; import { View, Text, StyleSheet, ScrollView, RefreshControl, TouchableOpacity, Alert, } from 'react-native'; import { Ionicons } from '@expo/vector-icons'; import { useAuthContext } from '../../lib/AuthContext'; import * as api from '../../lib/api'; const DAYS = ['Po', 'Ut', 'St', 'Ct', 'Pa', 'So', 'Ne']; const MONTHS = [ 'Leden', 'Unor', 'Brezen', 'Duben', 'Kveten', 'Cerven', 'Cervenec', 'Srpen', 'Zari', 'Rijen', 'Listopad', 'Prosinec', ]; function getDaysInMonth(year: number, month: number) { return new Date(year, month + 1, 0).getDate(); } function getFirstDayOfMonth(year: number, month: number) { const day = new Date(year, month, 1).getDay(); return day === 0 ? 6 : day - 1; // Monday = 0 } export default function CalendarScreen() { const { token } = useAuthContext(); const [tasks, setTasks] = useState([]); const [refreshing, setRefreshing] = useState(false); const [currentDate, setCurrentDate] = useState(new Date()); const [selectedDate, setSelectedDate] = useState(null); const year = currentDate.getFullYear(); const month = currentDate.getMonth(); const loadTasks = useCallback(async () => { if (!token) return; try { const res = await api.getTasks(token); setTasks(res.data || []); } catch (err: any) { Alert.alert('Chyba', err.message); } }, [token]); useEffect(() => { loadTasks(); }, [loadTasks]); const onRefresh = useCallback(async () => { setRefreshing(true); await loadTasks(); setRefreshing(false); }, [loadTasks]); const prevMonth = () => { setCurrentDate(new Date(year, month - 1, 1)); setSelectedDate(null); }; const nextMonth = () => { setCurrentDate(new Date(year, month + 1, 1)); setSelectedDate(null); }; const daysInMonth = getDaysInMonth(year, month); const firstDay = getFirstDayOfMonth(year, month); const tasksByDate: Record = {}; tasks.forEach((t) => { if (t.due_date) { const d = t.due_date.substring(0, 10); if (!tasksByDate[d]) tasksByDate[d] = []; tasksByDate[d].push(t); } }); const today = new Date().toISOString().substring(0, 10); const selectedTasks = selectedDate ? tasksByDate[selectedDate] || [] : []; return ( } > {/* Month navigator */} {MONTHS[month]} {year} {/* Day headers */} {DAYS.map((d) => ( {d} ))} {/* Calendar grid */} {Array.from({ length: firstDay }).map((_, i) => ( ))} {Array.from({ length: daysInMonth }).map((_, i) => { const day = i + 1; const dateStr = `${year}-${String(month + 1).padStart(2, '0')}-${String(day).padStart(2, '0')}`; const hasTasks = !!tasksByDate[dateStr]; const isToday = dateStr === today; const isSelected = dateStr === selectedDate; return ( setSelectedDate(dateStr)} > {day} {hasTasks && ( )} ); })} {/* Selected date tasks */} {selectedDate && ( Ukoly na {selectedDate} {selectedTasks.length === 0 ? ( Zadne ukoly ) : ( selectedTasks.map((t) => ( {t.title} )) )} )} ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#F8FAFC' }, monthNav: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', padding: 16, backgroundColor: '#fff', }, navBtn: { padding: 8 }, monthTitle: { fontSize: 18, fontWeight: '700', color: '#1E293B' }, dayHeaders: { flexDirection: 'row', backgroundColor: '#fff', paddingBottom: 8, borderBottomWidth: 1, borderBottomColor: '#E2E8F0', }, dayHeader: { flex: 1, textAlign: 'center', fontSize: 12, fontWeight: '600', color: '#64748B', }, grid: { flexDirection: 'row', flexWrap: 'wrap', backgroundColor: '#fff', padding: 4, }, dayCell: { width: '14.28%', aspectRatio: 1, alignItems: 'center', justifyContent: 'center', }, todayCell: { backgroundColor: '#EFF6FF', borderRadius: 20, }, selectedCell: { backgroundColor: '#3B82F6', borderRadius: 20, }, dayText: { fontSize: 15, color: '#1E293B' }, todayText: { color: '#3B82F6', fontWeight: '700' }, selectedText: { color: '#fff', fontWeight: '700' }, dot: { width: 5, height: 5, borderRadius: 3, backgroundColor: '#3B82F6', marginTop: 2, }, tasksSection: { margin: 12, padding: 16, backgroundColor: '#fff', borderRadius: 12, }, tasksSectionTitle: { fontSize: 16, fontWeight: '600', color: '#1E293B', marginBottom: 12 }, noTasks: { color: '#94A3B8', fontSize: 14 }, taskItem: { flexDirection: 'row', alignItems: 'center', gap: 10, paddingVertical: 8, borderBottomWidth: 1, borderBottomColor: '#F1F5F9', }, taskItemText: { fontSize: 14, color: '#1E293B', flex: 1 }, });