diff --git a/country-explorer/src/components/App.css b/country-explorer/src/components/App.css index 8f26ef0..c1321cc 100644 --- a/country-explorer/src/components/App.css +++ b/country-explorer/src/components/App.css @@ -1,19 +1 @@ -.country-selection { - display: flex; - flex-wrap: wrap; - align-items: center; - justify-content: center; - gap: 0.5rem; - margin: 1rem; -} - -.country-selection select { - min-width: 0; - max-width: 100%; - padding: 0.5rem; - font: inherit; - color: var(--text-h); - background: var(--bg); - border: 1px solid var(--border); - border-radius: 4px; -} +/* Main layout styles go here. */ diff --git a/country-explorer/src/components/App.tsx b/country-explorer/src/components/App.tsx index a0b019f..0415156 100644 --- a/country-explorer/src/components/App.tsx +++ b/country-explorer/src/components/App.tsx @@ -2,24 +2,41 @@ import './App.css'; import { useState } from 'react'; import { useCountries } from '../hooks/useCountries'; import CountryCard from './CountryCard'; +import CountrySelector from './CountrySelector'; +import RegionFilter from './RegionFilter'; import Loading from './Loading'; import ErrorMessage from './ErrorMessage'; import NavigationControls from './NavigationControls'; function App() { const { countries, isLoading, isError, error, refetch } = useCountries(); + const [selectedRegion, setSelectedRegion] = useState(''); + // The fetched countries are European, so filter by their geographic subregion. + const getRegion = (country: (typeof countries)[number]) => + country.subregion?.trim() || country.region?.trim() || 'Unknown region'; + const regions = [...new Set(countries.map(getRegion))].sort(); + const availableRegions = + regions.includes(selectedRegion) || !selectedRegion + ? regions + : [...regions, selectedRegion].sort(); + const filteredCountries = selectedRegion + ? countries.filter((country) => getRegion(country) === selectedRegion) + : countries; const [selectedCountryCode, setSelectedCountryCode] = useState(null); const selectedCountry = - countries.find((country) => country.code === selectedCountryCode) ?? countries[0]; + filteredCountries.find((country) => country.code === selectedCountryCode) ?? + filteredCountries[0]; const activeCountryCode = selectedCountry?.code ?? null; - const activeCountryIndex = countries.findIndex((country) => country.code === activeCountryCode); + const activeCountryIndex = filteredCountries.findIndex( + (country) => country.code === activeCountryCode, + ); function navigateCountry(direction: -1 | 1) { setSelectedCountryCode((currentCode) => { - const currentIndex = countries.findIndex((country) => country.code === currentCode); - if (currentIndex === -1) return countries[0]?.code ?? null; + const currentIndex = filteredCountries.findIndex((country) => country.code === currentCode); + if (currentIndex === -1) return filteredCountries[0]?.code ?? null; - return countries[currentIndex + direction]?.code ?? currentCode; + return filteredCountries[currentIndex + direction]?.code ?? currentCode; }); } @@ -39,23 +56,19 @@ function App() {

Filters and selection

- {/* RegionFilter and SortSelector go here */} -
- - -
+ {/* SortSelector goes here */} + +
@@ -72,13 +85,17 @@ function App() { navigateCountry(-1)} onNext={() => navigateCountry(1)} /> ) : ( -

No countries available.

+

+ {selectedRegion + ? 'No countries match the selected region.' + : 'No countries available.'} +

)} {/* FavoriteButton goes here */}
diff --git a/country-explorer/src/components/CountrySelector.css b/country-explorer/src/components/CountrySelector.css new file mode 100644 index 0000000..5bd5534 --- /dev/null +++ b/country-explorer/src/components/CountrySelector.css @@ -0,0 +1,24 @@ +.country-selection { + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: center; + gap: 0.5rem; + margin: 1rem; +} + +.country-selection select { + min-width: 0; + max-width: 100%; + padding: 0.5rem; + font: inherit; + color: var(--text-h); + background: var(--bg); + border: 1px solid var(--border); + border-radius: 4px; +} + +.country-selection select:focus-visible { + outline: 2px solid var(--accent); + outline-offset: 3px; +} diff --git a/country-explorer/src/components/CountrySelector.tsx b/country-explorer/src/components/CountrySelector.tsx new file mode 100644 index 0000000..3b24caf --- /dev/null +++ b/country-explorer/src/components/CountrySelector.tsx @@ -0,0 +1,46 @@ +import { useId } from 'react'; +import type { Country } from '../types/country'; +import './CountrySelector.css'; + +interface CountrySelectorProps { + countries: Country[]; + selectedCountryCode: string | null; + onSelectCountry: (code: string) => void; + disabled?: boolean; +} + +function CountrySelector({ + countries, + selectedCountryCode, + onSelectCountry, + disabled = false, +}: CountrySelectorProps) { + const selectId = useId(); + + return ( +
+ + +
+ ); +} + +export default CountrySelector; diff --git a/country-explorer/src/components/RegionFilter.css b/country-explorer/src/components/RegionFilter.css new file mode 100644 index 0000000..a3aea2f --- /dev/null +++ b/country-explorer/src/components/RegionFilter.css @@ -0,0 +1,24 @@ +.region-filter { + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: center; + gap: 0.5rem; + margin: 1rem; +} + +.region-filter select { + min-width: 0; + max-width: 100%; + padding: 0.5rem; + font: inherit; + color: var(--text-h); + background: var(--bg); + border: 1px solid var(--border); + border-radius: 4px; +} + +.region-filter select:focus-visible { + outline: 2px solid var(--accent); + outline-offset: 3px; +} diff --git a/country-explorer/src/components/RegionFilter.tsx b/country-explorer/src/components/RegionFilter.tsx new file mode 100644 index 0000000..9f29a28 --- /dev/null +++ b/country-explorer/src/components/RegionFilter.tsx @@ -0,0 +1,39 @@ +import { useId } from 'react'; +import './RegionFilter.css'; + +interface RegionFilterProps { + regions: string[]; + selectedRegion: string; + onRegionChange: (region: string) => void; + disabled?: boolean; +} + +function RegionFilter({ + regions, + selectedRegion, + onRegionChange, + disabled = false, +}: RegionFilterProps) { + const selectId = useId(); + + return ( +
+ + +
+ ); +} + +export default RegionFilter;