Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CountryLookup Project Submission #13

Open
3 of 6 tasks
infi opened this issue Nov 20, 2019 · 7 comments
Open
3 of 6 tasks

CountryLookup Project Submission #13

infi opened this issue Nov 20, 2019 · 7 comments

Comments

@infi
Copy link

infi commented Nov 20, 2019

Project Name / Title

CountryLookup

Your Name / Title

Infi

Project Description

CountryLookup helps you to find the most important information about a country without reading an entire wall of text. Among others, you quickly get things like languages, currencies, calling codes, and timezones.

What 3rd Party Web API do you plan to use?

REST Countries

Which of the following describes you:

  • YouTube Subscriber
  • Twitch Follower
  • Patreon Patron
  • Superchat Donor
  • Streamlabs Donor
  • Coding Garden Moderator
@w3cj
Copy link
Member

w3cj commented Nov 21, 2019

Looks great and well thought out. Feel free to get started.

@w3cj
Copy link
Member

w3cj commented Nov 23, 2019

How are things so far? Any updates to share?

@infi
Copy link
Author

infi commented Nov 24, 2019

It's pretty much done & deployed now: https://countrylookup.now.sh/

@w3cj
Copy link
Member

w3cj commented Nov 26, 2019

Would you like a UI review or a code review?

@infi
Copy link
Author

infi commented Nov 26, 2019

Mainly a code review, as I've not done Vanilla JS in a long time now.
However, feel free to point out any significant UI issues, if you have found any.

@w3cj
Copy link
Member

w3cj commented Dec 14, 2019

UI Review

  • Fonts choices are consistent
  • Body font is good for reading
  • Loading indicators are shown when there is background processing (API requests, calculations etc.)
    • Do not see a loading spinner
  • Page responds nicely to different screen sizes
    • Images resize accordingly
      • Images maintain aspect ratio
    • Columns break at smaller screen sizes

@w3cj
Copy link
Member

w3cj commented Dec 14, 2019

Code Review Checklist

README

  • Readme includes instructions for running the project locally

HTML

  • Consistent Indentation
  • Includes meta viewport tag for mobile devices
    • <meta name="viewport" content="width=device-width, initial-scale=1.0">
  • CSS Links and Font Links are in the head of the document
  • JavaScript files are linked at the bottom of the page OR at the top with an onload function OR at the top with a defer attribute
  • Uses semantic tags where available
    • Use a main element at the top level below the nav
  • Title / Header links back to home page
  • No extra elements. Only includes the necessary elements to make things work.

JavaScript

  • Consistent semicolon usage. Either do or do not. There is no inbetween.
  • Consistent quote usage. Either ' or ", don't mix.
  • Consistent indentation.
  • Reasonable max line length. Wrap / reformat code when it gets too long.
    • Line 57 and 77 are a little long
  • Variable / Function names are clear and concise.
    • No abbreviations.
  • Variable / Function naming convention is consistent.
    • camelCase or PascalCase or snake_case
  • Strings used more than once are in a variable.
    • API_URL etc.
  • Functions are as few lines as possible. Code reads like a sentence.
    • initializeSearch function is pretty long. Could be split up.
  • Function names dictate intent.
  • Nested loops avoided where possible.
  • Functions take in a reasonable number of parameters. Ideally 3 or less params. Otherwise, use an options object.
  • No extra variables.

CSS

  • Consistent indentation
  • Consistent naming convention
    • Uses app specific prefix where necessary
  • No duplicate styles. Re-use where applicable.

Refactor

Could possibly refactor initializeSearch to the below code. For the more complex transforms of the data, you could follow what was done with topLevelDomain.

const propertyNames = ["name", "capital", "region", "population", "demonym", "nativeName", "numericCode", "topLevelDomain"];

// This contains results
const resultContainer = {
    self: sel("#result-container"),
    children: {
        name: sel("#result-name"),
        flag: sel("#result-flag"),
        topLevelDomain: {
            self: sel("#result-tlds"),
            transform: (value) => value.join(", ") || ""
        },
        codes: sel("#result-codes"),
        callc: sel("#result-callc"),
        capital: sel("#result-capi"),
        aka: sel("#result-aka"),
        region: sel("#result-regio"),
        population: sel("#result-pop"),
        demonym: sel("#result-demonym"),
        time: sel("#result-time"),
        border: sel("#result-border"),
        nativeName: sel("#result-native"),
        numericCode: sel("#result-numeric"),
        lang: sel("#result-lang")
    }
}

async function getResult(query) {
    try {
        const res = await fetch("https://restcountries.eu/rest/v2/name/" + String(query))
        const body = await res.json()
        return body
    } catch (error) {
        error.title = "Failed to parse response"
        error.description = "Please make sure your query is valid."
        throw error
    }
}

/**
 * initializes a search
 * @param {String} query
 * @returns {void} 
 */
const initializeSearch = async (query) => {
    try {
        resultContainer.self.style.display = "none"
        errorContainer.self.style.display = "none"

        if (!query) {
            const queryError = new Error()
            queryError.title = "Searches cannot be empty"
            queryError.description = "Fun fact: This tool supports about 240 countries."
            throw queryError;
        }
    
        const body = await getResult(query)
    
        // WARNING: The following code is not great...
    
        const country = body[0]
        if (!country) {
            const notFoundError = new Error()
            notFoundError.title = "Not found"
            notFoundError.description = "No results were found to your query."
            throw notFoundError
        }

        console.log(country);

        resultContainer.self.style.display = "inherit"

        propertyNames.forEach(property => {
            const item = resultContainer.children[property]
            if (item.self) {
                item.self.innerText = item.transform(country[property])
            } else {
                item.innerText = country[property]
            }
        });

        // header
        resultContainer.children.flag.setAttribute("src", country.flag)

        // column 1
        resultContainer.children.codes.innerText = `2-Char: ${country.alpha2Code} / 3-Char: ${country.alpha3Code}`
        resultContainer.children.callc.innerText = country.callingCodes.map(x => "+" + x).join(", ") || ""

        // column 2
        resultContainer.children.aka.innerText = country.altSpellings.join(", ") || ""

        // column 3
        // just 2 sections, as those can get long already
        resultContainer.children.time.innerText = "UTC: " + country.timezones
            .map(x =>
                x // remove unneeded info
                    .replace("UTC", "")
                    .replace(":00", "")
            ).join(", ")
            || ""
        resultContainer.children.border.innerText = country.borders.join(", ") || "<nobody>"

        // column 4
        let languages = []
        country.languages.forEach(language => {
            languages.push(language.name)
        })
        resultContainer.children.lang.innerText = languages.join(", ") || ""
    
    } catch (e) {
        error(e.title, e.description);
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants