File size: 4,604 Bytes
98b952a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
"use client";

import { AnimatePresence, motion } from "framer-motion";
import {
  Line,
  LineChart,
  ReferenceLine,
  ResponsiveContainer,
  Tooltip,
  XAxis,
  YAxis,
} from "recharts";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { RewardDeltaBadge } from "@/components/RewardDeltaBadge";
import { RewardBars } from "@/components/RewardBars";
import { ScriptPanel } from "@/components/ScriptPanel";
import { ArbitratorReasoning } from "@/components/ArbitratorReasoning";

export interface EpisodeSnapshot {
  episode: number;
  script: string;
  reasoning: string[];
  rewards: {
    r1: number; r2: number; r3: number; r4: number; r5: number;
    r6: number; r7: number; r8: number; r9: number; r10: number;
    process: number; total: number;
  };
}

interface Props {
  episodes: EpisodeSnapshot[];
  current: number;
  historySeries: { episode: number; total: number }[];
}

export function LearningTimeline({ episodes, current, historySeries }: Props) {
  const snap = episodes[current];
  const prev = current > 0 ? episodes[current - 1] : null;
  const delta = prev ? snap.rewards.total - prev.rewards.total : 0;
  const improved = delta > 0.01;

  return (
    <div className="grid gap-5 lg:grid-cols-3">
      {/* LEFT — Script */}
      <div>
        <AnimatePresence mode="wait">
          <motion.div
            key={current}
            initial={{ opacity: 0, x: -10 }}
            animate={{ opacity: 1, x: 0 }}
            exit={{ opacity: 0, x: 10 }}
            transition={{ duration: 0.35, ease: "easeInOut" }}
          >
            <ScriptPanel
              script={snap.script}
              meta={{ platform: "Reels", region: "India", niche: "Creator productivity" }}
            />
          </motion.div>
        </AnimatePresence>
      </div>

      {/* CENTER — Reasoning */}
      <div>
        <AnimatePresence mode="wait">
          <motion.div
            key={current}
            initial={{ opacity: 0, y: 8 }}
            animate={{ opacity: 1, y: 0 }}
            exit={{ opacity: 0, y: -8 }}
            transition={{ duration: 0.4, ease: "easeInOut" }}
            className={improved ? "ring-2 ring-emerald-500/50 rounded-2xl" : ""}
          >
            <ArbitratorReasoning before={snap.reasoning} after={snap.reasoning} />
          </motion.div>
        </AnimatePresence>
      </div>

      {/* RIGHT — Rewards */}
      <div className="space-y-3">
        <AnimatePresence mode="wait">
          <motion.div
            key={current}
            initial={{ opacity: 0, x: 10 }}
            animate={{ opacity: 1, x: 0 }}
            exit={{ opacity: 0, x: -10 }}
            transition={{ duration: 0.35, ease: "easeInOut" }}
          >
            <RewardBars data={snap.rewards} title="Reward Components (R1–R10)" />
          </motion.div>
        </AnimatePresence>

        <Card>
          <CardContent className="p-4 flex items-center justify-between">
            <div>
              <p className="text-xs text-purple-400/70">Total Reward</p>
              <p className="text-2xl font-bold text-violet-400 tabular-nums">
                {snap.rewards.total.toFixed(3)}
              </p>
            </div>
            {prev && (
              <RewardDeltaBadge
                delta={(snap.rewards.total - prev.rewards.total) / prev.rewards.total}
              />
            )}
          </CardContent>
        </Card>

        {/* Progress chart */}
        <Card>
          <CardHeader className="pb-1">
            <CardTitle className="text-sm text-white">Reward Over Episodes</CardTitle>
          </CardHeader>
          <CardContent className="h-36 px-2 pb-3">
            <ResponsiveContainer width="100%" height="100%">
              <LineChart data={historySeries.slice(0, current + 1)}>
                <XAxis dataKey="episode" tick={{ fontSize: 10, fill: "#a78bfa" }} />
                <YAxis domain={[0, 1]} tick={{ fontSize: 10, fill: "#a78bfa" }} />
                <Tooltip contentStyle={{ background: "#120f1e", border: "1px solid #2e2255", borderRadius: "0.5rem", color: "#ede9f8" }} />
                <ReferenceLine y={historySeries[0]?.total} stroke="#4b3a7a" strokeDasharray="4 2" />
                <Line
                  type="monotone"
                  dataKey="total"
                  stroke="#8b5cf6"
                  strokeWidth={2}
                  dot={false}
                  isAnimationActive
                />
              </LineChart>
            </ResponsiveContainer>
          </CardContent>
        </Card>
      </div>
    </div>
  );
}