Files
Chromacase/front/views/HomeView.tsx
2023-06-17 07:01:23 +01:00

190 lines
5.5 KiB
TypeScript

import React from 'react';
import { useQueries, useQuery } from 'react-query';
import API from '../API';
import { LoadingView } from '../components/Loading';
import { Box, ScrollView, Flex, Stack, Heading, VStack, HStack } from 'native-base';
import { useNavigation } from '../Navigation';
import SongCardGrid from '../components/SongCardGrid';
import CompetenciesTable from '../components/CompetenciesTable';
import ProgressBar from '../components/ProgressBar';
import Translate from '../components/Translate';
import TextButton from '../components/TextButton';
import Song from '../models/Song';
import { FontAwesome5 } from '@expo/vector-icons';
const HomeView = () => {
const navigation = useNavigation();
const userQuery = useQuery(['user'], () => API.getUserInfo());
const playHistoryQuery = useQuery(['history', 'play'], () => API.getUserPlayHistory());
const searchHistoryQuery = useQuery(['history', 'search'], () => API.getSearchHistory(0, 10));
const skillsQuery = useQuery(['skills'], () => API.getUserSkills());
const nextStepQuery = useQuery(['user', 'recommendations'], () => API.getSongSuggestions());
const songHistory = useQueries(
playHistoryQuery.data?.map(({ songID }) => ({
queryKey: ['song', songID],
queryFn: () => API.getSong(songID),
})) ?? []
);
const artistsQueries = useQueries(
songHistory
.map((entry) => entry.data)
.concat(nextStepQuery.data ?? [])
.filter((s): s is Song => s !== undefined)
.map((song) => ({
queryKey: ['artist', song.id],
queryFn: () => API.getArtist(song.artistId),
}))
);
if (
!userQuery.data ||
!skillsQuery.data ||
!searchHistoryQuery.data ||
!playHistoryQuery.data
) {
return <LoadingView />;
}
return (
<ScrollView p={10}>
<Flex>
<Stack
space={4}
display={{ base: 'block', md: 'flex' }}
direction={{ base: 'column', md: 'row' }}
textAlign={{ base: 'center', md: 'inherit' }}
justifyContent="space-evenly"
>
<Translate
fontSize="xl"
flex={2}
translationKey="welcome"
format={(welcome) => `${welcome} ${userQuery.data.name}!`}
/>
<Box flex={1}>
<ProgressBar xp={userQuery.data.data.xp} />
</Box>
</Stack>
</Flex>
<Stack direction={{ base: 'column', lg: 'row' }} height="100%" space={5} paddingTop={5}>
<VStack flex={{ lg: 2 }} space={5}>
<SongCardGrid
heading={<Translate translationKey="goNextStep" />}
songs={
nextStepQuery.data
?.filter((song) =>
artistsQueries.find(
(artistQuery) => artistQuery.data?.id === song.artistId
)
)
.map((song) => ({
cover: song.cover,
name: song.name,
songId: song.id,
artistName: artistsQueries.find(
(artistQuery) => artistQuery.data?.id === song.artistId
)!.data!.name,
})) ?? []
}
/>
<Stack direction={{ base: 'column', lg: 'row' }}>
<Box flex={{ lg: 1 }}>
<Heading>
<Translate translationKey="mySkillsToImprove" />
</Heading>
<Box padding={5}>
<CompetenciesTable {...skillsQuery.data} />
</Box>
</Box>
<Box flex={{ lg: 1 }}>
<SongCardGrid
heading={<Translate translationKey="recentlyPlayed" />}
songs={
songHistory
.map(({ data }) => data)
.filter((data): data is Song => data !== undefined)
.filter(
(song, i, array) =>
array
.map((s) => s.id)
.findIndex((id) => id == song.id) == i
)
.filter((song) =>
artistsQueries.find(
(artistQuery) =>
artistQuery.data?.id === song.artistId
)
)
.map((song) => ({
cover: song.cover,
name: song.name,
songId: song.id,
artistName: artistsQueries.find(
(artistQuery) =>
artistQuery.data?.id === song.artistId
)!.data!.name,
})) ?? []
}
/>
</Box>
</Stack>
</VStack>
<VStack flex={{ lg: 1 }} height={{ lg: '100%' }} alignItems="center">
<HStack width="100%" justifyContent="space-evenly" p={5} space={5}>
<TextButton
translate={{ translationKey: 'searchBtn' }}
colorScheme="secondary"
size="sm"
onPress={() => navigation.navigate('Search', {})}
/>
<TextButton
translate={{ translationKey: 'settingsBtn' }}
colorScheme="gray"
size="sm"
onPress={() => navigation.navigate('Settings')}
/>
</HStack>
<Box style={{ width: '100%' }}>
<Heading>
<Translate translationKey="recentSearches" />
</Heading>
<Flex
padding={3}
style={{
width: '100%',
alignItems: 'flex-start',
alignContent: 'flex-start',
flexDirection: 'row',
flexWrap: 'wrap',
}}
>
{searchHistoryQuery.data?.length === 0 && (
<Translate translationKey="noRecentSearches" />
)}
{[...new Set(searchHistoryQuery.data.map((x) => x.query))]
.slice(0, 5)
.map((query) => (
<TextButton
leftIcon={<FontAwesome5 name="search" size={16} />}
style={{
margin: 2,
}}
key={query}
variant="solid"
size="xs"
colorScheme="primary"
label={query}
onPress={() =>
navigation.navigate('Search', { query: query })
}
/>
))}
</Flex>
</Box>
</VStack>
</Stack>
</ScrollView>
);
};
export default HomeView;