add hub menagment functions

This commit is contained in:
gitGnome
2026-04-29 14:46:22 +02:00
parent 221fb47495
commit 6378966267
19 changed files with 780 additions and 62 deletions
+102
View File
@@ -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>
)
}