Proyectos de Subversion LeadersLinked - SPA

Rev

Rev 2798 | Rev 2864 | Ir a la última revisión | Autoría | Comparar con el anterior | Ultima modificación | Ver Log |

import React, { useState, useEffect, useRef } from 'react'
import { axios, debounce } from '../../utils'
import { useDispatch, useSelector } from 'react-redux'
import { useNavigate, useLocation, useParams } from 'react-router-dom'
import { addNotification } from '../../redux/notification/notification.actions'
import { Search } from '@mui/icons-material'
import { Grid } from '@mui/material'

import Input from 'components/UI/Input'
import Spinner from 'components/UI/Spinner'
import SearchItem from 'components/search/SearchItem'
import EmptySection from 'components/UI/EmptySection'
import FiltersSidebar from 'components/search/FiltersSidebar'
import CategoryFilter from 'components/search/CategoryFilter'
import LocationFilter from 'components/search/LocationFilter'
import PaginationComponent from 'components/UI/PaginationComponent'
import LoaderContainer from 'components/UI/LoaderContainer'

const SearchPage = () => {
  const [entities, setEntities] = useState([])
  const [pages, setPages] = useState(1)
  const [loading, setLoading] = useState(true)
  const { search, pathname } = useLocation()
  const { category } = useParams()
  const addressRef = useRef({})
  const navigate = useNavigate()
  const labels = useSelector(({ intl }) => intl.labels)
  const dispatch = useDispatch()
  const params = new URLSearchParams(search)

  const onChangeKeyword = debounce((value = '') => {
    const params = new URLSearchParams(search)
    params.set('page', '1')
    params.set('keyword', value)
    navigate(`${pathname}?${params.toString()}`)
  }, 500)

  const onChangePage = (currentPage = 1) => {
    const params = new URLSearchParams(search)
    params.set('page', `${currentPage}`)
    navigate(`${pathname}?${params.toString()}`)
  }

  const onChangeCategory = (newCategory = 'user') => {
    const params = new URLSearchParams(search)
    params.set('page', '1')
    navigate(`/search/entity/${newCategory}?${params.toString()}`)
  }

  const onChangeAddress = (address = {}) => {
    const params = new URLSearchParams(search)
    params.set('page', '1')
    Object.entries(addressRef.current).forEach(([key]) => {
      if (!['page', 'keyword'].includes(key)) params.delete(key)
    })

    addressRef.current = address

    Object.entries(address).forEach(
      ([key, value]) => value && params.set(key, value)
    )

    navigate(`${pathname}?${params.toString()}`)
  }

  useEffect(() => {
    const searchEntities = async () => {
      setLoading(true)
      try {
        const { data: responseData } = await axios.get(`${pathname}${search}`)
        const { success, data } = responseData

        if (!success) {
          throw new Error(data)
        }

        setEntities(data.current.items)
        setPages(data.total.pages)
      } catch (error) {
        dispatch(addNotification({ style: 'danger', msg: error.message }))
      } finally {
        setLoading(false)
      }
    }

    searchEntities()
  }, [search, pathname])

  return (
    <>
      <Input
        icon={Search}
        onChange={(e) => onChangeKeyword(e.target.value)}
        placeholder={labels.search}
        defaultValue={params.get('keyword')}
      />

      <Grid container spacing={2} mt={2}>
        <Grid item xs={12} md={4} display='flex' direction='column' gap={2}>
          <FiltersSidebar>
            <CategoryFilter
              currentCategory={category}
              onChange={onChangeCategory}
            />

            <LocationFilter onChange={onChangeAddress} />
          </FiltersSidebar>
        </Grid>

        <Grid item xs={12} md={8} display='flex' direction='column' gap={2}>
          {loading ? (
            <LoaderContainer>
              <Spinner />
            </LoaderContainer>
          ) : (
            <>
              <EntitiesList entities={entities} />
              <PaginationComponent
                pages={pages}
                onChangePage={onChangePage}
                currentActivePage={+params.get('page')}
                isRow
              />
            </>
          )}
        </Grid>
      </Grid>
    </>
  )
}

const EntitiesList = ({ entities = [] }) => {
  if (!entities.length) {
    return <EmptySection message='No hay resultados' />
  }

  return (
    <>
      {entities.map((entity) => (
        <SearchItem key={entity.id} entity={entity} />
      ))}
    </>
  )
}

export default SearchPage