feat: merge admin routes into unified frontend
This commit is contained in:
95
frontend-web/src/app/admin/(secure)/users/page.tsx
Normal file
95
frontend-web/src/app/admin/(secure)/users/page.tsx
Normal file
@@ -0,0 +1,95 @@
|
||||
"use client";
|
||||
|
||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||
import { useState } from "react";
|
||||
|
||||
import { api } from "@/lib/api";
|
||||
|
||||
type UserRow = {
|
||||
id: number;
|
||||
publicId: string;
|
||||
username: string;
|
||||
nickname: string;
|
||||
email: string;
|
||||
status: number;
|
||||
createdAt: string;
|
||||
};
|
||||
|
||||
export default function UsersPage() {
|
||||
const [adjustForm, setAdjustForm] = useState({
|
||||
userId: 1,
|
||||
amountPoints: 100,
|
||||
reason: "manual bonus",
|
||||
});
|
||||
const usersQuery = useQuery({
|
||||
queryKey: ["admin-users"],
|
||||
queryFn: () => api.get<UserRow[]>("/api/v1/admin/users"),
|
||||
});
|
||||
const adjustMutation = useMutation({
|
||||
mutationFn: () =>
|
||||
api.post(`/api/v1/admin/users/${adjustForm.userId}/wallet-adjust`, adjustForm),
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="two-col-grid">
|
||||
<section className="panel">
|
||||
<h3>用户列表</h3>
|
||||
<div className="list-grid">
|
||||
{usersQuery.data?.map((user) => (
|
||||
<div className="list-item" key={user.id}>
|
||||
<strong>{user.nickname || user.username || user.publicId}</strong>
|
||||
<div className="muted">
|
||||
#{user.id} · {user.email} · 状态 {user.status}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="panel">
|
||||
<h3>人工调账</h3>
|
||||
<div className="form-stack">
|
||||
<label className="field-label">
|
||||
用户 ID
|
||||
<input
|
||||
type="number"
|
||||
value={adjustForm.userId}
|
||||
onChange={(event) =>
|
||||
setAdjustForm((previous) => ({
|
||||
...previous,
|
||||
userId: Number(event.target.value),
|
||||
}))
|
||||
}
|
||||
/>
|
||||
</label>
|
||||
<label className="field-label">
|
||||
调整积分
|
||||
<input
|
||||
type="number"
|
||||
value={adjustForm.amountPoints}
|
||||
onChange={(event) =>
|
||||
setAdjustForm((previous) => ({
|
||||
...previous,
|
||||
amountPoints: Number(event.target.value),
|
||||
}))
|
||||
}
|
||||
/>
|
||||
</label>
|
||||
<label className="field-label">
|
||||
原因
|
||||
<input
|
||||
value={adjustForm.reason}
|
||||
onChange={(event) =>
|
||||
setAdjustForm((previous) => ({ ...previous, reason: event.target.value }))
|
||||
}
|
||||
/>
|
||||
</label>
|
||||
<button className="primary-button" onClick={() => adjustMutation.mutate()}>
|
||||
执行调账
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user