From c52f2fff83009dfe89ac93bebd1a169ada983126 Mon Sep 17 00:00:00 2001
From: bsfelizardo
Date: Sun, 6 Feb 2022 14:02:08 +0800
Subject: [PATCH 1/7] Updates from react 3
---
src/components/FullscreenWrapper.module.scss | 2 +-
src/constants/ActionTypes.js | 6 ++
src/global.css | 5 ++
src/pages/Home.jsx | 66 ++++++++++++++++++--
src/pages/Login.jsx | 5 ++
src/redux/actions/authActions.js | 14 ++---
src/redux/actions/dogActions.js | 23 +++++++
src/redux/reducers/authReducer.js | 4 ++
src/redux/reducers/dogReducer.js | 33 ++++++++++
src/redux/reducers/index.js | 2 +
10 files changed, 144 insertions(+), 16 deletions(-)
create mode 100644 src/redux/actions/dogActions.js
create mode 100644 src/redux/reducers/dogReducer.js
diff --git a/src/components/FullscreenWrapper.module.scss b/src/components/FullscreenWrapper.module.scss
index 066957a..0ffffdf 100644
--- a/src/components/FullscreenWrapper.module.scss
+++ b/src/components/FullscreenWrapper.module.scss
@@ -1,6 +1,6 @@
.wrapper {
width: 100%;
- height: 100vh;
+ height: 100%;
padding: 70px 30px 0;
color: var(--color-black);
diff --git a/src/constants/ActionTypes.js b/src/constants/ActionTypes.js
index 0eefe60..b7ace14 100644
--- a/src/constants/ActionTypes.js
+++ b/src/constants/ActionTypes.js
@@ -7,3 +7,9 @@ export const auth = keyMirror({
LOGOUT: null,
});
+
+export const dog = keyMirror({
+ FETCH_DOG_PENDING: null,
+ FETCH_DOG_COMPLETED: null,
+ FETCH_DOG_FAILED: null,
+});
\ No newline at end of file
diff --git a/src/global.css b/src/global.css
index efecfff..5264090 100644
--- a/src/global.css
+++ b/src/global.css
@@ -1,3 +1,8 @@
+.dog-img {
+ width: 250px;
+ height: 250px;
+}
+
.m-all-1 {
margin: var(--space-1);
}
diff --git a/src/pages/Home.jsx b/src/pages/Home.jsx
index 30f8287..c692c3b 100644
--- a/src/pages/Home.jsx
+++ b/src/pages/Home.jsx
@@ -1,17 +1,73 @@
-import { FullscreenWrapper, CustomLink } from "components";
+import { useEffect } from "react";
+import { useSelector, useDispatch } from "react-redux";
+
+import { FullscreenWrapper, CustomLink, Loader, Button, Input } from "components";
+
+import { fetchDogs } from "redux/actions/dogActions";
+import { useState } from "react";
function Home() {
- const userName = null;
+ const username = useSelector(s => s.auth.username);
+ const fetchingDogs = useSelector(s => s.dog.fetchingDogs);
+ const dogsList = useSelector(s => s.dog.dogsList);
+
+ const dispatch = useDispatch();
+
+ const [currentPage, setCurrentPage] = useState(0);
+
+ useEffect(function onMount(){
+ if (username){
+ dispatch(fetchDogs({page: currentPage}));
+ }
+ }, [currentPage]);
+
+ function handleCurrentPageDecrement() {
+ if (currentPage === 0) {
+ return;
+ }
+
+ setCurrentPage(currentPage -1);
+ }
+
+ function handleCurrentPageIncrement() {
+ setCurrentPage(currentPage +1);
+ }
return (
Doggo List
- {userName
- ? `Welcome, ${userName}!`
+ {username
+ ? `Welcome, ${username}!`
: "To see a list of doggos, please log in first."}
-
+ {username ? (
+
+
+
+
+
+ ) : ()
+ }
+ {fetchingDogs ? : (
+
+ {
+ dogsList.map((dog) => (
+

+ ))
+ }
+
+ )}
);
}
diff --git a/src/pages/Login.jsx b/src/pages/Login.jsx
index 1cf752d..a1f0066 100644
--- a/src/pages/Login.jsx
+++ b/src/pages/Login.jsx
@@ -28,6 +28,11 @@ function Login() {
function handleFormSubmit(e) {
e.preventDefault();
console.log(name, password);
+ if(!name || !password){
+ alert("Name and Password required");
+ }else{
+ dispatch(login(name));
+ }
// dispatch(login());
}
diff --git a/src/redux/actions/authActions.js b/src/redux/actions/authActions.js
index ef33c2b..2f00d7f 100644
--- a/src/redux/actions/authActions.js
+++ b/src/redux/actions/authActions.js
@@ -1,6 +1,6 @@
import { auth } from "constants/ActionTypes";
-export function login() {
+export function login(username) {
return async (dispatch) => {
dispatch({
type: auth.LOGIN_PENDING,
@@ -8,19 +8,13 @@ export function login() {
const hasError = false;
setTimeout(() => {
- if (hasError) {
dispatch({
- type: auth.LOGIN_FAILED,
+ type: auth.LOGIN_COMPLETED,
payload: {
- errorMessage: "Something went wrong, please try again later.",
+ username,
},
});
- } else {
- dispatch({
- type: auth.LOGIN_COMPLETED,
- });
- }
- }, 3000);
+ }, 0);
};
}
diff --git a/src/redux/actions/dogActions.js b/src/redux/actions/dogActions.js
new file mode 100644
index 0000000..55c3d09
--- /dev/null
+++ b/src/redux/actions/dogActions.js
@@ -0,0 +1,23 @@
+import { dog } from "constants/ActionTypes";
+
+import { default as fetchDogsAPI } from "utils/fetchDogs";
+
+export function fetchDogs({page = 0,limit = 10,} = {}){
+ return async (dispatch) => {
+ dispatch({
+ type: dog.FETCH_DOG_PENDING,
+ });
+
+ const dogsList = await fetchDogsAPI(
+ page,
+ limit,
+ );
+
+ dispatch({
+ type: dog.FETCH_DOG_COMPLETED,
+ payload: {
+ dogsList,
+ },
+ })
+ };
+}
\ No newline at end of file
diff --git a/src/redux/reducers/authReducer.js b/src/redux/reducers/authReducer.js
index 3935383..8e39b6c 100644
--- a/src/redux/reducers/authReducer.js
+++ b/src/redux/reducers/authReducer.js
@@ -5,6 +5,7 @@ const initialState = {
loginError: null, // Wrong credentials / sorry you can't login today
isLoggedIn: false,
+ username: null,
};
/**
@@ -22,10 +23,12 @@ export default function reducer(state = initialState, action = {}) {
}
case auth.LOGIN_COMPLETED: {
+ const { username } = action.payload;
return {
...state,
loginPending: false,
isLoggedIn: true,
+ username,
};
}
@@ -42,6 +45,7 @@ export default function reducer(state = initialState, action = {}) {
return {
...state,
isLoggedIn: false,
+ username: null,
};
}
diff --git a/src/redux/reducers/dogReducer.js b/src/redux/reducers/dogReducer.js
new file mode 100644
index 0000000..e870d16
--- /dev/null
+++ b/src/redux/reducers/dogReducer.js
@@ -0,0 +1,33 @@
+import { dog } from "constants/ActionTypes";
+
+const initialState = {
+ fetchingDogs: false,
+ dogsList: [],
+};
+
+export default function reducer(state = initialState, action = {}) {
+ switch(action.type){
+ case dog.FETCH_DOG_PENDING: {
+ return {
+ ...state,
+ fetchingDogs: true,
+ }
+ }
+ case dog.FETCH_DOG_COMPLETED: {
+ const { dogsList} = action.payload;
+ return {
+ ...state,
+ fetchingDogs: false,
+ dogsList,
+ }
+ }
+ case dog.FETCH_DOG_FAILED: {
+ return {
+ ...state,
+ fetchingDogs: false,
+ }
+ }
+ default:
+ return state
+ }
+}
\ No newline at end of file
diff --git a/src/redux/reducers/index.js b/src/redux/reducers/index.js
index a70e020..0e41afc 100644
--- a/src/redux/reducers/index.js
+++ b/src/redux/reducers/index.js
@@ -1,9 +1,11 @@
import { combineReducers } from "redux";
import auth from "redux/reducers/authReducer";
+import dog from "redux/reducers/dogReducer";
const rootReducer = combineReducers({
auth,
+ dog,
});
export default rootReducer;
From 4ba7bf91d715566c768277a91910d6d0d10a43e4 Mon Sep 17 00:00:00 2001
From: bsfelizardo
Date: Sun, 6 Feb 2022 23:05:57 +0800
Subject: [PATCH 2/7] Add input field on home page to specify number of photos
to display
---
src/pages/Home.jsx | 17 ++++++++++++++++-
src/redux/actions/dogActions.js | 4 ++--
src/utils/fetchDogs.js | 1 +
3 files changed, 19 insertions(+), 3 deletions(-)
diff --git a/src/pages/Home.jsx b/src/pages/Home.jsx
index c692c3b..8ba6219 100644
--- a/src/pages/Home.jsx
+++ b/src/pages/Home.jsx
@@ -14,13 +14,19 @@ function Home() {
const dispatch = useDispatch();
const [currentPage, setCurrentPage] = useState(0);
+ const [photoLimit, setPhotoLimit] = useState(10);
useEffect(function onMount(){
if (username){
- dispatch(fetchDogs({page: currentPage}));
+ dispatch(fetchDogs({page: currentPage, limit: photoLimit}));
}
}, [currentPage]);
+ function handleValueChange(e, valueCb) {
+ const newValue = e.target.value;
+ valueCb(newValue);
+ }
+
function handleCurrentPageDecrement() {
if (currentPage === 0) {
return;
@@ -56,6 +62,15 @@ function Home() {
disabled={fetchingDogs}
onClick={handleCurrentPageIncrement}
/>
+
+ handleValueChange(e, setPhotoLimit)}
+ />
+
) : ()
}
diff --git a/src/redux/actions/dogActions.js b/src/redux/actions/dogActions.js
index 55c3d09..e6e86af 100644
--- a/src/redux/actions/dogActions.js
+++ b/src/redux/actions/dogActions.js
@@ -8,10 +8,10 @@ export function fetchDogs({page = 0,limit = 10,} = {}){
type: dog.FETCH_DOG_PENDING,
});
- const dogsList = await fetchDogsAPI(
+ const dogsList = await fetchDogsAPI({
page,
limit,
- );
+ });
dispatch({
type: dog.FETCH_DOG_COMPLETED,
diff --git a/src/utils/fetchDogs.js b/src/utils/fetchDogs.js
index e56b345..40fae17 100644
--- a/src/utils/fetchDogs.js
+++ b/src/utils/fetchDogs.js
@@ -4,6 +4,7 @@ async function fetchDogs({
order = "ASC",
size = "med",
} = {}) {
+ console.log(page);
const response = await fetch(
`https://api.thedogapi.com/v1/images/search?limit=${limit}&page=${page}&order=${order}&size=${size}`
);
From fe39f0579d0a819f711f64750949202648668184 Mon Sep 17 00:00:00 2001
From: bsfelizardo
Date: Mon, 7 Feb 2022 10:40:07 +0800
Subject: [PATCH 3/7] Add select input in home Initial commit: -
src/components/Select.jsx: a select input component Update: -
src/components/index.js: export Select component - src/page/Home.jsx:
add select input
---
src/components/Select.jsx | 36 ++++++++++++++++++++++++++++++++++++
src/components/index.js | 1 +
src/pages/Home.jsx | 10 ++++++++--
src/utils/fetchDogs.js | 2 +-
4 files changed, 46 insertions(+), 3 deletions(-)
create mode 100644 src/components/Select.jsx
diff --git a/src/components/Select.jsx b/src/components/Select.jsx
new file mode 100644
index 0000000..fb74520
--- /dev/null
+++ b/src/components/Select.jsx
@@ -0,0 +1,36 @@
+import PropTypes from "prop-types";
+import classnames from "classnames";
+
+function Select({ name, disabled, className, options }) {
+ return (
+
+ );
+ }
+
+Select.propTypes = {
+ name: PropTypes.string.isRequired,
+ disabled: PropTypes.bool,
+ className: PropTypes.string,
+ options: PropTypes.array,
+};
+
+Select.defaultProps = {
+ name: "Select",
+ disabled: false,
+ className: null,
+ options: [],
+ };
+
+export default Select;
\ No newline at end of file
diff --git a/src/components/index.js b/src/components/index.js
index f82e569..99c94ac 100644
--- a/src/components/index.js
+++ b/src/components/index.js
@@ -3,3 +3,4 @@ export { default as CustomLink } from "components/CustomLink";
export { default as FullscreenWrapper } from "components/FullscreenWrapper";
export { default as Input } from "components/Input";
export { default as Loader } from "components/Loader";
+export { default as Select } from "components/Select";
diff --git a/src/pages/Home.jsx b/src/pages/Home.jsx
index 8ba6219..ae63407 100644
--- a/src/pages/Home.jsx
+++ b/src/pages/Home.jsx
@@ -1,7 +1,7 @@
import { useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";
-import { FullscreenWrapper, CustomLink, Loader, Button, Input } from "components";
+import { FullscreenWrapper, CustomLink, Loader, Button, Input, Select } from "components";
import { fetchDogs } from "redux/actions/dogActions";
import { useState } from "react";
@@ -70,6 +70,12 @@ function Home() {
className="m-bottom-2"
onChange={(e) => handleValueChange(e, setPhotoLimit)}
/>
+
) : ()
@@ -78,7 +84,7 @@ function Home() {
{
dogsList.map((dog) => (
-

+

))
}
diff --git a/src/utils/fetchDogs.js b/src/utils/fetchDogs.js
index 40fae17..3d04fca 100644
--- a/src/utils/fetchDogs.js
+++ b/src/utils/fetchDogs.js
@@ -2,7 +2,7 @@ async function fetchDogs({
limit = 10,
page = 0,
order = "ASC",
- size = "med",
+ size = "small",
} = {}) {
console.log(page);
const response = await fetch(
From c83e2bf87d3b5985eb0266b9fac9ab72d97c6eef Mon Sep 17 00:00:00 2001
From: bsfelizardo
Date: Mon, 7 Feb 2022 11:18:40 +0800
Subject: [PATCH 4/7] Add toggle button for ordering Update: - in
src/pages/Home.jsx: add button for selecting order and variable to
keep track of button state - in src/redux/actions/dogActions.js: add
order to parameters
---
src/pages/Home.jsx | 75 ++++++++++++++++++++-------------
src/redux/actions/dogActions.js | 3 +-
src/utils/fetchDogs.js | 4 +-
3 files changed, 50 insertions(+), 32 deletions(-)
diff --git a/src/pages/Home.jsx b/src/pages/Home.jsx
index ae63407..7750601 100644
--- a/src/pages/Home.jsx
+++ b/src/pages/Home.jsx
@@ -15,12 +15,19 @@ function Home() {
const [currentPage, setCurrentPage] = useState(0);
const [photoLimit, setPhotoLimit] = useState(10);
+ const [ascending, setAscending] = useState(true);
useEffect(function onMount(){
if (username){
- dispatch(fetchDogs({page: currentPage, limit: photoLimit}));
+ dispatch(fetchDogs(
+ {
+ page: currentPage,
+ limit: photoLimit,
+ order: ascending ? "ASC" : "DESC"
+ }
+ ));
}
- }, [currentPage]);
+ }, [currentPage, ascending]);
function handleValueChange(e, valueCb) {
const newValue = e.target.value;
@@ -39,6 +46,10 @@ function Home() {
setCurrentPage(currentPage +1);
}
+ function handleOrderChange() {
+ setAscending(!ascending);
+ }
+
return (
Doggo List
@@ -49,34 +60,40 @@ function Home() {
{username ? (
-
-
-
-
- handleValueChange(e, setPhotoLimit)}
- />
-
-
+ onClick={handleCurrentPageDecrement}
+ />
+
+
+
+ handleValueChange(e, setPhotoLimit)}
+ />
+
+
+
) : ()
}
diff --git a/src/redux/actions/dogActions.js b/src/redux/actions/dogActions.js
index e6e86af..833a8f8 100644
--- a/src/redux/actions/dogActions.js
+++ b/src/redux/actions/dogActions.js
@@ -2,7 +2,7 @@ import { dog } from "constants/ActionTypes";
import { default as fetchDogsAPI } from "utils/fetchDogs";
-export function fetchDogs({page = 0,limit = 10,} = {}){
+export function fetchDogs({page = 0,limit = 10, order = "ASC"} = {}){
return async (dispatch) => {
dispatch({
type: dog.FETCH_DOG_PENDING,
@@ -11,6 +11,7 @@ export function fetchDogs({page = 0,limit = 10,} = {}){
const dogsList = await fetchDogsAPI({
page,
limit,
+ order,
});
dispatch({
diff --git a/src/utils/fetchDogs.js b/src/utils/fetchDogs.js
index 3d04fca..ca339e1 100644
--- a/src/utils/fetchDogs.js
+++ b/src/utils/fetchDogs.js
@@ -2,9 +2,9 @@ async function fetchDogs({
limit = 10,
page = 0,
order = "ASC",
- size = "small",
+ size = "med",
} = {}) {
- console.log(page);
+ console.log(order);
const response = await fetch(
`https://api.thedogapi.com/v1/images/search?limit=${limit}&page=${page}&order=${order}&size=${size}`
);
From c252b22ef250a6086e425e0a668beaf44d85d25d Mon Sep 17 00:00:00 2001
From: bsfelizardo
Date: Mon, 7 Feb 2022 11:34:08 +0800
Subject: [PATCH 5/7] Add doggo name below each photo Update: - in
src/pages/Home.jsx: add label to each photo containing name from
dogsList
---
src/pages/Home.jsx | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/src/pages/Home.jsx b/src/pages/Home.jsx
index 7750601..ed1c560 100644
--- a/src/pages/Home.jsx
+++ b/src/pages/Home.jsx
@@ -101,7 +101,12 @@ function Home() {
{
dogsList.map((dog) => (
-

+
+

+
+
))
}
From aab3668660b03f3beea9a1dbf9e5c9d2fa0d6f79 Mon Sep 17 00:00:00 2001
From: bsfelizardo
Date: Mon, 7 Feb 2022 12:08:20 +0800
Subject: [PATCH 6/7] Add logout button Update: - in src/pages/Home.jsx: add a
button for logging out, clearn username after logging out, only
display doggos if username is available
---
src/pages/Home.jsx | 23 ++++++++++++++++-------
1 file changed, 16 insertions(+), 7 deletions(-)
diff --git a/src/pages/Home.jsx b/src/pages/Home.jsx
index ed1c560..435b055 100644
--- a/src/pages/Home.jsx
+++ b/src/pages/Home.jsx
@@ -1,10 +1,10 @@
-import { useEffect } from "react";
+import { useState, useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";
import { FullscreenWrapper, CustomLink, Loader, Button, Input, Select } from "components";
+import { logout } from "redux/actions/authActions";
import { fetchDogs } from "redux/actions/dogActions";
-import { useState } from "react";
function Home() {
const username = useSelector(s => s.auth.username);
@@ -50,6 +50,10 @@ function Home() {
setAscending(!ascending);
}
+ function handleLogout() {
+ dispatch(logout());
+ }
+
return (
Doggo List
@@ -78,26 +82,31 @@ function Home() {
type="text"
name="limit"
placeholder="Photo limit"
- className="m-bottom-2"
+ className="m-all-2"
onChange={(e) => handleValueChange(e, setPhotoLimit)}
/>
+
) : ()
}
- {fetchingDogs ? : (
+ {username ? ((fetchingDogs) ? : (
{
dogsList.map((dog) => (
@@ -110,7 +119,7 @@ function Home() {
))
}
- )}
+ )): null}
);
}
From 85c87c0f649295afba585efc31d1fbb01c4a06e7 Mon Sep 17 00:00:00 2001
From: bsfelizardo
Date: Thu, 17 Feb 2022 16:46:37 +0800
Subject: [PATCH 7/7] Add select input to specify size of image Updat: - in
src/pages/Home.jsx: add select component with options indicating size of
photos. add function handleSelectChange() to handle changes on select
component
---
src/components/Select.jsx | 3 ++-
src/global.css | 17 ++++++++++++++++-
src/pages/Home.jsx | 29 +++++++++++++++++++++--------
src/utils/fetchDogs.js | 3 +--
4 files changed, 40 insertions(+), 12 deletions(-)
diff --git a/src/components/Select.jsx b/src/components/Select.jsx
index fb74520..5c25d62 100644
--- a/src/components/Select.jsx
+++ b/src/components/Select.jsx
@@ -1,12 +1,13 @@
import PropTypes from "prop-types";
import classnames from "classnames";
-function Select({ name, disabled, className, options }) {
+function Select({ name, disabled, className, options, value }) {
return (