diff --git a/src/widget/index.js b/src/widget/index.js index aeba7ed2..0316daa4 100644 --- a/src/widget/index.js +++ b/src/widget/index.js @@ -99,6 +99,14 @@ const generateModalStyles = () => { padding: 0; } + #hexlet-correction-modal_ReportTypo-invalid-feedback { + display: block; + width: 100%; + margin-top: .25rem; + font-size: .875em; + color: #dc3545; +} + #hexlet-correction-modal_ReportTypo-submit:hover { background-color: #1e7cd6; } @@ -192,14 +200,48 @@ const generateModal = (state) => { }; }; -const resetModalState = (state) => { - state.modalShown = false; - state.data.reporterComment = ''; - state.data.textBeforeTypo = ''; - state.data.textTypo = ''; - state.data.textAfterTypo = ''; +const resetModalState = (state, errors = new Map()) => { + if(errors.size === 0) { + state.modalShown = false; + state.data.reporterComment = ''; + state.data.textBeforeTypo = ''; + state.data.textTypo = ''; + state.data.textAfterTypo = ''; + } else { + for (let label of errors.keys()) { + console.log(label); + if (label === 'reporterName') { + renderInvalidFeedback('hexlet-correction-modal_ReportTypo-name', errors.get(label)); + } else { + renderInvalidFeedback('hexlet-correction-modal_ReportTypo-comment', errors.get(label)); + } + } + } }; +const renderInvalidFeedback = (elementId, message) => { + const targetElement = document.getElementById(elementId); + const divElement = document.createElement('div'); + divElement.textContent = message; + + targetElement.insertAdjacentElement('afterend', divElement); + + const style = document.createElement('style'); + style.textContent = ` + .hexlet-correction-modal_ReportTypo-invalid-feedback { + display: block; + width: 100%; + margin-top: 0.25rem; + font-size: 0.875em; + color: #dc3545; + } + `; + + document.head.insertAdjacentElement('beforeend', style); + + divElement.classList.add('hexlet-correction-modal_ReportTypo-invalid-feedback'); +} + const renderModal = (elements, state) => { if (state.modalShown) { elements.modalEl.style.display = 'block'; @@ -216,7 +258,16 @@ const renderModal = (elements, state) => { elements.commentEl.value = ''; }; +const removeInvalidElements = () => { + const invalidElements = document.querySelectorAll('.hexlet-correction-modal_ReportTypo-invalid-feedback'); + + invalidElements.forEach(element => { + element.remove(); + }); +} + const sendData = (elements, state) => async (event) => { + removeInvalidElements(); event.preventDefault(); const { value } = elements.inputName; state.data.reporterName = value === '' ? 'Anonymous' : value; @@ -231,19 +282,18 @@ const sendData = (elements, state) => async (event) => { body: JSON.stringify(state.data), }); let data = await response.json(); - if (isSuccessPost(response)) { + if (response.status === 201) { resetModalState(state); } else { const errors = getErrors(data); - alert(errors); + resetModalState(state, errors); } } catch (error) { - let errorText = - 'Error in plugin integration.\n' + - 'Check the settings (https://fixit.hexlet.io/workspace/{workspaceID}/integration).'; - alert(errorText) - resetModalState(state); - throw new Error('Произошла ошибка:', error); + const errorText = + 'Error in plugin integration.\n' + + 'Check the settings (https://fixit.hexlet.io/workspace/{workspaceID}/integration).'; + renderInvalidFeedback('hexlet-correction-modal_ReportTypo-header', errorText); + throw new Error('Произошла ошибка:', error); } }; @@ -278,17 +328,15 @@ const isSelectionLeftToRight = (selection) => { return range.collapsed; } -const isSuccessPost = (response) => { - return response.status === 201; -} - const getErrors = (data) => { - let text = 'There are the following errors in the submission form:\n'; - Object.keys(data.errors).forEach(key => { - let message = data.errors[key]; - text += `${message} \n`; - }); - return text; + const errors = new Map(); + + for (const [key, message] of Object.entries(data.errors)) { + const [label, errorMessage] = message.split(": "); + errors.set(label, errorMessage); + } + + return errors; } const handleTypoReporter = (options) => { @@ -299,7 +347,7 @@ const handleTypoReporter = (options) => { const initialState = { modalShown: false, options: { - workSpaceUrl: 'https://hexlet-correction-u17z.onrender.com/api/workspaces', + workSpaceUrl: 'http://localhost:8080/api/workspaces', userName: null, ...options, }, @@ -309,7 +357,7 @@ const handleTypoReporter = (options) => { reporterComment: '', textBeforeTypo: '', textTypo: '', - textAfterTypo: '', + textAfterTypo: '' }, };