From 4a1b27f9c79a9b950eab251f376ad83de975bd0f Mon Sep 17 00:00:00 2001 From: veerjot_dm Date: Wed, 1 Jan 2025 18:26:24 +0530 Subject: [PATCH] update code --- src/App.css | 33 ++++++++++++++++++-- src/App.js | 53 +++++++++++++++++++++++++++++---- src/components/BreedInfoPage.js | 2 +- src/components/Filters.js | 2 +- src/components/Gallery.js | 1 + src/utils/api.js | 50 ------------------------------- 6 files changed, 80 insertions(+), 61 deletions(-) diff --git a/src/App.css b/src/App.css index 3783830..5f116bc 100644 --- a/src/App.css +++ b/src/App.css @@ -1,4 +1,3 @@ -/* General Styles */ body { font-family: Arial, sans-serif; margin: 0; @@ -8,14 +7,15 @@ body { } h1 { - text-align: center; + text-align: left; margin: 0; padding: 7px; font-family: 'Lucida Sans', 'Lucida Sans Regular', 'Lucida Grande', 'Lucida Sans Unicode', Geneva, Verdana, sans-serif; background-color: #ff6b6b78; } .filters { - text-align: center; + +text-align: right; margin: 0px; margin-bottom: 8px; background-color: #ff6b6b78; @@ -23,6 +23,7 @@ h1 { .filters input, .filters select { + margin: 0 10px; padding: 8px; border-radius: 4px; @@ -183,6 +184,32 @@ button:hover:not(:disabled) { text-decoration: underline; font-family: 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif; } +.random-cat { + text-align: center; + margin: 20px 0; +} + +.random-cat-image { + max-width: 100%; + height: auto; + border-radius: 10px; +} + +.random-cat-button { + display: block; + margin: 20px auto; + padding: 10px 20px; + background-color: #ff6f61; + color: #fff; + border: none; + border-radius: 5px; + cursor: pointer; + font-size: 16px; +} + +.random-cat-button:hover { + background-color: #ff4f41; +} /* Responsive Design */ @media (max-width: 600px) { diff --git a/src/App.js b/src/App.js index bc17a47..917bf7b 100644 --- a/src/App.js +++ b/src/App.js @@ -6,19 +6,22 @@ import Favorites from "./components/Favorites"; import BreedInfoPage from "./components/BreedInfoPage"; import "./App.css"; import { debounce } from "lodash"; - +const apikey ="live_8bnMZatSzkOR7eyT6o0iwDmXQuTxPI3deVWy0KY2ABxDkTMJdTYZ13S9lVFmrZRO" const App = () => { const [cats, setCats] = useState([]); const [loading, setLoading] = useState(true); - const [filters, setFilters] = useState({ breed: "", hairLength: "" }); + const [filters, setFilters] = useState({ breed: "", hairLength: "" ,origin:"" }); const [favorites, setFavorites] = useState(JSON.parse(localStorage.getItem("favorites")) || []); const [page, setPage] = useState(1); + const [randomCat,setRandomCat]=useState(null); + useEffect(() => { const fetchCats = async () => { try { setLoading(true); let queryParams = `?limit=20&page=${page}`; + if (filters.breed) queryParams += `&breed_ids=${filters.breed}`; if (filters.hairLength) queryParams += `&hair_length=${filters.hairLength}`; if (filters.origin) queryParams += `&origin=${filters.origin}`; @@ -26,32 +29,56 @@ const App = () => { const response = await fetch( `https://api.thecatapi.com/v1/images/search${queryParams}`, { - headers: { "x-api-key": "live_8bnMZatSzkOR7eyT6o0iwDmXQuTxPI3deVWy0KY2ABxDkTMJdTYZ13S9lVFmrZRO" }, + headers: { "x-api-key": apikey }, } ); if (!response.ok) throw new Error("Failed to fetch data"); const data = await response.json(); - setCats((prevCats) => [...prevCats, ...data]); - } catch (err) { + setCats((prevCats) => (page === 1 ? data : [...prevCats, ...data])); + } + catch (err) { console.error(err.message); } finally { setLoading(false); } }; + fetchCats(); }, [filters, page]); + + const fetchRandomCat = async () => { + try { + const response = await fetch( + `https://api.thecatapi.com/v1/images/search?limit=1`, + { + headers: { "x-api-key": apikey }, + } + ); + + if (!response.ok) throw new Error("Failed to fetch random cat"); + + const data = await response.json(); + setRandomCat(data[0]); + } catch (err) { + console.error(err.message); + } + }; const debouncedHandleFilterChange = useCallback( - debounce((updatedFilters) => setFilters(updatedFilters), 300), + debounce((updatedFilters) => { + setFilters(updatedFilters); + setPage(1); + }, 300), [] ); const handleFilterChange = (e) => { const { name, value } = e.target; debouncedHandleFilterChange({ ...filters, [name]: value }); + }; return ( @@ -63,12 +90,26 @@ const App = () => {

Cat Gallery

+ setPage((prev) => prev + 1)} onAddFavorite={(cat) => setFavorites([...favorites, cat])} /> + + {randomCat && ( +
+

Random Cat

+ Random Cat +
+ )} diff --git a/src/components/BreedInfoPage.js b/src/components/BreedInfoPage.js index 28eae5c..2f3fef4 100644 --- a/src/components/BreedInfoPage.js +++ b/src/components/BreedInfoPage.js @@ -2,7 +2,7 @@ import React, { useEffect, useState } from "react"; import { useParams, useNavigate } from "react-router-dom"; const API_URL = "https://api.thecatapi.com/v1"; -const API_KEY = "live_8bnMZatSzkOR7eyT6o0iwDmXQuTxPI3deVWy0KY2ABxDkTMJdTYZ13S9lVFmrZRO"; // Replace with your actual API key +const API_KEY = "live_8bnMZatSzkOR7eyT6o0iwDmXQuTxPI3deVWy0KY2ABxDkTMJdTYZ13S9lVFmrZRO"; const BreedInfoPage = () => { const { id } = useParams(); diff --git a/src/components/Filters.js b/src/components/Filters.js index c168bf3..9ecec37 100644 --- a/src/components/Filters.js +++ b/src/components/Filters.js @@ -1,6 +1,6 @@ import React from "react"; -const Filters = ({ filters, onFilterChange }) => { +const Filters = ({ filters, onFilterChange}) => { return (
diff --git a/src/components/Gallery.js b/src/components/Gallery.js index 888b224..3e133f7 100644 --- a/src/components/Gallery.js +++ b/src/components/Gallery.js @@ -12,6 +12,7 @@ const Gallery = ({ cats, loading, onLoadMore, onAddFavorite }) => { 500:3, }; const handleCatClick =(cat)=>{ + console.log('id',cat) if (cat.breeds && cat.breeds[0] && cat.breeds[0].id) { navigate(`/breed/${cat.breeds[0].id}`); } else { diff --git a/src/utils/api.js b/src/utils/api.js index a4ad51c..e69de29 100644 --- a/src/utils/api.js +++ b/src/utils/api.js @@ -1,50 +0,0 @@ -const API_URL = "https://api.thecatapi.com/v1"; -const API_KEY = "live_8bnMZatSzkOR7eyT6o0iwDmXQuTxPI3deVWy0KY2ABxDkTMJdTYZ13S9lVFmrZRO"; - -/** - * Fetches a list of cat images with optional pagination. - * @param {number} limit - Number of images to fetch. - * @param {number} page - Page number for pagination. - * @returns {Promise} - A promise that resolves to an array of cat images. - */ -export const fetchCats = async (limit = 10, page = 1) => { - try { - const response = await fetch(`${API_URL}/images/search?limit=${limit}&page=${page}`, { - headers: { - "x-api-key": API_KEY, - }, - }); - - if (!response.ok) { - throw new Error(`Failed to fetch cats: ${response.statusText}`); - } - - return response.json(); - } catch (error) { - console.error("Error fetching cats:", error); - throw error; - } -}; - -/** - * Fetches a list of cat breeds. - * @returns {Promise} - A promise that resolves to an array of cat breeds. - */ -export const fetchBreeds = async () => { - try { - const response = await fetch(`${API_URL}/breeds`, { - headers: { - "x-api-key": API_KEY, - }, - }); - - if (!response.ok) { - throw new Error(`Failed to fetch breeds: ${response.statusText}`); - } - - return response.json(); - } catch (error) { - console.error("Error fetching breeds:", error); - throw error; - } -};