"use client"; import { useState, useEffect, useCallback } from "react"; import Card from "@/components/ui/Card"; const today = () => new Date().toISOString().split("T")[0]; interface MarketData { btc: string; eth: string; sol: string; btcChange: string; ethChange: string; solChange: string; } interface SitementeStatus { serverUptime: string; demoPages: string; leadStatus: string; } interface WarmLead { name: string; business: string; note: string; } interface FormState { date: string; location: string; weather: string; marketData: MarketData; aiNewsHeadlines: string[]; skillsToLearn: string[]; euAiActStatus: "OK" | "Risk" | "Opportunity"; sitementeStatus: SitementeStatus; warmLeads: WarmLead[]; dayPriorities: string[]; skippedTasks: string[]; autoExecutionSummary: string; } const defaultForm: FormState = { date: today(), location: "Benalmádena", weather: "", marketData: { btc: "", eth: "", sol: "", btcChange: "", ethChange: "", solChange: "" }, aiNewsHeadlines: ["", "", "", "", ""], skillsToLearn: ["", "", ""], euAiActStatus: "OK", sitementeStatus: { serverUptime: "", demoPages: "", leadStatus: "" }, warmLeads: [ { name: "", business: "", note: "" }, { name: "", business: "", note: "" }, { name: "", business: "", note: "" }, ], dayPriorities: ["", "", "", "", ""], skippedTasks: [""], autoExecutionSummary: "", }; export default function MorningBriefPage() { 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 loadBriefForDate = useCallback(async (date: string) => { setLoadingDate(true); try { const res = await fetch(`/api/morning?date=${date}`); const data = await res.json(); if (data) { setForm({ date: data.date, location: data.location || "Benalmádena", weather: data.weather || "", marketData: typeof data.marketData === "string" ? JSON.parse(data.marketData) : (data.marketData || defaultForm.marketData), aiNewsHeadlines: typeof data.aiNewsHeadlines === "string" ? JSON.parse(data.aiNewsHeadlines) : (data.aiNewsHeadlines || defaultForm.aiNewsHeadlines), skillsToLearn: typeof data.skillsToLearn === "string" ? JSON.parse(data.skillsToLearn) : (data.skillsToLearn || defaultForm.skillsToLearn), euAiActStatus: data.euAiActStatus || "OK", sitementeStatus: typeof data.sitementeStatus === "string" ? JSON.parse(data.sitementeStatus) : (data.sitementeStatus || defaultForm.sitementeStatus), warmLeads: typeof data.warmLeads === "string" ? JSON.parse(data.warmLeads) : (data.warmLeads || defaultForm.warmLeads), dayPriorities: typeof data.dayPriorities === "string" ? JSON.parse(data.dayPriorities) : (data.dayPriorities || defaultForm.dayPriorities), skippedTasks: typeof data.skippedTasks === "string" ? JSON.parse(data.skippedTasks) : (data.skippedTasks || defaultForm.skippedTasks), autoExecutionSummary: data.autoExecutionSummary || "", }); } else { setForm({ ...defaultForm, date }); } } catch { setForm({ ...defaultForm, date }); } finally { setLoadingDate(false); } }, []); useEffect(() => { loadBriefForDate(today()); }, [loadBriefForDate]); const validate = (): boolean => { const errs: Record = {}; if (!form.location.trim()) errs.location = "Location is required"; if (!form.weather.trim()) errs.weather = "Weather is required"; if (!form.dayPriorities.some((p) => p.trim())) errs.dayPriorities = "At least one priority is required"; setErrors(errs); return Object.keys(errs).length === 0; }; const handleSave = async () => { if (!validate()) return; setSaving(true); try { const res = await fetch("/api/morning", { 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 updateArrayItem = (field: keyof FormState, index: number, value: string) => { setForm((prev) => { const arr = [...(prev[field] as string[])]; arr[index] = value; return { ...prev, [field]: arr }; }); }; const addArrayItem = (field: keyof FormState, defaultVal: string = "") => { setForm((prev) => ({ ...prev, [field]: [...(prev[field] as string[]), defaultVal] })); }; const removeArrayItem = (field: keyof FormState, index: number) => { setForm((prev) => { const arr = (prev[field] as string[]).filter((_, i) => i !== index); return { ...prev, [field]: arr }; }); }; const updateLead = (index: number, field: keyof WarmLead, value: string) => { setForm((prev) => { const leads = [...prev.warmLeads]; leads[index] = { ...leads[index], [field]: value }; return { ...prev, warmLeads: leads }; }); }; const changeColor = (val: string) => { const n = parseFloat(val); if (isNaN(n)) return "text-slate-400"; return n >= 0 ? "text-emerald-400" : "text-red-400"; }; return (
{/* Header */}

Morning Brief

Horus daily intelligence log

{ 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-amber-500/50" />
{errors.submit && (
{errors.submit}
)} {loadingDate && (
Loading brief for selected date…
)}
{/* Location & Weather */}
setForm((p) => ({ ...p, location: e.target.value }))} placeholder="Benalmádena" className={`w-full bg-[#0f1117] border ${errors.location ? "border-red-500/50" : "border-[#2a2d3a]"} rounded-lg px-3 py-2 text-sm text-slate-200 focus:outline-none focus:border-amber-500/50`} /> {errors.location &&

{errors.location}

}
setForm((p) => ({ ...p, weather: e.target.value }))} placeholder="e.g. 22°C, Sunny" className={`w-full bg-[#0f1117] border ${errors.weather ? "border-red-500/50" : "border-[#2a2d3a]"} rounded-lg px-3 py-2 text-sm text-slate-200 focus:outline-none focus:border-amber-500/50`} /> {errors.weather &&

{errors.weather}

}
{/* Market Prices */}
{(["btc", "eth", "sol"] as const).map((coin) => (
setForm((p) => ({ ...p, marketData: { ...p.marketData, [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, marketData: { ...p.marketData, [`${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.marketData[`${coin}Change` as keyof MarketData])}`} />
))}
{/* AI News Headlines */}
{form.aiNewsHeadlines.map((h, i) => (
{i + 1}. updateArrayItem("aiNewsHeadlines", i, e.target.value)} placeholder={`Headline ${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-purple-500/50" /> {form.aiNewsHeadlines.length > 3 && ( )}
))} {form.aiNewsHeadlines.length < 7 && ( )}
{/* Skills to Learn */}
{form.skillsToLearn.map((s, i) => (
{i + 1}. updateArrayItem("skillsToLearn", i, e.target.value)} placeholder={`Skill ${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-emerald-500/50" />
))}
{/* EU AI Act Status */}
{(["OK", "Risk", "Opportunity"] as const).map((status) => ( ))}
{/* SiteMente Status */}
setForm((p) => ({ ...p, sitementeStatus: { ...p.sitementeStatus, serverUptime: e.target.value } })) } placeholder="e.g. 99.9% — All systems operational" 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" />
setForm((p) => ({ ...p, sitementeStatus: { ...p.sitementeStatus, demoPages: e.target.value } })) } placeholder="e.g. 3 live, 1 in review" 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" />