aboutsummaryrefslogtreecommitdiff
path: root/countries.ts
blob: 79fe2f70f61a73a65f9450cbbff2f7c7791e0b5d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import * as nano from "https://deno.land/x/[email protected]/mod.ts";
import { environment } from "./environment/environment.ts";
import { Country } from "./models/country.model.ts";

export class Countries {
  list: Country[] = [];
  names: string[] = [];
  query = environment.queries;

  async sync(config?: { force: boolean }): Promise<Country[]> {
    const lastSynced = localStorage.getItem("lastSynced");
    const savedCountries = localStorage.getItem("countries");
    const week = environment.syncInterval * 23 * 60 * 60 * 1000;
    if (
      !savedCountries ||
      !lastSynced ||
      config?.force ||
      Date.now() - Number(lastSynced) > week
    ) {
      console.log(
        nano.cyan("Syncronizing countries database..."),
        config?.force
          ? ""
          : `\nThis will only happen every ${environment.syncInterval} days`
      );
      // Fetch and parse countries data from API
      const response = await fetch(environment.baseUrl + this.query);
      const countries = (await response.json()) as Country[];
      this.list = countries;
      localStorage.setItem("countries", JSON.stringify(countries));
      localStorage.setItem("lastSynced", JSON.stringify(Date.now()));
      console.log("Synced successfully");
    } else {
      this.list = JSON.parse(savedCountries);
    }
    this.names = this.list.map((c) => c.name.common);
    return this.list;
  }

  find(name: string): Country {
    // Replace snake case or kebab case with whitespaces
    name = name.toLowerCase().replace(/-|_/g, " ");

    // Find exact match first, then fall back to fuzzy match
    const country = this.list.find((c) => {
      const countryName = c.name.common.toLocaleLowerCase();
      return countryName === name || countryName.includes(name);
    });

    if (!country) {
      throw Error(`Cannot find country named ${name}`);
    }

    return country;
  }

  print(name: string) {
    const country = this.find(name);
    let currencies = [];
    let iteration = 0;
    for (const currencyAbbr in country.currencies) {
      iteration++;
      const currency = country.currencies[currencyAbbr];
      currencies.push(
        `${iteration > 1 ? "\t\t " : ""}${currency.name} [${
          currency.symbol
        }](${currencyAbbr})\n`
      );
    }

    let languages = [];
    for (const langAbbr in country.languages) {
      languages.push(country.languages[langAbbr] + " ");
    }

    console.log(
      nano.cyan("\nCountry:\t"),
      country.flag,
      country.name.common,
      nano.green("\nLanguages:\t"),
      ...languages,
      nano.green("\nCapital:\t"),
      country.capital[0],
      nano.green("\nRegion:\t\t"),
      country.region,
      nano.green("\nPopulation:\t"),
      country.population.toLocaleString(),
      nano.green("\nCurrencies:\t"),
      ...currencies
    );
  }

  random(): string {
    const randomNum = Math.floor(Math.random() * this.names.length);
    return this.names[randomNum];
  }
}