add dashboard and setup pages with relay URL handling
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
"use client"
|
||||
|
||||
import { useState } from "react"
|
||||
import { useState, useEffect } from "react"
|
||||
import { useRouter } from "next/navigation"
|
||||
import Link from "next/link"
|
||||
import {
|
||||
Server,
|
||||
@@ -33,6 +34,30 @@ import { ScrollArea } from "@/components/ui/scroll-area"
|
||||
|
||||
export default function DashboardPage() {
|
||||
const [isSidebarOpen, setIsSidebarOpen] = useState(false)
|
||||
const [relayUrl, setRelayUrl] = useState<string | null>(null)
|
||||
const [isLoading, setIsLoading] = useState(true)
|
||||
const router = useRouter()
|
||||
|
||||
useEffect(() => {
|
||||
// Check if relay URL is set in localStorage
|
||||
const savedRelayUrl = localStorage.getItem("relayUrl")
|
||||
|
||||
if (!savedRelayUrl) {
|
||||
// Redirect to setup page if no relay URL is found
|
||||
router.push("/setup")
|
||||
} else {
|
||||
setRelayUrl(savedRelayUrl)
|
||||
setIsLoading(false)
|
||||
}
|
||||
}, [router])
|
||||
|
||||
// Display loading state while checking localStorage
|
||||
if (isLoading) {
|
||||
return <div className="flex min-h-screen items-center justify-center">Loading...</div>
|
||||
}
|
||||
|
||||
// Get the relay domain from the URL for display
|
||||
const relayDomain = relayUrl ? new URL(relayUrl).host : "my-relay.com"
|
||||
|
||||
return (
|
||||
<div className="flex min-h-screen flex-col">
|
||||
@@ -126,10 +151,13 @@ export default function DashboardPage() {
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="outline" size="sm" className="gap-1">
|
||||
my-relay.com <ChevronDown className="h-4 w-4 opacity-50" />
|
||||
{relayDomain} <ChevronDown className="h-4 w-4 opacity-50" />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end">
|
||||
<DropdownMenuItem onClick={() => {
|
||||
router.push('/setup');
|
||||
}}>Change Relay Connection</DropdownMenuItem>
|
||||
<DropdownMenuItem>Add New Relay</DropdownMenuItem>
|
||||
<DropdownMenuItem>Manage Relays</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
|
@@ -14,8 +14,8 @@ const geistMono = Geist_Mono({
|
||||
});
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Create Next App",
|
||||
description: "Generated by create next app",
|
||||
title: "Relay ControlPanel",
|
||||
description: "Written by highperfocused",
|
||||
};
|
||||
|
||||
export default function RootLayout({
|
||||
|
116
app/setup/page.tsx
Normal file
116
app/setup/page.tsx
Normal file
@@ -0,0 +1,116 @@
|
||||
"use client"
|
||||
|
||||
import { useState, useEffect } from "react"
|
||||
import { useRouter } from "next/navigation"
|
||||
import { Server, ArrowRight } from "lucide-react"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Input } from "@/components/ui/input"
|
||||
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card"
|
||||
|
||||
export default function SetupPage() {
|
||||
const [relayUrl, setRelayUrl] = useState("")
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
const [error, setError] = useState("")
|
||||
const router = useRouter()
|
||||
|
||||
// Check if user already has a relay configured - if yes, redirect to dashboard
|
||||
useEffect(() => {
|
||||
const savedRelayUrl = localStorage.getItem("relayUrl")
|
||||
if (savedRelayUrl) {
|
||||
router.push("/dashboard")
|
||||
}
|
||||
}, [router])
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault()
|
||||
setIsLoading(true)
|
||||
setError("")
|
||||
|
||||
// Validate the URL format
|
||||
try {
|
||||
// Simple validation for websocket URL format
|
||||
if (!relayUrl.trim()) {
|
||||
throw new Error("Please enter a relay URL")
|
||||
}
|
||||
|
||||
// Check if it's a valid URL
|
||||
const url = new URL(relayUrl)
|
||||
|
||||
// Check if it's a ws:// or wss:// protocol
|
||||
if (!url.protocol.match(/^wss?:$/)) {
|
||||
throw new Error("Relay URL must use WebSocket protocol (ws:// or wss://)")
|
||||
}
|
||||
|
||||
// Save to localStorage
|
||||
localStorage.setItem("relayUrl", relayUrl.trim())
|
||||
|
||||
// Redirect to dashboard
|
||||
router.push("/dashboard")
|
||||
} catch (err: any) {
|
||||
setError(err.message || "Invalid relay URL format")
|
||||
setIsLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-screen flex flex-col">
|
||||
<header className="border-b">
|
||||
<div className="container flex h-16 items-center px-4 md:px-6 mx-auto">
|
||||
<div className="flex items-center gap-2">
|
||||
<Server className="h-6 w-6" />
|
||||
<span className="text-lg font-bold">NOSTR Relay Manager</span>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main className="flex-1 flex items-center justify-center p-4">
|
||||
<Card className="w-full max-w-md">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-2xl">Connect to Your Relay</CardTitle>
|
||||
<CardDescription>
|
||||
Enter your relay's WebSocket URL to connect to your NOSTR relay
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<CardContent>
|
||||
<div className="grid gap-6">
|
||||
<div className="grid gap-3">
|
||||
<label className="text-sm font-medium leading-none" htmlFor="relay-url">
|
||||
Relay WebSocket URL
|
||||
</label>
|
||||
<Input
|
||||
id="relay-url"
|
||||
placeholder="wss://your-relay.com"
|
||||
value={relayUrl}
|
||||
onChange={(e) => setRelayUrl(e.target.value)}
|
||||
required
|
||||
/>
|
||||
{error && (
|
||||
<p className="text-sm text-red-500">{error}</p>
|
||||
)}
|
||||
<p className="text-xs text-muted-foreground">
|
||||
This should be the WebSocket URL of your NOSTR relay, starting with ws:// or wss://
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
<CardFooter>
|
||||
<Button type="submit" className="w-full" disabled={isLoading}>
|
||||
{isLoading ? "Connecting..." : "Connect to Relay"}
|
||||
{!isLoading && <ArrowRight className="ml-2 h-4 w-4" />}
|
||||
</Button>
|
||||
</CardFooter>
|
||||
</form>
|
||||
</Card>
|
||||
</main>
|
||||
|
||||
<footer className="border-t py-6">
|
||||
<div className="container flex items-center justify-center px-4 md:px-6 mx-auto">
|
||||
<p className="text-sm text-muted-foreground">
|
||||
© {new Date().getFullYear()} NOSTR Relay Manager
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
)
|
||||
}
|
Reference in New Issue
Block a user