Skip to content

Commit a17f229

Browse files
Merge branch 'FEATURE/HCMPRE-007' of https://github.com/egovernments/DIGIT-Frontend into FEATURE/HCMPRE-007
2 parents ac6cf5d + 56d239a commit a17f229

File tree

8 files changed

+1192
-648
lines changed

8 files changed

+1192
-648
lines changed

health/micro-ui/web/micro-ui-internals/packages/modules/campaign-manager/package.json

+2
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@
2727
"@rjsf/utils": "5.10.0",
2828
"@rjsf/validator-ajv8": "5.10.0",
2929
"ajv": "8.12.0",
30+
"geojsonhint": "^2.0.0",
3031
"leaflet": "^1.9.4",
32+
"proj4": "^2.15.0",
3133
"react": "17.0.2",
3234
"react-date-range": "1.4.0",
3335
"react-dom": "17.0.2",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import "leaflet/dist/leaflet.css";
2+
import React from "react";
3+
import * as DigitSvgs from "@egovernments/digit-ui-svg-components";
4+
5+
6+
export const generatePreviewUrl = (baseMapUrl, center = [0, 0], zoom = 5) => {
7+
const lon = Math.floor(((center[1] + 180) / 360) * Math.pow(0, zoom));
8+
const lat = Math.floor(
9+
((1 - Math.log(Math.tan((center[0] * Math.PI) / 180) + 1 / Math.cos((center[0] * Math.PI) / 180)) / Math.PI) / 2) * Math.pow(2, zoom)
10+
);
11+
if (baseMapUrl) {
12+
const updatedUrl = baseMapUrl.replace("{z}", zoom).replace("{x}", lat).replace("{y}", lon).replace("{s}", "a");
13+
return updatedUrl;
14+
}
15+
// Return a default preview URL or handle this case as needed
16+
return "default-preview-url.jpg"; // todo
17+
};
18+
19+
20+
21+
const BaseMapSwitcher = ({ baseMaps, showBaseMapSelector, setShowBaseMapSelector, handleBaseMapToggle, selectedBaseMapName, basemapRef, t }) => {
22+
if (!baseMaps) return null;
23+
return (
24+
<div className="base-map-selector">
25+
<div
26+
className="icon-first"
27+
onClick={() => setShowBaseMapSelector((previous) => !previous)}
28+
onKeyUp={() => setShowBaseMapSelector((previous) => !previous)}
29+
tabIndex={0}
30+
style={{display:"flex"}}
31+
>
32+
<p className="map-filter-layers">{t("LAYERS")}</p>
33+
<div className="layer-icon">{DigitSvgs.Layers && <DigitSvgs.Layers width={"1.667rem"} height={"1.667rem"} fill={"rgba(255, 255, 255, 1)"} />}</div>
34+
</div>
35+
<div className="base-map-area-wrapper" ref={basemapRef}>
36+
{showBaseMapSelector && (
37+
<div className="base-map-area" style={{display:"flex"}}>
38+
{Object.entries(baseMaps).map(([name, baseMap], index) => {
39+
return (
40+
<div key={index} className={`base-map-entity ${name === selectedBaseMapName ? "selected" : ""}`}>
41+
<img
42+
className="base-map-img"
43+
key={index}
44+
src={generatePreviewUrl(baseMap?.metadata?.url, [0, 0], 0)}
45+
alt={t("ERROR_LOADING_BASE_MAP")}
46+
onClick={() => handleBaseMapToggle(name)}
47+
/>
48+
<p>{t(name)}</p>
49+
</div>
50+
);
51+
})}
52+
</div>
53+
)}
54+
</div>
55+
</div>
56+
);
57+
};
58+
59+
export default BaseMapSwitcher;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import React, { memo, useEffect, useRef, useState } from "react";
2+
import L from "leaflet";
3+
import "leaflet/dist/leaflet.css";
4+
import { Card, Button, MultiSelectDropdown, TooltipWrapper, Tooltip , Dropdown } from "@egovernments/digit-ui-components";
5+
import { useTranslation } from "react-i18next";
6+
import { InfoIconOutline, CardLabel } from "@egovernments/digit-ui-react-components";
7+
8+
const BoundaryFilter = ({t,filterOptions , onSelectBoundary}) => {
9+
const [boundaryType , setBoundaryType] = useState();
10+
11+
function convertFilterOptionsToArray(filterOptions) {
12+
const keys = Object.keys(filterOptions);
13+
return keys
14+
.filter((key) => Array.isArray(filterOptions[key]))
15+
.map((key) => ({
16+
code: key,
17+
name: key,
18+
}));
19+
}
20+
21+
useEffect(() => {
22+
onSelectBoundary({boundaryType: boundaryType });
23+
}, [boundaryType]);
24+
25+
return (
26+
<div className={`map-filter-by-boundary`}>
27+
<Button
28+
type="actionButton"
29+
variation="secondary"
30+
icon="FilterAlt"
31+
label={t("BUTTON_FILTER_BY_BOUNDARY")}
32+
title={t("BUTTON_FILTER_BY_BOUNDARY")}
33+
options={convertFilterOptionsToArray(filterOptions)}
34+
optionsKey="name"
35+
showBottom={true}
36+
isSearchable={false}
37+
onOptionSelect={(value) => {
38+
setBoundaryType(value?.code);
39+
}}
40+
/>
41+
</div>
42+
);
43+
};
44+
45+
export default BoundaryFilter;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import React, { useEffect, useState } from "react";
2+
3+
const CustomScaleControl = ({ map }) => {
4+
if (!map) return null;
5+
const [scaleText, setScaleText] = useState("");
6+
// Function to calculate and update the scale text
7+
const updateScale = () => {
8+
// Calculate the scale based on the map's current zoom level
9+
const maxWidthMeters = map.containerPointToLatLng([0, map.getSize().y]).distanceTo(map.containerPointToLatLng([100, map.getSize().y]));
10+
const scale = maxWidthMeters / 1000; // Convert to kilometers
11+
12+
// Format the scale text
13+
const scaleTextData = scale < 1 ? `${Math.round(scale * 1000)} m` : `${Math.round(Math.round(scale.toFixed(0) / 10) * 10)} km`;
14+
15+
// Update the scale text in the container element
16+
setScaleText(scaleTextData);
17+
};
18+
19+
// Effect to update the scale text when the map component mounts and on map zoom change
20+
useEffect(() => {
21+
// Update the scale text initially
22+
updateScale();
23+
24+
// Register the map's zoom events to update the scale text
25+
map.on("zoomend", updateScale);
26+
27+
// Clean up event listener when the component unmounts
28+
return () => {
29+
map.off("zoomend", updateScale);
30+
};
31+
}, [map]);
32+
33+
return (
34+
<div className="custom-scale" aria-live="polite">
35+
{scaleText}
36+
<div className="border-spikes" aria-hidden="true" />
37+
</div>
38+
);
39+
};
40+
41+
export default CustomScaleControl;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import React,{Fragment} from "react";
2+
import * as DigitSvgs from "@egovernments/digit-ui-svg-components";
3+
4+
const IconCollection = {...DigitSvgs };
5+
6+
export const FilterItemBuilder = ({ item, MapFilters, t }) => {
7+
let temp = MapFilters?.find((e) => e?.name === item)?.icon?.index;
8+
let DynamicIcon = IconCollection?.[temp];
9+
// let icon;
10+
// if (typeof DynamicIcon === "function") icon = DynamicIcon({});
11+
return DynamicIcon && typeof DynamicIcon === "function" ? (
12+
<div className="filter-row">
13+
<DynamicIcon width={"1.5rem"} height={"1.5rem"} fill={"white"} />
14+
<p className="map-filter-layers">{t(item)}</p>
15+
</div>
16+
) : (
17+
// <div style={{width:"1.5rem"}}></div>
18+
""
19+
);
20+
};
21+
22+
const MapFilterIndex = ({ filterSelections, MapFilters, t }) => {
23+
return (
24+
<div className="filter-index">
25+
{filterSelections && filterSelections.length > 0 ? (
26+
<>
27+
{filterSelections.map((item, index) => (
28+
// <div className="filter-row">
29+
<FilterItemBuilder key={item?.id || index} item={item} MapFilters={MapFilters} t={t} />
30+
// <p>{t(item)}</p>
31+
// </div>
32+
))}
33+
</>
34+
) : (
35+
""
36+
)}
37+
</div>
38+
);
39+
};
40+
41+
export default MapFilterIndex;

0 commit comments

Comments
 (0)