Merge remote-tracking branch 'origin/main' into feat/adc/search-view-v2
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
import { Column, Row, Text, useTheme } from 'native-base';
|
||||
import ButtonBase from './UI/ButtonBase';
|
||||
import { Translate, TranslationKey, translate } from '../i18n/i18n';
|
||||
import { Play, Star1 } from 'iconsax-react-native';
|
||||
import { useNavigation } from '../Navigation';
|
||||
import { StackActions } from '@react-navigation/native';
|
||||
|
||||
type ScoreModalProps = {
|
||||
songId: number;
|
||||
overallScore: number;
|
||||
precision: number;
|
||||
score: {
|
||||
missed: number;
|
||||
good: number;
|
||||
great: number;
|
||||
perfect: number;
|
||||
wrong: number;
|
||||
max_score: number;
|
||||
current_streak: number;
|
||||
max_streak: number;
|
||||
};
|
||||
};
|
||||
|
||||
const ScoreModal = (props: ScoreModalProps) => {
|
||||
// const props = {
|
||||
// songId: 1,
|
||||
// overallScore: 74,
|
||||
// precision: 0,
|
||||
// score: {
|
||||
// missed: 9,
|
||||
// good: 1,
|
||||
// great: 2,
|
||||
// perfect: 4,
|
||||
// wrong: 0,
|
||||
// max_score: 100,
|
||||
// current_streak: 1,
|
||||
// max_streak: 11,
|
||||
// } as const
|
||||
// } as const; //TODO DELETE ME
|
||||
const navigation = useNavigation();
|
||||
const theme = useTheme();
|
||||
const score = (props.overallScore * 100) / props.score.max_score;
|
||||
const column1 = {
|
||||
perfect: [props.score.perfect, 'primary'],
|
||||
great: [props.score.great, 'secondary'],
|
||||
good: [props.score.good, 'success'],
|
||||
} as const;
|
||||
const column2 = {
|
||||
bestStreak: [props.score.max_streak, 'notification'],
|
||||
missed: [props.score.missed, 'alert'],
|
||||
wrong: [props.score.wrong, 'error'],
|
||||
} as const;
|
||||
|
||||
return (
|
||||
<Column w="xl" space={4} style={{ alignItems: 'center' }}>
|
||||
<Row space={2} style={{ justifyContent: 'center' }}>
|
||||
{[1, 2, 3].map((index) => (
|
||||
<Star1
|
||||
color={theme.colors.primary[500]}
|
||||
key={index}
|
||||
variant={score >= (index * 100) / 4 ? 'Bold' : 'Outline'}
|
||||
/>
|
||||
))}
|
||||
</Row>
|
||||
<Text fontSize="3xl">{Math.max(score, 0)}%</Text>
|
||||
<Row w="100%" style={{ justifyContent: 'space-between' }}>
|
||||
<Translate translationKey="precision" />
|
||||
<Text>{props.precision}%</Text>
|
||||
</Row>
|
||||
<Row w="100%" space={2}>
|
||||
{([column1, column2] as const).map((column, columnIndex) => (
|
||||
<Column w="50%" space={2} key={columnIndex}>
|
||||
{Object.entries(column).map(([key, [value, color]]) => {
|
||||
const translationKey = key as TranslationKey;
|
||||
|
||||
return (
|
||||
<Row
|
||||
key={translationKey}
|
||||
style={{ justifyContent: 'space-between' }}
|
||||
>
|
||||
<Translate
|
||||
translationKey={translationKey}
|
||||
fontWeight={'bold'}
|
||||
color={`${color}.500`}
|
||||
/>
|
||||
<Text>x{value}</Text>
|
||||
</Row>
|
||||
);
|
||||
})}
|
||||
</Column>
|
||||
))}
|
||||
</Row>
|
||||
<Row w="100%" style={{ justifyContent: 'space-between' }}>
|
||||
<ButtonBase
|
||||
style={{}}
|
||||
icon={Play}
|
||||
type="outlined"
|
||||
title={translate('playAgain')}
|
||||
onPress={() =>
|
||||
navigation.dispatch(StackActions.replace('Play', { songId: props.songId }))
|
||||
}
|
||||
/>
|
||||
<ButtonBase
|
||||
style={{}}
|
||||
icon={Play}
|
||||
type="filled"
|
||||
title={translate('menuMusic')}
|
||||
onPress={() =>
|
||||
navigation.canGoBack()
|
||||
? navigation.goBack()
|
||||
: navigation.navigate('HomeNew', {})
|
||||
}
|
||||
/>
|
||||
</Row>
|
||||
</Column>
|
||||
);
|
||||
};
|
||||
|
||||
export default ScoreModal;
|
||||
@@ -8,7 +8,7 @@ import React from 'react';
|
||||
import GlassmorphismCC from './Glassmorphism';
|
||||
|
||||
type PopupCCProps = {
|
||||
title: string;
|
||||
title?: string;
|
||||
description?: string;
|
||||
children?: ReactNode;
|
||||
isVisible: boolean;
|
||||
@@ -53,17 +53,19 @@ const PopupCC = ({ title, description, children, isVisible, setIsVisible }: Popu
|
||||
onPress={async () => setIsVisible(false)}
|
||||
/>
|
||||
)}
|
||||
<Heading
|
||||
size="md"
|
||||
style={{
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
}}
|
||||
>
|
||||
<Text style={{ flex: 1 }}>{title}</Text>
|
||||
</Heading>
|
||||
{title !== undefined && (
|
||||
<Heading
|
||||
size="md"
|
||||
style={{
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
}}
|
||||
>
|
||||
<Text style={{ flex: 1 }}>{title}</Text>
|
||||
</Heading>
|
||||
)}
|
||||
{description !== undefined && <Text>{description}</Text>}
|
||||
{children !== undefined && children}
|
||||
</View>
|
||||
|
||||
@@ -7,6 +7,7 @@ import { Cup, Discover, Music, SearchNormal1, Setting2, User } from 'iconsax-rea
|
||||
import { LoadingView } from '../Loading';
|
||||
import ScaffoldDesktopCC from './ScaffoldDesktopCC';
|
||||
import ScaffoldMobileCC from './ScaffoldMobileCC';
|
||||
import { useAssets } from 'expo-asset';
|
||||
|
||||
const menu = [
|
||||
{ type: 'main', title: 'menuDiscovery', icon: Discover, link: 'HomeNew' },
|
||||
@@ -37,10 +38,11 @@ const ScaffoldCC = ({
|
||||
return <LoadingView />;
|
||||
}
|
||||
const colorScheme = useColorScheme();
|
||||
const logo =
|
||||
const [logo] = useAssets(
|
||||
colorScheme == 'light'
|
||||
? require('../../assets/icon_light.png')
|
||||
: require('../../assets/icon_dark.png');
|
||||
: require('../../assets/icon_dark.png')
|
||||
);
|
||||
|
||||
return (
|
||||
<Flex style={{ flex: 1, backgroundColor: '#cdd4fd' }}>
|
||||
@@ -48,7 +50,7 @@ const ScaffoldCC = ({
|
||||
<ScaffoldMobileCC
|
||||
enableScroll={enableScroll}
|
||||
user={userQuery.data}
|
||||
logo={logo}
|
||||
logo={logo?.at(0)?.uri ?? ''}
|
||||
routeName={routeName}
|
||||
menu={menu}
|
||||
widthPadding={withPadding}
|
||||
@@ -58,7 +60,7 @@ const ScaffoldCC = ({
|
||||
) : (
|
||||
<ScaffoldDesktopCC
|
||||
user={userQuery.data}
|
||||
logo={logo}
|
||||
logo={logo?.at(0)?.uri ?? ''}
|
||||
routeName={routeName}
|
||||
menu={menu}
|
||||
widthPadding={withPadding}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* eslint-disable no-mixed-spaces-and-tabs */
|
||||
import { View, Image, TouchableOpacity } from 'react-native';
|
||||
import { View, Image, Pressable } from 'react-native';
|
||||
import { Divider, Text, ScrollView, Row, useMediaQuery, useTheme } from 'native-base';
|
||||
import { useQuery } from '../../Queries';
|
||||
import API from '../../API';
|
||||
@@ -36,7 +36,21 @@ const SongHistory = (props: { quantity: number }) => {
|
||||
return <LoadingView />;
|
||||
}
|
||||
|
||||
const musics = history.data.map((h) => h.song)?.slice(0, props.quantity);
|
||||
const musics = history.data
|
||||
.reduce(
|
||||
(acc, curr) => {
|
||||
if (acc.length === 0) {
|
||||
return [curr];
|
||||
}
|
||||
if (acc.find((h) => h.song!.id === curr.song!.id)) {
|
||||
return acc;
|
||||
}
|
||||
return [...acc, curr];
|
||||
},
|
||||
[] as typeof history.data
|
||||
)
|
||||
.map((h) => h.song)
|
||||
?.slice(0, props.quantity);
|
||||
|
||||
return (
|
||||
<View>
|
||||
@@ -45,18 +59,18 @@ const SongHistory = (props: { quantity: number }) => {
|
||||
) : (
|
||||
musics.map((song) => (
|
||||
<View
|
||||
key={'short-history-tab' + song.id}
|
||||
key={'short-history-tab' + song!.id}
|
||||
style={{
|
||||
paddingHorizontal: 16,
|
||||
paddingVertical: 10,
|
||||
flex: 1,
|
||||
}}
|
||||
>
|
||||
<TouchableOpacity
|
||||
onPress={() => navigation.navigate('Play', { songId: song.id })}
|
||||
<Pressable
|
||||
onPress={() => navigation.navigate('Play', { songId: song!.id })}
|
||||
>
|
||||
<Text numberOfLines={1}>{song.name}</Text>
|
||||
</TouchableOpacity>
|
||||
<Text numberOfLines={1}>{song!.name}</Text>
|
||||
</Pressable>
|
||||
</View>
|
||||
))
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user