Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

Rev 7186 | | Comparar con el anterior | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
7156 stevensc 1
import React, { useEffect, useRef, useState } from 'react'
2
import { useDispatch, useSelector } from 'react-redux'
3
import { Col, Container, Row } from 'react-bootstrap'
4
import { axios, debounce, jsonToParams } from '../../utils'
5
import { addNotification } from '../../redux/notification/notification.actions'
6
import styled from 'styled-components'
7
 
8
import SearchInput from '../../components/UI/SearchInput'
9
import EmptySection from '../../components/UI/EmptySection'
10
import WidgetLayout from '../../components/widgets/WidgetLayout'
11
import PaginationComponent from '../../components/UI/PaginationComponent'
12
 
13
import ConfirmModal from '../../components/modals/ConfirmModal'
7160 stevensc 14
import QuestionCard from '../../components/my-coach/QuestionCard'
7186 stevensc 15
import QuestionModal from '../../components/my-coach/QuestionModal'
7156 stevensc 16
 
17
const CoachCategories = styled(WidgetLayout)`
18
  padding: 1rem;
19
  ul {
20
    display: flex;
21
    flex-direction: column;
22
    gap: 1rem;
23
    li,
24
    label {
25
      cursor: pointer;
26
    }
27
    .selected label {
28
      font-weight: 600;
29
    }
30
  }
31
`
32
 
7157 stevensc 33
const QuestionsGrid = styled.div`
7156 stevensc 34
  display: grid;
7165 stevensc 35
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
7156 stevensc 36
  gap: 1rem;
37
`
38
 
39
const KnowledgeSearch = styled(SearchInput)`
40
  background-color: var(--bg-color);
41
`
42
 
43
const MyCoachPage = () => {
7157 stevensc 44
  const [questions, setQuestions] = useState([])
45
  const [questionsCategories, setQuestionsCategories] = useState([])
7156 stevensc 46
  const [search, setSearch] = useState('')
47
  const [category, setCategory] = useState('')
48
  const [currentPage, setCurrentPage] = useState(1)
49
  const [totalPages, setTotalPages] = useState(1)
50
  const [modalShow, setModalShow] = useState(null)
7158 stevensc 51
  const addUrl = useRef('/my-coach/questions/add')
7156 stevensc 52
  const actionUrl = useRef('')
53
  const labels = useSelector(({ intl }) => intl.labels)
54
  const dispatch = useDispatch()
55
 
7157 stevensc 56
  const getCategories = () => {
57
    axios
58
      .get('/my-coach', {
59
        headers: {
60
          'Content-Type': 'application/json',
61
        },
62
      })
63
      .then((response) => {
64
        const { data, success } = response.data
65
 
66
        if (!success) {
67
          const errorMessage =
7201 stevensc 68
            typeof data === 'string'
69
              ? data
70
              : 'Error interno. Por favor, inténtelo de nuevo más tarde.'
7157 stevensc 71
 
72
          dispatch(addNotification({ style: 'danger', msg: errorMessage }))
73
          return
74
        }
75
 
7158 stevensc 76
        const categories = Object.entries(data.categories).map((values) => ({
77
          name: values[1],
78
          uuid: values[0],
79
        }))
80
 
81
        setQuestionsCategories(categories)
7157 stevensc 82
      })
83
      .catch((error) => {
84
        dispatch(
85
          addNotification({
86
            style: 'danger',
7201 stevensc 87
            msg: 'Error interno. Por favor, inténtelo de nuevo más tarde.',
7157 stevensc 88
          })
89
        )
90
        throw new Error(error)
91
      })
92
  }
93
 
94
  const getQuestions = (search = '', page = 1, category_id = '') => {
7156 stevensc 95
    const urlParams = { search, page, category_id }
96
    axios
7158 stevensc 97
      .get(`/my-coach/questions?${jsonToParams(urlParams)}`, {
7156 stevensc 98
        headers: {
99
          'Content-Type': 'application/json',
100
        },
101
      })
102
      .then((response) => {
103
        const { data, success } = response.data
104
 
105
        if (!success) {
106
          const errorMessage =
7201 stevensc 107
            typeof data === 'string'
108
              ? data
109
              : 'Error interno. Por favor, inténtelo de nuevo más tarde.'
7156 stevensc 110
 
111
          dispatch(addNotification({ style: 'danger', msg: errorMessage }))
112
          return
113
        }
114
 
7158 stevensc 115
        setQuestions(data.items)
116
        setCurrentPage(data.page)
117
        setTotalPages(data.total_pages)
7156 stevensc 118
      })
119
      .catch((error) => {
120
        dispatch(
121
          addNotification({
122
            style: 'danger',
7201 stevensc 123
            msg: 'Error interno. Por favor, inténtelo de nuevo más tarde.',
7156 stevensc 124
          })
125
        )
126
        throw new Error(error)
127
      })
128
  }
129
 
130
  const confirmDelete = () => {
131
    axios
132
      .post(actionUrl.current)
133
      .then((response) => {
134
        const { data, success } = response.data
135
 
136
        if (!success) {
137
          const errorMessage =
138
            typeof data === 'string'
139
              ? data
140
              : 'Ha ocurrido un error, por favor intente más tarde.'
141
 
142
          dispatch(addNotification({ style: 'danger', msg: errorMessage }))
143
          return
144
        }
145
 
146
        dispatch(addNotification({ style: 'success', msg: data }))
7157 stevensc 147
        getQuestions(search, currentPage, category)
7156 stevensc 148
        closeModal()
149
      })
150
      .catch((error) => {
151
        dispatch(
152
          addNotification({
153
            style: 'danger',
154
            msg: 'Ha ocurrido un error, por favor intente más tarde.',
155
          })
156
        )
157
        throw new Error(error)
158
      })
159
  }
160
 
7157 stevensc 161
  const addQuestion = (url) => {
7156 stevensc 162
    actionUrl.current = url
163
    setModalShow('add')
164
  }
165
 
7157 stevensc 166
  const editQuestion = (url) => {
7156 stevensc 167
    actionUrl.current = url
168
    setModalShow('edit')
169
  }
170
 
7157 stevensc 171
  const deleteQuestion = (url) => {
7156 stevensc 172
    actionUrl.current = url
173
    setModalShow('delete')
174
  }
175
 
176
  const closeModal = () => {
177
    actionUrl.current = ''
178
    setModalShow(null)
179
  }
180
 
181
  const handleInputChange = debounce((e) => setSearch(e.target.value), 500)
182
 
183
  useEffect(() => {
7157 stevensc 184
    getCategories()
185
  }, [])
186
 
187
  useEffect(() => {
188
    getQuestions(search, currentPage, category)
7156 stevensc 189
  }, [search, currentPage, category])
190
 
191
  return (
192
    <>
193
      <Container as="section" className="companies-info">
194
        <div className="company-title">
7186 stevensc 195
          <h1 className="title mx-auto">{labels.my_coach}</h1>
7158 stevensc 196
          <h2
197
            className="title cursor-pointer"
198
            onClick={() => addQuestion(addUrl.current)}
199
          >
7186 stevensc 200
            {labels.my_coach_question_add}
7158 stevensc 201
          </h2>
7156 stevensc 202
        </div>
203
 
204
        <Row className="gap-3">
205
          <Col md="3">
206
            <CoachCategories>
207
              <ul>
208
                <li className={!category && 'selected'}>
209
                  <input
210
                    type="radio"
211
                    id="category-all"
212
                    value=""
213
                    name="category"
214
                    onChange={(e) => setCategory(e.target.value)}
215
                    hidden
216
                  />
217
                  <label htmlFor="category-all">
218
                    {labels.knowledge_area_category_all}
219
                  </label>
220
                </li>
7157 stevensc 221
                {questionsCategories.map(({ uuid, name }) => (
7156 stevensc 222
                  <li className={category === uuid && 'selected'} key={uuid}>
223
                    <input
224
                      type="radio"
225
                      id={`category-${name}`}
226
                      name="category"
227
                      value={uuid}
228
                      onChange={(e) => setCategory(e.target.value)}
229
                      hidden
230
                    />
231
                    <label htmlFor={`category-${name}`}>{name}</label>
232
                  </li>
233
                ))}
234
              </ul>
235
            </CoachCategories>
236
          </Col>
237
 
7165 stevensc 238
          <Col className="px-md-0">
7156 stevensc 239
            <KnowledgeSearch
240
              onChange={handleInputChange}
241
              placeholder={labels.search}
242
            />
7157 stevensc 243
            <QuestionsGrid className="mt-3">
244
              {questions.length ? (
7160 stevensc 245
                questions.map((question) => (
246
                  <QuestionCard
247
                    key={question.uuid}
7157 stevensc 248
                    onEdit={editQuestion}
249
                    onDelete={deleteQuestion}
7164 stevensc 250
                    {...question}
7156 stevensc 251
                  />
252
                ))
253
              ) : (
254
                <EmptySection
255
                  message={labels.error_no_record_matched_your_query}
256
                />
257
              )}
7157 stevensc 258
            </QuestionsGrid>
7156 stevensc 259
            <PaginationComponent
260
              onChangePage={(newPage) => setCurrentPage(newPage)}
261
              currentActivePage={currentPage}
262
              pages={totalPages}
263
              isRow
264
            />
265
          </Col>
266
        </Row>
267
      </Container>
7186 stevensc 268
      <QuestionModal
269
        show={['add', 'edit'].includes(modalShow)}
270
        onClose={closeModal}
271
        onComplete={getQuestions}
272
        url={actionUrl.current}
273
        isEdit={modalShow === 'edit'}
274
      />
7156 stevensc 275
      <ConfirmModal
276
        show={modalShow === 'delete'}
277
        onClose={closeModal}
278
        onAccept={confirmDelete}
279
      />
280
    </>
281
  )
282
}
283
 
284
export default MyCoachPage