import { useContext, useEffect, useState, useMemo } from 'react' import { Link, useNavigate } from 'react-router-dom' import { format, isAfter, isBefore, addDays } from 'date-fns' import { FileText, Megaphone, AlertTriangle, ArrowRight, Clock, Landmark, CheckSquare, FolderKanban } from 'lucide-react' import { AppContext } from '../App' import { useAuth } from '../contexts/AuthContext' import { useLanguage } from '../i18n/LanguageContext' import { api, PRIORITY_CONFIG } from '../utils/api' import StatusBadge from '../components/StatusBadge' import BrandBadge from '../components/BrandBadge' import DatePresetPicker from '../components/DatePresetPicker' import { SkeletonDashboard } from '../components/SkeletonLoader' function getBudgetBarColor(percentage) { if (percentage > 90) return 'bg-red-500' if (percentage > 70) return 'bg-amber-500' return 'bg-emerald-500' } function BudgetSummary({ finance }) { const { t, currencySymbol } = useLanguage() if (!finance) return null const totalReceived = finance.totalReceived || 0 const mainAvailable = finance.mainAvailable != null ? finance.mainAvailable : (finance.remaining || 0) const consumed = totalReceived - mainAvailable const pct = totalReceived > 0 ? (consumed / totalReceived) * 100 : 0 const barColor = getBudgetBarColor(pct) return (

{t('dashboard.budgetOverview')}

{t('dashboard.details')}
{totalReceived === 0 ? (
{t('dashboard.noBudgetRecorded')}. {t('dashboard.addBudget')}
) : ( <>
{consumed.toLocaleString()} {currencySymbol} {t('dashboard.spent')} {totalReceived.toLocaleString()} {currencySymbol} {t('dashboard.received')}
= 0 ? 'text-emerald-600' : 'text-red-600'}`}> {mainAvailable.toLocaleString()} {currencySymbol} {t('dashboard.remaining')}
)}
) } function ActiveCampaignsList({ campaigns, finance }) { const { t, currencySymbol } = useLanguage() const active = campaigns.filter(c => c.status === 'active') const campaignData = (finance?.campaigns || []).filter(c => c.status === 'active') if (active.length === 0) return null return (

{t('dashboard.activeCampaigns')}

{t('dashboard.viewAll')}
{active.slice(0, 5).map(c => { const cd = campaignData.find(d => d.id === (c._id || c.id)) || {} const spent = cd.tracks_spent || 0 const allocated = cd.tracks_allocated || 0 const pct = allocated > 0 ? (spent / allocated) * 100 : 0 const barColor = getBudgetBarColor(pct) return (

{c.name}

{allocated > 0 && (
{spent.toLocaleString()} {allocated.toLocaleString()} {currencySymbol}
)}
) })}
) } function MyTasksList({ tasks, currentUserId, navigate, t }) { const myTasks = useMemo(() => tasks .filter(task => { const assignedId = task.assigned_to_id || task.assignedTo return assignedId === currentUserId && task.status !== 'done' }) .slice(0, 5), [tasks, currentUserId]) return (

{t('dashboard.myTasks')}

{t('dashboard.viewAll')}
{myTasks.length === 0 ? (
{t('dashboard.allOnTrack')}
) : ( myTasks.map(task => ( )) )}
) } function ProjectProgress({ projects, tasks, t }) { if (!projects || projects.length === 0) return null const activeProjects = projects .filter(p => p.status === 'active' || p.status === 'in_progress') .slice(0, 5) if (activeProjects.length === 0) return null return (

{t('dashboard.projectProgress')}

{t('dashboard.viewAll')}
{activeProjects.map(project => { const projectId = project._id || project.id const projectTasks = tasks.filter(t => (t.project_id || t.projectId) === projectId) const doneTasks = projectTasks.filter(t => t.status === 'done').length const totalTasks = projectTasks.length const pct = totalTasks > 0 ? (doneTasks / totalTasks) * 100 : 0 return (

{project.name}

{doneTasks}/{totalTasks} {t('tasks.tasks')}
) })}
) } function ActivityFeed({ posts, deadlines, navigate, t }) { const [tab, setTab] = useState('posts') const hasPosts = posts.length > 0 const hasDeadlines = deadlines.length > 0 return (
{t('dashboard.viewAll')}
{tab === 'posts' ? ( !hasPosts ? (
{t('dashboard.noPostsYet')}
) : ( posts.slice(0, 6).map(post => ( )) ) ) : ( !hasDeadlines ? (
{t('dashboard.noUpcomingDeadlines')}
) : ( deadlines.map(task => ( )) ) )}
) } export default function Dashboard() { const { t, currencySymbol } = useLanguage() const navigate = useNavigate() const { currentUser } = useContext(AppContext) const { hasModule } = useAuth() const [posts, setPosts] = useState([]) const [campaigns, setCampaigns] = useState([]) const [tasks, setTasks] = useState([]) const [projects, setProjects] = useState([]) const [finance, setFinance] = useState(null) const [loading, setLoading] = useState(true) const [dateFrom, setDateFrom] = useState('') const [dateTo, setDateTo] = useState('') const [activePreset, setActivePreset] = useState('') useEffect(() => { loadData() }, []) const loadData = async () => { try { const fetches = [] if (hasModule('marketing')) { fetches.push(api.get('/posts?limit=50&sort=-createdAt').then(r => ({ key: 'posts', data: Array.isArray(r) ? r : [] }))) fetches.push(api.get('/campaigns').then(r => ({ key: 'campaigns', data: Array.isArray(r) ? r : [] }))) } if (hasModule('projects')) { fetches.push(api.get('/tasks').then(r => ({ key: 'tasks', data: Array.isArray(r) ? r : [] }))) fetches.push(api.get('/projects').then(r => ({ key: 'projects', data: Array.isArray(r) ? r : [] }))) } if (hasModule('finance')) { fetches.push(api.get('/finance/summary').then(r => ({ key: 'finance', data: r || null }))) } const results = await Promise.allSettled(fetches) results.forEach(r => { if (r.status !== 'fulfilled') return const { key, data } = r.value if (key === 'posts') setPosts(data) else if (key === 'campaigns') setCampaigns(data) else if (key === 'tasks') setTasks(data) else if (key === 'projects') setProjects(data) else if (key === 'finance') setFinance(data) }) } catch (err) { console.error('Dashboard load error:', err) } finally { setLoading(false) } } const filteredPosts = useMemo(() => { if (!dateFrom && !dateTo) return posts return posts.filter(p => { const d = p.scheduled_date || p.scheduledDate if (!d) return true if (dateFrom && d < dateFrom) return false if (dateTo && d > dateTo) return false return true }) }, [posts, dateFrom, dateTo]) const filteredTasks = useMemo(() => { if (!dateFrom && !dateTo) return tasks return tasks.filter(t => { const d = t.due_date || t.dueDate if (!d) return true if (dateFrom && d < dateFrom) return false if (dateTo && d > dateTo) return false return true }) }, [tasks, dateFrom, dateTo]) const activeCampaigns = campaigns.filter(c => c.status === 'active').length const overdueTasks = filteredTasks.filter(t => t.dueDate && new Date(t.dueDate) < new Date() && t.status !== 'done' ).length const upcomingDeadlines = useMemo(() => filteredTasks .filter(t => { if (!t.dueDate || t.status === 'done') return false const due = new Date(t.dueDate) const now = new Date() return isAfter(due, now) && isBefore(due, addDays(now, 7)) }) .sort((a, b) => new Date(a.dueDate) - new Date(b.dueDate)) .slice(0, 6), [filteredTasks]) // Inline stat values — no card component needed const stats = [] if (hasModule('marketing')) { stats.push({ label: t('dashboard.totalPosts'), value: filteredPosts.length, detail: `${filteredPosts.filter(p => p.status === 'published').length} ${t('dashboard.published')}`, icon: FileText, accent: 'text-indigo-600' }) stats.push({ label: t('dashboard.activeCampaigns'), value: activeCampaigns, detail: `${campaigns.length} ${t('dashboard.total')}`, icon: Megaphone, accent: 'text-pink-600' }) } if (hasModule('projects')) { stats.push({ label: t('dashboard.overdueTasks'), value: overdueTasks, detail: overdueTasks > 0 ? t('dashboard.needsAttention') : t('dashboard.allOnTrack'), icon: AlertTriangle, accent: overdueTasks > 0 ? 'text-red-600' : 'text-emerald-600' }) } if (loading) return return (
{/* Welcome + Date presets */}

{t('dashboard.welcomeBack')}, {currentUser?.name || 'there'}

{ setDateFrom(from); setDateTo(to); setActivePreset(key) }} onClear={() => { setDateFrom(''); setDateTo(''); setActivePreset('') }} />
{/* Stats — compact inline row, no cards */} {stats.length > 0 && (
{stats.map((s, i) => (
{s.value} {s.label}

{s.detail}

))}
)} {/* My Tasks + Project Progress */} {hasModule('projects') && (
)} {/* Budget + Active Campaigns */} {(hasModule('finance') || hasModule('marketing')) && (
{hasModule('finance') && } {hasModule('marketing') && (
)}
)} {/* Activity — merged posts + deadlines */} {(hasModule('marketing') || hasModule('projects')) && ( )}
) }