Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NTUEEPLUS-308 Add frontend validation to history Editor form & styles improvement #262

Merged
merged 2 commits into from
May 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions client/src/scss/_modalForm.scss
Original file line number Diff line number Diff line change
@@ -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;
}
}
1 change: 1 addition & 0 deletions client/src/scss/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ $enable-rtl: true;
@import 'outLanding.scss';
@import 'register.scss';
@import 'auth-register.scss';
@import 'modalForm.scss';
92 changes: 56 additions & 36 deletions client/src/views/out/home/history/Editor.js
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -98,6 +108,7 @@ const Editor = ({ visible, setVisible, add, dataForm, setDataForm, refetch }) =>
}
setPending(false)
setVisible(false)
setValidated(false)
refetch()
}

Expand All @@ -108,19 +119,24 @@ const Editor = ({ visible, setVisible, add, dataForm, setDataForm, refetch }) =>
<CModalTitle>{add ? 'Add a year' : 'Edit this year'} </CModalTitle>
</CModalHeader>
<CModalBody>
<CForm>
<CForm ref={formRef} validated={validated} noValidate>
<CInputGroup className="mb-3">
<CInputGroupText>
<CIcon icon="cil-calendar" />
</CInputGroupText>
<CFormControl
data-for="grade"
data-tip="Grade(Bxx)"
required
pattern="B\d{2}"
type="text"
name="grade"
data-for="grade" // for react-tooltip
data-tip="Grade(Bxx)" // the hovering texts
placeholder="Grade*"
value={dataForm.grade}
name="grade"
onChange={handleInputChange}
disabled={pending}
className="form-control"
onInvalid={preventDefaultAndFocus}
/>
<ReactTooltip id="grade" place="top" type="dark" effect="solid" />
</CInputGroup>
Expand All @@ -129,13 +145,17 @@ const Editor = ({ visible, setVisible, add, dataForm, setDataForm, refetch }) =>
<CIcon icon="cil-user" />
</CInputGroupText>
<CFormControl
required
type="text"
name="title"
placeholder="Title*"
data-for="title"
data-tip="Add Title Here"
placeholder="Title*"
value={dataForm.title}
name="title"
onChange={handleInputChange}
disabled={pending}
className="form-control"
onInvalid={preventDefaultAndFocus}
/>
<ReactTooltip id="title" place="top" type="dark" effect="solid" />
</CInputGroup>
Expand All @@ -147,19 +167,23 @@ const Editor = ({ visible, setVisible, add, dataForm, setDataForm, refetch }) =>
<CIcon icon="cil-user" />
</CInputGroupText>
<CFormControl
data-for="name"
data-tip="Enter the name"
type="text"
required
className="form-control"
data-for="name" // for react-tooltip
data-tip="Enter the name" // the hovering texts
placeholder="Name*"
name="name"
value={person.name}
onChange={(e) => handlePeopleChange(e, index)}
disabled={pending}
onInvalid={preventDefaultAndFocus}
/>
<ReactTooltip id="name" place="top" type="dark" effect="solid" />
<CButton
type="button"
name="name"
onClick={(e) => handlePeopleDelete(e, index)}
disabled={dataForm.people.length === 1 || pending}
>
x
</CButton>
Expand All @@ -172,28 +196,25 @@ const Editor = ({ visible, setVisible, add, dataForm, setDataForm, refetch }) =>
onMouseLeave={() => handleLeaveImgIcon(index)}
/>
<div
style={{
top: '-250%',
left: '30%',
maxWidth: '50%',
zIndex: 5,
}}
className={'position-absolute '.concat(
imgPreview[index] && dataForm.people[index].img ? 'visible' : 'invisible',
)}
className="position-absolute form-floating-img-container"
hidden={!(imgPreview[index] && dataForm.people[index].img)}
>
<CImage fluid src={dataForm.people[index].img} alt="img preview" />
</div>
</CInputGroupText>
<CFormControl
data-for="image"
data-tip="Put a picture"
id="formFile"
type="file"
id="formFile"
onChange={(e) => handleChangeImage(e, index)}
onClick={(e) => (e.target.value = null)}
disabled={pending}
></CFormControl>
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}
/>
<ReactTooltip id="image" place="top" type="dark" effect="solid" />
</CInputGroup>
</Fragment>
Expand All @@ -206,9 +227,8 @@ const Editor = ({ visible, setVisible, add, dataForm, setDataForm, refetch }) =>
<CButton
type="button"
name="person"
className="form-add"
className="form-add form-btn-full-width"
onClick={addPeople}
style={{ width: '91.2%' }}
disabled={pending}
>
+
Expand Down
Loading