Skip to content

Commit

Permalink
delete dummy data and process survey data from server
Browse files Browse the repository at this point in the history
  • Loading branch information
jiji14 committed May 5, 2024
1 parent 58cfb5f commit 8150e95
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 59 deletions.
5 changes: 5 additions & 0 deletions www/js/TimelineContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ type ContextProps = {
refreshTimeline: () => void;
shouldUpdateTimeline: Boolean;
setShouldUpdateTimeline: React.Dispatch<React.SetStateAction<boolean>>;
lastUpdateMetricDateTime: number;
setLastUpdateMetricDateTime: React.Dispatch<React.SetStateAction<number>>;
};

export const useTimelineContext = (): ContextProps => {
Expand All @@ -78,6 +80,7 @@ export const useTimelineContext = (): ContextProps => {
// Leaflet map encounters an error when prerendered, so we need to render the TimelineScrollList component when the active tab is 'label'
// 'shouldUpdateTimeline' gets updated based on the current tab index, and we can use it to determine whether to render the timeline or not
const [shouldUpdateTimeline, setShouldUpdateTimeline] = useState(true);
const [lastUpdateMetricDateTime, setLastUpdateMetricDateTime] = useState<number>(0);

// initialization, once the appConfig is loaded
useEffect(() => {
Expand Down Expand Up @@ -372,6 +375,8 @@ export const useTimelineContext = (): ContextProps => {
addUserInputToEntry,
shouldUpdateTimeline,
setShouldUpdateTimeline,
lastUpdateMetricDateTime,
setLastUpdateMetricDateTime,
};
};

Expand Down
14 changes: 8 additions & 6 deletions www/js/metrics/SurveyDoughnutCharts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { useTranslation } from 'react-i18next';
import { useAppTheme } from '../appTheme';
import { Chart as ChartJS, ArcElement, Tooltip, Legend } from 'chart.js';
import { Doughnut } from 'react-chartjs-2';
import { SurveyComparison } from './SurveyLeaderboardCard';

ChartJS.register(ArcElement, Tooltip, Legend);

Expand All @@ -25,12 +26,13 @@ export const LabelPanel = ({ first, second }) => {
);
};

const SurveyDoughnutCharts = () => {
type Props = {
surveyComparison : SurveyComparison
}

const SurveyDoughnutCharts = ({surveyComparison} : Props) => {
const { colors } = useAppTheme();
const { t } = useTranslation();
const myResonseRate = 68;
const othersResponseRate = 41;

const renderDoughnutChart = (rate, chartColor, myResponse) => {
const data = {
datasets: [
Expand Down Expand Up @@ -76,8 +78,8 @@ const SurveyDoughnutCharts = () => {
<View>
<Text style={styles.chartTitle}>{t('main-metrics.survey-response-rate')}</Text>
<View style={styles.chartWrapper}>
{renderDoughnutChart(myResonseRate, colors.navy, true)}
{renderDoughnutChart(othersResponseRate, colors.orange, false)}
{renderDoughnutChart(surveyComparison.me, colors.navy, true)}
{renderDoughnutChart(surveyComparison.others, colors.orange, false)}
</View>
<LabelPanel first={t('main-metrics.you')} second={t('main-metrics.others')} />
</View>
Expand Down
93 changes: 75 additions & 18 deletions www/js/metrics/SurveyLeaderboardCard.tsx
Original file line number Diff line number Diff line change
@@ -1,47 +1,104 @@
import React, { useState } from 'react';
import React, { useState, useMemo } from 'react';
import { View, Text } from 'react-native';
import { Card } from 'react-native-paper';
import { cardStyles } from './MetricsTab';
import { cardStyles, SurveyMetric, SurveyObject } from './MetricsTab';
import { useTranslation } from 'react-i18next';
import ToggleSwitch from '../components/ToggleSwitch';
import BarChart from '../components/BarChart';
import { useAppTheme } from '../appTheme';
import SurveyComparisonChart from './SurveyDoughnutCharts';
import { Chart as ChartJS, registerables } from 'chart.js';
import Annotation from 'chartjs-plugin-annotation';

const SurveyLeaderboardCard = () => {
ChartJS.register(...registerables, Annotation);

type Props = {
surveyMetric: SurveyMetric
}

type LeaderboardRecord = {
label: string,
x: number,
y: string
}
export type SurveyComparison = {
'me' : number,
'others' : number,
}

const SurveyLeaderboardCard = ( { surveyMetric }: Props) => {
const { colors } = useAppTheme();
const { t } = useTranslation();
const [tab, setTab] = useState('leaderboard');
const myLabel = '#3';

const myRank = surveyMetric.me.rank;
const mySurveyMetric = surveyMetric.me.overview;
const othersSurveyMetric = surveyMetric.others.overview;
const mySurveyRate = Math.round(mySurveyMetric.answered / (mySurveyMetric.answered + mySurveyMetric.unanswered) * 100);

const surveyComparison: SurveyComparison = {
'me' : mySurveyRate,
'others' : Math.round(othersSurveyMetric.answered / (othersSurveyMetric.answered + othersSurveyMetric.unanswered) * 100)
}

function getLabel(rank: number): string {
if(rank === 0) {
return '🏆 #1:';
}else if(rank === 1) {
return '🥈 #2:';
}else if(rank === 2) {
return '🥉 #3:';
}else {
return `#${rank+1}:`;
}
}

const leaderboardRecords: LeaderboardRecord[] = useMemo(() => {
const combinedLeaderboard:SurveyObject[] = [...surveyMetric.others.leaderboard];
combinedLeaderboard.splice(myRank, 0, mySurveyMetric);

// This is to prevent the leaderboard from being too long for UX purposes.
// For a total of 20 members, we only show the top 5 members, myself, and the bottom 3 members.
const numberOfTopUsers = 5
const numberOfBottomUsers = surveyMetric.others.leaderboard.length -3;

return combinedLeaderboard.map((item, idx) => (
{
'isMe': idx === myRank,
'rank': idx,
'answered': item.answered,
'unanswered': item.unanswered,
'mismatched': item.mismatched,
}
)).filter((item) => ( item.isMe || item.rank < numberOfTopUsers || item.rank >= numberOfBottomUsers))
.map((item) => (
{
label: item.isMe ? `${item.rank}-me` : `${item.rank}-other`,
x: Math.round(item.answered / (item.answered + item.unanswered) * 100),
y: getLabel(item.rank)
}
))
}, [surveyMetric])

const renderBarChart = () => {
const records = [
{ label: '#1', x: 91, y: '🏆 #1:' },
{ label: '#2', x: 72, y: '🥈 #2:' },
{ label: '#3', x: 68, y: '🥉 #3:' },
{ label: '#4', x: 57, y: '#4:' },
{ label: '#5', x: 50, y: '#5:' },
{ label: '#6', x: 40, y: '#6:' },
{ label: '#7', x: 30, y: '#7:' },
];
return (
<View>
<Text style={styles.chartTitle}>{t('main-metrics.survey-response-rate')}</Text>
<BarChart
records={records}
records={leaderboardRecords}
axisTitle=""
isHorizontal={true}
timeAxis={false}
stacked={false}
getColorForLabel={(l) => (l === myLabel ? colors.skyblue : colors.silver)}
getColorForChartEl={(l) => (l === myLabel ? colors.skyblue : colors.silver)}
getColorForLabel={(l) => (l === `${myRank}-me` ? colors.skyblue : colors.silver)}
getColorForChartEl={(l) => (l === `${myRank}-me` ? colors.skyblue : colors.silver)}
showLegend={false}
reverse={false}
enableTooltip={false}
/>
<View style={styles.statusTextWrapper}>
<Text>{t('main-metrics.you-are-in')}</Text>
<Text style={{ color: colors.navy, fontWeight: 'bold' }}> {myLabel} </Text>
<Text style={{ color: colors.navy, fontWeight: 'bold' }}> #{myRank+1} </Text>
<Text>{t('main-metrics.place')}</Text>
</View>
</View>
Expand Down Expand Up @@ -74,7 +131,7 @@ const SurveyLeaderboardCard = () => {
)}
/>
<Card.Content style={cardStyles.content}>
{tab === 'leaderboard' ? renderBarChart() : <SurveyComparisonChart />}
{tab === 'leaderboard' ? renderBarChart() : <SurveyComparisonChart surveyComparison={surveyComparison} />}
</Card.Content>
</Card>
);
Expand Down
60 changes: 25 additions & 35 deletions www/js/metrics/SurveyTripCategoriesCard.tsx
Original file line number Diff line number Diff line change
@@ -1,47 +1,37 @@
import React from 'react';
import { View, Text } from 'react-native';
import { Card } from 'react-native-paper';
import { cardStyles } from './MetricsTab';
import { cardStyles, SurveyObject } from './MetricsTab';
import { useTranslation } from 'react-i18next';
import BarChart from '../components/BarChart';
import { useAppTheme } from '../appTheme';
import { LabelPanel } from './SurveyDoughnutCharts';

const SurveyTripCategoriesCard = () => {
type SurveyTripRecord = {
label: string,
x: string,
y: number
}

type Props = {
surveyTripCategoryMetric : {[key: string]: SurveyObject}
}
const SurveyTripCategoriesCard = ( {surveyTripCategoryMetric}: Props ) => {
const { colors } = useAppTheme();
const { t } = useTranslation();
const records = [
{
label: 'Response',
x: 'EV Roaming trip',
y: 20,
},
{
label: 'No Response',
x: 'EV Roaming trip',
y: 20,
},
{
label: 'Response',
x: 'EV Return trip',
y: 30,
},
{
label: 'No Response',
x: 'EV Return trip',
y: 40,
},
{
label: 'Response',
x: 'Gas Car trip',
y: 50,
},
{
label: 'No Response',
x: 'Gas Car trip',
y: 10,
},
];
const records: SurveyTripRecord[] = [];

for(const category in surveyTripCategoryMetric) {
const metricByCategory = surveyTripCategoryMetric[category];
for(const key in metricByCategory) {
// we don't consider "mismatched" survey result for now
if(key === "mismatched") continue;
records.push({
label: key === 'answered' ? 'Response' : 'No Response',
x: category,
y: metricByCategory[key]
})
}
}

return (
<Card style={cardStyles.card} contentStyle={{ flex: 1 }}>
Expand Down

0 comments on commit 8150e95

Please sign in to comment.