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 = () => {