diff --git a/src/components/SearchModal/SearchModal.tsx b/src/components/SearchModal/SearchModal.tsx index bf860f1c..6374efd6 100644 --- a/src/components/SearchModal/SearchModal.tsx +++ b/src/components/SearchModal/SearchModal.tsx @@ -1,5 +1,6 @@ import React from 'react' import Portal from '~utils/Portal' +import api from '~utils/api' import Modal from '~components/Modal/Modal' import Overlay from '~components/Overlay/Overlay' @@ -8,7 +9,7 @@ import WeaponResult from '~components/WeaponResult/WeaponResult' import './SearchModal.css' interface Props { - close: () => void + close: OnClickEvent send: (weapon: Weapon, position: number) => any placeholderText: string fromPosition: number @@ -36,13 +37,13 @@ class SearchModal extends React.Component { } } - fetchResults = (query) => { - fetch(`http://127.0.0.1:3000/api/v1/search?query=${query}`) - .then(res => res.json()) - .then((result) => { - const totalResults = result.length + fetchResults = (query: string) => { + api.search(query) + .then((response) => { + const data = response.data + const totalResults = data.length this.setState({ - results: result, + results: data, totalResults: totalResults, loading: false }) diff --git a/src/components/WeaponGrid/WeaponGrid.tsx b/src/components/WeaponGrid/WeaponGrid.tsx index c0ba4315..53ea1246 100644 --- a/src/components/WeaponGrid/WeaponGrid.tsx +++ b/src/components/WeaponGrid/WeaponGrid.tsx @@ -1,5 +1,6 @@ import React, { useEffect, useState } from 'react' import { withRouter } from 'react-router' +import api from '~utils/api' import WeaponGridMainhand from '~components/WeaponGridMainhand/WeaponGridMainhand' import WeaponGridUnit from '~components/WeaponGridUnit/WeaponGridUnit' @@ -15,7 +16,7 @@ interface GridWeapon { type GridArray = { [key: number]: Weapon } -const WeaponGrid = (props: null) => { +const WeaponGrid = (props: {}) => { const [partyId, setPartyId] = useState() const [shortcode, setShortcode] = useState() @@ -29,25 +30,15 @@ const WeaponGrid = (props: null) => { if (shortcode) { fetchGrid(shortcode) - console.log(shortcode) } else { - console.log('nothing') + // There is no need to fetch a weapon } }, []) function fetchGrid(shortcode: string) { - const options = { - headers: { 'Content-Type': 'application/json' }, - method: 'GET' - } - - 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) + return api.endpoints.parties.getOne({ id: shortcode }) + .then(response => { + const grid = response.data.party.grid let weapons: GridArray = {} grid.forEach((gridWeapon: GridWeapon) => { @@ -71,11 +62,13 @@ const WeaponGrid = (props: null) => { if (partyId === undefined) { let _partyId = '' - createParty().then(data => { - setPartyId(data.party.id) - _partyId = data.party.id + createParty().then(response => { + const party = response.data.party - return data.party.shortcode + setPartyId(party.id) + _partyId = party.id + + return party.shortcode }) .then((code: string) => { setShortcode(shortcode) @@ -98,11 +91,16 @@ const WeaponGrid = (props: null) => { if (partyId === undefined) { let _partyId = '' - createParty().then(data => { - setPartyId(data.party.id) - _partyId = data.party.id + createParty().then(response => { + const party = response.data.party + 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(() => { saveWeapon(_partyId, weapon, position) @@ -113,56 +111,32 @@ const WeaponGrid = (props: null) => { } function createParty() { - const options = { - headers: { 'Content-Type': 'application/json' }, - method: 'POST' - } - - return fetch('http://127.0.0.1:3000/api/v1/party', options) - .then(response => response.json()) + return api.endpoints.parties.create({}) } function saveWeapon(pid: string, weapon: Weapon, position: number) { - const body = JSON.stringify({ + const body = { 'weapon': { 'party_id': pid, 'weapon_id': weapon.id, 'position': position, 'mainhand': false } - }) - - const options = { - headers: { 'Content-Type': 'application/json' }, - method: 'POST', - body: body } - fetch('http://127.0.0.1:3000/api/v1/weapons', options) - .then(data => { - console.log(data) - }) + api.endpoints.weapons.create(body) } function saveMainhand(pid: string, weapon: Weapon) { - const body = JSON.stringify({ + const body = { 'weapon': { 'party_id': pid, 'weapon_id': weapon.id, 'mainhand': true } - }) - - const options = { - headers: { 'Content-Type': 'application/json' }, - method: 'POST', - body: body } - fetch('http://127.0.0.1:3000/api/v1/weapons', options) - .then(data => { - console.log(data) - }) + api.endpoints.weapons.create(body) } return ( @@ -180,4 +154,4 @@ const WeaponGrid = (props: null) => { ) } -export default withRouter(WeaponGrid) \ No newline at end of file +export default withRouter(WeaponGrid) diff --git a/src/utils/api.tsx b/src/utils/api.tsx new file mode 100644 index 00000000..f15dc5d6 --- /dev/null +++ b/src/utils/api.tsx @@ -0,0 +1,60 @@ +import axios, { AxiosRequestConfig, AxiosResponse } from "axios" + +interface Entity { + name: string +} + +type CollectionEndpoint = ({ query }: { query: AxiosRequestConfig }) => Promise> +type IdEndpoint = ({ id }: { id: string }) => Promise> +type PostEndpoint = (object: {}) => Promise> + +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 \ No newline at end of file