Auth page done

This commit is contained in:
2022-04-25 17:47:24 -03:00
parent 32404d1104
commit bf31475316
17 changed files with 453 additions and 102 deletions

View File

@@ -6,13 +6,14 @@
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.0.1",
"@testing-library/user-event": "^13.5.0",
"@uiball/loaders": "^1.2.4",
"axios": "^0.26.1",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"react-router-dom": "^6.3.0",
"react-scripts": "5.0.1",
"styled-components": "^5.3.5",
"web-vitals": "^2.1.4"
"web-vitals": "^2.1.4",
"wouter": "^2.8.0-alpha.2"
},
"scripts": {
"start": "react-scripts start",

View File

@@ -1,24 +1,17 @@
import {
BrowserRouter as Router,
Routes,
Route
} from "react-router-dom";
import React from 'react'
import {Route} from 'wouter'
import Header from './components/Header/Header'
import Auth from './Pages/Auth'
import Auth from './Pages/Auth/Auth'
import Index from './Pages/Index/Index'
function App() {
return (
<>
<Header />
<Router>
<Routes>
<Route path="/auth" element={<Auth/>} />
<Route path="/" element={<Index/>} />
</Routes>
</Router>
<Header />
<Route path="/auth" children={<Auth/>} />
<Route path="/" children={<Index/>} />
</>
);
}

View File

@@ -1,83 +0,0 @@
import React, {useState} from "react"
import axios from 'axios'
function Auth() {
const [loading, setLoading] = useState(true)
const [permanentCode, setPermanentCode] = useState(false)
React.useEffect(() => {
async function getPermanentCode() {
const temporalCode = new URLSearchParams(window.location.search).get("code")
console.log(temporalCode);
if (!temporalCode) {
console.log("No temporal code")
return
}
let requestUrl
if (process.env.REACT_APP_ENV_MODE === "production") {
requestUrl = "https://telegram-to-notion-backend.herokuapp.com/api/v1/auth"
} else {
requestUrl = "http://localhost:5050/api/v1/auth"
}
axios({
method: "POST",
url: requestUrl,
headers: {
code: temporalCode,
}
})
.then(res => {
console.log(res)
setPermanentCode(res ? res.data : null)
})
.catch(err => {
console.log(err.response)
setPermanentCode(false)
})
.finally(() => {
setLoading(false)
})
}
getPermanentCode()
})
return (
<div className="auth">
{
loading ?
// <Loading />
<h1>Loading</h1>
:
<>
{
permanentCode ?
<>
<h3>Copy the following code on the Telegram chat</h3>
<div className="success">
<code className="code-selection">
{permanentCode}
</code>
</div>
</>
:
<div className="error">
<h3>There has been an error getting the code. Please try again later.</h3>
</div>
}
</>
}
</div>
)
}
export default Auth

103
src/Pages/Auth/Auth.jsx Normal file
View File

@@ -0,0 +1,103 @@
import React, {useState} from "react"
import axios from 'axios'
import Loading from "../../components/Loading/Loading"
import authImage from './auth_copy.svg'
import './auth-style.css'
import Notification from "../../components/Notification/Notification"
function Auth() {
const [loading, setLoading] = useState(true)
const [permanentCode, setPermanentCode] = useState(false)
const [notification, setNotification] = useState(false)
const getPermanentCode = () => {
const temporalCode = new URLSearchParams(window.location.search).get("code")
if (!temporalCode) {
setPermanentCode("empty")
setLoading(false)
return
}
let requestUrl
if (process.env.REACT_APP_ENV_MODE === "production") {
requestUrl = "http://localhost:5050/api/v1/auth"
} else {
requestUrl = "https://telegram-to-notion-backend.herokuapp.com/api/v1/auth"
}
axios({
method: "POST",
url: requestUrl,
headers: {'Content-Type': 'application/json'},
data: {code: temporalCode}
})
.then(res => {
console.log(res)
setPermanentCode(res ? res.data : null)
})
.catch(err => {
console.log(err.response)
setPermanentCode(false)
})
.finally(() => {
setLoading(false)
})
}
React.useEffect(() => {
getPermanentCode()
}, [])
return (
<div className="auth fullscreen">
{
loading ?
<Loading />
:
<>
{
permanentCode && permanentCode !== "empty" ?
<>
<h2>Copy the following code on Telegram chat</h2>
<div className="success">
<img src={authImage} alt="Copy text" />
<code
className="code-selection"
onClick={() => {
navigator.clipboard.writeText(permanentCode)
setNotification("Text copied to clipboard!")
}}
>
{permanentCode}
</code>
</div>
</>
:
<>
{
permanentCode === "empty" ?
<div className="error">
<h3>There is no temporal code. Please try again later.</h3>
</div>
:
<div className="error">
<h3>There has been an error getting the code. Please try again later.</h3>
</div>
}
</>
}
</>
}
<Notification notification={notification} setNotification={setNotification}/>
</div>
)
}
export default Auth

View File

@@ -0,0 +1,27 @@
.auth {
padding: 1vh 3vw;
}
.auth h2, .auth h3 {
margin-top: 5vh;
}
.auth .success {
display: flex;
align-items: center;
background-color: #ffebcd;
padding: 5vh 2vw;
margin-top: 5vh;
border-radius: 20px;
}
.auth .success img {
width: 75px;
height: 75px;
margin-right: 3vw;
}
.auth .success .code-selection {
-webkit-user-select: all;
-moz-user-select: all;
user-select: all;
overflow-wrap: anywhere;
color: rgb(73, 70, 50);
font-size: 1.2em;
}/*# sourceMappingURL=auth-style.css.map */

View File

@@ -0,0 +1 @@
{"version":3,"sources":["auth-style.scss","auth-style.css"],"names":[],"mappings":"AAAA;EACI,gBAAA;ACCJ;ADCI;EACI,eAAA;ACCR;ADEI;EAEI,aAAA;EACA,mBAAA;EAEA,yBAAA;EAEA,gBAAA;EAEA,eAAA;EAEA,mBAAA;ACLR;ADOQ;EACI,WAAA;EACA,YAAA;EAEA,iBAAA;ACNZ;ADSQ;EACI,wBAAA;KAAA,qBAAA;UAAA,gBAAA;EACA,uBAAA;EAEA,sBAAA;EACA,gBAAA;ACRZ","file":"auth-style.css"}

View File

@@ -0,0 +1,37 @@
.auth {
padding: 1vh 3vw;
h2, h3 {
margin-top: 5vh;
}
.success {
display: flex;
align-items: center;
background-color: #ffebcd;
padding: 5vh 2vw;
margin-top: 5vh;
border-radius: 20px;
img {
width: 75px;
height: 75px;
margin-right: 3vw;
}
.code-selection {
user-select: all;
overflow-wrap: anywhere;
color: rgb(73, 70, 50);
font-size: 1.2em;
}
}
}

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 24 24" fill="none" stroke="#b6a894" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-copy"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg>

After

Width:  |  Height:  |  Size: 348 B

View File

@@ -0,0 +1,31 @@
import React from 'react'
import styled from 'styled-components'
import {DotSpinner} from '@uiball/loaders'
const Loading = () => {
const Styles = styled.div`
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
box-sizing: border-box;
padding-bottom: 20vh;
* {
width: 10vw !important;
height: 10vw !important;
}
`
return (
<Styles>
<DotSpinner color="#4797ff"/>
</Styles>
)
}
export default Loading

View File

@@ -0,0 +1,36 @@
import React from 'react'
import './notification-style.css'
const Notification = ({notification, setNotification}) => {
React.useEffect(() => {
if (notification === false) {
return
}
setTimeout(() => {
const elem = document.querySelector("#notification-element")
elem.classList.remove('fade-in')
elem.classList.add('fade-out')
}, 2000)
setTimeout(() => {
setNotification(false)
}, 2400)
}, [notification])
return (
<>
{
notification ?
<div className="notification fade-in" id="notification-element">
<p>{notification}</p>
</div>
: null
}
</>
)
}
export default Notification

View File

@@ -0,0 +1,17 @@
.notification {
width: 15vw;
min-width: 300px;
background-color: rgba(71, 151, 255, 0.1647058824);
box-shadow: 0px 5px 20px rgba(0, 0, 0, 0.541);
position: absolute;
top: 80%;
left: 50%;
transform: translate(-50%, 0);
padding: 2vh 3vw;
border-radius: 10px;
}
.notification p {
overflow-wrap: anywhere;
text-align: center;
font-weight: bold;
}/*# sourceMappingURL=notification-style.css.map */

View File

@@ -0,0 +1 @@
{"version":3,"sources":["notification-style.scss","notification-style.css"],"names":[],"mappings":"AAAA;EAEI,WAAA;EACA,gBAAA;EAEA,kDAAA;EACA,6CAAA;EAEA,kBAAA;EACA,QAAA;EACA,SAAA;EACA,6BAAA;EAEA,gBAAA;EAEA,mBAAA;ACJJ;ADMI;EACI,uBAAA;EACA,kBAAA;EACA,iBAAA;ACJR","file":"notification-style.css"}

View File

@@ -0,0 +1,25 @@
.notification {
width: 15vw;
min-width: 300px;
background-color: #4797ff2a;
box-shadow: 0px 5px 20px rgba(0, 0, 0, 0.541);
position: absolute;
top: 80%;
left: 50%;
transform: translate(-50%, 0);
padding: 2vh 3vw;
border-radius: 10px;
p {
overflow-wrap: anywhere;
text-align: center;
font-weight: bold;
}
}

View File

@@ -7,9 +7,9 @@ import './styles.css'
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
// <React.StrictMode> //!WTF React
<App />
</React.StrictMode>
// </React.StrictMode> //Thank you: https://stackoverflow.com/a/61091205/18740899
);
// If you want to start measuring performance in your app, pass a function

View File

@@ -8,6 +8,19 @@ body {
font-family: "Inter", sans-serif;
}
html, body, #root {
height: 100%;
}
#root {
display: flex;
flex-direction: column;
}
.fullscreen {
flex-grow: 1;
}
h1, h2, h3, h4, h5, h6 {
margin: 0;
}
@@ -17,4 +30,69 @@ img {
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.fade-in {
-webkit-animation: fade-in 0.5s ease-in-out both;
animation: fade-in 0.5s ease-in-out both;
}
/* ----------------------------------------------
* Generated by Animista on 2022-4-25 17:26:50
* Licensed under FreeBSD License.
* See http://animista.net/license for more info.
* w: http://animista.net, t: @cssanimista
* ---------------------------------------------- */
/**
* ----------------------------------------
* animation fade-in
* ----------------------------------------
*/
@-webkit-keyframes fade-in {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@keyframes fade-in {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.fade-out {
-webkit-animation: fade-out 1s ease-in-out both;
animation: fade-out 1s ease-in-out both;
}
/* ----------------------------------------------
* Generated by Animista on 2022-4-25 17:27:42
* Licensed under FreeBSD License.
* See http://animista.net/license for more info.
* w: http://animista.net, t: @cssanimista
* ---------------------------------------------- */
/**
* ----------------------------------------
* animation fade-out
* ----------------------------------------
*/
@-webkit-keyframes fade-out {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
@keyframes fade-out {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}/*# sourceMappingURL=styles.css.map */

View File

@@ -1 +1 @@
{"version":3,"sources":["styles.scss","styles.css"],"names":[],"mappings":"AAAA;EACI,SAAA;EACA,UAAA;ACCJ;;ADEA;EACY,+FAAA;EACR,gCAAA;ACCJ;;ADEA;EACI,SAAA;ACCJ;;ADEA;EACI,yBAAA;KAAA,sBAAA;MAAA,qBAAA;UAAA,iBAAA;ACCJ","file":"styles.css"}
{"version":3,"sources":["styles.scss","styles.css"],"names":[],"mappings":"AAAA;EACI,SAAA;EACA,UAAA;ACCJ;;ADEA;EACY,+FAAA;EACR,gCAAA;ACCJ;;ADEA;EACI,YAAA;ACCJ;;ADEA;EACI,aAAA;EACA,sBAAA;ACCJ;;ADEA;EACI,YAAA;ACCJ;;ADEA;EACI,SAAA;ACCJ;;ADEA;EACI,yBAAA;KAAA,sBAAA;MAAA,qBAAA;UAAA,iBAAA;ACCJ;;ADIA;EACC,wEAAA;EACG,gEAAA;ACDJ;;ADIA;;;;;mDAAA;AAOA;;;;EAAA;AAKC;EACG;IACE,UAAA;ECFJ;EDIE;IACE,UAAA;ECFJ;AACF;ADIA;EACI;IACI,UAAA;ECFN;EDIE;IACI,UAAA;ECFN;AACF;ADKA;EACC,4CAAA;EACG,oCAAA;ACHJ;;ADKA;;;;;mDAAA;AAOA;;;;EAAA;AAKC;EACG;IACI,UAAA;ECHN;EDKE;IACI,UAAA;ECHN;AACF;ADKI;EACA;IACI,UAAA;ECHN;EDKE;IACI,UAAA;ECHN;AACF","file":"styles.css"}

View File

@@ -8,10 +8,93 @@ body {
font-family: 'Inter', sans-serif;
}
html, body, #root {
height: 100%;
}
#root {
display: flex;
flex-direction: column;
}
.fullscreen {
flex-grow: 1;
}
h1, h2, h3, h4, h5, h6 {
margin: 0;
}
img {
user-select: none;
}
}
//Animations
.fade-in {
-webkit-animation: fade-in 0.5s cubic-bezier(0.390, 0.575, 0.565, 1.000) both;
animation: fade-in 0.5s cubic-bezier(0.390, 0.575, 0.565, 1.000) both;
}
/* ----------------------------------------------
* Generated by Animista on 2022-4-25 17:26:50
* Licensed under FreeBSD License.
* See http://animista.net/license for more info.
* w: http://animista.net, t: @cssanimista
* ---------------------------------------------- */
/**
* ----------------------------------------
* animation fade-in
* ----------------------------------------
*/
@-webkit-keyframes fade-in {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@keyframes fade-in {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.fade-out {
-webkit-animation: fade-out 1s ease-out both;
animation: fade-out 1s ease-out both;
}
/* ----------------------------------------------
* Generated by Animista on 2022-4-25 17:27:42
* Licensed under FreeBSD License.
* See http://animista.net/license for more info.
* w: http://animista.net, t: @cssanimista
* ---------------------------------------------- */
/**
* ----------------------------------------
* animation fade-out
* ----------------------------------------
*/
@-webkit-keyframes fade-out {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
@keyframes fade-out {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}