Proyectos de Subversion LeadersLinked - Backend

Rev

Rev 14389 | Autoría | Comparar con el anterior | Ultima modificación | Ver Log |

/* eslint-disable no-mixed-spaces-and-tabs */
import React, { useState, useEffect } from 'react'
import axios from 'axios'
import parse from 'html-react-parser'
import { useForm } from 'react-hook-form'
import { useDispatch } from 'react-redux'
import { useHistory, useParams } from 'react-router-dom'
import { addNotification } from '../../../redux/notification/notification.actions'
import DescriptionInput from '../../../shared/DescriptionInput'
import SectionModal from '../components/SectionModal'
import DeleteModal from '../../../shared/DeleteModal'
import QuestionModal from '../components/QuestionModal'
import OptionModal from '../components/OptionModal'

const sectionTypeOptions = {
        open: 'Abierto',
        simple: 'Simple',
        multiple: 'Multiple'
}

const INITIAL_OPTION = {
        slug_section: '',
        slug_question: '',
        slug_option: '',
        text: '',
        checked: false,
        position: 0
}

const INITIAL_SECTION = {
        slug_section: '',
        name: '',
        text: '',
        position: 0,
        questions: [],
        status: 0
}

const INITIAL_QUESTION = {
        slug_section: '',
        slug_question: '',
        text: '',
        type: '',
        position: 0,
        maxlength: '0',
        multiline: '0',
        range: '0',
        options: [],
        answer: ''
}

const FormView = ({ actionLink }) => {

        // Hooks
        const history = useHistory()
        const { action } = useParams()
        const dispatch = useDispatch()
        const { register, setValue, watch, reset } = useForm()

        // Section modal states
        const [isShowSection, setIsShowSectionModal] = useState(false)
        const [sectionSelected, setSectionSelected] = useState(INITIAL_SECTION)
        const [sectionType, setSectionType] = useState('add')

        // Question modal states
        const [isShowQuestion, setIsShowQuestionModal] = useState(false)
        const [questionSelected, setQuestionSelected] = useState(INITIAL_QUESTION)
        const [questionType, setQuestionType] = useState('add')

        // Option modal states
        const [isShowOption, setIsShowOptionModal] = useState(false)
        const [optionSelected, setOptionSelected] = useState(INITIAL_OPTION)
        const [optionType, setOptionType] = useState('add')

        const [content, setContent] = useState([])
        const [status, setStatus] = useState('A')
        const [showDeleteModal, setShowDeleteModal] = useState(false)
        const [deleteType, setDeleteType] = useState('section')
        const deleteSlugsOptions = {
                section: sectionSelected.slug_section,
                question: questionSelected.slug_question,
                option: optionSelected.slug_option
        }

        const [text, setText] = useState((action != 'edit') ? ' ' : '')
        const [description, setDescription] = useState((action != 'edit') ? ' ' : '')

        // Section methods
        const showSectionModal = (section = INITIAL_SECTION, type = 'add') => {
                setSectionSelected(section)
                setSectionType(type)
                setIsShowSectionModal(true)
        }

        const closeSectionModal = () => {
                setIsShowSectionModal(false)
                setSectionSelected(INITIAL_SECTION)
        }

        const addSection = (name, text) => {
                const uuid = new Date().getTime()
                let position = content.length
                console.log(name)
                console.log(text)

                setContent(prev => [...prev, {
                        slug_section: `section${uuid}`,
                        name: name,
                        text: text,
                        position: position,
                        questions: [],
                        status: 0
                }])
        }

        const editSection = (name, text, slug) => {
                setContent(current =>
                        current.map(currentSection => {
                                if (currentSection.slug_section === slug) {
                                        return { ...currentSection, name: name, text: text }
                                }

                                return currentSection
                        })
                )
        }

        const deleteSection = (slug) => {
                setContent(current =>
                        current.filter(currentSection => {
                                return currentSection.slug_section !== slug
                        }),
                )
        }

        // Question methods
        const showQuestionModal = (question = INITIAL_QUESTION, type = 'add') => {
                setIsShowQuestionModal(true)
                setQuestionType(type)
                setQuestionSelected(question)
        }

        const closeQuestionModal = () => {
                setIsShowQuestionModal(false)
                setQuestionSelected(INITIAL_QUESTION)
        }

        const addQuestion = (question) => {
                const uuid = new Date().getTime()

                setContent(current =>
                        current.map(currentSection => {
                                if (currentSection.slug_section === sectionSelected.slug_section) {
                                        return {
                                                ...currentSection,
                                                questions: [
                                                        ...currentSection.questions,
                                                        {
                                                                ...question,
                                                                slug_question: `question${uuid}`,
                                                                slug_section: sectionSelected.slug_section,
                                                        }
                                                ]
                                        }
                                }

                                return currentSection
                        })
                )
        }

        const editQuestion = (question) => {
                setContent(current =>
                        current.map(currentSection => {
                                if (currentSection.slug_section === sectionSelected.slug_section) {

                                        const newQuestions = currentSection.questions.map((currentQuestion) => {
                                                if (currentQuestion.slug_question === question.slug_question) {
                                                        return question
                                                }

                                                return currentQuestion
                                        })

                                        return { ...currentSection, questions: newQuestions }
                                }

                                return currentSection
                        })
                )
        }

        const deleteQuestion = (slug) => {
                setContent(current =>
                        current.map(currentSection => {
                                if (currentSection.slug_section === sectionSelected.slug_section) {
                                        return {
                                                ...currentSection,
                                                questions: currentSection.questions.filter((currentQuestion) => currentQuestion.slug_question !== slug)
                                        }
                                }
                                return currentSection
                        }),
                )
        }

        // Option methods
        const showOptionModal = (option = INITIAL_OPTION, type = 'add') => {
                setIsShowOptionModal(true)
                setOptionType(type)
                setOptionSelected(option)
        }

        const closeOptionModal = () => {
                setIsShowOptionModal(false)
                setOptionSelected(INITIAL_QUESTION)
        }

        const addOption = (option) => {
                const uuid = new Date().getTime()

                setContent(current =>
                        current.map(currentSection => {
                                if (currentSection.slug_section === sectionSelected.slug_section) {

                                        return {
                                                ...currentSection,
                                                questions: currentSection.questions.map(currentQuestion => {
                                                        if (currentQuestion.slug_question === questionSelected.slug_question) {

                                                                return {
                                                                        ...currentQuestion,
                                                                        options: [
                                                                                ...currentQuestion.options,
                                                                                {
                                                                                        ...option,
                                                                                        slug_question: questionSelected.slug_question,
                                                                                        slug_section: sectionSelected.slug_section,
                                                                                        slug_option: `option${uuid}`
                                                                                }
                                                                        ]
                                                                }
                                                        }

                                                        return currentQuestion
                                                })
                                        }
                                }
                                return currentSection
                        })
                )
        }

        const editOption = (option) => {

                setContent(current =>
                        current.map(currentSection => {
                                if (currentSection.slug_section === sectionSelected.slug_section) {

                                        return {
                                                ...currentSection,
                                                questions: currentSection.questions.map(currentQuestion => {
                                                        if (currentQuestion.slug_question === questionSelected.slug_question) {

                                                                return {
                                                                        ...currentQuestion,
                                                                        options: currentQuestion.options.map(currentOption => {
                                                                                if (currentOption.slug_option === option.slug_option) {
                                                                                        return option
                                                                                }

                                                                                return currentOption
                                                                        })
                                                                }
                                                        }

                                                        return currentQuestion
                                                })
                                        }
                                }
                                return currentSection
                        })
                )
        }

        const deleteOption = (slug) => {
                setContent(current =>
                        current.map(currentSection => {
                                if (currentSection.slug_section === sectionSelected.slug_section) {

                                        return {
                                                ...currentSection,
                                                questions: currentSection.questions.map(question => {

                                                        if (question.slug_question === questionSelected.slug_question) {
                                                                return {
                                                                        ...question,
                                                                        options: question.options.filter(option => option.slug_option !== slug)
                                                                }
                                                        }

                                                        return question
                                                })
                                        }
                                }

                                return currentSection
                        }),
                )
        }

        // General methods
        const deleteHandler = (type, slug) => {
                if (type === 'section') {
                        return deleteSection(slug)
                }
                if (type === 'question') {
                        return deleteQuestion(slug)
                }
                if (type === 'option') {
                        return deleteOption(slug)
                }
        }

        const validate = () => {
                const sectionError = content.find(section => !section.questions.length)

                if (sectionError) {
                        dispatch(addNotification({
                                style: 'danger',
                                msg: `La sección ${sectionError.name} no tiene preguntas`
                        }))

                        return false
                } else {
                        return true
                }
        }

        const onSubmit = () => {

                const isValid = validate()

                if (isValid) {
                        const submitData = new FormData()
                        submitData.append('name', watch('name'))
                        submitData.append('description', watch('description'))
                        submitData.append('text', watch('text'))
                        submitData.append('status', status)
                        submitData.append('content', JSON.stringify(content))

                        axios.post(actionLink, submitData)
                                .then(({ data }) => {
                                        if (!data.success) {
                                                typeof data.data === 'string'
                                                        ?
                                                        dispatch(addNotification({
                                                                style: 'danger',
                                                                msg: data.data
                                                        }))
                                                        : Object.entries(data.data).map(([key, value]) =>
                                                                value.map(err =>
                                                                        dispatch(addNotification({
                                                                                style: 'danger',
                                                                                msg: `${key}: ${err}`
                                                                        }))
                                                                )
                                                        )
                                                return
                                        }

                                        dispatch(addNotification({
                                                style: 'success',
                                                msg: data.data
                                        }))
                                })
                }
        }

        const submitAndClose = () => {
                onSubmit()
                reset()
                history.goBack()
        }

        useEffect(() => {
                register('text')
                register('description')

        }, [])

        useEffect(() => {
                if (action === 'edit') {
                        axios.get(actionLink)
                                .then(({ data }) => {
                                        if (!data.success) {
                                                return dispatch(addNotification({
                                                        style: 'danger',
                                                        msg: 'Ha ocurrido un error'
                                                }))
                                        }

                                        register('text')
                                        register('description')

                                        setContent(data.data.content)
                                        setStatus(data.data.status)

                                        setValue('name', data.data.name)
                                        setValue('description', data.data.description)
                                        setValue('text', data.data.description)
                                        setDescription(data.data.description)
                                        setText(data.data.text)
                                })
                }
        }, [actionLink])


        return (
                <>
                        <section className="content">
                                <div className="row" style={{ padding: 16 }}>
                                        <div className="col-xs-12 col-md-12">
                                                <div className="form-group">
                                                        <label>Nombre</label>
                                                        <input type="text" name="name" className='form-control' ref={register({ required: true, maxLength: 50 })} />
                                                </div>
                                                <div className="form-group">
                                                        <label htmlFor="form-description">Descripción</label>
                                                        {(description) &&
                                                                <DescriptionInput
                                                                        defaultValue={description}
                                                                        name="description"
                                                                        onChange={setValue}
                                                                />}

                                                </div>
                                                <div className="form-group">
                                                        <label htmlFor="form-description">Texto</label>
                                                        {(text) &&
                                                                <DescriptionInput
                                                                        defaultValue={text}
                                                                        name="text"
                                                                        onChange={setValue}
                                                                />}
                                                </div>
                                                <div className="form-group">
                                                        <label htmlFor="form-status">Estatus</label>
                                                        <select name="form-status" className="form-control" onChange={(e) => setStatus(e.target.value)} value={status}>
                                                                <option value="A">Activo</option>
                                                                <option value="I">Inactivo</option>
                                                        </select>
                                                </div>
                                                <br />
                                                <div className="row">
                                                        <div className="col-xs-12 col-md-12">
                                                                <div className="panel-group" id="rows" >
                                                                        <div className="form-group">
                                                                                <div className="row">
                                                                                        <div className="col-xs-12 col-md-12">
                                                                                                <hr />
                                                                                                <div className="d-flex justify-content-end">
                                                                                                        <button className='btn btn-primary' onClick={() => showSectionModal()}>
                                                                                                                <i className="fa fa-plus" />
                                                                                                                Agregar sección
                                                                                                        </button>
                                                                                                </div>
                                                                                                <br />
                                                                                                <div className="panel-group" id="rows-job-competencies" >
                                                                                                        {
                                                                                                                content.length > 0
                                                                                                                &&
                                                                                                                content.map((section) => {

                                                                                                                        return (
                                                                                                                                <div className="panel panel-default" key={section.slug_section}>
                                                                                                                                        <div className="panel-heading">
                                                                                                                                                <h4 className="panel-title">
                                                                                                                                                        <a className="accordion-toggle" data-toggle="collapse" aria-expanded="true" data-parent={`panel-${section.slug_section}`} href={`#collapse-${section.slug_section}`}>
                                                                                                                                                                <span className={`section-name${section.slug_section}`}>
                                                                                                                                                                        {section.name}
                                                                                                                                                                </span>
                                                                                                                                                        </a>
                                                                                                                                                </h4>
                                                                                                                                        </div>
                                                                                                                                        <div id={`collapse-section${section.slug_section}`} className="panel-collapse in collapse show">
                                                                                                                                                <div className="panel-body">
                                                                                                                                                        <div className="table-responsive">
                                                                                                                                                                <table className="table table-bordered">
                                                                                                                                                                        <thead>
                                                                                                                                                                                <tr>
                                                                                                                                                                                        <th style={{ width: '10%' }}>Elemento</th>
                                                                                                                                                                                        <th style={{ width: '50%' }}>Texto</th>
                                                                                                                                                                                        <th style={{ width: '10%' }}>Tipo</th>
                                                                                                                                                                                        <th style={{ width: '20%' }}>Acciones</th>
                                                                                                                                                                                </tr>
                                                                                                                                                                        </thead>
                                                                                                                                                                        <tbody>
                                                                                                                                                                                <tr className="tr-section">
                                                                                                                                                                                        <td className="text-left">Sección</td>
                                                                                                                                                                                        <td className="text-left">{section.name}</td>
                                                                                                                                                                                        <td />
                                                                                                                                                                                        <td>
                                                                                                                                                                                                <button className="btn btn-default" onClick={() => showSectionModal(section, 'edit')}>
                                                                                                                                                                                                        <i className="fa fa-edit" />
                                                                                                                                                                                                        Editar Sección
                                                                                                                                                                                                </button>
                                                                                                                                                                                                <button className="btn btn-default" onClick={() => {
                                                                                                                                                                                                        setSectionSelected(section)
                                                                                                                                                                                                        setDeleteType('section')
                                                                                                                                                                                                        setShowDeleteModal(true)
                                                                                                                                                                                                }}>
                                                                                                                                                                                                        <i className="fa fa-ban" />
                                                                                                                                                                                                        Borrar Sección
                                                                                                                                                                                                </button>
                                                                                                                                                                                                <button className="btn btn-default" onClick={() => {
                                                                                                                                                                                                        setSectionSelected(section)
                                                                                                                                                                                                        showQuestionModal()
                                                                                                                                                                                                }}>
                                                                                                                                                                                                        <i className="fa fa-plus" />
                                                                                                                                                                                                        Agregar  Pregunta
                                                                                                                                                                                                </button>
                                                                                                                                                                                        </td>
                                                                                                                                                                                </tr>
                                                                                                                                                                                {
                                                                                                                                                                                        section.questions.map((question) => (
                                                                                                                                                                                                <>
                                                                                                                                                                                                        <tr key={question.slug_question} className="tr-question">
                                                                                                                                                                                                                <td className="text-left">Pregunta</td>
                                                                                                                                                                                                                <td className="text-left">
                                                                                                                                                                                                                        {parse(question.text)}
                                                                                                                                                                                                                </td>
                                                                                                                                                                                                                <td className="text-capitalize">
                                                                                                                                                                                                                        {sectionTypeOptions[question.type]}
                                                                                                                                                                                                                </td>
                                                                                                                                                                                                                <td>
                                                                                                                                                                                                                        <button className="btn btn-default" onClick={() => {
                                                                                                                                                                                                                                setSectionSelected(section)
                                                                                                                                                                                                                                showQuestionModal(question, 'edit')
                                                                                                                                                                                                                        }}>
                                                                                                                                                                                                                                <i className="fa fa-edit" /> Editar Pregunta
                                                                                                                                                                                                                        </button>
                                                                                                                                                                                                                        <button className="btn btn-default" onClick={() => {
                                                                                                                                                                                                                                setSectionSelected(section)
                                                                                                                                                                                                                                setQuestionSelected(question)
                                                                                                                                                                                                                                setDeleteType('question')
                                                                                                                                                                                                                                setShowDeleteModal(true)
                                                                                                                                                                                                                        }}>
                                                                                                                                                                                                                                <i className="fa fa-ban" /> Borrar Pregunta
                                                                                                                                                                                                                        </button>
                                                                                                                                                                                                                        {
                                                                                                                                                                                                                                question.type !== 'open'
                                                                                                                                                                                                                                &&
                                                                                                                                                                                                                                <button className="btn btn-default" onClick={() => {
                                                                                                                                                                                                                                        setSectionSelected(section)
                                                                                                                                                                                                                                        setQuestionSelected(question)
                                                                                                                                                                                                                                        showOptionModal()
                                                                                                                                                                                                                                }}>
                                                                                                                                                                                                                                        <i className="fa fa-plus" /> Agregar opción
                                                                                                                                                                                                                                </button>
                                                                                                                                                                                                                        }
                                                                                                                                                                                                                </td>
                                                                                                                                                                                                        </tr>
                                                                                                                                                                                                        {
                                                                                                                                                                                                                question.options.map(option => (
                                                                                                                                                                                                                        <tr key={option.slug_question} className="tr-option">
                                                                                                                                                                                                                                <td className="text-left">Opción</td>
                                                                                                                                                                                                                                <td className="text-left">
                                                                                                                                                                                                                                        {parse(option.text)}
                                                                                                                                                                                                                                </td>
                                                                                                                                                                                                                                <td />
                                                                                                                                                                                                                                <td>
                                                                                                                                                                                                                                        <button className="btn btn-default" onClick={() => {
                                                                                                                                                                                                                                                setSectionSelected(section)
                                                                                                                                                                                                                                                setQuestionSelected(question)
                                                                                                                                                                                                                                                showOptionModal(option, 'edit')
                                                                                                                                                                                                                                        }}>
                                                                                                                                                                                                                                                <i className="fa fa-edit" /> Editar opción
                                                                                                                                                                                                                                        </button>
                                                                                                                                                                                                                                        <button className="btn btn-default" onClick={() => {
                                                                                                                                                                                                                                                setOptionSelected(option)
                                                                                                                                                                                                                                                setSectionSelected(section)
                                                                                                                                                                                                                                                setQuestionSelected(question)
                                                                                                                                                                                                                                                setDeleteType('option')
                                                                                                                                                                                                                                                setShowDeleteModal(true)
                                                                                                                                                                                                                                        }}>
                                                                                                                                                                                                                                                <i className="fa fa-ban" /> Borrar opción
                                                                                                                                                                                                                                        </button>
                                                                                                                                                                                                                                </td>
                                                                                                                                                                                                                        </tr>
                                                                                                                                                                                                                ))
                                                                                                                                                                                                        }
                                                                                                                                                                                                </>
                                                                                                                                                                                        ))
                                                                                                                                                                                }

                                                                                                                                                                        </tbody>
                                                                                                                                                                </table>
                                                                                                                                                        </div>
                                                                                                                                                </div>
                                                                                                                                        </div>
                                                                                                                                </div>
                                                                                                                        )
                                                                                                                })
                                                                                                        }
                                                                                                </div>
                                                                                        </div>
                                                                                </div>
                                                                        </div>
                                                                </div>
                                                        </div>
                                                </div>
                                                <div className="d-flex" style={{ gap: '5px' }}>
                                                        {(action === 'edit') ? <button type="button" className="btn btn-info" onClick={onSubmit}>Guardar & Continuar</button> : <></>}
                                                        <button type="button" className="btn btn-primary" onClick={submitAndClose}>Guardar & Cerrar</button>
                                                        <button type="button" className="btn btn-secondary" onClick={() => history.goBack()}>Cancelar</button>
                                                </div>
                                        </div>
                                </div >
                        </section >
                        <SectionModal
                                show={isShowSection}
                                sectionType={sectionType}
                                section={sectionSelected}
                                closeModal={closeSectionModal}
                                onSubmit={sectionType === 'add' ? addSection : editSection}
                        />
                        <QuestionModal
                                show={isShowQuestion}
                                questionType={questionType}
                                question={questionSelected}
                                closeModal={closeQuestionModal}
                                onSubmit={questionType === 'add' ? addQuestion : editQuestion}
                        />
                        <OptionModal
                                show={isShowOption}
                                optionType={optionType}
                                option={optionSelected}
                                closeModal={closeOptionModal}
                                onSubmit={optionType === 'add' ? addOption : editOption}
                        />
                        <DeleteModal
                                isOpen={showDeleteModal}
                                closeModal={() => setShowDeleteModal(false)}
                                onComplete={() => deleteHandler(deleteType, deleteSlugsOptions[deleteType])}
                                message="Registro eliminado"
                        />
                </>
        )
}

export default FormView