Decentralize api calls

This commit is contained in:
Justin Edmund 2020-09-18 03:32:57 -07:00
parent 6c11239503
commit 0852591a0a
3 changed files with 95 additions and 60 deletions

View file

@ -1,5 +1,6 @@
import React from 'react' import React from 'react'
import Portal from '~utils/Portal' import Portal from '~utils/Portal'
import api from '~utils/api'
import Modal from '~components/Modal/Modal' import Modal from '~components/Modal/Modal'
import Overlay from '~components/Overlay/Overlay' import Overlay from '~components/Overlay/Overlay'
@ -8,7 +9,7 @@ import WeaponResult from '~components/WeaponResult/WeaponResult'
import './SearchModal.css' import './SearchModal.css'
interface Props { interface Props {
close: () => void close: OnClickEvent
send: (weapon: Weapon, position: number) => any send: (weapon: Weapon, position: number) => any
placeholderText: string placeholderText: string
fromPosition: number fromPosition: number
@ -36,13 +37,13 @@ class SearchModal extends React.Component<Props, State> {
} }
} }
fetchResults = (query) => { fetchResults = (query: string) => {
fetch(`http://127.0.0.1:3000/api/v1/search?query=${query}`) api.search(query)
.then(res => res.json()) .then((response) => {
.then((result) => { const data = response.data
const totalResults = result.length const totalResults = data.length
this.setState({ this.setState({
results: result, results: data,
totalResults: totalResults, totalResults: totalResults,
loading: false loading: false
}) })

View file

@ -1,5 +1,6 @@
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from 'react'
import { withRouter } from 'react-router' import { withRouter } from 'react-router'
import api from '~utils/api'
import WeaponGridMainhand from '~components/WeaponGridMainhand/WeaponGridMainhand' import WeaponGridMainhand from '~components/WeaponGridMainhand/WeaponGridMainhand'
import WeaponGridUnit from '~components/WeaponGridUnit/WeaponGridUnit' import WeaponGridUnit from '~components/WeaponGridUnit/WeaponGridUnit'
@ -15,7 +16,7 @@ interface GridWeapon {
type GridArray = { [key: number]: Weapon } type GridArray = { [key: number]: Weapon }
const WeaponGrid = (props: null) => { const WeaponGrid = (props: {}) => {
const [partyId, setPartyId] = useState<string>() const [partyId, setPartyId] = useState<string>()
const [shortcode, setShortcode] = useState<string>() const [shortcode, setShortcode] = useState<string>()
@ -29,25 +30,15 @@ const WeaponGrid = (props: null) => {
if (shortcode) { if (shortcode) {
fetchGrid(shortcode) fetchGrid(shortcode)
console.log(shortcode)
} else { } else {
console.log('nothing') // There is no need to fetch a weapon
} }
}, []) }, [])
function fetchGrid(shortcode: string) { function fetchGrid(shortcode: string) {
const options = { return api.endpoints.parties.getOne({ id: shortcode })
headers: { 'Content-Type': 'application/json' }, .then(response => {
method: 'GET' const grid = response.data.party.grid
}
return fetch(`http://127.0.0.1:3000/api/v1/party/${shortcode}`, options)
.then(response => response.json())
.then(data => {
const grid = data.party.grid
const mainhand = grid.filter((gridWeapon: GridWeapon) => gridWeapon.mainhand)[0].weapon
setMainhand(mainhand)
let weapons: GridArray = {} let weapons: GridArray = {}
grid.forEach((gridWeapon: GridWeapon) => { grid.forEach((gridWeapon: GridWeapon) => {
@ -71,11 +62,13 @@ const WeaponGrid = (props: null) => {
if (partyId === undefined) { if (partyId === undefined) {
let _partyId = '' let _partyId = ''
createParty().then(data => { createParty().then(response => {
setPartyId(data.party.id) const party = response.data.party
_partyId = data.party.id
return data.party.shortcode setPartyId(party.id)
_partyId = party.id
return party.shortcode
}) })
.then((code: string) => { .then((code: string) => {
setShortcode(shortcode) setShortcode(shortcode)
@ -98,11 +91,16 @@ const WeaponGrid = (props: null) => {
if (partyId === undefined) { if (partyId === undefined) {
let _partyId = '' let _partyId = ''
createParty().then(data => { createParty().then(response => {
setPartyId(data.party.id) const party = response.data.party
_partyId = data.party.id setPartyId(party.id)
_partyId = party.id
return data.party.shortcode return party.shortcode
})
.then((code: string) => {
setShortcode(shortcode)
window.history.replaceState(null, `Grid Tool: ${code}`, `/p/${code}`)
}) })
.then(() => { .then(() => {
saveWeapon(_partyId, weapon, position) saveWeapon(_partyId, weapon, position)
@ -113,56 +111,32 @@ const WeaponGrid = (props: null) => {
} }
function createParty() { function createParty() {
const options = { return api.endpoints.parties.create({})
headers: { 'Content-Type': 'application/json' },
method: 'POST'
}
return fetch('http://127.0.0.1:3000/api/v1/party', options)
.then(response => response.json())
} }
function saveWeapon(pid: string, weapon: Weapon, position: number) { function saveWeapon(pid: string, weapon: Weapon, position: number) {
const body = JSON.stringify({ const body = {
'weapon': { 'weapon': {
'party_id': pid, 'party_id': pid,
'weapon_id': weapon.id, 'weapon_id': weapon.id,
'position': position, 'position': position,
'mainhand': false 'mainhand': false
} }
})
const options = {
headers: { 'Content-Type': 'application/json' },
method: 'POST',
body: body
} }
fetch('http://127.0.0.1:3000/api/v1/weapons', options) api.endpoints.weapons.create(body)
.then(data => {
console.log(data)
})
} }
function saveMainhand(pid: string, weapon: Weapon) { function saveMainhand(pid: string, weapon: Weapon) {
const body = JSON.stringify({ const body = {
'weapon': { 'weapon': {
'party_id': pid, 'party_id': pid,
'weapon_id': weapon.id, 'weapon_id': weapon.id,
'mainhand': true 'mainhand': true
} }
})
const options = {
headers: { 'Content-Type': 'application/json' },
method: 'POST',
body: body
} }
fetch('http://127.0.0.1:3000/api/v1/weapons', options) api.endpoints.weapons.create(body)
.then(data => {
console.log(data)
})
} }
return ( return (
@ -180,4 +154,4 @@ const WeaponGrid = (props: null) => {
) )
} }
export default withRouter(WeaponGrid) export default withRouter(WeaponGrid)

60
src/utils/api.tsx Normal file
View file

@ -0,0 +1,60 @@
import axios, { AxiosRequestConfig, AxiosResponse } from "axios"
interface Entity {
name: string
}
type CollectionEndpoint = ({ query }: { query: AxiosRequestConfig }) => Promise<AxiosResponse<any>>
type IdEndpoint = ({ id }: { id: string }) => Promise<AxiosResponse<any>>
type PostEndpoint = (object: {}) => Promise<AxiosResponse<any>>
interface EndpointMap {
getAll: CollectionEndpoint
getOne: IdEndpoint
create: PostEndpoint
update: PostEndpoint
destroy: IdEndpoint
}
class Api {
url: string
endpoints: { [key: string]: EndpointMap }
constructor({url}: {url: string}) {
this.url = url
this.endpoints = {}
}
createEntity(entity: Entity) {
this.endpoints[entity.name] = this.createEndpoints(entity)
}
createEntities(entities: Entity[]) {
entities.forEach(this.createEntity.bind(this))
}
createEndpoints({name}: {name: string}) {
const resourceUrl = `${this.url}/${name}`
return {
getAll: ({ query }: { query: AxiosRequestConfig }) => axios.get(resourceUrl, { params: { query }}),
getOne: ({ id }: { id: string }) => axios.get(`${resourceUrl}/${id}`),
create: (object: {}) => axios.post(resourceUrl, object),
update: (object: {}) => axios.put(resourceUrl, object),
destroy: ({ id }: { id: string }) => axios.delete(`${resourceUrl}/${id}`)
} as EndpointMap
}
search(query: string) {
const resourceUrl = `${this.url}/${name}`
return axios.get(`${resourceUrl}/search?query=${query}`)
}
}
const api: Api = new Api({ url: 'http://127.0.0.1:3000/api/v1' })
api.createEntity( { name: 'users' })
api.createEntity( { name: 'parties' })
api.createEntity( { name: 'weapons' })
export default api