diff --git a/client/src/scss/_modalForm.scss b/client/src/scss/_modalForm.scss new file mode 100644 index 000000000..4f5146991 --- /dev/null +++ b/client/src/scss/_modalForm.scss @@ -0,0 +1,11 @@ +form { + button.form-btn-full-width { + width: 91.2%; + } + div.form-floating-img-container { + top: -250%; + left: 30%; + max-width: 50%; + z-index: 5; + } +} diff --git a/client/src/scss/style.scss b/client/src/scss/style.scss index 7221260ed..2f63eb394 100644 --- a/client/src/scss/style.scss +++ b/client/src/scss/style.scss @@ -23,3 +23,4 @@ $enable-rtl: true; @import 'outLanding.scss'; @import 'register.scss'; @import 'auth-register.scss'; +@import 'modalForm.scss'; diff --git a/client/src/views/out/home/history/Editor.js b/client/src/views/out/home/history/Editor.js index 9975fbc5b..f972075f7 100644 --- a/client/src/views/out/home/history/Editor.js +++ b/client/src/views/out/home/history/Editor.js @@ -1,25 +1,31 @@ +import CIcon from '@coreui/icons-react' import { - CModal, - CModalBody, - CModalHeader, - CModalFooter, - CModalTitle, CButton, CForm, - CInputGroup, CFormControl, - CInputGroupText, CImage, + CInputGroup, + CInputGroupText, + CModal, + CModalBody, + CModalFooter, + CModalHeader, + CModalTitle, } from '@coreui/react' -import ReactTooltip from 'react-tooltip' -import CIcon from '@coreui/icons-react' -import React, { Fragment, useState } from 'react' -import PropTypes from 'prop-types' import axios from 'axios' +import PropTypes from 'prop-types' +import React, { Fragment, useRef, useState } from 'react' +import ReactTooltip from 'react-tooltip' const Editor = ({ visible, setVisible, add, dataForm, setDataForm, refetch }) => { - const [imgPreview, setImgPreview] = useState(dataForm.people.slice().fill(false)) + const [imgPreview, setImgPreview] = useState(new Array(dataForm.people.length).fill(false)) const [pending, setPending] = useState(false) + const [validated, setValidated] = useState(false) + const formRef = useRef(null) + const preventDefaultAndFocus = (e) => { + e.preventDefault() + e.target.focus() + } const handleEnterImgIcon = (index) => { const result = imgPreview.slice() result[index] = true @@ -60,6 +66,10 @@ const Editor = ({ visible, setVisible, add, dataForm, setDataForm, refetch }) => reader.readAsDataURL(file) } const handleSubmit = async () => { + setValidated(true) // display the validation message & style + // prevent the form from submitting if the form is invalid + if (!formRef.current.checkValidity()) return + setPending(true) const data = new FormData() data.append('grade', dataForm.grade) @@ -98,6 +108,7 @@ const Editor = ({ visible, setVisible, add, dataForm, setDataForm, refetch }) => } setPending(false) setVisible(false) + setValidated(false) refetch() } @@ -108,19 +119,24 @@ const Editor = ({ visible, setVisible, add, dataForm, setDataForm, refetch }) => {add ? 'Add a year' : 'Edit this year'} - + @@ -129,13 +145,17 @@ const Editor = ({ visible, setVisible, add, dataForm, setDataForm, refetch }) => @@ -147,19 +167,23 @@ const Editor = ({ visible, setVisible, add, dataForm, setDataForm, refetch }) => handlePeopleChange(e, index)} disabled={pending} + onInvalid={preventDefaultAndFocus} /> handlePeopleDelete(e, index)} + disabled={dataForm.people.length === 1 || pending} > x @@ -172,28 +196,25 @@ const Editor = ({ visible, setVisible, add, dataForm, setDataForm, refetch }) => onMouseLeave={() => handleLeaveImgIcon(index)} /> handleChangeImage(e, index)} onClick={(e) => (e.target.value = null)} disabled={pending} - > + className="form-control" + data-for="image" + data-tip="Put a picture" + accept="image/png, image/jpeg, image/jpg, image/webp, image/avif" + required={dataForm.people[index].img === null} + onInvalid={preventDefaultAndFocus} + /> @@ -206,9 +227,8 @@ const Editor = ({ visible, setVisible, add, dataForm, setDataForm, refetch }) => +