feat: front illustration, sorry for linting
This commit is contained in:
committed by
Clément Le Bihan
parent
5843da2d02
commit
7f51582043
+75
-47
@@ -151,7 +151,9 @@ export default class API {
|
||||
return response.access_token;
|
||||
}
|
||||
|
||||
public static async transformGuestToUser(registrationInput: RegistrationInput): Promise<void> {
|
||||
public static async transformGuestToUser(
|
||||
registrationInput: RegistrationInput
|
||||
): Promise<void> {
|
||||
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<UserSettings>): Promise<void> {
|
||||
public static async updateUserSettings(
|
||||
settings: PartialDeep<UserSettings>
|
||||
): Promise<void> {
|
||||
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<Album[]> {
|
||||
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<SearchHistory[]> {
|
||||
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<SearchHistory[]> {
|
||||
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<void> {
|
||||
public static async createSearchHistoryEntry(
|
||||
query: string,
|
||||
type: string,
|
||||
timestamp: number
|
||||
): Promise<void> {
|
||||
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<SongHistory[]> {
|
||||
return this.fetch({
|
||||
route: '/history'
|
||||
route: "/history",
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -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 (
|
||||
<Card
|
||||
shadow={3}
|
||||
onPress={props.onPress}
|
||||
>
|
||||
<Card shadow={3} onPress={props.onPress}>
|
||||
<VStack m={1.5} space={3} alignItems="center">
|
||||
<Box
|
||||
bg={theme.colors.primary[400]}
|
||||
@@ -30,7 +27,12 @@ const GenreCard = (props: GenreCardProps) => {
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
>
|
||||
<Icon size={"md"} as={Ionicons} name={icon} />
|
||||
<Image
|
||||
source={{
|
||||
uri: API.getGenreIllustration(id),
|
||||
}}
|
||||
size="md"
|
||||
/>
|
||||
</Box>
|
||||
<VStack>
|
||||
<Text isTruncated bold fontSize="md" noOfLines={2} height={50}>
|
||||
@@ -40,12 +42,12 @@ const GenreCard = (props: GenreCardProps) => {
|
||||
</VStack>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
GenreCard.defaultProps = {
|
||||
icon: 'https://picsum.photos/200',
|
||||
name: 'Genre',
|
||||
onPress: () => { }
|
||||
}
|
||||
icon: "https://picsum.photos/200",
|
||||
name: "Genre",
|
||||
onPress: () => { },
|
||||
};
|
||||
|
||||
export default GenreCard;
|
||||
export default GenreCard;
|
||||
|
||||
+195
-129
@@ -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<typeof Box>[0] & { onPress?: () => void }) => {
|
||||
const RowCustom = (
|
||||
props: Parameters<typeof Box>[0] & { onPress?: () => void }
|
||||
) => {
|
||||
const settings = useSelector((state: RootState) => state.settings.local);
|
||||
const systemColorMode = useColorScheme();
|
||||
const colorScheme = settings.colorScheme;
|
||||
|
||||
return <Pressable onPress={props.onPress}>
|
||||
{({ isHovered, isPressed }) => (
|
||||
<Box {...props}
|
||||
py={3}
|
||||
my={1}
|
||||
bg={(colorScheme == 'system' ? systemColorMode : colorScheme) == 'dark'
|
||||
? (isHovered || isPressed) ? 'gray.800' : undefined
|
||||
: (isHovered || isPressed) ? 'coolGray.200' : undefined
|
||||
}
|
||||
>
|
||||
{ props.children }
|
||||
</Box>
|
||||
)}
|
||||
</Pressable>
|
||||
}
|
||||
return (
|
||||
<Pressable onPress={props.onPress}>
|
||||
{({ isHovered, isPressed }) => (
|
||||
<Box
|
||||
{...props}
|
||||
py={3}
|
||||
my={1}
|
||||
bg={
|
||||
(colorScheme == "system" ? systemColorMode : colorScheme) == "dark"
|
||||
? isHovered || isPressed
|
||||
? "gray.800"
|
||||
: undefined
|
||||
: isHovered || isPressed
|
||||
? "coolGray.200"
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
{props.children}
|
||||
</Box>
|
||||
)}
|
||||
</Pressable>
|
||||
);
|
||||
};
|
||||
|
||||
type SongRowProps = {
|
||||
song: Song | SongWithArtist; // TODO: remove Song
|
||||
@@ -63,155 +74,205 @@ type SongRowProps = {
|
||||
};
|
||||
|
||||
const SongRow = ({ song, onPress }: SongRowProps) => {
|
||||
|
||||
return (
|
||||
<RowCustom width={"100%"}>
|
||||
<HStack px={2} space={5} justifyContent={"space-between"} >
|
||||
<Image
|
||||
flexShrink={0}
|
||||
flexGrow={0}
|
||||
pl={10}
|
||||
style={{ zIndex: 0, aspectRatio: 1, borderRadius: 5 }}
|
||||
source={{ uri: song.cover ?? 'https://picsum.photos/200' }}
|
||||
alt={song.name}
|
||||
/>
|
||||
<HStack style={{display: 'flex', flexShrink: 1, flexGrow: 1, alignItems: 'center', justifyContent: "flex-start"}} space={6}>
|
||||
<Text style={{
|
||||
<HStack px={2} space={5} justifyContent={"space-between"}>
|
||||
<Image
|
||||
flexShrink={0}
|
||||
flexGrow={0}
|
||||
pl={10}
|
||||
style={{ zIndex: 0, aspectRatio: 1, borderRadius: 5 }}
|
||||
source={{ uri: song.cover ?? "https://picsum.photos/200" }}
|
||||
alt={song.name}
|
||||
/>
|
||||
<HStack
|
||||
style={{
|
||||
display: "flex",
|
||||
flexShrink: 1,
|
||||
flexGrow: 1,
|
||||
alignItems: "center",
|
||||
justifyContent: "flex-start",
|
||||
}}
|
||||
space={6}
|
||||
>
|
||||
<Text
|
||||
style={{
|
||||
flexShrink: 1,
|
||||
}} isTruncated pl={10} maxW={"100%"} bold fontSize='md'>{song.name}</Text>
|
||||
<Text style={{
|
||||
}}
|
||||
isTruncated
|
||||
pl={10}
|
||||
maxW={"100%"}
|
||||
bold
|
||||
fontSize="md"
|
||||
>
|
||||
{song.name}
|
||||
</Text>
|
||||
<Text
|
||||
style={{
|
||||
flexShrink: 0,
|
||||
}} fontSize={"sm"}>{song.artistId ?? 'artist'}</Text>
|
||||
</HStack>
|
||||
<TextButton
|
||||
flexShrink={0}
|
||||
flexGrow={0}
|
||||
translate={{ translationKey: 'playBtn' }}
|
||||
colorScheme='primary' variant={"outline"} size='sm'
|
||||
onPress={onPress}
|
||||
/>
|
||||
}}
|
||||
fontSize={"sm"}
|
||||
>
|
||||
{song.artistId ?? "artist"}
|
||||
</Text>
|
||||
</HStack>
|
||||
<TextButton
|
||||
flexShrink={0}
|
||||
flexGrow={0}
|
||||
translate={{ translationKey: "playBtn" }}
|
||||
colorScheme="primary"
|
||||
variant={"outline"}
|
||||
size="sm"
|
||||
onPress={onPress}
|
||||
/>
|
||||
</HStack>
|
||||
</RowCustom>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
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 (
|
||||
<VStack mt="5" style={{overflow: 'hidden'}}>
|
||||
<VStack mt="5" style={{ overflow: "hidden" }}>
|
||||
<Card shadow={3} mb={5}>
|
||||
<Heading margin={5}>{translate('lastSearched')}</Heading>
|
||||
{ isLoadingHistory ? <LoadingComponent/> : <CardGridCustom content={historyData.map((h) => {
|
||||
return {
|
||||
...h,
|
||||
timestamp: h.timestamp.toLocaleString(),
|
||||
onPress: () => {updateStringQuery(h.query)}
|
||||
}
|
||||
})} cardComponent={SearchHistoryCard}/> }
|
||||
<Heading margin={5}>{translate("lastSearched")}</Heading>
|
||||
{isLoadingHistory ? (
|
||||
<LoadingComponent />
|
||||
) : (
|
||||
<CardGridCustom
|
||||
content={historyData.map((h) => {
|
||||
return {
|
||||
...h,
|
||||
timestamp: h.timestamp.toLocaleString(),
|
||||
onPress: () => {
|
||||
updateStringQuery(h.query);
|
||||
},
|
||||
};
|
||||
})}
|
||||
cardComponent={SearchHistoryCard}
|
||||
/>
|
||||
)}
|
||||
</Card>
|
||||
<Card shadow={3} mt={5} mb={5}>
|
||||
<Heading margin={5}>{translate('songsToGetBetter')}</Heading>
|
||||
{ isLoadingSuggestions ? <LoadingComponent/> : <CardGridCustom content={suggestionsData.map(swaToSongCardProps)} cardComponent={SongCard}/> }
|
||||
<Heading margin={5}>{translate("songsToGetBetter")}</Heading>
|
||||
{isLoadingSuggestions ? (
|
||||
<LoadingComponent />
|
||||
) : (
|
||||
<CardGridCustom
|
||||
content={suggestionsData.map(swaToSongCardProps)}
|
||||
cardComponent={SongCard}
|
||||
/>
|
||||
)}
|
||||
</Card>
|
||||
</VStack>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const SongsSearchComponent = (props: any) => {
|
||||
const {songData} = React.useContext(SearchContext);
|
||||
const { songData } = React.useContext(SearchContext);
|
||||
const navigation = useNavigation();
|
||||
|
||||
return (
|
||||
<ScrollView>
|
||||
<Text fontSize="xl" fontWeight="bold" mt={4}>
|
||||
{translate('songsFilter')}
|
||||
</Text>
|
||||
<Box>
|
||||
{songData?.length ? (
|
||||
songData.slice(0, props.maxRows).map((comp, index) => (
|
||||
<SongRow
|
||||
key={index}
|
||||
song={comp}
|
||||
onPress={() => {
|
||||
API.createSearchHistoryEntry(comp.name, "song", Date.now());
|
||||
navigation.navigate('Song', { songId: comp.id });
|
||||
}}
|
||||
/>
|
||||
))
|
||||
) : (
|
||||
<Text>{translate('errNoResults')}</Text>
|
||||
)}
|
||||
</Box>
|
||||
</ScrollView>
|
||||
<ScrollView>
|
||||
<Text fontSize="xl" fontWeight="bold" mt={4}>
|
||||
{translate("songsFilter")}
|
||||
</Text>
|
||||
<Box>
|
||||
{songData?.length ? (
|
||||
songData.slice(0, props.maxRows).map((comp, index) => (
|
||||
<SongRow
|
||||
key={index}
|
||||
song={comp}
|
||||
onPress={() => {
|
||||
API.createSearchHistoryEntry(comp.name, "song", Date.now());
|
||||
navigation.navigate("Song", { songId: comp.id });
|
||||
}}
|
||||
/>
|
||||
))
|
||||
) : (
|
||||
<Text>{translate("errNoResults")}</Text>
|
||||
)}
|
||||
</Box>
|
||||
</ScrollView>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const ArtistSearchComponent = (props: any) => {
|
||||
const {artistData} = React.useContext(SearchContext);
|
||||
const { artistData } = React.useContext(SearchContext);
|
||||
const navigation = useNavigation();
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Text fontSize="xl" fontWeight="bold" mt={4}>
|
||||
{translate('artistFilter')}
|
||||
{translate("artistFilter")}
|
||||
</Text>
|
||||
{ artistData?.length
|
||||
? <CardGridCustom content={artistData.slice(0, props?.maxItems ?? artistData.length).map((a) => (
|
||||
{
|
||||
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} />
|
||||
: <Text>{translate('errNoResults')}</Text> }
|
||||
{artistData?.length ? (
|
||||
<CardGridCustom
|
||||
content={artistData
|
||||
.slice(0, props?.maxItems ?? artistData.length)
|
||||
.map((a) => ({
|
||||
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}
|
||||
/>
|
||||
) : (
|
||||
<Text>{translate("errNoResults")}</Text>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const GenreSearchComponent = (props: any) => {
|
||||
const {genreData} = React.useContext(SearchContext);
|
||||
const { genreData } = React.useContext(SearchContext);
|
||||
const navigation = useNavigation();
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Text fontSize="xl" fontWeight="bold" mt={4}>
|
||||
{translate('genreFilter')}
|
||||
{translate("genreFilter")}
|
||||
</Text>
|
||||
{ genreData?.length
|
||||
? <CardGridCustom content={genreData.slice(0, props?.maxItems ?? genreData.length).map((g) => (
|
||||
{
|
||||
icon: 'musical-note-sharp',
|
||||
name: g.name,
|
||||
onPress: () => {
|
||||
API.createSearchHistoryEntry(g.name, "genre", Date.now());
|
||||
navigation.navigate('Home');
|
||||
}
|
||||
}
|
||||
))} cardComponent={GenreCard}/>
|
||||
: <Text>{translate('errNoResults')}</Text> }
|
||||
{genreData?.length ? (
|
||||
<CardGridCustom
|
||||
content={genreData
|
||||
.slice(0, props?.maxItems ?? genreData.length)
|
||||
.map((g) => ({
|
||||
icon: "musical-note-sharp",
|
||||
name: g.name,
|
||||
id: g.id,
|
||||
onPress: () => {
|
||||
API.createSearchHistoryEntry(g.name, "genre", Date.now());
|
||||
navigation.navigate("Home");
|
||||
},
|
||||
}))}
|
||||
cardComponent={GenreCard}
|
||||
/>
|
||||
) : (
|
||||
<Text>{translate("errNoResults")}</Text>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const AllComponent = () => {
|
||||
const screenSize = useBreakpointValue({ base: "small", md: "big" });
|
||||
@@ -219,22 +280,27 @@ const AllComponent = () => {
|
||||
|
||||
return (
|
||||
<SafeAreaView>
|
||||
<Flex flexWrap="wrap" direction={isMobileView ? 'column' : 'row'} justifyContent={['flex-start']} mt={4}>
|
||||
<Column w={isMobileView ? '100%' : '50%'}>
|
||||
<Flex
|
||||
flexWrap="wrap"
|
||||
direction={isMobileView ? "column" : "row"}
|
||||
justifyContent={["flex-start"]}
|
||||
mt={4}
|
||||
>
|
||||
<Column w={isMobileView ? "100%" : "50%"}>
|
||||
<Box minH={isMobileView ? 100 : 200}>
|
||||
<ArtistSearchComponent maxItems={6}/>
|
||||
<ArtistSearchComponent maxItems={6} />
|
||||
</Box>
|
||||
<Box minH={isMobileView ? 100 : 200}>
|
||||
<GenreSearchComponent maxItems={6}/>
|
||||
<GenreSearchComponent maxItems={6} />
|
||||
</Box>
|
||||
</Column>
|
||||
<Box w={isMobileView ? '100%' : '50%'}>
|
||||
<SongsSearchComponent maxRows={9}/>
|
||||
<Box w={isMobileView ? "100%" : "50%"}>
|
||||
<SongsSearchComponent maxRows={9} />
|
||||
</Box>
|
||||
</Flex>
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const FilterSwitch = () => {
|
||||
const { filter } = React.useContext(SearchContext);
|
||||
@@ -270,4 +336,4 @@ export const SearchResultComponent = (props: any) => {
|
||||
) : (
|
||||
<HomeSearchComponent />
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user