login page

This commit is contained in:
VividTruthKeeper 2022-09-04 17:21:57 +05:00
parent c509761b9b
commit 6e13bad6cb
9 changed files with 550 additions and 3748 deletions

4038
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -10,7 +10,6 @@
},
"dependencies": {
"axios": "^0.27.2",
"node-sass": "^7.0.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.3.0"
@ -19,6 +18,7 @@
"@types/react": "^18.0.17",
"@types/react-dom": "^18.0.6",
"@vitejs/plugin-react": "^2.0.1",
"sass": "^1.54.8",
"typescript": "^4.6.4",
"vite": "^3.0.7"
}

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -1,5 +1,20 @@
// Modules
import { Routes, Route } from "react-router-dom";
// Style
import "./assets/styles/style.scss";
// Pages
import Login from "./pages/Login";
const App = () => {
return <div className="App"></div>;
return (
<div className="App">
<Routes>
<Route path="/login" element={<Login />} />
</Routes>
</div>
);
};
export default App;

View File

@ -0,0 +1,52 @@
@import url("https://fonts.googleapis.com/css2?family=Montserrat&display=swap");
* {
font-family: "Montserrat", sans-serif;
margin: 0;
padding: 0;
box-sizing: border-box;
scroll-behavior: smooth;
}
.container {
width: 100%;
padding: 0 5rem;
max-width: 150rem;
margin: 0 auto;
height: 100%;
}
html {
font-size: 62.5%;
height: 100%;
}
body {
background-color: #f1f4f8;
}
body,
#root,
.App {
height: 100%;
}
ul {
list-style-type: none;
}
input,
button {
background: none;
outline: none;
border: none;
}
a {
color: #000;
text-decoration: none;
}
@mixin transition-std {
transition: 0.3s all ease;
}

View File

@ -0,0 +1,89 @@
.login {
height: 100%;
&.inner {
display: flex;
align-items: center;
justify-content: center;
}
&__wrapper {
display: flex;
flex-direction: column;
gap: 2.4rem;
}
&__header {
text-align: center;
font-size: 2.8rem;
}
&__form {
min-width: 35rem;
background: #fff;
padding: 3.5rem;
border: 1px solid #d9e2ef;
border-radius: 0.5rem;
display: flex;
flex-direction: column;
gap: 1.6rem;
&__error {
overflow: hidden;
height: 0;
color: red;
font-size: 1.4rem;
font-weight: bold;
@include transition-std;
&.active {
@include transition-std;
height: 2rem;
}
}
&__button {
border-radius: 0.2rem;
cursor: pointer;
width: 100%;
padding: 0.6rem 1.2rem;
color: #fff;
font-size: 1.6rem;
&--violet {
background-color: #7c69ef;
border: 0.1rem solid #7c69ef;
@include transition-std;
&:hover {
@include transition-std;
background-color: #705ed6;
border: 0.1rem solid #705ed6;
}
}
}
&__block {
display: flex;
flex-direction: column;
gap: 0.8rem;
label {
font-size: 1.6rem;
}
input {
padding: 0.6rem 1.2rem;
border: 1px solid #d9e2ef;
border-radius: 0.2rem;
}
&--check {
label {
font-size: 1.6rem;
display: flex;
align-items: center;
gap: 0.6rem;
}
}
}
}
}

View File

@ -0,0 +1,2 @@
@import "./general";
@import "./login";

View File

@ -1,9 +1,12 @@
import React from "react";
import { BrowserRouter } from "react-router-dom";
import ReactDOM from "react-dom/client";
import App from "./App";
ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
<React.StrictMode>
<App />
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>
);

92
src/pages/Login.tsx Normal file
View File

@ -0,0 +1,92 @@
import React, { useState, useEffect } from "react";
const Login = () => {
const cred: Record<string, string> = {
username: "admin@2022",
password: "backpackadmin",
};
const [valid, setValid] = useState({
username: "",
password: "",
check: false,
valid: false,
});
useEffect(() => {
if (valid.username === cred.username && valid.password === cred.password) {
setValid({ ...valid, valid: true });
} else {
setValid({ ...valid, valid: false });
}
}, [valid.username, valid.password]);
return (
<main className="login">
<div className="container">
<div className="login inner">
<div className="login__wrapper">
<h1 className="login__header">Login</h1>
<form
className="login__form"
onSubmit={(e: React.FormEvent) => {
e.preventDefault();
}}
>
<div className="login__form__block">
<label htmlFor="username">Username</label>
<input
required
autoComplete="true"
type="text"
id="username"
placeholder="username"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setValid({ ...valid, username: e.target.value });
}}
/>
</div>
<div className="login__form__block">
<label htmlFor="password">Password</label>
<input
required
autoComplete="true"
type="password"
id="password"
placeholder="password"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setValid({ ...valid, password: e.target.value });
}}
/>
</div>
<div className="login__form__block--check">
<label>
<input type="checkbox" name="remember" id="remember" />
<span>Remember me</span>
</label>
</div>
<span
className={
valid.check && !valid.valid
? "login__form__error active"
: "login__form__error"
}
>
Invalid credentials
</span>
<button
className="login__form__button login__form__button--violet"
onClick={(e: React.FormEvent<HTMLButtonElement>) => {
setValid({ ...valid, check: true });
}}
>
Login
</button>
</form>
</div>
</div>
</div>
</main>
);
};
export default Login;