A quick vibe-coded site to test response times of PLC.directory mirrors (over 3 attempts)
1import { useState } from "react"; 2import { Button } from "@/components/ui/button"; 3import { Input } from "@/components/ui/input"; 4import { BenchmarkTable } from "@/components/BenchmarkTable"; 5import { mirrors } from "@/config/mirrors"; 6import { benchmarkAllMirrors } from "@/utils/benchmark"; 7import { BenchmarkResult } from "@/types/benchmark"; 8import { toast } from "sonner"; 9import { Activity, Zap } from "lucide-react"; 10 11const Index = () => { 12 const [did, setDid] = useState(""); 13 const [loading, setLoading] = useState(false); 14 const [results, setResults] = useState<BenchmarkResult[]>([]); 15 16 const handleBenchmark = async () => { 17 if (!did.trim()) { 18 toast.error("Please enter a DID"); 19 return; 20 } 21 22 setLoading(true); 23 setResults([]); 24 25 try { 26 const benchmarkResults = await benchmarkAllMirrors(mirrors, did.trim()); 27 setResults(benchmarkResults); 28 29 const successCount = benchmarkResults.filter(r => r.status === "success").length; 30 toast.success(`Benchmark complete! ${successCount}/${benchmarkResults.length} mirrors responded`); 31 } catch (error) { 32 toast.error("Failed to run benchmark"); 33 console.error(error); 34 } finally { 35 setLoading(false); 36 } 37 }; 38 39 const handleKeyPress = (e: React.KeyboardEvent) => { 40 if (e.key === "Enter" && !loading) { 41 handleBenchmark(); 42 } 43 }; 44 45 return ( 46 <div className="min-h-screen bg-background py-8 px-4"> 47 <div className="max-w-6xl mx-auto space-y-8"> 48 {/* Header */} 49 <header className="text-center space-y-3"> 50 <div className="flex items-center justify-center gap-2 text-primary"> 51 <Activity className="w-8 h-8" /> 52 <h1 className="text-4xl font-bold">PLC Mirror Benchmark</h1> 53 </div> 54 <p className="text-muted-foreground text-lg max-w-2xl mx-auto"> 55 Test and compare response times across different PLC.directory mirrors 56 </p> 57 </header> 58 59 {/* Input Section */} 60 <div className="bg-card border border-border rounded-lg p-6 shadow-sm"> 61 <div className="space-y-4"> 62 <div> 63 <label htmlFor="did-input" className="block text-sm font-medium mb-2"> 64 ATProto DID 65 </label> 66 <div className="flex gap-3"> 67 <Input 68 id="did-input" 69 type="text" 70 placeholder="did:plc:example123..." 71 value={did} 72 onChange={(e) => setDid(e.target.value)} 73 onKeyPress={handleKeyPress} 74 className="flex-1 font-mono" 75 disabled={loading} 76 /> 77 <Button 78 onClick={handleBenchmark} 79 disabled={loading || !did.trim()} 80 className="gap-2" 81 > 82 <Zap className="w-4 h-4" /> 83 {loading ? "Benchmarking..." : "Run Benchmark"} 84 </Button> 85 </div> 86 </div> 87 <div className="text-sm text-muted-foreground"> 88 Testing {mirrors.length} mirrors with 3 attempts each 89 </div> 90 </div> 91 </div> 92 93 {/* Results Section */} 94 {(results.length > 0 || loading) && ( 95 <div className="space-y-4"> 96 <h2 className="text-2xl font-semibold">Results</h2> 97 {loading ? ( 98 <div className="bg-card border border-border rounded-lg p-12 text-center"> 99 <div className="inline-block animate-spin rounded-full h-8 w-8 border-b-2 border-primary mb-4"></div> 100 <p className="text-muted-foreground">Benchmarking mirrors...</p> 101 </div> 102 ) : ( 103 <BenchmarkTable results={results} /> 104 )} 105 </div> 106 )} 107 108 {/* Info Section */} 109 {results.length === 0 && !loading && ( 110 <div className="bg-muted/30 border border-border rounded-lg p-6"> 111 <h3 className="font-semibold mb-2">How to use:</h3> 112 <ol className="list-decimal list-inside space-y-1 text-sm text-muted-foreground"> 113 <li>Enter an ATProto DID (e.g., did:plc:z72i7hdynmk6r22z27h6tvur)</li> 114 <li>Click "Run Benchmark" or press Enter</li> 115 <li>View response times and status for each mirror</li> 116 </ol> 117 <div className="mt-4 pt-4 border-t border-border"> 118 <p className="text-sm text-muted-foreground"> 119 Mirrors can be configured in <code className="bg-background px-2 py-1 rounded text-mono">src/config/mirrors.ts</code> 120 </p> 121 </div> 122 </div> 123 )} 124 </div> 125 </div> 126 ); 127}; 128 129export default Index;