diff --git a/country-explorer/src/components/App.tsx b/country-explorer/src/components/App.tsx index 4b0a541..76f2fd6 100644 --- a/country-explorer/src/components/App.tsx +++ b/country-explorer/src/components/App.tsx @@ -1,6 +1,7 @@ import './App.css'; import { useEffect, useState } from 'react'; import { useCountries } from '../hooks/useCountries'; +import { useFavorites } from '../hooks/useFavorites'; import { isSortOption, sortCountries, type SortOption } from '../utils/sortCountries'; import { readSessionValue, writeSessionValue } from '../utils/sessionStorage'; import CountryCard from './CountryCard'; @@ -17,6 +18,7 @@ const SORT_STORAGE_KEY = 'sortOption'; function App() { const { countries, isLoading, isError, error, refetch } = useCountries(); + const { isFavorite, addFavorite, removeFavorite } = useFavorites(); // Lazily read any saved choice on first render, so the page opens already // showing what the user had before reloading within the same session. const [selectedRegion, setSelectedRegion] = useState( @@ -68,6 +70,14 @@ function App() { }); } + function toggleFavorite(code: string) { + if (isFavorite(code)) { + removeFavorite(code); + } else { + addFavorite(code); + } + } + // Keep the selection valid when data arrives or the available countries change. // Store the fallback so a removed country is not reselected if it returns later. if (selectedCountryCode !== activeCountryCode) { @@ -114,7 +124,11 @@ function App() { /> ) : selectedCountry ? ( <> - + toggleFavorite(selectedCountry.code)} + /> )} - {/* FavoriteButton goes here */}
diff --git a/country-explorer/src/components/CountryCard.css b/country-explorer/src/components/CountryCard.css index de7df82..c20369c 100644 --- a/country-explorer/src/components/CountryCard.css +++ b/country-explorer/src/components/CountryCard.css @@ -28,8 +28,17 @@ overflow-wrap: anywhere; } -.country-card h3 { +.country-card__heading-row { + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: space-between; + gap: 0.75rem; margin: 0 0 1rem; +} + +.country-card__heading-row h3 { + margin: 0; color: var(--text-h); font-size: 1.5rem; line-height: 1.3; diff --git a/country-explorer/src/components/CountryCard.tsx b/country-explorer/src/components/CountryCard.tsx index 8ff5923..318f1ff 100644 --- a/country-explorer/src/components/CountryCard.tsx +++ b/country-explorer/src/components/CountryCard.tsx @@ -1,9 +1,12 @@ import { useId } from 'react'; import type { Country } from '../types/country'; +import FavoriteButton from './FavoriteButton'; import './CountryCard.css'; interface CountryCardProps { country: Country; + isFavorite: boolean; + onToggleFavorite: () => void; } const numberFormatter = new Intl.NumberFormat('en-GB'); @@ -15,7 +18,7 @@ function formatNumber(value: number | null | undefined, unit = '') { : unavailable; } -function CountryCard({ country }: CountryCardProps) { +function CountryCard({ country, isFavorite, onToggleFavorite }: CountryCardProps) { const headingId = useId(); const name = country.name?.trim() || 'Unknown country'; @@ -27,7 +30,14 @@ function CountryCard({ country }: CountryCardProps) {

Flag not available

)}
-

{name}

+
+

{name}

+ +
Capital
diff --git a/country-explorer/src/components/FavoriteButton.css b/country-explorer/src/components/FavoriteButton.css new file mode 100644 index 0000000..9ffb4e7 --- /dev/null +++ b/country-explorer/src/components/FavoriteButton.css @@ -0,0 +1,35 @@ +.favorite-button { + display: inline-flex; + align-items: center; + gap: 0.4rem; + flex-shrink: 0; + min-height: 44px; + padding: 0.5rem 1rem; + font: inherit; + color: var(--text-h); + background: var(--bg); + border: 1px solid var(--border); + border-radius: 4px; + cursor: pointer; +} + +.favorite-button:hover { + background: var(--accent-bg); + border-color: var(--accent); +} + +.favorite-button:focus-visible { + outline: 2px solid var(--accent); + outline-offset: 3px; +} + +.favorite-button[aria-pressed='true'] { + color: var(--accent); + border-color: var(--accent); + background: var(--accent-bg); +} + +.favorite-button__icon { + font-size: 1.2em; + line-height: 1; +} diff --git a/country-explorer/src/components/FavoriteButton.tsx b/country-explorer/src/components/FavoriteButton.tsx new file mode 100644 index 0000000..8bd1902 --- /dev/null +++ b/country-explorer/src/components/FavoriteButton.tsx @@ -0,0 +1,30 @@ +import './FavoriteButton.css'; + +interface FavoriteButtonProps { + isFavorite: boolean; + countryName: string; + onToggleFavorite: () => void; +} + +function FavoriteButton({ isFavorite, countryName, onToggleFavorite }: FavoriteButtonProps) { + const label = isFavorite + ? `Remove ${countryName} from favorites` + : `Add ${countryName} to favorites`; + + return ( + + ); +} + +export default FavoriteButton;