import React, { useState, useEffect, useCallback, useMemo } from 'react'; import { useSource, useAppState, useAction } from './sdk'; import { Badge, Metric, Glass, Icon } from './components'; import { BarChart, Bar, LineChart, Line, PieChart, Pie, Cell, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, Legend } from 'recharts'; import { Calendar, Plus, Settings, Twitter, Linkedin, Instagram, Facebook, TrendingUp, Clock, CheckCircle, FileText, Sparkles, Trash2, Edit2, ChevronLeft, ChevronRight, GripVertical, Save, X, Search, Filter } from 'lucide-react'; // Platform colors from Design Spec const PLATFORM_COLORS: Record = { twitter: '#1da1f2', linkedin: '#0a66c2', instagram: '#e4405f', facebook: '#1877f2', tiktok: '#000000', youtube: '#ff0000', threads: '#000000' }; const PLATFORM_ICONS: Record = { twitter: Twitter, linkedin: Linkedin, instagram: Instagram, facebook: Facebook }; // MOCK DATA - since no providers connected yet const MOCK_KPIs = { total_posts: 127, scheduled_count: 23, published_count: 89, engagement_rate: 4.7, total_reach: 125000 }; const MOCK_POSTS = [ { id: '1', content: 'Excited to announce our new AI-powered feature! ๐Ÿš€ #tech #startup #innovation', platform: 'twitter', scheduled_date: '2026-04-11', scheduled_time: '09:00', status: 'scheduled', engagement: 245, reach: 12500 }, { id: '2', content: 'Behind the scenes at our startup: How we built our MVP in 30 days. Link in bio.', platform: 'linkedin', scheduled_date: '2026-04-11', scheduled_time: '14:00', status: 'scheduled', engagement: 189, reach: 8900 }, { id: '3', content: 'Product update: We just shipped dark mode! ๐ŸŒ™ What feature should we build next?', platform: 'twitter', scheduled_date: '2026-04-10', scheduled_time: '11:30', status: 'published', engagement: 567, reach: 28000 }, { id: '4', content: 'Team spotlight: Meet Sarah, our lead engineer who makes magic happen every day โœจ', platform: 'instagram', scheduled_date: '2026-04-10', scheduled_time: '16:00', status: 'published', engagement: 892, reach: 45000 }, { id: '5', content: '5 lessons we learned scaling from 0 to 10k users. Thread ๐Ÿงต', platform: 'twitter', scheduled_date: '2026-04-09', scheduled_time: '10:00', status: 'published', engagement: 1234, reach: 67000 }, { id: '6', content: 'We are hiring! Join our growing team as a Senior Frontend Developer. Remote-friendly.', platform: 'linkedin', scheduled_date: '2026-04-12', scheduled_time: '09:00', status: 'draft', engagement: 0, reach: 0 }, { id: '7', content: 'Customer success story: How @TechCorp increased productivity by 40% using our platform', platform: 'twitter', scheduled_date: '2026-04-12', scheduled_time: '15:00', status: 'draft', engagement: 0, reach: 0 }, { id: '8', content: 'Weekend vibes: Our team offsite in the mountains ๐Ÿ”๏ธ #teamculture', platform: 'instagram', scheduled_date: '2026-04-13', scheduled_time: '12:00', status: 'scheduled', engagement: 0, reach: 0 }, { id: '9', content: 'New blog post: The future of AI in startup operations. Read more on our website.', platform: 'facebook', scheduled_date: '2026-04-14', scheduled_time: '10:00', status: 'scheduled', engagement: 0, reach: 0 }, { id: '10', content: 'Quick tip: Use keyboard shortcuts to navigate faster. Press ? to see all shortcuts.', platform: 'twitter', scheduled_date: '2026-04-08', scheduled_time: '14:30', status: 'published', engagement: 345, reach: 15600 }, ]; const MOCK_DRAFTS = [ { id: 'd1', content: 'Announcing our Series A funding round! Thank you to all our supporters ๐ŸŽ‰', target_platform: 'twitter', created_at: '2026-04-10' }, { id: 'd2', content: 'Product roadmap update: Q2 2026 priorities and what to expect', target_platform: 'linkedin', created_at: '2026-04-09' }, { id: 'd3', content: 'Tutorial: Getting started with our API in 5 minutes', target_platform: 'twitter', created_at: '2026-04-08' }, { id: 'd4', content: 'Feature comparison: Us vs competitors (humble brag edition)', target_platform: 'linkedin', created_at: '2026-04-07' }, ]; const ENGAGEMENT_DATA = [ { day: 'Mon', engagement: 1200, reach: 45000 }, { day: 'Tue', engagement: 1800, reach: 62000 }, { day: 'Wed', engagement: 2100, reach: 78000 }, { day: 'Thu', engagement: 1650, reach: 55000 }, { day: 'Fri', engagement: 2400, reach: 89000 }, { day: 'Sat', engagement: 980, reach: 34000 }, { day: 'Sun', engagement: 750, reach: 28000 }, ]; const PLATFORM_DISTRIBUTION = [ { name: 'Twitter', value: 45, color: '#1da1f2' }, { name: 'LinkedIn', value: 28, color: '#0a66c2' }, { name: 'Instagram', value: 18, color: '#e4405f' }, { name: 'Facebook', value: 9, color: '#1877f2' }, ]; export default function App() { const [activeTab, setActiveTab] = useState('calendar'); const [selectedPlatform, setSelectedPlatform] = useState('all'); const [selectedPost, setSelectedPost] = useState(null); const [calendarMonth, setCalendarMonth] = useState(new Date(2026, 3, 1)); // April 2026 const [generatorTopic, setGeneratorTopic] = useState(''); const [generatorTone, setGeneratorTone] = useState('professional'); const [generatorPlatform, setGeneratorPlatform] = useState('twitter'); const [generatedContent, setGeneratedContent] = useState(''); const [isGenerating, setIsGenerating] = useState(false); const [draggedDraft, setDraggedDraft] = useState(null); const [showGenerator, setShowGenerator] = useState(false); const dispatch = useAction(); const { data, loading, error } = useSource('/api/framework/connections/app/social-media-content/data', 30000); // Use live data if available, otherwise mock data const kpis = useMemo(() => MOCK_KPIs, []); const posts = useMemo(() => { const allPosts = MOCK_POSTS; if (selectedPlatform === 'all') return allPosts; return allPosts.filter(p => p.platform === selectedPlatform); }, [selectedPlatform]); const drafts = MOCK_DRAFTS; // Calendar helpers const getDaysInMonth = (date: Date) => { const year = date.getFullYear(); const month = date.getMonth(); const firstDay = new Date(year, month, 1); const lastDay = new Date(year, month + 1, 0); const daysInMonth = lastDay.getDate(); const startingDay = firstDay.getDay(); return { daysInMonth, startingDay, year, month }; }; const { daysInMonth, startingDay, year, month } = getDaysInMonth(calendarMonth); const monthName = calendarMonth.toLocaleString('default', { month: 'long' }); const getPostsForDay = useCallback((day: number) => { const dateStr = `${year}-${String(month + 1).padStart(2, '0')}-${String(day).padStart(2, '0')}`; return posts.filter(p => p.scheduled_date === dateStr); }, [posts, year, month]); const getStatusBadge = (status: string) => { const variants: Record = { published: { variant: 'positive' as const, label: 'Published', icon: CheckCircle }, scheduled: { variant: 'neutral' as const, label: 'Scheduled', icon: Clock }, draft: { variant: 'negative' as const, label: 'Draft', icon: FileText } }; const config = variants[status] || variants.draft; const IconComp = config.icon; return ( ); }; const getPlatformIcon = (platform: string) => { const IconComp = PLATFORM_ICONS[platform] || FileText; return ; }; const handleGenerateContent = async () => { if (!generatorTopic.trim()) return; setIsGenerating(true); // Simulate AI generation await new Promise(resolve => setTimeout(resolve, 1500)); const templates: Record = { professional: `๐Ÿš€ ${generatorTopic}\n\nIn today's fast-paced business environment, staying ahead requires innovative solutions. Our team has been working diligently to bring you cutting-edge features that drive results.\n\n#Innovation #Business #Technology #Startup`, casual: `Hey everyone! ๐Ÿ‘‹ Just wanted to share something cool about ${generatorTopic}...\n\nWe've been experimenting with this and the results are pretty awesome! What do you think? Drop a comment below! ๐Ÿ‘‡\n\n#Startup #Tech #Innovation`, witty: `${generatorTopic} walks into a bar... ๐Ÿบ\n\nJust kidding! But seriously, we've been diving deep into this and found some fascinating insights. Thread incoming! ๐Ÿงต\n\n#TechTwitter #Startup #Humor`, inspirational: `โœจ ${generatorTopic}\n\n"The only way to do great work is to love what you do." - Steve Jobs\n\nThis quote perfectly captures our journey. Every challenge is an opportunity in disguise.\n\n#Motivation #Startup #Growth #Inspiration` }; setGeneratedContent(templates[generatorTone] || templates.professional); setIsGenerating(false); }; const handleSaveGenerated = () => { if (!generatedContent.trim()) return; dispatch('toast', { message: 'Draft saved successfully!', type: 'success' }); setGeneratedContent(''); setGeneratorTopic(''); setShowGenerator(false); }; const handleDeletePost = (postId: string) => { dispatch('toast', { message: 'Post deleted', type: 'success' }); setSelectedPost(null); }; const handleDragStart = (draftId: string) => { setDraggedDraft(draftId); }; const handleDrop = (day: number) => { if (!draggedDraft) return; dispatch('toast', { message: `Draft scheduled for ${monthName} ${day}`, type: 'success' }); setDraggedDraft(null); }; const handleDragOver = (e: React.DragEvent) => { e.preventDefault(); }; // Render calendar days const renderCalendarDays = () => { const days = []; const totalCells = 35; // 5 rows ร— 7 cols // Empty cells for days before month starts for (let i = 0; i < startingDay; i++) { days.push(
); } // Actual days for (let day = 1; day <= daysInMonth; day++) { const dayPosts = getPostsForDay(day); days.push(
{}} onDrop={() => handleDrop(day)} onDragOver={handleDragOver} >
{day}
{dayPosts.slice(0, 3).map(post => (
{ e.stopPropagation(); setSelectedPost(post); }} > {post.scheduled_time} ยท {post.content.slice(0, 20)}...
))} {dayPosts.length > 3 && (
+{dayPosts.length - 3} more
)}
); } // Empty cells to fill grid for (let i = days.length; i < totalCells; i++) { days.push(
); } return days; }; return (
{/* Header */}

ContentFlow

Social Media Dashboard

{/* KPI Row */}
{/* Platform Filter */}
Platform: {Object.entries(PLATFORM_ICONS).map(([platform, IconComp]) => ( ))}
{/* Main Grid: Calendar + Upcoming Posts */}
{/* Calendar View */}

{monthName} {year}

{/* Weekday labels */}
{['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'].map(day => (
{day}
))}
{/* Calendar grid */}
{renderCalendarDays()}
{/* Upcoming Posts List */}

Upcoming Posts

{posts.filter(p => p.status !== 'published').slice(0, 8).map(post => (
setSelectedPost(post)} >
{getPlatformIcon(post.platform)} {post.scheduled_date} ยท {post.scheduled_time}
{getStatusBadge(post.status)}

{post.content}

))}
{/* Content Queue & Analytics Row */}
{/* Content Queue (Drafts) */}

Content Queue

{drafts.map(draft => (
handleDragStart(draft.id)} className="flex-shrink-0 w-48 p-3 bg-white/[0.03] rounded-lg border border-white/[0.06] hover:bg-white/[0.06] transition-colors cursor-grab active:cursor-grabbing" >
{getPlatformIcon(draft.target_platform)} {new Date(draft.created_at).toLocaleDateString()}

{draft.content}

))}

Drag drafts to calendar to schedule

{/* Analytics Chart */}

Engagement Trends

{/* Platform Distribution */}

Platform Distribution

`${name} ${(percent * 100).toFixed(0)}%`} labelLine={false} > {PLATFORM_DISTRIBUTION.map((entry, index) => ( ))}
{/* AI Post Generator Panel (collapsible) */} {showGenerator && (

AI Post Generator

setGeneratorTopic(e.target.value)} placeholder="e.g., New feature launch" className="w-full px-3 py-2 bg-white/[0.05] border border-white/[0.08] rounded-lg text-sm focus:outline-none focus:border-blue-500/50" />
{generatedContent && (