UNPKG

design-comuni-plone-theme

Version:
270 lines (246 loc) 8.04 kB
import React, { useState, useReducer, useEffect, createRef } from 'react'; import { useIntl, defineMessages } from 'react-intl'; import { useDispatch, useSelector } from 'react-redux'; import { Container, Button, Spinner } from 'design-react-kit'; import moment from 'moment'; import cx from 'classnames'; import { getQueryStringResults } from '@plone/volto/actions'; import { flattenToAppURL } from '@plone/volto/helpers'; import CardWithImageTemplate from 'design-comuni-plone-theme/components/ItaliaTheme/Blocks/Listing/CardWithImageTemplate'; import { Pagination } from 'design-comuni-plone-theme/components/ItaliaTheme'; import { resetQuerystringResults } from 'design-comuni-plone-theme/actions'; import FiltersConfig from 'design-comuni-plone-theme/components/ItaliaTheme/Blocks/EventSearch/FiltersConfig'; const messages = defineMessages({ find: { id: 'find', defaultMessage: 'Cerca', }, insert_filter: { id: 'insert_filter', defaultMessage: 'Inserire un filtro dal menù laterale per visualizzare i relativi risultati', }, venues: { id: 'venues', defaultMessage: 'Luoghi', }, noResult: { id: 'noResult', defaultMessage: 'Nessun risultato trovato', }, }); const Body = ({ data, id, inEditMode, path, onChangeBlock }) => { const intl = useIntl(); const b_size = 6; moment.locale(intl.locale); const [currentPage, setCurrentPage] = useState(1); const subsite = useSelector((state) => state.subsite?.data); const dispatch = useDispatch(); const querystringResults = useSelector((state) => { return state.querystringsearch?.subrequests?.[id + '_events_search']; }); const items = useSelector((state) => { return ( state.querystringsearch?.subrequests?.[id + '_events_search']?.items ?? [] ); }); const loading = useSelector((state) => { return ( state.querystringsearch?.subrequests?.[id + '_events_search']?.loading || false ); }); const firstLoading = useSelector((state) => { return ( !state.querystringsearch?.subrequests?.[id + '_events_search']?.loading && !state.querystringsearch?.subrequests?.[id + '_events_search']?.loaded ); }); const resultsRef = createRef(); const doRequest = (page = currentPage) => { let query = [ { i: 'portal_type', o: 'plone.app.querystring.operation.selection.any', v: ['Event'], }, { i: 'rassegna', o: 'plone.app.querystring.operation.boolean.isFalse', v: '', }, ]; [filterOne, filterTwo, filterThree].forEach((f) => { if (f?.widget) { const value = f.widget.props.value; if (f.query) { f.query(value, query); } } }); if (data.location && data.location[0]) { query.push({ i: 'path', o: 'plone.app.querystring.operation.string.absolutePath', v: flattenToAppURL(data.location[0]['@id']), }); } dispatch( getQueryStringResults( subsite ? flattenToAppURL(subsite['@id']) : '', { query: query, metadata_fields: '_all', b_size: b_size, sort_order: 'ascending', sort_on: 'start', }, id + '_events_search', page, ), ); }; // Se cambia uno dei tre filtri resetto lo stato dei filtri useEffect(() => { dispatchFilter({ type: 'reset' }); if (data.show_default_results && firstLoading) { doRequest(); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [data]); const filtersReducer = (state = getInitialState(), action) => { let newState = { ...state, }; if (action.type === 'reset') { newState = { ...getInitialState(), }; dispatch(resetQuerystringResults(id + '_events_search')); } else { const f = newState[action.filter]; const defaultReducer = (value, state) => value; const reducer = f.reducer || defaultReducer; f.widget.props.value = reducer(action.value, state[action.filter]); } return newState; }; const filtersConfig = FiltersConfig(null); const getInitialState = () => { return { filterOne: filtersConfig[data?.filter_one], filterTwo: filtersConfig[data?.filter_two], filterThree: filtersConfig[data?.filter_three], }; }; const [{ filterOne, filterTwo, filterThree }, dispatchFilter] = useReducer( filtersReducer, getInitialState(), ); function handleQueryPaginationChange(e, { activePage }) { resultsRef.current.scrollIntoView({ behavior: 'smooth' }); const current = activePage?.children ?? 1; setCurrentPage(current); doRequest(current); } return filterOne || filterTwo || filterThree ? ( <Container> <div className={cx('rounded bg-' + (data.bg_color || 'primary'), { 'public-ui': inEditMode, })} > <form onSubmit={(event) => { event.preventDefault(); doRequest(1); }} > <div className="d-flex justify-content-center"> <div className="d-flex search-container align-items-center justify-content-center flex-wrap"> {filterOne && ( <> {React.createElement(filterOne.widget.component, { ...filterOne.widget?.props, blockID: id, id: 'filterOne', onChange: (filter, value) => { dispatchFilter({ filter: filter, value: value, }); }, })} </> )} {filterTwo && React.createElement(filterTwo.widget?.component, { ...filterTwo.widget?.props, blockID: id, id: 'filterTwo', onChange: (filter, value) => dispatchFilter({ filter: filter, value: value, }), })} {filterThree && React.createElement(filterThree.widget?.component, { ...filterThree.widget?.props, blockID: id, id: 'filterThree', onChange: (filter, value) => dispatchFilter({ filter: filter, value: value, }), })} <Button color={data.button_color || 'tertiary'} icon={false} tag="button" className="my-2 my-lg-1" type="submit" > {intl.formatMessage(messages.find)} </Button> </div> </div> </form> </div> {!loading ? ( items?.length > 0 ? ( <div className="mt-4" ref={resultsRef} aria-live="polite"> <div className="block listing"> <CardWithImageTemplate items={items} full_width={false} always_show_image={data.always_show_image} /> </div> {querystringResults.total > b_size && ( <Pagination activePage={currentPage} totalPages={Math.ceil(querystringResults.total / b_size)} onPageChange={handleQueryPaginationChange} /> )} </div> ) : querystringResults ? ( <> <div className="mt-4" aria-live="polite"> <p className="text-center"> {intl.formatMessage(messages.noResult)} </p> </div> </> ) : null ) : ( <div className="d-flex justify-content-center mt-3"> <Spinner active /> </div> )} </Container> ) : null; }; export default Body;