Front: Merge

This commit is contained in:
Arthur Jamet
2023-05-08 12:55:16 +01:00
5 changed files with 86 additions and 23 deletions

View File

@@ -13,6 +13,7 @@ import { en } from "./i18n/Translations";
import { QueryClient } from "react-query";
import UserSettings from "./models/UserSettings";
import { PartialDeep } from "type-fest";
import SearchHistory from "./models/SearchHistory";
type AuthenticationInput = { username: string; password: string };
type RegistrationInput = AuthenticationInput & { email: string };
@@ -364,15 +365,16 @@ export default class API {
* Retrieve the authenticated user's search history
* @param lessonId the id to find the lesson
*/
public static async getSearchHistory(): Promise<Song[]> {
const queryClient = new QueryClient();
let songs = await queryClient.fetchQuery(
["API", "allsongs"],
API.getAllSongs
);
const shuffled = [...songs].sort(() => 0.5 - Math.random());
public static async getSearchHistory(): Promise<SearchHistory[]> {
const tmp = await this.fetch({
route: "/history/search",
});
return shuffled.slice(0, 2);
return tmp.map((value: any) => ({
query: value.query,
userID: value.userId,
id: value.id,
}));
}
/**

View File

@@ -3,6 +3,7 @@ import { NavigationProp, ParamListBase, useNavigation as navigationHook } from "
import React, { useEffect } from 'react';
import { DarkTheme, DefaultTheme, NavigationContainer } from '@react-navigation/native';
import { RootState, useSelector } from './state/Store';
import { useDispatch } from 'react-redux';
import { Translate, translate } from './i18n/i18n';
import SongLobbyView from './views/SongLobbyView';
import AuthenticationView from './views/AuthenticationView';
@@ -18,7 +19,6 @@ import { LoadingView } from './components/Loading';
import ProfileView from './views/ProfileView';
import useColorScheme from './hooks/colorScheme';
import { Button, Center, VStack } from 'native-base';
import { useDispatch } from 'react-redux';
import { unsetAccessToken } from './state/UserSlice';
import TextButton from './components/TextButton';
@@ -86,10 +86,16 @@ const ProfileErrorView = (props: { onTryAgain: () => any }) => {
}
export const Router = () => {
const dispatch = useDispatch();
const accessToken = useSelector((state: RootState) => state.user.accessToken);
const userProfile = useQuery(['user', 'me', accessToken], () => API.getUserInfo(), {
retry: 1,
refetchOnWindowFocus: false
refetchOnWindowFocus: false,
onError: (err) => {
if (err.status === 401) {
dispatch(unsetAccessToken());
}
},
});
const colorScheme = useColorScheme();

View File

@@ -162,6 +162,9 @@ export const en = {
Attention: 'Attention',
YouAreCurrentlyConnectedWithAGuestAccountWarning: "You are currently connected with a guest account. Disconneting will result in your data being lost. If you want to save your progress, you need to create an account.",
recentSearches: 'Recent searches',
noRecentSearches: 'No recent searches',
};
export const fr: typeof en = {
@@ -323,6 +326,9 @@ export const fr: typeof en = {
Attention: 'Attention',
YouAreCurrentlyConnectedWithAGuestAccountWarning: 'Vous êtes actuellement connecté en tant qu\'invité. La déconnexion résultera en une perte de données. Vous pouvez créer un compte pour sauvegarder vos données.',
recentSearches: 'Recherches récentes',
noRecentSearches: 'Aucune recherche récente',
};
export const sp: typeof en = {
@@ -489,4 +495,7 @@ export const sp: typeof en = {
Attention: 'Atención',
YouAreCurrentlyConnectedWithAGuestAccountWarning: 'Actualmente estás conectado como invitado. La desconexión resultará en la pérdida de datos. Puedes crear una cuenta para guardar tus datos.',
recentSearches: 'Búsquedas recientes',
noRecentSearches: 'No hay búsquedas recientes',
};

View File

@@ -0,0 +1,7 @@
interface SearchHistory {
query: string;
userID: number;
id: number;
}
export default SearchHistory;

View File

@@ -2,17 +2,34 @@ import React from "react";
import { useQueries, useQuery } from "react-query";
import API from "../API";
import { LoadingView } from "../components/Loading";
import { Center, Box, ScrollView, Flex, useBreakpointValue, Stack, Heading, Container, VStack, HStack } from 'native-base';
import {
Center,
Box,
ScrollView,
Flex,
useBreakpointValue,
Stack,
Heading,
Container,
VStack,
HStack,
Column,
Button,
Text,
useTheme
} from "native-base";
import { useNavigation } from "../Navigation";
import SongCardGrid from '../components/SongCardGrid';
import CompetenciesTable from '../components/CompetenciesTable'
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 theme = useTheme();
const navigation = useNavigation();
const screenSize = useBreakpointValue({ base: 'small', md: "big"});
const userQuery = useQuery(['user'], () => API.getUserInfo());
@@ -106,17 +123,39 @@ const HomeView = () => {
/>
</HStack>
<Box style={{ width: '100%' }}>
<SongCardGrid
heading={<Translate translationKey='lastSearched'/>}
songs={searchHistoryQuery.data?.filter((song) => artistsQueries.find((artistQuery) => artistQuery.data?.id === song.artistId))
.map((song) => ({
albumCover: song.cover,
songTitle: song.name,
songId: song.id,
artistName: artistsQueries.find((artistQuery) => artistQuery.data?.id === song.artistId)!.data!.name
})) ?? []
<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)))].reverse().slice(0, 5).map((query) => (
<Button
leftIcon={
<FontAwesome5 name="search" size={16} />
}
style={{
margin: 2,
}}
key={ query }
variant="solid"
size="xs"
colorScheme="primary"
onPress={() => navigation.navigate('Search', { query: query })}
>
<Text fontSize={"xs"} isTruncated maxW={"150px"}>
{ query }
</Text>
</Button>
))
}
</Flex>
</Box>
</VStack>
</Stack>