Requests / src /app /page.tsx
armand0e's picture
Optionally add name upon submission + update source models with Qwen3 2507 specifications
f15ff24
"use client";
import { useState, useEffect } from "react";
import { ArrowUp, Cpu, Database, Plus, Loader2, ChevronRight } from "lucide-react";
import Navbar from "@/components/Navbar";
import Footer from "@/components/Footer";
import { useRouter } from "next/navigation";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Badge } from "@/components/ui/badge";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { Combobox } from "@/components/ui/combobox";
import { toast } from "@/components/ui/toaster";
interface DistillationRequest {
id: string;
sourceDataset: string;
studentModel: string;
submitterName?: string;
additionalNotes: string;
upvotes: number;
createdAt: string;
status: "pending" | "in_progress" | "completed";
}
interface DatasetRequest {
id: string;
sourceModel: string;
submitterName?: string;
datasetSize: string;
reasoningDepth: string;
topics: string[];
additionalNotes: string;
upvotes: number;
createdAt: string;
status: "pending" | "in_progress" | "completed";
}
interface TeichAIDataset {
id: string;
name: string;
}
interface OpenRouterModel {
id: string;
name: string;
}
interface HuggingFaceModel {
id: string;
name: string;
}
const STUDENT_MODELS = [
"Qwen3-4B",
"Qwen3-4B-Thinking-2507",
"Qwen3-4B-Instruct-2507",
"Qwen3-8B",
"Qwen3-14B",
"Qwen3-30B-A3B-Thinking-2507",
"Qwen3-32B",
"Nemotron-Cascade-14B-Thinking",
"Nemotron-Cascade-8B-Thinking",
"Other",
];
const SOURCE_MODEL_OTHER_HF = "Other (HuggingFace)";
const REASONING_DEPTHS = ["low", "medium", "high"];
const DATASET_SIZES = ["100x", "250x", "500x", "1000x", "3000x", "11000x"];
const TOPICS = [
"Coding",
"Math",
"Science",
"Web Development",
"Data Science",
"Machine Learning",
"Creative Writing",
"Reasoning",
"Logic",
"General Knowledge",
];
export default function Home() {
const router = useRouter();
const [distillationRequests, setDistillationRequests] = useState<DistillationRequest[]>([]);
const [datasetRequests, setDatasetRequests] = useState<DatasetRequest[]>([]);
const [loading, setLoading] = useState(true);
const [submitting, setSubmitting] = useState(false);
const [showDistillForm, setShowDistillForm] = useState(false);
const [showDatasetForm, setShowDatasetForm] = useState(false);
// External data
const [teichaiDatasets, setTeichaiDatasets] = useState<TeichAIDataset[]>([]);
const [openrouterModels, setOpenrouterModels] = useState<OpenRouterModel[]>([]);
const [loadingDatasets, setLoadingDatasets] = useState(false);
const [loadingModels, setLoadingModels] = useState(false);
const [huggingfaceModels, setHuggingfaceModels] = useState<HuggingFaceModel[]>([]);
const [hfModelQuery, setHfModelQuery] = useState("");
const [loadingHfModels, setLoadingHfModels] = useState(false);
const [distillHuggingfaceModels, setDistillHuggingfaceModels] = useState<HuggingFaceModel[]>([]);
const [distillHfModelQuery, setDistillHfModelQuery] = useState("");
const [loadingDistillHfModels, setLoadingDistillHfModels] = useState(false);
// Distillation form state
const [sourceDataset, setSourceDataset] = useState("");
const [sourceDatasetOther, setSourceDatasetOther] = useState("");
const [studentModel, setStudentModel] = useState("");
const [studentModelOther, setStudentModelOther] = useState("");
const [distillSubmitterName, setDistillSubmitterName] = useState("");
const [distillNotes, setDistillNotes] = useState("");
// Dataset form state
const [sourceModel, setSourceModel] = useState("");
const [sourceModelOther, setSourceModelOther] = useState("");
const [datasetSubmitterName, setDatasetSubmitterName] = useState("");
const [datasetSize, setDatasetSize] = useState("250x");
const [reasoningDepth, setReasoningDepth] = useState("high");
const [selectedTopics, setSelectedTopics] = useState<string[]>([]);
const [datasetNotes, setDatasetNotes] = useState("");
useEffect(() => {
fetchRequests();
fetchTeichaiDatasets();
fetchOpenrouterModels();
}, []);
useEffect(() => {
let cancelled = false;
const q = hfModelQuery.trim();
const timer = setTimeout(async () => {
setLoadingHfModels(true);
try {
const res = await fetch(`/api/huggingface-models?q=${encodeURIComponent(q)}&limit=20`);
const data = await res.json();
if (!cancelled) {
setHuggingfaceModels(Array.isArray(data) ? data : []);
}
} catch (error) {
console.error("Error fetching Hugging Face models:", error);
if (!cancelled) {
setHuggingfaceModels([]);
}
} finally {
if (!cancelled) {
setLoadingHfModels(false);
}
}
}, 250);
return () => {
cancelled = true;
clearTimeout(timer);
};
}, [hfModelQuery]);
useEffect(() => {
let cancelled = false;
const q = distillHfModelQuery.trim();
const timer = setTimeout(async () => {
setLoadingDistillHfModels(true);
try {
const res = await fetch(`/api/huggingface-models?q=${encodeURIComponent(q)}&limit=20`);
const data = await res.json();
if (!cancelled) {
setDistillHuggingfaceModels(Array.isArray(data) ? data : []);
}
} catch (error) {
console.error("Error fetching Hugging Face models:", error);
if (!cancelled) {
setDistillHuggingfaceModels([]);
}
} finally {
if (!cancelled) {
setLoadingDistillHfModels(false);
}
}
}, 250);
return () => {
cancelled = true;
clearTimeout(timer);
};
}, [distillHfModelQuery]);
async function fetchRequests() {
try {
const [distillRes, datasetRes] = await Promise.all([
fetch("/api/distillation"),
fetch("/api/dataset"),
]);
const distillData = await distillRes.json();
const datasetData = await datasetRes.json();
setDistillationRequests(Array.isArray(distillData) ? distillData : []);
setDatasetRequests(Array.isArray(datasetData) ? datasetData : []);
} catch (error) {
console.error("Error fetching requests:", error);
} finally {
setLoading(false);
}
}
async function fetchTeichaiDatasets() {
setLoadingDatasets(true);
try {
const res = await fetch("/api/teichai-datasets");
const data = await res.json();
setTeichaiDatasets(Array.isArray(data) ? data : []);
} catch (error) {
console.error("Error fetching TeichAI datasets:", error);
} finally {
setLoadingDatasets(false);
}
}
async function fetchOpenrouterModels() {
setLoadingModels(true);
try {
const res = await fetch("/api/openrouter-models");
const data = await res.json();
setOpenrouterModels(Array.isArray(data) ? data : []);
} catch (error) {
console.error("Error fetching OpenRouter models:", error);
} finally {
setLoadingModels(false);
}
}
async function handleDistillSubmit(e: React.FormEvent) {
e.preventDefault();
const resolvedSourceDataset = sourceDataset === "Other" ? sourceDatasetOther.trim() : sourceDataset;
const resolvedStudentModel = studentModel === "Other" ? studentModelOther.trim() : studentModel;
const resolvedSubmitterName = distillSubmitterName.trim();
if (!resolvedSourceDataset || !resolvedStudentModel) {
toast({ title: "Error", description: "Please fill in required fields", variant: "destructive" });
return;
}
setSubmitting(true);
try {
const res = await fetch("/api/distillation", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
sourceDataset: resolvedSourceDataset,
studentModel: resolvedStudentModel,
submitterName: resolvedSubmitterName || undefined,
additionalNotes: distillNotes,
}),
});
if (res.ok) {
toast({ title: "Success", description: "Distillation request submitted!" });
setSourceDataset("");
setSourceDatasetOther("");
setStudentModel("");
setStudentModelOther("");
setDistillHfModelQuery("");
setDistillHuggingfaceModels([]);
setDistillSubmitterName("");
setDistillNotes("");
setShowDistillForm(false);
fetchRequests();
} else {
throw new Error("Failed to submit");
}
} catch (error) {
toast({ title: "Error", description: "Failed to submit request", variant: "destructive" });
} finally {
setSubmitting(false);
}
}
async function handleDatasetSubmit(e: React.FormEvent) {
e.preventDefault();
const resolvedSourceModel =
sourceModel === SOURCE_MODEL_OTHER_HF ? sourceModelOther.trim() : sourceModel;
const resolvedSubmitterName = datasetSubmitterName.trim();
if (!resolvedSourceModel) {
toast({ title: "Error", description: "Please select a source model", variant: "destructive" });
return;
}
setSubmitting(true);
try {
const res = await fetch("/api/dataset", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
sourceModel: resolvedSourceModel,
submitterName: resolvedSubmitterName || undefined,
datasetSize,
reasoningDepth,
topics: selectedTopics,
additionalNotes: datasetNotes,
}),
});
if (res.ok) {
toast({ title: "Success", description: "Dataset request submitted!" });
setSourceModel(openrouterModels[0]?.id || "");
setSourceModelOther("");
setHfModelQuery("");
setHuggingfaceModels([]);
setDatasetSubmitterName("");
setDatasetSize("250x");
setReasoningDepth("high");
setSelectedTopics([]);
setDatasetNotes("");
setShowDatasetForm(false);
fetchRequests();
} else {
throw new Error("Failed to submit");
}
} catch (error) {
toast({ title: "Error", description: "Failed to submit request", variant: "destructive" });
} finally {
setSubmitting(false);
}
}
async function handleUpvote(type: "distillation" | "dataset", id: string) {
try {
const endpoint = type === "distillation" ? "/api/distillation" : "/api/dataset";
const res = await fetch(endpoint, {
method: "PATCH",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ id }),
});
const data = await res.json();
if (!res.ok) {
if (res.status === 404) {
toast({ title: "Not found", description: "This request no longer exists", variant: "destructive" });
return;
}
toast({ title: "Error", description: data?.error || "Failed to vote", variant: "destructive" });
return;
}
if (type === "distillation") {
setDistillationRequests((prev) =>
prev.map((r) => (r.id === id ? { ...r, upvotes: data.upvotes } : r))
);
} else {
setDatasetRequests((prev) =>
prev.map((r) => (r.id === id ? { ...r, upvotes: data.upvotes } : r))
);
}
if (data.action === "unvoted") {
toast({ title: "Vote removed", description: "Your vote has been removed" });
} else {
toast({ title: "Voted!", description: "Your vote has been recorded" });
}
} catch (error) {
toast({ title: "Error", description: "Failed to vote", variant: "destructive" });
}
}
function toggleTopic(topic: string) {
setSelectedTopics((prev) =>
prev.includes(topic) ? prev.filter((t) => t !== topic) : [...prev, topic]
);
}
function getStatusBadge(status: string) {
switch (status) {
case "completed":
return <Badge variant="success">Completed</Badge>;
case "in_progress":
return <Badge variant="warning">In Progress</Badge>;
default:
return <Badge variant="secondary">Pending</Badge>;
}
}
function formatDate(dateStr: string) {
return new Date(dateStr).toLocaleDateString("en-US", {
month: "short",
day: "numeric",
year: "numeric",
});
}
function goToDiscussion(type: "distillation" | "dataset", id: string) {
router.push(`/requests/${type}/${id}`);
}
return (
<main className="min-h-screen bg-background">
<Navbar />
{/* Hero */}
<section className="relative overflow-hidden pt-24 pb-16">
<div className="pointer-events-none absolute inset-0 -z-10 bg-[radial-gradient(circle_at_top,rgba(255,76,0,0.10),transparent_55%)] dark:bg-[radial-gradient(circle_at_top,rgba(255,76,0,0.16),transparent_55%)]" />
<div className="mx-auto max-w-6xl px-4 sm:px-6">
<div className="max-w-3xl">
<p className="mb-3 text-sm font-medium text-primary">Community Requests</p>
<h1 className="mb-6 text-4xl font-bold leading-tight tracking-tight text-foreground md:text-5xl">
Request Model Distillations & Datasets
</h1>
<p className="mb-8 text-lg leading-relaxed text-muted-foreground">
Submit your requests for new distilled models or reasoning datasets. Vote on requests
from other community members to help us prioritize what to build next.
</p>
</div>
</div>
</section>
{/* Main Content */}
<section className="py-8">
<div className="mx-auto max-w-6xl px-4 sm:px-6">
<Tabs defaultValue="distillation" className="w-full">
<TabsList className="mb-6 grid w-full grid-cols-2">
<TabsTrigger value="distillation" className="flex items-center gap-2">
<Cpu className="h-4 w-4" />
Model Distillation
</TabsTrigger>
<TabsTrigger value="dataset" className="flex items-center gap-2">
<Database className="h-4 w-4" />
Dataset
</TabsTrigger>
</TabsList>
{/* Distillation Tab */}
<TabsContent value="distillation">
<div className="mb-6 flex items-center justify-between">
<h2 className="text-xl font-semibold text-foreground">Distillation Requests</h2>
<Button onClick={() => setShowDistillForm(!showDistillForm)}>
<Plus className="h-4 w-4" />
New Request
</Button>
</div>
{showDistillForm && (
<Card className="mb-6">
<CardHeader>
<CardTitle>Request a Distilled Model</CardTitle>
<CardDescription>
Select one of our existing datasets to distill into a student model
</CardDescription>
</CardHeader>
<CardContent>
<form onSubmit={handleDistillSubmit} className="space-y-4">
<div className="grid gap-4 md:grid-cols-2">
<div className="space-y-2">
<Label htmlFor="dataset">Source Dataset *</Label>
<Combobox
options={[...teichaiDatasets, { id: "Other", name: "Other" }]}
value={sourceDataset}
onValueChange={(v) => {
setSourceDataset(v);
if (v !== "Other") setSourceDatasetOther("");
}}
placeholder="Select a TeichAI dataset"
searchPlaceholder="Search datasets..."
emptyMessage="No datasets found"
loading={loadingDatasets}
/>
</div>
<div className="space-y-2">
<Label htmlFor="student">Student Model *</Label>
<Select
value={studentModel}
onValueChange={(v) => {
setStudentModel(v);
if (v !== "Other") {
setStudentModelOther("");
setDistillHfModelQuery("");
setDistillHuggingfaceModels([]);
} else {
setStudentModelOther("");
setDistillHfModelQuery("");
setDistillHuggingfaceModels([]);
}
}}
>
<SelectTrigger>
<SelectValue placeholder="Select student model" />
</SelectTrigger>
<SelectContent>
{STUDENT_MODELS.map((model) => (
<SelectItem key={model} value={model}>
{model}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
</div>
{sourceDataset === "Other" && (
<div className="space-y-2">
<Label htmlFor="datasetOther">Source Dataset (Other) *</Label>
<input
id="datasetOther"
className="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2"
value={sourceDatasetOther}
onChange={(e) => setSourceDatasetOther(e.target.value)}
placeholder="Type the dataset name"
/>
</div>
)}
{studentModel === "Other" && (
<div className="space-y-2">
<Label htmlFor="studentOther">Hugging Face Student Model *</Label>
<Combobox
options={distillHuggingfaceModels}
value={studentModelOther}
onValueChange={setStudentModelOther}
placeholder="Search safetensors models"
searchPlaceholder="Type to search models..."
emptyMessage={distillHfModelQuery.trim() ? "No models found" : "Start typing to search"}
loading={loadingDistillHfModels}
searchValue={distillHfModelQuery}
onSearchValueChange={setDistillHfModelQuery}
disableLocalFilter
/>
</div>
)}
<div className="space-y-2">
<Label htmlFor="distillSubmitterName">Name (optional)</Label>
<input
id="distillSubmitterName"
title="Name"
className="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2"
value={distillSubmitterName}
onChange={(e) => setDistillSubmitterName(e.target.value)}
placeholder="Your name (optional)"
/>
</div>
<div className="space-y-2">
<Label htmlFor="notes">Additional Notes</Label>
<Textarea
id="notes"
placeholder="Any specific requirements or context..."
value={distillNotes}
onChange={(e) => setDistillNotes(e.target.value)}
/>
</div>
<div className="flex gap-2">
<Button type="submit" disabled={submitting}>
{submitting && <Loader2 className="h-4 w-4 animate-spin" />}
Submit Request
</Button>
<Button type="button" variant="outline" onClick={() => setShowDistillForm(false)}>
Cancel
</Button>
</div>
</form>
</CardContent>
</Card>
)}
{loading ? (
<div className="flex justify-center py-12">
<Loader2 className="h-8 w-8 animate-spin text-muted-foreground" />
</div>
) : distillationRequests.length === 0 ? (
<Card className="p-12 text-center">
<p className="text-muted-foreground">No distillation requests yet. Be the first!</p>
</Card>
) : (
<div className="space-y-4">
{distillationRequests.map((request) => (
<Card
key={request.id}
className="group cursor-pointer transition-all hover:shadow-md"
onClick={() => goToDiscussion("distillation", request.id)}
role="link"
tabIndex={0}
onKeyDown={(e) => {
if (e.key === "Enter" || e.key === " ") {
e.preventDefault();
goToDiscussion("distillation", request.id);
}
}}
>
<CardContent className="p-5">
<div className="flex items-start gap-4">
<button
onClick={(e) => {
e.stopPropagation();
handleUpvote("distillation", request.id);
}}
className="flex flex-col items-center gap-1 rounded-lg border border-border bg-muted px-3 py-2 transition-colors hover:border-primary hover:bg-accent"
>
<ArrowUp className="h-4 w-4 text-primary" />
<span className="text-sm font-semibold">{request.upvotes}</span>
</button>
<div className="flex-1">
<div className="mb-2 flex flex-wrap items-center gap-2">
<h3 className="font-medium text-foreground">
{request.sourceDataset} → {request.studentModel}
</h3>
{getStatusBadge(request.status)}
</div>
{request.submitterName ? (
<p className="mb-2 text-sm text-muted-foreground">By {request.submitterName}</p>
) : null}
{request.additionalNotes && (
<p className="mb-2 text-sm text-muted-foreground">{request.additionalNotes}</p>
)}
<p className="text-xs text-muted-foreground">
Requested on {formatDate(request.createdAt)}
</p>
</div>
<div className="flex items-center text-muted-foreground">
<ChevronRight className="h-5 w-5 opacity-50 transition-opacity group-hover:opacity-100" />
</div>
</div>
</CardContent>
</Card>
))}
</div>
)}
</TabsContent>
{/* Dataset Tab */}
<TabsContent value="dataset">
<div className="mb-6 flex items-center justify-between">
<h2 className="text-xl font-semibold text-foreground">Dataset</h2>
<Button onClick={() => setShowDatasetForm(!showDatasetForm)}>
<Plus className="h-4 w-4" />
New Request
</Button>
</div>
{showDatasetForm && (
<Card className="mb-6">
<CardHeader>
<CardTitle>Request a Dataset</CardTitle>
<CardDescription>
Specify which model to generate reasoning data from
</CardDescription>
</CardHeader>
<CardContent>
<form onSubmit={handleDatasetSubmit} className="space-y-4">
<div className="grid gap-4 md:grid-cols-2">
<div className="space-y-2">
<Label htmlFor="sourceModel">Source Model *</Label>
<Combobox
options={[
...openrouterModels,
{ id: SOURCE_MODEL_OTHER_HF, name: SOURCE_MODEL_OTHER_HF },
]}
value={sourceModel}
onValueChange={(v) => {
setSourceModel(v);
if (v !== SOURCE_MODEL_OTHER_HF) {
setSourceModelOther("");
setHfModelQuery("");
setHuggingfaceModels([]);
}
}}
placeholder="Select a model"
searchPlaceholder="Search OpenRouter models..."
emptyMessage="No models found"
loading={loadingModels}
/>
</div>
<div className="space-y-2">
<Label htmlFor="size">Dataset Size</Label>
<Select value={datasetSize} onValueChange={setDatasetSize}>
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectContent>
{DATASET_SIZES.map((size) => (
<SelectItem key={size} value={size}>
{size} samples
</SelectItem>
))}
</SelectContent>
</Select>
</div>
</div>
{sourceModel === SOURCE_MODEL_OTHER_HF && (
<div className="space-y-2">
<Label htmlFor="sourceModelOther">Hugging Face Model *</Label>
<Combobox
options={huggingfaceModels}
value={sourceModelOther}
onValueChange={setSourceModelOther}
placeholder="Search safetensors models"
searchPlaceholder="Type to search models..."
emptyMessage={hfModelQuery.trim() ? "No models found" : "Start typing to search"}
loading={loadingHfModels}
searchValue={hfModelQuery}
onSearchValueChange={setHfModelQuery}
disableLocalFilter
/>
</div>
)}
<div className="space-y-2">
<Label htmlFor="datasetSubmitterName">Name (optional)</Label>
<input
id="datasetSubmitterName"
title="Name"
className="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2"
value={datasetSubmitterName}
onChange={(e) => setDatasetSubmitterName(e.target.value)}
placeholder="Your name (optional)"
/>
</div>
<div className="space-y-2">
<Label htmlFor="depth">Reasoning Depth</Label>
<Select value={reasoningDepth} onValueChange={setReasoningDepth}>
<SelectTrigger className="w-[200px]">
<SelectValue />
</SelectTrigger>
<SelectContent>
{REASONING_DEPTHS.map((depth) => (
<SelectItem key={depth} value={depth}>
{depth.charAt(0).toUpperCase() + depth.slice(1)}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
<div className="space-y-2">
<Label>Topics (select multiple)</Label>
<div className="flex flex-wrap gap-2">
{TOPICS.map((topic) => (
<button
key={topic}
type="button"
onClick={() => toggleTopic(topic)}
className={`rounded-full px-3 py-1 text-sm transition-colors ${selectedTopics.includes(topic)
? "bg-primary text-primary-foreground"
: "bg-muted text-muted-foreground hover:bg-accent"
}`}
>
{topic}
</button>
))}
</div>
</div>
<div className="space-y-2">
<Label htmlFor="datasetNotes">Additional Notes</Label>
<Textarea
id="datasetNotes"
placeholder="Any specific requirements or context..."
value={datasetNotes}
onChange={(e) => setDatasetNotes(e.target.value)}
/>
</div>
<div className="flex gap-2">
<Button type="submit" disabled={submitting}>
{submitting && <Loader2 className="h-4 w-4 animate-spin" />}
Submit Request
</Button>
<Button type="button" variant="outline" onClick={() => setShowDatasetForm(false)}>
Cancel
</Button>
</div>
</form>
</CardContent>
</Card>
)}
{loading ? (
<div className="flex justify-center py-12">
<Loader2 className="h-8 w-8 animate-spin text-muted-foreground" />
</div>
) : datasetRequests.length === 0 ? (
<Card className="p-12 text-center">
<p className="text-muted-foreground">No dataset requests yet. Be the first!</p>
</Card>
) : (
<div className="space-y-4">
{datasetRequests.map((request) => (
<Card
key={request.id}
className="group cursor-pointer transition-all hover:shadow-md"
onClick={() => goToDiscussion("dataset", request.id)}
role="link"
tabIndex={0}
onKeyDown={(e) => {
if (e.key === "Enter" || e.key === " ") {
e.preventDefault();
goToDiscussion("dataset", request.id);
}
}}
>
<CardContent className="p-5">
<div className="flex items-start gap-4">
<button
onClick={(e) => {
e.stopPropagation();
handleUpvote("dataset", request.id);
}}
className="flex flex-col items-center gap-1 rounded-lg border border-border bg-muted px-3 py-2 transition-colors hover:border-primary hover:bg-accent"
>
<ArrowUp className="h-4 w-4 text-primary" />
<span className="text-sm font-semibold">{request.upvotes}</span>
</button>
<div className="flex-1">
<div className="mb-2 flex flex-wrap items-center gap-2">
<h3 className="font-medium text-foreground">
{request.sourceModel} Dataset ({request.datasetSize})
</h3>
{getStatusBadge(request.status)}
<Badge variant="outline">{request.reasoningDepth} reasoning</Badge>
</div>
{request.submitterName ? (
<p className="mb-2 text-sm text-muted-foreground">By {request.submitterName}</p>
) : null}
{request.topics.length > 0 && (
<div className="mb-2 flex flex-wrap gap-1">
{request.topics.map((topic) => (
<Badge key={topic} variant="secondary" className="text-xs">
{topic}
</Badge>
))}
</div>
)}
{request.additionalNotes && (
<p className="mb-2 text-sm text-muted-foreground">{request.additionalNotes}</p>
)}
<p className="text-xs text-muted-foreground">
Requested on {formatDate(request.createdAt)}
</p>
</div>
<div className="flex items-center text-muted-foreground">
<ChevronRight className="h-5 w-5 opacity-50 transition-opacity group-hover:opacity-100" />
</div>
</div>
</CardContent>
</Card>
))}
</div>
)}
</TabsContent>
</Tabs>
</div>
</section>
{/* Info Section */}
<section className="py-16">
<div className="mx-auto max-w-6xl px-4 sm:px-6">
<Card className="overflow-hidden">
<CardContent className="p-8 md:p-12">
<div className="max-w-2xl">
<h2 className="mb-4 text-2xl font-bold text-foreground">How It Works</h2>
<ul className="space-y-3 text-muted-foreground">
<li className="flex items-start gap-2">
<span className="font-bold text-primary">1.</span>
Submit a request for a model distillation or reasoning dataset
</li>
<li className="flex items-start gap-2">
<span className="font-bold text-primary">2.</span>
Upvote requests from other community members
</li>
<li className="flex items-start gap-2">
<span className="font-bold text-primary">3.</span>
We prioritize requests based on community interest
</li>
<li className="flex items-start gap-2">
<span className="font-bold text-primary">4.</span>
Models and datasets are published on our Hugging Face page
</li>
<li className="flex items-start gap-2">
<span className="font-bold text-primary">Note:</span>
We will do our best to fulfill as many requests as possible, but we can’t guarantee anything due to time and money constraints.
</li>
</ul>
</div>
</CardContent>
</Card>
</div>
</section>
<Footer />
</main>
);
}