diff --git a/front/API.ts b/front/API.ts index 9b9c776..775887f 100644 --- a/front/API.ts +++ b/front/API.ts @@ -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 { - 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 { + 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, + })); } /** diff --git a/front/Navigation.tsx b/front/Navigation.tsx index 5255564..61ce96a 100644 --- a/front/Navigation.tsx +++ b/front/Navigation.tsx @@ -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(); diff --git a/front/i18n/Translations.ts b/front/i18n/Translations.ts index c211228..68fd756 100644 --- a/front/i18n/Translations.ts +++ b/front/i18n/Translations.ts @@ -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', }; \ No newline at end of file diff --git a/front/models/SearchHistory.ts b/front/models/SearchHistory.ts new file mode 100644 index 0000000..53c162d --- /dev/null +++ b/front/models/SearchHistory.ts @@ -0,0 +1,7 @@ +interface SearchHistory { + query: string; + userID: number; + id: number; +} + +export default SearchHistory; \ No newline at end of file diff --git a/front/views/HomeView.tsx b/front/views/HomeView.tsx index db84211..7cc73c6 100644 --- a/front/views/HomeView.tsx +++ b/front/views/HomeView.tsx @@ -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 = () => { /> - } - 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 - })) ?? [] + + + { + searchHistoryQuery.data?.length === 0 && } - /> + { + [...(new Set(searchHistoryQuery.data.map((x) => x.query)))].reverse().slice(0, 5).map((query) => ( + + )) + } +