diff options
| author | l3wdfut4pwr <l3wdfut4pwr@gmail.com> | 2026-04-27 13:45:25 +0300 |
|---|---|---|
| committer | l3wdfut4pwr <l3wdfut4pwr@gmail.com> | 2026-04-27 13:45:25 +0300 |
| commit | ab330c64eeed9edfc2a6ef6a6f5cd38587ba0996 (patch) | |
| tree | 9ca46c6552e427a9461387dc63362be0f9301acb /src/components | |
| parent | c7d2526afec5ffb8918c20d7c1c58852f1c647bd (diff) | |
add username change and logout
Diffstat (limited to 'src/components')
| -rw-r--r-- | src/components/header/authdialog/LoginForm.tsx | 1 | ||||
| -rw-r--r-- | src/components/header/authdialog/register.ts | 29 | ||||
| -rw-r--r-- | src/components/settings/AboutMe.tsx | 6 | ||||
| -rw-r--r-- | src/components/settings/AccountButton.tsx | 17 | ||||
| -rw-r--r-- | src/components/settings/LogoutButton.tsx | 31 | ||||
| -rw-r--r-- | src/components/settings/ProfilePage.tsx | 19 | ||||
| -rw-r--r-- | src/components/settings/SecurityPage.tsx | 4 | ||||
| -rw-r--r-- | src/components/settings/changeusername.tsx | 41 |
8 files changed, 115 insertions, 33 deletions
diff --git a/src/components/header/authdialog/LoginForm.tsx b/src/components/header/authdialog/LoginForm.tsx index 1dc2df4..b4d90f1 100644 --- a/src/components/header/authdialog/LoginForm.tsx +++ b/src/components/header/authdialog/LoginForm.tsx @@ -48,6 +48,7 @@ export default function LoginForm({ redirectTo }: { redirectTo?: string }) { if (!res.ok) { setErrors({ general: 'Неверный логин или пароль' }); + return; } else { const meRes = await fetch(`${API_URL}/api/me`, { credentials: 'include', diff --git a/src/components/header/authdialog/register.ts b/src/components/header/authdialog/register.ts index 3098df7..031fa69 100644 --- a/src/components/header/authdialog/register.ts +++ b/src/components/header/authdialog/register.ts @@ -52,29 +52,38 @@ export const registerUser = async ( credentials: 'include', }); - if (!res.ok) { - const errorData = await res.json(); + let data: any = null; + + try { + data = await res.json(); + } catch { + data = null; + } - const { field, message } = errorData.detail || {}; + if (!res.ok) { + const detail = data?.detail; return { data: null, - error: field - ? { [field]: message } - : { general: 'Ошибка регистрации' }, + error: detail?.field + ? { [detail.field]: detail.message } + : { general: detail?.message || 'Ошибка регистрации' }, }; } - const user = await res.json(); - return { - data: user, + data, error: null, }; } catch (err: any) { return { data: null, - error: { general: err.message }, + error: { + general: + err?.message === 'Failed to fetch' + ? 'Нет соединения с сервером' + : err?.message || 'Network error', + }, }; } }; diff --git a/src/components/settings/AboutMe.tsx b/src/components/settings/AboutMe.tsx index b065a26..769885a 100644 --- a/src/components/settings/AboutMe.tsx +++ b/src/components/settings/AboutMe.tsx @@ -1,10 +1,12 @@ import { useState } from 'react'; - +import { ChangeEvent } from 'react'; +import { Input } from '@/components/ui/input'; +import { Button } from '@/components/ui/button'; export default function AboutMe() { const maxLength = 250; const [text, setText] = useState(''); - const handleChange = (e) => { + const handleChange = (e: ChangeEvent<HTMLInputElement>) => { const value = e.target.value; if (value.length <= maxLength) { diff --git a/src/components/settings/AccountButton.tsx b/src/components/settings/AccountButton.tsx deleted file mode 100644 index ecd0eb4..0000000 --- a/src/components/settings/AccountButton.tsx +++ /dev/null @@ -1,17 +0,0 @@ -'use client'; - -import Link from 'next/link'; -import { Button } from '@/components/ui'; -import { useUser } from '@/lib/contexts/Auth.context'; - -export default function AccountButton() { - const user = useUser(); - - if (!user) return null; - - return ( - <Button> - <Link href="/settings">Управление аккаунтом</Link> - </Button> - ); -} diff --git a/src/components/settings/LogoutButton.tsx b/src/components/settings/LogoutButton.tsx new file mode 100644 index 0000000..22cbb27 --- /dev/null +++ b/src/components/settings/LogoutButton.tsx @@ -0,0 +1,31 @@ +'use client'; + +import { Button } from '@/components/ui/button'; +import { useAuthContext } from '@/lib/contexts/Auth.context'; +import { useRouter } from 'next/navigation'; +import { useState } from 'react'; + +export default function LogoutButton() { + const { logout } = useAuthContext(); + const router = useRouter(); + const [loading, setLoading] = useState(false); + + const handleLogout = async () => { + if (loading) return; + + setLoading(true); + + try { + await logout(); + router.push('/'); + } finally { + setLoading(false); + } + }; + + return ( + <Button className="w-[310px]" onClick={handleLogout} disabled={loading}> + {loading ? 'Выход...' : 'Выйти из аккаунта'} + </Button> + ); +} diff --git a/src/components/settings/ProfilePage.tsx b/src/components/settings/ProfilePage.tsx index cac8e7e..75370d2 100644 --- a/src/components/settings/ProfilePage.tsx +++ b/src/components/settings/ProfilePage.tsx @@ -1,16 +1,31 @@ import { InputField } from '@/components/ui/inputfield'; import { Button } from '@/components/ui'; import { Separator } from '@/components/ui'; +import { changeUsername } from './changeusername'; import { useState } from 'react'; export default function ProfilePage() { const maxLength = 250; const [about, setAbout] = useState(''); + const [username, setUsername] = useState(''); + const [usernameLoading, setUsernameLoading] = useState(false); return ( <div className="flex flex-col flex-start gap-[20px] w-[900px] h-[804px]"> <div className="flex flex-col flex-start gap-[10px] w-[310px] h-[123px]"> <p className="font-medium gap-[10px] ml-[20px]">НИКНЕЙМ</p> - <InputField placeholder="Введите никнейм" /> - <Button className="w-[105px]">Сменить</Button> + + <InputField + placeholder="Введите никнейм" + value={username} + onChange={(e: any) => setUsername(e.target.value)} + /> + + <Button + className="w-[105px]" + onClick={() => changeUsername(username)} + disabled={usernameLoading} + > + {usernameLoading ? '...' : 'Сменить'} + </Button> </div> <Separator className="bg-violet/50 h-[1px]" /> <div className="flex flex-col flex-start gap-[10px] w-[600px] h-[284px]"> diff --git a/src/components/settings/SecurityPage.tsx b/src/components/settings/SecurityPage.tsx index d9079df..b5f38a9 100644 --- a/src/components/settings/SecurityPage.tsx +++ b/src/components/settings/SecurityPage.tsx @@ -2,7 +2,7 @@ import { InputField } from '@/components/ui/inputfield'; import { Button } from '@/components/ui'; import { Separator } from '@/components/ui'; import { useAuthContext } from '@/lib/contexts/Auth.context'; - +import LogoutButton from './LogoutButton'; export default function SecurityPage() { const { user } = useAuthContext(); @@ -87,7 +87,7 @@ export default function SecurityPage() { <Separator className="bg-violet/30 h-[1px]" /> </div> )} - <Button className="w-[310px]">Выйти из аккаунта</Button> + <LogoutButton /> </div> </div> </> diff --git a/src/components/settings/changeusername.tsx b/src/components/settings/changeusername.tsx new file mode 100644 index 0000000..c8527c4 --- /dev/null +++ b/src/components/settings/changeusername.tsx @@ -0,0 +1,41 @@ +const API_URL = process.env.NEXT_PUBLIC_API_URL; + +export const changeUsername = async (username: string) => { + try { + const res = await fetch(`${API_URL}/api/users/change-username`, { + method: 'PATCH', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ username }), + credentials: 'include', + }); + + if (!res.ok) { + let errorData: any = null; + + try { + errorData = await res.json(); + } catch {} + + return { + data: null, + error: { + general: errorData?.detail || 'Ошибка изменения никнейма', + }, + }; + } + + const data = await res.json(); + + return { + data, + error: null, + }; + } catch (err: any) { + return { + data: null, + error: { general: err.message }, + }; + } +}; |
