Skip to content

Commit 6d2aa0e

Browse files
authored
Merge pull request #12 from yakovenko79/module11-task1
2 parents 420d133 + af8f9e2 commit 6d2aa0e

6 files changed

Lines changed: 118 additions & 74 deletions

File tree

js/api.js

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
const BASE_URL = 'https://31.javascript.htmlacademy.pro/kekstagram';
2+
const ERROR_MESSAGE_TIMEOUT = 5000;
3+
4+
const errorTemplate = document.querySelector('#data-error');
5+
6+
const Routes = {
7+
GET_DATA: '/data',
8+
SEND_DATA: '/'
9+
};
10+
11+
const Method = {
12+
GET: 'GET',
13+
POST: 'POST'
14+
};
15+
16+
const ErrorText = {
17+
GET_DATA: 'Не удалось загрузить данные. Попробуйте обновить страницу',
18+
SEND_DATA: 'Не удалось отправить форму. Попробуйте ещё раз',
19+
};
20+
21+
function showDataError(message) {
22+
const errorMessage = errorTemplate.content.cloneNode(true).firstElementChild;
23+
const titleElement = errorMessage.querySelector('.data-error__title');
24+
titleElement.textContent = message;
25+
document.body.appendChild(errorMessage);
26+
setTimeout(() => {
27+
errorMessage.remove();
28+
}, ERROR_MESSAGE_TIMEOUT);
29+
}
30+
31+
function load(route, errorText, method = Method.GET, body = null){
32+
return fetch(`${BASE_URL}${route}`, {method, body})
33+
.then((response) => {
34+
if(!response.ok) {
35+
throw new Error(errorText);
36+
}
37+
return response.json();
38+
})
39+
.catch((err) => {
40+
throw err;
41+
});
42+
}
43+
44+
function getData(){
45+
return load(Routes.GET_DATA, ErrorText.GET_DATA);
46+
}
47+
48+
function sendData(body){
49+
return load(Routes.SEND_DATA, ErrorText.SEND_DATA, Method.POST, body);
50+
}
51+
52+
export { getData, sendData, showDataError, ErrorText };

js/generate-data.js

Lines changed: 0 additions & 63 deletions
This file was deleted.

js/hashtag-validator.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
11
const MAX_HASHTAG_SYMBOLS = 20;
22
const MAX_HASHTAGS = 5;
33

4-
54
let errorMessage = '';
65

76
function error() {
87
return errorMessage;
98
}
109

11-
function isHashtagValid(value){
10+
function isHashtagValid(value = null){
1211
errorMessage = '';
1312
const inputText = value.toLowerCase().trim();
1413

15-
if(inputText.lenght === 0){
14+
if(inputText.trim().length === 0){
1615
return true;
1716
}
1817

js/main.js

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
11
import { createThumbnails } from './thumbnails';
2-
import { getPhotos } from './generate-data.js';
32
import { initUploadModal } from './upload-photo-form.js';
3+
import { ErrorText, getData, showDataError } from './api.js';
44

5-
const photos = getPhotos();
5+
async function init() {
6+
try {
7+
const data = await getData();
8+
createThumbnails(data);
9+
} catch (error) {
10+
showDataError(ErrorText.GET_DATA);
11+
}
12+
initUploadModal();
13+
}
614

7-
createThumbnails(photos);
8-
initUploadModal();
15+
init();

js/popup.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ const modalLikes = modal.querySelector('.likes-count');
77
const modalDescription = modal.querySelector('.social__caption');
88
const closePopupButton = modal.querySelector('.big-picture__cancel');
99
const modalCommonCommentsAmount = modal.querySelector('.social__comment-total-count');
10+
const messageInputField = modal.querySelector('.social__footer-text');
1011
const documentBody = document.body;
1112

1213
function onDocumentKeydown() {
@@ -41,4 +42,8 @@ function openPopup(currentImage){
4142
document.addEventListener('keydown', onDocumentKeydown);
4243
}
4344

45+
messageInputField.addEventListener('keydown', (evt) => {
46+
evt.stopPropagation();
47+
});
48+
4449
export { openPopup };

js/upload-photo-form.js

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
import { isHashtagValid, error } from './hashtag-validator';
22
import { isEscapeKey } from './utils';
33
import { onEffectChange, resetFilter } from './slider-effect.js';
4+
import { ErrorText, sendData, showDataError } from './api.js';
45

56
const STEP = 25;
67
const MIN_SCALE = 25;
78
const MAX_SCALE = 100;
89

10+
const SubmitButtonText = {
11+
IDLE: 'Сохранить',
12+
SENDING: 'Сохраняю...'
13+
};
914

1015
const uploadForm = document.querySelector('.img-upload__form');
1116
const pageBody = document.body;
@@ -22,6 +27,9 @@ const increaseScaleButton = uploadForm.querySelector('.scale__control--bigger');
2227
const scaleValue = uploadForm.querySelector('.scale__control--value');
2328
const uploadImagePreview = uploadForm.querySelector('.img-upload__preview img');
2429
const effectsList = uploadForm.querySelector('.effects__list');
30+
const submitButton = uploadForm.querySelector('.img-upload__submit');
31+
const templateSuccess = document.querySelector('#success').content;
32+
const templateError = document.querySelector('#error').content;
2533

2634
let currentScaleValue = parseInt(scaleValue.value.slice(0, -1), 10);
2735

@@ -45,6 +53,34 @@ function onDocumentKeyDown(evt) {
4553
}
4654
}
4755

56+
function onCloseNotification(evt){
57+
evt.stopPropagation();
58+
const existElement = document.querySelector('.success') || document.querySelector('.error');
59+
const closeButton = existElement.querySelector('button');
60+
if (evt.target === existElement || evt.target === closeButton || isEscapeKey(evt)) {
61+
existElement.remove();
62+
pageBody.removeEventListener('click', onCloseNotification);
63+
pageBody.removeEventListener('keydown', onCloseNotification);
64+
}
65+
}
66+
67+
function appendNotification(template) {
68+
const notificationNode = template.cloneNode(true);
69+
pageBody.append(notificationNode);
70+
pageBody.addEventListener('click', onCloseNotification);
71+
pageBody.addEventListener('keydown', onCloseNotification);
72+
}
73+
74+
const blockSubmitButton = () => {
75+
submitButton.disabled = true;
76+
submitButton.textContent = SubmitButtonText.SENDING;
77+
};
78+
79+
const unblockSubmitButton = () => {
80+
submitButton.disabled = false;
81+
submitButton.textContent = SubmitButtonText.IDLE;
82+
};
83+
4884
const pristine = new Pristine(uploadForm, {
4985
classTo: 'img-upload__field-wrapper',
5086
errorClass: 'img-upload__field-wrapper--error',
@@ -59,7 +95,6 @@ function closePhotoEditorForm(){
5995
pristine.reset();
6096
uploadForm.reset();
6197
resetFilter();
62-
6398
}
6499

65100
function initUploadModal() {
@@ -78,10 +113,9 @@ function onScaleImage(direction) {
78113
let newValue = currentScaleValue + STEP * direction;
79114
if(newValue < MIN_SCALE) {
80115
newValue = MIN_SCALE;
81-
} else if(newValue > MAX_SCALE){
116+
} else if (newValue > MAX_SCALE) {
82117
newValue = MAX_SCALE;
83118
}
84-
85119
currentScaleValue = newValue;
86120
scaleValue.value = `${currentScaleValue}%`;
87121
uploadImagePreview.style.transform = `scale(${currentScaleValue / MAX_SCALE})`;
@@ -97,7 +131,17 @@ function onFormSubmit(evt) {
97131
evt.preventDefault();
98132
if(pristine.validate()) {
99133
hashtagInput.value = hashtagInput.value.trim().replaceAll(/\s+/g, ' ');
100-
uploadForm.submit();
134+
blockSubmitButton();
135+
sendData(new FormData(evt.target))
136+
.then(() => {
137+
appendNotification(templateSuccess);
138+
closePhotoEditorForm();
139+
})
140+
.catch(() => {
141+
showDataError(ErrorText.SEND_DATA);
142+
appendNotification(templateError);
143+
})
144+
.finally(unblockSubmitButton);
101145
}
102146
}
103147

0 commit comments

Comments
 (0)