From 648ffdef375d231c735440ee1981ff0c44f7d36d Mon Sep 17 00:00:00 2001 From: xenia_grib Date: Mon, 14 Sep 2026 13:09:40 +0200 Subject: [PATCH 1/4] docs: added generative AI documentation for Favorites.tsx --- t29-project-1/src/components/Favorites.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/t29-project-1/src/components/Favorites.tsx b/t29-project-1/src/components/Favorites.tsx index 9fc2e58..c97bcb6 100644 --- a/t29-project-1/src/components/Favorites.tsx +++ b/t29-project-1/src/components/Favorites.tsx @@ -20,6 +20,8 @@ export const Favorites: React.FC = ({ } aria-pressed={isViewingFavorites} > + {/*Generated with Gemini (September 2026) */} + {/*Prompt: Generate code that will create a star with rounded corners */} Date: Tue, 15 Sep 2026 14:08:19 +0200 Subject: [PATCH 2/4] feat: add catCard and a hook for catNavigation --- t29-project-1/src/App.tsx | 35 +++++---- t29-project-1/src/components/CatCard.css | 78 +++++++++++++++------ t29-project-1/src/components/CatCard.tsx | 52 +++++++++++--- t29-project-1/src/hooks/useCatNavigation.ts | 77 ++++++++++++++++++++ 4 files changed, 195 insertions(+), 47 deletions(-) create mode 100644 t29-project-1/src/hooks/useCatNavigation.ts diff --git a/t29-project-1/src/App.tsx b/t29-project-1/src/App.tsx index 54f1f06..d9b3191 100644 --- a/t29-project-1/src/App.tsx +++ b/t29-project-1/src/App.tsx @@ -1,31 +1,30 @@ -import { useState } from 'react'; +import { useCatNavigation } from './hooks/useCatNavigation'; import { NavPrevious, NavNext } from './components/ActionButtons'; import { CatCard } from './components/CatCard'; -import { Favorites } from './components/Favorites'; import './App.css'; export default function App() { - const [isViewingFavorites, setIsViewingFavorites] = useState(false); - - const handlePrevious = () => {}; - const handleNext = () => {}; + const { + currentCat, + isLoading, + error, + canGoPrevious, + handleNext, + handlePrevious, + } = useCatNavigation(); return (
- {/* Top bar containing ONLY the Star Button */} -
- setIsViewingFavorites(!isViewingFavorites)} - isViewingFavorites={isViewingFavorites} +
- {/* 3-Column Navigation Grid */} -
); -} \ No newline at end of file +} diff --git a/t29-project-1/src/components/CatCard.css b/t29-project-1/src/components/CatCard.css index 33bd049..beba7e9 100644 --- a/t29-project-1/src/components/CatCard.css +++ b/t29-project-1/src/components/CatCard.css @@ -1,31 +1,69 @@ -/* Card container using semantic article tag */ -article.cat-card { +/* Card Container */ +.cat-card-frame { + box-sizing: border-box; + display: flex; + flex-direction: column; + align-items: center; width: 100%; - max-width: 420px; - min-height: 480px; - background-color: #ffffff; - border: 2px solid #e2e8f0; + max-width: 400px; + background-color: #fff4c8; + border: 3px solid #7d5d75; border-radius: 16px; - padding: 1.5rem; - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05); + padding: 1rem; + gap: 0.75rem; +} + +/* Header Flex Layout to place Favorite in top-right */ +.card-header { + width: 100%; display: flex; - flex-direction: column; align-items: center; - justify-content: center; + justify-content: space-between; + position: relative; +} + +.breed-title { + margin: 0; + font-size: 1.25rem; + font-weight: 700; + color: #7d5d75; + flex-grow: 1; text-align: center; - margin: 0 auto; + /* Extra left margin offsets the favorite button width to keep title perfectly centered */ + margin-left: 2rem; } -/* Temporary image box placeholder */ -.card-image-placeholder { - width: 100%; - height: 300px; - background-color: #f1f5f9; - border: 2px dashed #cbd5e1; - border-radius: 12px; +.favorite-action { + display: flex; + align-items: center; + justify-content: flex-end; +} + +/* Image Viewport */ +.image-viewport { + box-sizing: border-box; + width: 90%; + aspect-ratio: 2/3; display: flex; align-items: center; justify-content: center; - color: #64748b; - font-weight: 500; + background-color: #fff4c8; + overflow: hidden; + margin: 0; +} + +.cat-image { + width: 100%; + height: 90%; + object-fit: contain; +} + +.status-text { + font-size: 0.95rem; + color: #7d5d75; + text-align: center; +} + +.status-text.error { + color: #dc2626; } diff --git a/t29-project-1/src/components/CatCard.tsx b/t29-project-1/src/components/CatCard.tsx index 5a84022..2f3f5ff 100644 --- a/t29-project-1/src/components/CatCard.tsx +++ b/t29-project-1/src/components/CatCard.tsx @@ -1,16 +1,50 @@ -import React from 'react'; +import { Favorites } from './Favorites'; +import { type CatData } from '../api/catApi'; import './CatCard.css'; -export const CatCard: React.FC = () => { +interface CatCardProps { + cat?: CatData | null; + isFavorite?: boolean; + onToggleFavorite?: () => void; + isLoading?: boolean; + error?: Error | null; +} + +export const CatCard = ({ + cat, + isFavorite = false, + onToggleFavorite, + isLoading = false, + error = null, +}: CatCardProps) => { return ( -
-
-

🐱 Cat Image Placeholder

+
+
+ +
+ +
+ {isLoading &&

Loading cat...

} + + {error &&

{error.message}

} + + {cat?.url && !isLoading && ( + Random cat + )} + + {!cat && !isLoading && !error && ( +

Use arrows to load a cat

+ )}
-

Breed Name Placeholder

-

Temperament description placeholder

); }; - -export default CatCard; diff --git a/t29-project-1/src/hooks/useCatNavigation.ts b/t29-project-1/src/hooks/useCatNavigation.ts new file mode 100644 index 0000000..50af1cc --- /dev/null +++ b/t29-project-1/src/hooks/useCatNavigation.ts @@ -0,0 +1,77 @@ +import { useState, useCallback, useEffect } from 'react'; +import { fetchCat, type CatData } from '../api/catApi'; + +const STORAGE_KEY_HISTORY = 'cat_app_history'; +const STORAGE_KEY_INDEX = 'cat_app_index'; + +export function useCatNavigation() { + const [history, setHistory] = useState(() => { + try { + const savedHistory = localStorage.getItem(STORAGE_KEY_HISTORY); + return savedHistory ? JSON.parse(savedHistory) : []; + } catch { + return []; + } + }); + + const [currentIndex, setCurrentIndex] = useState(() => { + try { + const savedIndex = localStorage.getItem(STORAGE_KEY_INDEX); + return savedIndex !== null ? Number(savedIndex) : -1; + } catch { + return -1; + } + }); + + const [isLoading, setIsLoading] = useState(false); + const [error, setError] = useState(null); + + const currentCat = history[currentIndex] || null; + const canGoPrevious = currentIndex > 0; + + // Sync state changes to localStorage + useEffect(() => { + try { + localStorage.setItem(STORAGE_KEY_HISTORY, JSON.stringify(history)); + localStorage.setItem(STORAGE_KEY_INDEX, currentIndex.toString()); + } catch (err) { + console.error('Failed to save cat history to localStorage:', err); + } + }, [history, currentIndex]); + + const handleNext = useCallback(async () => { + // If browsing backward in history, advance forward index + if (currentIndex < history.length - 1) { + setCurrentIndex((prev) => prev + 1); + return; + } + + // Fetch new cat + setIsLoading(true); + setError(null); + try { + const newCat = await fetchCat(); + setHistory((prev) => [...prev, newCat]); + setCurrentIndex((prev) => prev + 1); + } catch (err) { + setError(err instanceof Error ? err : new Error('Failed to load cat')); + } finally { + setIsLoading(false); + } + }, [currentIndex, history.length]); + + const handlePrevious = useCallback(() => { + if (canGoPrevious) { + setCurrentIndex((prev) => prev - 1); + } + }, [canGoPrevious]); + + return { + currentCat, + isLoading, + error, + canGoPrevious, + handleNext, + handlePrevious, + }; +} From d6aaf824ddd60855e942a8cb7c374045145123a3 Mon Sep 17 00:00:00 2001 From: xenia_grib Date: Tue, 15 Sep 2026 14:28:57 +0200 Subject: [PATCH 3/4] fix: deleted breed title from CatCard.css --- t29-project-1/src/components/CatCard.css | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/t29-project-1/src/components/CatCard.css b/t29-project-1/src/components/CatCard.css index beba7e9..fff6094 100644 --- a/t29-project-1/src/components/CatCard.css +++ b/t29-project-1/src/components/CatCard.css @@ -22,17 +22,6 @@ position: relative; } -.breed-title { - margin: 0; - font-size: 1.25rem; - font-weight: 700; - color: #7d5d75; - flex-grow: 1; - text-align: center; - /* Extra left margin offsets the favorite button width to keep title perfectly centered */ - margin-left: 2rem; -} - .favorite-action { display: flex; align-items: center; From 6c8bf5bdf6fca597bf12a35efac8adcec802810a Mon Sep 17 00:00:00 2001 From: xenia_grib Date: Tue, 15 Sep 2026 14:32:28 +0200 Subject: [PATCH 4/4] style: changed the position of favorite button --- t29-project-1/src/components/CatCard.css | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/t29-project-1/src/components/CatCard.css b/t29-project-1/src/components/CatCard.css index fff6094..06bdd1c 100644 --- a/t29-project-1/src/components/CatCard.css +++ b/t29-project-1/src/components/CatCard.css @@ -16,16 +16,16 @@ /* Header Flex Layout to place Favorite in top-right */ .card-header { width: 100%; - display: flex; align-items: center; - justify-content: space-between; - position: relative; + display: flex; + justify-content: flex-end; } .favorite-action { display: flex; align-items: center; - justify-content: flex-end; + justify-content: flex; + margin-left: auto; } /* Image Viewport */