const { useState, useEffect, useCallback, useRef } = React; const api = { get: (p) => fetch(p).then((r) => r.json()), post: (p, body) => fetch(p, { method: "POST", headers: { "Content-Type": "application/json" }, body: body ? JSON.stringify(body) : null, }).then((r) => r.json()), patch: (p, body) => fetch(p, { method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body), }).then((r) => r.json()), delete: (p) => fetch(p, { method: "DELETE" }).then((r) => r.json()), }; function fmtDate(iso) { if (!iso) return ""; const d = new Date(iso); return d.toLocaleDateString("en-GB", { day: "numeric", month: "short" }); } function titleCase(s) { return s ? s[0].toUpperCase() + s.slice(1).replace(/_/g, " ") : ""; } const TABS = [ { id: "ideas", label: "Ideas" }, { id: "edit", label: "Edit" }, { id: "review", label: "Review" }, { id: "carousels", label: "Carousels" }, { id: "journey", label: "Journey" }, { id: "longvideo", label: "Long video"}, { id: "calendar", label: "Calendar" }, ]; function subtitle(tab) { switch (tab) { case "ideas": return "Type a topic and angle — AI writes the script and hooks"; case "edit": return "Drop raw footage to edit, or run the pipeline on a filmed idea"; case "review": return "Edited videos waiting for your approval"; case "carousels": return "Topic in → research, slides, caption, render, schedule"; case "journey": return "Reflective image+text posts about your business journey — X, Threads, LinkedIn"; case "longvideo": return "Weekly long-form for YouTube + auto-announcement on X / Threads / LinkedIn"; case "calendar": return "Everything in the queue, by day. Filter by channel or format."; default: return ""; } } // ───────────────────────────────────────────────────────────────────────────── // App shell // ───────────────────────────────────────────────────────────────────────────── function App() { const [tab, setTab] = useState(localStorage.getItem("ce-tab") || "ideas"); const [reviewCount, setReviewCount] = useState(0); useEffect(() => { localStorage.setItem("ce-tab", tab); }, [tab]); const refreshCounts = useCallback(async () => { try { const data = await api.get("/api/review"); setReviewCount(Array.isArray(data) ? data.length : 0); } catch {} }, []); useEffect(() => { refreshCounts(); const t = setInterval(refreshCounts, 20000); return () => clearInterval(t); }, [refreshCounts]); return (
Type a topic above and hit Generate — your script will appear here in about 10 seconds.