add hub menagment functions
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
import { useState } from 'react'
|
||||
import { Link, useNavigate } from 'react-router-dom'
|
||||
import { apiFetch } from '../api/http'
|
||||
|
||||
export default function SettingsPage() {
|
||||
const userId = localStorage.getItem('userId') ?? ''
|
||||
const [recipient, setRecipient] = useState('')
|
||||
const [status, setStatus] = useState(null)
|
||||
const [busy, setBusy] = useState(false)
|
||||
const [copied, setCopied] = useState(false)
|
||||
const navigate = useNavigate()
|
||||
|
||||
async function copyId() {
|
||||
if (!userId) return
|
||||
try {
|
||||
await navigator.clipboard.writeText(userId)
|
||||
setCopied(true)
|
||||
setTimeout(() => setCopied(false), 1500)
|
||||
} catch {
|
||||
setStatus({ kind: 'err', text: 'Clipboard unavailable' })
|
||||
}
|
||||
}
|
||||
|
||||
async function addConnection() {
|
||||
const id = recipient.trim()
|
||||
if (!id) return
|
||||
setBusy(true)
|
||||
setStatus(null)
|
||||
try {
|
||||
await apiFetch('GET', '/connection', { query: { recipient: id } })
|
||||
setStatus({ kind: 'ok', text: 'Connection created' })
|
||||
setRecipient('')
|
||||
} catch (err) {
|
||||
setStatus({ kind: 'err', text: err.message ?? String(err) })
|
||||
} finally {
|
||||
setBusy(false)
|
||||
}
|
||||
}
|
||||
|
||||
function logout() {
|
||||
localStorage.removeItem('token')
|
||||
localStorage.removeItem('userId')
|
||||
navigate('/auth')
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-gray-900 text-white flex justify-center py-10 px-4">
|
||||
<div className="w-full max-w-md flex flex-col gap-8">
|
||||
<div className="flex items-center justify-between">
|
||||
<Link to="/" className="text-blue-400 hover:text-blue-300 text-sm">← Back</Link>
|
||||
<button
|
||||
onClick={logout}
|
||||
className="text-gray-400 hover:text-red-400 text-sm"
|
||||
>
|
||||
Logout
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<section className="flex flex-col gap-2">
|
||||
<h2 className="text-lg font-semibold">Your user ID</h2>
|
||||
<div className="flex items-stretch gap-2">
|
||||
<code className="flex-1 bg-gray-800 text-gray-200 text-xs px-3 py-2 rounded break-all">
|
||||
{userId || '(missing)'}
|
||||
</code>
|
||||
<button
|
||||
onClick={copyId}
|
||||
disabled={!userId}
|
||||
className="px-3 py-2 rounded bg-gray-700 hover:bg-gray-600 text-sm disabled:opacity-50 shrink-0"
|
||||
>
|
||||
{copied ? 'Copied' : 'Copy'}
|
||||
</button>
|
||||
</div>
|
||||
<p className="text-xs text-gray-500">Share this with someone so they can add you.</p>
|
||||
</section>
|
||||
|
||||
<section className="flex flex-col gap-2">
|
||||
<h2 className="text-lg font-semibold">Add connection</h2>
|
||||
<input
|
||||
className="bg-gray-800 text-white text-sm px-3 py-2 rounded outline-none focus:ring-2 focus:ring-blue-500"
|
||||
placeholder="Recipient user UUID"
|
||||
value={recipient}
|
||||
onChange={e => setRecipient(e.target.value)}
|
||||
onKeyDown={e => { if (e.key === 'Enter' && !busy) addConnection() }}
|
||||
autoComplete="off"
|
||||
/>
|
||||
<button
|
||||
onClick={addConnection}
|
||||
disabled={busy || !recipient.trim()}
|
||||
className="self-end px-4 py-2 rounded bg-blue-600 hover:bg-blue-700 text-white disabled:opacity-50"
|
||||
>
|
||||
{busy ? 'Adding…' : 'Add'}
|
||||
</button>
|
||||
{status && (
|
||||
<p className={`text-sm ${status.kind === 'ok' ? 'text-green-400' : 'text-red-400'}`}>
|
||||
{status.text}
|
||||
</p>
|
||||
)}
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user