-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #68 from CodeForFoco/issue-64-redux
I completed the requested changes, so I'll go ahead and merge.
- Loading branch information
Showing
15 changed files
with
367 additions
and
61 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,7 +2,7 @@ | |
"name": "fd-servicedirectory", | ||
"version": "1.0.0", | ||
"description": "PFA Service Directory", | ||
"main": "src/index.jsx", | ||
"main": "src/index.tsx", | ||
"repository": "[email protected]:CodeForFoco/fd-servicedirectory.git", | ||
"author": "Code for Fort Collins", | ||
"license": "MIT", | ||
|
@@ -49,14 +49,18 @@ | |
}, | ||
"dependencies": { | ||
"@types/jest": "^24.0.23", | ||
"@types/node": "^12.12.11", | ||
"axios": "0.18.1", | ||
"husky": "^2.4.0", | ||
"lodash": "^4.17.13", | ||
"polished": "^3.3.0", | ||
"qs": "^6.7.0", | ||
"react": "^16.8.6", | ||
"react": "^16.8.3", | ||
"react-dom": "^16.8.6", | ||
"react-redux": "^7.1.3", | ||
"react-router-dom": "^5.0.0", | ||
"redux": "^4.0.5", | ||
"redux-thunk": "^2.3.0", | ||
"styled-components": "^4.2.0", | ||
"styled-normalize": "^8.0.6", | ||
"ts-jest": "^24.1.0" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
import { useEffect } from "react"; | ||
import { useSelector, useDispatch } from "react-redux"; | ||
import { stringify } from "qs"; | ||
import { formatService } from "~core/utils"; | ||
|
||
import { ActionRequest, Request, FormattedService } from "~/types/services"; | ||
import { axiosClient as client, DEFAULT_ERROR_MESSAGE } from "~/core/constants"; | ||
|
||
export const useServices = (): Request => { | ||
const services = useSelector(state => state.services); | ||
const dispatch = useDispatch(); | ||
|
||
useEffect(() => { | ||
if (!services || !services.data) { | ||
dispatch(getAllServices); | ||
} | ||
}, []); | ||
|
||
return services; | ||
}; | ||
|
||
const getAllServices = async (dispatch: Function) => { | ||
dispatch(getServicesLoading()); | ||
|
||
try { | ||
const types = await getSheetTitles(); | ||
const allServicesRes = await client.get("values:batchGet", { | ||
params: { | ||
majorDimension: "ROWS", | ||
ranges: types, | ||
}, | ||
paramsSerializer: params => { | ||
return stringify(params, { indices: false }); | ||
}, | ||
}); | ||
|
||
dispatch( | ||
getServicesSuccess( | ||
allServicesRes.data.valueRanges.reduce((list, type) => { | ||
// Remove "Types, Id, etc..." row from service | ||
type.values.shift(); | ||
|
||
return [...list, type.values.map(service => formatService(service))]; | ||
}, []) | ||
) | ||
); | ||
} catch (e) { | ||
return dispatch(getServicesError(DEFAULT_ERROR_MESSAGE)); | ||
} | ||
}; | ||
|
||
const getSheetTitles = async () => { | ||
// sheetMetadata will be a list of sheets: { "sheets": [ { "properties": { "title": "Index" } }, ... ] } | ||
const sheetMetadata = await client.get("", { | ||
params: { | ||
fields: "sheets.properties.title", | ||
}, | ||
}); | ||
return sheetMetadata.data.sheets | ||
.map(sheet => sheet.properties.title) | ||
.filter(title => title !== "Index"); | ||
}; | ||
|
||
// Reducer that handles state for the useAPI hook | ||
export const getServicesReducer = ( | ||
state: Request = { loading: true, errorMessage: null, data: null }, | ||
action: ActionRequest | ||
) => { | ||
switch (action.type) { | ||
case "GET_SERVICES_LOADING": | ||
return { ...state, loading: true, data: null, errorMessage: null }; | ||
case "GET_SERVICES_ERROR": | ||
return { | ||
loading: false, | ||
data: null, | ||
errorMessage: action.errorMessage, | ||
}; | ||
case "GET_SERVICES_SUCCESS": | ||
return { | ||
loading: false, | ||
data: action.payload, | ||
errorMessage: null, | ||
}; | ||
default: | ||
return state; | ||
} | ||
}; | ||
|
||
export const getServicesSuccess = (payload: FormattedService[][]) => ({ | ||
type: "GET_SERVICES_SUCCESS", | ||
payload, | ||
errorMessage: null, | ||
}); | ||
|
||
export const getServicesError = (errorMessage: string) => ({ | ||
type: "GET_SERVICES_ERROR", | ||
payload: null, | ||
errorMessage, | ||
}); | ||
|
||
export const getServicesLoading = () => ({ | ||
type: "GET_SERVICES_LOADING", | ||
payload: null, | ||
errorMessage: null, | ||
}); | ||
|
||
export default useServices; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
import { useEffect } from "react"; | ||
import { useSelector, useDispatch } from "react-redux"; | ||
import { getSheetData } from "~/core/utils"; | ||
|
||
import { ActionRequest, Request } from "~/types/services"; | ||
import { | ||
axiosClient as client, | ||
DEFAULT_ERROR_MESSAGE, | ||
INDEX_SHEET_TITLE, | ||
} from "~/core/constants"; | ||
|
||
const useServicesIndex = (): Request => { | ||
const servicesIndex = useSelector(state => state.servicesIndex); | ||
const dispatch = useDispatch(); | ||
|
||
useEffect(() => { | ||
if (servicesIndex && servicesIndex.data) return; | ||
dispatch(getServicesIndex); | ||
}, []); | ||
|
||
return servicesIndex; | ||
}; | ||
|
||
const getServicesIndex = async (dispatch: Function) => { | ||
dispatch(getServicesIndexLoading()); | ||
|
||
try { | ||
const res = await getSheetByTitle(INDEX_SHEET_TITLE); | ||
dispatch(getServicesIndexSuccess(getSheetData(res.data))); | ||
} catch { | ||
dispatch(getServicesIndexError(DEFAULT_ERROR_MESSAGE)); | ||
} | ||
}; | ||
|
||
const getSheetByTitle = async title => | ||
await client.get("values:batchGet", { | ||
params: { | ||
majorDimension: "ROWS", | ||
ranges: title, | ||
}, | ||
}); | ||
|
||
export const getServicesIndexReducer = ( | ||
state: Request = { loading: true, errorMessage: null, data: null }, | ||
action: ActionRequest | ||
) => { | ||
switch (action.type) { | ||
case "GET_SHEET_INDEX_SUCCESS": | ||
return { loading: false, data: action.payload, errorMessage: null }; | ||
case "GET_SHEET_INDEX_ERROR": | ||
return { loading: false, data: null, errorMessage: action.errorMessage }; | ||
case "GET_SHEET_INDEX_LOADING": | ||
return { loading: true, data: null, errorMessage: null }; | ||
default: | ||
return state; | ||
} | ||
}; | ||
|
||
export const getServicesIndexSuccess = (payload): ActionRequest => ({ | ||
type: "GET_SHEET_INDEX_SUCCESS", | ||
payload, | ||
}); | ||
|
||
export const getServicesIndexError = (errorMessage): ActionRequest => ({ | ||
type: "GET_SHEET_INDEX_ERROR", | ||
errorMessage, | ||
}); | ||
|
||
export const getServicesIndexLoading = (): ActionRequest => ({ | ||
type: "GET_SHEET_INDEX_LOADING", | ||
}); | ||
|
||
export default useServicesIndex; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import axios from "axios"; | ||
|
||
export const API_KEY = process.env.GOOGLE_API_KEY; | ||
export const DEFAULT_ERROR_MESSAGE = "Something went wrong!"; | ||
export const INDEX_SHEET_TITLE = "Index"; | ||
export const SHEET_ID = | ||
process.env.SHEET_ID || "1ZPRRR8T51Tk-Co8h_GBh3G_7P2F7ZrYxPQDSYycpCUg"; | ||
|
||
// Create our API client and inject the API key into every request | ||
export const axiosClient = axios.create({ | ||
baseURL: `https://sheets.googleapis.com/v4/spreadsheets/${SHEET_ID}/`, | ||
params: { key: API_KEY }, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { createStore, combineReducers, applyMiddleware } from "redux"; | ||
import thunk from "redux-thunk"; | ||
import { getServicesReducer as services } from "~core/api/services/useServices"; | ||
import { getServicesIndexReducer as servicesIndex } from "~core/api/services/useServicesIndex"; | ||
|
||
const reducers = combineReducers({ | ||
services, | ||
servicesIndex, | ||
}); | ||
|
||
export const configureStore = initialState => { | ||
return createStore(reducers, initialState, applyMiddleware(thunk)); | ||
}; | ||
|
||
export const initializeStore = () => { | ||
// State is intialized per reducer | ||
return configureStore({}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.