import { revalidatePath } from "next/cache";
import { redirect } from "next/navigation";
import { listTokens, createToken, revokeToken, deleteToken, updateToken, fetchUsers, createUser, deleteUser, updateUser, TokenDto, UserDto } from "@/lib/api";
import { Card, CardHeader, CardTitle, CardDescription, CardContent, Button, Badge, FormField, FormInput, FormSelect, FormRow } from "@/app/components/ui";
import { TokenUserSelect } from "@/app/components/TokenUserSelect";
import { UsernameEdit } from "@/app/components/UsernameEdit";
import { getServerTranslations } from "@/lib/i18n/server";
export const dynamic = "force-dynamic";
export default async function TokensPage({
searchParams
}: {
searchParams: Promise<{ created?: string }>;
}) {
const { t } = await getServerTranslations();
const params = await searchParams;
const tokens = await listTokens().catch(() => [] as TokenDto[]);
const users = await fetchUsers().catch(() => [] as UserDto[]);
async function createTokenAction(formData: FormData) {
"use server";
const name = formData.get("name") as string;
const scope = formData.get("scope") as string;
const userId = (formData.get("user_id") as string) || undefined;
if (name) {
const result = await createToken(name, scope, userId);
revalidatePath("/tokens");
redirect(`/tokens?created=${encodeURIComponent(result.token)}`);
}
}
async function revokeTokenAction(formData: FormData) {
"use server";
const id = formData.get("id") as string;
await revokeToken(id);
revalidatePath("/tokens");
}
async function deleteTokenAction(formData: FormData) {
"use server";
const id = formData.get("id") as string;
await deleteToken(id);
revalidatePath("/tokens");
}
async function createUserAction(formData: FormData) {
"use server";
const username = formData.get("username") as string;
if (username) {
await createUser(username);
revalidatePath("/tokens");
}
}
async function deleteUserAction(formData: FormData) {
"use server";
const id = formData.get("id") as string;
await deleteUser(id);
revalidatePath("/tokens");
}
async function renameUserAction(formData: FormData) {
"use server";
const id = formData.get("id") as string;
const username = formData.get("username") as string;
if (username?.trim()) {
await updateUser(id, username.trim());
revalidatePath("/tokens");
}
}
async function reassignTokenAction(formData: FormData) {
"use server";
const id = formData.get("id") as string;
const userId = (formData.get("user_id") as string) || null;
await updateToken(id, userId);
revalidatePath("/tokens");
}
return (
<>
{/* ── Lecteurs ─────────────────────────────────────────── */}
{t("users.title")}
{t("users.createNew")}
{t("users.createDescription")}
| {t("users.name")} |
{t("users.tokenCount")} |
{t("status.read")} |
{t("status.reading")} |
{t("users.createdAt")} |
{t("users.actions")} |
{/* Ligne admin synthétique */}
|
{process.env.ADMIN_USERNAME ?? "admin"}
{t("tokens.scopeAdmin")}
|
{tokens.filter(tok => tok.scope === "admin" && !tok.revoked_at).length}
|
— |
— |
— |
— |
{/* Ligne tokens read non assignés */}
{(() => {
const unassigned = tokens.filter(tok => tok.scope === "read" && !tok.user_id && !tok.revoked_at);
if (unassigned.length === 0) return null;
return (
|
{t("tokens.noUser")}
|
{unassigned.length} |
— |
— |
— |
— |
);
})()}
{users.map((user) => (
|
|
{user.token_count} |
{user.books_read > 0
? {user.books_read}
: —}
|
{user.books_reading > 0
? {user.books_reading}
: —}
|
{new Date(user.created_at).toLocaleDateString()}
|
|
))}
{/* ── Tokens API ───────────────────────────────────────── */}
{t("tokens.apiTokens")}
{params.created ? (
{t("tokens.created")}
{t("tokens.createdDescription")}
{params.created}
) : null}
{t("tokens.createNew")}
{t("tokens.createDescription")}
| {t("tokens.name")} |
{t("tokens.user")} |
{t("tokens.scope")} |
{t("tokens.prefix")} |
{t("tokens.status")} |
{t("tokens.actions")} |
{tokens.map((token) => (
| {token.name} |
|
{token.scope}
|
{token.prefix}
|
{token.revoked_at ? (
{t("tokens.revoked")}
) : (
{t("tokens.active")}
)}
|
{!token.revoked_at ? (
) : (
)}
|
))}
>
);
}