import { useState, useEffect } from "react";
const DAYS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
const MONTHS = ["January","February","March","April","May","June","July","August","September","October","November","December"];
const CONTENT_TYPES = ["Reel", "Carousel", "Story", "Static Post", "Collab", "Live"];
const STATUS_OPTIONS = ["Idea", "Draft", "In Review", "Scheduled", "Posted"];
const PILLARS = ["Education", "Entertainment", "Promotion", "Community", "Behind the Scenes", "User Generated"];
const TYPE_COLORS = {
"Reel": "#FF6B6B",
"Carousel": "#FFD93D",
"Story": "#6BCB77",
"Static Post": "#4D96FF",
"Collab": "#C77DFF",
"Live": "#FF9F1C",
};
const STATUS_COLORS = {
"Idea": "#666",
"Draft": "#FF9F1C",
"In Review": "#4D96FF",
"Scheduled": "#C77DFF",
"Posted": "#6BCB77",
};
const PILLAR_COLORS = {
"Education": "#4D96FF",
"Entertainment": "#FF6B6B",
"Promotion": "#FFD93D",
"Community": "#6BCB77",
"Behind the Scenes": "#FF9F1C",
"User Generated": "#C77DFF",
};
function getToday() {
return new Date();
}
function getDaysInMonth(year, month) {
return new Date(year, month + 1, 0).getDate();
}
function getFirstDayOfMonth(year, month) {
return new Date(year, month, 1).getDay();
}
const initialPosts = [
{
id: 1,
title: "Morning Routine Reel",
caption: "Start your day right ✨ Here's my 5am morning routine...",
type: "Reel",
pillar: "Education",
status: "Scheduled",
date: "2026-05-05",
time: "08:00",
hashtags: "#morningroutine #wellness #selfcare",
notes: "Record b-roll of coffee & journal",
engagementGoal: "500 likes",
},
{
id: 2,
title: "Product Launch Carousel",
caption: "Swipe to see what's dropping this week 👀",
type: "Carousel",
pillar: "Promotion",
status: "Draft",
date: "2026-05-08",
time: "12:00",
hashtags: "#newproduct #launch #shopnow",
notes: "Need final images from designer",
engagementGoal: "200 saves",
},
{
id: 3,
title: "Behind the Scenes Story",
caption: "Ever wonder what goes into making content?",
type: "Story",
pillar: "Behind the Scenes",
status: "Idea",
date: "2026-05-12",
time: "18:00",
hashtags: "#bts #contentcreator",
notes: "",
engagementGoal: "100 replies",
},
];
function PostModal({ post, onClose, onSave, onDelete, mode }) {
const [form, setForm] = useState(post || {
title: "", caption: "", type: "Reel", pillar: "Education",
status: "Idea", date: "", time: "12:00", hashtags: "", notes: "", engagementGoal: ""
});
const update = (k, v) => setForm(f => ({ ...f, [k]: v }));
return (
{/* Modal Header */}
{mode === "new" ? "✦ New Post" : "✦ Edit Post"}
{/* Title */}
update("title", e.target.value)}
placeholder="e.g. Morning Routine Reel"
style={inputStyle} />
{/* Type + Pillar */}
{/* Date + Time + Status */}
{/* Caption */}
{/* Hashtags */}
update("hashtags", e.target.value)}
placeholder="#content #instagram #creator"
style={inputStyle} />
{/* Engagement Goal */}
update("engagementGoal", e.target.value)}
placeholder="e.g. 500 likes, 200 saves"
style={inputStyle} />
{/* Notes */}
{/* Actions */}
{mode === "edit" && (
)}
);
}
const labelStyle = {
display: "block", marginBottom: "6px", fontSize: "11px", letterSpacing: "0.1em",
textTransform: "uppercase", color: "#666", fontFamily: "monospace"
};
const inputStyle = {
width: "100%", background: "#1a1a1a", border: "1px solid #2a2a2a", borderRadius: "10px",
color: "#fff", padding: "10px 14px", fontSize: "14px", outline: "none",
boxSizing: "border-box", fontFamily: "inherit",
transition: "border-color 0.2s"
};
const btnStyle = {
padding: "10px 22px", borderRadius: "10px", fontSize: "13px",
cursor: "pointer", fontFamily: "inherit", fontWeight: "600", letterSpacing: "0.03em"
};
function PostCard({ post, onClick }) {
const typeColor = TYPE_COLORS[post.type] || "#888";
const statusColor = STATUS_COLORS[post.status] || "#888";
return (
onClick(post)} style={{
background: "#111", border: "1px solid #1e1e1e", borderRadius: "14px",
padding: "16px", cursor: "pointer", transition: "all 0.2s",
borderLeft: `3px solid ${typeColor}`,
marginBottom: "10px",
}}
onMouseEnter={e => { e.currentTarget.style.borderColor = typeColor; e.currentTarget.style.background = "#161616"; }}
onMouseLeave={e => { e.currentTarget.style.borderColor = "#1e1e1e"; e.currentTarget.style.borderLeftColor = typeColor; e.currentTarget.style.background = "#111"; }}
>
{post.title || "Untitled Post"}
{post.status}
{post.type}
{post.pillar && (
{post.pillar}
)}
{post.date && 📅 {post.date}}
{post.time && ⏰ {post.time}}
{post.caption && (
{post.caption}
)}
);
}
export default function InstagramPlanner() {
const [posts, setPosts] = useState(initialPosts);
const [view, setView] = useState("calendar"); // "calendar" | "list" | "analytics"
const [modal, setModal] = useState(null); // null | { mode: "new"|"edit", post }
const [filterType, setFilterType] = useState("All");
const [filterStatus, setFilterStatus] = useState("All");
const [calDate, setCalDate] = useState(getToday());
const [selectedDay, setSelectedDay] = useState(null);
const year = calDate.getFullYear();
const month = calDate.getMonth();
const daysInMonth = getDaysInMonth(year, month);
const firstDay = getFirstDayOfMonth(year, month);
const savePost = (form) => {
if (modal.mode === "new") {
setPosts(p => [...p, { ...form, id: Date.now() }]);
} else {
setPosts(p => p.map(x => x.id === form.id ? form : x));
}
setModal(null);
};
const deletePost = (id) => {
setPosts(p => p.filter(x => x.id !== id));
setModal(null);
};
const openNew = (date = "") => setModal({ mode: "new", post: { date, time: "12:00", type: "Reel", pillar: "Education", status: "Idea", title: "", caption: "", hashtags: "", notes: "", engagementGoal: "" } });
const openEdit = (post) => setModal({ mode: "edit", post });
const filteredPosts = posts.filter(p => {
const typeOk = filterType === "All" || p.type === filterType;
const statusOk = filterStatus === "All" || p.status === filterStatus;
return typeOk && statusOk;
}).sort((a, b) => (a.date + a.time).localeCompare(b.date + b.time));
const getPostsForDay = (d) => {
const dateStr = `${year}-${String(month + 1).padStart(2, "0")}-${String(d).padStart(2, "0")}`;
return posts.filter(p => p.date === dateStr);
};
// Analytics
const totalPosts = posts.length;
const postedCount = posts.filter(p => p.status === "Posted").length;
const scheduledCount = posts.filter(p => p.status === "Scheduled").length;
const typeCounts = CONTENT_TYPES.map(t => ({ type: t, count: posts.filter(p => p.type === t).length }));
const pillarCounts = PILLARS.map(pi => ({ pillar: pi, count: posts.filter(p => p.pillar === pi).length }));
return (
{/* Ambient BG */}
{/* Header */}
Content Studio
INSTAGRAM PLANNER — {totalPosts} posts planned
{/* Nav Tabs */}
{["calendar", "list", "analytics"].map(v => (
))}
{/* CALENDAR VIEW */}
{view === "calendar" && (
{/* Month nav */}
{MONTHS[month]} {year}
{/* Day headers */}
{/* Calendar cells */}
{Array.from({ length: firstDay }).map((_, i) =>
)}
{Array.from({ length: daysInMonth }).map((_, i) => {
const d = i + 1;
const dayPosts = getPostsForDay(d);
const isToday = getToday().getDate() === d && getToday().getMonth() === month && getToday().getFullYear() === year;
const isSelected = selectedDay === d;
return (
setSelectedDay(isSelected ? null : d)}
style={{
minHeight: "70px", background: isSelected ? "#1a1a1a" : "#0e0e0e",
border: isToday ? "1px solid #FF6B6B" : "1px solid #1a1a1a",
borderRadius: "10px", padding: "6px", cursor: "pointer",
transition: "all 0.15s",
position: "relative"
}}
onMouseEnter={e => e.currentTarget.style.background = "#161616"}
onMouseLeave={e => e.currentTarget.style.background = isSelected ? "#1a1a1a" : "#0e0e0e"}
>
{d}
{dayPosts.slice(0, 3).map(p => (
{ e.stopPropagation(); openEdit(p); }} style={{
background: (TYPE_COLORS[p.type] || "#888") + "28",
borderLeft: `2px solid ${TYPE_COLORS[p.type] || "#888"}`,
borderRadius: "4px", padding: "2px 5px", marginBottom: "2px",
fontSize: "10px", color: TYPE_COLORS[p.type] || "#aaa",
overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap"
}}>{p.title || p.type}
))}
{dayPosts.length > 3 && (
+{dayPosts.length - 3} more
)}
);
})}
{/* Day Panel */}
{selectedDay ? (
<>
{MONTHS[month]} {selectedDay}
{getPostsForDay(selectedDay).length === 0 ? (
No posts scheduled
) : (
getPostsForDay(selectedDay).map(p =>
)
)}
>
) : (
Select a day to view
or add posts
)}
)}
{/* LIST VIEW */}
{view === "list" && (
{/* Filters */}
{filteredPosts.length} post{filteredPosts.length !== 1 ? "s" : ""}
{filteredPosts.length === 0 ? (
) : (
{filteredPosts.map(p =>
)}
)}
)}
{/* ANALYTICS VIEW */}
{view === "analytics" && (
{/* KPI Row */}
{[
{ label: "Total Posts", value: totalPosts, color: "#fff" },
{ label: "Posted", value: postedCount, color: "#6BCB77" },
{ label: "Scheduled", value: scheduledCount, color: "#C77DFF" },
{ label: "In Draft", value: posts.filter(p => p.status === "Draft").length, color: "#FF9F1C" },
].map(k => (
))}
{/* Content Types */}
Content Mix
{typeCounts.map(({ type, count }) => (
{type}
{count}
0 ? `${(count / totalPosts) * 100}%` : "0%",
height: "100%", background: TYPE_COLORS[type], borderRadius: "4px",
transition: "width 0.6s"
}} />
))}
{/* Content Pillars */}
Content Pillars
{pillarCounts.map(({ pillar, count }) => (
{pillar}
{count}
0 ? `${(count / totalPosts) * 100}%` : "0%",
height: "100%", background: PILLAR_COLORS[pillar] || "#888", borderRadius: "4px",
transition: "width 0.6s"
}} />
))}
{/* Upcoming */}
All Posts Timeline
{posts.sort((a, b) => (a.date + a.time).localeCompare(b.date + b.time)).map(p => (
openEdit(p)} style={{
display: "flex", alignItems: "center", gap: "16px", padding: "12px 0",
borderBottom: "1px solid #111", cursor: "pointer"
}}>
{p.title || "Untitled"}
{p.date} • {p.time}
{p.status}
))}
)}
{/* Modal */}
{modal && (
setModal(null)}
onSave={savePost}
onDelete={deletePost}
/>
)}
{/* Google Fonts */}
);
}
const navBtn = {
background: "#111", border: "1px solid #1e1e1e", borderRadius: "8px",
color: "#888", padding: "8px 14px", cursor: "pointer", fontSize: "16px"
};