Skip to content

Commit f0e7324

Browse files
author
Balashov Nikita
committed
Add user page, sort contacts by import, little fixes
1 parent 70144a5 commit f0e7324

File tree

11 files changed

+335
-15
lines changed

11 files changed

+335
-15
lines changed

phone-book/build/bundle.js

Lines changed: 15 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

phone-book/index.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
<meta name="viewport" content="width=device-width, initial-scale=1">
88
<link rel="stylesheet" href="style/main.css">
99
<link rel="stylesheet" href="style/keypad.css">
10+
<link rel="stylesheet" href="style/add-user.css">
11+
<link rel="stylesheet" href="style/user-page.css">
1012
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.2/css/bootstrap.min.css" integrity="sha384-Smlep5jCw/wG7hdkwQ/Z5nLIefveQRIY9nfy6xoR1uRYBtpZgI6339F5dgvm/e9B" crossorigin="anonymous">
1113
</head>
1214
<body>
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
import {Url} from '../url/url';
2+
3+
class AddUserPage {
4+
constructor(store) {
5+
this.setStateContact = () => {
6+
const {setState} = store;
7+
const initializeState = {
8+
stateName: 'ADD USER',
9+
activePage: this.render(),
10+
};
11+
setState(initializeState);
12+
}
13+
14+
this.serverSide = new Url();
15+
}
16+
17+
render() {
18+
return /*html*/`
19+
<div id="add-user-page">
20+
21+
<header class="container">
22+
<div class="row d-flex justify-content-center">
23+
<span class="add-user-header">Add new user</span>
24+
</div>
25+
</header>
26+
27+
<main class="container add-user-block">
28+
<form>
29+
30+
<div class="form-group">
31+
<label for="fullName-input">Full name:</label>
32+
<input type="text" name="fullName" class="form-control" id="fullName-input" placeholder="Enter full name" required>
33+
</div>
34+
35+
<div class="form-group">
36+
<label for="email-input">Email address:</label>
37+
<input type="email" name="email" class="form-control" id="email-input" placeholder="Enter email" required>
38+
</div>
39+
40+
<div class="form-group">
41+
<label for="phoneNumber-input">Phone Number:</label>
42+
<input type="number" name="phone" class="form-control" id="phoneNumber-input" placeholder="Enter phone number" required>
43+
</div>
44+
45+
<div class="form-group">
46+
<label for="birthDate-input">Birth date:</label>
47+
<input type="date" name="birthdate" class="form-control" id="birthDate-input">
48+
</div>
49+
50+
<div class="form-group">
51+
<label for="address-input">Address:</label>
52+
<input type="text" name="address" class="form-control" id="address-input" placeholder="Enter address">
53+
</div>
54+
55+
<div class="form-group">
56+
<label for="gender-selection">Gender:</label>
57+
<select name="gender" class="form-control" id="gender-selection">
58+
<option>Male</option>
59+
<option>Female</option>
60+
</select>
61+
</div>
62+
63+
<div class="form-group">
64+
<label for="avatarUrl-input">Avatar url:</label>
65+
<input type="text" name="avatarUrl" class="form-control" id="avatarUrl-input" aria-describedby="avatarHelp" placeholder="Enter avatar url">
66+
<small id="avatarHelp" class="form-text text-muted">ex: https://cloud-drive/photo123456.</small>
67+
</div>
68+
69+
<div class="row d-flex justify-content-center">
70+
<button type="submit" class="btn btn-primary">Add user</button>
71+
</div>
72+
73+
</form>
74+
</main>
75+
76+
</div>
77+
`;
78+
}
79+
80+
applyListenersForAddUserPage() {
81+
// const fullNameInput = document.querySelector('#fullName-input');
82+
// const emailInput = document.querySelector('#email-input');
83+
// const phoneNumberInput = document.querySelector('#phoneNumber-input');
84+
// const birthDateInput = document.querySelector('#birthDate-input');
85+
// const addressInput = document.querySelector('#address-input');
86+
// const genderInput = document.querySelector('#gender-selection');
87+
// const avatarUrlInput = document.querySelector('#avatarUrl-input');
88+
89+
const addUserForm = document.querySelector('form');
90+
const inputs = [...addUserForm.elements]
91+
.filter(elem => elem.tagName === 'INPUT' || elem.tagName === 'SELECT');
92+
93+
addUserForm.addEventListener('submit', (e) => {
94+
95+
const user = inputs.reduce((newUser, input) => {
96+
const KEY = input.name;
97+
const VALUE = input.value;
98+
99+
if(VALUE.lenght !== 0) {
100+
newUser[KEY] = VALUE;
101+
}
102+
if(VALUE === 'Male' || VALUE === 'Female') {
103+
const firstChar = input.value[0];
104+
newUser[KEY] = firstChar;
105+
}
106+
return newUser;
107+
}, {});
108+
109+
this.serverSide.postUser(user);
110+
})
111+
}
112+
113+
isValid() {
114+
115+
}
116+
}
117+
118+
export {AddUserPage};

phone-book/src/contact/contact.js

Lines changed: 66 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -81,30 +81,43 @@ class ContactPage {
8181
email: 'Email'
8282
};
8383

84-
const ListOfContacts = document.getElementById('list-of-contacts');
84+
const listOfContacts = document.getElementById('list-of-contacts');
8585

8686
if(TH_ELEM_CONTAINS === PREDICT_TEXT_CONTENT.firstName) {
87-
const sortedListByFirsName = this.sortUsersByValue('firstName', users);
88-
ListOfContacts.innerHTML = this.contactListComponent(sortedListByFirsName);
87+
const firstName = 0;
88+
const sortedListByFirsName = this.mergeSort(users, firstName);
89+
listOfContacts.innerHTML = this.contactListComponent(sortedListByFirsName);
8990
return;
9091
}
9192

9293
if(TH_ELEM_CONTAINS === PREDICT_TEXT_CONTENT.lastName) {
93-
const sortedListByLastName = this.sortUsersByValue('lastName', users);
94-
ListOfContacts.innerHTML = this.contactListComponent(sortedListByLastName);
94+
const lastName = 1;
95+
const sortedListByLastName = this.mergeSort(users, lastName);
96+
listOfContacts.innerHTML = this.contactListComponent(sortedListByLastName);
9597
return;
9698
}
9799

98100
if(TH_ELEM_CONTAINS === PREDICT_TEXT_CONTENT.email) {
99101
const sortedListByEmail = this.sortUsersByValue('email', users);
100-
ListOfContacts.innerHTML = this.contactListComponent(sortedListByEmail);
102+
listOfContacts.innerHTML = this.contactListComponent(sortedListByEmail);
101103
return;
102104
}
103105
})
104106

105107
/* SORT USERS BY INPUTED LETTERS OF NAME */
108+
const contactSearchField = document.querySelector('#search');
106109

107-
110+
contactSearchField.addEventListener('input', () => {
111+
const VALUE = contactSearchField.value;
112+
const filteredUsers = this.filterUsersByInputValueByName(VALUE);
113+
const listOfContacts = document.getElementById('list-of-contacts');
114+
115+
filteredUsers.length === 0
116+
? listOfContacts.innerHTML = /*html*/`<p>No such users</p>`
117+
: listOfContacts.innerHTML = this.contactListComponent(filteredUsers);
118+
119+
120+
})
108121
}
109122

110123
sortUsersByValue(key, users) {
@@ -115,6 +128,52 @@ class ContactPage {
115128

116129
return [...users].sort(sortFunction);
117130
}
131+
132+
mergeSort(arr, index) {
133+
134+
const len = arr.length;
135+
if(len < 2) return arr;
136+
const mid = Math.floor(len / 2),
137+
left = arr.slice(0, mid),
138+
right =arr.slice(mid);
139+
140+
return this.merge(this.mergeSort(left, index), this.mergeSort(right, index), index);
141+
}
142+
143+
merge(left, right, index) {
144+
let result = [],
145+
lLen = left.length,
146+
rLen = right.length,
147+
l = 0,
148+
r = 0;
149+
while(l < lLen && r < rLen){
150+
const leftWord = left[l].fullName.split(' ')[index];
151+
const rightWord = right[r].fullName.split(' ')[index];
152+
if(leftWord < rightWord){
153+
result.push(left[l++]);
154+
}
155+
else{
156+
result.push(right[r++]);
157+
}
158+
}
159+
160+
return result.concat(left.slice(l)).concat(right.slice(r));
161+
}
162+
163+
filterUsersByInputValueByName(inputValue) {
164+
return users.reduce((newUsers, user) => {
165+
const firstName = user.fullName.split(' ')[0].toLowerCase();
166+
167+
const comparedPartOfName = firstName.slice(0, inputValue.length);
168+
169+
if(inputValue.toLowerCase() === comparedPartOfName) {
170+
newUsers.push(user);
171+
}
172+
173+
return newUsers;
174+
}, []);
175+
176+
}
118177
}
119178

120179
/* ================== CONTACT END================== */

phone-book/src/index.js

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
1-
import {users} from './components/users';
2-
import {MOBILE_OPERATORS_IDENTIFICATORS} from './components/mobile-operators-identifiers';
31

42
import {ContactPage} from './contact/contact';
53
import {KeypadPage} from './keypad/keypad';
6-
// import {} from './add-user/add-user';
4+
import {AddUserPage} from './add-user/add-user';
75

86
class App {
97
constructor() {
108
this.store = this.createStore();
119
this.pages = {
1210
'contacts': new ContactPage(this.store),
1311
'keypad': new KeypadPage(this.store),
12+
'addUser': new AddUserPage(this.store),
1413
'footer': new FooterNavigationBar()
1514
}
1615
this.pages.contacts.setStateContact();
@@ -53,6 +52,13 @@ class App {
5352
return;
5453
}
5554

55+
if(action.type === 'MOVE_TO_ADD_USER_PAGE') {
56+
this.pages.addUser.setStateContact();
57+
switchBetweenPages();
58+
this.pages.addUser.applyListenersForAddUserPage();
59+
return;
60+
}
61+
5662
}
5763

5864
render() {
@@ -80,6 +86,10 @@ class App {
8086
type: 'MOVE_TO_CONTACT_PAGE'
8187
}
8288

89+
const _MOVE_TO_ADD_USER_PAGE = {
90+
type: 'MOVE_TO_ADD_USER_PAGE'
91+
}
92+
8393
const wraperForFooter = document.getElementById('wraper-for-footer');
8494
wraperForFooter.addEventListener('click', (e) => {
8595
const currentState = this.store.getState();
@@ -113,6 +123,19 @@ class App {
113123
}
114124
return;
115125
}
126+
127+
if(
128+
BUTTON_ID === 'to-addUser-page'
129+
|| BUTTON_ID_FROM_SVG === 'to-addUser-page'
130+
|| BUTTON_ID_FROM_PATH === 'to-addUser-page'
131+
) {
132+
133+
if(currentState.stateName !== 'ADD USER') {
134+
this.pages.addUser.setStateContact();
135+
return this.reducer(_MOVE_TO_ADD_USER_PAGE);
136+
}
137+
return;
138+
}
116139
})
117140
}
118141
}

phone-book/src/url/url.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,20 @@ class Url{
2020
this.getUsersFromServer();
2121
return this.users;
2222
}
23+
24+
postUser(user) {
25+
const xhr = new XMLHttpRequest();
26+
xhr.open('POST', this.url, true);
27+
xhr.setRequestHeader('Content-type', 'application/json');
28+
xhr.send(JSON.stringify(user));
29+
}
30+
31+
deleteUserById(id) {
32+
const xhr = new XMLHttpRequest();
33+
xhr.open('DELETE', `${this.url}/${id}`, true);
34+
xhr.setRequestHeader('Content-type', 'application/json');
35+
xhr.send();
36+
}
2337
}
2438

2539
export {Url};
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
class UserPage{
2+
constructor(store) {
3+
4+
}
5+
6+
render() {
7+
return /*html*/`
8+
<div id="user-page">
9+
10+
<header class="container">
11+
<div class="row d-flex justify-content-center">
12+
<span class="user-header">User page</span>
13+
</div>
14+
</header>
15+
16+
<main class="container mt-2">
17+
18+
<div class="row d-flex justify-content-center">
19+
<img id="user-page-avatar" src="img/avatar.jpg" alt="avatar">
20+
</div>
21+
22+
<div class="row d-flex justify-content-between">
23+
<p class="user-page-key">Full Name: </p>
24+
<p class="user-page-value">???????????</p>
25+
</div>
26+
<div class="row d-flex justify-content-between">
27+
<p class="user-page-key">Email: </p>
28+
<p class="user-page-value">??????@??????.???</p>
29+
</div>
30+
<div class="row d-flex justify-content-between">
31+
<p class="user-page-key">Phone number: </p>
32+
<p class="user-page-value">(???) ???-??-??</p>
33+
</div>
34+
<div class="row d-flex justify-content-between">
35+
<p class="user-page-key">Birth date: </p>
36+
<p class="user-page-value">????/??/??</p>
37+
</div>
38+
<div class="row d-flex justify-content-between">
39+
<p class="user-page-key">Address: </p>
40+
<p class="user-page-value">????? ??????</p>
41+
</div>
42+
<div class="row d-flex justify-content-between">
43+
<p class="user-page-key">Gender: </p>
44+
<p class="user-page-value">?????</p>
45+
</div>
46+
47+
<div class="row d-flex justify-content-around">
48+
<button type="button" class="btn btn-primary">Edit</button>
49+
<button type="button" class="btn btn-danger">Delete</button>
50+
</div>
51+
52+
</main>
53+
54+
</div>
55+
`;
56+
}
57+
}

phone-book/style/add-user.css

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
.add-user-header{
2+
font-size: 26px;
3+
border-bottom: 2px solid black;
4+
}
5+
6+
.add-user-block{
7+
padding: 10px 0;
8+
}

phone-book/style/keypad.css

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ input::-webkit-inner-spin-button {
4545
}
4646

4747
.borders{
48-
border-bottom: 3px solid black;
4948
border-top: 3px solid black;
5049
}
5150

0 commit comments

Comments
 (0)