Регистрация и вход работают
This commit is contained in:
62
cucumber-frontend/src/API/api.ts
Normal file
62
cucumber-frontend/src/API/api.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import axios, { AxiosError, AxiosRequestHeaders } from 'axios';
|
||||
import IUser from '../models/IUser';
|
||||
import IFarm from '../models/IFarm';
|
||||
import LoginRequest from '../Requests/LoginRequest';
|
||||
import IRegisterRequest from '../Requests/RegisterRequest';
|
||||
|
||||
const API_BASE_URL = 'https://localhost:7113/api';
|
||||
|
||||
const getHeaders = (): { [key: string]: string } => {
|
||||
return {
|
||||
'Content-Type': 'application/json',
|
||||
};
|
||||
};
|
||||
export const getFarms = async (): Promise<IFarm[]> => {
|
||||
try {
|
||||
const response = await axios.get(`${API_BASE_URL}/farms`, { headers: getHeaders() });
|
||||
return response.data;
|
||||
} catch (error: unknown) {
|
||||
const axiosError = error as AxiosError;
|
||||
console.error('Error fetching farms:', axiosError.message);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
export const getUser = async (userId: number): Promise<IUser> => {
|
||||
try {
|
||||
const response = await axios.get(`${API_BASE_URL}/Auth/user/${userId}`, { headers: getHeaders() });
|
||||
return response.data;
|
||||
} catch (error: unknown) {
|
||||
const axiosError = error as AxiosError;
|
||||
console.error('Error fetching user:', axiosError.message);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
export const createUser = async (userData: IRegisterRequest): Promise<IUser> => {
|
||||
try {
|
||||
const response = await axios.post(`${API_BASE_URL}/Auth/register`, userData, { headers: getHeaders() });
|
||||
return response.data;
|
||||
} catch (error: unknown) {
|
||||
const axiosError = error as AxiosError;
|
||||
console.error('Error creating user:', axiosError.message);
|
||||
if (axiosError.response) {
|
||||
// Логируем дополнительные данные об ошибке
|
||||
console.error('Response data:', axiosError.response.data);
|
||||
console.error('Response status:', axiosError.response.status);
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
export const loginUser = async (userData: LoginRequest): Promise<string> => {
|
||||
try {
|
||||
const response = await axios.post(`${API_BASE_URL}/Auth/login`, userData, { headers: getHeaders() });
|
||||
return response.data; // JWT токен
|
||||
} catch (error: unknown) {
|
||||
const axiosError = error as AxiosError;
|
||||
console.error('Error logging in:', axiosError.message);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
@@ -1,11 +1,20 @@
|
||||
import React from 'react';
|
||||
import './App.css';
|
||||
import { Routes } from 'react-router-dom';
|
||||
import { Navigate, Route, Routes } from 'react-router-dom';
|
||||
import {LoginPage} from './pages/Login';
|
||||
import {RegisterPage} from './pages/Register';
|
||||
import {AppLayout} from './components/Layout';
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<div className="App">
|
||||
<Routes>
|
||||
<Route path="/" element={<AppLayout />}>
|
||||
<Route index element={<Navigate to="/login" />} />
|
||||
<Route path="/login" element={<LoginPage />} />
|
||||
<Route path="/register" element={<RegisterPage />} />
|
||||
</Route>
|
||||
|
||||
</Routes>
|
||||
</div>
|
||||
);
|
||||
|
||||
6
cucumber-frontend/src/Requests/LoginRequest.ts
Normal file
6
cucumber-frontend/src/Requests/LoginRequest.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
interface ILoginRequest {
|
||||
email: string;
|
||||
password: string;
|
||||
}
|
||||
|
||||
export default ILoginRequest;
|
||||
7
cucumber-frontend/src/Requests/RegisterRequest.ts
Normal file
7
cucumber-frontend/src/Requests/RegisterRequest.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
interface IRegisterRequest {
|
||||
name: string;
|
||||
email: string;
|
||||
password: string;
|
||||
}
|
||||
|
||||
export default IRegisterRequest;
|
||||
8
cucumber-frontend/src/components/Footer.tsx
Normal file
8
cucumber-frontend/src/components/Footer.tsx
Normal file
@@ -0,0 +1,8 @@
|
||||
export function Footer () {
|
||||
return (
|
||||
<footer className="footer">
|
||||
<p>© {new Date().getFullYear()} Cucumber</p>
|
||||
</footer>
|
||||
);
|
||||
};
|
||||
|
||||
22
cucumber-frontend/src/components/Header.tsx
Normal file
22
cucumber-frontend/src/components/Header.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
export function Header () {
|
||||
return (
|
||||
<header className="header">
|
||||
<div className="logo">
|
||||
<Link to="/">Cucumber App</Link>
|
||||
</div>
|
||||
<nav className="nav">
|
||||
<ul>
|
||||
<li>
|
||||
<Link to="/login">Login</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link to="/register">Register</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
);
|
||||
};
|
||||
19
cucumber-frontend/src/components/Layout.tsx
Normal file
19
cucumber-frontend/src/components/Layout.tsx
Normal file
@@ -0,0 +1,19 @@
|
||||
import React from 'react';
|
||||
import { Layout } from 'antd';
|
||||
import { Outlet } from 'react-router-dom';
|
||||
import {Header} from './Header';
|
||||
import {Footer} from './Footer';
|
||||
|
||||
export function AppLayout () {
|
||||
return (
|
||||
<Layout>
|
||||
<Header />
|
||||
<Layout.Content>
|
||||
<Outlet />
|
||||
</Layout.Content>
|
||||
<Footer />
|
||||
</Layout>
|
||||
);
|
||||
};
|
||||
|
||||
export default AppLayout;
|
||||
@@ -11,3 +11,27 @@ code {
|
||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
||||
monospace;
|
||||
}
|
||||
|
||||
header {
|
||||
text-align: center;
|
||||
background-color: #282c34;
|
||||
min-height: 10vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: calc(10px + 2vmin);
|
||||
color: white;
|
||||
}
|
||||
|
||||
footer {
|
||||
text-align: center;
|
||||
background-color: #282c34;
|
||||
min-height: 10vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: calc(10px + 2vmin);
|
||||
color: white;
|
||||
}
|
||||
11
cucumber-frontend/src/models/IFarm.tsx
Normal file
11
cucumber-frontend/src/models/IFarm.tsx
Normal file
@@ -0,0 +1,11 @@
|
||||
import type IUser from "./IUser";
|
||||
|
||||
interface IFarm {
|
||||
id: string;
|
||||
name: string;
|
||||
userId: number;
|
||||
user: IUser | null;
|
||||
rasberryMacAddr: string;
|
||||
}
|
||||
|
||||
export default IFarm;
|
||||
11
cucumber-frontend/src/models/IUser.tsx
Normal file
11
cucumber-frontend/src/models/IUser.tsx
Normal file
@@ -0,0 +1,11 @@
|
||||
import type IFarm from "./IFarm";
|
||||
|
||||
interface IUser {
|
||||
id: number;
|
||||
name: string;
|
||||
email: string;
|
||||
password: string;
|
||||
farms: IFarm[];
|
||||
}
|
||||
|
||||
export default IUser
|
||||
66
cucumber-frontend/src/pages/Login.tsx
Normal file
66
cucumber-frontend/src/pages/Login.tsx
Normal file
@@ -0,0 +1,66 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Link, useNavigate } from 'react-router-dom';
|
||||
import { Button, Form, Input } from 'antd';
|
||||
import { loginUser } from '../API/api';
|
||||
import ILoginRequest from '../Requests/LoginRequest';
|
||||
|
||||
export function LoginPage () {
|
||||
const [email, setEmail] = useState('');
|
||||
const [password, setPassword] = useState('');
|
||||
const navigate = useNavigate();
|
||||
|
||||
const onFinish = async () => {
|
||||
// Создаём объект с данными для отправки на сервер
|
||||
const userData: ILoginRequest = {
|
||||
email,
|
||||
password,
|
||||
};
|
||||
|
||||
try {
|
||||
const token = await loginUser(userData);
|
||||
// Сохраняем токен
|
||||
localStorage.setItem('token', token);
|
||||
alert('Вы успешно вошли в систему!');
|
||||
navigate('/'); // Перенаправляем на главную страницу
|
||||
} catch (error) {
|
||||
console.error('Error logging in:', error);
|
||||
alert('Ошибка при входе в систему. Проверьте введенные данные.');
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="login-page">
|
||||
<h1>Login</h1>
|
||||
<Form onFinish={onFinish}>
|
||||
<Form.Item
|
||||
label="Email"
|
||||
name="email"
|
||||
rules={[{ required: true, type: 'email', message: 'Пожалуйста, введите корректный email!' }]}
|
||||
>
|
||||
<Input value={email} onChange={e => setEmail(e.target.value)} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label="Password"
|
||||
name="password"
|
||||
rules={[{ required: true, min: 8, message: 'Пароль должен содержать не менее 8 символов!' }]}
|
||||
>
|
||||
<Input
|
||||
type="password"
|
||||
value={password}
|
||||
onChange={e => setPassword(e.target.value)}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item>
|
||||
<Button type="primary" htmlType="submit">
|
||||
Войти
|
||||
</Button>
|
||||
</Form.Item>
|
||||
<p>
|
||||
Нет аккаунта? <Link to="/register">Зарегистрируйтесь</Link>
|
||||
</p>
|
||||
</Form>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default LoginPage;
|
||||
70
cucumber-frontend/src/pages/Register.tsx
Normal file
70
cucumber-frontend/src/pages/Register.tsx
Normal file
@@ -0,0 +1,70 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Link, useNavigate } from 'react-router-dom';
|
||||
import { Button, Form, Input } from 'antd';
|
||||
import { createUser } from '../API/api';
|
||||
import IRegisterRequest from '../Requests/RegisterRequest';
|
||||
|
||||
export function RegisterPage () {
|
||||
const [name, setName] = useState('');
|
||||
const [email, setEmail] = useState('');
|
||||
const [password, setPassword] = useState('');
|
||||
const navigate = useNavigate();
|
||||
|
||||
const handleFinish = async () => {
|
||||
// Create the user data object to send to the API
|
||||
const userData: IRegisterRequest = {
|
||||
name,
|
||||
email,
|
||||
password,
|
||||
};
|
||||
|
||||
try {
|
||||
if (!navigator.onLine) {
|
||||
alert('No internet connection');
|
||||
return;
|
||||
}
|
||||
const response = await createUser(userData); // Pass the userData object
|
||||
|
||||
if (response) {
|
||||
navigate('/login'); // Redirect to the login page after successful registration
|
||||
alert('Пользователь успешно зарегестрирован!');
|
||||
} else {
|
||||
console.error('Error registering:');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error registering:', error);
|
||||
alert('Error registering');
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="register-page">
|
||||
<h1>Register</h1>
|
||||
<Form onFinish={handleFinish}>
|
||||
<Form.Item label="Name" name="name" rules={[{ required: true, message: 'Пожалуйста, введите имя!' }]}>
|
||||
<Input value={name} onChange={e => setName(e.target.value)} />
|
||||
</Form.Item>
|
||||
<Form.Item label="Email" name="email" rules={[{ required: true, type: 'email', message: 'Пожалуйста, введите корректный адрес почты!' }]}>
|
||||
<Input value={email} onChange={e => setEmail(e.target.value)} />
|
||||
</Form.Item>
|
||||
<Form.Item label="Password" name="password" rules={[{ required: true, min: 8, message: 'Пароль должен содержать не менее 8 символов!' }]}>
|
||||
<Input
|
||||
type="password"
|
||||
value={password}
|
||||
onChange={e => setPassword(e.target.value)}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item>
|
||||
<Button type="primary" htmlType="submit">
|
||||
Регистрация
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
<p>
|
||||
Уже есть аккаунт? <Link to="/login">Войдите</Link>
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default RegisterPage;
|
||||
Reference in New Issue
Block a user