💕😁
This commit is contained in:
		@@ -20,11 +20,9 @@ python manage.py createsuperuser --email admin@example.com --username admin --pa
 | 
			
		||||
 | 
			
		||||
# Frontend
 | 
			
		||||
 | 
			
		||||
- [x] useGet hook
 | 
			
		||||
- [x] User context
 | 
			
		||||
- [x] auth api
 | 
			
		||||
- [ ] user crud api (new user flow)
 | 
			
		||||
- [ ] socket hook
 | 
			
		||||
 | 
			
		||||
# Backend
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,22 @@
 | 
			
		||||
import { BrowserRouter } from 'react-router-dom'
 | 
			
		||||
import { UserContextProvider } from './contexts/UserContext'
 | 
			
		||||
import { CoreLayout } from './app/CoreLayout'
 | 
			
		||||
import { AppContextProvider } from './contexts/AppContext'
 | 
			
		||||
import { Api } from './api'
 | 
			
		||||
import { users } from './api/data/users'
 | 
			
		||||
 | 
			
		||||
import './scss/app.scss'
 | 
			
		||||
 | 
			
		||||
const App = () => {
 | 
			
		||||
  const api = new Api({ mock: true, users })
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <BrowserRouter>
 | 
			
		||||
      <UserContextProvider>
 | 
			
		||||
        <CoreLayout />
 | 
			
		||||
      </UserContextProvider>
 | 
			
		||||
      <AppContextProvider api={api}>
 | 
			
		||||
        <UserContextProvider>
 | 
			
		||||
          <CoreLayout />
 | 
			
		||||
        </UserContextProvider>
 | 
			
		||||
      </AppContextProvider>
 | 
			
		||||
    </BrowserRouter>
 | 
			
		||||
  )
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +0,0 @@
 | 
			
		||||
import { User } from '../../types'
 | 
			
		||||
 | 
			
		||||
export const mockUser: User = {
 | 
			
		||||
  id: '4242-4242-4242-4242',
 | 
			
		||||
  username: 'TestUser42',
 | 
			
		||||
  email: 'testuser@email.com',
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										12
									
								
								frontend/src/api/data/users.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								frontend/src/api/data/users.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
import { DataBuddy } from '@dank-inc/data-buddy'
 | 
			
		||||
import { User } from '../../types'
 | 
			
		||||
 | 
			
		||||
const userRecords: User[] = [
 | 
			
		||||
  {
 | 
			
		||||
    id: '42',
 | 
			
		||||
    username: 'TestUser42',
 | 
			
		||||
    email: 'testuser@email.com',
 | 
			
		||||
  },
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
export const users = new DataBuddy(userRecords)
 | 
			
		||||
@@ -51,7 +51,7 @@ export class Api {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const logOut = () => {
 | 
			
		||||
export const logOut = async () => {
 | 
			
		||||
  wipeJWT()
 | 
			
		||||
  // axios -> delete session?
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										28
									
								
								frontend/src/contexts/AppContext.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								frontend/src/contexts/AppContext.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
			
		||||
import React, { createContext, useContext } from 'react'
 | 
			
		||||
import { Api } from '../api'
 | 
			
		||||
 | 
			
		||||
type Props = {
 | 
			
		||||
  children: React.ReactNode
 | 
			
		||||
  api: Api
 | 
			
		||||
}
 | 
			
		||||
type Context = {
 | 
			
		||||
  api: Api
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Just find-replace "AppContext" with whatever context name you like. (ie. DankContext)
 | 
			
		||||
const AppContext = createContext<Context | null>(null)
 | 
			
		||||
 | 
			
		||||
export const AppContextProvider = ({ api, children }: Props) => {
 | 
			
		||||
  return <AppContext.Provider value={{ api }}>{children}</AppContext.Provider>
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const useAppContext = () => {
 | 
			
		||||
  const context = useContext(AppContext)
 | 
			
		||||
 | 
			
		||||
  if (!context)
 | 
			
		||||
    throw new Error(
 | 
			
		||||
      'AppContext must be called from within the AppContextProvider',
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
  return context
 | 
			
		||||
}
 | 
			
		||||
@@ -11,7 +11,8 @@ import { message } from 'antd'
 | 
			
		||||
import { useHistory } from 'react-router'
 | 
			
		||||
 | 
			
		||||
import { User } from '../types'
 | 
			
		||||
import { getLoggedInUser, logIn, logOut } from '../api'
 | 
			
		||||
import { useAppContext } from './AppContext'
 | 
			
		||||
import { logOut } from '../api'
 | 
			
		||||
 | 
			
		||||
type Props = {
 | 
			
		||||
  children: React.ReactNode
 | 
			
		||||
@@ -27,36 +28,17 @@ type Context = {
 | 
			
		||||
const UserContext = createContext<Context | null>(null)
 | 
			
		||||
 | 
			
		||||
export const UserContextProvider = ({ children }: Props) => {
 | 
			
		||||
  const { api } = useAppContext()
 | 
			
		||||
  const history = useHistory()
 | 
			
		||||
 | 
			
		||||
  const [user, setUser] = useState<User | null>(null)
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    const login = async () => {
 | 
			
		||||
      try {
 | 
			
		||||
        // const res = axios.post('/dj-rest-auth/login', {
 | 
			
		||||
        //   email: 'blah',
 | 
			
		||||
        //   password: 'blah',
 | 
			
		||||
        // })
 | 
			
		||||
        const user = await getLoggedInUser()
 | 
			
		||||
        if (!user) throw new Error()
 | 
			
		||||
        setUser(user)
 | 
			
		||||
 | 
			
		||||
        message.success(`logged in as ${user?.username}`, 0.5)
 | 
			
		||||
      } catch {
 | 
			
		||||
        // this can possibly be handled better
 | 
			
		||||
        message.error('Login Failed')
 | 
			
		||||
        window.location.reload()
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    login()
 | 
			
		||||
  }, [])
 | 
			
		||||
 | 
			
		||||
  const handleLogin = async (username: string, password: string) => {
 | 
			
		||||
    try {
 | 
			
		||||
      const user = await logIn(username, password)
 | 
			
		||||
      if (!user) throw new Error('Problem logging in!')
 | 
			
		||||
      const { id } = await api.login(username, password)
 | 
			
		||||
      if (!id) throw new Error('Problem logging in!')
 | 
			
		||||
      const user = await api.getUser(id)
 | 
			
		||||
 | 
			
		||||
      setUser(user)
 | 
			
		||||
      message.success(`logged in as ${user?.username}`, 0.5)
 | 
			
		||||
    } catch (err) {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,53 +0,0 @@
 | 
			
		||||
import { useCallback, useEffect, useState } from 'react'
 | 
			
		||||
import Axios from 'axios'
 | 
			
		||||
import { setHeaders } from '../utils/jwt'
 | 
			
		||||
 | 
			
		||||
type Options = {
 | 
			
		||||
  subscribe: boolean
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export type Response<T> =
 | 
			
		||||
  | {
 | 
			
		||||
      data: T
 | 
			
		||||
      loading: false
 | 
			
		||||
      error: false
 | 
			
		||||
      refetch: () => void
 | 
			
		||||
    }
 | 
			
		||||
  | {
 | 
			
		||||
      data: null
 | 
			
		||||
      loading: false
 | 
			
		||||
      error: true
 | 
			
		||||
      refetch: () => void
 | 
			
		||||
    }
 | 
			
		||||
  | {
 | 
			
		||||
      data: null
 | 
			
		||||
      loading: true
 | 
			
		||||
      error: false
 | 
			
		||||
      refetch: () => void
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
export const useGet = <T>(path: string, options?: Options): Response<T> => {
 | 
			
		||||
  const [data, setData] = useState<T | null>(null)
 | 
			
		||||
  const [error, setError] = useState(false)
 | 
			
		||||
 | 
			
		||||
  const get = useCallback(async () => {
 | 
			
		||||
    try {
 | 
			
		||||
      const { data } = await Axios.get<T>(`/api/${path}`, { ...setHeaders() })
 | 
			
		||||
      setData(data)
 | 
			
		||||
    } catch (err) {
 | 
			
		||||
      setError(true)
 | 
			
		||||
    }
 | 
			
		||||
  }, [path])
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    get()
 | 
			
		||||
  }, [get])
 | 
			
		||||
 | 
			
		||||
  if (data) {
 | 
			
		||||
    return { data, loading: false, error: false, refetch: get }
 | 
			
		||||
  } else if (error) {
 | 
			
		||||
    return { data: null, loading: false, error: true, refetch: get }
 | 
			
		||||
  } else {
 | 
			
		||||
    return { data: null, loading: true, error: false, refetch: get }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user