74 lines
2.3 KiB
TypeScript
74 lines
2.3 KiB
TypeScript
"use client";
|
||
|
||
import { useState, useEffect } from "react";
|
||
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "./ui/card";
|
||
import { Badge } from "./ui/badge";
|
||
import { Button } from "./ui/button";
|
||
import { useAuth } from "./AuthProvider";
|
||
|
||
type Campaign = {
|
||
id: string;
|
||
name: string;
|
||
gridSize: number;
|
||
status: string;
|
||
createdAt: string;
|
||
};
|
||
|
||
export function CampaignList({ onSelect }: { onSelect: (id: string) => void }) {
|
||
const { user } = useAuth();
|
||
const [campaigns, setCampaigns] = useState<Campaign[]>([]);
|
||
const [loading, setLoading] = useState(true);
|
||
|
||
useEffect(() => {
|
||
fetch("/api/campaigns")
|
||
.then(r => r.json())
|
||
.then(data => setCampaigns(data))
|
||
.finally(() => setLoading(false));
|
||
}, []);
|
||
|
||
if (loading) {
|
||
return (
|
||
<div className="text-center text-slate-500 font-mono text-sm py-8">
|
||
Scanning submarine network...
|
||
</div>
|
||
);
|
||
}
|
||
|
||
if (campaigns.length === 0) {
|
||
return (
|
||
<Card className="border-slate-700/30">
|
||
<CardContent className="py-8 text-center">
|
||
<div className="text-3xl mb-2">🗺️</div>
|
||
<p className="text-slate-500 font-mono text-sm">No active campaigns</p>
|
||
<p className="text-slate-600 font-mono text-xs mt-1">Admin can create one</p>
|
||
</CardContent>
|
||
</Card>
|
||
);
|
||
}
|
||
|
||
return (
|
||
<div className="grid gap-3 w-full max-w-md">
|
||
{campaigns.map(c => (
|
||
<Card key={c.id} className="border-slate-700/30 hover:border-cyan-700/30 transition-all cursor-pointer group" onClick={() => onSelect(c.id)}>
|
||
<CardContent className="p-4 flex items-center justify-between">
|
||
<div>
|
||
<h3 className="font-mono text-sm text-slate-200 group-hover:text-cyan-300 transition-colors">
|
||
{c.name}
|
||
</h3>
|
||
<div className="flex gap-2 mt-1">
|
||
<Badge variant={c.status === "active" ? "success" : "secondary"} className="text-[9px]">
|
||
{c.status}
|
||
</Badge>
|
||
<span className="text-[10px] text-slate-600 font-mono">{c.gridSize}×{c.gridSize}</span>
|
||
</div>
|
||
</div>
|
||
<Button variant="ghost" size="sm" className="font-mono text-xs">
|
||
▶ JOIN
|
||
</Button>
|
||
</CardContent>
|
||
</Card>
|
||
))}
|
||
</div>
|
||
);
|
||
}
|