6565
6666 < script >
6767
68- let comments = [
69- {
70- id : 1 ,
71- name : "Глеб Фокин" ,
72- date : "12.02.22 12:18" ,
73- text : "Это будет первый комментарий на этой странице" ,
74- likes : 3 ,
75- isLiked : false
76- } ,
77- {
78- id : 2 ,
79- name : "Варвара Н." ,
80- date : "13.02.22 19:22" ,
81- text : "Мне нравится как оформлена эта страница! ❤" ,
82- likes : 75 ,
83- isLiked : true
84- }
85- ] ;
86-
87- const nameInput = document . querySelector ( '.add-form-name' ) ;
88- const textInput = document . querySelector ( '.add-form-text' ) ;
89- const addButton = document . querySelector ( '.add-form-button' ) ;
90- const commentsList = document . querySelector ( '.comments' ) ;
91-
92- let replyingToCommentId = null ;
93-
94- function getCurrentDateTime ( ) {
95- const now = new Date ( ) ;
96- const day = String ( now . getDate ( ) ) . padStart ( 2 , '0' ) ;
97- const month = String ( now . getMonth ( ) + 1 ) . padStart ( 2 , '0' ) ;
98- const year = String ( now . getFullYear ( ) ) . slice ( - 2 ) ;
99- const hours = String ( now . getHours ( ) ) . padStart ( 2 , '0' ) ;
100- const minutes = String ( now . getMinutes ( ) ) . padStart ( 2 , '0' ) ;
101-
102- return `${ day } .${ month } .${ year } ${ hours } :${ minutes } ` ;
103- }
68+ const host = "https://wedev-api.sky.pro/api/v1/dmitriy-skachkov"
10469
105- function escapeHtml ( unsafe ) {
106- if ( ! unsafe ) return '' ;
107- return unsafe
108- . replaceAll ( '&' , '&' )
109- . replaceAll ( '<' , '<' )
110- . replaceAll ( '>' , '>' )
111- . replaceAll ( '"' , '"' )
112- . replaceAll ( "'" , ''' ) ;
70+ const fetchComments = ( ) => {
71+ return fetch ( host + "/comments" ) . then ( res => {
72+ if ( ! res . ok ) {
73+ throw new Error ( 'Ошибка загрузки комментариев' ) ;
11374 }
75+ return res . json ( )
76+ } )
77+ . then ( ( responseData ) => {
78+ const appComments = responseData . comments . map ( comment => {
79+ return {
80+ id : comment . id ,
81+ name : comment . author . name ,
82+ date : new Date ( comment . date ) ,
83+ text : comment . text ,
84+ likes : comment . likes ,
85+ isLiked : false ,
86+ }
87+ } )
88+ return appComments
89+ } )
90+ }
11491
115- function renderComments ( ) {
116- let commentsHTML = '' ;
117-
118- comments . forEach ( ( comment ) => {
119- commentsHTML += `
120- <li class="comment" data-id="${ comment . id } ">
121- <div class="comment-header">
122- <div>${ escapeHtml ( comment . name ) } </div>
123- <div>${ comment . date } </div>
124- </div>
125- <div class="comment-body">
126- <div class="comment-text">
127- ${ escapeHtml ( comment . text ) }
128- </div>
129- </div>
130- <div class="comment-footer">
131- <div class="likes">
132- <span class="likes-counter">${ comment . likes } </span>
133- <button class="like-button ${ comment . isLiked ? '-active-like' : '' } " data-id="${ comment . id } "></button>
134- </div>
135- </div>
136- </li>
137- ` ;
138- } ) ;
139-
140- commentsList . innerHTML = commentsHTML ;
141-
142- document . querySelectorAll ( '.like-button' ) . forEach ( ( button ) => {
143- button . addEventListener ( 'click' , ( event ) => {
144- event . stopPropagation ( ) ;
145- const commentId = parseInt ( event . target . dataset . id ) ;
146- toggleLike ( commentId ) ;
147- } ) ;
148- } ) ;
149-
150- document . querySelectorAll ( '.comment' ) . forEach ( ( commentElement ) => {
151- commentElement . addEventListener ( 'click' , ( event ) => {
152- if ( ! event . target . closest ( '.like-button' ) ) {
153- const commentId = parseInt ( commentElement . dataset . id ) ;
154- replyToComment ( commentId ) ;
155- }
156- } ) ;
92+ fetchComments ( ) . then ( data => {
93+ updateComments ( data ) ;
94+ renderComments ( )
95+ } ) . catch ( error => {
96+ console . error ( 'Ошибка загрузки комментариев:' , error ) ;
97+ alert ( 'Не удалось загрузить комментарии' ) ;
98+ } )
99+
100+ const updateComments = ( newComments ) => {
101+ comments = newComments
102+ }
103+
104+ let comments = [ ] ;
105+
106+ const postComment = ( name , text ) => {
107+ return fetch ( host + "/comments" , {
108+ method : "POST" ,
109+ body : JSON . stringify ( {
110+ text : text ,
111+ name : name ,
112+ } ) ,
113+ } )
114+ . then ( ( response ) => {
115+ if ( ! response . ok ) {
116+ return response . text ( ) . then ( text => {
117+ throw new Error ( `Ошибка сервера: ${ response . status } ${ text } ` ) ;
157118 } ) ;
158119 }
120+ return response . json ( ) ;
121+ } )
122+ }
159123
160- function toggleLike ( commentId ) {
161- const comment = comments . find ( c => c . id === commentId ) ;
162-
163- if ( comment ) {
164- if ( comment . isLiked ) {
165- comment . likes -- ;
166- comment . isLiked = false ;
167- } else {
168- comment . likes ++ ;
169- comment . isLiked = true ;
170- }
171-
172- renderComments ( ) ;
173- }
174- }
124+ const nameInput = document . querySelector ( '.add-form-name' ) ;
125+ const textInput = document . querySelector ( '.add-form-text' ) ;
126+ const addButton = document . querySelector ( '.add-form-button' ) ;
127+ const commentsList = document . querySelector ( '.comments' ) ;
175128
176- function replyToComment ( commentId ) {
177- const comment = comments . find ( c => c . id === commentId ) ;
178-
179- if ( comment ) {
180- replyingToCommentId = commentId ;
181-
182- const replyText = `> ${ comment . name } :\n> ${ comment . text } \n\n` ;
183-
184- nameInput . value = '' ;
185- textInput . value = replyText ;
186-
187- textInput . focus ( ) ;
188- }
189- }
129+ let replyingToCommentId = null ;
130+
131+ function escapeHtml ( unsafe ) {
132+ if ( ! unsafe ) return '' ;
133+ return unsafe
134+ . replaceAll ( '&' , '&' )
135+ . replaceAll ( '<' , '<' )
136+ . replaceAll ( '>' , '>' )
137+ . replaceAll ( '"' , '"' )
138+ . replaceAll ( "'" , ''' ) ;
139+ }
190140
191- function addNewComment ( ) {
192- const name = escapeHtml ( nameInput . value . trim ( ) ) ;
193- let text = textInput . value . trim ( ) ;
194-
195- if ( ! name || ! text ) {
196- alert ( 'Пожалуйста, заполните все поля' ) ;
197- return ;
141+ function renderComments ( ) {
142+ let commentsHTML = '' ;
143+
144+ comments . forEach ( ( comment ) => {
145+ const formattedDate = comment . date instanceof Date
146+ ? comment . date . toLocaleDateString ( 'ru-RU' , {
147+ day : '2-digit' ,
148+ month : '2-digit' ,
149+ year : '2-digit' ,
150+ hour : '2-digit' ,
151+ minute : '2-digit'
152+ } )
153+ : comment . date ;
154+
155+ commentsHTML += `
156+ <li class="comment" data-id="${ comment . id } ">
157+ <div class="comment-header">
158+ <div>${ escapeHtml ( comment . name ) } </div>
159+ <div>${ formattedDate } </div>
160+ </div>
161+ <div class="comment-body">
162+ <div class="comment-text">
163+ ${ escapeHtml ( comment . text ) }
164+ </div>
165+ </div>
166+ <div class="comment-footer">
167+ <div class="likes">
168+ <span class="likes-counter">${ comment . likes } </span>
169+ <button class="like-button ${ comment . isLiked ? '-active-like' : '' } " data-id="${ comment . id } "></button>
170+ </div>
171+ </div>
172+ </li>
173+ ` ;
174+ } ) ;
175+
176+ commentsList . innerHTML = commentsHTML ;
177+
178+ document . querySelectorAll ( '.like-button' ) . forEach ( ( button ) => {
179+ button . addEventListener ( 'click' , ( event ) => {
180+ event . stopPropagation ( ) ;
181+ const commentId = parseInt ( event . target . dataset . id ) ;
182+ toggleLike ( commentId ) ;
183+ } ) ;
184+ } ) ;
185+
186+ document . querySelectorAll ( '.comment' ) . forEach ( ( commentElement ) => {
187+ commentElement . addEventListener ( 'click' , ( event ) => {
188+ if ( ! event . target . closest ( '.like-button' ) ) {
189+ const commentId = parseInt ( commentElement . dataset . id ) ;
190+ replyToComment ( commentId ) ;
198191 }
199-
200- text = escapeHtml ( text ) ;
201-
202- const newId = comments . length > 0 ? Math . max ( ...comments . map ( c => c . id ) ) + 1 : 1 ;
203-
204- comments . push ( {
205- id : newId ,
206- name : name ,
207- date : getCurrentDateTime ( ) ,
208- text : text ,
209- likes : 0 ,
210- isLiked : false
211- } ) ;
212-
213- renderComments ( ) ;
214-
215- nameInput . value = '' ;
216- textInput . value = '' ;
217- replyingToCommentId = null ;
192+ } ) ;
193+ } ) ;
194+ }
195+
196+ function toggleLike ( commentId ) {
197+ const comment = comments . find ( c => c . id === commentId ) ;
198+
199+ if ( comment ) {
200+ if ( comment . isLiked ) {
201+ comment . likes -- ;
202+ comment . isLiked = false ;
203+ } else {
204+ comment . likes ++ ;
205+ comment . isLiked = true ;
218206 }
207+
208+ renderComments ( ) ;
209+ }
210+ }
219211
220- function initApp ( ) {
221- renderComments ( ) ;
222-
223- addButton . addEventListener ( 'click' , addNewComment ) ;
224-
225- nameInput . addEventListener ( 'input' , function ( ) {
226- console . log ( 'Имя изменено:' , this . value ) ;
227- } ) ;
228-
229- textInput . addEventListener ( 'input' , function ( ) {
230- console . log ( 'Комментарий изменен:' , this . value ) ;
231- } ) ;
232-
233- textInput . addEventListener ( 'keypress' , function ( e ) {
234- if ( e . key === 'Enter' && ! e . shiftKey ) {
235- e . preventDefault ( ) ;
236- addNewComment ( ) ;
237- }
238- } ) ;
212+ function replyToComment ( commentId ) {
213+ const comment = comments . find ( c => c . id === commentId ) ;
214+
215+ if ( comment ) {
216+ replyingToCommentId = commentId ;
217+
218+ const replyText = `> ${ comment . name } :\n> ${ comment . text } \n\n` ;
219+
220+ nameInput . value = comment . name ;
221+ textInput . value = replyText ;
222+
223+ textInput . focus ( ) ;
224+ }
225+ }
226+
227+ async function addNewComment ( ) {
228+ const name = nameInput . value . trim ( ) ;
229+ let text = textInput . value . trim ( ) ;
230+
231+ if ( ! name || ! text ) {
232+ alert ( 'Пожалуйста, заполните все поля' ) ;
233+ return ;
234+ }
235+
236+ const originalText = addButton . textContent ;
237+ addButton . disabled = true ;
238+ addButton . textContent = 'Добавляем...' ;
239+
240+ try {
241+ await postComment ( name , text ) ;
242+
243+ const updatedComments = await fetchComments ( ) ;
244+ updateComments ( updatedComments ) ;
245+ renderComments ( ) ;
246+
247+ nameInput . value = '' ;
248+ textInput . value = '' ;
249+ replyingToCommentId = null ;
250+
251+ } catch ( error ) {
252+ console . error ( 'Ошибка при добавлении комментария:' , error ) ;
253+ alert ( `Не удалось отправить комментарий: ${ error . message } ` ) ;
254+ } finally {
255+ addButton . disabled = false ;
256+ addButton . textContent = originalText ;
257+ }
258+ }
259+
260+ function initApp ( ) {
261+ renderComments ( ) ;
262+
263+ addButton . addEventListener ( 'click' , addNewComment ) ;
264+
265+ nameInput . addEventListener ( 'input' , function ( ) {
266+ console . log ( 'Имя изменено:' , this . value ) ;
267+ } ) ;
268+
269+ textInput . addEventListener ( 'input' , function ( ) {
270+ console . log ( 'Комментарий изменен:' , this . value ) ;
271+ } ) ;
272+
273+ textInput . addEventListener ( 'keydown' , function ( e ) {
274+ if ( e . key === 'Enter' && e . ctrlKey ) {
275+ e . preventDefault ( ) ;
276+ addNewComment ( ) ;
239277 }
278+ } ) ;
279+ }
240280
241- document . addEventListener ( 'DOMContentLoaded' , initApp ) ;
281+ document . addEventListener ( 'DOMContentLoaded' , initApp ) ;
242282
243283 </ script >
244- </ html >
284+ </ html >
0 commit comments