diff --git a/country-explorer/src/api/README.md b/country-explorer/src/api/README.md index a084bc0..baec3d9 100644 --- a/country-explorer/src/api/README.md +++ b/country-explorer/src/api/README.md @@ -71,17 +71,36 @@ This list includes a handful of dependent territories alongside sovereign states ## Data fields used -| Field (from the wireframe) | API key(s) | Notes | -| -------------------------- | -------------------------- | --------------------------------------------------------------------------------------- | -| Name | `name` | | -| Flag | `flags.svg`, `flags.png` | `flag` also gives an emoji flag | -| Capital | `capital` | | -| Region | `region`, `subregion` | Used by `RegionFilter` | -| Population | `population` | | -| Area | `area` | In km² | -| Currency | `currencies` | | -| Languages | `languages` | | -| — | `alpha2Code`, `alpha3Code` | Not shown in the UI; used internally as a stable id/key and for `/alpha/{code}` lookups | +| Field (from the wireframe) | API key(s) | Notes | +| -------------------------- | -------------------------------------------------------------------- | --------------------------------------------------------------------------------------- | +| Name | `name` | | +| Flag | `Mapped to flagUrl, `flags.png` | `flag` also gives an emoji flag | +| Capital | `capital` | | +| Region | `region`, `subregion` | Used by `RegionFilter` | +| Population | `population` | | +| Area | `area` | In km² | +| Currency | `currencies` | | +| Languages | `languages` | | +| — | `alpha2Code`, `Mapped to code for selection, favorites, and lookups` | Not shown in the UI; used internally as a stable id/key and for `/alpha/{code}` lookups | + +## TypeScript models + +The shared types are defined in `src/types/country.ts`: + +- `CountryApiResponse` describes the API fields used for one country. +- `CountriesApiResponse` describes the array returned by the region endpoint. +- `Country` describes the internal data model used by components. + +The `toCountry` function in `src/api/countries.ts` converts API data +into the internal model: + +- `alpha3Code` becomes `code`, a stable country identifier. +- `flags.svg` becomes `flagUrl`. +- Currencies become strings containing the currency name and code. +- Languages become strings containing the language name. + +Only fields required by the application are retained. +Favorite status is managed separately as application state. ## Error handling diff --git a/country-explorer/src/api/countries.ts b/country-explorer/src/api/countries.ts index dce6375..4f9144f 100644 --- a/country-explorer/src/api/countries.ts +++ b/country-explorer/src/api/countries.ts @@ -1,3 +1,5 @@ +import type { CountriesApiResponse, Country, CountryApiResponse } from '../types/country'; + const BASE_URL = 'https://countries.dev'; // Thrown for a failed request: a non-2xx response (status holds the real @@ -12,40 +14,9 @@ export class ApiError extends Error { } } -// The internal shape this module returns to the rest of the app. This is a -// placeholder until #8 ("Define TypeScript Types for Country Data") lands -// its own Country type in src/types/country.ts — once it does, delete this -// and the RawCountry type below, import that one instead, and point -// `toCountry` at it. Kept local to this file (instead of touching -// src/types/country.ts) so the two issues can be worked on in parallel -// without both branches editing the same file. -export interface Country { - name: string; - capital: string; - region: string; - subregion: string; - population: number; - area: number; - flagUrl: string; - currencies: string[]; - languages: string[]; -} - -// The relevant slice of the raw shape returned by https://countries.dev. -interface RawCountry { - name: string; - capital: string; - region: string; - subregion: string; - population: number; - area: number; - flags: { svg: string; png: string }; - currencies: { code: string; name: string; symbol: string }[]; - languages: { name: string }[]; -} - -function toCountry(raw: RawCountry): Country { +function toCountry(raw: CountryApiResponse): Country { return { + code: raw.alpha3Code, name: raw.name, capital: raw.capital, region: raw.region, @@ -84,12 +55,16 @@ async function fetchJson(url: string): Promise { // GET /region/{region} — every country in a region, e.g. "europe". export async function getCountriesByRegion(region: string): Promise { - const raw = await fetchJson(`${BASE_URL}/region/${encodeURIComponent(region)}`); + const raw = await fetchJson( + `${BASE_URL}/region/${encodeURIComponent(region)}`, + ); + return raw.map(toCountry); } // GET /alpha/{code} — a single country by ISO alpha-2 or alpha-3 code. export async function getCountryByAlpha(code: string): Promise { - const raw = await fetchJson(`${BASE_URL}/alpha/${encodeURIComponent(code)}`); + const raw = await fetchJson(`${BASE_URL}/alpha/${encodeURIComponent(code)}`); + return toCountry(raw); } diff --git a/country-explorer/src/types/country.ts b/country-explorer/src/types/country.ts index 2bd537b..3e9a2b4 100644 --- a/country-explorer/src/types/country.ts +++ b/country-explorer/src/types/country.ts @@ -1,48 +1,37 @@ -export interface Currency { - code: string; - name: string; - symbol: string; -} - -export interface Language { +// Relevant fields from a successful single-country API response. +export interface CountryApiResponse { + alpha3Code: string; name: string; - nativeName: string; - iso639_1: string; - iso639_2: string; + capital: string; + region: string; + subregion: string; + population: number; + area: number; + flags: { + svg: string; + }; + currencies: { + code: string; + name: string; + }[]; + languages: { + name: string; + }[]; } -export interface Flags { - png: string; - svg: string; -} +// Successful response from /region/{region}. +export type CountriesApiResponse = CountryApiResponse[]; -// Shape returned by https://countries.dev for both `/region/{region}` (as an -// array) and `/alpha/{code}` (as a single object). A few fields are missing -// on some entries (e.g. dependent territories don't have `cioc`/`gini`, and -// some don't have `borders`), so they're marked optional here. +// Internal country model used by application components. export interface Country { + code: string; name: string; - nativeName: string; - alpha2Code: string; - alpha3Code: string; - numericCode: string; capital: string; region: string; subregion: string; population: number; - populationDensity: number; area: number; - currencies: Currency[]; - languages: Language[]; - timezones: string[]; - latlng: [number, number]; - demonym: string; - flag: string; - flags: Flags; - independent: boolean; - callingCodes: string[]; - topLevelDomain: string[]; - borders?: string[]; - cioc?: string; - gini?: number; + flagUrl: string; + currencies: string[]; + languages: string[]; }