Files
NexaPG/frontend/src/pages/TargetsPage.jsx
2026-02-12 09:09:13 +01:00

115 lines
3.6 KiB
JavaScript

import React, { useEffect, useState } from "react";
import { Link } from "react-router-dom";
import { apiFetch } from "../api";
import { useAuth } from "../state";
const emptyForm = {
name: "",
host: "",
port: 5432,
dbname: "",
username: "",
password: "",
sslmode: "prefer",
tags: {},
};
export function TargetsPage() {
const { tokens, refresh, me } = useAuth();
const [targets, setTargets] = useState([]);
const [form, setForm] = useState(emptyForm);
const [error, setError] = useState("");
const [loading, setLoading] = useState(true);
const canManage = me?.role === "admin" || me?.role === "operator";
const load = async () => {
setLoading(true);
try {
setTargets(await apiFetch("/targets", {}, tokens, refresh));
setError("");
} catch (e) {
setError(String(e.message || e));
} finally {
setLoading(false);
}
};
useEffect(() => {
load();
}, []);
const createTarget = async (e) => {
e.preventDefault();
try {
await apiFetch("/targets", { method: "POST", body: JSON.stringify(form) }, tokens, refresh);
setForm(emptyForm);
await load();
} catch (e) {
setError(String(e.message || e));
}
};
const deleteTarget = async (id) => {
if (!confirm("Target löschen?")) return;
try {
await apiFetch(`/targets/${id}`, { method: "DELETE" }, tokens, refresh);
await load();
} catch (e) {
setError(String(e.message || e));
}
};
return (
<div>
<h2>Targets Management</h2>
{error && <div className="card error">{error}</div>}
{canManage && (
<form className="card grid two" onSubmit={createTarget}>
<input placeholder="Name" value={form.name} onChange={(e) => setForm({ ...form, name: e.target.value })} required />
<input placeholder="Host" value={form.host} onChange={(e) => setForm({ ...form, host: e.target.value })} required />
<input placeholder="Port" value={form.port} onChange={(e) => setForm({ ...form, port: Number(e.target.value) })} type="number" />
<input placeholder="DB Name" value={form.dbname} onChange={(e) => setForm({ ...form, dbname: e.target.value })} required />
<input placeholder="Username" value={form.username} onChange={(e) => setForm({ ...form, username: e.target.value })} required />
<input placeholder="Passwort" type="password" value={form.password} onChange={(e) => setForm({ ...form, password: e.target.value })} required />
<select value={form.sslmode} onChange={(e) => setForm({ ...form, sslmode: e.target.value })}>
<option value="disable">disable</option>
<option value="prefer">prefer</option>
<option value="require">require</option>
</select>
<button>Target anlegen</button>
</form>
)}
<div className="card">
{loading ? (
<p>Lade Targets...</p>
) : (
<table>
<thead>
<tr>
<th>Name</th>
<th>Host</th>
<th>DB</th>
<th>Aktionen</th>
</tr>
</thead>
<tbody>
{targets.map((t) => (
<tr key={t.id}>
<td>{t.name}</td>
<td>{t.host}:{t.port}</td>
<td>{t.dbname}</td>
<td>
<Link to={`/targets/${t.id}`}>Details</Link>{" "}
{canManage && <button onClick={() => deleteTarget(t.id)}>Delete</button>}
</td>
</tr>
))}
</tbody>
</table>
)}
</div>
</div>
);
}