@tmf_ciclica/ciclicastorybook 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. package/.storybook/main.js +21 -0
  2. package/.storybook/preview.jsx +31 -0
  3. package/README.md +8 -0
  4. package/eslint.config.js +38 -0
  5. package/index.html +13 -0
  6. package/package.json +67 -0
  7. package/public/vite.svg +1 -0
  8. package/src/App.css +0 -0
  9. package/src/App.jsx +36 -0
  10. package/src/_variables.scss +56 -0
  11. package/src/assets/img/arrowDown.svg +3 -0
  12. package/src/assets/img/closeIcon.svg +4 -0
  13. package/src/assets/img/copyIcon.svg +17 -0
  14. package/src/assets/img/deleteIcon.svg +6 -0
  15. package/src/assets/img/eyeActiveIcon.svg +6 -0
  16. package/src/assets/img/eyeNotActiveIcon.svg +8 -0
  17. package/src/assets/img/filtersIcon.svg +6 -0
  18. package/src/assets/img/langarrow.png +0 -0
  19. package/src/assets/img/pause.svg +5 -0
  20. package/src/assets/img/play.svg +4 -0
  21. package/src/assets/img/processingIcon.svg +20 -0
  22. package/src/assets/img/sample-image.png +0 -0
  23. package/src/assets/img/sample2.png +0 -0
  24. package/src/assets/img/world.svg +3 -0
  25. package/src/assets/mapStyles/mapStyle.js +781 -0
  26. package/src/components/AmbitSelector/AmbitItem/AmbitItem.jsx +74 -0
  27. package/src/components/AmbitSelector/AmbitItem/AmbitItem.module.scss +27 -0
  28. package/src/components/AmbitSelector/AmbitSelector.jsx +68 -0
  29. package/src/components/AmbitSelector/AmbitSelector.module.scss +29 -0
  30. package/src/components/AmbitSelector/AmbitSelector.stories.jsx +21 -0
  31. package/src/components/ButtonsList/ButtonsList.jsx +92 -0
  32. package/src/components/ButtonsList/ButtonsList.module.scss +37 -0
  33. package/src/components/ButtonsList/ButtonsList.stories.jsx +55 -0
  34. package/src/components/DropdownList/DropdownList.jsx +69 -0
  35. package/src/components/DropdownList/DropdownList.module.scss +20 -0
  36. package/src/components/DropdownList/DropdownList.stories.jsx +22 -0
  37. package/src/components/DropdownList/DropdownListExample/DropDownListExample.jsx +33 -0
  38. package/src/components/DropdownList/DropdownListExample/DropdownListExample.stories.jsx +11 -0
  39. package/src/components/EditAmbit/EditAmbit.jsx +7 -0
  40. package/src/components/FiltersAmbit/AppliedFilters/AppliedFilters.jsx +57 -0
  41. package/src/components/FiltersAmbit/AppliedFilters/AppliedFilters.module.scss +13 -0
  42. package/src/components/FiltersAmbit/AppliedFilters/AppliedFilters.stories.jsx +47 -0
  43. package/src/components/FiltersAmbit/FiltersAmbit.jsx +58 -0
  44. package/src/components/FiltersAmbit/FiltersAmbit.module.scss +28 -0
  45. package/src/components/FiltersAmbit/FiltersAmbit.stories.jsx +36 -0
  46. package/src/components/FiltersAmbit/GeographicFilters/GeographicalFilters.jsx +33 -0
  47. package/src/components/FiltersAmbit/GeographicFilters/GeographicalFilters.module.scss +13 -0
  48. package/src/components/FiltersAmbit/GeographicFilters/GeographicalFilters.stories.jsx +47 -0
  49. package/src/components/FiltersAmbit/TematicalFilters/TematicalFilters.jsx +83 -0
  50. package/src/components/FiltersAmbit/TematicalFilters/TematicalFilters.module.scss +8 -0
  51. package/src/components/FiltersAmbit/TematicalFilters/TematicalFilters.stories.jsx +17 -0
  52. package/src/components/FiltersAmbit/TematicalFilters/TematicalFiltersCategory/TematicalFiltersCategory.jsx +60 -0
  53. package/src/components/FiltersAmbit/TematicalFilters/TematicalFiltersInput/AbsoluteSlider/AbsoluteSlider.jsx +61 -0
  54. package/src/components/FiltersAmbit/TematicalFilters/TematicalFiltersInput/AbsoluteSlider/AbsoluteSlider.module.scss +45 -0
  55. package/src/components/FiltersAmbit/TematicalFilters/TematicalFiltersInput/CategoryCheckbox/CategoryChackbox.module.scss +18 -0
  56. package/src/components/FiltersAmbit/TematicalFilters/TematicalFiltersInput/CategoryCheckbox/CategoryCheckbox.jsx +47 -0
  57. package/src/components/FiltersAmbit/TematicalFilters/TematicalFiltersInput/TematicalFiltersInput.jsx +267 -0
  58. package/src/components/FiltersAmbit/TematicalFilters/TematicalFiltersInput/TematicalFiltersInput.module.scss +31 -0
  59. package/src/components/FiltersAmbit/TematicalFilters/TematicalFiltersSubcat/TematicalFiltersSubcat.jsx +58 -0
  60. package/src/components/FiltersAmbit/useAmbitStore.jsx +10 -0
  61. package/src/components/Graphic/BarChart/BarChart.jsx +146 -0
  62. package/src/components/Graphic/BarChart/BarChart.module.scss +5 -0
  63. package/src/components/Graphic/BarChart/BarChart.stories.jsx +18 -0
  64. package/src/components/Graphic/Graphic.jsx +55 -0
  65. package/src/components/Graphic/Graphic.module.scss +12 -0
  66. package/src/components/Graphic/Graphic.stories.jsx +25 -0
  67. package/src/components/IndicatorsList/Indicator/Indicator.jsx +180 -0
  68. package/src/components/IndicatorsList/Indicator/Indicator.module.scss +46 -0
  69. package/src/components/IndicatorsList/IndicatorSubCategory/IndicatorSubCategory.jsx +76 -0
  70. package/src/components/IndicatorsList/IndicatorSubCategory/IndicatorSubCategory.module.scss +12 -0
  71. package/src/components/IndicatorsList/IndicatorsCategory/IndicatorsCategory.jsx +122 -0
  72. package/src/components/IndicatorsList/IndicatorsCategory/IndicatorsCategory.module.scss +20 -0
  73. package/src/components/IndicatorsList/IndicatorsList.jsx +173 -0
  74. package/src/components/IndicatorsList/IndicatorsList.module.scss +10 -0
  75. package/src/components/IndicatorsList/IndicatorsList.stories.jsx +263 -0
  76. package/src/components/LangSelector/LangSelector.jsx +70 -0
  77. package/src/components/LangSelector/LangSelector.module.scss +41 -0
  78. package/src/components/LangSelector/LangSelector.stories.jsx +27 -0
  79. package/src/components/Legend/Legend.jsx +132 -0
  80. package/src/components/Legend/Legend.module.scss +121 -0
  81. package/src/components/Legend/Legend.stories.jsx +53 -0
  82. package/src/components/LogoApp/LogoApp.jsx +33 -0
  83. package/src/components/LogoApp/LogoApp.module.scss +7 -0
  84. package/src/components/LogoApp/LogoApp.stories.jsx +27 -0
  85. package/src/components/MapboxMap/MapboxMap.jsx +160 -0
  86. package/src/components/MapboxMap/MapboxMap.module.scss +4 -0
  87. package/src/components/MapboxMap/MapboxMap.stories.jsx +57 -0
  88. package/src/components/MaplibreMap/MaplibreMap.jsx +166 -0
  89. package/src/components/MaplibreMap/MaplibreMap.module.scss +5 -0
  90. package/src/components/MaplibreMap/MaplibreMap.stories.jsx +55 -0
  91. package/src/components/SectionBar/SectionBar.jsx +41 -0
  92. package/src/components/SectionBar/SectionBar.module.scss +40 -0
  93. package/src/components/SectionBar/SectionBar.stories.jsx +35 -0
  94. package/src/components/TimeSlider/TimeSlider.jsx +147 -0
  95. package/src/components/TimeSlider/TimeSlider.module.scss +63 -0
  96. package/src/components/TimeSlider/TimeSlider.stories.jsx +9 -0
  97. package/src/components/Tooltip/Tooltip.jsx +40 -0
  98. package/src/components/Tooltip/Tooltip.module.scss +141 -0
  99. package/src/components/Tooltip/Tooltip.stories.jsx +51 -0
  100. package/src/components/TopNavMenu/TopNavMenu.jsx +62 -0
  101. package/src/components/TopNavMenu/TopNavMenu.module.scss +21 -0
  102. package/src/components/TopNavMenu/TopNavMenu.stories.jsx +20 -0
  103. package/src/components/UserMenuTrigger/UserMenuTrigger.jsx +47 -0
  104. package/src/components/UserMenuTrigger/UserMenuTrigger.module.scss +5 -0
  105. package/src/components/UserMenuTrigger/UserMenuTrigger.stories.jsx +33 -0
  106. package/src/components/index.jsx +17 -0
  107. package/src/constants/indicators.js +1371 -0
  108. package/src/constants/mapTexts.js +161 -0
  109. package/src/constants/textLayers.js +639 -0
  110. package/src/constants/topNavMenuOptions.js +14 -0
  111. package/src/i18n.js +19 -0
  112. package/src/index.js +2 -0
  113. package/src/index.scss +87 -0
  114. package/src/locales/ca.json +8 -0
  115. package/src/locales/es.json +15 -0
  116. package/src/main.jsx +10 -0
  117. package/src/sections/HeaderSection/HeaderSection.jsx +51 -0
  118. package/src/sections/HeaderSection/HeaderSection.module.scss +33 -0
  119. package/src/sections/HeaderSection/HeaderSection.stories.jsx +61 -0
  120. package/src/sections/RightSidebar/RightSidebar.jsx +35 -0
  121. package/src/sections/RightSidebar/RightSidebar.module.scss +39 -0
  122. package/src/sections/RightSidebar/RightSidebar.stories.jsx +21 -0
  123. package/src/sections/index.js +2 -0
  124. package/src/store/index.js +1 -0
  125. package/src/store/mapSlice/index.js +1 -0
  126. package/src/store/mapSlice/mapSlice.js +30 -0
  127. package/src/store/rightBarSlice/index.js +1 -0
  128. package/src/store/rightBarSlice/rightBarSlice.js +28 -0
  129. package/src/store/routerSlice/index.js +1 -0
  130. package/src/store/routerSlice/routerSlice.js +14 -0
  131. package/src/store/store.js +14 -0
  132. package/src/store/userSlice/index.js +1 -0
  133. package/src/store/userSlice/userSlice.js +22 -0
  134. package/vite.config.js +36 -0
@@ -0,0 +1,180 @@
1
+ /*
2
+ Componente para cada indicador listado.
3
+ Recibe las siguientes propiedades del propio indicador: name, ikey, type y values(solo en el caso de que sea type 'twoUnits')
4
+ Recibe también activeColor (color indicador seleccionado) y defaultColor
5
+ Lee del store mapState:
6
+ - activeIndicatorKey: ikey del indicador seleccionado
7
+ - activeIndicatorType: type del indicador seleccionado (abs, cat, both, twoUnits)
8
+ - activeIndicatorUnit: code de la unit seleccionada en caso de que el indicador seleccionado sea tipo 'twoUnits'
9
+ Ejecuta las acciones del store mapState: setActiveIndicatorKey, setActiveIndicatorType, setActiveIndicatorUnit
10
+ */
11
+ import PropTypes from "prop-types"
12
+ import { useTranslation } from "react-i18next"
13
+
14
+ // Styles
15
+ import styles from "./Indicator.module.scss"
16
+ import { useEffect, useState } from "react"
17
+
18
+ export const Indicator = ({
19
+ indicator,
20
+ values = [],
21
+ activeColor,
22
+ defaultColor = "black",
23
+ activeIndicator,
24
+ onClickIndicator,
25
+ multiple = false,
26
+ }) => {
27
+ const { t } = useTranslation()
28
+ const { name, ikey, type } = indicator
29
+
30
+ const [selected, setSelected] = useState(false)
31
+
32
+ useEffect(() => {
33
+ if (activeIndicator) {
34
+ if (!multiple) {
35
+ setSelected(activeIndicator.ikey == ikey)
36
+ } else {
37
+ setSelected(
38
+ activeIndicator.some(
39
+ (activeIndicatorElement) =>
40
+ activeIndicatorElement.ikey == String(ikey)
41
+ )
42
+ )
43
+ }
44
+ }
45
+ }, [activeIndicator])
46
+
47
+ const switchCatAbsComponent = () => {
48
+ return (
49
+ <div className={styles.switchExternalContainer}>
50
+ <div className={styles.switchType}>
51
+ <div className={styles.switchTypeOptions}>
52
+ <div
53
+ className={styles.optionContainer}
54
+ // onClick={() => dispatch(setActiveIndicatorType("cat"))}
55
+ >
56
+ <span
57
+ className={`${styles.customRadious}`}
58
+ // style={{
59
+ // backgroundColor:
60
+ // activeIndicatorType === "cat" ? activeColor : "transparent",
61
+ // borderColor:
62
+ // activeIndicatorType === "cat" ? activeColor : defaultColor,
63
+ // }}
64
+ />
65
+ <h4
66
+ className={styles.optionText}
67
+ // style={{
68
+ // color:
69
+ // activeIndicatorType === "cat" ? activeColor : defaultColor,
70
+ // }}
71
+ >
72
+ {t("indicators.cat")}
73
+ </h4>
74
+ </div>
75
+
76
+ <div
77
+ className={styles.optionContainer}
78
+ // onClick={() => dispatch(setActiveIndicatorType("abs"))}
79
+ >
80
+ <span
81
+ className={`${styles.customRadious}`}
82
+ // style={{
83
+ // backgroundColor:
84
+ // activeIndicatorType === "abs" ? activeColor : "transparent",
85
+ // borderColor:
86
+ // activeIndicatorType === "abs" ? activeColor : defaultColor,
87
+ // }}
88
+ />
89
+ <h4
90
+ className={styles.optionText}
91
+ // style={{
92
+ // color:
93
+ // activeIndicatorType === "abs" ? activeColor : defaultColor,
94
+ // }}
95
+ >
96
+ {t("indicators.abs")}
97
+ </h4>
98
+ </div>
99
+ </div>
100
+ </div>
101
+ </div>
102
+ )
103
+ }
104
+ const switchUnitComponent = () => {
105
+ return (
106
+ <div className={styles.switchExternalContainer}>
107
+ <div className={styles.switchType}>
108
+ <div className={styles.switchTypeOptions}>
109
+ {values.map((val, i) => {
110
+ return (
111
+ <div
112
+ className={styles.optionContainer}
113
+ // onClick={() => dispatch(setActiveIndicatorUnit(val.codename))}
114
+ key={i}
115
+ >
116
+ <span
117
+ className={styles.customRadious}
118
+ // style={{
119
+ // backgroundColor:
120
+ // activeIndicatorUnit === val.codename
121
+ // ? activeColor
122
+ // : "transparent",
123
+ // borderColor:
124
+ // activeIndicatorUnit === val.codename
125
+ // ? activeColor
126
+ // : defaultColor,
127
+ // }}
128
+ />
129
+ <h4>{t(val.unit)}</h4>
130
+ </div>
131
+ )
132
+ })}
133
+ </div>
134
+ </div>
135
+ </div>
136
+ )
137
+ }
138
+
139
+ return (
140
+ <button
141
+ onClick={() => onClickIndicator({ indicator })}
142
+ className={styles.indicatorContainer}
143
+ >
144
+ <div
145
+ style={{
146
+ border: selected
147
+ ? `1px solid ${activeColor}`
148
+ : `1px solid ${defaultColor}`,
149
+ }}
150
+ className={styles.dot}
151
+ ></div>
152
+ <h4
153
+ className={styles.indicatorName}
154
+ style={{ color: selected ? activeColor : defaultColor }}
155
+ >
156
+ {t(name)}
157
+ </h4>
158
+
159
+ {activeIndicator === ikey && type === "both" && (
160
+ <div>{switchCatAbsComponent()}</div>
161
+ )}
162
+ {activeIndicator === ikey && type === "twoUnits" && (
163
+ <div>{switchUnitComponent()}</div>
164
+ )}
165
+ </button>
166
+ )
167
+ }
168
+ Indicator.propTypes = {
169
+ indicator: PropTypes.shape({
170
+ name: PropTypes.string,
171
+ ikey: PropTypes.number,
172
+ type: PropTypes.string,
173
+ }),
174
+ values: PropTypes.oneOfType([PropTypes.bool, PropTypes.array]),
175
+ activeColor: PropTypes.string,
176
+ defaultColor: PropTypes.string,
177
+ activeIndicator: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
178
+ multiple: PropTypes.bool,
179
+ onClickIndicator: PropTypes.func,
180
+ }
@@ -0,0 +1,46 @@
1
+ .indicatorContainer {
2
+ @include flex($direction: row, $justify: start, $align: center);
3
+ gap: 10px;
4
+ .dot {
5
+ border-radius: 100px;
6
+ width: 16px;
7
+ height: 16px;
8
+ }
9
+ .indicatorName {
10
+ cursor: pointer;
11
+ font-weight: 400;
12
+ text-align: left;
13
+ }
14
+ }
15
+
16
+ .switchExternalContainer {
17
+ @include flex($direction: column, $justify: start, $align: start);
18
+ // gap: 20px;
19
+ margin: 20px 0 0 0;
20
+ .switchType {
21
+ // @include flex($direction: column, $justify: start, $align: start);
22
+ margin: 0;
23
+ width: 100%;
24
+
25
+ .switchTypeOptions {
26
+ gap: 20px;
27
+ @include flex($direction: column, $justify: start, $align: start);
28
+ margin-bottom: 20px;
29
+ margin: 0 0 20px 23px;
30
+
31
+ .optionContainer {
32
+ @include flex($direction: row, $justify: center, $align: center);
33
+ gap: 10px;
34
+ cursor: pointer;
35
+
36
+ .customRadious {
37
+ width: 16px;
38
+ height: 16px;
39
+ border-radius: 100px;
40
+ border: 1px solid;
41
+ padding: 0px;
42
+ }
43
+ }
44
+ }
45
+ }
46
+ }
@@ -0,0 +1,76 @@
1
+ import { useTranslation } from "react-i18next"
2
+ import { Indicator } from "../Indicator/Indicator"
3
+ import PropTypes from "prop-types"
4
+ import { useEffect, useState } from "react"
5
+ import { motion } from "framer-motion"
6
+ import style from "./IndicatorSubCategory.module.scss"
7
+ export const IndicatorSubCategory = ({
8
+ subcName,
9
+ indicators,
10
+ defaultColor,
11
+ activeColor,
12
+ activeSubCategory,
13
+ onClickSubCategory,
14
+ id,
15
+ activeIndicator,
16
+ onClickIndicator,
17
+ multiple,
18
+ }) => {
19
+ const { t } = useTranslation()
20
+ const [open, setOpen] = useState(false)
21
+
22
+ useEffect(() => {
23
+ setOpen(activeSubCategory == id)
24
+ }, [activeSubCategory, id])
25
+
26
+ return (
27
+ <motion.div
28
+ className={style.indicatorsSubCategory}
29
+ initial={{ height: "43px" }}
30
+ animate={{ height: open ? "auto" : "43px" }}
31
+ transition={{ duration: 0.4 }}
32
+ >
33
+ <button onClick={() => onClickSubCategory(id)}>
34
+ <h3 style={{ color: open ? activeColor : defaultColor }}>
35
+ <span style={{ color: open ? activeColor : defaultColor }}>
36
+ {open ? "-" : "+"}
37
+ </span>
38
+ <span
39
+ style={{ marginLeft: 12, color: open ? activeColor : defaultColor }}
40
+ >
41
+ {t(subcName)}
42
+ </span>
43
+ </h3>
44
+ </button>
45
+ {indicators && (
46
+ <div className={style.list}>
47
+ {indicators?.map((indicator, id) => {
48
+ return (
49
+ <Indicator
50
+ indicator={indicator}
51
+ key={"indicator" + id}
52
+ defaultColor={defaultColor}
53
+ activeColor={activeColor}
54
+ activeIndicator={activeIndicator}
55
+ onClickIndicator={onClickIndicator}
56
+ multiple={multiple}
57
+ />
58
+ )
59
+ })}
60
+ </div>
61
+ )}
62
+ </motion.div>
63
+ )
64
+ }
65
+ IndicatorSubCategory.propTypes = {
66
+ subcName: PropTypes.string,
67
+ indicators: PropTypes.array,
68
+ activeColor: PropTypes.string,
69
+ defaultColor: PropTypes.string,
70
+ activeSubCategory: PropTypes.string,
71
+ id: PropTypes.string,
72
+ activeIndicator: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
73
+ multiple: PropTypes.bool,
74
+ onClickSubCategory: PropTypes.func,
75
+ onClickIndicator: PropTypes.func,
76
+ }
@@ -0,0 +1,12 @@
1
+ .indicatorsSubCategory {
2
+ overflow: hidden;
3
+
4
+ h3 {
5
+ text-align: left;
6
+ }
7
+ .list {
8
+ @include flex($direction: column, $align: start);
9
+ margin: 20px 0px;
10
+ gap: 20px;
11
+ }
12
+ }
@@ -0,0 +1,122 @@
1
+ /*
2
+ Componente para las categorías de Indicadores dentro del listado de Indicadores
3
+ Recibe:
4
+ - el objeto con toda la categoría
5
+ - el valor Open si está desplegada o no
6
+ - la función changeActive para desplegar o plegar la categoría
7
+ - activeColor: color categoría Seleccionada
8
+ - defaultColor
9
+ Necesita el elemento motion de la librería 'framer-motion' | yarn add framer-motion |
10
+ */
11
+ import PropTypes from "prop-types"
12
+ import { useTranslation } from "react-i18next"
13
+ import { motion } from "framer-motion"
14
+
15
+ import style from "./IndicatorsCategory.module.scss"
16
+ import { Indicator } from "../Indicator/Indicator"
17
+ import { useEffect, useState } from "react"
18
+ import { IndicatorSubCategory } from "../IndicatorSubCategory/IndicatorSubCategory"
19
+ export const IndicatorsCategory = ({
20
+ cat,
21
+ id,
22
+ activeColor,
23
+ defaultColor,
24
+ onClickCategory,
25
+ activeCategory,
26
+ activeSubCategory,
27
+ onClickSubCategory,
28
+ activeIndicator,
29
+ onClickIndicator,
30
+ multiple,
31
+ }) => {
32
+ const { t } = useTranslation()
33
+ const [open, setOpen] = useState(false)
34
+ // const containsActive = (cat) => {
35
+ // return cat.indicators.some((ind) => ind.ikey === activeKey)
36
+ // }
37
+
38
+ // useEffect(() => {
39
+ // setActiveCat(indicators.findIndex((cat) => containsActive(cat)))
40
+ // }, [])
41
+ useEffect(() => {
42
+ setOpen(activeCategory === id)
43
+ }, [activeCategory, id])
44
+
45
+ return (
46
+ <motion.div
47
+ className={style.indicatorsCategory}
48
+ initial={{ height: "53px" }}
49
+ animate={{ height: open ? "auto" : "53px" }}
50
+ transition={{ duration: 0.4 }}
51
+ style={{
52
+ backgroundColor: "white",
53
+ borderBottom: open ? `1px solid ${activeColor}` : "0px",
54
+ marginBottom: open ? "20px" : "0px",
55
+ }}
56
+ >
57
+ <h2 className={`${style.title}`} onClick={() => onClickCategory(id)}>
58
+ <span style={{ color: open ? activeColor : defaultColor }}>
59
+ {open ? "-" : "+"}
60
+ </span>
61
+ <span
62
+ style={{ marginLeft: 12, color: open ? activeColor : defaultColor }}
63
+ >
64
+ {t(cat.name)}
65
+ </span>
66
+ </h2>
67
+ {cat.subcategories ? (
68
+ cat.subcategories.map(
69
+ (
70
+ { name: subcName, subcategory, indicators: subcIndicators },
71
+ idxSubc
72
+ ) => (
73
+ <IndicatorSubCategory
74
+ id={subcategory}
75
+ key={`subcKey ${idxSubc}`}
76
+ activeSubCategory={activeSubCategory}
77
+ subcName={subcName}
78
+ onClickSubCategory={onClickSubCategory}
79
+ activeIndicator={activeIndicator}
80
+ onClickIndicator={onClickIndicator}
81
+ multiple={multiple}
82
+ activeColor={activeColor}
83
+ defaultColor={defaultColor}
84
+ indicators={subcIndicators}
85
+ />
86
+ )
87
+ )
88
+ ) : (
89
+ <div className={style.list}>
90
+ {cat.indicators?.map((indicator, id) => {
91
+ return (
92
+ <Indicator
93
+ key={`indicator${id}`}
94
+ indicator={indicator}
95
+ values={indicator.type == "twoUnits" && indicator.values}
96
+ activeColor={activeColor}
97
+ defaultColor={defaultColor}
98
+ activeIndicator={activeIndicator}
99
+ onClickIndicator={onClickIndicator}
100
+ multiple={multiple}
101
+ />
102
+ )
103
+ })}
104
+ </div>
105
+ )}
106
+ </motion.div>
107
+ )
108
+ }
109
+ IndicatorsCategory.propTypes = {
110
+ cat: PropTypes.object,
111
+ id: PropTypes.string,
112
+ onChange: PropTypes.func,
113
+ onClickCategory: PropTypes.func,
114
+ activeCategory: PropTypes.string,
115
+ activeSubCategory: PropTypes.string,
116
+ onClickSubCategory: PropTypes.func,
117
+ onClickIndicator: PropTypes.func,
118
+ activeIndicator: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
119
+ multiple: PropTypes.bool,
120
+ activeColor: PropTypes.string,
121
+ defaultColor: PropTypes.string,
122
+ }
@@ -0,0 +1,20 @@
1
+ .indicatorsCategory {
2
+ overflow: hidden;
3
+
4
+ .title {
5
+ align-items: center;
6
+ gap: 10px;
7
+ cursor: pointer;
8
+ margin-bottom: 25px;
9
+ }
10
+ .list {
11
+ display: flex;
12
+ flex-wrap: nowrap;
13
+ justify-content: start;
14
+ flex-direction: column;
15
+ align-items: start;
16
+ width: 100%;
17
+ gap: 20px;
18
+ padding-bottom: 20px;
19
+ }
20
+ }
@@ -0,0 +1,173 @@
1
+ /*
2
+ Componente para listar todas los indicadores clasificados en sus categorías
3
+ Recibe el array de objetos que contiente todos los indicadores con esta estructura:
4
+ [
5
+ {
6
+ category: 'codi',
7
+ name: 'locales.nomCategoria',
8
+ // Las subcategorias son opcionales
9
+ subcategories: [
10
+ {
11
+ subcategory: 'codi',
12
+ name: 'locales.nomSubcategoria',
13
+ indicators: []
14
+ }
15
+ ]
16
+ indicators: [
17
+ {
18
+ ikey: number,
19
+ name: 'locales.nomIndicador',
20
+ code:['codi/s'],
21
+ type: 'cat/abs/both/twoUnits',
22
+ values: (si type cat, both o twoUnits),
23
+ maxColor: (si type abs o both),
24
+ midColor: (si type abs o both),
25
+ minColor: (si type abs o both),
26
+ maxValue: (si type abs o both),
27
+ minValue: (si type abs o both),
28
+ minValueIndicador: 'locales.indicador.minValueIndicador',
29
+ maxValueIndicador: 'locales.indicador.minValueIndicador',
30
+ unit: 'locales.unidadIndicador',
31
+ time: bool (si tiene que mostrarse el slider de tiempo)
32
+ }
33
+ ]
34
+ }
35
+ ]
36
+ También recibe el activeColor para elementos seleccionados y defaultColor para los que no
37
+ */
38
+ import PropTypes from "prop-types"
39
+ import { useTranslation } from "react-i18next"
40
+ //components
41
+ import { IndicatorsCategory } from "./IndicatorsCategory/IndicatorsCategory"
42
+
43
+ //styles
44
+ import style from "./IndicatorsList.module.scss"
45
+ import { useEffect, useState } from "react"
46
+
47
+ export const IndicatorsList = ({
48
+ indicators,
49
+ activeColor,
50
+ defaultColor = "black",
51
+ // Función que se ejecuta al seleccionar un indicador, recibe el o los ikeys como parametro
52
+ onChange,
53
+ // Selección multiple
54
+ multiple = false,
55
+ // Si multiple es true, debe ser un array de strings, sino un string
56
+ defaultValue = null,
57
+ }) => {
58
+ const { t } = useTranslation()
59
+ const [activeCategory, setActiveCategory] = useState()
60
+ const [activeSubCategory, setActiveSubCategory] = useState()
61
+ const [activeIndicator, setActiveIndicator] = useState()
62
+
63
+ const onClickCategory = (id) => {
64
+ setActiveCategory(activeCategory == id ? null : id)
65
+ }
66
+ const onClickSubCategory = (id) => {
67
+ setActiveSubCategory(activeSubCategory == id ? null : id)
68
+ }
69
+ const onClickIndicator = ({ indicator }) => {
70
+ updateActiveIndicator(indicator)
71
+ }
72
+ const updateActiveIndicator = (indicator) => {
73
+ if (!multiple) {
74
+ setActiveIndicator(
75
+ activeIndicator?.ikey == indicator.ikey ? null : indicator
76
+ )
77
+ } else {
78
+ let newActiveIndicator =
79
+ activeIndicator && activeIndicator.length > 0
80
+ ? [...activeIndicator]
81
+ : []
82
+ setActiveIndicator(
83
+ newActiveIndicator?.some(
84
+ (indicatorElement) => indicatorElement.ikey == indicator.ikey
85
+ )
86
+ ? newActiveIndicator.filter(
87
+ (ind) => ind.ikey != String(indicator.ikey)
88
+ )
89
+ : [...newActiveIndicator, indicator]
90
+ )
91
+ }
92
+ }
93
+ useEffect(() => {
94
+ if (onChange && typeof onChange === "function")
95
+ onChange({ activeIndicator })
96
+ }, [activeIndicator])
97
+
98
+ //Setea el valor por defecto si existe y no tenemos un indicador activo
99
+ //Busca el valor por defecto en el array de indicadores y setea también las categorias y subcategoirias activas
100
+ useEffect(() => {
101
+ if (defaultValue && !activeIndicator) {
102
+ if (multiple && defaultValue && Array.isArray(defaultValue)) {
103
+ let newActiveIndicator =
104
+ activeIndicator && activeIndicator.length > 0
105
+ ? [...activeIndicator]
106
+ : []
107
+ setActiveIndicator([...newActiveIndicator, ...defaultValue])
108
+ updateActiveCategoiriesOnChangeDefaultVal(defaultValue[0].ikey)
109
+ } else {
110
+ updateActiveIndicator(defaultValue)
111
+ updateActiveCategoiriesOnChangeDefaultVal(defaultValue.ikey)
112
+ }
113
+ }
114
+ }, [defaultValue])
115
+
116
+ const updateActiveCategoiriesOnChangeDefaultVal = (defaultValue) => {
117
+ const category = indicators.find((cat) => {
118
+ if (cat.subcategories) {
119
+ let subcategoryFound = cat.subcategories.find((subc) =>
120
+ subc.indicators.find((indSubc) => indSubc.ikey == defaultValue)
121
+ )
122
+ if (subcategoryFound) {
123
+ // console.log("subCategoryFound: ", subcategoryFound)
124
+ setActiveSubCategory(subcategoryFound.subcategory)
125
+ return subcategoryFound
126
+ }
127
+ } else {
128
+ return cat.indicators.some((ind) => ind.ikey == defaultValue)
129
+ }
130
+ })
131
+ // console.log("foundCategory: ", category)
132
+ if (category) {
133
+ setActiveCategory(category.category)
134
+ }
135
+ }
136
+
137
+ return (
138
+ <div className={style.indicatorsList}>
139
+ <h2 className={style.title} style={{ color: defaultColor }}>
140
+ {t("indicators.indicators")}
141
+ </h2>
142
+
143
+ {indicators.map((cat, id) => {
144
+ return (
145
+ <IndicatorsCategory
146
+ id={cat.category}
147
+ key={`categoryKey${id}`}
148
+ cat={cat}
149
+ onClickCategory={onClickCategory}
150
+ activeCategory={activeCategory}
151
+ onClickSubCategory={onClickSubCategory}
152
+ activeSubCategory={activeSubCategory}
153
+ onClickIndicator={onClickIndicator}
154
+ activeIndicator={activeIndicator}
155
+ activeColor={activeColor}
156
+ defaultColor={defaultColor}
157
+ multiple={multiple}
158
+ onChange={onChange}
159
+ />
160
+ )
161
+ })}
162
+ </div>
163
+ )
164
+ }
165
+ IndicatorsList.propTypes = {
166
+ indicators: PropTypes.arrayOf(PropTypes.object),
167
+ activeColor: PropTypes.string,
168
+ defaultColor: PropTypes.string,
169
+ onChange: PropTypes.func,
170
+ multiple: PropTypes.bool,
171
+ activeIndicator: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
172
+ defaultValue: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
173
+ }
@@ -0,0 +1,10 @@
1
+ pr.indicatorsList {
2
+ width: 100%;
3
+ padding-left: 30px;
4
+
5
+ .title {
6
+ border-bottom: 1px solid;
7
+ padding-bottom: 25px;
8
+ margin-bottom: 32px;
9
+ }
10
+ }