COmponente

mail@pastecode.io avatar
unknown
javascript
a month ago
25 kB
1
Indexable
Never
import { setSubcenter } from 'redux-store/reducers/cadSession/actions';
import React, { memo, useCallback, useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useQuery } from 'react-query';
import { useDispatch, useSelector } from 'react-redux';
import {
  Avatar,
  Button,
  Col,
  Collapse,
  Form,
  Layout,
  Row,
  Select,
  Space,
  Spin,
  Switch,
  Tag,
  Tooltip,
  Typography
} from 'antd';
import { LeftOutlined, MenuOutlined, RightOutlined, SoundFilled, SoundOutlined } from '@ant-design/icons';
import { PROFILE_SUBMODULES } from 'config/profile-permissions';
import { REACT_QUERY_KEYS } from 'config/react-query-keys';
import emergenciesCatalogues from 'api/emergenciesCatalogues';
import { advanceFilterOption } from 'utils';
import { AUTHORITIES, DISPATCH_TYPE_VIEW, EMERGENCIES_STATUS } from 'utils/constants';
import { useSdcApi } from 'hooks';
import { useAccess } from 'hooks/useAccess';
import DelayedSearcher from 'components/DelayedSearcher';
import EmptyContentSelect from 'components/EmptyContentSelect';
import { GridIcon, ListIcon, MapIcon, TriangleWarningIcon } from 'components/icons';
import { DEFAULT_FILTER_PARAMS } from '../constants';
import './index.scss';

const { Header } = Layout;
const { Text } = Typography;

const assignedStatusOptionsValue = {
  ASSIGNED: 'assigned',
  UNASSIGNED: 'unassigned'
};

const NoCossableTag = (props) => {
  const { label } = props;
  return (
    <Tag {...props} closable={false}>
      {label}
    </Tag>
  );
};

/**
 *
 * @param {{
 * onChangeParams: (params:import('types').GetEmergenciesByFiltersParams) => void,
 * onChangeTypeView: (value:number) => void,
 * typeView: number,
 * loadingEmergencies:boolean,
 * muteEmergencySoundAlert:boolean,
 * showMuteEmergencySoundAlertButton:boolean,
 * onClickMuteEmergencySoundAlert: () => void,
 * onClickHideSidebarButton: () => void,
 * emergencyFilterParams: import('types').GetEmergenciesByFiltersParams
 * showAssignationStatusFilter?: boolean,
 * showEmergencyStatusButtonsFilter?: boolean,
 * showMunicipalityFilter?: boolean,
 * showDispatchedByMeFilter?: boolean,
 * showDispatchingStatusFilter?: boolean,
 * showOpenEmergenciesFilter?: boolean,
 * showCreateIncidentByMeFilter?: boolean
 * showHideSidebarButton?: boolean
 * showSidebar?: boolean
 * }} param0
 * @returns
 */
const EmergenciesHeader = ({
  onChangeTypeView,
  onClickMuteEmergencySoundAlert,
  onChangeParams,
  onClickHideSidebarButton,
  muteEmergencySoundAlert,
  showMuteEmergencySoundAlertButton = true,
  typeView,
  loadingEmergencies,
  emergencyFilterParams,
  showAssignationStatusFilter,
  showEmergencyStatusButtonsFilter,
  showMunicipalityFilter,
  showDispatchedByMeFilter,
  showDispatchingStatusFilter,
  showOpenEmergenciesFilter,
  showCreateIncidentByMeFilter,
  showHideSidebarButton,
  showSidebar
}) => {
  const {
    microservices: {
      admin: {
        priority: { getAll: getAllPriorities }
      },
      stateSuperviser: {
        admin: { getSubcenter }
      },
      dispatch: {
        incidentRelevant: { getIncidentRelevantCount }
      }
    }
  } = useSdcApi();
  const dispatch = useDispatch();
  const { t } = useTranslation('translations');
  const [form] = Form.useForm();
  const { timeOpenEmergencies, stateIdDefault } = useSelector((state) => state.systemParamas);
  const [searchText, setSearchText] = useState(null);
  const [activeCollapsiblePanel, setActiveCollapsiblePanel] = useState();
  const [checkAssignedUnit, setCheckAssignedUnit] = useState(false);
  const { userId, assignedCorporation: profileCorporations, subcenter } = useSelector((state) => state.CadSession);
  const { validateAuthority, hasAccess } = useAccess();

  const showFilterByTime = useMemo(() => hasAccess(PROFILE_SUBMODULES.SDCW_SHOW_FILTER_BY_TIME), [hasAccess]);

  const corporationOptions = useMemo(
    () =>
      profileCorporations?.map((pc) => ({
        label: pc?.name,
        value: pc?.id
      })),
    [profileCorporations]
  );

  /**
   * filteredOperativeGroups devuelve un listado de grupos operativos que estén relacionados a alguna de las corporaciones que recibe por props
   */
  const filteredOperativeGroups = useCallback(
    (corporationIds = []) =>
      profileCorporations?.reduce((result, corporation) => {
        if (corporationIds.includes(corporation.id)) {
          result.push(...corporation.operativeGroups.map(({ name, id }) => ({ label: name, value: id })));
        }
        return result;
      }, []) ?? [],
    [profileCorporations]
  );

  const operativeGroupOptions = useMemo(() => {
    return filteredOperativeGroups(emergencyFilterParams?.corporationIds);
  }, [filteredOperativeGroups, emergencyFilterParams?.corporationIds]);

  /* QUERIES */
  const { data: priorityOptions, isLoading: isLoadingPriorities } = useQuery(
    [getAllPriorities.queryKeyFunction()],
    () => getAllPriorities.endpoint(),
    {
      select: (data) =>
        data?.data?.result?.map((p) => ({
          label: p?.name,
          value: p?.id
        }))
    }
  );

  const { data: subcenters, isLoading: isLoadingSubcenters } = useQuery(
    [getSubcenter.queryKeyFunction()],
    () => getSubcenter.endpoint(),
    {
      enabled: validateAuthority(AUTHORITIES.STATE_SUPERVISOR),
      select: getSubcenter.selectQueryFunction,
      onSuccess: (data) => {
        if (!subcenter?.dwKey && data?.length > 0) {
          selectSubcenterFromDwKey(data?.[0]?.subCenter, data);
        }
      }
    }
  );

  const { data: dataMunicipalities = [], isLoading: isLoadingMunicipalitys } = useQuery(
    [REACT_QUERY_KEYS.admin.municipality.getByStateId(`id-municipality-${stateIdDefault}`)],
    () => emergenciesCatalogues.municipalitiesByState(stateIdDefault) /** CAMBIAR A dispatchDefaultStateId */,
    {
      select: (data) => data?.data?.result
    }
  );

  const { data: incidentRelevantCount } = useQuery(
    [getIncidentRelevantCount.queryKeyFunction(userId), userId],
    () => getIncidentRelevantCount.endpoint({ 'user-id': userId }),
    {
      select: (data) => {
        const { count } = getIncidentRelevantCount.selectQueryFunction(data) || { count: 0 };
        return count;
      }
    }
  );

  const subcenterOptions = useMemo(
    () =>
      subcenters?.map((p) => ({
        label: p?.ambiente,
        value: p?.subCenter
      })),
    [subcenters]
  );

  const munipalityOptions = useMemo(
    () => dataMunicipalities?.map((item) => ({ label: item?.name, value: item?.id })),
    [dataMunicipalities]
  );

  /* EFFECTS */
  const triangleWarningIconColor = useMemo(() => {
    if (emergencyFilterParams?.filterByRelevantIncident) return 'var(--primary-color-main)';
    else if (incidentRelevantCount > 0) return 'var(--error-color)';
    return '#C6C6C6';
  }, [emergencyFilterParams?.filterByRelevantIncident, incidentRelevantCount]);

  /* EFFECTS */
  // Set initial state
  useEffect(() => {
    const initialParams = DEFAULT_FILTER_PARAMS;
    if (showOpenEmergenciesFilter && timeOpenEmergencies) initialParams.maxHours = timeOpenEmergencies;
    if (showDispatchingStatusFilter) initialParams.statusEmergency = EMERGENCIES_STATUS.DISPATCHING;
    if (!showDispatchedByMeFilter) delete initialParams.assignedUnit;
    onChangeParams(initialParams);
  }, [showOpenEmergenciesFilter, dispatch, timeOpenEmergencies, showDispatchingStatusFilter]);

  const changeViewTypeHandler = (v) => {
    onChangeTypeView && onChangeTypeView(v);
  };

  function changeSearchHandler(event) {
    // setSearchText(!e.target.value ? undefined : e.target.value);
    setSearchText(event?.target?.value);
  }

  const clickAdvanceFilterButtonHandler = () => {
    setActiveCollapsiblePanel((v) => (v ? null : '1'));
  };

  function delayedSearchHandler() {
    if (searchText !== null) {
      onChangeParams({
        page: 0,
        query: searchText?.trim()
      });
    }
  }

  function selectSubcenterFromDwKey(dwKey, subcenters) {
    const subcenterSelected = subcenters?.find((sc) => sc?.subCenter === dwKey);
    if (subcenterSelected) {
      const { subCenter: dwKey, ambiente: name, ...rest } = subcenterSelected;
      const newSubcenter = {
        ...rest,
        id: undefined,
        dwKey,
        name
      };
      dispatch(setSubcenter(newSubcenter));
    }
  }

  function onChangeSubcenter(value) {
    selectSubcenterFromDwKey(value, subcenters);
  }

  const changeFormFilterValuesHandler = () => {
    const values = form?.getFieldsValue();
    const createdBy =
      showCreateIncidentByMeFilter && values?.createdBy ? userId : values.createdByMe ? userId : undefined;
    const statusEmergency = showEmergencyStatusButtonsFilter && values?.incompleteEmergency ? 'OPEN' : undefined;

    if (values?.corporationOperativeIds)
      /** Esta linea de código actualiza los grupos operativos seleccionado cuando se quita una corporación */
      values.corporationOperativeIds = values?.corporationOperativeIds?.reduce((result, ogId) => {
        if (filteredOperativeGroups(values?.corporationIds).some(({ value }) => ogId === value)) result.push(ogId);
        return result;
      }, []);
    form?.setFieldValue('corporationOperativeIds', values.corporationOperativeIds);

    const updatedParams = {
      ...values,
      page: 0,
      createdBy,
      statusEmergency,
      status: 'OPEN'
    };

    // Esta validación aplica sólo si `!allowAdvanceFilter` ya que el input de `incompleteEmergency` sólo se muestra en dicha condición
    if (!showEmergencyStatusButtonsFilter) {
      updatedParams.statusEmergency = values?.incompleteEmergency ? 'OPEN' : undefined;
    }

    delete values.createdByMe;
    delete values.incompleteEmergency;
    onChangeParams(updatedParams);
  };

  const assignedStatusOptions = useMemo(
    () => [
      {
        label: t('despacho.assigned_folio'),
        value: assignedStatusOptionsValue?.ASSIGNED
      },
      {
        label: t('despacho.unassigned_folio'),
        value: assignedStatusOptionsValue?.UNASSIGNED
      }
    ],
    [t]
  );

  function changeStatusEmergency(corporationStatus, statusEmergency) {
    onChangeParams({
      status: corporationStatus,
      statusEmergency
    });
  }

  const onSelectRelevantView = () => {
    if (loadingEmergencies) return;
    onChangeParams({
      filterByRelevantIncident: !emergencyFilterParams.filterByRelevantIncident,
      page: 0
    });
  };

  const clickDispatchedTabButtonHandler = () => changeStatusEmergency(EMERGENCIES_STATUS.OPEN, undefined);

  const clickOpenedTabButtonHandler = () => changeStatusEmergency(undefined, EMERGENCIES_STATUS.OPEN);

  const clickClosedTabButtonHandler = () => changeStatusEmergency(undefined, EMERGENCIES_STATUS.CLOSED);

  const statusButtonsType = useMemo(
    () => ({
      dispatched: !emergencyFilterParams.statusEmergency ? 'primary' : 'text',
      opened: emergencyFilterParams.statusEmergency === EMERGENCIES_STATUS.OPEN ? 'primary' : 'text',
      closed: emergencyFilterParams.statusEmergency === EMERGENCIES_STATUS.CLOSED ? 'primary' : 'text'
    }),
    [emergencyFilterParams.statusEmergency]
  );

  const onHandlerFilterDispatch = (e) => {
    setCheckAssignedUnit(e);
  };

  return (
    <Header className="dashboard-dispatcher-emergencies-header ">
      <Row justify="space-between" align="middle" wrap={false} className="options-view-wrapper" gutter={10}>
        <Col span={3}>
          <Row justify="start">
            <Space className="title-header-wrapper">
              <Typography.Text>{t('map_operador.Incident')}</Typography.Text>
              {loadingEmergencies && <Spin size="small" />}
            </Space>
          </Row>
        </Col>
        <Col flex="auto">
          {showEmergencyStatusButtonsFilter && (
            <Space size="middle">
              <Button type={statusButtonsType?.dispatched} onClick={clickDispatchedTabButtonHandler}>
                {t('despacho.dispatched')}
              </Button>
              <Button type={statusButtonsType?.opened} onClick={clickOpenedTabButtonHandler}>
                {t('despacho.opened')}
              </Button>
              <Button type={statusButtonsType?.closed} onClick={clickClosedTabButtonHandler}>
                {t('despacho.closed')}
              </Button>
            </Space>
          )}
        </Col>
        <Col flex="250px">
          {validateAuthority(AUTHORITIES.STATE_SUPERVISOR) && (
            <Form.Item
              label={t('despacho.subcenter')}
              className="select-item"
              labelCol={{ span: 24 }}
              wrapperCol={{ className: 'advanced-filter-col-wrapper' }}
            >
              <Select
                allowClear={false}
                className="cadlite-ant-select"
                value={subcenter?.dwKey}
                loading={isLoadingSubcenters}
                options={subcenterOptions}
                filterOption={advanceFilterOption}
                onChange={onChangeSubcenter}
              />
            </Form.Item>
          )}
        </Col>
        <Col flex="auto">
          <Row justify="end" align="middle" wrap={false} gutter={8}>
            <Col
              className="relevant-emergencies-filter"
              style={{ cursor: 'pointer', paddingRight: '12px', borderRight: '1px solid #3E5378', marginRight: '12px' }}
            >
              <Tooltip title={t('Incidentes Relevantes')}>
                <TriangleWarningIcon
                  className="relevant-incident"
                  color={triangleWarningIconColor}
                  width={21}
                  height={21}
                  onClick={onSelectRelevantView}
                />
              </Tooltip>
            </Col>
            {showMuteEmergencySoundAlertButton && (
              <Col className="button-wrapper">
                <Button
                  type="text"
                  icon={
                    <Tooltip title={t('despacho.emergency_sound_alert')}>
                      {muteEmergencySoundAlert ? (
                        <SoundFilled style={{ color: '#3867FC', fontSize: '19px' }} />
                      ) : (
                        <SoundOutlined style={{ color: '#C6C6C6', fontSize: '19px' }} />
                      )}
                    </Tooltip>
                  }
                  onClick={onClickMuteEmergencySoundAlert}
                />
              </Col>
            )}
            <Col className="button-wrapper">
              <Button
                type="text"
                icon={<GridIcon status={typeView === DISPATCH_TYPE_VIEW.GRID ? 'true' : undefined} />}
                onClick={() => changeViewTypeHandler(DISPATCH_TYPE_VIEW.GRID)}
              />
            </Col>
            <Col className="button-wrapper">
              <Button
                type="text"
                icon={<ListIcon status={typeView === DISPATCH_TYPE_VIEW.LIST ? 'true' : undefined} />}
                onClick={() => changeViewTypeHandler(DISPATCH_TYPE_VIEW.LIST)}
              />
            </Col>
            <Col className="button-wrapper">
              <Button
                type="text"
                icon={<MapIcon status={typeView === DISPATCH_TYPE_VIEW.MAP ? 'true' : undefined} />}
                onClick={() => changeViewTypeHandler(DISPATCH_TYPE_VIEW.MAP)}
              />
            </Col>
            <Col style={{ display: 'flex' }}>
              <DelayedSearcher
                allowClear
                value={searchText}
                onChange={changeSearchHandler}
                delayedTime={1250}
                onDelayedChange={delayedSearchHandler}
                placeholder={t('searchAdvaced.input')}
                informationText={t('despacho.info_text')}
              />
            </Col>
            <Col>
              <Tooltip title={t('despacho.advanced_filter')} placement="bottom">
                <Button
                  className="filter-button"
                  type="primary"
                  shape="default"
                  icon={<MenuOutlined />}
                  onClick={clickAdvanceFilterButtonHandler}
                />
              </Tooltip>
            </Col>
            {showHideSidebarButton && (
              <Col>
                <Avatar
                  className="icon-button"
                  style={{ background: 'var(--primary-color-main)' }}
                  size={20}
                  icon={showSidebar ? <RightOutlined /> : <LeftOutlined />}
                  onClick={onClickHideSidebarButton}
                />
              </Col>
            )}
          </Row>
        </Col>
      </Row>
      <Collapse
        bordered={false}
        collapsible="disabled"
        className="collapse-filter-panel"
        activeKey={activeCollapsiblePanel}
        items={[
          {
            key: '1',
            children: (
              <Row align="middle" className="advanced-filter-row-wrapper" gutter={12} wrap={false}>
                <Col flex="100px">
                  <Text strong>{t('despacho.filter_by')}:</Text>
                </Col>
                <Col flex="auto">
                  <Form layout="inline" form={form} onFieldsChange={changeFormFilterValuesHandler}>
                    <Form.Item
                      name="priorityIds"
                      label={t('despacho.Prioridad')}
                      labelCol={{ span: 24 }}
                      className="select-item"
                      wrapperCol={{ className: 'advanced-filter-col-wrapper', span: 24 }}
                    >
                      <Select
                        className="cadlite-ant-select"
                        value={emergencyFilterParams?.priorityIds}
                        mode="multiple"
                        loading={isLoadingPriorities}
                        options={priorityOptions}
                        tagRender={NoCossableTag}
                        filterOption={advanceFilterOption}
                        notFoundContent={<EmptyContentSelect fullText={t('despacho.not_found_priority')} />}
                      />
                    </Form.Item>
                    <Form.Item
                      name="corporationIds"
                      label={t('despacho.Corporacion')}
                      className="select-item"
                      labelCol={{ span: 24 }}
                      wrapperCol={{ className: 'advanced-filter-col-wrapper' }}
                    >
                      <Select
                        className="cadlite-ant-select"
                        value={emergencyFilterParams?.corporationIds}
                        mode="multiple"
                        options={corporationOptions}
                        tagRender={NoCossableTag}
                        filterOption={advanceFilterOption}
                        notFoundContent={<EmptyContentSelect fullText={t('despacho.not_found_corporation')} />}
                      />
                    </Form.Item>
                    <Form.Item
                      name="corporationOperativeIds"
                      label={t('despacho.operative_groups')}
                      className="select-item"
                      labelCol={{ span: 24 }}
                      wrapperCol={{ className: 'advanced-filter-col-wrapper' }}
                    >
                      <Select
                        className="cadlite-ant-select"
                        value={emergencyFilterParams?.corporationOperativeIds}
                        mode="multiple"
                        options={operativeGroupOptions}
                        tagRender={NoCossableTag}
                        filterOption={advanceFilterOption}
                        notFoundContent={<EmptyContentSelect fullText={t('despacho.operative_group_search_msg')} />}
                      />
                    </Form.Item>
                    {showAssignationStatusFilter && (
                      <Form.Item
                        name="assignedStatus"
                        label={t('despacho.assigned_status')}
                        className="select-item"
                        labelCol={{ span: 24 }}
                        wrapperCol={{ className: 'advanced-filter-col-wrapper' }}
                      >
                        <Select
                          allowClear
                          className="cadlite-ant-select"
                          value={emergencyFilterParams?.corporationIds}
                          options={assignedStatusOptions}
                          filterOption={advanceFilterOption}
                        />
                      </Form.Item>
                    )}
                    {showMunicipalityFilter && (
                      <Form.Item
                        name="municipalityAlternativeIds"
                        label={t('despacho.municipality')}
                        className="select-item"
                        labelCol={{ span: 24 }}
                        wrapperCol={{ className: 'advanced-filter-col-wrapper' }}
                      >
                        <Select
                          allowClear
                          mode="multiple"
                          className="cadlite-ant-select"
                          loading={isLoadingMunicipalitys}
                          options={munipalityOptions}
                          filterOption={advanceFilterOption}
                        />
                      </Form.Item>
                    )}
                    {showCreateIncidentByMeFilter && (
                      <Form.Item
                        label={t('despacho.Creados_mi')}
                        labelCol={{ span: 24 }}
                        wrapperCol={{ className: 'advanced-filter-col-wrapper' }}
                        name="createdBy"
                      >
                        <Switch
                          checked={
                            (emergencyFilterParams?.createdBy && emergencyFilterParams?.createdBy === userId) || false
                          }
                        />
                      </Form.Item>
                    )}
                    {showDispatchedByMeFilter && (
                      <Form.Item
                        label={t('despacho.dispatched_by_me')}
                        labelCol={{ span: 24 }}
                        wrapperCol={{ className: 'advanced-filter-col-wrapper' }}
                        name="assignedUnit"
                      >
                        <Switch onClick={(e) => onHandlerFilterDispatch(e)} checked={checkAssignedUnit} />
                      </Form.Item>
                    )}
                    {!showEmergencyStatusButtonsFilter && (
                      <Form.Item
                        label={t('despacho.incomplete_folio')}
                        labelCol={{ span: 24 }}
                        wrapperCol={{ className: 'advanced-filter-col-wrapper' }}
                        name="incompleteEmergency"
                      >
                        <Switch
                          checked={
                            (emergencyFilterParams?.statusEmergency &&
                              emergencyFilterParams?.statusEmergency === 'OPEN') ||
                            false
                          }
                        />
                      </Form.Item>
                    )}
                    {!showFilterByTime && (
                      <Form.Item
                        label={t('despacho.filter_by_time')}
                        labelCol={{ span: 24 }}
                        wrapperCol={{ className: 'advanced-filter-col-wrapper' }}
                        name="moreQueries"
                      >
                        <Switch
                          checked={emergencyFilterParams?.moreQueries || false}
                          onChange={(checked) => {
                            const updatedParams = {
                              ...emergencyFilterParams,
                              moreQueries: checked ? true : undefined
                            };
                            onChangeParams(updatedParams);
                          }}
                        />
                      </Form.Item>
                    )}
                  </Form>
                </Col>
              </Row>
            )
          }
        ]}
      ></Collapse>
    </Header>
  );
};
export default memo(EmergenciesHeader);
Leave a Comment