|
@@ -1,8 +1,135 @@
|
|
|
|
|
+import {Button} from "primereact/button";
|
|
|
|
|
+import {InputText} from "primereact/inputtext";
|
|
|
|
|
+import {Navigate, useNavigate} from "react-router-dom";
|
|
|
|
|
+import {useEffect, useRef, useState} from "react";
|
|
|
|
|
+import {Toast} from "primereact/toast";
|
|
|
|
|
+import {SPRING_SERVER} from "../config";
|
|
|
|
|
+import jwt_decode from "jwt-decode";
|
|
|
|
|
+import authorizedFetch from "../Utils";
|
|
|
|
|
+import {useTranslation} from "react-i18next";
|
|
|
|
|
+import {ReCAPTCHA} from "react-google-recaptcha";
|
|
|
|
|
+
|
|
|
export default function () {
|
|
export default function () {
|
|
|
|
|
+ const navigate = useNavigate();
|
|
|
|
|
+ const [login, setLogin] = useState("");
|
|
|
|
|
+ const [password, setPassword] = useState("");
|
|
|
|
|
+ const [login2, setLogin2] = useState("");
|
|
|
|
|
+ const [password2, setPassword2] = useState("");
|
|
|
|
|
+ const [email, setEmail] = useState("");
|
|
|
|
|
+ const [recaptchaValue, setRecaptchaValue] = useState('');
|
|
|
|
|
+
|
|
|
|
|
+ const handleRecaptchaChange = (value) => {
|
|
|
|
|
+ setRecaptchaValue(value);
|
|
|
|
|
+ };
|
|
|
|
|
+ useEffect(() => {
|
|
|
|
|
+ window.handleRecaptchaChange = handleRecaptchaChange;
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ const my_toast = useRef(null)
|
|
|
|
|
+ const { t } = useTranslation(); // Initialize the hook
|
|
|
|
|
+
|
|
|
|
|
+ if (localStorage.getItem("access_token")) {
|
|
|
|
|
+ return <Navigate to="/home" replace/>
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function onLoginClick() {
|
|
|
|
|
+ fetch(SPRING_SERVER + '/login', {
|
|
|
|
|
+ method: 'POST', headers: {
|
|
|
|
|
+ 'Content-Type': 'application/json'
|
|
|
|
|
+ }, body: JSON.stringify({
|
|
|
|
|
+ 'login': login, 'password': password,'captcha': recaptchaValue,
|
|
|
|
|
+
|
|
|
|
|
+ })
|
|
|
|
|
+ })
|
|
|
|
|
+ .then(response => {
|
|
|
|
|
+ if (!response.ok) {
|
|
|
|
|
+ my_toast.current.show({severity: 'error', summary: 'Error Message', detail: 'Validation failed'});
|
|
|
|
|
+ throw new Error(response.status)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ return response.json()
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ .then((data) => {
|
|
|
|
|
+ var decoded = jwt_decode(data);
|
|
|
|
|
+ console.log(decoded)
|
|
|
|
|
+ localStorage.setItem("access_token", data)
|
|
|
|
|
+ localStorage.setItem("expires_at", (parseInt(decoded.exp) * 1000).toString())
|
|
|
|
|
+ })
|
|
|
|
|
+ .then(() => {
|
|
|
|
|
+ if (localStorage.getItem("access_token")) return navigate("/home")
|
|
|
|
|
+ })
|
|
|
|
|
+ .catch((e) => console.log(e))
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function onRegisterClick() {
|
|
|
|
|
+ fetch(SPRING_SERVER + '/register', {
|
|
|
|
|
+ method: 'POST', headers: {
|
|
|
|
|
+ 'Content-Type': 'application/json'
|
|
|
|
|
+ }, body: JSON.stringify({
|
|
|
|
|
+ 'login': login2, 'password': password2, 'email': email
|
|
|
|
|
+ })
|
|
|
|
|
+ }).then(response => {
|
|
|
|
|
+ if (!response.ok)
|
|
|
|
|
+ my_toast.current.show({severity: 'error', summary: 'Error Message', detail: 'Validation failed'});
|
|
|
|
|
+ else
|
|
|
|
|
+ my_toast.current.show({severity: 'success', summary: 'Success', detail: 'Account created'});
|
|
|
|
|
+
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return (<div style={{display: 'flex', alignItems: 'center', justifyContent: 'center', height: '100vh'}}
|
|
|
|
|
+ className="bg-blue-500 flex flex-row">
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ <Toast ref={my_toast}></Toast>
|
|
|
|
|
+
|
|
|
|
|
+ <div className="surface-card p-4 shadow-2 border-round flex flex-column w-3 mx-2">
|
|
|
|
|
+ <div className="text-3xl font-medium text-900 mb-2">{t('lpanel')}</div>
|
|
|
|
|
+ <div className="font-medium text-500 mb-3">{t('ldesc')}</div>
|
|
|
|
|
+
|
|
|
|
|
+ <span className="p-input-icon-left py-1 ">
|
|
|
|
|
+ <i className="pi pi-user"/>
|
|
|
|
|
+ <InputText placeholder={t('username')} onChange={(e) => setLogin(e.target.value)}
|
|
|
|
|
+ className="min-w-full max-w-full"/>
|
|
|
|
|
+ </span>
|
|
|
|
|
+ <span className="p-input-icon-left py-1">
|
|
|
|
|
+ <i className="pi pi-key"/>
|
|
|
|
|
+ <InputText type="password" placeholder={t('password')} onChange={(e) => setPassword(e.target.value)}
|
|
|
|
|
+ className="min-w-full max-w-full"/>
|
|
|
|
|
+ </span>
|
|
|
|
|
+ <div className="g-recaptcha" data-sitekey="SITE_KEY" data-callback="handleRecaptchaChange"></div>
|
|
|
|
|
+
|
|
|
|
|
+ <div className="flex justify-content-end pt-2">
|
|
|
|
|
+ <Button onClick={onLoginClick}>{t('login')}</Button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div className="surface-card p-4 shadow-2 border-round flex flex-column w-3 mx-2">
|
|
|
|
|
+ <div className="text-3xl font-medium text-900 mb-2">{t('rpanel')}</div>
|
|
|
|
|
+ <div className="font-medium text-500 mb-3">{t('rdesc')}</div>
|
|
|
|
|
+
|
|
|
|
|
+ <span className="p-input-icon-left py-1 ">
|
|
|
|
|
+ <i className="pi pi-user"/>
|
|
|
|
|
+ <InputText placeholder={t('username')} onChange={(e) => setLogin2(e.target.value)}
|
|
|
|
|
+ className="min-w-full max-w-full"/>
|
|
|
|
|
+ </span>
|
|
|
|
|
+ <span className="p-input-icon-left py-1 ">
|
|
|
|
|
+ <i className="pi pi-envelope"/>
|
|
|
|
|
+ <InputText placeholder="Email" onChange={(e) => setEmail(e.target.value)}
|
|
|
|
|
+ className="min-w-full max-w-full"/>
|
|
|
|
|
+ </span>
|
|
|
|
|
+ <span className="p-input-icon-left py-1">
|
|
|
|
|
+ <i className="pi pi-key"/>
|
|
|
|
|
+ <InputText type="password" placeholder={t('password')} onChange={(e) => setPassword2(e.target.value)}
|
|
|
|
|
+ className="min-w-full max-w-full"/>
|
|
|
|
|
+ </span>
|
|
|
|
|
+ <div className="flex justify-content-end pt-2">
|
|
|
|
|
+ <Button onClick={onRegisterClick}>{t('register')}</Button>
|
|
|
|
|
+ </div>
|
|
|
|
|
|
|
|
- return (
|
|
|
|
|
- <div>
|
|
|
|
|
- hello
|
|
|
|
|
- </div>
|
|
|
|
|
- )
|
|
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>)
|
|
|
}
|
|
}
|