Kaynağa Gözat

all the database interaction is now in the hook. the information is passed to the modules via context.

Tomi Cvetic 5 yıl önce
ebeveyn
işleme
6687de36ee

+ 33 - 17
frontend/src/user/components/LoginForm.tsx

@@ -1,25 +1,41 @@
-import { useUserLoginMutation, CurrentUserDocument } from "../../gql";
-import { TextInput } from "../../form";
-
-const initialValues = {
-  email: "tomislav.cvetic@u-blox.com",
-  password: "1234"
-};
+import { TextInput, useForm } from '../../form'
+import { useContext } from 'react'
+import { UserContext } from '../hooks'
 
 const LoginForm = () => {
-  const [login, { loading, error, data }] = useUserLoginMutation();
-  console.log("LoginForm", loading, error, data);
+  const { values, onChange } = useForm({ email: '', password: '' })
+  const { login } = useContext(UserContext)
+
+  if (!login) return <p>Loading context.</p>
+  const [userLogin, { error, loading }] = login
 
   return (
-    <form>
-      <TextInput label="Email" name="email" type="text" placeholder="Email" />
-      <TextInput label="Password" name="password" type="password" />
-      <button type="submit" disabled={loading}>
+    <form
+      onSubmit={async ev => {
+        ev.preventDefault()
+        const result = await userLogin({ variables: values })
+        console.log('login', result)
+      }}
+    >
+      <TextInput
+        label='Email'
+        name='email'
+        value={values.email}
+        onChange={onChange}
+      />
+      <TextInput
+        label='Password'
+        name='password'
+        type='password'
+        value={values.password}
+        onChange={onChange}
+      />
+      <button type='submit' disabled={loading}>
         Login!
       </button>
-      {error && <div className="error">{error.message}</div>}
+      {error && <div className='error'>{error.message}</div>}
     </form>
-  );
-};
+  )
+}
 
-export default LoginForm;
+export default LoginForm

+ 9 - 13
frontend/src/user/components/LogoutButton.tsx

@@ -1,24 +1,20 @@
-import { useUserLogoutMutation, CurrentUserDocument } from '../../gql'
+import { useContext } from 'react'
+import { UserContext } from '../hooks'
 
 interface LogoutButtonProps {
   title?: string
 }
 
-const LogoutButton = ({ title }: LogoutButtonProps) => {
+const LogoutButton = ({ title = 'Logout' }: LogoutButtonProps) => {
+  const { logout } = useContext(UserContext)
 
-  const [logout, { loading, error }] = useUserLogoutMutation(
-    { refetchQueries: [{ query: CurrentUserDocument }] }
-  )
+  if (!logout) return <p>Loading context.</p>
+  const [userLogout, { error, loading }] = logout
 
   return (
-    <button disabled={loading} onClick={async (event: React.SyntheticEvent) => {
-      try {
-        const data = await logout()
-        console.log('LogoutButton', data)
-      } catch (error) {
-        console.log('LogoutButton', error)
-      }
-    }}>{title || 'Log out'}</button>
+    <button disabled={loading} onClick={event => userLogout()}>
+      {title}
+    </button>
   )
 }
 

+ 45 - 0
frontend/src/user/components/UserNav.tsx

@@ -0,0 +1,45 @@
+import { useState, useContext } from 'react'
+import Link from 'next/link'
+import LogoutButton from './LogoutButton'
+import LoginForm from './LoginForm'
+import { UserContext } from '../hooks'
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
+import { faUser } from '@fortawesome/free-solid-svg-icons'
+
+const UserNav = () => {
+  const [menu, setMenu] = useState(false)
+  const { user } = useContext(UserContext)
+
+  return (
+    <li>
+      <a
+        href=''
+        onClick={ev => {
+          ev.preventDefault()
+          setMenu(!menu)
+        }}
+      >
+        <FontAwesomeIcon icon={faUser} />
+        {user?.data ? user.data.currentUser.name : 'Login'}
+      </a>
+
+      {menu ? (
+        <section className='usermenu'>
+          {user?.data ? (
+            <>
+              <h2>Welcome, {user.data.currentUser.name}</h2>
+              <Link href={{ pathname: 'user' }}>
+                <a>Edit user data</a>
+              </Link>
+              <LogoutButton />
+            </>
+          ) : (
+            <LoginForm />
+          )}
+        </section>
+      ) : null}
+    </li>
+  )
+}
+
+export default UserNav

+ 2 - 1
frontend/src/user/components/__tests__/DeleteUserButton.test.tsx

@@ -1,3 +1,4 @@
+import React from 'react'
 import { shallow } from 'enzyme'
 import { MockedProvider } from '@apollo/client/testing'
 
@@ -28,4 +29,4 @@ describe('testing delete user button', () => {
       </MockedProvider>
     )
   })
-})
+})

+ 23 - 6
frontend/src/user/hooks.tsx

@@ -1,14 +1,31 @@
 import { createContext, FunctionComponent } from 'react'
-import { CurrentUserQuery, useCurrentUserQuery } from '../gql'
+import {
+  CurrentUserQuery,
+  useCurrentUserQuery,
+  useUserLogoutMutation,
+  useUserLoginMutation,
+  CurrentUserDocument
+} from '../gql'
 
-export const UserContext = createContext<
-  CurrentUserQuery['currentUser'] | undefined
->(undefined)
+interface IUserContext {
+  user?: ReturnType<typeof useCurrentUserQuery>
+  login?: ReturnType<typeof useUserLoginMutation>
+  logout?: ReturnType<typeof useUserLogoutMutation>
+}
+
+export const UserContext = createContext<IUserContext>({})
 
 export const UserProvider: FunctionComponent = ({ children }) => {
-  const user = useCurrentUserQuery()
+  const user = useCurrentUserQuery({ fetchPolicy: 'network-only' })
+  const logout = useUserLogoutMutation({
+    refetchQueries: [{ query: CurrentUserDocument }]
+  })
+  const login = useUserLoginMutation({
+    refetchQueries: [{ query: CurrentUserDocument }]
+  })
+  console.log('current user', user.data)
   return (
-    <UserContext.Provider value={user.data?.currentUser}>
+    <UserContext.Provider value={{ user, login, logout }}>
       {children}
     </UserContext.Provider>
   )

+ 0 - 62
frontend/src/user/user.js

@@ -1,62 +0,0 @@
-import { useState, useEffect } from 'react'
-import Link from 'next/link'
-import { useQuery } from '@apollo/client'
-import { CURRENT_USER } from './graphql'
-import LogoutButton from './components/LogoutButton'
-import LoginForm from './components/LoginForm'
-
-const UserNav = props => {
-  const [menu, setMenu] = useState(false)
-
-  return (
-    <>
-      <a
-        href='' onClick={ev => {
-          ev.preventDefault()
-          setMenu(!menu)
-        }}
-      >sali
-      </a>
-      {menu ? (
-        <UserNavMenu />
-      ) : null}
-    </>
-  )
-}
-
-const UserNavMenu = props => {
-  const { data, loading, error } = useQuery(CURRENT_USER, { fetchPolicy: 'cache-and-network' })
-  console.log('UserNav', data, loading, error && error.message)
-  const user = data && data.me
-
-  if (loading) return <p>Loading user data...</p>
-  if (error) return <p>Error loading user data.</p>
-
-  return (
-    <section className='usermenu'>
-      {user ? (
-        <>
-          <h2>Welcome, {user.name}</h2>
-          <Link href={{ pathname: 'user' }}><a>Edit user data</a></Link>
-          <LogoutButton />
-        </>
-      ) : (
-          <LoginForm />
-        )}
-
-      <style jsx>
-        {`
-          section.usermenu {
-          position: absolute;
-          background: rgba(127,0,0,0.5);
-          }
-        `}
-      </style>
-    </section>
-  )
-}
-
-const User = props => <a />
-
-export { UserNav }
-export default User