🎨 standardJS all files
This commit is contained in:
@ -1,33 +1,33 @@
|
||||
.CommentCard {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
word-wrap: break-word;
|
||||
box-shadow: 0px 0px 6px 6px rgba(0, 0, 0, .25);
|
||||
border: 1px solid black;
|
||||
border-radius: .7em;
|
||||
margin: 15px 0 15px 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
word-wrap: break-word;
|
||||
box-shadow: 0px 0px 6px 6px rgba(0, 0, 0, 0.25);
|
||||
border: 1px solid black;
|
||||
border-radius: 0.7em;
|
||||
margin: 15px 0 15px 0;
|
||||
}
|
||||
.CommentCard__container {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 20px;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 20px;
|
||||
}
|
||||
.CommentCard__user-logo {
|
||||
border-radius: 50%;
|
||||
object-fit: cover;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
cursor: pointer;
|
||||
border-radius: 50%;
|
||||
object-fit: cover;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.CommentCard__message-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-left: 10px;
|
||||
font-size: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-left: 10px;
|
||||
font-size: 16px;
|
||||
}
|
||||
.CommentCard__message {
|
||||
line-height: 1.8;
|
||||
margin: 15px 0 0 0;
|
||||
}
|
||||
line-height: 1.8;
|
||||
margin: 15px 0 0 0;
|
||||
}
|
||||
|
@ -23,28 +23,42 @@ const CommentCard = forwardRef((props, ref) => {
|
||||
props.manageComment.setLoadingComments(true)
|
||||
if (isAuth && user.token != null) {
|
||||
try {
|
||||
await api.delete(`/comments/${props.id}`, { headers: { Authorization: user.token } })
|
||||
await api.delete(`/comments/${props.id}`, {
|
||||
headers: { Authorization: user.token }
|
||||
})
|
||||
const newCommentsData = { ...props.manageComment.commentsData }
|
||||
const commentIndex = newCommentsData.rows.findIndex((value) => value.id === props.id)
|
||||
const commentIndex = newCommentsData.rows.findIndex(
|
||||
value => value.id === props.id
|
||||
)
|
||||
newCommentsData.rows.splice(commentIndex, 1)
|
||||
props.manageComment.setCommentsData({ hasMore: props.manageComment.commentsData.hasMore, rows: newCommentsData.rows })
|
||||
props.manageComment.setCommentsData({
|
||||
hasMore: props.manageComment.commentsData.hasMore,
|
||||
rows: newCommentsData.rows
|
||||
})
|
||||
} catch {}
|
||||
}
|
||||
props.manageComment.setLoadingComments(false)
|
||||
}
|
||||
|
||||
const handleChange = (event) => {
|
||||
const handleChange = event => {
|
||||
setEditInput(event.target.value)
|
||||
}
|
||||
|
||||
const handleSubmit = (event) => {
|
||||
const handleSubmit = event => {
|
||||
event.preventDefault()
|
||||
api.put(`/comments/${props.id}`, { message: editInput }, { headers: { Authorization: user.token } })
|
||||
.then((_response) => {
|
||||
api
|
||||
.put(
|
||||
`/comments/${props.id}`,
|
||||
{ message: editInput },
|
||||
{ headers: { Authorization: user.token } }
|
||||
)
|
||||
.then(_response => {
|
||||
setEditing(false)
|
||||
})
|
||||
.catch((error) => {
|
||||
setMessage(`<p class="form-error"><b>Erreur:</b> ${error.response.data.message}</p>`)
|
||||
.catch(error => {
|
||||
setMessage(
|
||||
`<p class="form-error"><b>Erreur:</b> ${error.response.data.message}</p>`
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
@ -58,47 +72,73 @@ const CommentCard = forwardRef((props, ref) => {
|
||||
<div className='CommentCard__container'>
|
||||
<div className='row'>
|
||||
<Link href='/users/[name]' as={`/users/${props.user.name}`}>
|
||||
<img className='CommentCard__user-logo' src={API_URL + props.user.logo} alt={props.user.name} />
|
||||
<img
|
||||
className='CommentCard__user-logo'
|
||||
src={API_URL + props.user.logo}
|
||||
alt={props.user.name}
|
||||
/>
|
||||
</Link>
|
||||
<span className='CommentCard__message-info'>
|
||||
<Link href='/users/[name]' as={`/users/${props.user.name}`}>
|
||||
<a>{props.user.name}</a>
|
||||
</Link>
|
||||
- {date.format(new Date(props.createdAt), 'DD/MM/YYYY à HH:mm', true)}
|
||||
-{' '}
|
||||
{date.format(new Date(props.createdAt), 'DD/MM/YYYY à HH:mm', true)}
|
||||
</span>
|
||||
</div>
|
||||
<div className='row'>
|
||||
<div className='col-24'>
|
||||
{
|
||||
(!isEditing)
|
||||
? (
|
||||
<>
|
||||
<div className='CommentCard__message'>
|
||||
<ReactMarkdown source={editInput} renderers={{ code: CodeBlock }} />
|
||||
</div>
|
||||
{(isAuth && user.name === props.user.name) &&
|
||||
<p style={{ fontSize: '15px', margin: '15px 0 0 0', fontStyle: 'italic' }}>
|
||||
<a onClick={deleteCommentById} href='#'>supprimer</a>
|
||||
-
|
||||
<a style={{ cursor: 'pointer' }} onClick={editComment}>modifier</a>
|
||||
</p>}
|
||||
</>
|
||||
)
|
||||
: (
|
||||
<form onSubmit={handleSubmit}>
|
||||
<div className='form-group FunctionComments__post-group'>
|
||||
<label className='form-label' htmlFor='commentEdit'>Modifier le commentaire :</label>
|
||||
<textarea style={{ height: 'auto' }} value={editInput} onChange={handleChange} name='commentEdit' id='commentEdit' className='form-control' rows='5' placeholder="Idée d'amélioration, avis, remarque, partage d'expérience personnel, ... (Markdown autorisé)" />
|
||||
</div>
|
||||
<div className='form-group' style={{ marginTop: '0.7em' }}>
|
||||
<button type='submit' className='btn btn-dark'>Envoyer</button>
|
||||
</div>
|
||||
<div className='text-center'>
|
||||
{htmlParser(message)}
|
||||
</div>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
{!isEditing ? (
|
||||
<>
|
||||
<div className='CommentCard__message'>
|
||||
<ReactMarkdown
|
||||
source={editInput}
|
||||
renderers={{ code: CodeBlock }}
|
||||
/>
|
||||
</div>
|
||||
{isAuth && user.name === props.user.name && (
|
||||
<p
|
||||
style={{
|
||||
fontSize: '15px',
|
||||
margin: '15px 0 0 0',
|
||||
fontStyle: 'italic'
|
||||
}}
|
||||
>
|
||||
<a onClick={deleteCommentById} href='#'>
|
||||
supprimer
|
||||
</a>
|
||||
-
|
||||
<a style={{ cursor: 'pointer' }} onClick={editComment}>
|
||||
modifier
|
||||
</a>
|
||||
</p>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<form onSubmit={handleSubmit}>
|
||||
<div className='form-group FunctionComments__post-group'>
|
||||
<label className='form-label' htmlFor='commentEdit'>
|
||||
Modifier le commentaire :
|
||||
</label>
|
||||
<textarea
|
||||
style={{ height: 'auto' }}
|
||||
value={editInput}
|
||||
onChange={handleChange}
|
||||
name='commentEdit'
|
||||
id='commentEdit'
|
||||
className='form-control'
|
||||
rows='5'
|
||||
placeholder="Idée d'amélioration, avis, remarque, partage d'expérience personnel, ... (Markdown autorisé)"
|
||||
/>
|
||||
</div>
|
||||
<div className='form-group' style={{ marginTop: '0.7em' }}>
|
||||
<button type='submit' className='btn btn-dark'>
|
||||
Envoyer
|
||||
</button>
|
||||
</div>
|
||||
<div className='text-center'>{htmlParser(message)}</div>
|
||||
</form>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -3,7 +3,11 @@ import htmlParser from 'html-react-parser'
|
||||
const FunctionArticle = ({ article }) => {
|
||||
return (
|
||||
<div style={{ marginBottom: '50px' }} className='container-fluid'>
|
||||
{(article != null) ? htmlParser(article) : <p className='text-center'>L'article n'est pas encore disponible.</p>}
|
||||
{article != null ? (
|
||||
htmlParser(article)
|
||||
) : (
|
||||
<p className='text-center'>L'article n'est pas encore disponible.</p>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
.FunctionComments__row {
|
||||
margin-bottom: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.FunctionComments__textarea {
|
||||
height: auto;
|
||||
resize: vertical;
|
||||
}
|
||||
height: auto;
|
||||
resize: vertical;
|
||||
}
|
||||
|
@ -18,49 +18,69 @@ const FunctionComments = ({ functionId }) => {
|
||||
|
||||
// Récupère les commentaires si la page change
|
||||
useEffect(() => {
|
||||
getCommentsData().then((data) => setCommentsData({
|
||||
hasMore: data.hasMore,
|
||||
rows: [...commentsData.rows, ...data.rows]
|
||||
}))
|
||||
getCommentsData().then(data =>
|
||||
setCommentsData({
|
||||
hasMore: data.hasMore,
|
||||
rows: [...commentsData.rows, ...data.rows]
|
||||
})
|
||||
)
|
||||
}, [pageComments])
|
||||
|
||||
// Permet la pagination au scroll
|
||||
const observer = useRef()
|
||||
const lastCommentCardRef = useCallback((node) => {
|
||||
if (isLoadingComments) return
|
||||
if (observer.current) observer.current.disconnect()
|
||||
observer.current = new window.IntersectionObserver((entries) => {
|
||||
if (entries[0].isIntersecting && commentsData.hasMore) {
|
||||
setPageComments(pageComments + 1)
|
||||
}
|
||||
}, { threshold: 1 })
|
||||
if (node) observer.current.observe(node)
|
||||
}, [isLoadingComments, commentsData.hasMore])
|
||||
const lastCommentCardRef = useCallback(
|
||||
node => {
|
||||
if (isLoadingComments) return
|
||||
if (observer.current) observer.current.disconnect()
|
||||
observer.current = new window.IntersectionObserver(
|
||||
entries => {
|
||||
if (entries[0].isIntersecting && commentsData.hasMore) {
|
||||
setPageComments(pageComments + 1)
|
||||
}
|
||||
},
|
||||
{ threshold: 1 }
|
||||
)
|
||||
if (node) observer.current.observe(node)
|
||||
},
|
||||
[isLoadingComments, commentsData.hasMore]
|
||||
)
|
||||
|
||||
const getCommentsData = async () => {
|
||||
setLoadingComments(true)
|
||||
const { data } = await api.get(`/comments/${functionId}/?page=${pageComments}&limit=10`)
|
||||
const { data } = await api.get(
|
||||
`/comments/${functionId}/?page=${pageComments}&limit=10`
|
||||
)
|
||||
setLoadingComments(false)
|
||||
return data
|
||||
}
|
||||
|
||||
const handleChange = (event) => {
|
||||
const handleChange = event => {
|
||||
const inputStateNew = { ...inputState }
|
||||
inputStateNew[event.target.name] = event.target.value
|
||||
setInputState(inputStateNew)
|
||||
}
|
||||
|
||||
const handleSubmit = async (event) => {
|
||||
const handleSubmit = async event => {
|
||||
setLoadingComments(true)
|
||||
event.preventDefault()
|
||||
const token = user.token
|
||||
if (isAuth && token != null && inputState.commentPost != null) {
|
||||
try {
|
||||
const response = await api.post(`/comments/${functionId}`, { message: inputState.commentPost }, { headers: { Authorization: token } })
|
||||
const comment = { ...response.data, user: { name: user.name, logo: user.logo } }
|
||||
setCommentsData({ hasMore: commentsData.hasMore, rows: [comment, ...commentsData.rows] })
|
||||
const response = await api.post(
|
||||
`/comments/${functionId}`,
|
||||
{ message: inputState.commentPost },
|
||||
{ headers: { Authorization: token } }
|
||||
)
|
||||
const comment = {
|
||||
...response.data,
|
||||
user: { name: user.name, logo: user.logo }
|
||||
}
|
||||
setCommentsData({
|
||||
hasMore: commentsData.hasMore,
|
||||
rows: [comment, ...commentsData.rows]
|
||||
})
|
||||
setInputState({ commentPost: '' })
|
||||
} catch { }
|
||||
} catch {}
|
||||
}
|
||||
setLoadingComments(false)
|
||||
}
|
||||
@ -70,40 +90,73 @@ const FunctionComments = ({ functionId }) => {
|
||||
<div className='FunctionComments__post container-fluid'>
|
||||
<div className='row FunctionComments__row'>
|
||||
<div className='col-24'>
|
||||
{
|
||||
(isAuth)
|
||||
? (
|
||||
<form onSubmit={handleSubmit}>
|
||||
<div className='form-group FunctionComments__post-group'>
|
||||
<label className='form-label' htmlFor='commentPost'>Ajouter un commentaire :</label>
|
||||
<textarea className='FunctionComments__textarea form-control' value={inputState.commentPost} onChange={handleChange} name='commentPost' id='commentPost' placeholder="Idée d'amélioration, avis, remarque, partage d'expérience personnel, ... (Markdown autorisé)" />
|
||||
</div>
|
||||
<div className='form-group' style={{ marginTop: '0.7em' }}>
|
||||
<button type='submit' className='btn btn-dark'>Envoyer</button>
|
||||
</div>
|
||||
</form>
|
||||
)
|
||||
: (
|
||||
<p className='text-center'>
|
||||
Vous devez être <Link href='/users/login'><a>connecté</a></Link> pour poster un commentaire.
|
||||
</p>
|
||||
)
|
||||
}
|
||||
{isAuth ? (
|
||||
<form onSubmit={handleSubmit}>
|
||||
<div className='form-group FunctionComments__post-group'>
|
||||
<label className='form-label' htmlFor='commentPost'>
|
||||
Ajouter un commentaire :
|
||||
</label>
|
||||
<textarea
|
||||
className='FunctionComments__textarea form-control'
|
||||
value={inputState.commentPost}
|
||||
onChange={handleChange}
|
||||
name='commentPost'
|
||||
id='commentPost'
|
||||
placeholder="Idée d'amélioration, avis, remarque, partage d'expérience personnel, ... (Markdown autorisé)"
|
||||
/>
|
||||
</div>
|
||||
<div className='form-group' style={{ marginTop: '0.7em' }}>
|
||||
<button type='submit' className='btn btn-dark'>
|
||||
Envoyer
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
) : (
|
||||
<p className='text-center'>
|
||||
Vous devez être{' '}
|
||||
<Link href='/users/login'>
|
||||
<a>connecté</a>
|
||||
</Link>{' '}
|
||||
pour poster un commentaire.
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='container-fluid'>
|
||||
{isLoadingComments &&
|
||||
{isLoadingComments && (
|
||||
<div className='row justify-content-center'>
|
||||
<Loader />
|
||||
</div>}
|
||||
</div>
|
||||
)}
|
||||
<div className='row justify-content-center'>
|
||||
{commentsData.rows.map((comment, index) => {
|
||||
// Si c'est le dernier élément
|
||||
if (commentsData.rows.length === index + 1) {
|
||||
return <CommentCard key={comment.id} ref={lastCommentCardRef} {...comment} manageComment={{ setCommentsData, commentsData, setLoadingComments }} />
|
||||
return (
|
||||
<CommentCard
|
||||
key={comment.id}
|
||||
ref={lastCommentCardRef}
|
||||
{...comment}
|
||||
manageComment={{
|
||||
setCommentsData,
|
||||
commentsData,
|
||||
setLoadingComments
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
return <CommentCard key={comment.id} {...comment} manageComment={{ setCommentsData, commentsData, setLoadingComments }} />
|
||||
return (
|
||||
<CommentCard
|
||||
key={comment.id}
|
||||
{...comment}
|
||||
manageComment={{
|
||||
setCommentsData,
|
||||
commentsData,
|
||||
setLoadingComments
|
||||
}}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -9,7 +9,7 @@ import api from '../../utils/api'
|
||||
import { API_URL } from '../../utils/config/config'
|
||||
import '../FunctionCard/FunctionCard.css'
|
||||
|
||||
const FunctionComponentTop = (props) => {
|
||||
const FunctionComponentTop = props => {
|
||||
const { isAuth, user } = useContext(UserContext)
|
||||
const [isFavorite, setIsFavorite] = useState(false)
|
||||
|
||||
@ -21,7 +21,9 @@ const FunctionComponentTop = (props) => {
|
||||
|
||||
const fetchFavorite = async () => {
|
||||
try {
|
||||
const favoriteResponse = await api.get(`/favorites/${props.id}`, { headers: { Authorization: user.token } })
|
||||
const favoriteResponse = await api.get(`/favorites/${props.id}`, {
|
||||
headers: { Authorization: user.token }
|
||||
})
|
||||
setIsFavorite(favoriteResponse.data.isFavorite)
|
||||
} catch {}
|
||||
}
|
||||
@ -30,16 +32,22 @@ const FunctionComponentTop = (props) => {
|
||||
if (isAuth && user.token != null) {
|
||||
try {
|
||||
if (isFavorite) {
|
||||
const response = await api.delete(`/favorites/${props.id}`, { headers: { Authorization: user.token } })
|
||||
const response = await api.delete(`/favorites/${props.id}`, {
|
||||
headers: { Authorization: user.token }
|
||||
})
|
||||
if (response.status === 200) return setIsFavorite(false)
|
||||
}
|
||||
const response = await api.post(`/favorites/${props.id}`, {}, { headers: { Authorization: user.token } })
|
||||
const response = await api.post(
|
||||
`/favorites/${props.id}`,
|
||||
{},
|
||||
{ headers: { Authorization: user.token } }
|
||||
)
|
||||
if (response.status === 201) return setIsFavorite(true)
|
||||
} catch {}
|
||||
}
|
||||
}
|
||||
|
||||
const handleError = (event) => {
|
||||
const handleError = event => {
|
||||
event.target.src = API_URL + '/images/functions/default.png'
|
||||
}
|
||||
|
||||
@ -47,18 +55,44 @@ const FunctionComponentTop = (props) => {
|
||||
<div className='container-fluid'>
|
||||
<div className='row justify-content-center text-center'>
|
||||
<div className='FunctionComponent__top col-24'>
|
||||
{isAuth && (
|
||||
<FontAwesomeIcon
|
||||
onClick={toggleFavorite}
|
||||
{...(isFavorite ? { icon: faStar } : { icon: farStar })}
|
||||
title={
|
||||
isFavorite
|
||||
? 'Retirer la fonction des favoris'
|
||||
: 'Ajouter la fonction aux favoris'
|
||||
}
|
||||
className='FunctionComponent__star-favorite'
|
||||
/>
|
||||
)}
|
||||
|
||||
{(isAuth) &&
|
||||
<FontAwesomeIcon onClick={toggleFavorite} {...(isFavorite) ? { icon: faStar } : { icon: farStar }} title={(isFavorite) ? 'Retirer la fonction des favoris' : 'Ajouter la fonction aux favoris'} className='FunctionComponent__star-favorite' />}
|
||||
|
||||
<img onError={handleError} className='FunctionComponent__image' src={API_URL + props.image} alt={props.title} />
|
||||
<h1 className='FunctionComponent__title title-important'>{props.title}</h1>
|
||||
<img
|
||||
onError={handleError}
|
||||
className='FunctionComponent__image'
|
||||
src={API_URL + props.image}
|
||||
alt={props.title}
|
||||
/>
|
||||
<h1 className='FunctionComponent__title title-important'>
|
||||
{props.title}
|
||||
</h1>
|
||||
<p className='FunctionComponent__description'>{props.description}</p>
|
||||
<div className='FunctionCard__info'>
|
||||
<Link href={`/functions?categoryId=${props.categorieId}`}>
|
||||
<a className='FunctionCard__category' style={{ backgroundColor: props.categorie.color, color: 'inherit' }}>{props.categorie.name}</a>
|
||||
<a
|
||||
className='FunctionCard__category'
|
||||
style={{
|
||||
backgroundColor: props.categorie.color,
|
||||
color: 'inherit'
|
||||
}}
|
||||
>
|
||||
{props.categorie.name}
|
||||
</a>
|
||||
</Link>
|
||||
<p className='FunctionCard__publication-date'>{date.format(new Date(props.createdAt), 'DD/MM/YYYY', true)}</p>
|
||||
<p className='FunctionCard__publication-date'>
|
||||
{date.format(new Date(props.createdAt), 'DD/MM/YYYY', true)}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -10,7 +10,7 @@ import 'react-datepicker/dist/react-datepicker.css'
|
||||
|
||||
registerLocale('fr', fr)
|
||||
|
||||
const FunctionForm = (props) => {
|
||||
const FunctionForm = props => {
|
||||
const [inputState, setInputState] = useState({})
|
||||
const [message, setMessage] = useState('')
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
@ -18,7 +18,7 @@ const FunctionForm = (props) => {
|
||||
// inputState par défaut
|
||||
useEffect(() => {
|
||||
const inputStateNew = { ...inputState }
|
||||
props.inputsArray.forEach((input) => {
|
||||
props.inputsArray.forEach(input => {
|
||||
if (input.type === 'select' && input.options.length > 0) {
|
||||
inputStateNew[input.name] = input.options[0].value
|
||||
}
|
||||
@ -26,21 +26,22 @@ const FunctionForm = (props) => {
|
||||
setInputState(inputStateNew)
|
||||
}, [])
|
||||
|
||||
const handleSubmit = (event) => {
|
||||
const handleSubmit = event => {
|
||||
setIsLoading(true)
|
||||
event.preventDefault()
|
||||
api.post(`/functions/${props.slug}`, inputState)
|
||||
.then((response) => {
|
||||
api
|
||||
.post(`/functions/${props.slug}`, inputState)
|
||||
.then(response => {
|
||||
setMessage(response.data.resultHTML)
|
||||
setIsLoading(false)
|
||||
})
|
||||
.catch((error) => {
|
||||
.catch(error => {
|
||||
setMessage(error.response.data.message)
|
||||
setIsLoading(false)
|
||||
})
|
||||
}
|
||||
|
||||
const handleChange = (event) => {
|
||||
const handleChange = event => {
|
||||
const inputStateNew = { ...inputState }
|
||||
inputStateNew[event.target.name] = event.target.value
|
||||
setInputState(inputStateNew)
|
||||
@ -61,16 +62,35 @@ const FunctionForm = (props) => {
|
||||
case 'text':
|
||||
return (
|
||||
<div key={index} className='form-group'>
|
||||
<label className='form-label' htmlFor={input.name}>{input.label}</label>
|
||||
<input onChange={handleChange} type='text' name={input.name} id={input.name} placeholder={input.placeholder} className='form-control' />
|
||||
<label className='form-label' htmlFor={input.name}>
|
||||
{input.label}
|
||||
</label>
|
||||
<input
|
||||
onChange={handleChange}
|
||||
type='text'
|
||||
name={input.name}
|
||||
id={input.name}
|
||||
placeholder={input.placeholder}
|
||||
className='form-control'
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
case 'integer':
|
||||
case 'float':
|
||||
return (
|
||||
<div key={index} className='form-group'>
|
||||
<label className='form-label' htmlFor={input.name}>{input.label}</label>
|
||||
<input onChange={handleChange} type='number' step={(input.type === 'integer') ? '1' : '0.01'} name={input.name} id={input.name} placeholder={input.placeholder} className='form-control' />
|
||||
<label className='form-label' htmlFor={input.name}>
|
||||
{input.label}
|
||||
</label>
|
||||
<input
|
||||
onChange={handleChange}
|
||||
type='number'
|
||||
step={input.type === 'integer' ? '1' : '0.01'}
|
||||
name={input.name}
|
||||
id={input.name}
|
||||
placeholder={input.placeholder}
|
||||
className='form-control'
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
case 'calendar':
|
||||
@ -81,13 +101,14 @@ const FunctionForm = (props) => {
|
||||
document.body.appendChild(newScript)
|
||||
}
|
||||
// eslint-disable-next-line
|
||||
const DatePicker = dynamic(
|
||||
() => import('react-datepicker'),
|
||||
{ ssr: false }
|
||||
)
|
||||
const DatePicker = dynamic(() => import('react-datepicker'), {
|
||||
ssr: false
|
||||
})
|
||||
return (
|
||||
<div key={index} className='form-group'>
|
||||
<label className='form-label' htmlFor={input.name}>{input.label}</label>
|
||||
<label className='form-label' htmlFor={input.name}>
|
||||
{input.label}
|
||||
</label>
|
||||
<br />
|
||||
<DatePicker
|
||||
selected={(() => {
|
||||
@ -97,7 +118,11 @@ const FunctionForm = (props) => {
|
||||
const year = dateArray[2]
|
||||
const month = dateArray[1]
|
||||
const day = dateArray[0]
|
||||
return new Date(year, parseInt(month) - 1, parseInt(day) + 1)
|
||||
return new Date(
|
||||
year,
|
||||
parseInt(month) - 1,
|
||||
parseInt(day) + 1
|
||||
)
|
||||
}
|
||||
throw new Error('Not a valid date')
|
||||
} catch {
|
||||
@ -108,9 +133,13 @@ const FunctionForm = (props) => {
|
||||
dateFormat='dd/MM/yyyy'
|
||||
fixedHeight
|
||||
placeholderText={input.placeholder}
|
||||
onChange={(dateObject) => {
|
||||
onChange={dateObject => {
|
||||
try {
|
||||
const formattedDate = date.format(dateObject, 'DD/MM/YYYY', true)
|
||||
const formattedDate = date.format(
|
||||
dateObject,
|
||||
'DD/MM/YYYY',
|
||||
true
|
||||
)
|
||||
handleChange({
|
||||
target: {
|
||||
name: input.name,
|
||||
@ -125,33 +154,39 @@ const FunctionForm = (props) => {
|
||||
case 'select':
|
||||
return (
|
||||
<div key={index} className='form-group'>
|
||||
<label className='form-label' htmlFor={input.name}>{input.label}</label>
|
||||
<select onChange={handleChange} name={input.name} id={input.name} value={inputState[input.name] || input.options[0]} className='form-control'>
|
||||
<label className='form-label' htmlFor={input.name}>
|
||||
{input.label}
|
||||
</label>
|
||||
<select
|
||||
onChange={handleChange}
|
||||
name={input.name}
|
||||
id={input.name}
|
||||
value={inputState[input.name] || input.options[0]}
|
||||
className='form-control'
|
||||
>
|
||||
{input.options.map((option, optionIndex) => {
|
||||
return (
|
||||
<option key={optionIndex} value={option.value}>{option.name}</option>
|
||||
<option key={optionIndex} value={option.value}>
|
||||
{option.name}
|
||||
</option>
|
||||
)
|
||||
})}
|
||||
</select>
|
||||
</div>
|
||||
)
|
||||
default:
|
||||
return (
|
||||
<p>Erreur, l'input n'est pas valide...</p>
|
||||
)
|
||||
return <p>Erreur, l'input n'est pas valide...</p>
|
||||
}
|
||||
})}
|
||||
|
||||
<div className='form-group text-center'>
|
||||
<button type='submit' className='btn btn-dark'>Envoyer</button>
|
||||
<button type='submit' className='btn btn-dark'>
|
||||
Envoyer
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
<div className='form-result text-center'>
|
||||
{
|
||||
(isLoading)
|
||||
? <Loader />
|
||||
: htmlParser(message)
|
||||
}
|
||||
{isLoading ? <Loader /> : htmlParser(message)}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
|
@ -4,17 +4,29 @@ import HeadTag from '../HeadTag'
|
||||
import FunctionTabsTop from './FunctionTabsTop'
|
||||
import FunctionComponentTop from './FunctionComponentTop'
|
||||
|
||||
const FunctionPage = (props) => {
|
||||
const FunctionPage = props => {
|
||||
const [slideIndex, setSlideIndex] = useState(0)
|
||||
|
||||
return (
|
||||
<>
|
||||
<HeadTag title={props.title} description={props.description} image={API_URL + props.image} />
|
||||
<HeadTag
|
||||
title={props.title}
|
||||
description={props.description}
|
||||
image={API_URL + props.image}
|
||||
/>
|
||||
|
||||
<div className='container-fluid'>
|
||||
<FunctionTabsTop slideIndex={slideIndex} setSlideIndex={setSlideIndex} tabNames={props.tabNames} />
|
||||
<FunctionTabsTop
|
||||
slideIndex={slideIndex}
|
||||
setSlideIndex={setSlideIndex}
|
||||
tabNames={props.tabNames}
|
||||
/>
|
||||
<FunctionComponentTop {...props} />
|
||||
<props.FunctionTabManager {...props} slideIndex={slideIndex} setSlideIndex={setSlideIndex} />
|
||||
<props.FunctionTabManager
|
||||
{...props}
|
||||
slideIndex={slideIndex}
|
||||
setSlideIndex={setSlideIndex}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
|
@ -1,41 +1,41 @@
|
||||
.FunctionTabs__nav {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
padding-left: 0;
|
||||
margin-bottom: 0;
|
||||
list-style: none;
|
||||
border-bottom: 1px solid #d9e2ef;
|
||||
margin-bottom: -1px;
|
||||
margin-top: 30px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
padding-left: 0;
|
||||
margin-bottom: 0;
|
||||
list-style: none;
|
||||
border-bottom: 1px solid #d9e2ef;
|
||||
margin-bottom: -1px;
|
||||
margin-top: 30px;
|
||||
}
|
||||
.FunctionTabs__nav-item {
|
||||
margin-bottom: -1px;
|
||||
cursor: pointer;
|
||||
margin-bottom: -1px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.FunctionTabs__nav-link {
|
||||
color: var(--text-color);
|
||||
border: 1px solid #0c0b0b38;
|
||||
border-bottom: 0px;
|
||||
border-top-left-radius: .375rem;
|
||||
border-top-right-radius: .375rem;
|
||||
display: block;
|
||||
padding: .5rem 1rem;
|
||||
transition: .2s;
|
||||
color: var(--text-color);
|
||||
border: 1px solid #0c0b0b38;
|
||||
border-bottom: 0px;
|
||||
border-top-left-radius: 0.375rem;
|
||||
border-top-right-radius: 0.375rem;
|
||||
display: block;
|
||||
padding: 0.5rem 1rem;
|
||||
transition: 0.2s;
|
||||
}
|
||||
.FunctionTabs__nav-link-active {
|
||||
border-color: #d9e2ef #d9e2ef #fff;
|
||||
color: var(--important);
|
||||
border-color: #d9e2ef #d9e2ef #fff;
|
||||
color: var(--important);
|
||||
}
|
||||
.FunctionTabs__nav-link:hover {
|
||||
border-color: #f1f4f8 #f1f4f8 #d9e2ef;
|
||||
text-decoration: none;
|
||||
border-color: #f1f4f8 #f1f4f8 #d9e2ef;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
@media (max-width: 490px) {
|
||||
.FunctionTabs__nav {
|
||||
flex-direction: column;
|
||||
}
|
||||
.FunctionTabs__nav-link {
|
||||
border-color: #f1f4f8 #f1f4f8 #d9e2ef;
|
||||
}
|
||||
}
|
||||
.FunctionTabs__nav {
|
||||
flex-direction: column;
|
||||
}
|
||||
.FunctionTabs__nav-link {
|
||||
border-color: #f1f4f8 #f1f4f8 #d9e2ef;
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
import SwipeableViews from 'react-swipeable-views'
|
||||
import './FunctionTabs.css'
|
||||
|
||||
const FunctionTabs = (props) => {
|
||||
const FunctionTabs = props => {
|
||||
return (
|
||||
<div className='container-fluid'>
|
||||
<SwipeableViews onChangeIndex={(index) => props.setSlideIndex(index)} index={props.slideIndex}>
|
||||
<SwipeableViews
|
||||
onChangeIndex={index => props.setSlideIndex(index)}
|
||||
index={props.slideIndex}
|
||||
>
|
||||
{props.children}
|
||||
</SwipeableViews>
|
||||
</div>
|
||||
|
@ -1,4 +1,4 @@
|
||||
const FunctionTabsTop = (props) => {
|
||||
const FunctionTabsTop = props => {
|
||||
return (
|
||||
<div className='container'>
|
||||
<div className='row justify-content-center'>
|
||||
@ -7,7 +7,11 @@ const FunctionTabsTop = (props) => {
|
||||
return (
|
||||
<li key={index} className='FunctionTabs__nav-item'>
|
||||
<a
|
||||
className={`FunctionTabs__nav-link ${(props.slideIndex === index) ? 'FunctionTabs__nav-link-active' : ''}`}
|
||||
className={`FunctionTabs__nav-link ${
|
||||
props.slideIndex === index
|
||||
? 'FunctionTabs__nav-link-active'
|
||||
: ''
|
||||
}`}
|
||||
onClick={() => props.setSlideIndex(index)}
|
||||
>
|
||||
{tabName}
|
||||
|
Reference in New Issue
Block a user