Skip to content

Commit

Permalink
milestone: have broken categories page WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
alex-cannon committed Nov 21, 2019
1 parent 7a98ff6 commit 7344f02
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 40 deletions.
11 changes: 11 additions & 0 deletions src/core/interfaces/asyncAction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export interface asyncAction {
type: string;
payload: any;
errorMessage: string;
}

export interface asyncState {
loading: boolean;
errorMessage: string;
data: any;
}
38 changes: 25 additions & 13 deletions src/core/store/services/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,22 @@ export const getServicesLoading = () => ({
errorMessage: null,
});

export default {
/**
* Handlers for the various types of data we want from the Sheets API
* They should return parsed sheet data, rather than the raw response
* from the API.
*/
// Returns *all* services as a single array—for use in search
getAllServices: () => async ({ services }, dispatch) => {
// Check if we have the google sheet
if (services) return;
/**
* Handlers for the various types of data we want from the Sheets API
* They should return parsed sheet data, rather than the raw response
* from the API.
*/
// Fetches all services and updates global state. "redux-thunk" action.
export const getAllServices = () => async (dispatch, getState) => {
// Check if we have the google sheet
const services = getState().services;
if (services.data)
return dispatch(getServicesError("Error: all services already loaded."));

let allServices = [];

try {
dispatch(getServicesLoading());
const types = await getSheetTitles();
const allServicesRes = await client.get("values:batchGet", {
params: {
Expand All @@ -78,11 +83,18 @@ export default {
return stringify(params, { indices: false });
},
});
const allServices = allServicesRes.data.valueRanges.reduce((list, type) => {
allServices = allServicesRes.data.valueRanges.reduce((list, type) => {
return [...list, ...type.values];
}, []);
dispatch(getServicesSuccess(allServices));
},
} catch (e) {
// Dispatch a 'failure' action if the request failed
return dispatch(getServicesError(DEFAULT_ERROR_MESSAGE));
}

dispatch(getServicesSuccess(allServices));
};

export default {
// Returns the spreadsheet's index sheet
getIndex: async () => {
const res = await getSheetByTitle("Index");
Expand Down
21 changes: 7 additions & 14 deletions src/core/store/services/reducers.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,10 @@
// Reducer that handles state for the useAPI hook
interface iAction {
type: string;
payload: any;
errorMessage: string;
}

interface iState {
loading: boolean;
errorMessage: string;
data: any;
}
import { asyncState, asyncAction } from "~/core/interfaces/asyncAction";

const getServicesReducer = (state: iState, action: iAction) => {
// Reducer that handles state for the useAPI hook
const getServicesReducer = (
state: asyncState = { loading: false, errorMessage: null, data: null },
action: asyncAction
) => {
switch (action.type) {
case "GET_SERVICES_LOADING":
return { ...state, loading: false, data: null, errorMessage: null };
Expand All @@ -30,7 +23,7 @@ const getServicesReducer = (state: iState, action: iAction) => {
errorMessage: null,
};
default:
throw new Error();
return state;
}
};

Expand Down
22 changes: 22 additions & 0 deletions src/core/store/services/useServices.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";
import { getAllServices } from "./actions";

/**
* Hook to use all services data. Service data is parsed into an object.
* Services object: { loading, errorMessage, data }
*/
const useServices = () => {
const services = useSelector(state => state.services);
const dispatch = useDispatch();

// Equivilent to componentDidMount
useEffect(() => {
if (services.data) return;
dispatch(getAllServices());
}, []);

return services;
};

export default useServices;
9 changes: 2 additions & 7 deletions src/core/store/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,6 @@ export const configureStore = initialState => {
};

export const initializeStore = () => {
return configureStore({
services: {
loading: false,
errorMessage: null,
data: null,
},
});
// State is intialized per reducer
return configureStore({});
};
8 changes: 5 additions & 3 deletions src/pages/categories/index.jsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import React, { Fragment } from "react";
import useServices from "~/core/store/services/useServices";
import styled from "styled-components";
import Logo from "~/components/logo";
import Loader from "~/components/loader";
import Error from "~/components/error";
import { H1 } from "~/components/typography";
import api, { useAPI } from "~/core/api";
import CategoryCard from "./category-card";

const StyledLogo = styled(Logo)({
Expand Down Expand Up @@ -39,7 +39,7 @@ const getCategories = data =>
);

const Categories = () => {
const { loading, errorMessage, data } = useAPI(api.getIndex);
const { loading, errorMessage, data } = useServices();

if (errorMessage) {
return <Error {...{ errorMessage }} />;
Expand All @@ -51,12 +51,14 @@ const Categories = () => {
<IntroText>Pick a category to see services in your area.</IntroText>
{loading ? (
<Loader />
) : (
) : data ? (
<CategoryList>
{getCategories(data).map(c => (
<CategoryCard key={c.slug} {...c} />
))}
</CategoryList>
) : (
"Oops, something went wrong!"
)}
</Fragment>
);
Expand Down
6 changes: 3 additions & 3 deletions src/pages/search/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Logo from "~/components/logo";
import Loader from "~/components/loader";
import InputAndSubmit from "~/components/inputAndSubmit";
import { H1 } from "~/components/typography";
import api, { useAPI } from "~/core/api";
import { useSelector } from "react-redux";
import ServiceCard from "~/pages/services/service-card";
import { formatService } from "~/core/utils";

Expand Down Expand Up @@ -58,8 +58,8 @@ const queryServices = (data, query) => {
};

const Search = () => {
const { loading, error, data } = useAPI(api.getAllServices);
const index = useAPI(api.getIndex);
const { loading, error, data } = useSelector(state => state.services);
const index = { error: null };
const urlQuery = new URLSearchParams(location.search);

const [searchValue, setSearchValue] = useState(urlQuery.get("s") || "");
Expand Down

0 comments on commit 7344f02

Please sign in to comment.