-
Notifications
You must be signed in to change notification settings - Fork 28
Ran : Add Countries Project #8
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -61,7 +61,7 @@ body { | |
|
|
||
| .country-flag img { | ||
| display: block; | ||
| max-width: 100%; | ||
| /* max-width: 100%; */ | ||
| object-fit: cover; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here remove comment |
||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,85 @@ | ||
|
|
||
|
|
||
|
|
||
| const getAllCountriesData = async () => { | ||
| let isLoading = true; | ||
| try { | ||
| loading(isLoading); | ||
| const result = await fetch(`../FullCountriesData.json`); | ||
| if (!result.ok) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hardcoded strings should be extracted into constants file |
||
| throw "Failed to fetch data"; | ||
| } | ||
| const json = await result.json(); | ||
| // console.log(json); | ||
| return json; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove this comment |
||
| } | ||
| catch (error) { | ||
| console.log(error); | ||
| } finally { | ||
| isLoading = false; | ||
| loading(isLoading); | ||
| } | ||
| } | ||
|
|
||
| const loading = () => { | ||
| const loader = document.querySelector('.country-details') | ||
| ? document.querySelector('.country-details') | ||
| : document.querySelector('.countries-grid'); | ||
|
|
||
| if (loader) { | ||
| loader.innerHTML = ` | ||
| <div class="loader"> | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't use |
||
| <div class="spinner"> | ||
| <i class="fa-regular fa-circle-notch fa-spin icon"></i> | ||
| </div> | ||
| </div> | ||
| `; | ||
| } | ||
| else { | ||
| loader.innerHtml = ''; | ||
| } | ||
| } | ||
|
|
||
|
|
||
| const selectCountry = async (e) => { | ||
| const data = await getAllCountriesData(); | ||
| const countryName = e.target.closest(".country"); | ||
| const country = countryName.dataset.countryName; | ||
| const findCountry = data.find(({ name }) => name === country) | ||
|
|
||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good job I like it. |
||
| if (!findCountry) return; | ||
|
|
||
| window.location.href = `details.html?country=${country}`; | ||
| } | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can extract this code into service that exposes methods instead of writing the same logic again and again |
||
|
|
||
|
|
||
| const darkModeToggle = document.querySelector('.theme-toggle'); | ||
| darkModeToggle.addEventListener('click', () => { | ||
| const darkMode = darkModeToggle.classList.contains('dark-mode'); | ||
| const themeText = document.querySelector('.theme-text'); | ||
| const themeIcon = document.querySelector('.theme-toggle>i'); | ||
|
|
||
| themeIcon.classList.add('fa-moon'); | ||
| themeIcon.classList.remove('fa-sun'); | ||
| if (darkMode) { | ||
| document.body.style.backgroundColor = '#ffff'; | ||
| themeText.innerHTML = 'Dark Mode'; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use classes in here as well to style elements. |
||
| themeIcon.classList.add('fa-moon'); | ||
| themeIcon.classList.remove('fa-sun'); | ||
| darkModeToggle.classList.remove('dark-mode') | ||
| } | ||
| else { | ||
| themeText.innerText = 'Light Mode'; | ||
| document.body.style.backgroundColor = '#333'; | ||
| themeIcon.classList.add('fa-sun'); | ||
| themeIcon.classList.remove('fa-moon'); | ||
| darkModeToggle.classList.add('dark-mode'); | ||
| } | ||
| }); | ||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
|
|
||
| const getSelectedCountry = async () => { | ||
| const data = await getAllCountriesData(); | ||
| const displayCountry = document.querySelector('.country-details'); | ||
|
|
||
| let params = new URLSearchParams(document.location.search); | ||
| let countryName = params.get('country'); | ||
| if (!countryName) return; | ||
|
|
||
| const myCountry = data?.find(({ name }) => name === countryName); | ||
| console.log(countryName); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good work on destructuring here |
||
|
|
||
| const { name,nativeName,subRegion, flag, population, region, capital,topLevelDomain,currencies,languages ,borders} = myCountry; | ||
| displayCountry.innerHTML = ` | ||
| <div class="country-details "> | ||
| <div class="country-flag"style="width: 100%; max-width: 500px;height: 100%;"> | ||
| <img src="${flag}" alt="${name} Flag" style="width: 100%;object-fit: cover; height: 100%;" /> | ||
| </div> | ||
| <div class="country-info"> | ||
| <h2 class="country-title">${name}</h2> | ||
| <br/> | ||
| <div class="col-2"> | ||
| <ul> | ||
| <li><strong>Native Name: </strong>${nativeName}</li> | ||
| <li><strong>Population: </strong>${population}</li> | ||
| <li><strong>Region: </strong>${region}</li> | ||
| <li><strong>Sub Region: </strong>${subRegion}</li> | ||
| <li><strong>Capital: </strong>${capital}</li> | ||
| </ul> | ||
| <ul> | ||
| <li><strong>Top Level Domain: </strong>${topLevelDomain.map(item => item)}</li> | ||
| <li><strong>Currencies: </strong>${currencies.map(item => item)}</li> | ||
| <li><strong>Languages: </strong>${languages.map(item => item)}</li> | ||
| </ul> | ||
| </div> | ||
| <h2><strong>Border Countries: </strong></h2> | ||
| <div class="col-3"> | ||
| ${borders.length > 0? borders?.map(item => | ||
| ` | ||
| <button class="btn">${item}</button> | ||
| ` | ||
| ).join(' '): 'No border countries found.'} | ||
| </div> | ||
| </div> | ||
| </div> | ||
| `; | ||
|
|
||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
|
|
||
| const allCountries = async () => { | ||
| const data = await getAllCountriesData(); | ||
|
|
||
| const countries = document.querySelector('.countries-grid'); | ||
| countries.innerHTML = ''; | ||
|
|
||
| return data.forEach(item => { | ||
| countries.innerHTML += ` | ||
| <a | ||
| href="#" | ||
| class="country scale-effect" | ||
| data-country-name='${item.name}' | ||
| > | ||
| <div class="country-flag"> | ||
| <img | ||
| src='${item.flag}' | ||
| alt="'${item.name}' FLag" | ||
| /> | ||
| </div> | ||
| <div class="country-info"> | ||
| <h2 class="country-title">${item.name}</h2> | ||
| <ul class="country-brief"> | ||
| <li><strong>population: </strong>${item.population}</li> | ||
| <li><strong>Region: </strong>${item.region}</li> | ||
| <li><strong>capital: </strong>${item.capital}</li> | ||
| </ul> | ||
| </div> | ||
| </a> | ||
| ` | ||
| }); | ||
| } | ||
|
|
||
| const searchByRegion = async (e) => { | ||
| const data = await getAllCountriesData(); | ||
| const selectRegion = e.target.attributes[0].nodeValue; | ||
| const clearInputValue = document.querySelector('.search-input'); | ||
| if (clearInputValue.value !== '') clearInputValue.value = ''; | ||
|
|
||
|
|
||
| const regionData = data?.filter(({ region }) => { | ||
| if (region.toLowerCase() === selectRegion) | ||
| return region; | ||
| else if (selectRegion == 'all') | ||
| return region | ||
| }); | ||
|
|
||
| return displayCountries(regionData) | ||
|
|
||
| } | ||
|
|
||
| const displayCountries = (data) => { | ||
|
|
||
| const countries = document.querySelector('.countries-grid'); | ||
| countries.innerHTML = ''; | ||
|
|
||
| data?.forEach(({ name, flag, population, region, capital }) => { | ||
| countries.innerHTML += ` | ||
| <a | ||
| href="#" | ||
| class="country scale-effect" | ||
| data-country-name='${name}' | ||
| > | ||
| <div class="country-flag"> | ||
| <img | ||
| src='${flag}' | ||
| alt="'${name}' FLag" | ||
| /> | ||
| </div> | ||
| <div class="country-info"> | ||
| <h2 class="country-title">${name}</h2> | ||
| <ul class="country-brief"> | ||
| <li><strong>population: </strong>${population}</li> | ||
| <li><strong>Region: </strong>${region}</li> | ||
| <li><strong>capital: </strong>${capital}</li> | ||
| </ul> | ||
| </div> | ||
| </a> | ||
| ` | ||
| }); | ||
| } | ||
|
|
||
|
|
||
| const searchByInputCountries = async (e) => { | ||
| const data = await getAllCountriesData(); | ||
| let searchInput = e.target.value.toLowerCase() | ||
| let searchLength = searchInput.length; | ||
| const filteredData = data?.filter(({ name }) => { | ||
| const space = name.toLowerCase().indexOf(searchInput[0]); | ||
| if (name.slice(0, searchLength).toLowerCase() == searchInput) | ||
| return name; | ||
| else if (name[space - 1] === ' ' && name.slice(space, space + searchLength).toLowerCase() == searchInput) | ||
| return name; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Extract your complex condition into a variable or a function |
||
| }); | ||
|
|
||
| return displayCountries(filteredData); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| function toggleDropdown() { | ||
| const wrapper = document.querySelector('.dropdown-wrapper'); | ||
| wrapper.classList.toggle('open'); | ||
|
|
||
| if (wrapper.classList.contains('open')) { | ||
| document.addEventListener('click', handleOutsideClick); | ||
| } else { | ||
| document.removeEventListener('click', handleOutsideClick); | ||
| } | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Amazing work on removing your event listeners, it's really important practice |
||
| } | ||
|
|
||
| function handleOutsideClick(event) { | ||
| const wrapper = document.querySelector('.dropdown-wrapper'); | ||
| const body = document.querySelector('.dropdown-body'); | ||
| const header = document.querySelector('.dropdown-header'); | ||
|
|
||
| if (!body.contains(event.target) && !header.contains(event.target)) { | ||
| wrapper.classList.remove('open'); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same thing in here, extract complex logic into a variable or a function |
||
| document.removeEventListener('click', handleOutsideClick); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove the comments