COmponente
unknown
javascript
a year ago
25 kB
9
Indexable
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);
Editor is loading...
Leave a Comment