Files
Chromacase/front/components/ScoreGraph.tsx

206 lines
5.5 KiB
TypeScript

import { Box, Flex, Select, useBreakpointValue, useTheme, Wrap } from 'native-base';
import { LineChart } from 'react-native-chart-kit';
import { useState } from 'react';
import { useWindowDimensions } from 'react-native';
import { useQuery } from '../Queries';
import API from '../API';
import { LoadingView } from './Loading';
const formatScoreDate = (playDate: Date): string => {
// const formattedDate = `${pad(playDate.getDay())}/${pad(playDate.getMonth())}`;
// const formattedTime = `${pad(playDate.getHours())}:${pad(playDate.getMinutes())}`;
// console.log(playDate.toDateString());
// console.log(`${playDate.getDate()}/${playDate.getMonth() + 1}`);
return `${playDate.getDate()}`;
};
type GraphProps = {
songId: number;
since: Date;
};
const calculateDailyAverages = (
scores: { playDate: Date; score: number }[]
): { playDate: Date; score: number }[] => {
const dailyScores: { [key: string]: number[] } = {};
// Regroupez les scores par date
scores.forEach((score) => {
const date = score.playDate.toISOString().split('T')[0] as string; // Obtenez la date au format 'YYYY-MM-DD'
if (!dailyScores[date]) {
dailyScores[date] = [];
}
dailyScores[date]!.push(score.score);
});
// Calculez la moyenne des scores par jour et créez un tableau d'objets avec le format final
const dailyAverages: { playDate: Date; score: number }[] = [];
Object.keys(dailyScores).forEach((date) => {
const oneDayScore = dailyScores[date];
if (oneDayScore) {
const average =
oneDayScore.reduce((total, score) => total + score, 0) / oneDayScore.length;
dailyAverages.push({ playDate: new Date(date), score: average });
}
});
return dailyAverages;
};
const Graph = ({ songId, since }: GraphProps) => {
const isSmall = useBreakpointValue({ base: true, md: false });
const theme = useTheme();
const [containerWidth, setContainerWidth] = useState(0);
const scoresQuery = useQuery(API.getSongHistory(songId), { refetchOnWindowFocus: true });
if (!scoresQuery.data) {
return <LoadingView />;
}
const dailyScore = calculateDailyAverages(scoresQuery.data.history);
const scoresToSort = dailyScore.filter((item: { playDate: Date }) => item.playDate >= since);
const scores = scoresToSort.sort((a, b) => {
if (a.playDate < b.playDate) {
return -1;
} else if (a.playDate > b.playDate) {
return 1;
}
return 0;
});
console.log(scores);
return (
<Box
style={{ width: '100%', marginTop: 20 }}
onLayout={(event) => setContainerWidth(event.nativeEvent.layout.width)}
>
{scores && scores.length > 0 && (
<LineChart
data={{
labels: isSmall
? []
: scores.map(({ playDate }) => formatScoreDate(playDate)),
datasets: [
{
data: scores.map(({ score }) => score),
},
],
}}
width={containerWidth}
height={300} // Completely arbitrary
transparent={true}
yAxisSuffix=" pts"
chartConfig={{
propsForLabels: {
fontFamily: 'Lexend',
},
// propsForVerticalLabels: {
// rotation: -90,
// },
propsForBackgroundLines: {
strokeDasharray: '',
strokeWidth: '1',
color: '#fff000',
},
decimalPlaces: 0,
color: (opacity = 1) => `rgba(255, 255, 255, ${opacity})`,
labelColor: () => theme.colors.white,
propsForDots: {
r: '6',
strokeWidth: '2',
},
}}
bezier
/>
)}
</Box>
);
};
const ScoreGraph = () => {
const layout = useWindowDimensions();
const songs = useQuery(API.getAllSongs());
const rangeOptions = [
{ label: '3 derniers jours', value: '3days' },
{ label: 'Dernière semaine', value: 'week' },
{ label: 'Dernier mois', value: 'month' },
];
const { colors } = useTheme();
const threeDaysAgo = new Date();
threeDaysAgo.setDate(threeDaysAgo.getDate() - 3);
const oneWeekAgo = new Date();
oneWeekAgo.setDate(oneWeekAgo.getDate() - 7);
const oneMonthAgo = new Date();
oneMonthAgo.setDate(1);
const [selectedSinceDate, setSelectedSinceDate] = useState(threeDaysAgo);
const [selectedSong, setSelectedSong] = useState<number | undefined>(0);
if (!songs.data) {
return <LoadingView />;
}
const setSelectedRange = (selectedRange: string) => {
switch (selectedRange) {
case 'week':
setSelectedSinceDate(oneWeekAgo);
break;
case 'month':
setSelectedSinceDate(oneMonthAgo);
break;
default:
setSelectedSinceDate(threeDaysAgo);
break;
}
};
return (
<Flex flex={1}>
<Wrap style={{ gap: 16, flexDirection: 'row', justifyContent: 'flex-end' }}>
<Box>
<Select
onValueChange={(selectedValue) =>
setSelectedSong(
songs.data.find((song) => selectedValue === song.name)?.id
)
}
defaultValue={songs.data.at(0)?.name}
bgColor={colors.coolGray[500]}
variant="filled"
width={layout.width > 650 ? '200' : '150'}
>
{songs.data.map((option) => (
<Select.Item key={option.id} label={option.name} value={option.name} />
))}
</Select>
</Box>
<Box>
<Select
onValueChange={(itemValue) => setSelectedRange(itemValue)}
defaultValue={'3days'}
bgColor={colors.coolGray[500]}
variant="filled"
width={layout.width > 650 ? '200' : '150'}
>
{rangeOptions.map((option) => (
<Select.Item
key={option.label}
label={option.label}
value={option.value}
/>
))}
</Select>
</Box>
</Wrap>
{selectedSong !== undefined && (
<Graph songId={selectedSong} since={selectedSinceDate} />
)}
</Flex>
);
};
export default ScoreGraph;