v0.1 - макет интерфейса, аутентификация через логин, аккаунт админа, создание партии в 2 этапа, базовые настройки профиля и группы, переключение между группами, статистика
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
import { useState } from "react";
|
||||
|
||||
import { Spinner } from "../../components/Spinner";
|
||||
import { formatDateTime } from "../../domain/format";
|
||||
import { useAdminLogs } from "../../hooks/admin";
|
||||
|
||||
const ACTIONS = ["", "login", "create", "update", "delete"];
|
||||
const ENTITIES = ["", "user", "group", "group_member", "match", "admin"];
|
||||
|
||||
export function AdminLogsPage() {
|
||||
const [action, setAction] = useState("");
|
||||
const [entityType, setEntityType] = useState("");
|
||||
const { data, isLoading } = useAdminLogs({
|
||||
action: action || undefined,
|
||||
entity_type: entityType || undefined,
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h3>Журнал событий</h3>
|
||||
<div className="row" style={{ marginBottom: 10, gap: 8 }}>
|
||||
<select style={{ width: "auto" }} value={action} onChange={(e) => setAction(e.target.value)}>
|
||||
{ACTIONS.map((a) => (
|
||||
<option key={a} value={a}>
|
||||
{a || "все действия"}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<select style={{ width: "auto" }} value={entityType} onChange={(e) => setEntityType(e.target.value)}>
|
||||
{ENTITIES.map((en) => (
|
||||
<option key={en} value={en}>
|
||||
{en || "все сущности"}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
{isLoading ? (
|
||||
<Spinner />
|
||||
) : (
|
||||
<div className="stack">
|
||||
{(data?.items ?? []).map((log) => (
|
||||
<div key={log.id} className="card" style={{ margin: 0 }}>
|
||||
<div className="row-between">
|
||||
<b>
|
||||
{log.action} · {log.entity_type}
|
||||
{log.entity_id != null ? ` #${log.entity_id}` : ""}
|
||||
</b>
|
||||
<span className="muted small">{formatDateTime(log.created_at)}</span>
|
||||
</div>
|
||||
<div className="muted small">
|
||||
actor: {log.actor_id ?? "—"}
|
||||
{log.ip ? ` · ${log.ip}` : ""}
|
||||
</div>
|
||||
{log.payload && (
|
||||
<pre className="small muted" style={{ whiteSpace: "pre-wrap", margin: "4px 0 0" }}>
|
||||
{JSON.stringify(log.payload)}
|
||||
</pre>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
{(data?.items ?? []).length === 0 && <div className="muted small">Событий нет.</div>}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user