diff --git a/src/app/(student)/layout.tsx b/src/app/(student)/layout.tsx index 52aa8c7..3f1b92d 100644 --- a/src/app/(student)/layout.tsx +++ b/src/app/(student)/layout.tsx @@ -44,7 +44,9 @@ export default async function StudentLayout({ children }: { children: React.Reac {schoolName}
- {session.user.name} + + {session.user.name} +
diff --git a/src/app/(student)/profile/change-password-form.tsx b/src/app/(student)/profile/change-password-form.tsx new file mode 100644 index 0000000..9aa6e49 --- /dev/null +++ b/src/app/(student)/profile/change-password-form.tsx @@ -0,0 +1,121 @@ +"use client"; + +import { useState } from "react"; +import { authClient } from "@/lib/auth-client"; + +const inputStyle: React.CSSProperties = { + border: "2px solid var(--border)", + color: "var(--foreground)", + fontFamily: "var(--font-sans)", + outline: "none", +}; + +export function ChangePasswordForm() { + const [current, setCurrent] = useState(""); + const [next, setNext] = useState(""); + const [confirm, setConfirm] = useState(""); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(""); + const [success, setSuccess] = useState(false); + + async function handleSubmit(e: React.FormEvent) { + e.preventDefault(); + setError(""); + setSuccess(false); + + if (next !== confirm) { + setError("Пароли не совпадают"); + return; + } + if (next.length < 8) { + setError("Новый пароль должен быть не короче 8 символов"); + return; + } + + setLoading(true); + const result = await authClient.changePassword({ + currentPassword: current, + newPassword: next, + revokeOtherSessions: false, + }); + setLoading(false); + + if (result.error) { + setError("Неверный текущий пароль"); + return; + } + + setCurrent(""); + setNext(""); + setConfirm(""); + setSuccess(true); + } + + return ( +
+
+ + setCurrent(e.target.value)} + required + className="w-full px-3 py-2 text-sm bg-transparent" + style={inputStyle} + onFocus={(e) => (e.target.style.borderColor = "var(--foreground)")} + onBlur={(e) => (e.target.style.borderColor = "var(--border)")} + placeholder="••••••••" + /> +
+
+ + setNext(e.target.value)} + required + minLength={8} + className="w-full px-3 py-2 text-sm bg-transparent" + style={inputStyle} + onFocus={(e) => (e.target.style.borderColor = "var(--foreground)")} + onBlur={(e) => (e.target.style.borderColor = "var(--border)")} + placeholder="Минимум 8 символов" + /> +
+
+ + setConfirm(e.target.value)} + required + className="w-full px-3 py-2 text-sm bg-transparent" + style={inputStyle} + onFocus={(e) => (e.target.style.borderColor = "var(--foreground)")} + onBlur={(e) => (e.target.style.borderColor = "var(--border)")} + placeholder="••••••••" + /> +
+ {error && ( +

{error}

+ )} + {success && ( +

Пароль успешно изменён.

+ )} + +
+ ); +} diff --git a/src/app/(student)/profile/page.tsx b/src/app/(student)/profile/page.tsx new file mode 100644 index 0000000..6e7c0a0 --- /dev/null +++ b/src/app/(student)/profile/page.tsx @@ -0,0 +1,42 @@ +import { headers } from "next/headers"; +import { auth } from "@/lib/auth"; +import { redirect } from "next/navigation"; +import { ChangePasswordForm } from "./change-password-form"; + +export const metadata = { title: "Профиль" }; + +export default async function ProfilePage() { + const session = await auth.api.getSession({ headers: await headers() }); + if (!session) redirect("/login"); + + return ( +
+

+ Профиль +

+ +
+

+ Аккаунт +

+
+
+ Имя + {session.user.name} +
+
+ Email + {session.user.email} +
+
+
+ +
+

+ Смена пароля +

+ +
+
+ ); +}