Merge branch 'feature/adc/#243-leaderboard' into feat/adc/search-view-v2

This commit is contained in:
danis
2023-12-01 15:03:26 +01:00
5 changed files with 173 additions and 100 deletions

View File

@@ -90,7 +90,7 @@ const protectedRoutes = () =>
},
Leaderboard: {
component: Leaderboardiew,
options: { title: translate('leaderboardTitle') },
options: { title: translate('leaderboardTitle'), headerShown: false },
link: '/leaderboard',
},
Error: {

View File

@@ -13,7 +13,7 @@ const menu = [
{ type: 'main', title: 'menuProfile', icon: User, link: 'User' },
{ type: 'main', title: 'menuMusic', icon: Music, link: 'Music' },
{ type: 'main', title: 'menuSearch', icon: SearchNormal1, link: 'Search' },
{ type: 'main', title: 'menuLeaderBoard', icon: Cup, link: 'Score' },
{ type: 'main', title: 'menuLeaderBoard', icon: Cup, link: 'Leaderboard' },
{ type: 'sub', title: 'menuSettings', icon: Setting2, link: 'Settings' },
] as const;

View File

@@ -18,6 +18,7 @@ export const UserValidator = yup
googleID: yup.string().required().nullable(),
isGuest: yup.boolean().required(),
partyPlayed: yup.number().required(),
totalScore: yup.number().required(),
})
.concat(ModelValidator);
@@ -30,6 +31,7 @@ export const UserHandler: ResponseHandler<yup.InferType<typeof UserValidator>, U
premium: false,
data: {
gamesPlayed: value.partyPlayed as number,
totalScore: value.totalScore as number,
xp: 0,
createdAt: new Date('2023-04-09T00:00:00.000Z'),
avatar: `${API.baseUrl}/users/${value.id}/picture`,
@@ -51,7 +53,7 @@ interface User extends Model {
interface UserData {
gamesPlayed: number;
xp: number;
totalScore: number;
totalScore: number;
avatar: string;
createdAt: Date;
}

View File

@@ -122,7 +122,7 @@ const HomeView = (props: RouteProps<{}>) => {
translate={{ translationKey: 'leaderboardTitle' }}
colorScheme="primary"
size="sm"
onPress={() => navigation.navigate('Leaderboard')}
onPress={() => navigation.navigate('Leaderboard', {})}
/>
<TextButton
label={'V2'}

View File

@@ -1,8 +1,11 @@
import { Box, Heading, useBreakpointValue, ScrollView, Text } from 'native-base';
import { useBreakpointValue, ScrollView, Text } from 'native-base';
import { View, Image } from 'react-native';
import { useQuery } from '../Queries';
import API from '../API';
import { Ionicons } from '@expo/vector-icons';
import { LoadingView } from '../components/Loading';
import { useNavigation, RouteProps } from '../Navigation';
import { MedalStar } from 'iconsax-react-native';
import ScaffoldCC from '../components/UI/ScaffoldCC';
import User from '../models/User';
type PodiumCardProps = {
@@ -10,15 +13,21 @@ type PodiumCardProps = {
medalColor: string;
userAvatarUrl: string;
userPseudo: string;
userXp: number;
userLvl: number;
};
const PodiumCardComponent = ({ offset, medalColor, userAvatarUrl, userPseudo, userXp }: PodiumCardProps) => {
const PodiumCardComponent = ({
offset,
medalColor,
userAvatarUrl,
userPseudo,
userLvl,
}: PodiumCardProps) => {
return (
<View
style={{
display: 'flex',
paddingTop: 0 + offset,
paddingTop: offset,
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
@@ -43,10 +52,10 @@ const PodiumCardComponent = ({ offset, medalColor, userAvatarUrl, userPseudo, us
borderRadius: 12,
}}
/>
<Ionicons
style={{ position: 'absolute', top: 106, left: 106 }}
name="medal"
size={24}
<MedalStar
style={{ position: 'absolute', top: 115, left: 115 }}
size="42"
variant="Bold"
color={medalColor}
/>
</View>
@@ -68,22 +77,25 @@ const PodiumCardComponent = ({ offset, medalColor, userAvatarUrl, userPseudo, us
fontWeight: '500',
}}
>
{userXp} LVL
{userLvl} LVL
</Text>
</View>
);
};
type BoardRowProps = {
userAvatarUrl: string;
userPseudo: string;
userXp: number;
}
userLvl: number;
index: number;
};
const BoardRowComponent = () => {
const BoardRowComponent = ({ userAvatarUrl, userPseudo, userLvl, index }: BoardRowProps) => {
return (
<View
style={{
margin: 5,
marginVertical: 5,
marginHorizontal: 10,
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
@@ -105,9 +117,14 @@ const BoardRowComponent = () => {
>
<Image
source={{
uri: 'https://picsum.photos/50/50',
uri: userAvatarUrl,
}}
style={{
width: '100%',
height: '100%',
borderTopLeftRadius: 8,
borderBottomLeftRadius: 8,
}}
style={{ width: '100%', height: '100%' }}
/>
</View>
@@ -115,12 +132,12 @@ const BoardRowComponent = () => {
style={{
fontSize: 16,
fontStyle: 'normal',
flex: '1 1 0',
flex: 1,
marginHorizontal: 10,
fontWeight: '500',
}}
>
Momo est boutain
{userPseudo}
</Text>
<Text
style={{
@@ -130,7 +147,7 @@ const BoardRowComponent = () => {
marginHorizontal: 10,
}}
>
200 LVL
{userLvl} LVL
</Text>
<View
style={{
@@ -151,98 +168,152 @@ const BoardRowComponent = () => {
textAlign: 'center',
}}
>
8
{index + 4}
</Text>
</View>
</View>
);
};
const dummyScores = [
{
id: 1,
},
{
id: 2,
},
{
id: 3,
},
{
id: 4,
},
{
id: 5,
},
{
id: 6,
},
{
id: 7,
},
{
id: 8,
},
{
id: 9,
},
];
const Leaderboardiew = (props: RouteProps<Record<string, never>>) => {
const navigation = useNavigation();
const scoresQuery = useQuery(API.getTopTwentyPlayers());
const screenSize = useBreakpointValue({ base: 'small', md: 'big' });
const isPhone = screenSize === 'small';
const Leaderboardiew = () => {
const scoresQuery = useQuery(API.getTopTwentyPlayers);
if (scoresQuery.isError) {
navigation.navigate('Error');
return <></>;
}
if (scoresQuery.data === undefined) {
return (
<ScaffoldCC routeName={props.route.name}>
<LoadingView />
</ScaffoldCC>
);
}
return (
<ScrollView style={{ marginBottom: 5 }}>
<View
style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'flex-start',
flex: 1,
flexGrow: 1,
flexShrink: 0,
flexBasis: 0,
alignSelf: 'stretch',
}}
>
<View /** podium view */
<ScaffoldCC routeName={props.route.name}>
<ScrollView style={{ marginBottom: 5 }}>
<View
style={{
display: 'flex',
paddingBottom: 0,
justifyContent: 'center',
alignItems: 'center',
flexDirection: 'column',
alignItems: 'flex-start',
flex: 1,
flexGrow: 1,
flexShrink: 0,
flexBasis: 0,
alignSelf: 'stretch',
flexDirection: 'row',
marginBottom: 20,
}}
>
<PodiumCardComponent
medalColor="#AE84FB"
offset={80}
userAvatarUrl={scoresQuery.data?.at(2)?.data.avatar ?? "fake image"}
userPseudo={scoresQuery.data?.at(2)?.name ?? "Momo"}
userXp={scoresQuery.data?.at(2)?.data.xp ?? 0}
/>
<PodiumCardComponent
medalColor="#EAD93C"
offset={0}
userAvatarUrl={scoresQuery.data?.at(0)?.data.avatar ?? "fake image"}
userPseudo={scoresQuery.data?.at(0)?.name ?? "Momo"}
userXp={scoresQuery.data?.at(0)?.data.xp ?? 0}
/>
<PodiumCardComponent
medalColor="#5F74F7"
offset={60}
userAvatarUrl={scoresQuery.data?.at(1)?.data.avatar ?? "fake image"}
userPseudo={scoresQuery.data?.at(1)?.name ?? "Momo"}
userXp={scoresQuery.data?.at(1)?.data.xp ?? 0}
/>
{!isPhone ? (
<View /** podium view */
style={{
display: 'flex',
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
alignSelf: 'stretch',
paddingBottom: 10,
marginBottom: 20,
}}
>
<PodiumCardComponent
medalColor="#AE84FB"
offset={80}
userAvatarUrl={
scoresQuery.data?.at(2)?.data.avatar ??
'https://picsum.photos/140/140'
}
userPseudo={scoresQuery.data?.at(2)?.name ?? '---'}
userLvl={scoresQuery.data?.at(2)?.data.totalScore ?? 42}
/>
<PodiumCardComponent
medalColor="#EAD93C"
offset={0}
userAvatarUrl={
scoresQuery.data?.at(0)?.data.avatar ??
'https://picsum.photos/140/140'
}
userPseudo={scoresQuery.data?.at(0)?.name ?? '---'}
userLvl={scoresQuery.data?.at(0)?.data.totalScore ?? 42}
/>
<PodiumCardComponent
medalColor="#5F74F7"
offset={60}
userAvatarUrl={
scoresQuery.data?.at(1)?.data.avatar ??
'https://picsum.photos/140/140'
}
userPseudo={scoresQuery.data?.at(1)?.name ?? '---'}
userLvl={scoresQuery.data?.at(1)?.data.totalScore ?? 42}
/>
</View>
) : (
<View
style={{
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
alignSelf: 'stretch',
}}
>
<PodiumCardComponent
medalColor="#AE84FB"
offset={80}
userAvatarUrl={
scoresQuery.data?.at(0)?.data.avatar ??
'https://picsum.photos/140/140'
}
userPseudo={scoresQuery.data?.at(0)?.name ?? '---'}
userLvl={scoresQuery.data?.at(0)?.data.totalScore ?? 42}
/>
<View
style={{
display: 'flex',
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
}}
>
<PodiumCardComponent
medalColor="#EAD93C"
offset={0}
userAvatarUrl={
scoresQuery.data?.at(1)?.data.avatar ??
'https://picsum.photos/140/140'
}
userPseudo={scoresQuery.data?.at(1)?.name ?? '---'}
userLvl={scoresQuery.data?.at(1)?.data.totalScore ?? 42}
/>
<PodiumCardComponent
medalColor="#5F74F7"
offset={60}
userAvatarUrl={
scoresQuery.data?.at(2)?.data.avatar ??
'https://picsum.photos/140/140'
}
userPseudo={scoresQuery.data?.at(2)?.name ?? '---'}
userLvl={scoresQuery.data?.at(2)?.data.totalScore ?? 42}
/>
</View>
</View>
)}
{scoresQuery.data.slice(3).map((comp: User, index: number) => (
<BoardRowComponent
key={index}
index={index}
userAvatarUrl={comp?.data.avatar ?? 'https://picsum.photos/50/50'}
userLvl={comp?.data.totalScore ?? 42}
userPseudo={comp?.name ?? '---'}
/>
))}
</View>
{dummyScores.map((comp, index) => (
<BoardRowComponent />
))}
</View>
</ScrollView>
</ScrollView>
</ScaffoldCC>
);
};