Merge branch 'main' of github.com:dank-inc/mvp-django-react into main
This commit is contained in:
commit
87d8d8e815
|
@ -20,11 +20,9 @@ python manage.py createsuperuser --email admin@example.com --username admin --pa
|
||||||
|
|
||||||
# Frontend
|
# Frontend
|
||||||
|
|
||||||
- [x] useGet hook
|
|
||||||
- [x] User context
|
- [x] User context
|
||||||
- [x] auth api
|
- [x] auth api
|
||||||
- [ ] user crud api (new user flow)
|
- [ ] user crud api (new user flow)
|
||||||
- [ ] socket hook
|
|
||||||
|
|
||||||
# Backend
|
# Backend
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,22 @@
|
||||||
import { BrowserRouter } from 'react-router-dom'
|
import { BrowserRouter } from 'react-router-dom'
|
||||||
import { UserContextProvider } from './contexts/UserContext'
|
import { UserContextProvider } from './contexts/UserContext'
|
||||||
import { CoreLayout } from './app/CoreLayout'
|
import { CoreLayout } from './app/CoreLayout'
|
||||||
|
import { AppContextProvider } from './contexts/AppContext'
|
||||||
|
import { Api } from './api'
|
||||||
|
import { users } from './api/data/users'
|
||||||
|
|
||||||
import './scss/app.scss'
|
import './scss/app.scss'
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
|
const api = new Api({ mock: true, users })
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
|
<AppContextProvider api={api}>
|
||||||
<UserContextProvider>
|
<UserContextProvider>
|
||||||
<CoreLayout />
|
<CoreLayout />
|
||||||
</UserContextProvider>
|
</UserContextProvider>
|
||||||
|
</AppContextProvider>
|
||||||
</BrowserRouter>
|
</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()
|
wipeJWT()
|
||||||
// axios -> delete session?
|
// 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 { useHistory } from 'react-router'
|
||||||
|
|
||||||
import { User } from '../types'
|
import { User } from '../types'
|
||||||
import { getLoggedInUser, logIn, logOut } from '../api'
|
import { useAppContext } from './AppContext'
|
||||||
|
import { logOut } from '../api'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
children: React.ReactNode
|
children: React.ReactNode
|
||||||
|
@ -27,36 +28,17 @@ type Context = {
|
||||||
const UserContext = createContext<Context | null>(null)
|
const UserContext = createContext<Context | null>(null)
|
||||||
|
|
||||||
export const UserContextProvider = ({ children }: Props) => {
|
export const UserContextProvider = ({ children }: Props) => {
|
||||||
|
const { api } = useAppContext()
|
||||||
const history = useHistory()
|
const history = useHistory()
|
||||||
|
|
||||||
const [user, setUser] = useState<User | null>(null)
|
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) => {
|
const handleLogin = async (username: string, password: string) => {
|
||||||
try {
|
try {
|
||||||
const user = await logIn(username, password)
|
const { id } = await api.login(username, password)
|
||||||
if (!user) throw new Error('Problem logging in!')
|
if (!id) throw new Error('Problem logging in!')
|
||||||
|
const user = await api.getUser(id)
|
||||||
|
|
||||||
setUser(user)
|
setUser(user)
|
||||||
message.success(`logged in as ${user?.username}`, 0.5)
|
message.success(`logged in as ${user?.username}`, 0.5)
|
||||||
} catch (err) {
|
} 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 }
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user