Переглянути джерело

User registeration and auth completed

master
kj1352 4 роки тому
джерело
коміт
fad0041232
5 змінених файлів з 207 додано та 8 видалено
  1. +71
    -6
      package-lock.json
  2. +1
    -0
      package.json
  3. +4
    -0
      src/App.tsx
  4. +20
    -2
      src/components/auth/Login.tsx
  5. +111
    -0
      src/components/auth/Signup.tsx

+ 71
- 6
package-lock.json Переглянути файл

@@ -18,6 +18,7 @@
"@types/node": "^12.20.15",
"@types/react": "^17.0.13",
"@types/react-dom": "^17.0.8",
"axios": "^0.23.0",
"moment": "^2.29.1",
"node-sass": "^6.0.1",
"query-string": "^7.0.1",
@@ -3725,6 +3726,15 @@
"pretty-format": "^26.0.0"
}
},
"node_modules/@types/jquery": {
"version": "3.5.8",
"resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.8.tgz",
"integrity": "sha512-cXk6NwqjDYg+UI9p2l3x0YmPa4m7RrXqmbK4IpVVpRJiYXU/QTo+UZrn54qfE1+9Gao4qpYqUnxm5ZCy2FTXAw==",
"dev": true,
"dependencies": {
"@types/sizzle": "*"
}
},
"node_modules/@types/json-schema": {
"version": "7.0.7",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz",
@@ -3827,6 +3837,12 @@
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.1.tgz",
"integrity": "sha512-EaCxbanVeyxDRTQBkdLb3Bvl/HK7PBK6UJjsSixB0iHKoWxE5uu2Q/DgtpOhPIojN0Zl1whvOd7PoHs2P0s5eA=="
},
"node_modules/@types/sizzle": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz",
"integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==",
"dev": true
},
"node_modules/@types/source-list-map": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz",
@@ -3850,6 +3866,15 @@
"@types/jest": "*"
}
},
"node_modules/@types/toastr": {
"version": "2.1.39",
"resolved": "https://registry.npmjs.org/@types/toastr/-/toastr-2.1.39.tgz",
"integrity": "sha512-jgbMLTjj7dsSY/EYYOoZXhK6OY/bR909Bn6YNnwL3Oq+f0AeFKbYa198XU/6bsmUqqCCWw5VvCi11FDN1/fetw==",
"dev": true,
"dependencies": {
"@types/jquery": "*"
}
},
"node_modules/@types/uglify-js": {
"version": "3.13.1",
"resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.13.1.tgz",
@@ -4805,6 +4830,14 @@
"node": ">=4"
}
},
"node_modules/axios": {
"version": "0.23.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.23.0.tgz",
"integrity": "sha512-NmvAE4i0YAv5cKq8zlDoPd1VLKAqX5oLuZKs8xkJa4qi6RGn0uhCYFjWtHHC9EM/MwOwYWOs53W+V0aqEXq1sg==",
"dependencies": {
"follow-redirects": "^1.14.4"
}
},
"node_modules/axobject-query": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz",
@@ -9432,9 +9465,9 @@
}
},
"node_modules/follow-redirects": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz",
"integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==",
"version": "1.14.4",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.4.tgz",
"integrity": "sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g==",
"funding": [
{
"type": "individual",
@@ -25798,6 +25831,15 @@
"pretty-format": "^26.0.0"
}
},
"@types/jquery": {
"version": "3.5.8",
"resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.8.tgz",
"integrity": "sha512-cXk6NwqjDYg+UI9p2l3x0YmPa4m7RrXqmbK4IpVVpRJiYXU/QTo+UZrn54qfE1+9Gao4qpYqUnxm5ZCy2FTXAw==",
"dev": true,
"requires": {
"@types/sizzle": "*"
}
},
"@types/json-schema": {
"version": "7.0.7",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz",
@@ -25900,6 +25942,12 @@
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.1.tgz",
"integrity": "sha512-EaCxbanVeyxDRTQBkdLb3Bvl/HK7PBK6UJjsSixB0iHKoWxE5uu2Q/DgtpOhPIojN0Zl1whvOd7PoHs2P0s5eA=="
},
"@types/sizzle": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz",
"integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==",
"dev": true
},
"@types/source-list-map": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz",
@@ -25923,6 +25971,15 @@
"@types/jest": "*"
}
},
"@types/toastr": {
"version": "2.1.39",
"resolved": "https://registry.npmjs.org/@types/toastr/-/toastr-2.1.39.tgz",
"integrity": "sha512-jgbMLTjj7dsSY/EYYOoZXhK6OY/bR909Bn6YNnwL3Oq+f0AeFKbYa198XU/6bsmUqqCCWw5VvCi11FDN1/fetw==",
"dev": true,
"requires": {
"@types/jquery": "*"
}
},
"@types/uglify-js": {
"version": "3.13.1",
"resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.13.1.tgz",
@@ -26656,6 +26713,14 @@
"resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.2.3.tgz",
"integrity": "sha512-pXnVMfJKSIWU2Ml4JHP7pZEPIrgBO1Fd3WGx+fPBsS+KRGhE4vxooD8XBGWbQOIVSZsVK7pUDBBkCicNu80yzQ=="
},
"axios": {
"version": "0.23.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.23.0.tgz",
"integrity": "sha512-NmvAE4i0YAv5cKq8zlDoPd1VLKAqX5oLuZKs8xkJa4qi6RGn0uhCYFjWtHHC9EM/MwOwYWOs53W+V0aqEXq1sg==",
"requires": {
"follow-redirects": "^1.14.4"
}
},
"axobject-query": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz",
@@ -30298,9 +30363,9 @@
}
},
"follow-redirects": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz",
"integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg=="
"version": "1.14.4",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.4.tgz",
"integrity": "sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g=="
},
"for-in": {
"version": "1.0.2",


+ 1
- 0
package.json Переглянути файл

@@ -13,6 +13,7 @@
"@types/node": "^12.20.15",
"@types/react": "^17.0.13",
"@types/react-dom": "^17.0.8",
"axios": "^0.23.0",
"moment": "^2.29.1",
"node-sass": "^6.0.1",
"query-string": "^7.0.1",


+ 4
- 0
src/App.tsx Переглянути файл

@@ -19,6 +19,9 @@ import { ALL_WORDS } from "./data/all-words";
import { WordDetails } from "./components/word-details/WordDetails";
import { Calendar } from "./components/calendar/Calendar";
import { Login } from "./components/auth/Login";
import { Signup } from "./components/auth/Signup";

export const SERVER_URL = 'http://localhost:8001';


export var userProfileData: IProfile = {
@@ -86,6 +89,7 @@ function App() {
</BrowserRouter> : <BrowserRouter>
<Switch>
<Route path="/login" component={Login} />
<Route path="/register" component={Signup} />
<Redirect from="/" to="/login" />
</Switch>
</BrowserRouter>


+ 20
- 2
src/components/auth/Login.tsx Переглянути файл

@@ -4,12 +4,30 @@ import { ReactComponent as LogoIcon } from '../../assets/icons/anamnesis.svg';
import { ReactComponent as EyeOffIcon } from '../../assets/icons/eye-off-outline.svg';
import { ReactComponent as EyeIcon } from '../../assets/icons/eye-outline.svg';
import { NavLink } from "react-router-dom";
import axios from 'axios';
import { SERVER_URL } from "../../App";

const authenticateCredentials = async (username: string, password: string) => {
return await axios.post(SERVER_URL + '/auth/api-auth/', {
email: username,
password: password
});
}

export const Login: React.FC = () => {
const [showPassowrd, setShowPassword] = useState<boolean>(true);
const [userName, setUsername] = useState<string>('');
const [password, setPassword] = useState<string>('');

function auth() {
authenticateCredentials(userName, password).then((response: any) => {
localStorage.anamnesisToken = response.data.token;
window.location.assign('/home');
}, () => {
window.alert("Please check your credentials");
});
}

return <section className="page">
<header className={styles.pageHeader}>
<LogoIcon />
@@ -30,11 +48,11 @@ export const Login: React.FC = () => {
</button>
</div>

<button className={styles.submitButton}>
<button className={styles.submitButton} onClick={() => auth()}>
Knock Knock
</button>

<NavLink className={styles.otherLinks} to="/signup"> Signup? </NavLink>
<NavLink className={styles.otherLinks} to="/register"> Signup? </NavLink>

</section>



+ 111
- 0
src/components/auth/Signup.tsx Переглянути файл

@@ -0,0 +1,111 @@
import React, { useState } from "react";
import styles from './Auth.module.scss';
import { ReactComponent as LogoIcon } from '../../assets/icons/anamnesis.svg';
import { ReactComponent as EyeOffIcon } from '../../assets/icons/eye-off-outline.svg';
import { ReactComponent as EyeIcon } from '../../assets/icons/eye-outline.svg';
import { NavLink } from "react-router-dom";
import axios from 'axios';
import { SERVER_URL } from "../../App";


const registerUser = async (name: string, username: string, password: string) => {
return await axios.post(SERVER_URL + '/auth/register/', {
name: name,
email: username,
password: password
});
}

const requestVerification = async (email: string) => {
return await axios.post(SERVER_URL + '/auth/request-verification/', {
email: email,
});
}

const verifyUser = async (email: string, otp: string) => {
return await axios.post(SERVER_URL + '/auth/verify-user/', {
email: email,
otp: otp
});
}


export const Signup: React.FC = () => {
const [showPassowrd, setShowPassword] = useState<boolean>(true);
const [fullName, setFullName] = useState<string>('');
const [userName, setUsername] = useState<string>('');
const [password, setPassword] = useState<string>('');
const [otp, setOtp] = useState<string>('');
const [viewState, setViewState] = useState<'REGISTER' | 'VERIFY'>('REGISTER');

function register() {
registerUser(fullName, userName, password).then(() => {

setTimeout(() => {
requestVerification(userName).then(() => {
setViewState('VERIFY');
}, () => {
window.alert("Couldn't send Verfication request");
});
}, 1000);

}, (e) => {
window.alert(e.toString());
});
}

function verify() {
verifyUser(userName, otp).then(() => {
window.alert("Verified user!");
window.location.assign("/login");
}, () => window.alert("Failed Verification, please try again"))
}

return <section className="page">
<header className={styles.pageHeader}>
<LogoIcon />
</header>

{ viewState === 'REGISTER' && <section className={styles.form}>

<div className={styles.inputHolder}>
<input defaultValue={fullName} onInput={(e) => setFullName(e.currentTarget.value)}
type="text" placeholder="Full Name" />
</div>

<div className={styles.inputHolder}>
<input defaultValue={userName} onInput={(e) => setUsername(e.currentTarget.value)}
type="email" placeholder="Email ID" />
</div>

<div className={styles.inputHolder}>
<input defaultValue={password} onInput={(e) => setPassword(e.currentTarget.value)}
type={ showPassowrd ? "text" : "password" } placeholder="Password" />
<button className={styles.rightButton} onClick={() => setShowPassword(!showPassowrd)}>
{ showPassowrd ? <EyeOffIcon /> : <EyeIcon /> }
</button>
</div>

<button className={styles.submitButton} onClick={() => register()}>
Next Step
</button>

<NavLink className={styles.otherLinks} to="/Login"> Login? </NavLink>

</section> }

{ viewState === 'VERIFY' && <section className={styles.form}>

<div className={styles.inputHolder}>
<input defaultValue={otp} onInput={(e) => setOtp(e.currentTarget.value)}
type="tel" placeholder="Enter OTP sent to your Mail ID" />
</div>

<button className={styles.submitButton} onClick={() => verify()}>
Verify
</button>

</section> }

</section>
};

Завантаження…
Відмінити
Зберегти