Add src/components/AddHostModal.tsx
This commit is contained in:
parent
69c7f281c0
commit
7a6fdde3ed
1 changed files with 81 additions and 0 deletions
81
src/components/AddHostModal.tsx
Normal file
81
src/components/AddHostModal.tsx
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
import { useState } from "react";
|
||||
import { api } from "../api";
|
||||
|
||||
interface Props {
|
||||
onClose: () => void;
|
||||
onAdded: () => void;
|
||||
}
|
||||
|
||||
export function AddHostModal({ onClose, onAdded }: Props) {
|
||||
const [name, setName] = useState("");
|
||||
const [ip, setIp] = useState("");
|
||||
const [port, setPort] = useState("47984");
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [saving, setSaving] = useState(false);
|
||||
|
||||
async function handleSubmit(e: React.FormEvent) {
|
||||
e.preventDefault();
|
||||
setSaving(true);
|
||||
setError(null);
|
||||
try {
|
||||
await api.addManualHost(name, ip, parseInt(port, 10) || 47984);
|
||||
onAdded();
|
||||
onClose();
|
||||
} catch (err: unknown) {
|
||||
setError(err instanceof Error ? err.message : "Failed to add host");
|
||||
} finally {
|
||||
setSaving(false);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 bg-black/60 flex items-center justify-center z-50" onClick={onClose}>
|
||||
<div
|
||||
className="bg-surface-raised border border-surface-elevated rounded-2xl p-6 w-80 shadow-2xl"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<h2 className="text-lg font-semibold mb-4">Add Host Manually</h2>
|
||||
<form onSubmit={handleSubmit} className="flex flex-col gap-3">
|
||||
<input
|
||||
className="bg-surface-elevated rounded-lg px-3 py-2 text-sm outline-none focus:ring-2 focus:ring-accent"
|
||||
placeholder="Display name"
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
required
|
||||
/>
|
||||
<input
|
||||
className="bg-surface-elevated rounded-lg px-3 py-2 text-sm outline-none focus:ring-2 focus:ring-accent"
|
||||
placeholder="IP or Tailscale hostname"
|
||||
value={ip}
|
||||
onChange={(e) => setIp(e.target.value)}
|
||||
required
|
||||
/>
|
||||
<input
|
||||
className="bg-surface-elevated rounded-lg px-3 py-2 text-sm outline-none focus:ring-2 focus:ring-accent"
|
||||
placeholder="Port (default 47984)"
|
||||
value={port}
|
||||
onChange={(e) => setPort(e.target.value)}
|
||||
type="number"
|
||||
/>
|
||||
{error && <p className="text-xs text-red-400">{error}</p>}
|
||||
<div className="flex gap-2 mt-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={onClose}
|
||||
className="flex-1 py-2 rounded-lg bg-surface-elevated text-sm"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
disabled={saving}
|
||||
className="flex-1 py-2 rounded-lg bg-accent text-sm font-medium disabled:opacity-50"
|
||||
>
|
||||
{saving ? "Adding…" : "Add"}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Loading…
Reference in a new issue