mirror of
https://github.com/FranP-code/Open-Telegram-to-Notion-Website.git
synced 2025-10-13 00:42:53 +00:00
Auth page done
This commit is contained in:
@@ -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",
|
||||
|
||||
19
src/App.jsx
19
src/App.jsx
@@ -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/>} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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
103
src/Pages/Auth/Auth.jsx
Normal 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
|
||||
27
src/Pages/Auth/auth-style.css
Normal file
27
src/Pages/Auth/auth-style.css
Normal 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 */
|
||||
1
src/Pages/Auth/auth-style.css.map
Normal file
1
src/Pages/Auth/auth-style.css.map
Normal 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"}
|
||||
37
src/Pages/Auth/auth-style.scss
Normal file
37
src/Pages/Auth/auth-style.scss
Normal 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;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
1
src/Pages/Auth/auth_copy.svg
Normal file
1
src/Pages/Auth/auth_copy.svg
Normal 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 |
31
src/components/Loading/Loading.jsx
Normal file
31
src/components/Loading/Loading.jsx
Normal 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
|
||||
36
src/components/Notification/Notification.jsx
Normal file
36
src/components/Notification/Notification.jsx
Normal 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
|
||||
17
src/components/Notification/notification-style.css
Normal file
17
src/components/Notification/notification-style.css
Normal 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 */
|
||||
1
src/components/Notification/notification-style.css.map
Normal file
1
src/components/Notification/notification-style.css.map
Normal 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"}
|
||||
25
src/components/Notification/notification-style.scss
Normal file
25
src/components/Notification/notification-style.scss
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
@@ -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"}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user