"use client"; import { useState, useEffect, useCallback } from "react"; import Card from "@/components/ui/Card"; const today = () => new Date().toISOString().split("T")[0]; interface MarketUpdate { btc: string; eth: string; sol: string; btcChange: string; ethChange: string; solChange: string; } interface CompletedTask { task: string; completed: boolean; } interface ProjectProgress { project: string; progress: number; } interface CouncilFeedback { horus: string; amun: string; [key: string]: string; } interface FormState { date: string; marketUpdate: MarketUpdate; completedTasks: CompletedTask[]; tomorrowPriorities: string[]; councilFeedback: CouncilFeedback; projectProgress: ProjectProgress[]; } const defaultProjects = ["SiteMente", "HolaCompi", "WandVoice"]; const defaultForm: FormState = { date: today(), marketUpdate: { btc: "", eth: "", sol: "", btcChange: "", ethChange: "", solChange: "" }, completedTasks: [{ task: "", completed: true }], tomorrowPriorities: ["", "", "", "", ""], councilFeedback: { horus: "", amun: "" }, projectProgress: defaultProjects.map((p) => ({ project: p, progress: 0 })), }; export default function EodBriefPage() { const [form, setForm] = useState(defaultForm); const [saving, setSaving] = useState(false); const [saved, setSaved] = useState(false); const [errors, setErrors] = useState>({}); const [loadingDate, setLoadingDate] = useState(false); const [extraAgents, setExtraAgents] = useState([]); const loadBriefForDate = useCallback(async (date: string) => { setLoadingDate(true); try { const res = await fetch(`/api/eod?date=${date}`); const data = await res.json(); if (data) { const mu = typeof data.marketUpdate === "string" ? JSON.parse(data.marketUpdate) : (data.marketUpdate || defaultForm.marketUpdate); const ct = typeof data.completedTasks === "string" ? JSON.parse(data.completedTasks) : (data.completedTasks || defaultForm.completedTasks); const tp = typeof data.tomorrowPriorities === "string" ? JSON.parse(data.tomorrowPriorities) : (data.tomorrowPriorities || defaultForm.tomorrowPriorities); const cf = typeof data.councilFeedback === "string" ? JSON.parse(data.councilFeedback) : (data.councilFeedback || defaultForm.councilFeedback); const pp = typeof data.projectProgress === "string" ? JSON.parse(data.projectProgress) : (data.projectProgress || defaultForm.projectProgress); setForm({ date: data.date, marketUpdate: mu, completedTasks: ct, tomorrowPriorities: tp, councilFeedback: cf, projectProgress: pp }); // Detect extra agents const extras = Object.keys(cf).filter((k) => k !== "horus" && k !== "amun"); setExtraAgents(extras); } else { setForm({ ...defaultForm, date }); setExtraAgents([]); } } catch { setForm({ ...defaultForm, date }); } finally { setLoadingDate(false); } }, []); useEffect(() => { loadBriefForDate(today()); }, [loadBriefForDate]); const validate = (): boolean => { const errs: Record = {}; if (!form.completedTasks.some((t) => t.task.trim())) errs.completedTasks = "At least one completed task is required"; if (!form.tomorrowPriorities.some((p) => p.trim())) errs.tomorrowPriorities = "At least one priority for tomorrow is required"; setErrors(errs); return Object.keys(errs).length === 0; }; const handleSave = async () => { if (!validate()) return; setSaving(true); try { const res = await fetch("/api/eod", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(form), }); if (!res.ok) { const err = await res.json(); setErrors({ submit: err.error || "Failed to save" }); } else { setSaved(true); setTimeout(() => setSaved(false), 3000); } } catch { setErrors({ submit: "Network error. Please try again." }); } finally { setSaving(false); } }; const updateTask = (index: number, field: keyof CompletedTask, value: string | boolean) => { setForm((prev) => { const tasks = [...prev.completedTasks]; tasks[index] = { ...tasks[index], [field]: value }; return { ...prev, completedTasks: tasks }; }); }; const addTask = () => { setForm((prev) => ({ ...prev, completedTasks: [...prev.completedTasks, { task: "", completed: true }] })); }; const removeTask = (index: number) => { setForm((prev) => ({ ...prev, completedTasks: prev.completedTasks.filter((_, i) => i !== index) })); }; const updatePriority = (index: number, value: string) => { setForm((prev) => { const arr = [...prev.tomorrowPriorities]; arr[index] = value; return { ...prev, tomorrowPriorities: arr }; }); }; const addPriority = () => { setForm((prev) => ({ ...prev, tomorrowPriorities: [...prev.tomorrowPriorities, ""] })); }; const removePriority = (index: number) => { setForm((prev) => ({ ...prev, tomorrowPriorities: prev.tomorrowPriorities.filter((_, i) => i !== index) })); }; const updateProgress = (index: number, value: number) => { setForm((prev) => { const pp = [...prev.projectProgress]; pp[index] = { ...pp[index], progress: value }; return { ...prev, projectProgress: pp }; }); }; const addProject = () => { setForm((prev) => ({ ...prev, projectProgress: [...prev.projectProgress, { project: "", progress: 0 }] })); }; const updateProjectName = (index: number, name: string) => { setForm((prev) => { const pp = [...prev.projectProgress]; pp[index] = { ...pp[index], project: name }; return { ...prev, projectProgress: pp }; }); }; const updateCouncil = (agent: string, value: string) => { setForm((prev) => ({ ...prev, councilFeedback: { ...prev.councilFeedback, [agent]: value } })); }; const addAgent = () => { const name = prompt("Agent name:"); if (name?.trim()) { setExtraAgents((prev) => [...prev, name.trim()]); setForm((prev) => ({ ...prev, councilFeedback: { ...prev.councilFeedback, [name.trim()]: "" } })); } }; const changeColor = (val: string) => { const n = parseFloat(val); if (isNaN(n)) return "text-slate-400"; return n >= 0 ? "text-emerald-400" : "text-red-400"; }; const progressColor = (p: number) => { if (p >= 80) return "bg-emerald-500"; if (p >= 50) return "bg-amber-500"; if (p >= 25) return "bg-orange-500"; return "bg-red-500"; }; return (
{/* Header */}

🌙 End-of-Day Brief

Horus + Amun daily debrief

{ setForm((prev) => ({ ...prev, date: e.target.value })); loadBriefForDate(e.target.value); }} className="bg-[#1a1d27] border border-[#2a2d3a] rounded-lg px-3 py-2 text-sm text-slate-300 focus:outline-none focus:border-blue-500/50" />
{errors.submit && (
{errors.submit}
)} {loadingDate && (
Loading brief for selected date…
)}
{/* Market Update */}
{(["btc", "eth", "sol"] as const).map((coin) => (
setForm((p) => ({ ...p, marketUpdate: { ...p.marketUpdate, [coin]: e.target.value } })) } placeholder="$0.00" className="w-full bg-[#0f1117] border border-[#2a2d3a] rounded-lg px-3 py-2 text-sm text-slate-200 focus:outline-none focus:border-blue-500/50 mb-2" /> setForm((p) => ({ ...p, marketUpdate: { ...p.marketUpdate, [`${coin}Change`]: e.target.value }, })) } placeholder="24h % (e.g. +2.5)" className={`w-full bg-[#0f1117] border border-[#2a2d3a] rounded-lg px-3 py-2 text-sm focus:outline-none focus:border-blue-500/50 ${changeColor(form.marketUpdate[`${coin}Change` as keyof MarketUpdate])}`} />
))}
{/* Completed Tasks */} {errors.completedTasks && (

{errors.completedTasks}

)}
{form.completedTasks.map((task, i) => (
updateTask(i, "task", e.target.value)} placeholder={`Task ${i + 1}`} className={`flex-1 bg-[#0f1117] border border-[#2a2d3a] rounded-lg px-3 py-2 text-sm focus:outline-none focus:border-emerald-500/50 ${ task.completed ? "text-slate-400 line-through" : "text-slate-200" }`} /> {form.completedTasks.length > 1 && ( )}
))}
{/* Tomorrow's Priorities */} {errors.tomorrowPriorities && (

{errors.tomorrowPriorities}

)}
{form.tomorrowPriorities.map((p, i) => (
{i + 1}. updatePriority(i, e.target.value)} placeholder={`Priority ${i + 1}`} className="flex-1 bg-[#0f1117] border border-[#2a2d3a] rounded-lg px-3 py-2 text-sm text-slate-200 focus:outline-none focus:border-amber-500/50" /> {form.tomorrowPriorities.length > 3 && ( )}
))} {form.tomorrowPriorities.length < 7 && ( )}
{/* Council Feedback */}
{(["horus", "amun", ...extraAgents] as string[]).map((agent) => (
updateCouncil(agent, e.target.value)} placeholder={`${agent.charAt(0).toUpperCase() + agent.slice(1)}'s one-sentence feedback`} className="w-full bg-[#0f1117] border border-[#2a2d3a] rounded-lg px-3 py-2 text-sm text-slate-200 focus:outline-none focus:border-purple-500/50" />
))}
{/* Project Progress */}
{form.projectProgress.map((proj, i) => (
updateProjectName(i, e.target.value)} placeholder="Project name" className="bg-transparent text-sm font-medium text-slate-300 focus:outline-none border-b border-transparent focus:border-blue-500/50 pb-0.5 w-40" />
{proj.progress}% updateProgress(i, Math.min(100, Math.max(0, parseInt(e.target.value) || 0)))} className="w-16 bg-[#0f1117] border border-[#2a2d3a] rounded px-2 py-1 text-xs text-slate-300 focus:outline-none focus:border-blue-500/50 text-center" />
))}
{/* Save Button */}
); }