summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorl3wdfut4pwr <l3wdfut4pwr@gmail.com>2026-04-02 08:36:51 +0300
committerl3wdfut4pwr <l3wdfut4pwr@gmail.com>2026-04-02 08:36:51 +0300
commit1d20080db8a26e4b7dd4071daac1166142592afa (patch)
treeb4c1bbb3725f00515b4d9a3d1cd18584cba36c81 /src
parent37f51ee88710868a77b4645294cf32862f55e7c4 (diff)
minor improvements
Diffstat (limited to 'src')
-rw-r--r--src/app/premium/page.tsx3
-rw-r--r--src/components/header/AuthDialog.tsx6
-rw-r--r--src/components/header/authdialog/LoginForm.tsx22
-rw-r--r--src/components/header/authdialog/register.ts39
-rw-r--r--src/components/ui/inputfield.tsx6
-rw-r--r--src/components/upload/SourceInput.tsx3
-rw-r--r--src/components/upload/TagsInput.tsx1
-rw-r--r--src/lib/contexts/Auth.context.tsx42
-rw-r--r--src/lib/contexts/Global.context.tsx2
9 files changed, 61 insertions, 63 deletions
diff --git a/src/app/premium/page.tsx b/src/app/premium/page.tsx
new file mode 100644
index 0000000..17cee81
--- /dev/null
+++ b/src/app/premium/page.tsx
@@ -0,0 +1,3 @@
+export default function Premium() {
+ return null;
+}
diff --git a/src/components/header/AuthDialog.tsx b/src/components/header/AuthDialog.tsx
index 0b4bc74..8c00b81 100644
--- a/src/components/header/AuthDialog.tsx
+++ b/src/components/header/AuthDialog.tsx
@@ -1,5 +1,5 @@
import { Button } from '@/components/ui/button';
-import { DialogContent } from '@/components/ui/dialog';
+import { DialogContent, DialogTitle } from '@/components/ui/dialog';
import { Input } from '@/components/ui/input';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import GoogleIcon from '../../../public/icons/google.svg';
@@ -7,10 +7,14 @@ import { InputField } from '../ui/inputfield';
import LoginForm from './authdialog/LoginForm';
import RegisterForm from './authdialog/RegisterForm';
import ResetForm from './authdialog/ResetForm';
+import { VisuallyHidden } from '@radix-ui/react-visually-hidden';
export function AuthDialog() {
return (
<div className="absolute">
<DialogContent className="w-[350px] p-0 bg-transparent border-transparent">
+ <VisuallyHidden>
+ <DialogTitle>Authentication</DialogTitle>
+ </VisuallyHidden>
<Tabs defaultValue="Login">
<div className="flex flex-col gap-[5px] ">
<TabsList className="w-[350px] h-[36px] justify-between bg-background border border-violet rounded-[15px]">
diff --git a/src/components/header/authdialog/LoginForm.tsx b/src/components/header/authdialog/LoginForm.tsx
index ceadbcd..c6cdbcd 100644
--- a/src/components/header/authdialog/LoginForm.tsx
+++ b/src/components/header/authdialog/LoginForm.tsx
@@ -6,6 +6,7 @@ import { InputField } from '@/components/ui/inputfield';
import { useAuthContext } from '@/lib/contexts/Auth.context';
export default function LoginForm() {
+ const API_URL = process.env.NEXT_PUBLIC_API_URL;
const [errors, setErrors] = useState<any>({});
const [loading, setLoading] = useState(false);
const { setUser } = useAuthContext();
@@ -36,27 +37,27 @@ export default function LoginForm() {
body.append('password', password);
try {
- const res = await fetch('http://localhost:8000/api/auth/login', {
+ const res = await fetch(`${API_URL}/api/auth/login`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: body.toString(),
+ credentials: 'include',
});
- const data = await res.json();
-
if (!res.ok) {
setErrors({ general: 'Неверный логин или пароль' });
- } else if (data.access_token) {
- localStorage.setItem('token', data.access_token);
-
- const meRes = await fetch('http://localhost:8000/api/me', {
- headers: { Authorization: `Bearer ${data.access_token}` },
+ } else {
+ const meRes = await fetch(`${API_URL}/api/me`, {
+ credentials: 'include',
});
+ if (!meRes.ok) throw new Error('Failed to fetch user');
const meData = await meRes.json();
setUser(meData);
}
+ } catch (err) {
+ setErrors({ general: 'Ошибка при авторизации' });
} finally {
setLoading(false);
}
@@ -91,11 +92,6 @@ export default function LoginForm() {
placeholder="Пароль"
name="password"
/>
- {errors.password && (
- <p className="text-red pl-5 text-[12px] leading-[16px] mt-[5px]">
- {errors.password}
- </p>
- )}
{!errors.password && errors.general && (
<p className="text-red pl-5 text-[12px] leading-[16px] mt-[5px]">
{errors.general}
diff --git a/src/components/header/authdialog/register.ts b/src/components/header/authdialog/register.ts
index ba8bceb..46a59f2 100644
--- a/src/components/header/authdialog/register.ts
+++ b/src/components/header/authdialog/register.ts
@@ -1,4 +1,3 @@
-// register.ts
export const validate = (
username: string,
email: string,
@@ -36,20 +35,23 @@ export const validate = (
return newErrors;
};
+const API_URL = process.env.NEXT_PUBLIC_API_URL;
+
export const registerUser = async (
username: string,
email: string,
password: string,
) => {
try {
- const res = await fetch('http://localhost:8000/api/auth/register', {
+ const res = await fetch(`${API_URL}/api/auth/register`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username, email, password }),
+ credentials: 'include',
});
- const data = await res.json();
if (!res.ok) {
+ const data = await res.json();
const { field, message } = data.detail || {};
return {
data: null,
@@ -59,35 +61,16 @@ export const registerUser = async (
};
}
- const body = new URLSearchParams();
- body.append('username', username);
- body.append('password', password);
-
- const loginRes = await fetch('http://localhost:8000/api/auth/login', {
- method: 'POST',
- headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
- body: body.toString(),
+ const meRes = await fetch(`${API_URL}/api/me`, {
+ credentials: 'include',
});
- const loginData = await loginRes.json();
-
- if (!loginRes.ok) {
- return {
- data: null,
- error: {
- general:
- loginData.detail || 'Ошибка входа после регистрации',
- },
- };
+ if (!meRes.ok) {
+ throw new Error(
+ 'Не удалось получить данные пользователя после регистрации',
+ );
}
- localStorage.setItem('token', loginData.access_token);
- localStorage.setItem('refresh_token', loginData.refresh_token);
-
- const meRes = await fetch('http://localhost:8000/api/me', {
- headers: { Authorization: `Bearer ${loginData.access_token}` },
- });
-
const meData = await meRes.json();
return { data: meData, error: null };
diff --git a/src/components/ui/inputfield.tsx b/src/components/ui/inputfield.tsx
index 6b585a9..991aca0 100644
--- a/src/components/ui/inputfield.tsx
+++ b/src/components/ui/inputfield.tsx
@@ -1,7 +1,11 @@
import { Input } from '@/components/ui/input';
import React from 'react';
-export function InputField(props: React.InputHTMLAttributes<HTMLInputElement>) {
+type InputFieldProps = React.InputHTMLAttributes<HTMLInputElement> & {
+ isPassword?: boolean;
+};
+
+export function InputField(props: InputFieldProps) {
return (
<div className="rounded-[20px] border-violet border-[2px] h-[39px] flex items-center justify-between py-[10px] px-[20px]">
<Input
diff --git a/src/components/upload/SourceInput.tsx b/src/components/upload/SourceInput.tsx
index c93c4b6..fbc8f52 100644
--- a/src/components/upload/SourceInput.tsx
+++ b/src/components/upload/SourceInput.tsx
@@ -1,5 +1,6 @@
'use client';
import { Input } from '@/components/ui';
+import React from 'react';
export function SourceInput() {
return (
@@ -7,7 +8,7 @@ export function SourceInput() {
<span>ИСТОЧНИК</span>
<Input
name="source"
- onKeyDown={(e) => {
+ onKeyDown={(e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === 'Enter') {
e.preventDefault();
}
diff --git a/src/components/upload/TagsInput.tsx b/src/components/upload/TagsInput.tsx
index 1b88fa2..cdff794 100644
--- a/src/components/upload/TagsInput.tsx
+++ b/src/components/upload/TagsInput.tsx
@@ -72,7 +72,6 @@ class RemoveTag extends React.Component {
onClick={onRemove}
className={className}
onFocus={(e) => {
- // Это говно здесь из-за того, что без него после удаления бэкспейсом, фокусится крестик
document.getElementById('tags-input')?.focus();
}}
>
diff --git a/src/lib/contexts/Auth.context.tsx b/src/lib/contexts/Auth.context.tsx
index 29e2005..fbf2e24 100644
--- a/src/lib/contexts/Auth.context.tsx
+++ b/src/lib/contexts/Auth.context.tsx
@@ -1,39 +1,49 @@
'use client';
import React, { createContext, useState, useContext, useEffect } from 'react';
-type User = {
+export type User = {
id: number;
username: string;
+ avatar?: string;
+ banner_file?: string;
+ premium?: boolean;
+ is_banned?: boolean;
+ is_moderator?: boolean;
};
-
interface AuthContextType {
user: User | null;
setUser: (user: User | null) => void;
logout: () => void;
}
-
const AuthContext = createContext<AuthContextType | null>(null);
+const API_URL = process.env.NEXT_PUBLIC_API_URL;
export const AuthContextProvider = ({ children }: React.PropsWithChildren) => {
const [user, setUser] = useState<User | null>(null);
useEffect(() => {
- const token = localStorage.getItem('token');
- if (!token) return;
+ const fetchUser = async () => {
+ const hasCookies = document.cookie.includes('access_token');
+ if (!hasCookies) return;
+
+ try {
+ const res = await fetch(`${API_URL}/api/me`, {
+ credentials: 'include',
+ });
+ if (!res.ok) return;
+ const userData = await res.json();
+ setUser(userData);
+ } catch {}
+ };
- fetch('http://localhost:8000/api/me', {
- headers: { Authorization: `Bearer ${token}` },
- })
- .then((res) => {
- if (!res.ok) throw new Error('Not authenticated');
- return res.json();
- })
- .then((userData) => setUser(userData))
- .catch(() => setUser(null));
+ fetchUser();
}, []);
- const logout = () => {
- localStorage.removeItem('token');
+ const logout = async () => {
+ await fetch(`${API_URL}/api/auth/logout`, {
+ method: 'POST',
+ credentials: 'include',
+ });
setUser(null);
};
diff --git a/src/lib/contexts/Global.context.tsx b/src/lib/contexts/Global.context.tsx
index c903456..3f8b61b 100644
--- a/src/lib/contexts/Global.context.tsx
+++ b/src/lib/contexts/Global.context.tsx
@@ -1,5 +1,3 @@
-import react from 'react';
-import { authcontextprovider } from './auth.context';
import React from 'react';
import { AuthContextProvider } from './Auth.context';