diff --git a/apps/frontend/app/layout.tsx b/apps/frontend/app/layout.tsx index 9e8c8e9..3adc96f 100644 --- a/apps/frontend/app/layout.tsx +++ b/apps/frontend/app/layout.tsx @@ -19,6 +19,7 @@ export default async function RootLayout({ children }: { children: React.ReactNo Kanal Durumu Segment & Aday Kütüphanesi Ayarlar + Kullanıcılar {session.username}
diff --git a/apps/frontend/app/users/actions.ts b/apps/frontend/app/users/actions.ts new file mode 100644 index 0000000..c5bf115 --- /dev/null +++ b/apps/frontend/app/users/actions.ts @@ -0,0 +1,35 @@ +"use server"; + +import bcrypt from "bcryptjs"; +import { prisma } from "@streamclipper/db"; +import { revalidatePath } from "next/cache"; +import { getSession } from "../../lib/auth"; + +export async function addUser(formData: FormData) { + const username = String(formData.get("username") ?? "").trim(); + const password = String(formData.get("password") ?? ""); + + if (!username || password.length < 8) { + throw new Error("Kullanıcı adı gerekli, şifre en az 8 karakter olmalı."); + } + + const passwordHash = await bcrypt.hash(password, 12); + await prisma.user.create({ data: { username, passwordHash } }); + + revalidatePath("/users"); +} + +export async function deleteUser(userId: string) { + const session = await getSession(); + if (session?.sub === userId) { + throw new Error("Kendi hesabını silemezsin."); + } + + const totalUsers = await prisma.user.count(); + if (totalUsers <= 1) { + throw new Error("Son kalan kullanıcı silinemez."); + } + + await prisma.user.delete({ where: { id: userId } }); + revalidatePath("/users"); +} diff --git a/apps/frontend/app/users/page.tsx b/apps/frontend/app/users/page.tsx new file mode 100644 index 0000000..494e844 --- /dev/null +++ b/apps/frontend/app/users/page.tsx @@ -0,0 +1,66 @@ +import { prisma } from "@streamclipper/db"; +import { getSession } from "../../lib/auth"; +import { addUser, deleteUser } from "./actions"; +import { DeleteButton } from "../components/DeleteButton"; + +export const dynamic = "force-dynamic"; + +const fieldStyle = { + background: "var(--bg)", + border: "1px solid var(--border)", + borderRadius: "6px", + padding: "0.5rem 0.7rem", + color: "var(--text)", + fontSize: "0.9rem", +}; + +export default async function UsersPage() { + const [users, session] = await Promise.all([ + prisma.user.findMany({ orderBy: { createdAt: "asc" } }), + getSession(), + ]); + + return ( + <> +

Kullanıcılar

+ + + + + +
+ + + + + + + + + + + {users.map((u) => ( + + + + + + ))} + +
Kullanıcı AdıOluşturulma
+ {u.username} + {u.id === session?.sub && sen} + {u.createdAt.toLocaleString("tr-TR")} + {u.id !== session?.sub && users.length > 1 && ( +
+ + + )} +
+ + ); +}