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 #457

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions submissions/SamVal007/Friends_APP/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Friends App</title>

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main id="wrapper">
<div id="menu_forms">
<form class="form">
<div class="form_section section_name">
<span>Name</span>
<input type='text' name="textField" id="searchField">
</div>
<div class="form_section">
<span>Gender</span>
<input type="radio" id="genderAll" name="genderField" class="rdBtn" value="genderAll">
<label for="genderAll" class="form_label">All</label><br/>
<input type="radio" id="genderMale" name="genderField" class="rdBtn" value="genderMale">
<label for="genderMale" class="form_label">Male</label><br/>
<input type="radio" id="genderFemale" name="genderField" class="rdBtn" value="genderFemale">
<label for="genderFemale" class="form_label">Female</label><br/>
</div>
<div class="form_section">
<span>Name</span>
<input type="radio" id="nameAsc" name="nameField" class="rdBtn" value="nameAsc">
<label for="nameAsc" class="form_label">A-Z</label><br/>
<input type="radio" id="nameDesc" name="nameField" class="rdBtn" value="nameDesc">
<label for="nameDesc" class="form_label">Z -A</label>
</div>
<div class="form_section">
<span>Age</span>
<input type="radio" id="ageLow" name="ageField" class="rdBtn" value="ageLow">
<label for="ageLow" class="form_label">lowest to highest</label><br/>
<input type="radio" id="ageHigh" name="ageField" class="rdBtn" value="ageHigh">
<label for="ageHigh" class="form_label">highest to lowest</label>
</div>
<button type="reset" class="resetButton">Reset</button>
</form>
</div>
<div id="container"></div>
</main>
<script src="script.js"></script>
</body>
</html>
100 changes: 100 additions & 0 deletions submissions/SamVal007/Friends_APP/script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
const CONTAINER = document.getElementById('container');
const SIDEBAR = document.getElementById('sidebar');
const SEARCH_FIELD = document.getElementById('searchField');
const URL = 'https://randomuser.me/api/?results=40';

let persons = [];
let displayList = [];

function getPeopleData() {
let response = fetch(URL)
SamVal007 marked this conversation as resolved.
Show resolved Hide resolved
.then(
successResponse => {
if (successResponse.status != 200) {
return null;
} else {
return successResponse;
}
}
)
.then(data => data.json())
.then(function (data) {
persons = data.results;
displayList = persons;
displayCards();
Copy link
Member

Choose a reason for hiding this comment

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

Single responsibility - your functions should do only one job. As an example function in which you fetch users should only fetch them and not render, transform or process them in other ways. All these things should be done in another place, outside your function. The same applied to the sort function, which usually does all types of sorting 😉

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I would be honest, but i didnt find the way how to delete this displayCards() from this piece of code, so i just renamed function. I was trying to put this displayCards() in document.addEventListener('DOMContentLoaded', function () , but it didnt work...

Copy link
Member

Choose a reason for hiding this comment

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

Tip - you should use then in special place ;)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yep, this I understood, but where:)
Ok, I will try to figure out!

Copy link
Member

Choose a reason for hiding this comment

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

"in special place" 😄

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, I think I found out how to do it!
First of all - I tried to use one more promise inside of document.addEventListener('DOMContentLoaded', function (){...} , but it didnt work, i dont know why. Then I decided to use async and seems it worked!

})
.catch(function (error) {
console.log('We have an error: ', error);
alert('Please, check your internet connection and try again');
})
}

function getTemplate(person) {
return `<div class="card">
<div class="picture">
<img src="${person.picture.large}">
</div>
<h1>${person.name.last} ${person.name.first}</h1>
<div class="cardInfo">
<p><span class="text_title">Age:</span> ${person.dob.age}</p>
<p><span class="text_title">Gender:</span> ${person.gender}</p>
<p><span class="text_title">Phone:</span> ${person.phone}</p>
<p><span class="text_title">Country:</span> ${person.location.country}</p>
<p><span class="text_title">City:</span> ${person.location.city}</p>
</div>
</div>`
}

function displayCards() {
CONTAINER.innerHTML = '';
let cardMarkup = '';
cardMarkup += displayList.reduce((accumulator, currentValue) => accumulator.concat(getTemplate(currentValue)), '');
CONTAINER.insertAdjacentHTML('afterbegin', cardMarkup);
}

document.addEventListener('DOMContentLoaded', function () {
getPeopleData();

SIDEBAR.addEventListener('click', function (event) {
let radio = event.target.closest('.rdBtn');
let btn = event.target.closest('button');

if (radio) {

switch (radio.id) {
case 'genderAll':
displayList = persons;
break;
case 'genderMale':
displayList = persons.filter(el => el.gender === 'male');
break;
case 'genderFemale':
displayList = persons.filter(el => el.gender === 'female');
break;
case 'nameAsc':
displayList = displayList.sort((b, a) => a.name.last > b.name.last ? -1 : 1);
break;
case 'nameDesc':
displayList = displayList.sort((b, a) => a.name.last < b.name.last ? -1 : 1);
break;
case 'ageLow':
displayList = displayList.sort((a, b) => a.dob.age - b.dob.age);
break;
case 'ageHigh':
displayList = displayList.sort((b, a) => a.dob.age - b.dob.age);
Copy link
Member

Choose a reason for hiding this comment

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

  1. Why you need assigning to displayList?
  2. Same function as at line 81. DRY

Copy link
Member

Choose a reason for hiding this comment

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

Also, please check this comment #449 (comment)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thank you!
Yes, really, i dont need this 'assigning '!
Ok, I will read this comments.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm sorry, Did I understand correctly - I should remake this part of code (this switch is too long and it's not "Single responsibility"):

if (radio) {
switch (radio.id) {
case 'genderAll':
displayList = persons;
break;
case 'genderMale':
displayList = persons.filter(el => el.gender === 'male');
break;
case 'genderFemale':
displayList = persons.filter(el => el.gender === 'female');
break;
case 'nameAsc':
displayList.sort((b, a) => a.name.last > b.name.last ? -1 : 1);
break;
case 'nameDesc':
displayList.sort((b, a) => a.name.last < b.name.last ? -1 : 1);
break;
case 'ageLow':
displayList.sort((a, b) => a.dob.age - b.dob.age);
break;
case 'ageHigh':
displayList.sort((b, a) => a.dob.age - b.dob.age);
break;
}

With adding functions for sorting.
BTW, Should I delete "long switch" and make few different "addEventListneres" for each case of switch or it will be very ig load on site? (sorry may be for stupid questions, but i just want to understand)

Copy link
Member

Choose a reason for hiding this comment

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

  1. Yes, you should delete the long switch
  2. You can have a listener on the form and listen to change event. Or you can separate listeners between fieldsets. Up to you

Copy link
Contributor Author

@SamVal007 SamVal007 Feb 27, 2021

Choose a reason for hiding this comment

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

Huh! Unbelievable, but seems I did it!:)
I dodnt know why, but this refactoring took me quit long time.
Basically, I think. It because I start fixing everything at one time... it was big mistake - nothing work and could understand why. So, then I started do it step-by-step, like You teaching us:) Refactored sort logic, then long switch.
Sorry, may be It's not necessary to write it here, but whom else can i write it;))

Ok, so now code looks better, I hope:)

break;
}

} else if (btn) {
displayList = persons;
}
displayCards();
})

SEARCH_FIELD.addEventListener('input', function (e) {
let searchStr = '';
searchStr = SEARCH_FIELD.value.toLowerCase().trim();
displayList = persons.filter(elem => elem.name.last.toLowerCase().includes(searchStr));
displayCards();
})
});
166 changes: 166 additions & 0 deletions submissions/SamVal007/Friends_APP/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
* {
box-sizing: border-box;
}

body,
html {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}

body {
font-family: Arial, Helvetica, sans-serif;
font-weight: 400;
font-size: 12px;
line-height: 1.05;
background: #5278a3;
}

h1,
h2,
h3,
h4,
h5,
h6 {
font-family: "Segoe UI", Arial, sans-serif;
}

#wrapper {
display: flex;
margin: 0 auto;
flex-wrap: wrap;
}

#menu_forms {
margin: 20px 0 0 20px;
}

.form {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-around;
}

.form_section {
display: inherit;
flex-wrap: wrap;
justify-content: center;
align-items: flex-start;
margin: 22px;
}

.section_name {
margin-top: 10px;
}

#container {

display: flex;
flex-wrap: wrap;
justify-content: space-around;
}

.card {
display: inline-block;
box-shadow: 0 7px 12px 0 rgba(0, 0, 0, 0.2);
width: 200px;
height: 260px;
margin: 20px 25px;
color: #3118bd;
text-align: center;
vertical-align: top;
padding-bottom: 10px;
background: #93d42a;
border-radius: 3%;

}

.picture {
width: 100%;
height: 115px;
padding: 5px 0;
border-bottom: 1px solid #cccccc;
}

.picture img {
width: 100px;
height: 100px;
border-radius: 50%;
}

.card h1 {
font-size: 16px;
margin-bottom: 10px;
color: #000000;
}

.cardInfo {
text-align: left;
padding-left: 10px;
}

.cardInfo .text_title {
font-weight: 600;
}

.card p {
margin: 10px 0;
}

button {
border: none;
outline: 0;
display: inline-block;
padding: 8px;
color: white;
background-color: #000;
text-align: center;
cursor: pointer;
width: 100%;
font-size: 18px;
}

a {
text-decoration: none;
font-size: 22px;
color: black;
}

button:hover,
a:hover {
opacity: 0.7;
}

.form_section {
padding: 0px;
}

.form_section span {
display: block;
font-weight: 600;
padding: 4px;
font-size: 16px;
}

.rdBtn {
padding: 5px 0;
margin: 4px 11px 20px 13px;
}

.form_label {
padding: 5px 0;
}

.resetButton {
width: 180px;
height: 30px;
margin-top: -15px;
padding: 2px;
background: #696969;
color: #ffffff;
text-align: center;
vertical-align: top;
}