Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft: Create reusable error and loading components #5

Draft
wants to merge 9 commits into
base: main
Choose a base branch
from
8 changes: 8 additions & 0 deletions client/.prettierrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module.exports = {
semi: true,
trailingComma: "all",
singleQuote: false,
printWidth: 80,
tabWidth: 4,
useTabs: true,
};
78 changes: 61 additions & 17 deletions client/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 1 addition & 3 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@reduxjs/toolkit": "^1.7.1",
"@testing-library/jest-dom": "^5.15.1",
"@testing-library/react": "^11.2.7",
"@testing-library/user-event": "^12.8.3",
Expand All @@ -13,9 +14,6 @@
"react-redux": "^7.2.6",
"react-router-dom": "^5.3.0",
"react-scripts": "4.0.3",
"redux": "^4.1.2",
"redux-devtools-extension": "^2.13.9",
"redux-thunk": "^2.4.1",
"web-vitals": "^1.1.2"
},
"scripts": {
Expand Down
28 changes: 0 additions & 28 deletions client/src/actions/propertyActions.js

This file was deleted.

3 changes: 0 additions & 3 deletions client/src/actions/types.js

This file was deleted.

15 changes: 15 additions & 0 deletions client/src/components/common/ReusableErrorAlert.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from "react";
import { Alert } from "antd";

const ReusableErrorAlert = ({ error }) => {
return error ? (
<Alert
type="error"
message={error}
showIcon
className="alert-margin--top"
/>
) : null;
};

export default ReusableErrorAlert;
12 changes: 12 additions & 0 deletions client/src/components/common/ReusableLoader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from "react";
import { Spin } from "antd";

const ReusableLoader = ({ loading }) => {
return loading ? (
<div className="spinner">
<Spin size="large" />
</div>
) : null;
};

export default ReusableLoader;
47 changes: 17 additions & 30 deletions client/src/pages/PropertyListPage.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { Alert, Col, Row, Spin } from "antd";
import { Col, Row } from "antd";
import React, { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { listProperties } from "../actions/propertyActions";
import { fetchPropertyList } from "../store/property/propertiesThunks";
import ReusableLoader from "../components/common/ReusableLoader";
import ReusableErrorAlert from "../components/common/ReusableErrorAlert";

function PropertyListPage() {
const dispatch = useDispatch();
Expand All @@ -11,37 +13,22 @@ function PropertyListPage() {
const { loading, error, properties } = propertiesList;

useEffect(() => {
dispatch(listProperties());
dispatch(fetchPropertyList());
}, [dispatch]);
return (
<>
{loading ? (
<div className="spinner">
<Spin size="large" />
</div>
) : error ? (
<Alert
type="error"
message={error}
showIcon
className="alert-margin--top"
/>
) : (
<>
<Row>
<Col span={24}>
<h2 className="margin--top">
Our Catalog of Properties
</h2>
</Col>
{properties.map((property) => (
<Col key={property.id} sm={12} md={6} lg={4} xs={3}>
<p>{property.title}</p>
</Col>
))}
</Row>
</>
)}
<ReusableLoader loading={loading} />
<ReusableErrorAlert error={error} />
<Row>
<Col span={24}>
<h2 className="margin--top">Our Catalog of Properties</h2>
</Col>
{properties.map((property) => (
<Col key={property.id} sm={12} md={6} lg={4} xs={3}>
<p>{property.title}</p>
</Col>
))}
</Row>
</>
);
}
Expand Down
6 changes: 0 additions & 6 deletions client/src/reducers/index.js

This file was deleted.

19 changes: 0 additions & 19 deletions client/src/reducers/propertyReducers.js

This file was deleted.

16 changes: 0 additions & 16 deletions client/src/store.js

This file was deleted.

10 changes: 10 additions & 0 deletions client/src/store/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { configureStore } from "@reduxjs/toolkit";
import propertiesListReducer from "./property/propertiesSlice";

const rootReducer = {
propertiesList: propertiesListReducer,
};

const store = configureStore({ reducer: rootReducer });

export default store;
32 changes: 32 additions & 0 deletions client/src/store/property/propertiesSlice.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { createSlice } from "@reduxjs/toolkit";

const initialState = {
properties: [],
loading: false,
error: undefined, // Optionally could be set to null or empty string. I find that undefined works best when using TypeScript
};

const propertiesSlice = createSlice({
name: "properties",
initialState,
reducers: {
propertyListRequest: (state, action) => {
state.loading = true;
state.error = undefined;
},
propertyListSuccess: (state, action) => {
state.loading = false;
state.error = undefined;
state.properties = action.payload.results;
},
propertyListFail: (state, action) => {
state.loading = false;
state.error = action.payload;
},
},
});

export const { propertyListRequest, propertyListSuccess, propertyListFail } =
propertiesSlice.actions;

export default propertiesSlice.reducer;
22 changes: 22 additions & 0 deletions client/src/store/property/propertiesThunks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import axios from "axios";

import {
propertyListRequest,
propertyListSuccess,
propertyListFail,
} from "./propertiesSlice";

export const fetchPropertyList = () => async (dispatch) => {
try {
dispatch(propertyListRequest());
const { data } = await axios.get("/api/v1/properties/all/");

dispatch(propertyListSuccess(data));
} catch (error) {
const errorMessage =
error.response && error.response.data.message
? error.response.data.message
: error.message;
dispatch(propertyListFail(errorMessage));
}
};