Front: Home Page: Basic Responsive Layout
This commit is contained in:
committed by
Clément Le Bihan
parent
2bed2e1c64
commit
8a332ede38
@@ -1,6 +1,6 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { translate } from "../i18n/i18n";
|
import { translate } from "../i18n/i18n";
|
||||||
import { Box, useBreakpointValue, Text, VStack, Progress } from 'native-base';
|
import { Box, useBreakpointValue, Text, VStack, Progress, Stack, AspectRatio } from 'native-base';
|
||||||
import { useNavigation } from "@react-navigation/native";
|
import { useNavigation } from "@react-navigation/native";
|
||||||
import { Pressable, Image } from "native-base";
|
import { Pressable, Image } from "native-base";
|
||||||
import Card from "../components/Card";
|
import Card from "../components/Card";
|
||||||
@@ -12,27 +12,23 @@ const ProgressBar = ({ xp }: { xp: number}) => {
|
|||||||
const progessValue = 100 * xp / nextLevelThreshold;
|
const progessValue = 100 * xp / nextLevelThreshold;
|
||||||
|
|
||||||
const nav = useNavigation();
|
const nav = useNavigation();
|
||||||
const flexDirection = useBreakpointValue({ base: 'column', xl: "row"});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card w="90%" maxW='500' style={{flexDirection}}
|
<Card w="100%" onPress={() => nav.navigate('User')} >
|
||||||
onPress={() => nav.navigate('User')}
|
<Stack padding={4} space={2} direction="row">
|
||||||
>
|
<AspectRatio ratio={1}>
|
||||||
<Box w="20%" paddingRight={2} paddingLeft={2} paddingY={2}>
|
<Image position="relative" borderRadius={100} source={{
|
||||||
<Image borderRadius={100} source={{
|
uri: "https://wallpaperaccess.com/full/317501.jpg" // TODO : put the actual profile pic
|
||||||
uri: "https://wallpaperaccess.com/full/317501.jpg" // TODO : put the actual profile pic
|
}} alt="Profile picture" zIndex={0}/>
|
||||||
}} alt="Profile picture" size="sm"
|
</AspectRatio>
|
||||||
/>
|
<VStack alignItems={'center'} flexGrow={1} space={2}>
|
||||||
</Box>
|
|
||||||
<Box w='80%' paddingY={4}>
|
|
||||||
<VStack alignItems={'center'}>
|
|
||||||
<Text>{`${translate('level')} ${level}`}</Text>
|
<Text>{`${translate('level')} ${level}`}</Text>
|
||||||
<Box w="100%">
|
<Box w="100%">
|
||||||
<Progress value={progessValue} mx="4" />
|
<Progress value={progessValue} mx="4" />
|
||||||
</Box>
|
</Box>
|
||||||
<Text>{xp} / {nextLevelThreshold} {translate('levelProgress')}</Text>
|
<Text>{xp} / {nextLevelThreshold} {translate('levelProgress')}</Text>
|
||||||
</VStack>
|
</VStack>
|
||||||
</Box>
|
</Stack>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,16 +2,18 @@ import React from 'react';
|
|||||||
import SongCard from './SongCard';
|
import SongCard from './SongCard';
|
||||||
import { FlatGrid } from 'react-native-super-grid';
|
import { FlatGrid } from 'react-native-super-grid';
|
||||||
import { Heading, VStack } from 'native-base';
|
import { Heading, VStack } from 'native-base';
|
||||||
|
import { RequireExactlyOne } from 'type-fest';
|
||||||
|
|
||||||
type SongCardGrid = {
|
type SongCardGrid = {
|
||||||
songs: Parameters<typeof SongCard>[0][];
|
songs: Parameters<typeof SongCard>[0][];
|
||||||
maxItemsPerRow?: number,
|
|
||||||
itemDimension?: number,
|
|
||||||
heading?: JSX.Element,
|
heading?: JSX.Element,
|
||||||
}
|
} & RequireExactlyOne<{
|
||||||
|
maxItemsPerRow: number,
|
||||||
|
itemDimension: number,
|
||||||
|
}>
|
||||||
|
|
||||||
const SongCardGrid = (props: SongCardGrid) => {
|
const SongCardGrid = (props: SongCardGrid) => {
|
||||||
return <VStack>
|
return <VStack space={5}>
|
||||||
<Heading>{props.heading}</Heading>
|
<Heading>{props.heading}</Heading>
|
||||||
<FlatGrid
|
<FlatGrid
|
||||||
maxItemsPerRow={props.maxItemsPerRow}
|
maxItemsPerRow={props.maxItemsPerRow}
|
||||||
|
|||||||
+72
-74
@@ -2,7 +2,7 @@ import React from "react";
|
|||||||
import { useQueries, useQuery } from "react-query";
|
import { useQueries, useQuery } from "react-query";
|
||||||
import API from "../API";
|
import API from "../API";
|
||||||
import LoadingComponent from "../components/Loading";
|
import LoadingComponent from "../components/Loading";
|
||||||
import { Box, ScrollView, Flex, useBreakpointValue, Text, VStack, Button, Heading } from 'native-base';
|
import { Center, Box, ScrollView, Flex, useBreakpointValue, Stack, Heading, Container, VStack, HStack } from 'native-base';
|
||||||
import { useNavigation } from "@react-navigation/native";
|
import { useNavigation } from "@react-navigation/native";
|
||||||
import SongCardGrid from '../components/SongCardGrid';
|
import SongCardGrid from '../components/SongCardGrid';
|
||||||
import CompetenciesTable from '../components/CompetenciesTable'
|
import CompetenciesTable from '../components/CompetenciesTable'
|
||||||
@@ -13,7 +13,6 @@ import TextButton from "../components/TextButton";
|
|||||||
const HomeView = () => {
|
const HomeView = () => {
|
||||||
const navigation = useNavigation();
|
const navigation = useNavigation();
|
||||||
const screenSize = useBreakpointValue({ base: 'small', md: "big"});
|
const screenSize = useBreakpointValue({ base: 'small', md: "big"});
|
||||||
const flexDirection = useBreakpointValue({ base: 'column', xl: "row"});
|
|
||||||
const userQuery = useQuery(['user'], () => API.getUserInfo());
|
const userQuery = useQuery(['user'], () => API.getUserInfo());
|
||||||
const playHistoryQuery = useQuery(['history', 'play'], () => API.getUserPlayHistory());
|
const playHistoryQuery = useQuery(['history', 'play'], () => API.getUserPlayHistory());
|
||||||
const searchHistoryQuery = useQuery(['history', 'search'], () => API.getSearchHistory());
|
const searchHistoryQuery = useQuery(['history', 'search'], () => API.getSearchHistory());
|
||||||
@@ -22,28 +21,82 @@ const HomeView = () => {
|
|||||||
const artistsQueries = useQueries((playHistoryQuery.data?.concat(searchHistoryQuery.data ?? []).concat(nextStepQuery.data ?? []) ?? []).map((song) => (
|
const artistsQueries = useQueries((playHistoryQuery.data?.concat(searchHistoryQuery.data ?? []).concat(nextStepQuery.data ?? []) ?? []).map((song) => (
|
||||||
{ queryKey: ['artist', song.id], queryFn: () => API.getArtist(song.id) }
|
{ queryKey: ['artist', song.id], queryFn: () => API.getArtist(song.id) }
|
||||||
)));
|
)));
|
||||||
|
|
||||||
if (!userQuery.data || !skillsQuery.data || !searchHistoryQuery.data || !playHistoryQuery.data) {
|
if (!userQuery.data || !skillsQuery.data || !searchHistoryQuery.data || !playHistoryQuery.data) {
|
||||||
return <Box style={{ flexGrow: 1, justifyContent: 'center' }}>
|
return <Center style={{ flexGrow: 1 }}>
|
||||||
<LoadingComponent/>
|
<LoadingComponent/>
|
||||||
</Box>
|
</Center>
|
||||||
}
|
}
|
||||||
return <ScrollView>
|
return <ScrollView p={10}>
|
||||||
<Box style={{ display: 'flex', padding: 30 }}>
|
<Flex>
|
||||||
<Box textAlign={ screenSize == 'small' ? 'center' : undefined } style={{ flexDirection, justifyContent: 'center', display: 'flex' }}>
|
<Stack space={4}
|
||||||
<Text fontSize="xl" flex={screenSize == 'small' ? 1 : 2}>
|
display={{ base: 'block', md: 'flex' }}
|
||||||
<Translate translationKey="welcome" format={(welcome) => `${welcome} ${userQuery.data.name}!`}/>
|
direction={{ base: 'column', md: 'row' }}
|
||||||
</Text>
|
textAlign={{ base: 'center', md: 'inherit' }}
|
||||||
|
justifyContent="space-evenly"
|
||||||
|
>
|
||||||
|
<Translate fontSize="xl" flex={2}
|
||||||
|
translationKey="welcome" format={(welcome) => `${welcome} ${userQuery.data.name}!`}
|
||||||
|
/>
|
||||||
<Box flex={1}>
|
<Box flex={1}>
|
||||||
<ProgressBar xp={userQuery.data.xp}/>
|
<ProgressBar xp={userQuery.data.xp}/>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Stack>
|
||||||
|
</Flex>
|
||||||
<Box paddingY={5} style={{ flexDirection }}>
|
<Stack direction={{ base: 'column', lg: 'row' }} height="100%" space={5}>
|
||||||
<Box flex={2}>
|
<VStack flex={{ lg: 2 }} space={5}>
|
||||||
|
<SongCardGrid
|
||||||
|
heading={<Translate translationKey='goNextStep'/>}
|
||||||
|
itemDimension={screenSize == 'small' ? 200 : 170}
|
||||||
|
songs={nextStepQuery.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
|
||||||
|
})) ?? []
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Stack direction={{ base: 'column', lg: 'row' }}>
|
||||||
|
<Box flex={{ md: 1 }}>
|
||||||
|
<Heading><Translate translationKey='mySkillsToImprove'/></Heading>
|
||||||
|
<Box padding={5}>
|
||||||
|
<CompetenciesTable {...skillsQuery.data}/>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
<Box flex={{ md: 1 }}>
|
||||||
|
<SongCardGrid
|
||||||
|
heading={<Translate translationKey='recentlyPlayed'/>}
|
||||||
|
itemDimension={screenSize == 'small' ? 200 : 170}
|
||||||
|
songs={playHistoryQuery.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
|
||||||
|
})) ?? []
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</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%' }}>
|
||||||
<SongCardGrid
|
<SongCardGrid
|
||||||
heading={<Translate translationKey='goNextStep'/>}
|
itemDimension={screenSize == 'small' ? 200 : 170}
|
||||||
itemDimension={screenSize == 'small' ? 250 : 200}
|
heading={<Translate translationKey='lastSearched'/>}
|
||||||
songs={nextStepQuery.data?.filter((song) => artistsQueries.find((artistQuery) => artistQuery.data?.id === song.artistId))
|
songs={searchHistoryQuery.data?.filter((song) => artistsQueries.find((artistQuery) => artistQuery.data?.id === song.artistId))
|
||||||
.map((song) => ({
|
.map((song) => ({
|
||||||
albumCover: song.cover,
|
albumCover: song.cover,
|
||||||
songTitle: song.name,
|
songTitle: song.name,
|
||||||
@@ -52,65 +105,10 @@ const HomeView = () => {
|
|||||||
})) ?? []
|
})) ?? []
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Flex style={{ flexDirection }}>
|
|
||||||
<Box flex={1} paddingY={5}>
|
|
||||||
<Heading><Translate translationKey='mySkillsToImprove'/></Heading>
|
|
||||||
<Box padding={5}>
|
|
||||||
<CompetenciesTable {...skillsQuery.data}/>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
<Box flex={1} padding={5}>
|
|
||||||
<SongCardGrid
|
|
||||||
heading={<Translate translationKey='recentlyPlayed'/>}
|
|
||||||
itemDimension={screenSize == 'small' ? 200 : 170}
|
|
||||||
songs={playHistoryQuery.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
|
|
||||||
})) ?? []
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
</Flex>
|
|
||||||
</Box>
|
</Box>
|
||||||
|
</VStack>
|
||||||
|
</Stack>
|
||||||
|
|
||||||
<VStack padding={5} flex={1} space={10}>
|
|
||||||
<Box style={{flexDirection: 'row'}}>
|
|
||||||
|
|
||||||
<Box flex="2" padding={5}>
|
|
||||||
<Box style={{ flexDirection: 'row', justifyContent:'center' }}>
|
|
||||||
<TextButton
|
|
||||||
translate={{ translationKey: 'searchBtn' }}
|
|
||||||
colorScheme='secondary' size="sm"
|
|
||||||
onPress={() => navigation.navigate('Search')}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
<SongCardGrid
|
|
||||||
itemDimension={screenSize == 'small' ? 150 : 120}
|
|
||||||
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
|
|
||||||
})) ?? []
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
<Box style={{ flexDirection: 'row', justifyContent:'center' }}>
|
|
||||||
<TextButton translate={{ translationKey: 'settingsBtn' }}
|
|
||||||
size="sm" onPress={() => navigation.navigate('Settings')}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
</VStack>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user