Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 47 additions & 35 deletions dashboard/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,21 @@ const NODE_POS = {
cart:[215,72], payment:[215,135], shipping:[215,195]
};

// ─── Colours — clean light palette ──────────────────────────────────────────
// ─── Colours — professional monochrome palette ──────────────────────────────
const C = {
blue: "#2563EB",
indigo: "#4F46E5",
green: "#16A34A",
amber: "#D97706",
red: "#DC2626",
slate: "#475569",
sky: "#0EA5E9",
bg: "#F8FAFC",
blue: "#111111",
indigo: "#1F1F1F",
green: "#2B2B2B",
amber: "#3A3A3A",
red: "#000000",
slate: "#4A4A4A",
sky: "#262626",
bg: "#FAFAFA",
surface: "#FFFFFF",
border: "#E2E8F0",
text: "#1E293B",
text2: "#64748B",
text3: "#94A3B8",
border: "#E5E5E5",
text: "#111111",
text2: "#525252",
text3: "#737373",
};

// ─── Mock data ────────────────────────────────────────────────────────────────
Expand Down Expand Up @@ -72,12 +72,12 @@ const CMP_DATA = [
// ─── Helpers ──────────────────────────────────────────────────────────────────
const phaseBadge = (phase) => {
const map = {
Stable: {bg:"#DCFCE7",color:"#16A34A"},
Scaling: {bg:"#FEF3C7",color:"#D97706"},
Predicting:{bg:"#DBEAFE",color:"#2563EB"},
Error: {bg:"#FEE2E2",color:"#DC2626"},
Stable: {bg:"#F5F5F5",color:"#1F1F1F"},
Scaling: {bg:"#F0F0F0",color:"#2B2B2B"},
Predicting:{bg:"#EBEBEB",color:"#111111"},
Error: {bg:"#E5E5E5",color:"#000000"},
};
const s = map[phase] || {bg:"#F1F5F9",color:"#64748B"};
const s = map[phase] || {bg:"#F5F5F5",color:"#525252"};
return (
<span style={{
background:s.bg, color:s.color,
Expand All @@ -91,7 +91,7 @@ const ConfBar = ({v}) => {
const color = v>=.82 ? C.green : v>=.68 ? C.amber : C.red;
return (
<div style={{display:"flex",alignItems:"center",gap:6}}>
<div style={{width:56,height:5,background:"#E2E8F0",borderRadius:99,overflow:"hidden"}}>
<div style={{width:56,height:5,background:"#E5E5E5",borderRadius:99,overflow:"hidden"}}>
<div style={{width:`${v*100}%`,height:"100%",background:color,borderRadius:99,transition:"width .5s"}}/>
</div>
<span style={{fontSize:11,color,fontWeight:600,minWidth:34}}>{(v*100).toFixed(0)}%</span>
Expand Down Expand Up @@ -133,7 +133,7 @@ function CallGraph({chaos,graph}) {
const sp=NODE_POS[s], tp=NODE_POS[t];
const hot = chaos&&(s==="checkout"||t==="checkout");
return <line key={i} x1={sp[0]} y1={sp[1]} x2={tp[0]} y2={tp[1]}
stroke={hot?"#FCA5A5":"#CBD5E1"} strokeWidth={hot?2:1.5} strokeDasharray={hot?"5 3":"none"}/>;
stroke={hot?"#4A4A4A":"#D4D4D4"} strokeWidth={hot?2:1.5} strokeDasharray={hot?"5 3":"none"}/>;
})}
{SERVICES.map(svc=>{
const p=NODE_POS[svc]; if(!p) return null;
Expand All @@ -143,7 +143,7 @@ function CallGraph({chaos,graph}) {
return (
<g key={svc}>
<circle cx={p[0]} cy={p[1]} r={18}
fill={hot?"#FEF2F2":isFrontend?"#EFF6FF":"#F8FAFC"}
fill={hot?"#E5E5E5":isFrontend?"#F3F3F3":"#FAFAFA"}
stroke={hot?C.red:isFrontend?C.blue:C.slate}
strokeWidth={isFrontend?2:1.5}/>
<text x={p[0]} y={p[1]-3} textAnchor="middle" dominantBaseline="central"
Expand Down Expand Up @@ -179,7 +179,7 @@ export default function App() {
]);
const [graph, setGraph] = useState({nodes:[],edges:[]});
const [scaleCount,setScaleCount] = useState(0);
const [clock, setClock] = useState("");
const [clock, setClock] = useState(() => new Date().toLocaleTimeString("en",{hour12:false}));

useEffect(()=>{
const id = setInterval(()=>{
Expand Down Expand Up @@ -245,7 +245,7 @@ export default function App() {
}}>
<div style={{display:"flex",alignItems:"center",gap:12}}>
<div style={{
width:32,height:32,background:`linear-gradient(135deg,${C.blue},${C.indigo})`,
width:32,height:32,background:`linear-gradient(135deg,${C.text},${C.slate})`,
borderRadius:8,display:"flex",alignItems:"center",justifyContent:"center",
color:"white",fontWeight:700,fontSize:14
}}>P</div>
Expand All @@ -257,10 +257,16 @@ export default function App() {
<div style={{display:"flex",alignItems:"center",gap:10}}>
<span style={{fontSize:12,color:C.text2,marginRight:4}}>{clock}</span>

<button onClick={()=>setPhantom(p=>!p)} style={{
<button onClick={()=>{
setPhantom(p => {
const next = !p;
setMode(next ? "PHANTOM" : "HPA");
return next;
});
}} style={{
padding:"6px 14px", borderRadius:8, fontSize:12, fontWeight:600,
cursor:"pointer", border:`1.5px solid ${phantom?C.blue:C.border}`,
background:phantom?"#EFF6FF":C.surface, color:phantom?C.blue:C.text2,
background:phantom?"#F3F3F3":C.surface, color:phantom?C.blue:C.text2,
transition:"all .15s"
}}>{phantom?"◉ PHANTOM ON":"○ PHANTOM OFF"}</button>

Expand All @@ -274,11 +280,17 @@ export default function App() {
}} style={{
padding:"6px 14px", borderRadius:8, fontSize:12, fontWeight:600,
cursor:"pointer", border:`1.5px solid ${chaos?C.red:C.border}`,
background:chaos?"#FEF2F2":C.surface, color:chaos?C.red:C.text2,
background:chaos?"#EAEAEA":C.surface, color:chaos?C.red:C.text2,
transition:"all .15s"
}}>{chaos?"✕ CHAOS ACTIVE":"⚡ Inject Chaos"}</button>

<button onClick={()=>setMode(m=>m==="PHANTOM"?"HPA":m==="HPA"?"KEDA":"PHANTOM")} style={{
<button onClick={()=>{
setMode(m=>{
const next = m==="PHANTOM" ? "HPA" : m==="HPA" ? "KEDA" : "PHANTOM";
setPhantom(next === "PHANTOM");
return next;
});
}} style={{
padding:"6px 14px", borderRadius:8, fontSize:12, fontWeight:600,
cursor:"pointer", border:`1.5px solid ${C.border}`,
background:C.surface, color:C.amber, transition:"all .15s"
Expand Down Expand Up @@ -316,17 +328,17 @@ export default function App() {
<Tooltip {...TT}/>
<Legend wrapperStyle={{fontSize:11}}/>
<Line dataKey="predFrontend" stroke={C.blue} strokeWidth={2} strokeDasharray="6 3" dot={false} name="Pred: frontend"/>
<Line dataKey="actFrontend" stroke="#93C5FD" strokeWidth={1.5} dot={false} name="Actual: frontend"/>
<Line dataKey="actFrontend" stroke="#A3A3A3" strokeWidth={1.5} dot={false} name="Actual: frontend"/>
<Line dataKey="predCheckout" stroke={C.indigo} strokeWidth={2} strokeDasharray="6 3" dot={false} name="Pred: checkout"/>
<Line dataKey="actCheckout" stroke="#A5B4FC" strokeWidth={1.5} dot={false} name="Actual: checkout"/>
<Line dataKey="actCheckout" stroke="#D4D4D4" strokeWidth={1.5} dot={false} name="Actual: checkout"/>
</LineChart>
</ResponsiveContainer>
</Panel>

<Panel title="Live Service Call Graph" color={C.sky}>
{chaos && (
<div style={{
background:"#FEF2F2",border:`1px solid #FCA5A5`,borderRadius:8,
background:"#EAEAEA",border:`1px solid #A3A3A3`,borderRadius:8,
padding:"6px 12px",fontSize:11,color:C.red,fontWeight:500,
marginBottom:10
}}>⚠ Chaos active — pod kill injected on checkout</div>
Expand All @@ -348,8 +360,8 @@ export default function App() {
<YAxis {...TICK} allowDecimals={false}/>
<Tooltip {...TT}/>
<Legend wrapperStyle={{fontSize:10}}/>
<Area dataKey="hpa" stroke="#CBD5E1" fill="#F1F5F9" strokeWidth={1.5} name="HPA (reactive)" dot={false}/>
<Area dataKey="phantom" stroke={C.blue} fill="#DBEAFE" strokeWidth={2} name="PHANTOM (predictive)" dot={false} strokeDasharray="5 2"/>
<Area dataKey="hpa" stroke="#D4D4D4" fill="#F5F5F5" strokeWidth={1.5} name="HPA (reactive)" dot={false}/>
<Area dataKey="phantom" stroke={C.blue} fill="#EBEBEB" strokeWidth={2} name="PHANTOM (predictive)" dot={false} strokeDasharray="5 2"/>
</AreaChart>
</ResponsiveContainer>
</Panel>
Expand All @@ -363,7 +375,7 @@ export default function App() {
<Tooltip {...TT}/>
<ReferenceLine y={0.75} stroke={C.amber} strokeDasharray="4 3"
label={{value:"threshold",position:"insideTopRight",fontSize:9,fill:C.amber}}/>
<Area dataKey="v" stroke={C.green} fill="#DCFCE7" strokeWidth={2} name="Confidence" dot={false}/>
<Area dataKey="v" stroke={C.green} fill="#E5E5E5" strokeWidth={2} name="Confidence" dot={false}/>
</AreaChart>
</ResponsiveContainer>
</Panel>
Expand Down Expand Up @@ -428,8 +440,8 @@ export default function App() {
<ReferenceLine y={200} stroke={C.red} strokeDasharray="4 3"
label={{value:"SLO 200ms",position:"insideTopRight",fontSize:9,fill:C.red}}/>
<Bar dataKey="PHANTOM" fill={C.blue} radius={[4,4,0,0]} name="PHANTOM (ours)"/>
<Bar dataKey="HPA" fill="#CBD5E1" radius={[4,4,0,0]} name="HPA baseline"/>
<Bar dataKey="KEDA" fill="#E0E7FF" radius={[4,4,0,0]} name="KEDA baseline"/>
<Bar dataKey="HPA" fill="#D4D4D4" radius={[4,4,0,0]} name="HPA baseline"/>
<Bar dataKey="KEDA" fill="#A3A3A3" radius={[4,4,0,0]} name="KEDA baseline"/>
</BarChart>
</ResponsiveContainer>
</Panel>
Expand Down
Loading