Files
Chromacase/front/views/LeaderboardView.tsx

321 lines
7.1 KiB
TypeScript

import { useBreakpointValue, ScrollView, Text } from 'native-base';
import { View, Image } from 'react-native';
import { useQuery } from '../Queries';
import API from '../API';
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 = {
offset: number;
medalColor: string;
userAvatarUrl: string;
userPseudo: string;
userLvl: number;
};
const PodiumCardComponent = ({
offset,
medalColor,
userAvatarUrl,
userPseudo,
userLvl,
}: PodiumCardProps) => {
return (
<View
style={{
display: 'flex',
paddingTop: offset,
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
marginLeft: 32,
}}
>
<View /** image + medal container*/
style={{
width: 140,
height: 140,
}}
>
<Image
source={{
uri: userAvatarUrl,
}}
style={{
aspectRatio: 1,
width: '100%',
height: '100%',
flexShrink: 0,
borderRadius: 12,
}}
/>
<MedalStar
style={{ position: 'absolute', top: 115, left: 115 }}
size="42"
variant="Bold"
color={medalColor}
/>
</View>
<Text
mt={4}
style={{
fontSize: 16,
fontStyle: 'normal',
fontWeight: '500',
}}
>
{userPseudo}
</Text>
<Text
mt={1}
style={{
fontSize: 16,
fontStyle: 'normal',
fontWeight: '500',
}}
>
{userLvl} LVL
</Text>
</View>
);
};
type BoardRowProps = {
userAvatarUrl: string;
userPseudo: string;
userLvl: number;
index: number;
};
const BoardRowComponent = ({ userAvatarUrl, userPseudo, userLvl, index }: BoardRowProps) => {
return (
<View
style={{
marginVertical: 5,
marginHorizontal: 10,
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
alignSelf: 'stretch',
borderRadius: 8,
backgroundColor: 'rgba(16, 16, 20, 0.50)',
shadowColor: 'rgba(0, 0, 0, 0.25)',
shadowOffset: { width: 0, height: 4 },
shadowOpacity: 1,
shadowRadius: 4,
marginTop: 10,
}}
>
<View
style={{
width: 50,
height: 50,
}}
>
<Image
source={{
uri: userAvatarUrl,
}}
style={{
width: '100%',
height: '100%',
borderTopLeftRadius: 8,
borderBottomLeftRadius: 8,
}}
/>
</View>
<Text
style={{
fontSize: 16,
fontStyle: 'normal',
flex: 1,
marginHorizontal: 10,
fontWeight: '500',
}}
>
{userPseudo}
</Text>
<Text
style={{
fontSize: 16,
fontStyle: 'normal',
fontWeight: '500',
marginHorizontal: 10,
}}
>
{userLvl} LVL
</Text>
<View
style={{
backgroundColor: 'rgba(255, 255, 255, 0.50)',
borderTopRightRadius: 8,
borderBottomRightRadius: 8,
width: 50,
height: '100%',
flexDirection: 'column',
justifyContent: 'center',
}}
>
<Text
style={{
fontSize: 16,
fontStyle: 'normal',
fontWeight: '500',
textAlign: 'center',
}}
>
{index + 4}
</Text>
</View>
</View>
);
};
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';
if (scoresQuery.isError) {
navigation.navigate('Error');
return <></>;
}
if (scoresQuery.data === undefined) {
return (
<ScaffoldCC routeName={props.route.name}>
<LoadingView />
</ScaffoldCC>
);
}
return (
<ScaffoldCC routeName={props.route.name}>
<ScrollView style={{ marginBottom: 5 }}>
<View
style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'flex-start',
flex: 1,
flexGrow: 1,
flexShrink: 0,
flexBasis: 0,
alignSelf: 'stretch',
}}
>
{!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>
</ScrollView>
</ScaffoldCC>
);
};
export default Leaderboardiew;