-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Add learning by sector,regions bar chart and Map for learning #1577
base: project/operational-learning-2.0
Are you sure you want to change the base?
feat: Add learning by sector,regions bar chart and Map for learning #1577
Conversation
|
89e0a01
to
e80e0a5
Compare
e80e0a5
to
3bde6b9
Compare
3bde6b9
to
3ef7309
Compare
3ef7309
to
a9f5ebb
Compare
a9f5ebb
to
3071d1b
Compare
8ee38d7
to
6af5950
Compare
6af5950
to
087c25b
Compare
0d21ba8
to
ba0314f
Compare
app/src/views/OperationalLearning/OperationalLearningMap/index.tsx
Outdated
Show resolved
Hide resolved
ba0314f
to
3d5b4bf
Compare
emergencyAppeal: styles.emergencyAppeal, | ||
}; | ||
const now = new Date(); | ||
const startDate = new Date(now.getFullYear() - 20, 0, 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add FIXME to decide start date properly
query: { | ||
...query, | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
query: { | |
...query, | |
}, | |
query, |
const transformSourcesOvertimeData = (data: { | ||
date: string; | ||
type_display: string; | ||
count: number; | ||
}[]) => { | ||
const groupedData: Record<string, { dref: number; emergencyAppeal: number }> = {}; | ||
|
||
data.forEach((entry: { | ||
date: string | number | Date; | ||
type_display: string; | ||
count: number; | ||
}) => { | ||
const year = new Date(entry.date).getFullYear().toString(); | ||
if (!groupedData[year]) { | ||
groupedData[year] = { dref: 0, emergencyAppeal: 0 }; | ||
} | ||
if (entry.type_display === 'DREF') { | ||
groupedData[year].dref = entry.count; | ||
} else if (entry.type_display === 'Emergency Appeal') { | ||
groupedData[year].emergencyAppeal += entry.count; | ||
} | ||
}); | ||
|
||
return groupedData; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use useMemo
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or can be moved outside if this is a pure function
interface Props { | ||
className?: string; | ||
learning: learningStatsResponse | undefined; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
move props next to the main function
const learningCount = useMemo(() => ( | ||
learning?.learning_by_country | ||
.filter((country) => country.count > 0) | ||
), [learning?.learning_by_country]); | ||
|
||
const maxScaleValue = useMemo(() => ( | ||
Math.max( | ||
...(learningCount | ||
?.map((activity: { count: number; }) => activity.count) | ||
.filter(isDefined) ?? []), | ||
)), [learningCount]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
both of these can go inside calculation of bluePointHaloCirclePaint
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, handle case when array length is zero.
const { | ||
bluePointHaloCirclePaint, | ||
} = useMemo( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const { | |
bluePointHaloCirclePaint, | |
} = useMemo( | |
const bluePointHaloCirclePaint = useMemo( |
function getMaxLearning(learning: learningStatsResponse) { | ||
const learningData = learning?.learning_by_country.filter( | ||
({ count }) => isDefined(count), | ||
); | ||
|
||
const maxLearning = maxSafe( | ||
learningData?.map(({ count }) => count), | ||
); | ||
return maxLearning; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move this function inside to directly calculate getMaxLearning
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree. We do not need a separate function that cannot be reused anywhere else.
3d5b4bf
to
34e3d93
Compare
<BaseMap | ||
baseLayers={( | ||
<MapLayer | ||
layerKey="admin-0" | ||
hoverable | ||
layerOptions={adminFillLayerOptions} | ||
onClick={handleCountryClick} | ||
/> | ||
)} | ||
> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use GlobalMap instead of BaseMap.
We are deprecating the use of BaseMap in the future.
function getMaxLearning(learning: learningStatsResponse) { | ||
const learningData = learning?.learning_by_country.filter( | ||
({ count }) => isDefined(count), | ||
); | ||
|
||
const maxLearning = maxSafe( | ||
learningData?.map(({ count }) => count), | ||
); | ||
return maxLearning; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree. We do not need a separate function that cannot be reused anywhere else.
const features = countryResponse | ||
?.map((country) => { | ||
const learningList = learning?.learning_by_country?.find( | ||
(item: { country_id: number; }) => item.country_id === country.id, | ||
); | ||
if (isNotDefined(learningList)) { | ||
return undefined; | ||
} | ||
const units = learningList.count; | ||
return { | ||
type: 'Feature' as const, | ||
geometry: country.centroid as { | ||
type: 'Point', | ||
coordinates: [0, 0], | ||
}, | ||
properties: { | ||
country_id: country.id, | ||
name: country.name, | ||
operation_count: units, | ||
}, | ||
}; | ||
}) | ||
.filter(isDefined) ?? []; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mapping should be done the other way around and use a dict/map to find elements on a loop.
const learningCount = useMemo(() => ( | ||
learning?.learning_by_country | ||
.filter((country) => country.count > 0) | ||
), [learning?.learning_by_country]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The variable learningCount
does not hold count of learnings. Rename this to something appropriate.
const learningCount = useMemo(() => ( | ||
learning?.learning_by_country | ||
.filter((country) => country.count > 0) | ||
), [learning?.learning_by_country]); | ||
|
||
const maxScaleValue = useMemo(() => ( | ||
Math.max( | ||
...(learningCount | ||
?.map((activity: { count: number; }) => activity.count) | ||
.filter(isDefined) ?? []), | ||
)), [learningCount]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, handle case when array length is zero.
const handleCountryClick = useCallback( | ||
(feature: mapboxgl.MapboxGeoJSONFeature, lngLat: mapboxgl.LngLatLike) => { | ||
setClickedPointProperties({ | ||
feature: feature as unknown as ClickedPoint['feature'], | ||
lngLat, | ||
}); | ||
return false; | ||
}, | ||
[], | ||
); | ||
const handlePointClose = useCallback(() => { | ||
setClickedPointProperties(undefined); | ||
}, []); | ||
|
||
const handlePointClick = useCallback( | ||
(feature: mapboxgl.MapboxGeoJSONFeature, lngLat: mapboxgl.LngLatLike) => { | ||
setClickedPointProperties({ | ||
feature: feature as unknown as ClickedPoint['feature'], | ||
lngLat, | ||
}); | ||
return true; | ||
}, | ||
[setClickedPointProperties], | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if handleCountryClick and handlePointClick can be handled the same way. Do we even need handleCountryClick?
}; | ||
const now = new Date(); | ||
|
||
// FIX ME : ADD START DATE PROPERLY |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// FIX ME : ADD START DATE PROPERLY | |
// FIXME: ADD START DATE PROPERLY |
const { | ||
error: learningStatsResponseError, | ||
response: learningStatsResponse, | ||
} = useRequest({ | ||
url: '/api/v2/ops-learning/stats/', | ||
query, | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's also handle pending state.
34e3d93
to
10a77b8
Compare
Addresses:
Changes
This PR doesn't introduce:
console.log
meant for debugging