Skip to content
This repository was archived by the owner on Mar 17, 2025. It is now read-only.

PR: Dog Breed Challenge Fetch API #78

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
"jest": "^26.6.3",
"jest-environment-enzyme": "^7.1.1",
"jest-enzyme": "^7.1.1",
"node-sass": "^4.13.1",
"react": "^16.10.2",
"react-dom": "^16.10.2",
"rimraf": "^3.0.0",
Expand All @@ -58,6 +57,7 @@
"@hot-loader/react-dom": "16.10.2",
"react-hot-loader": "^4.12.15",
"react-redux": "^7.1.1",
"redux": "^4.0.4"
"redux": "^4.0.4",
"sass": "^1.66.1"
}
}
10 changes: 6 additions & 4 deletions src/components/App.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import React, { FC } from 'react'
import styled from '@emotion/styled'
import Header from './Header'
import React, { FC } from 'react';
import styled from '@emotion/styled';
import Header from './Header';
import FetchFilterDogBreedApi from './FetchFilterDogBreedApi';

const App: FC = () => {
return (
<Container>
<Header />
{/* <Header /> */}
{/* Happy coding! */}
<FetchFilterDogBreedApi></FetchFilterDogBreedApi>
</Container>
)
}
Expand Down
47 changes: 47 additions & 0 deletions src/components/FetchFilterDogBreedApi.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
* {
box-sizing: border-box;
}

.dog_breed{
text-align: center;
}
.filter_box{
width: 60%;
height: 10vh;
margin: auto;
display: block;
border: 1px solid rgb(97, 117, 163);
color: black;
}
.row{
border: 2px solid grey;
}
.column {
float: left;
width: 33.33%;
height: fit-content;
padding: 5px;
outline-width:2px solid grey;
}
.row::after {
content: "";
clear: both;
display: table;
}
.image-container {
position: relative;
}
.favorite-button {
position: absolute;
bottom: 10px;
right: 10px;
font-size: 24px;
background: transparent;
border: none;
cursor: pointer;
z-index: 1;
}
hr{
border: 2px solid black;
border-radius: 3px;
}
110 changes: 110 additions & 0 deletions src/components/FetchFilterDogBreedApi.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import React, { useEffect, useState } from "react";
import "./FetchFilterDogBreedApi.css";

function FetchFilterDogBreedApi() {
const [data, setData] = useState({ message: [], status: "idle" }); // to get api list
const [searchTitle, setSearchTitle] = useState(""); // to filter the result
const [favorites, setFavorites] = useState([]); // Initialize favorites as an empty array

useEffect(() => {
fetch("https://dog.ceo/api/breed/hound/images")
.then((res) => res.json())
.then((result) => {
//console.log(result);
setData({ message: result.message, status: "success" });
})
.catch((err) => {
console.log(err);
setData({ message: [], status: "error" });
});
}, []);

// To select toggle button favorites and unfavorites
const toggleFavorite = (image) => {
if (favorites.includes(image)) {
setFavorites(favorites.filter((fav) => fav !== image));
} else {
setFavorites([...favorites, image]);
}
};

// Filter the images based on the search input
const filteredImages = data.message.filter((item) =>
item.toLowerCase().includes(searchTitle.toLowerCase())
);

// Limit the displayed images to the first 10
const displayedImages = filteredImages.slice(0, 10);

return (
<div>
<h2 className="dog_breed">Dog Breeds</h2>
{/* Input box to search result */}
<input
type="text"
onChange={(e) => setSearchTitle(e.target.value)}
placeholder="Search for a breed..."
className="filter_box"
></input><i className="fa fa-search" />
<br></br>

{/* map loop to display all images in box*/}
{data.status === "success" ? (
<div className="row">
{displayedImages.map((item, index) => (
<div className="column image-container" key={index}>
<img
src={item}
alt={`Dog ${index}`}
className="img-thumbnail rounded"
style={{ width: "100%", height: "300px" }}
/>
{/* add favoriote toggle button */}
<button
onClick={() => toggleFavorite(item)}
style={{
fontSize: "30px",
color: favorites.includes(item) ? "red" : "white", // Change color based on favorite status
backgroundColor: "transparent",
border: "none",
}}
className="favorite-button"
>
&hearts;
</button>
</div>
))}
</div>

) : data.status === "error" ? (
<p>No images available</p>
) : (
<p>Loading...</p>
)}
<hr></hr>
<br></br>
<div className="row">
{favorites.length > 0 && <h2>Favorites</h2>}
{favorites.map((fav, index) => (
<div className="column image-container" key={index}>
<img src={fav} alt={`Dog ${index}`} className="img-thumbnail" style={{ width: "100%", height: "300px" }}/>
<button
onClick={() => toggleFavorite(fav)}
style={{
fontSize: "30px",
color: "red",
backgroundColor: "transparent",
border: "none",
}}
className="favorite-button"
>
&hearts;
</button>
</div>
))}
</div>
</div>
);
}

export default FetchFilterDogBreedApi;
Loading