diff --git a/submissions/igarok88/friends-app/index.html b/submissions/igarok88/friends-app/index.html new file mode 100644 index 0000000000..b0a4c22c55 --- /dev/null +++ b/submissions/igarok88/friends-app/index.html @@ -0,0 +1,122 @@ + + + + + + + + Friends App + + +
+
+
+ +
+ +
+

Sort by alphabet:

+
+
A - Z
+
Z - A
+
+ Reset +
+
+
+ +
+

Sort by age:

+
+
+
+
+ Reset +
+
+
+ +
+

Filter by age:

+
+
+ + +
+
+
+
Min age:
+ +
+
+
Max age:
+ +
+
+
+
+ +
+

Filter by gender:

+
+
+ All +
+
Male
+
Female
+
+
+ +
+

+ Users:  +

+

+  /  +

+
+
<
+
>
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+ + + diff --git a/submissions/igarok88/friends-app/script.js b/submissions/igarok88/friends-app/script.js new file mode 100644 index 0000000000..066d3627bb --- /dev/null +++ b/submissions/igarok88/friends-app/script.js @@ -0,0 +1,423 @@ +(async function () { + const ALL_USERS_LINK = + "https://randomuser.me/api/?inc=name,picture,dob,email,phone,location,gender,&results=5000"; + + const container = document.querySelector(".container"); + const userContainer = document.querySelector(".user__container"); + + const inputSearch = document.querySelector(".options-bar__search"); + + const arrowLeft = document.querySelector("#paginationLeft"); + const arrowRight = document.querySelector("#paginationRight"); + + const numberOfUsers = document.querySelector("#numberOfUsers"); + const totalPages = document.querySelector("#totalPages"); + const currentPage = document.querySelector("#currentPage"); + + let genderValue = "all"; + let searchValue = ""; + let sortByAgeValue = "reset"; + let sortByAlphabetValue = "reset"; + + let countPages = 1; + + let minAge; + let maxAge; + + let index1 = 0; + let index2 = 20; + + const getUsers = async (url) => { + try { + const response = await fetch(url).then((data) => data.json()); + const newUsers = response.results.map((user) => { + return { + name: `${user.name.first} ${user.name.last}`, + photoUrl: user.picture.medium, + age: user.dob.age, + email: user.email, + tel: user.phone, + location: user.location.city, + gender: user.gender, + }; + }); + + return newUsers; + } catch (e) { + console.error(e); + userContainer.innerHTML = "
Something went wrong
"; + } + }; + + const allUsers = await getUsers(ALL_USERS_LINK); + let currentUsers; + if (allUsers) { + currentUsers = allUsers.concat(); + } else { + return; + } + + container.addEventListener("click", async (e) => { + if (e.target.closest(".options-bar__gender .options-bar__btn")) { + activeBtnHandler(e, ".options-bar__gender .options-bar__btn"); + + genderValue = e.target.getAttribute("data-value"); + + currentUsers = await handlerUsers(allUsers); + } + + if (e.target.closest(".options-bar__sort-age .options-bar__btn")) { + activeBtnHandler(e, ".options-bar__sort-age .options-bar__btn"); + activeBtnHandler(e, ".options-bar__sort-name-alphabet .options-bar__btn"); + + sortByAgeValue = e.target.getAttribute("data-value"); + + sortByAlphabetValue = "reset"; + + currentUsers = await handlerUsers(allUsers); + } + + if ( + e.target.closest(".options-bar__sort-name-alphabet .options-bar__btn") + ) { + activeBtnHandler(e, ".options-bar__sort-name-alphabet .options-bar__btn"); + activeBtnHandler(e, ".options-bar__sort-age .options-bar__btn"); + + sortByAlphabetValue = e.target.getAttribute("data-value"); + + sortByAgeValue = "reset"; + + currentUsers = await handlerUsers(allUsers); + } + + if (e.target.closest(".options-bar__pagination")) { + if (e.target.closest("#paginationRight")) { + const numberRemainingUsers = currentUsers.slice(index2).length; + + if (numberRemainingUsers < 20 && numberRemainingUsers !== 0) { + index1 = currentUsers.length - numberRemainingUsers; + + if (20 > currentUsers.length) { + index1 = 0; + } + + index2 = currentUsers.length; + } + + if (index2 < currentUsers.length) { + index1 += 20; + index2 += 20; + arrowLeft.classList.remove("options-bar__btn_disabled"); + } + + if (index2 > currentUsers.length) { + index2 = currentUsers.length; + } + if (index2 === currentUsers.length) { + arrowRight.classList.add("options-bar__btn_disabled"); + } + + if (20 >= currentUsers.length) { + index1 = 0; + index2 = currentUsers.length; + } + + if (index1 >= 20) { + arrowLeft.classList.remove("options-bar__btn_disabled"); + } + + const users20 = currentUsers.slice(index1, index2); + + renderUsers(users20); + countPages++; + showPaginationInfo(currentUsers); + } + + if (e.target.closest("#paginationLeft")) { + if (index2 % index1) { + index2 -= index2 % index1; + index1 -= 20; + } else { + index2 -= 20; + index1 -= 20; + } + if (index1 <= 0) { + index1 = 0; + index2 = 20; + arrowLeft.classList.add("options-bar__btn_disabled"); + } + if (20 >= currentUsers.length) { + index1 = 0; + index2 = currentUsers.length; + } + + const users20 = currentUsers.slice(index1, index2); + + renderUsers(users20); + + const numberRemainingUsers = currentUsers.slice(index2).length; + if (numberRemainingUsers) { + arrowRight.classList.remove("options-bar__btn_disabled"); + } + countPages--; + showPaginationInfo(currentUsers); + } + } + }); + + const renderUsers = (users) => { + userContainer.innerHTML = ""; + users.forEach((user) => { + const { name, photoUrl, age, email, tel, location, gender } = user; + userContainer.innerHTML += ` +
+
${name} +
+ +
I have ${age} years old
+ + ${email} + + ${tel} + ${location} +
${gender}
+
+ `; + }); + }; + renderUsers(currentUsers.slice(0, 20)); + + inputSearch.addEventListener("input", async () => { + searchValue = inputSearch.value; + + currentUsers = await handlerUsers(allUsers); + }); + + const searchUserByName = async (users, str) => { + const filteredUsersName = users.filter((user) => { + if (user.name.toLowerCase().includes(str.toLowerCase())) { + return user; + } + }); + + return filteredUsersName; + }; + + const sortByAlphabet = (users) => { + if (sortByAlphabetValue === "reset") { + return users; + } + let newUsers; + if (sortByAlphabetValue === "A-Z") { + newUsers = users.sort((user, user2) => + user.name === user2.name ? 0 : user.name > user2.name ? 1 : -1 + ); + } + if (sortByAlphabetValue === "Z-A") { + newUsers = users.sort((user, user2) => + user.name === user2.name ? 0 : user.name < user2.name ? 1 : -1 + ); + } + + return newUsers; + }; + + const sortByAge = (users, sortAge) => { + if (sortAge === "reset") { + return users; + } + let newUsers; + if (sortAge === "up") { + newUsers = users.sort((user, user2) => user.age - user2.age); + } + if (sortAge === "down") { + newUsers = users.sort((user, user2) => user2.age - user.age); + } + + return newUsers; + }; + + minAge = sortByAge(currentUsers, "up")[0].age; + maxAge = sortByAge(currentUsers, "up")[currentUsers.length - 1].age; + + const rangeHandler = () => { + const controlRangeMin = (rangeMin, rangeMax, inputMin) => { + const [from, to] = getParsed(rangeMin, rangeMax); + fillSlider(rangeMin, rangeMax, "#C6C6C6", "#25daa5", rangeMax); + if (from > to) { + rangeMin.value = to; + inputMin.value = to; + } else { + inputMin.value = from; + } + }; + + const controlRangeMax = (rangeMin, rangeMax, inputMax) => { + const [from, to] = getParsed(rangeMin, rangeMax); + fillSlider(rangeMin, rangeMax, "#C6C6C6", "#25daa5", rangeMax); + setToggleAccessible(rangeMax); + if (from <= to) { + rangeMax.value = to; + inputMax.value = to; + } else { + inputMax.value = from; + rangeMax.value = from; + } + }; + + const getParsed = (currentFrom, currentTo) => { + const from = parseInt(currentFrom.value, 10); + const to = parseInt(currentTo.value, 10); + return [from, to]; + }; + + const fillSlider = (from, to, sliderColor, rangeColor, controlSlider) => { + const rangeDistance = to.max - to.min; + const fromPosition = from.value - to.min; + const toPosition = to.value - to.min; + controlSlider.style.background = `linear-gradient( + to right, + ${sliderColor} 0%, + ${sliderColor} ${(fromPosition / rangeDistance) * 100}%, + ${rangeColor} ${(fromPosition / rangeDistance) * 100}%, + ${rangeColor} ${(toPosition / rangeDistance) * 100}%, + ${sliderColor} ${(toPosition / rangeDistance) * 100}%, + ${sliderColor} 100%)`; + }; + + const setToggleAccessible = (currentTarget) => { + const rangeMax = document.querySelector("#rangeMax"); + if (Number(currentTarget.value) <= 0) { + rangeMax.style.zIndex = 2; + } else { + rangeMax.style.zIndex = 0; + } + }; + + const rangeMin = document.querySelector("#rangeMin"); + const rangeMax = document.querySelector("#rangeMax"); + const inputMin = document.querySelector("#inputMin"); + const inputMax = document.querySelector("#inputMax"); + + rangeMin.setAttribute("min", minAge); + rangeMin.setAttribute("max", maxAge); + rangeMin.setAttribute("value", minAge); + + rangeMax.setAttribute("min", minAge); + rangeMax.setAttribute("max", maxAge); + rangeMax.setAttribute("value", maxAge); + + inputMin.setAttribute("value", minAge); + + inputMax.setAttribute("value", maxAge); + + fillSlider(rangeMin, rangeMax, "#C6C6C6", "#25daa5", rangeMax); + setToggleAccessible(rangeMax); + + rangeMin.addEventListener("input", () => + controlRangeMin(rangeMin, rangeMax, inputMin) + ); + + rangeMin.addEventListener("click", async () => { + minAge = rangeMin.value; + currentUsers = await handlerUsers(allUsers); + }); + + rangeMax.addEventListener("input", () => + controlRangeMax(rangeMin, rangeMax, inputMax) + ); + rangeMax.addEventListener("click", async () => { + maxAge = rangeMax.value; + currentUsers = await handlerUsers(allUsers); + }); + }; + rangeHandler(); + + const filterByAge = (users, min, max) => { + const filteredUsers = users.filter( + (user) => user.age >= min && user.age <= max + ); + return filteredUsers; + }; + + const filterByGender = (users, sex) => { + if (sex === "all") { + return users; + } + const filteredUsersGender = users.filter((user) => user.gender === sex); + + index1 = 0; + index2 = 20; + arrowDisabledHandler(users); + + return filteredUsersGender; + }; + + const showPaginationInfo = (users) => { + numberOfUsers.innerHTML = users.length; + totalPages.innerHTML = Math.ceil(users.length / 20); + if (countPages < 1) { + countPages = 1; + } + if (countPages > Math.ceil(users.length / 20)) { + countPages = Math.ceil(users.length / 20); + } + currentPage.innerHTML = countPages; + }; + showPaginationInfo(currentUsers); + + const arrowDisabledHandler = (users) => { + index1 = 0; + index2 = 20; + + if (users.length <= 20) { + arrowRight.classList.add("options-bar__btn_disabled"); + arrowLeft.classList.add("options-bar__btn_disabled"); + } else { + arrowRight.classList.remove("options-bar__btn_disabled"); + arrowLeft.classList.remove("options-bar__btn_disabled"); + } + arrowLeft.classList.add("options-bar__btn_disabled"); + }; + arrowDisabledHandler(currentUsers); + + const activeBtnHandler = (e, elements) => { + const btns = document.querySelectorAll(elements); + btns.forEach((btn) => { + btn.classList.remove("options-bar__btn_active"); + }); + + e.target.classList.add("options-bar__btn_active"); + + const noActiveBtns = document.querySelectorAll( + ".options-bar__btn_no-active" + ); + noActiveBtns.forEach((btn) => { + btn.classList.remove("options-bar__btn_active"); + }); + }; + + const handlerUsers = async (users) => { + let newUsers = await searchUserByName(users, inputSearch.value); + + newUsers = sortByAge(newUsers, sortByAgeValue); + + newUsers = sortByAlphabet(newUsers, sortByAlphabetValue); + + newUsers = filterByAge(newUsers, minAge, maxAge); + + newUsers = filterByGender(newUsers, genderValue); + + arrowDisabledHandler(newUsers); + + renderUsers(newUsers.slice(0, 20)); + + countPages = 1; + + showPaginationInfo(newUsers); + + return newUsers; + }; +})(); diff --git a/submissions/igarok88/friends-app/style.css b/submissions/igarok88/friends-app/style.css new file mode 100644 index 0000000000..0631700a7c --- /dev/null +++ b/submissions/igarok88/friends-app/style.css @@ -0,0 +1,302 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; + font-family: Arial; + font-size: 20px; +} + +input[type="range"]::-webkit-slider-thumb { + -webkit-appearance: none; + pointer-events: all; + width: 24px; + height: 24px; + background-color: #fff; + border-radius: 50%; + box-shadow: 0 0 0 1px #c6c6c6; + cursor: pointer; +} + +input[type="range"]::-moz-range-thumb { + -webkit-appearance: none; + pointer-events: all; + width: 24px; + height: 24px; + background-color: #fff; + border-radius: 50%; + box-shadow: 0 0 0 1px #c6c6c6; + cursor: pointer; +} + +input[type="range"]::-webkit-slider-thumb:hover { + background: #f7f7f7; +} + +input[type="range"]::-webkit-slider-thumb:active { + box-shadow: inset 0 0 3px #387bbe, 0 0 9px #387bbe; + -webkit-box-shadow: inset 0 0 3px #387bbe, 0 0 9px #387bbe; +} + +input[type="text"]::-webkit-inner-spin-button, +input[type="text"]::-webkit-outer-spin-button { + opacity: 1; +} + +input[type="range"] { + -webkit-appearance: none; + appearance: none; + height: 2px; + width: 100%; + position: absolute; + background-color: #c6c6c6; + pointer-events: none; + padding-left: 20px; +} + +#rangeMin { + right: 20px; + top: 1px; + height: 0; + z-index: 1; +} + +.options-bar__filter-age-container { + padding: 10px 0; +} + +.options-bar__ranges { + position: relative; + min-height: 15px; +} + +.options-bar__inputs-age { + color: #fff; +} + +.options-bar__input-age-container { + display: flex; + justify-content: space-between; +} + +.options-bar__input-age-title { + margin: 15px 0; +} + +.options-bar__input { + background-color: transparent; + margin: 15px 0; + text-align: center; + color: #fff; + width: 55px; + border: none; +} + +.container { + margin: 0 auto; + display: flex; +} + +.options-bar { + background-color: rgb(48, 175, 192); + min-height: 100px; + padding: 25px; +} + +.options-bar__option { + padding: 10px 0; + border-bottom: 2px solid #fff; +} + +.options-bar__search { + padding: 10px; +} + +.options-bar__title { + color: #fff; + display: flex; + align-items: center; + padding: 10px 0; +} + +.options-bar__btn-container { + display: flex; + margin: 0 -5px; +} + +.options-bar__btn { + cursor: pointer; + color: #fff; + padding: 5px 15px; + margin: 5px; + background-color: rgb(79, 189, 154); + border-radius: 10px; + border: 1px solid #fff; + transition: all 0.3s ease; +} + +.options-bar__btn:hover { + background-color: rgb(119, 121, 224); +} + +.options-bar__btn_active { + background-color: rgb(241, 131, 131); +} + +.options-bar__btn:hover.options-bar__btn_active { + background-color: rgb(241, 131, 131); +} + +.options-bar__btn_disabled { + background-color: rgb(159, 185, 178); +} + +.options-bar__btn:hover.options-bar__btn_disabled { + background-color: rgb(159, 185, 178); + cursor: not-allowed; +} + +.options-bar__range { + display: flex; + height: 70px; +} + +.user__container { + position: relative; + background-color: rgb(79, 189, 154); + width: 100%; + min-height: 100vh; + padding: 15px; + display: flex; + align-content: flex-start; + flex-wrap: wrap; +} + +.user__container-spiner { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +} + +.user__container * { + font-size: 16px; +} + +.user__card { + display: flex; + flex-direction: column; + color: #000; + width: 200px; + background-color: #fff; + text-align: center; + margin: 5px; + border-radius: 10px; + transition: all 0.5s ease; +} + +.user__card:hover { + box-shadow: 0px 0px 10px 3px rgba(21, 7, 104, 0.685); +} + +.user__info { + display: flex; + flex-direction: column; +} + +.user__name { + flex: 1 1 auto; + color: #fff; + padding: 10px; + font-size: 18px; + border-top-left-radius: 10px; + border-top-right-radius: 10px; + background-color: rgb(101, 151, 209); + text-overflow: ellipsis; + overflow: hidden; +} + +.user__name_female { + background-color: rgb(236, 124, 221); +} + +.user__photo { + padding: 10px; + width: 200px; + height: 200px; + border-radius: 50%; +} + +.user__age { + padding: 5px 10px; + font-weight: bold; +} + +.user__link { + padding: 5px 10px; + font-size: 14px; + color: #000; + text-decoration: none; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; +} + +.user__link:hover { + text-decoration: underline; +} + +.user__location { + font-weight: bold; +} + +.user__gender { + padding: 10px; + text-transform: uppercase; + border-top: 1px solid #000; +} + +.lds-ring { + display: inline-block; + position: relative; + width: 80px; + height: 80px; +} + +.lds-ring div { + box-sizing: border-box; + display: block; + position: absolute; + width: 64px; + height: 64px; + margin: 8px; + border: 8px solid #fff; + border-radius: 50%; + animation: lds-ring 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite; + border-color: #fff transparent transparent transparent; +} + +.lds-ring div:nth-child(1) { + animation-delay: -0.45s; +} + +.lds-ring div:nth-child(2) { + animation-delay: -0.3s; +} + +.lds-ring div:nth-child(3) { + animation-delay: -0.15s; +} + +@keyframes lds-ring { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } +} + +.error { + color: red; + font-size: 28px; +}