update code

This commit is contained in:
veerjot_dm 2025-01-01 18:26:24 +05:30
parent 213e225797
commit 4a1b27f9c7
6 changed files with 80 additions and 61 deletions

View file

@ -1,4 +1,3 @@
/* General Styles */
body { body {
font-family: Arial, sans-serif; font-family: Arial, sans-serif;
margin: 0; margin: 0;
@ -8,14 +7,15 @@ body {
} }
h1 { h1 {
text-align: center; text-align: left;
margin: 0; margin: 0;
padding: 7px; padding: 7px;
font-family: 'Lucida Sans', 'Lucida Sans Regular', 'Lucida Grande', 'Lucida Sans Unicode', Geneva, Verdana, sans-serif; font-family: 'Lucida Sans', 'Lucida Sans Regular', 'Lucida Grande', 'Lucida Sans Unicode', Geneva, Verdana, sans-serif;
background-color: #ff6b6b78; background-color: #ff6b6b78;
} }
.filters { .filters {
text-align: center;
text-align: right;
margin: 0px; margin: 0px;
margin-bottom: 8px; margin-bottom: 8px;
background-color: #ff6b6b78; background-color: #ff6b6b78;
@ -23,6 +23,7 @@ h1 {
.filters input, .filters input,
.filters select { .filters select {
margin: 0 10px; margin: 0 10px;
padding: 8px; padding: 8px;
border-radius: 4px; border-radius: 4px;
@ -183,6 +184,32 @@ button:hover:not(:disabled) {
text-decoration: underline; text-decoration: underline;
font-family: 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif; 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 */ /* Responsive Design */
@media (max-width: 600px) { @media (max-width: 600px) {

View file

@ -6,19 +6,22 @@ import Favorites from "./components/Favorites";
import BreedInfoPage from "./components/BreedInfoPage"; import BreedInfoPage from "./components/BreedInfoPage";
import "./App.css"; import "./App.css";
import { debounce } from "lodash"; import { debounce } from "lodash";
const apikey ="live_8bnMZatSzkOR7eyT6o0iwDmXQuTxPI3deVWy0KY2ABxDkTMJdTYZ13S9lVFmrZRO"
const App = () => { const App = () => {
const [cats, setCats] = useState([]); const [cats, setCats] = useState([]);
const [loading, setLoading] = useState(true); 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 [favorites, setFavorites] = useState(JSON.parse(localStorage.getItem("favorites")) || []);
const [page, setPage] = useState(1); const [page, setPage] = useState(1);
const [randomCat,setRandomCat]=useState(null);
useEffect(() => { useEffect(() => {
const fetchCats = async () => { const fetchCats = async () => {
try { try {
setLoading(true); setLoading(true);
let queryParams = `?limit=20&page=${page}`; let queryParams = `?limit=20&page=${page}`;
if (filters.breed) queryParams += `&breed_ids=${filters.breed}`; if (filters.breed) queryParams += `&breed_ids=${filters.breed}`;
if (filters.hairLength) queryParams += `&hair_length=${filters.hairLength}`; if (filters.hairLength) queryParams += `&hair_length=${filters.hairLength}`;
if (filters.origin) queryParams += `&origin=${filters.origin}`; if (filters.origin) queryParams += `&origin=${filters.origin}`;
@ -26,32 +29,56 @@ const App = () => {
const response = await fetch( const response = await fetch(
`https://api.thecatapi.com/v1/images/search${queryParams}`, `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"); if (!response.ok) throw new Error("Failed to fetch data");
const data = await response.json(); const data = await response.json();
setCats((prevCats) => [...prevCats, ...data]); setCats((prevCats) => (page === 1 ? data : [...prevCats, ...data]));
} catch (err) { }
catch (err) {
console.error(err.message); console.error(err.message);
} finally { } finally {
setLoading(false); setLoading(false);
} }
}; };
fetchCats(); fetchCats();
}, [filters, page]); }, [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( const debouncedHandleFilterChange = useCallback(
debounce((updatedFilters) => setFilters(updatedFilters), 300), debounce((updatedFilters) => {
setFilters(updatedFilters);
setPage(1);
}, 300),
[] []
); );
const handleFilterChange = (e) => { const handleFilterChange = (e) => {
const { name, value } = e.target; const { name, value } = e.target;
debouncedHandleFilterChange({ ...filters, [name]: value }); debouncedHandleFilterChange({ ...filters, [name]: value });
}; };
return ( return (
@ -63,12 +90,26 @@ const App = () => {
<div> <div>
<h1>Cat Gallery</h1> <h1>Cat Gallery</h1>
<Filters filters={filters} onFilterChange={handleFilterChange} /> <Filters filters={filters} onFilterChange={handleFilterChange} />
<Gallery <Gallery
cats={cats} cats={cats}
loading={loading} loading={loading}
onLoadMore={() => setPage((prev) => prev + 1)} onLoadMore={() => setPage((prev) => prev + 1)}
onAddFavorite={(cat) => setFavorites([...favorites, cat])} onAddFavorite={(cat) => setFavorites([...favorites, cat])}
/> />
<button className="random-cat-button" onClick={fetchRandomCat}>
Show Me a Random Cat!
</button>
{randomCat && (
<div className="random-cat">
<h2>Random Cat</h2>
<img
src={randomCat.url}
alt="Random Cat"
className="random-cat-image"
/>
</div>
)}
<Favorites <Favorites
favorites={favorites} favorites={favorites}
onRemoveFavorite={(id) => onRemoveFavorite={(id) =>

View file

@ -2,7 +2,7 @@ import React, { useEffect, useState } from "react";
import { useParams, useNavigate } from "react-router-dom"; import { useParams, useNavigate } from "react-router-dom";
const API_URL = "https://api.thecatapi.com/v1"; 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 BreedInfoPage = () => {
const { id } = useParams(); const { id } = useParams();

View file

@ -1,6 +1,6 @@
import React from "react"; import React from "react";
const Filters = ({ filters, onFilterChange }) => { const Filters = ({ filters, onFilterChange}) => {
return ( return (
<div className="filters"> <div className="filters">

View file

@ -12,6 +12,7 @@ const Gallery = ({ cats, loading, onLoadMore, onAddFavorite }) => {
500:3, 500:3,
}; };
const handleCatClick =(cat)=>{ const handleCatClick =(cat)=>{
console.log('id',cat)
if (cat.breeds && cat.breeds[0] && cat.breeds[0].id) { if (cat.breeds && cat.breeds[0] && cat.breeds[0].id) {
navigate(`/breed/${cat.breeds[0].id}`); navigate(`/breed/${cat.breeds[0].id}`);
} else { } else {

View file

@ -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<Array>} - 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<Array>} - 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;
}
};