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

Friends app #95

Merged
merged 9 commits into from
Sep 8, 2022
71 changes: 71 additions & 0 deletions submissions/asaMitaka/FriendsApp/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Friends App</title>
<link rel="stylesheet" href="style.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Roboto+Condensed:ital@1&display=swap" rel="stylesheet">
</head>
<body>
<div class="container">
<header class="header">
<a class='header__a' href="https://kottans.org/" target="_blank">Kottans</a>
</header>

<main class="mainBlock">
<div class="asideBlock">
<form name="age" id="ageForm">
<div class="asideBlock__items">
<p>By Age</p>
<input type="radio" name="sort" id="ageMore">
<label for="ageMore">Age < </label>
<input type="radio" name="sort" id="ageLess">
<label for="ageLess">Age > </label>
</div>
<div class="asideBlock__items">
<p>By Last Name</p>
<input type="radio" name="sort" id="lastAToZ">
<label for="lastAToZ">A-Z</label>
<input type="radio" name="sort" id="lastZToA">
<label for="lastZToA">Z-A</label>
</div>
</form>

<form name="gender" id="genderForm">
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're still using separate forms. It makes your code more complicated in the JS. Why not tie it up in one form?

<div class="asideBlock__items">
<input type="radio" id="male"
name="gender">
<label for="male" class="gender">Male</label>

<input type="radio" id="female"
name="gender">
<label for="female">Female</label>

<input type="radio" id="all"
name="gender" checked>
<label for="all">All</label>
</div>
</form>

<div class="asideBlock__items">
<p>Search: </p>
<input type="text" name="search" id="search">
</div>

<div class="asideBlock__items">
<button id="reset">Reset</button>
</div>
</div>
<article class="articleBlock"></article>
</main>
<footer class="footer">
<a class="footer__a" href="https://kottans.org/" target="_blank">Kottans</a>
</footer>
</div>
<script src="script.js"></script>
</body>
</html>
161 changes: 161 additions & 0 deletions submissions/asaMitaka/FriendsApp/script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
const url = 'https://randomuser.me/api/?results=12';
const content = document.querySelector('.articleBlock');
const ageForm = document.querySelector('#ageForm');
const genderForm = document.querySelector('#genderForm');
const search = document.querySelector('#search');
let friends = [];
let friendsCopy = [];

const data = (url) => fetch(url)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getData?

.then(handleErrors)
.then(res => res.json())
.then(res => {
friends = [...res.results];
init();
});

function handleErrors(res) {
if (!res.ok) {
throw Error(res.statusText);
}
return res;
}

const filterState = {
search: null,
gender: null,
sort: null,
reset() {
this.search = null;
this.gender = null;
this.sort = null;
}
}

function filterBy(id, usersToFilter) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe the only id you have there is somehow connected with gender, so filterBy is actually filterByGender.

switch(id) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can shorten this switch like this:

switch(id) {
  case 'male':
  case 'female':
    usersToFilter = userstoFilter.filter(item => item.gender === id);
    break;
  case 'all':
  ...
}

case 'male':
usersToFilter = usersToFilter.filter(item => item.gender === 'male');
break;
case 'female':
usersToFilter = usersToFilter.filter(item => item.gender === 'female');
break;
case 'all':
usersToFilter = [...friends];
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First of all, it would be more readable to create a new variable, something like filteredUsers in the beginning of this function to store the returned result. Secondly, if you're getting this from friends what's the point of passing some array in the function argument?

break;
}
return usersToFilter;
}

function sortAge(a, b) {
return a.dob.age - b.dob.age;
}

function sortAlph(a, b) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sortByName? And sortByAge

return a.name.last !== b.name.last ? a.name.last < b.name.last ? -1 : 1 : 0;
}

function sortBy(id, usersToSort) {
switch(id) {
case 'ageMore':
usersToSort = usersToSort.sort((a, b) => sortAge(a, b));
break;
case 'ageLess':
usersToSort = usersToSort.sort((a, b) => sortAge(b, a));
break;
case 'lastAToZ':
usersToSort = usersToSort.sort((a, b) => sortAlph(a, b));
break;
case 'lastZToA':
usersToSort = usersToSort.sort((a, b) => sortAlph(b, a));
break;
}

return usersToSort;
}

function filterBySearch(searchValue, usersToSearch) {
return usersToSearch.filter((elem) =>
`${elem.name.first}${elem.name.last}`.toLowerCase().includes(searchValue.toLowerCase())
);
};



function creatingProfileCard({picture, name, email, dob, phone, location, gender}) {
return `
<div class='content__item'>
<img class='content__item-img' src='${picture.medium}'>
<div class='content__item-name'>${name.title} ${name.first} ${name.last}</div>
<p class='content__item-p content__item-email'>
<a class='content__item-a' href="mailto: ${email}" target="_blank"> ${email}</a>
</p>
<p class='content__item-p'>Age: ${dob.age}</p>
<a class='content__item-a' href='${phone}'>${phone}</a>
<p class='content__item-p content__item-country'>${location.country}, ${location.city}</p>
<div class='content__item-gender'>${gender}</div>
</div>
`;
}


function init() {
renderAllItemsToPage(friends);

document.querySelector('.asideBlock').addEventListener('input', ({target}) => {
if (target.name === 'gender') {
filterState.gender = target.id;
}

if (target.name === 'search') {
filterState.search = target.value;
}

if (target.name === 'sort') {
filterState.sort = target.id;
}

render();
});

document.querySelector('#reset').addEventListener('click', function() {
ageForm.reset();
genderForm.reset();
filterState.reset();
search.value = '';
friendsCopy = [...friends];

render();
})
}

function render() {
friendsCopy = [...friends];

if (filterState.gender) {
friendsCopy = filterBy(filterState.gender, friendsCopy);
}

if (filterState.sort) {
friendsCopy = sortBy(filterState.sort, friendsCopy);
}

if (filterState.search) {
friendsCopy = filterBySearch(filterState.search, friendsCopy);
}

renderAllItemsToPage(friendsCopy);
}

function renderAllItemsToPage(arr) {
content.innerHTML = '';

let acc = '';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of creating a string of elements, it would be better to use the map method and create an array of elements, just join them before rendering. This would allow you to manipulate this array in the future if needed.

arr.forEach(item => {
acc += creatingProfileCard(item);
});

content.innerHTML = acc;
}

data(url);
Loading