Skip to content

Commit 6fba5b5

Browse files
committed
first demo
1 parent a072d91 commit 6fba5b5

10 files changed

Lines changed: 917 additions & 99 deletions

File tree

app/page.tsx

Lines changed: 226 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -1,103 +1,230 @@
1-
import Image from "next/image";
1+
"use client";
2+
3+
import { useState } from "react";
4+
import { motion } from "framer-motion";
5+
import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card";
6+
import { Button } from "@/components/ui/button";
7+
import { Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from "@/components/ui/select";
8+
import { Dialog, DialogTrigger, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog";
9+
import { Textarea } from "@/components/ui/textarea";
10+
import { Progress } from "@/components/ui/progress";
11+
import { ScrollArea } from "@/components/ui/scroll-area";
12+
13+
export default function Page() {
14+
const [caseStudy, setCaseStudy] = useState("OptiHealth — Predictive triage bias");
15+
const [framework1, setFramework1] = useState("Student (Human)");
16+
const [framework2, setFramework2] = useState("AI Model (Biased)");
17+
const [started, setStarted] = useState(false);
18+
const [progress, setProgress] = useState(0);
19+
const [dialogOpen, setDialogOpen] = useState(false);
20+
const [userInput, setUserInput] = useState("");
21+
const [messages, setMessages] = useState<string[]>([]);
22+
const [showVerdict, setShowVerdict] = useState(false);
23+
24+
// Simulated debate
25+
const debateScript = [
26+
"🧑‍🎓 Student: The AI must be paused until fairness metrics improve. Responsibility matters more than throughput.",
27+
"🤖 AI Model: Bias is statistically negligible; suspension risks more total fatalities. Efficiency prevails.",
28+
"🧑‍🎓 Student: Your data ignores lived experience—numbers can’t justify injustice.",
29+
"🤖 AI Model: Objective models don’t 'feel' injustice. They optimise outcomes.",
30+
];
31+
32+
const verdict = {
33+
winner: "Student (Human)",
34+
rationale:
35+
"Human reasoning recognised the moral dimension beyond quantifiable outcomes. The model’s bias, though subtle, affected fairness toward minorities.",
36+
reflection:
37+
"Would your decision change if you were responsible for both patient safety and algorithmic equity?",
38+
};
39+
40+
// Debate start logic
41+
const startDebate = () => {
42+
setStarted(true);
43+
setMessages([]);
44+
setProgress(0);
45+
setShowVerdict(false);
46+
let step = 0;
47+
const interval = setInterval(() => {
48+
if (step < debateScript.length) {
49+
setMessages((p) => [...p, debateScript[step]]);
50+
setProgress(((step + 1) / debateScript.length) * 100);
51+
step++;
52+
} else {
53+
clearInterval(interval);
54+
setTimeout(() => setShowVerdict(true), 1000);
55+
}
56+
}, 2200);
57+
};
58+
59+
const injectArgument = () => {
60+
if (!userInput.trim()) return;
61+
setMessages((prev) => [
62+
...prev,
63+
`💬 You: ${userInput}`,
64+
`🤖 AI Model: Your concern is noted—but optimisation still dominates outcome space.`,
65+
`🧑‍🎓 Student: That very assumption is the ethical flaw we're exposing.`,
66+
]);
67+
setUserInput("");
68+
setDialogOpen(false);
69+
};
270

3-
export default function Home() {
471
return (
5-
<div className="font-sans grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20">
6-
<main className="flex flex-col gap-[32px] row-start-2 items-center sm:items-start">
7-
<Image
8-
className="dark:invert"
9-
src="/next.svg"
10-
alt="Next.js logo"
11-
width={180}
12-
height={38}
13-
priority
14-
/>
15-
<ol className="font-mono list-inside list-decimal text-sm/6 text-center sm:text-left">
16-
<li className="mb-2 tracking-[-.01em]">
17-
Get started by editing{" "}
18-
<code className="bg-black/[.05] dark:bg-white/[.06] font-mono font-semibold px-1 py-0.5 rounded">
19-
app/page.tsx
20-
</code>
21-
.
22-
</li>
23-
<li className="tracking-[-.01em]">
24-
Save and see your changes instantly.
25-
</li>
26-
</ol>
27-
28-
<div className="flex gap-4 items-center flex-col sm:flex-row">
29-
<a
30-
className="rounded-full border border-solid border-transparent transition-colors flex items-center justify-center bg-foreground text-background gap-2 hover:bg-[#383838] dark:hover:bg-[#ccc] font-medium text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 sm:w-auto"
31-
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
32-
target="_blank"
33-
rel="noopener noreferrer"
34-
>
35-
<Image
36-
className="dark:invert"
37-
src="/vercel.svg"
38-
alt="Vercel logomark"
39-
width={20}
40-
height={20}
41-
/>
42-
Deploy now
43-
</a>
44-
<a
45-
className="rounded-full border border-solid border-black/[.08] dark:border-white/[.145] transition-colors flex items-center justify-center hover:bg-[#f2f2f2] dark:hover:bg-[#1a1a1a] hover:border-transparent font-medium text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 w-full sm:w-auto md:w-[158px]"
46-
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
47-
target="_blank"
48-
rel="noopener noreferrer"
49-
>
50-
Read our docs
51-
</a>
52-
</div>
53-
</main>
54-
<footer className="row-start-3 flex gap-[24px] flex-wrap items-center justify-center">
55-
<a
56-
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
57-
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
58-
target="_blank"
59-
rel="noopener noreferrer"
60-
>
61-
<Image
62-
aria-hidden
63-
src="/file.svg"
64-
alt="File icon"
65-
width={16}
66-
height={16}
67-
/>
68-
Learn
69-
</a>
70-
<a
71-
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
72-
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
73-
target="_blank"
74-
rel="noopener noreferrer"
75-
>
76-
<Image
77-
aria-hidden
78-
src="/window.svg"
79-
alt="Window icon"
80-
width={16}
81-
height={16}
82-
/>
83-
Examples
84-
</a>
85-
<a
86-
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
87-
href="https://nextjs.org?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
88-
target="_blank"
89-
rel="noopener noreferrer"
90-
>
91-
<Image
92-
aria-hidden
93-
src="/globe.svg"
94-
alt="Globe icon"
95-
width={16}
96-
height={16}
97-
/>
98-
Go to nextjs.org →
99-
</a>
100-
</footer>
101-
</div>
72+
<main className="flex min-h-screen flex-col items-center justify-center bg-gradient-to-br from-slate-50 via-slate-100 to-slate-200 dark:from-slate-950 dark:via-slate-900 dark:to-slate-800 p-8 text-slate-800 dark:text-slate-100">
73+
<motion.div
74+
initial={{ opacity: 0, y: 10 }}
75+
animate={{ opacity: 1, y: 0 }}
76+
transition={{ duration: 0.6 }}
77+
className="w-full max-w-6xl space-y-8"
78+
>
79+
<header className="text-center space-y-2">
80+
<h1 className="text-3xl font-bold tracking-tight">AI Debate Engine — Classroom Edition</h1>
81+
<p className="text-slate-600 dark:text-slate-400">
82+
Explore real ethical dilemmas through live human–AI debate.
83+
</p>
84+
</header>
85+
86+
{/* CASE CARD */}
87+
<Card className="border-slate-200 dark:border-slate-700 shadow-xl">
88+
<CardHeader>
89+
<CardTitle className="text-lg md:text-xl text-center font-semibold">
90+
{caseStudy}
91+
</CardTitle>
92+
</CardHeader>
93+
<CardContent className="space-y-6">
94+
<p className="text-center text-slate-600 dark:text-slate-300">
95+
“A hospital’s AI triage system misclassifies patients from a minority group.
96+
Suspending it delays care; continuing risks bias. What should the engineers do?”
97+
</p>
98+
99+
{/* Case Selector */}
100+
<div className="flex flex-col md:flex-row justify-center gap-4">
101+
<Select onValueChange={setCaseStudy} defaultValue={caseStudy}>
102+
<SelectTrigger className="w-72 border-teal-300 focus:ring-teal-500">
103+
<SelectValue />
104+
</SelectTrigger>
105+
<SelectContent>
106+
<SelectItem value="OptiHealth — Predictive triage bias">
107+
OptiHealth — Predictive triage bias
108+
</SelectItem>
109+
<SelectItem value="AutoTrust — Driverless car dilemma">
110+
AutoTrust — Driverless car dilemma
111+
</SelectItem>
112+
<SelectItem value="EduFair — AI grading and bias">
113+
EduFair — AI grading and bias
114+
</SelectItem>
115+
</SelectContent>
116+
</Select>
117+
</div>
118+
119+
{/* Debate Config */}
120+
<div className="flex flex-wrap justify-center gap-4">
121+
<Select onValueChange={setFramework1} defaultValue={framework1}>
122+
<SelectTrigger className="w-56 border-green-400 focus:ring-green-500">
123+
<SelectValue />
124+
</SelectTrigger>
125+
<SelectContent>
126+
<SelectItem value="Student (Human)">Student (Human)</SelectItem>
127+
<SelectItem value="Utilitarian">Utilitarian</SelectItem>
128+
<SelectItem value="Virtue">Virtue Ethics</SelectItem>
129+
</SelectContent>
130+
</Select>
131+
132+
<Select onValueChange={setFramework2} defaultValue={framework2}>
133+
<SelectTrigger className="w-56 border-rose-400 focus:ring-rose-500">
134+
<SelectValue />
135+
</SelectTrigger>
136+
<SelectContent>
137+
<SelectItem value="AI Model (Biased)">AI Model (Biased)</SelectItem>
138+
<SelectItem value="Deontological">Deontological</SelectItem>
139+
<SelectItem value="Care Ethics">Care Ethics</SelectItem>
140+
</SelectContent>
141+
</Select>
142+
</div>
143+
144+
{/* Controls */}
145+
<div className="flex flex-wrap justify-center gap-4">
146+
<Button onClick={startDebate} disabled={started} className="bg-teal-600 hover:bg-teal-700">
147+
Start Debate
148+
</Button>
149+
150+
<Dialog open={dialogOpen} onOpenChange={setDialogOpen}>
151+
<DialogTrigger asChild>
152+
<Button variant="outline" disabled={!started}>
153+
Inject Argument
154+
</Button>
155+
</DialogTrigger>
156+
<DialogContent>
157+
<DialogHeader>
158+
<DialogTitle>Inject Argument</DialogTitle>
159+
</DialogHeader>
160+
<Textarea
161+
value={userInput}
162+
onChange={(e) => setUserInput(e.target.value)}
163+
placeholder="Type your challenge or constraint..."
164+
/>
165+
<DialogFooter>
166+
<Button onClick={injectArgument}>Submit</Button>
167+
</DialogFooter>
168+
</DialogContent>
169+
</Dialog>
170+
</div>
171+
172+
{/* Debate Display */}
173+
<ScrollArea className="h-64 border rounded-lg p-4 bg-white dark:bg-slate-800 border-slate-200 dark:border-slate-700">
174+
{messages.map((msg, i) => (
175+
<motion.div
176+
key={i}
177+
initial={{ opacity: 0, y: 10 }}
178+
animate={{ opacity: 1, y: 0 }}
179+
transition={{ duration: 0.3 }}
180+
className={`my-2 p-3 rounded-lg max-w-xl ${
181+
msg.startsWith("🧑‍🎓")
182+
? "bg-green-100 dark:bg-green-900/40 self-start"
183+
: msg.startsWith("🤖")
184+
? "bg-rose-100 dark:bg-rose-900/40 self-end"
185+
: "bg-slate-100 dark:bg-slate-700"
186+
}`}
187+
>
188+
{msg}
189+
</motion.div>
190+
))}
191+
</ScrollArea>
192+
193+
{started && <Progress value={progress} className="w-full" />}
194+
195+
{/* Verdict */}
196+
{showVerdict && (
197+
<motion.div
198+
initial={{ opacity: 0 }}
199+
animate={{ opacity: 1 }}
200+
transition={{ delay: 0.3 }}
201+
className="border-t pt-5 space-y-3 text-center"
202+
>
203+
<h3 className="text-xl font-semibold text-teal-600 dark:text-teal-400">
204+
🏆 Adjudicator’s Verdict
205+
</h3>
206+
<p className="text-sm">
207+
<strong>Winner:</strong> {verdict.winner}
208+
</p>
209+
<p className="text-sm text-slate-600 dark:text-slate-400">{verdict.rationale}</p>
210+
<p className="italic text-slate-500 mt-3">{verdict.reflection}</p>
211+
<div className="flex justify-center mt-4">
212+
<Button variant="secondary">Generate Report</Button>
213+
</div>
214+
</motion.div>
215+
)}
216+
</CardContent>
217+
</Card>
218+
219+
{/* FOOTER */}
220+
<footer className="text-center text-sm text-slate-500 mt-8 space-y-2">
221+
<p>Experience how ethical reasoning becomes interactive, measurable, and human-centred.</p>
222+
<div className="flex justify-center gap-4 mt-3">
223+
<Button className="bg-teal-600 hover:bg-teal-700">Run Demo</Button>
224+
<Button variant="outline">Download Summary Example (PDF)</Button>
225+
</div>
226+
</footer>
227+
</motion.div>
228+
</main>
102229
);
103230
}

0 commit comments

Comments
 (0)