import { useState, useEffect, useContext } from 'react' import { ChevronLeft, ChevronRight, Calendar as CalendarIcon, CalendarDays } from 'lucide-react' import { AppContext } from '../App' import { useLanguage } from '../i18n/LanguageContext' import { api, PLATFORMS } from '../utils/api' import PostDetailPanel from '../components/PostDetailPanel' import { SkeletonCalendar } from '../components/SkeletonLoader' const DAYS = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'] const STATUS_COLORS = { draft: 'bg-surface-tertiary text-text-secondary', in_review: 'bg-amber-100 text-amber-700', approved: 'bg-blue-100 text-blue-700', scheduled: 'bg-purple-100 text-purple-700', published: 'bg-emerald-100 text-emerald-700', rejected: 'bg-red-100 text-red-700', } function getMonthData(year, month) { const firstDay = new Date(year, month, 1).getDay() const daysInMonth = new Date(year, month + 1, 0).getDate() const prevDays = new Date(year, month, 0).getDate() const cells = [] // Previous month trailing days for (let i = firstDay - 1; i >= 0; i--) { cells.push({ day: prevDays - i, current: false, date: new Date(year, month - 1, prevDays - i) }) } // Current month for (let d = 1; d <= daysInMonth; d++) { cells.push({ day: d, current: true, date: new Date(year, month, d) }) } // Next month leading days const remaining = 42 - cells.length for (let d = 1; d <= remaining; d++) { cells.push({ day: d, current: false, date: new Date(year, month + 1, d) }) } return cells } function getWeekData(startDate) { const cells = [] const start = new Date(startDate) // Align to Sunday start.setDate(start.getDate() - start.getDay()) for (let i = 0; i < 7; i++) { const d = new Date(start) d.setDate(start.getDate() + i) cells.push({ day: d.getDate(), current: true, date: d }) } return cells } function dateKey(d) { return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}` } export default function PostCalendar() { const { t } = useLanguage() const { brands } = useContext(AppContext) const today = new Date() const [year, setYear] = useState(today.getFullYear()) const [month, setMonth] = useState(today.getMonth()) const [posts, setPosts] = useState([]) const [loading, setLoading] = useState(true) const [filters, setFilters] = useState({ brand: '', platform: '', status: '' }) const [selectedPost, setSelectedPost] = useState(null) const [calView, setCalView] = useState('month') // 'month' | 'week' const [weekStart, setWeekStart] = useState(() => { const d = new Date(); d.setDate(d.getDate() - d.getDay()); return d }) useEffect(() => { loadPosts() }, []) const loadPosts = async () => { try { const res = await api.get('/posts') setPosts(Array.isArray(res) ? res : []) } catch (err) { console.error('Failed to load posts:', err) } finally { setLoading(false) } } const cells = calView === 'month' ? getMonthData(year, month) : getWeekData(weekStart) const todayKey = dateKey(today) // Filter posts const filteredPosts = posts.filter(p => { if (filters.brand && String(p.brand_id || p.brandId) !== filters.brand) return false if (filters.platform) { const platforms = p.platforms || (p.platform ? [p.platform] : []) if (!platforms.includes(filters.platform)) return false } if (filters.status && p.status !== filters.status) return false return true }) // Group posts by date (use scheduled_date or published_date) const postsByDate = {} const unscheduled = [] for (const post of filteredPosts) { const dateStr = post.scheduled_date || post.scheduledDate || post.published_date || post.publishedDate if (dateStr) { const key = dateStr.slice(0, 10) // yyyy-mm-dd if (!postsByDate[key]) postsByDate[key] = [] postsByDate[key].push(post) } else { unscheduled.push(post) } } const prevMonth = () => { if (month === 0) { setMonth(11); setYear(y => y - 1) } else setMonth(m => m - 1) } const nextMonth = () => { if (month === 11) { setMonth(0); setYear(y => y + 1) } else setMonth(m => m + 1) } const prevWeek = () => setWeekStart(d => { const n = new Date(d); n.setDate(n.getDate() - 7); return n }) const nextWeek = () => setWeekStart(d => { const n = new Date(d); n.setDate(n.getDate() + 7); return n }) const goToday = () => { setYear(today.getFullYear()); setMonth(today.getMonth()) const d = new Date(); d.setDate(d.getDate() - d.getDay()); setWeekStart(d) } const monthLabel = new Date(year, month).toLocaleString('default', { month: 'long', year: 'numeric' }) const weekLabel = (() => { const start = new Date(weekStart) start.setDate(start.getDate() - start.getDay()) const end = new Date(start); end.setDate(start.getDate() + 6) const fmt = (d) => d.toLocaleString('default', { month: 'short', day: 'numeric' }) return `${fmt(start)} – ${fmt(end)}, ${end.getFullYear()}` })() const handlePostClick = (post) => { setSelectedPost(post) } const handlePanelClose = () => { setSelectedPost(null) loadPosts() } if (loading) { return (
Schedule and plan your posts