const { useState, useEffect, useCallback } = React; // --- Design Tokens --- const C = { bg: "#08080f", bgCard: "#0d0d1a", bgHover: "#0f0f1e", bgInput: "#050508", border: "#1a1a28", borderLight: "#2a2a3a", text: "#ddd8cc", textDim: "#888", textMuted: "#7c7c8c", textFaint: "#555", accent: "#4a9eff", green: "#34d399", orange: "#f59e0b", red: "#e01e5a", purple: "#a78bfa", }; const font = { mono: "'DM Mono', 'Courier New', monospace", heading: "'Syne', sans-serif" }; // --- API --- let onAuthFail = () => {}; let onServerError = () => {}; async function handleResponse(r) { if (r.status === 401) { onAuthFail(); throw new Error("Not authenticated"); } const data = await r.json(); if (r.status === 500 && data.error_id) { onServerError(data); throw new Error(data.error); } return data; } const api = { get: (path) => fetch(`/api${path}`, { credentials: "same-origin" }).then(handleResponse), post: (path, body) => fetch(`/api${path}`, { method: "POST", credentials: "same-origin", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body), }).then(handleResponse), patch: (path, body) => fetch(`/api${path}`, { method: "PATCH", credentials: "same-origin", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body), }).then(handleResponse), del: (path) => fetch(`/api${path}`, { method: "DELETE", credentials: "same-origin", }).then(r => r.json()), }; // --- Global refs (set by App, used by deep components) --- let globalNav = () => {}; let globalEnvLookup = {}; // name -> id // --- Components --- function StatusBadge({ status }) { const colors = { open: C.orange, resolved: C.green, stale: C.textFaint }; const color = colors[status] || C.textDim; return ( {status} ); } function EnvBadge({ env, envId, clickable = true }) { if (!env) return null; const resolvedId = envId || globalEnvLookup[env]; const handleClick = (e) => { if (!clickable || !resolvedId) return; e.stopPropagation(); globalNav("env-show", resolvedId); }; return ( {env} ); } function StatTile({ label, value, color, onClick, delta }) { const len = String(value).length; const sz = len > 10 ? "0.85rem" : len > 4 ? "1rem" : "1.25rem"; const deltaNum = delta != null ? Number(delta) : null; const deltaStr = deltaNum != null && deltaNum !== 0 ? (deltaNum > 0 ? `+${deltaNum.toLocaleString()}` : deltaNum.toLocaleString()) : null; const deltaColor = deltaNum > 0 ? C.green : deltaNum < 0 ? C.red : C.textFaint; return (
{ if (onClick) e.currentTarget.style.borderColor = C.accent + "44"; }} onMouseLeave={e => { if (onClick) e.currentTarget.style.borderColor = C.border; }}>
{label}
{value}
{deltaStr &&
{deltaStr}
}
); } function Btn({ children, onClick, variant = "primary", disabled, style: extra }) { const styles = { primary: { background: C.accent, color: "#000" }, ghost: { background: "transparent", color: C.textDim, border: `1px solid ${C.borderLight}` }, danger: { background: C.red, color: "#fff" }, success: { background: C.green, color: "#000" }, }; return ( ); } function Input({ label, value, onChange, placeholder, type = "text", style: extra }) { return (
{label && } onChange(e.target.value)} placeholder={placeholder} style={{ background: C.bgInput, color: C.text, border: `1px solid ${C.border}`, borderRadius: "3px", padding: "0.5rem", fontFamily: font.mono, fontSize: "1rem", letterSpacing: "0.04em", outline: "none", width: "100%", boxSizing: "border-box", ...extra, }} />
); } function Select({ label, value, onChange, options, placeholder }) { return (
{label && }
); } // --- Pages --- function Dashboard({ user, investigations, environments, onNav }) { const [tab, setTab] = useState("investigations"); const open = investigations.filter(i => i.status === "open").length; const resolved = investigations.filter(i => i.status === "resolved").length; const recent = investigations.slice(0, 5); return (

Watson

StoreConnect Investigation Platform

{/* Dashboard tabs */}
{[{key: "investigations", label: "Investigations"}, {key: "environments", label: "Environments"}].map(t => ( setTab(t.key)} style={{ fontSize: "0.8rem", padding: "0.4rem 0.8rem" }}>{t.label} ))}
{tab === "investigations" && (<>
onNav("list")} /> onNav("list")} /> onNav("list")} /> setTab("environments")} />
onNav("new")}>New Investigation onNav("list")}>All Investigations
)} {tab === "environments" && (<>
{environments.length} environment(s) onNav("env-new")} style={{ fontSize: "0.75rem" }}>Add Environment
{environments.map(env => (
onNav("env-show", env.id)} style={{ background: C.bgCard, border: `1px solid ${C.border}`, borderRadius: "5px", padding: "0.7rem", cursor: "pointer", transition: "border-color 0.15s" }} onMouseEnter={e => e.currentTarget.style.borderColor = C.accent + "44"} onMouseLeave={e => e.currentTarget.style.borderColor = C.border}>
{env.name}
App: {env.rails_app || env.db_app} · DB: {env.db_app}
{env.org_id &&
Org: {env.org_id}
}
))}
)} {recent.length > 0 && (
Recent
{recent.map((inv) => (
onNav("show", inv.id)} style={{ padding: "0.7rem", cursor: "pointer", background: C.bgCard, border: `1px solid ${C.border}`, borderRadius: "5px", transition: "border-color 0.15s", }} onMouseEnter={e => e.currentTarget.style.borderColor = C.accent + "44"} onMouseLeave={e => e.currentTarget.style.borderColor = C.border} >
{timeAgo(inv.updated_at)}
{inv.title}
{inv.entity_type} {inv.entity_id?.slice(0, 8)} {inv.case_number && <>{" "}· {inv.case_number}}
))}
)}
); } function InvestigationList({ investigations, onNav }) { const [filter, setFilter] = useState("all"); const filtered = filter === "all" ? investigations : investigations.filter(i => i.status === filter); return (

Investigations

onNav("new")}>New
{["all", "open", "resolved", "stale"].map(s => ( setFilter(s)} style={{ fontSize: "0.75rem", padding: "0.3rem 0.6rem" }}> {s.charAt(0).toUpperCase() + s.slice(1)} ))}
{filtered.length === 0 && (
No investigations found.
)} {filtered.map((inv) => (
onNav("show", inv.id)} style={{ padding: "0.7rem", cursor: "pointer", background: C.bgCard, border: `1px solid ${C.border}`, borderRadius: "5px", transition: "border-color 0.15s", }} onMouseEnter={e => e.currentTarget.style.borderColor = C.accent + "44"} onMouseLeave={e => e.currentTarget.style.borderColor = C.border} >
{inv.case_number && {inv.case_number}}
{timeAgo(inv.updated_at)}
{inv.title}
{inv.entity_type} {inv.entity_id?.slice(0, 8)} {inv.user && <>{" "}· {inv.user.name}}
))}
); } function InvestigationShow({ id, onNav, environments }) { const [inv, setInv] = useState(null); const [loading, setLoading] = useState(true); const [editing, setEditing] = useState(false); const [editForm, setEditForm] = useState({}); const [chatMsg, setChatMsg] = useState(""); const [chatLoading, setChatLoading] = useState(false); const [toolPanel, setToolPanel] = useState(null); // "lookup"|"audit"|"timeline"|"shipments" const [toolForm, setToolForm] = useState({}); const [toolLoading, setToolLoading] = useState(false); const [connectCase, setConnectCase] = useState(false); const [caseInput, setCaseInput] = useState(""); const [connectLoading, setConnectLoading] = useState(false); const [bugForm, setBugForm] = useState(null); // null = hidden const [bugLoading, setBugLoading] = useState(false); const reload = () => api.get(`/investigations/${id}`).then(setInv); useEffect(() => { setLoading(true); reload().then(() => setLoading(false)); }, [id]); const saveEdit = async () => { await api.patch(`/investigations/${id}`, editForm); setEditing(false); reload(); }; const startEdit = () => { setEditForm({ status: inv.status, findings: inv.findings || "", resolution: inv.resolution || "", case_number: inv.case_number || "", case_url: inv.case_url || "", description: inv.description || "" }); setEditing(true); }; const [chatError, setChatError] = useState(null); const sendChat = async () => { if (!chatMsg.trim()) return; const msg = chatMsg; setChatMsg(""); setChatLoading(true); setChatError(null); try { const result = await api.post(`/investigations/${id}/chat_sync`, { message: msg }); if (result.error) { setChatError(result.error); } else { reload(); } } catch (e) { setChatError(e.message || "Failed to send message"); } setChatLoading(false); }; const runTool = async () => { setToolLoading(true); try { await api.post(`/investigations/${id}/run_tool`, { tool: toolPanel, tool_params: toolForm }); reload(); setToolPanel(null); setToolForm({}); } catch (e) { /* ignore */ } setToolLoading(false); }; const doConnectCase = async () => { if (!caseInput.trim()) return; setConnectLoading(true); try { const result = await api.post(`/investigations/${id}/connect_case`, { platform: "salesforce", case_number: caseInput }); if (result.errors) { alert(result.errors.join(", ")); } else { setInv(result); setConnectCase(false); setCaseInput(""); } } catch (e) { /* ignore */ } setConnectLoading(false); }; const logBug = async () => { if (!bugForm?.title?.trim()) return; setBugLoading(true); try { const result = await api.post(`/investigations/${id}/log_bug`, bugForm); if (result.error) { alert(result.error); } else { setBugForm(null); reload(); } } catch (e) { /* ignore */ } setBugLoading(false); }; if (loading) return
Loading...
; if (!inv) return
Not found
; const chatEntries = (inv.entries || []).filter(e => e.entry_type === "chat_message"); const otherEntries = (inv.entries || []).filter(e => e.entry_type !== "chat_message"); return (

{inv.title}

{inv.case_number && ( <>{inv.case_url ? {inv.case_number} : {inv.case_number} }{" "}·{" "} )} {inv.entity_type} {inv.entity_id} · by {inv.user?.name} · {timeAgo(inv.created_at)}

setEditing(false) : startEdit}> {editing ? "Cancel" : "Edit"} onNav("list")}>Back
{editing && (
setEditForm({...editForm, case_number: v})} placeholder="WEB-8502" /> setEditForm({...editForm, case_url: v})} placeholder="https://..." />