diff --git a/front/API.ts b/front/API.ts index d7287c7..c44fa87 100644 --- a/front/API.ts +++ b/front/API.ts @@ -151,7 +151,9 @@ export default class API { return response.access_token; } - public static async transformGuestToUser(registrationInput: RegistrationInput): Promise { + public static async transformGuestToUser( + registrationInput: RegistrationInput + ): Promise { await API.fetch({ route: "/auth/me", body: registrationInput, @@ -180,7 +182,7 @@ export default class API { createdAt: new Date("2023-04-09T00:00:00.000Z"), avatar: "https://imgs.search.brave.com/RnQpFhmAFvuQsN_xTw7V-CN61VeHDBg2tkEXnKRYHAE/rs:fit:768:512:1/g:ce/aHR0cHM6Ly96b29h/c3Ryby5jb20vd3At/Y29udGVudC91cGxv/YWRzLzIwMjEvMDIv/Q2FzdG9yLTc2OHg1/MTIuanBn", - } + }, } as User; } @@ -194,16 +196,18 @@ export default class API { pushNotif: settings.pushNotification, emailNotif: settings.emailNotification, trainNotif: settings.trainingNotification, - newSongNotif: settings.newSongNotification + newSongNotif: settings.newSongNotification, }, recommendations: settings.recommendations, weeklyReport: settings.weeklyReport, leaderBoard: settings.leaderBoard, - showActivity: settings.showActivity + showActivity: settings.showActivity, }; } - public static async updateUserSettings(settings: PartialDeep): Promise { + public static async updateUserSettings( + settings: PartialDeep + ): Promise { const dto = { pushNotification: settings.notifications?.pushNotif, emailNotification: settings.notifications?.emailNotif, @@ -213,11 +217,11 @@ export default class API { weeklyReport: settings.weeklyReport, leaderBoard: settings.leaderBoard, showActivity: settings.showActivity, - } + }; return API.fetch({ - method: 'PATCH', - route: '/auth/me/settings', - body: dto + method: "PATCH", + route: "/auth/me/settings", + body: dto, }); } @@ -248,16 +252,16 @@ export default class API { // this is a dummy illustration, we will need to fetch the real one from the API return songs.data.map( (song: any) => - ({ - id: song.id as number, - name: song.name as string, - artistId: song.artistId as number, - albumId: song.albumId as number, - genreId: song.genreId as number, - details: song.difficulties, - cover: getDummyIllustration(), - metrics: {}, - } as Song) + ({ + id: song.id as number, + name: song.name as string, + artistId: song.artistId as number, + albumId: song.albumId as number, + genreId: song.genreId as number, + details: song.difficulties, + cover: getDummyIllustration(), + metrics: {}, + } as Song) ); } @@ -292,6 +296,19 @@ export default class API { }); } + /** + * Retrive a song's midi partition + * @param songId the id to find the song + */ + public static getGenreIllustration(genreId: number): string { + return `${baseAPIUrl}/genre/${genreId}/illustration`; + /* + return API.fetch({ + route: `/genre/${genreId}/illustration`, + raw: true, + });*/ + } + /** * Retrive a song's musicXML partition * @param songId the id to find the song @@ -333,7 +350,9 @@ export default class API { * Retrieve a song's play history * @param songId the id to find the song */ - public static async getSongHistory(songId: number): Promise<{best: number, history: SongHistory[]}> { + public static async getSongHistory( + songId: number + ): Promise<{ best: number; history: SongHistory[] }> { return API.fetch({ route: `/song/${songId}/history`, }); @@ -365,22 +384,22 @@ export default class API { */ public static async searchAlbum(query?: string): Promise { return [ - { - id: 1, - name: "Super Trooper", - }, - { - id: 2, - name: "Kingdom Heart 365/2 OST", - }, - { - id: 3, - name: "The Legend Of Zelda Ocarina Of Time OST", - }, - { - id: 4, - name: "Random Access Memories", - }, + { + id: 1, + name: "Super Trooper", + }, + { + id: 2, + name: "Kingdom Heart 365/2 OST", + }, + { + id: 3, + name: "The Legend Of Zelda Ocarina Of Time OST", + }, + { + id: 4, + name: "Random Access Memories", + }, ] as Album[]; } @@ -413,19 +432,24 @@ export default class API { * @param take how much do we take to return * @returns Returns an array of history entries (temporary type any) */ - public static async getSearchHistory(skip?: number, take?: number): Promise { - return (await API.fetch({ - route: `/history/search?skip=${skip ?? 0}&take=${take ?? 5}`, - method: "GET", - })).map((e: any) => { + public static async getSearchHistory( + skip?: number, + take?: number + ): Promise { + return ( + await API.fetch({ + route: `/history/search?skip=${skip ?? 0}&take=${take ?? 5}`, + method: "GET", + }) + ).map((e: any) => { return { id: e.id, query: e.query, type: e.type, userId: e.userId, timestamp: new Date(e.searchDate), - } as SearchHistory - }) + } as SearchHistory; + }); } /** @@ -435,15 +459,19 @@ export default class API { * @param timestamp the date it's been issued * @returns nothing */ - public static async createSearchHistoryEntry(query: string, type: string, timestamp: number): Promise { + public static async createSearchHistoryEntry( + query: string, + type: string, + timestamp: number + ): Promise { return await API.fetch({ route: `/history/search`, method: "POST", body: { query: query, - type: type + type: type, }, - }) + }); } /** @@ -461,7 +489,7 @@ export default class API { */ public static async getUserPlayHistory(): Promise { return this.fetch({ - route: '/history' + route: "/history", }); } diff --git a/front/components/GenreCard.tsx b/front/components/GenreCard.tsx index 40784a2..2acc032 100644 --- a/front/components/GenreCard.tsx +++ b/front/components/GenreCard.tsx @@ -1,25 +1,22 @@ import React from "react"; -import Card from './Card'; -import { VStack, Text, Box, Icon } from 'native-base'; +import Card from "./Card"; +import { VStack, Text, Box, Icon, Image } from "native-base"; import { useTheme } from "native-base"; import { Ionicons } from "@expo/vector-icons"; import API from "../API"; type GenreCardProps = { icon: string; name: string; + id: number; onPress: () => void; -} +}; const GenreCard = (props: GenreCardProps) => { - const { icon, name } = props; + const { icon, name, id } = props; const theme = useTheme(); - return ( - + { alignItems="center" justifyContent="center" > - + @@ -40,12 +42,12 @@ const GenreCard = (props: GenreCardProps) => { ); -} +}; GenreCard.defaultProps = { - icon: 'https://picsum.photos/200', - name: 'Genre', - onPress: () => { } -} + icon: "https://picsum.photos/200", + name: "Genre", + onPress: () => { }, +}; -export default GenreCard; \ No newline at end of file +export default GenreCard; diff --git a/front/components/SearchResult.tsx b/front/components/SearchResult.tsx index 39481ff..7bf3ccb 100644 --- a/front/components/SearchResult.tsx +++ b/front/components/SearchResult.tsx @@ -11,9 +11,10 @@ import { Flex, useBreakpointValue, Column, - ScrollView} from "native-base"; + ScrollView, +} from "native-base"; import { SafeAreaView, useColorScheme } from "react-native"; -import { RootState, useSelector } from '../state/Store'; +import { RootState, useSelector } from "../state/Store"; import { SearchContext } from "../views/SearchView"; import { useQuery } from "react-query"; import { translate } from "../i18n/i18n"; @@ -33,29 +34,39 @@ const swaToSongCardProps = (song: SongWithArtist) => ({ songId: song.id, name: song.name, artistName: song.artist.name, - cover: song.cover ?? 'https://picsum.photos/200', + cover: song.cover ?? "https://picsum.photos/200", }); -const RowCustom = (props: Parameters[0] & { onPress?: () => void }) => { +const RowCustom = ( + props: Parameters[0] & { onPress?: () => void } +) => { const settings = useSelector((state: RootState) => state.settings.local); const systemColorMode = useColorScheme(); const colorScheme = settings.colorScheme; - return - {({ isHovered, isPressed }) => ( - - { props.children } - - )} - -} + return ( + + {({ isHovered, isPressed }) => ( + + {props.children} + + )} + + ); +}; type SongRowProps = { song: Song | SongWithArtist; // TODO: remove Song @@ -63,155 +74,205 @@ type SongRowProps = { }; const SongRow = ({ song, onPress }: SongRowProps) => { - return ( - - {song.name} - - + {song.name} + + {song.name} - + {song.name} + + {song.artistId ?? 'artist'} - - + }} + fontSize={"sm"} + > + {song.artistId ?? "artist"} + + + ); -} +}; SongRow.defaultProps = { - onPress: () => {}, + onPress: () => { }, }; const HomeSearchComponent = () => { - const {stringQuery, updateStringQuery} = React.useContext(SearchContext); - const {isLoading: isLoadingHistory, data: historyData = []} = useQuery( - 'history', - () => API.getSearchHistory(0, 12), - { enabled: true }, - ); + const { stringQuery, updateStringQuery } = React.useContext(SearchContext); + const { isLoading: isLoadingHistory, data: historyData = [] } = useQuery( + "history", + () => API.getSearchHistory(0, 12), + { enabled: true } + ); - const {isLoading: isLoadingSuggestions, data: suggestionsData = []} = useQuery( - 'suggestions', - () => getSongWArtistSuggestions(), - { enabled: true }, - ); + const { isLoading: isLoadingSuggestions, data: suggestionsData = [] } = + useQuery("suggestions", () => getSongWArtistSuggestions(), { + enabled: true, + }); return ( - + - {translate('lastSearched')} - { isLoadingHistory ? : { - return { - ...h, - timestamp: h.timestamp.toLocaleString(), - onPress: () => {updateStringQuery(h.query)} - } - })} cardComponent={SearchHistoryCard}/> } + {translate("lastSearched")} + {isLoadingHistory ? ( + + ) : ( + { + return { + ...h, + timestamp: h.timestamp.toLocaleString(), + onPress: () => { + updateStringQuery(h.query); + }, + }; + })} + cardComponent={SearchHistoryCard} + /> + )} - {translate('songsToGetBetter')} - { isLoadingSuggestions ? : } + {translate("songsToGetBetter")} + {isLoadingSuggestions ? ( + + ) : ( + + )} ); -} +}; const SongsSearchComponent = (props: any) => { - const {songData} = React.useContext(SearchContext); + const { songData } = React.useContext(SearchContext); const navigation = useNavigation(); return ( - - - {translate('songsFilter')} - - - {songData?.length ? ( - songData.slice(0, props.maxRows).map((comp, index) => ( - { - API.createSearchHistoryEntry(comp.name, "song", Date.now()); - navigation.navigate('Song', { songId: comp.id }); - }} - /> - )) - ) : ( - {translate('errNoResults')} - )} - - + + + {translate("songsFilter")} + + + {songData?.length ? ( + songData.slice(0, props.maxRows).map((comp, index) => ( + { + API.createSearchHistoryEntry(comp.name, "song", Date.now()); + navigation.navigate("Song", { songId: comp.id }); + }} + /> + )) + ) : ( + {translate("errNoResults")} + )} + + ); -} +}; const ArtistSearchComponent = (props: any) => { - const {artistData} = React.useContext(SearchContext); + const { artistData } = React.useContext(SearchContext); const navigation = useNavigation(); return ( - {translate('artistFilter')} + {translate("artistFilter")} - { artistData?.length - ? ( - { - image: a.picture ?? 'https://picsum.photos/200', - name: a.name, - id: a.id, - onPress: () => { - API.createSearchHistoryEntry(a.name, "artist", Date.now()); - navigation.navigate('Artist', { artistId: a.id }) - } - } - ))} cardComponent={ArtistCard} /> - : {translate('errNoResults')} } + {artistData?.length ? ( + ({ + image: a.picture ?? "https://picsum.photos/200", + name: a.name, + id: a.id, + onPress: () => { + API.createSearchHistoryEntry(a.name, "artist", Date.now()); + navigation.navigate("Artist", { artistId: a.id }); + }, + }))} + cardComponent={ArtistCard} + /> + ) : ( + {translate("errNoResults")} + )} ); -} +}; const GenreSearchComponent = (props: any) => { - const {genreData} = React.useContext(SearchContext); + const { genreData } = React.useContext(SearchContext); const navigation = useNavigation(); return ( - {translate('genreFilter')} + {translate("genreFilter")} - { genreData?.length - ? ( - { - icon: 'musical-note-sharp', - name: g.name, - onPress: () => { - API.createSearchHistoryEntry(g.name, "genre", Date.now()); - navigation.navigate('Home'); - } - } - ))} cardComponent={GenreCard}/> - : {translate('errNoResults')} } + {genreData?.length ? ( + ({ + icon: "musical-note-sharp", + name: g.name, + id: g.id, + onPress: () => { + API.createSearchHistoryEntry(g.name, "genre", Date.now()); + navigation.navigate("Home"); + }, + }))} + cardComponent={GenreCard} + /> + ) : ( + {translate("errNoResults")} + )} ); -} +}; const AllComponent = () => { const screenSize = useBreakpointValue({ base: "small", md: "big" }); @@ -219,22 +280,27 @@ const AllComponent = () => { return ( - - + + - + - + - - + + ); -} +}; const FilterSwitch = () => { const { filter } = React.useContext(SearchContext); @@ -270,4 +336,4 @@ export const SearchResultComponent = (props: any) => { ) : ( ); -}; \ No newline at end of file +};