From 46389bad329986d985c5abf8cf8bdc1be69fae1f Mon Sep 17 00:00:00 2001
From: Dm1tr1y147 <me@dmitriy.icu>
Date: Wed, 14 Oct 2020 11:21:24 +0500
Subject: [PATCH] Added login and authorize routes and components, added basic
 UserPage component and query

---
 package.json                           |  1 +
 src/apollo/{queries.ts => defs.ts}     | 12 +++++-
 src/apollo/index.ts                    |  3 +-
 src/components/App.tsx                 | 56 ++++++++++++++------------
 src/components/Authorize/index.tsx     | 15 +++++++
 src/components/Login/index.tsx         | 35 ++++++++++++++++
 src/components/TextComponent/index.tsx |  7 ++++
 src/components/UserPage/index.tsx      | 22 ++++++++++
 src/hooks.ts                           |  5 +++
 9 files changed, 127 insertions(+), 29 deletions(-)
 rename src/apollo/{queries.ts => defs.ts} (67%)
 create mode 100644 src/components/Authorize/index.tsx
 create mode 100644 src/components/Login/index.tsx
 create mode 100644 src/components/TextComponent/index.tsx
 create mode 100644 src/components/UserPage/index.tsx

diff --git a/package.json b/package.json
index 409fc11..e645900 100644
--- a/package.json
+++ b/package.json
@@ -8,6 +8,7 @@
     "@types/react": "^16.9.0",
     "@types/react-dom": "^16.9.0",
     "@types/react-router-dom": "^5.1.6",
+    "@types/validator": "^13.1.0",
     "graphql": "^15.3.0",
     "react": "^16.13.1",
     "react-dom": "^16.13.1",
diff --git a/src/apollo/queries.ts b/src/apollo/defs.ts
similarity index 67%
rename from src/apollo/queries.ts
rename to src/apollo/defs.ts
index f360e2b..0d05073 100644
--- a/src/apollo/queries.ts
+++ b/src/apollo/defs.ts
@@ -17,4 +17,14 @@ const FORM = gql`
   }
 `
 
-export { LOGIN, FORM }
+const USER = gql`
+  query User {
+    user {
+      email
+      id
+      name
+    }
+  }
+`
+
+export { LOGIN, FORM, USER }
diff --git a/src/apollo/index.ts b/src/apollo/index.ts
index fe62862..3343847 100644
--- a/src/apollo/index.ts
+++ b/src/apollo/index.ts
@@ -2,7 +2,7 @@ import { ApolloClient, createHttpLink, InMemoryCache } from '@apollo/client'
 
 import { setContext } from '@apollo/client/link/context'
 
-import { LOGIN } from './queries'
+export * from './defs'
 
 const httpLink = createHttpLink({
   uri: process.env.GRAPHQL_URL || process.env.REACT_APP_GRAPHQL_URL || undefined
@@ -28,4 +28,3 @@ const client = new ApolloClient({
 })
 
 export default client
-export { LOGIN }
diff --git a/src/components/App.tsx b/src/components/App.tsx
index c958fe3..a39064a 100644
--- a/src/components/App.tsx
+++ b/src/components/App.tsx
@@ -1,38 +1,40 @@
-import { ApolloProvider, useMutation, useQuery } from '@apollo/client'
-import React, { useContext } from 'react'
+import { ApolloProvider } from '@apollo/client'
+import React from 'react'
 import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'
 
 import client from '../apollo'
-import { FORM, LOGIN } from '../apollo/queries'
 import Context from '../context'
 import { useUser } from '../hooks'
+import Authorize from './Authorize'
+import Login from './Login'
+import UserPage from './UserPage'
 
-const TestComponent: React.FC = () => {
-  const { loading, error, data } = useQuery(FORM, {
-    variables: {
-      id: 1
-    }
-  })
+// const TestComponent: React.FC = () => {
+//   const { loading, error, data } = useQuery(FORM, {
+//     variables: {
+//       id: 1
+//     }
+//   })
 
-  const { user } = useContext(Context)
+//   const { user } = useContext(Context)
 
-  const [doLogin] = useMutation(LOGIN)
+//   const [doLogin] = useMutation(LOGIN)
 
-  if (loading) return <p>Loading...</p>
-  if (error) return <p>Error :(</p>
+//   if (loading) return <p>Loading...</p>
+//   if (error) return <p>Error :(</p>
 
-  return (
-    <div>
-      <button
-        onClick={() => doLogin({ variables: { email: 'test@test.test' } })}
-      >
-        Click!
-      </button>
-      {user.id}
-      {data.form.id}
-    </div>
-  )
-}
+//   return (
+//     <div>
+//       <button
+//         onClick={() => doLogin({ variables: { email: 'test@test.test' } })}
+//       >
+//         Click!
+//       </button>
+//       {user.id}
+//       {data.form.id}
+//     </div>
+//   )
+// }
 
 const App: React.FC = () => {
   const userContext = useUser()
@@ -43,7 +45,9 @@ const App: React.FC = () => {
         <Context.Provider value={userContext}>
           <Router>
             <Switch>
-              <Route path="/" component={TestComponent} />
+              <Route path="/login" component={Login} />
+              <Route path="/authorize" component={Authorize} />
+              <Route path="/user" component={UserPage} />
             </Switch>
           </Router>
         </Context.Provider>
diff --git a/src/components/Authorize/index.tsx b/src/components/Authorize/index.tsx
new file mode 100644
index 0000000..dcd920f
--- /dev/null
+++ b/src/components/Authorize/index.tsx
@@ -0,0 +1,15 @@
+import React from 'react'
+import { Redirect } from 'react-router-dom'
+import { useURLQuery } from '../../hooks'
+
+const Authorize: React.FC = () => {
+  const query = useURLQuery()
+
+  const token = query.get('token')
+
+  if (token) localStorage.setItem('token', token)
+
+  return <Redirect to="/" />
+}
+
+export default Authorize
diff --git a/src/components/Login/index.tsx b/src/components/Login/index.tsx
new file mode 100644
index 0000000..d2ac539
--- /dev/null
+++ b/src/components/Login/index.tsx
@@ -0,0 +1,35 @@
+import { useMutation } from '@apollo/client'
+import React, { ChangeEvent, FormEvent, useState } from 'react'
+import { Redirect } from 'react-router-dom'
+
+import { LOGIN } from '../../apollo'
+
+const Login: React.FC = () => {
+  const [email, setEmail] = useState<string>('')
+
+  const [doLogin, { error, data }] = useMutation(LOGIN)
+
+  const handleFormSubmit = async (e: FormEvent) => {
+    e.preventDefault()
+    try {
+      await doLogin({ variables: { email } })
+    } catch (err) {}
+  }
+
+  const handleInputChange = (e: ChangeEvent<HTMLInputElement>) => {
+    setEmail(e.currentTarget.value)
+  }
+
+  return (
+    <div>
+      <form onSubmit={handleFormSubmit}>
+        <input type="text" onChange={handleInputChange} />
+        <input type="submit" value="Login" />
+      </form>
+      {error && error.message}
+      {data && data.login && data.login.success && <Redirect to="/" />}
+    </div>
+  )
+}
+
+export default Login
diff --git a/src/components/TextComponent/index.tsx b/src/components/TextComponent/index.tsx
new file mode 100644
index 0000000..d0b8455
--- /dev/null
+++ b/src/components/TextComponent/index.tsx
@@ -0,0 +1,7 @@
+import React from 'react'
+
+const TextComponent: React.FC<{ text: string }> = (text) => {
+  return <div>{text}</div>
+}
+
+export default TextComponent
diff --git a/src/components/UserPage/index.tsx b/src/components/UserPage/index.tsx
new file mode 100644
index 0000000..2a62f60
--- /dev/null
+++ b/src/components/UserPage/index.tsx
@@ -0,0 +1,22 @@
+import { useQuery } from '@apollo/client'
+import React from 'react'
+import { USER } from '../../apollo'
+
+const UserPage: React.FC = () => {
+  const { data, error, loading } = useQuery(USER)
+  if (loading) return <p>Loading...</p>
+
+  if (error) return <p>{error.message}</p>
+
+  console.log(Object.entries(data.user))
+
+  const user = Object.entries(data.user).map((el, index) => (
+    <li key={index}>
+      {el[0]}: {el[1]}
+    </li>
+  ))
+
+  return <ul>{user}</ul>
+}
+
+export default UserPage
diff --git a/src/hooks.ts b/src/hooks.ts
index 444f78c..0f85206 100644
--- a/src/hooks.ts
+++ b/src/hooks.ts
@@ -1,4 +1,5 @@
 import { useCallback, useState } from 'react'
+import { useLocation } from 'react-router-dom'
 import { ContextType, initialUser, UserType } from './context'
 
 export const useUser = (): ContextType => {
@@ -10,3 +11,7 @@ export const useUser = (): ContextType => {
 
   return { user, setUser }
 }
+
+export const useURLQuery = () => {
+  return new URLSearchParams(useLocation().search)
+}