Front; Song Lobby: Cpaters, Scores and layout
This commit is contained in:
+11
-11
@@ -59,7 +59,7 @@ export default class API {
|
|||||||
static async getSong(songId: number): Promise<Song> {
|
static async getSong(songId: number): Promise<Song> {
|
||||||
return delay(1).then(() => ({
|
return delay(1).then(() => ({
|
||||||
title: "Song",
|
title: "Song",
|
||||||
description: "A song",
|
description: "A very very very very very very very very very very very very very very very very very very very very very very very very good song",
|
||||||
album: "Album",
|
album: "Album",
|
||||||
metrics: {},
|
metrics: {},
|
||||||
id: songId
|
id: songId
|
||||||
@@ -72,16 +72,16 @@ export default class API {
|
|||||||
* @param songId the id to find the song
|
* @param songId the id to find the song
|
||||||
*/
|
*/
|
||||||
static async getSongChapters(songId: number): Promise<Chapter[]> {
|
static async getSongChapters(songId: number): Promise<Chapter[]> {
|
||||||
return [{
|
return [1, 2, 3, 4, 5].map((value) => ({
|
||||||
start: 0,
|
start: 100 * (value - 1),
|
||||||
end: 100,
|
end: 100 * value,
|
||||||
songId: songId,
|
songId: songId,
|
||||||
name: "Chapter",
|
name: `Chapter ${value}`,
|
||||||
type: "chorus",
|
type: "chorus",
|
||||||
key_aspect: "rhythm",
|
key_aspect: "rhythm",
|
||||||
difficulty: 1,
|
difficulty: value,
|
||||||
id: 1
|
id: value * 10
|
||||||
}];
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -89,11 +89,11 @@ export default class API {
|
|||||||
* @param songId the id to find the song
|
* @param songId the id to find the song
|
||||||
*/
|
*/
|
||||||
static async getSongHistory(songId: number): Promise<SongHistory[]> {
|
static async getSongHistory(songId: number): Promise<SongHistory[]> {
|
||||||
return [{
|
return [6, 1, 2, 3, 4, 5].map((value) => ({
|
||||||
songId: songId,
|
songId: songId,
|
||||||
userId: 1,
|
userId: 1,
|
||||||
score: 2
|
score: value
|
||||||
}];
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -2,10 +2,16 @@ export const en = {
|
|||||||
welcome: 'Welcome to Chromacase',
|
welcome: 'Welcome to Chromacase',
|
||||||
signoutBtn: 'Sign out',
|
signoutBtn: 'Sign out',
|
||||||
signinBtn: 'Sign in',
|
signinBtn: 'Sign in',
|
||||||
|
playBtn: 'Play',
|
||||||
|
level: 'Level',
|
||||||
|
chapters: 'Chapters'
|
||||||
};
|
};
|
||||||
|
|
||||||
export const fr: typeof en = {
|
export const fr: typeof en = {
|
||||||
welcome: 'Bienvenue sur Chromacase',
|
welcome: 'Bienvenue sur Chromacase',
|
||||||
signoutBtn: 'Se déconnecter',
|
signoutBtn: 'Se déconnecter',
|
||||||
signinBtn: 'Se connecter',
|
signinBtn: 'Se connecter',
|
||||||
|
playBtn: 'Jouer',
|
||||||
|
level: 'Niveau',
|
||||||
|
chapters: 'Chapitres'
|
||||||
};
|
};
|
||||||
+6
-5
@@ -16,14 +16,16 @@
|
|||||||
"@react-navigation/native": "^6.0.11",
|
"@react-navigation/native": "^6.0.11",
|
||||||
"@react-navigation/native-stack": "^6.7.0",
|
"@react-navigation/native-stack": "^6.7.0",
|
||||||
"@reduxjs/toolkit": "^1.8.3",
|
"@reduxjs/toolkit": "^1.8.3",
|
||||||
|
"@tanstack/react-query": "^4.2.3",
|
||||||
"@types/jest": "^28.1.4",
|
"@types/jest": "^28.1.4",
|
||||||
"@types/react": "^18.0.8",
|
"@types/react-dom": "^18.0.6",
|
||||||
"@types/react-query": "^1.2.9",
|
"@types/react-query": "^1.2.9",
|
||||||
"@types/react-test-renderer": "^18.0.0",
|
"@types/react-test-renderer": "^18.0.0",
|
||||||
"expo": "~45.0.0",
|
"expo": "~45.0.0",
|
||||||
"expo-asset": "^8.6.1",
|
"expo-asset": "^8.6.1",
|
||||||
"expo-dev-client": "~1.0.0",
|
"expo-dev-client": "~1.0.0",
|
||||||
"expo-status-bar": "~1.3.0",
|
"expo-status-bar": "~1.3.0",
|
||||||
|
"format-duration": "^2.0.0",
|
||||||
"i18next": "^21.8.16",
|
"i18next": "^21.8.16",
|
||||||
"jest": "^26.6.3",
|
"jest": "^26.6.3",
|
||||||
"jest-expo": "^45.0.1",
|
"jest-expo": "^45.0.1",
|
||||||
@@ -31,19 +33,18 @@
|
|||||||
"react-dom": "17.0.2",
|
"react-dom": "17.0.2",
|
||||||
"react-i18next": "^11.18.3",
|
"react-i18next": "^11.18.3",
|
||||||
"react-native": "0.68.2",
|
"react-native": "0.68.2",
|
||||||
"react-native-paper": "^4.12.2",
|
"react-native-paper": "^4.12.4",
|
||||||
"react-native-safe-area-context": "4.2.4",
|
"react-native-safe-area-context": "4.2.4",
|
||||||
"react-native-screens": "~3.11.1",
|
"react-native-screens": "~3.11.1",
|
||||||
"react-native-testing-library": "^6.0.0",
|
"react-native-testing-library": "^6.0.0",
|
||||||
"react-native-web": "0.17.7",
|
"react-native-web": "0.17.7",
|
||||||
"react-query": "^4.0.0",
|
|
||||||
"react-redux": "^8.0.2"
|
"react-redux": "^8.0.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.12.9",
|
"@babel/core": "^7.12.9",
|
||||||
"@testing-library/react-native": "^11.0.0",
|
"@testing-library/react-native": "^11.0.0",
|
||||||
"@types/react": "~17.0.21",
|
"@types/react": "^18.0.18",
|
||||||
"@types/react-native": "~0.66.13",
|
"@types/react-native": "^0.69.6",
|
||||||
"react-test-renderer": "17.0.2",
|
"react-test-renderer": "17.0.2",
|
||||||
"typescript": "~4.3.5"
|
"typescript": "~4.3.5"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
import { useRoute } from "@react-navigation/native";
|
import { useRoute } from "@react-navigation/native";
|
||||||
import { Image, View } from "react-native"
|
import { Image, View } from "react-native"
|
||||||
import { Surface, Text } from "react-native-paper";
|
import { Button, Divider, IconButton, List, Surface, Text } from "react-native-paper";
|
||||||
import API from "../API";
|
import API from "../API";
|
||||||
import { useQuery } from 'react-query';
|
import { useQuery } from 'react-query';
|
||||||
import LoadingComponent from "../components/loading";
|
import LoadingComponent from "../components/loading";
|
||||||
import React, { useEffect } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import logo from '../assets/cover.png';
|
import logo from '../assets/cover.png';
|
||||||
|
import { translate } from "../i18n/i18n";
|
||||||
|
import formatDuration from "format-duration";
|
||||||
|
|
||||||
interface SongLobbyProps {
|
interface SongLobbyProps {
|
||||||
// The unique identifier to find a song
|
// The unique identifier to find a song
|
||||||
@@ -15,27 +17,65 @@ interface SongLobbyProps {
|
|||||||
const SongLobbyView = () => {
|
const SongLobbyView = () => {
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const props: SongLobbyProps = route.params as any;
|
const props: SongLobbyProps = route.params as any;
|
||||||
const { isLoading, data } = useQuery(['song', props.songId], () => API.getSong(props.songId));
|
const songQuery = useQuery(['song', props.songId], () => API.getSong(props.songId));
|
||||||
useEffect(() => {}, [isLoading]);
|
const chaptersQuery = useQuery(['song', props.songId, 'chapters'], () => API.getSongChapters(props.songId));
|
||||||
if (isLoading)
|
const scoresQuery = useQuery(['song', props.songId, 'scores'], () => API.getSongHistory(props.songId));
|
||||||
|
const [chaptersOpen, setChaptersOpen] = useState(false);
|
||||||
|
useEffect(() => {
|
||||||
|
if (chaptersOpen && !chaptersQuery.data)
|
||||||
|
chaptersQuery.refetch();
|
||||||
|
}, [chaptersOpen]);
|
||||||
|
useEffect(() => {}, [songQuery.isLoading]);
|
||||||
|
if (songQuery.isLoading || scoresQuery.isLoading)
|
||||||
return <View style={{ flexGrow: 1, justifyContent: 'center' }}>
|
return <View style={{ flexGrow: 1, justifyContent: 'center' }}>
|
||||||
<LoadingComponent/>
|
<LoadingComponent/>
|
||||||
</View>
|
</View>
|
||||||
return (
|
return (
|
||||||
<View style={{ padding: 30 }}>
|
<View style={{ padding: 30, flexDirection: 'column' }}>
|
||||||
<View style={{ flexDirection: 'row' }}>
|
<View style={{ flexDirection: 'row'}}>
|
||||||
<View style={{ flex: 3 }}>
|
<View style={{ flex: 3 }}>
|
||||||
<Surface style={{ aspectRatio: 1, zIndex: 0 }}>
|
<Surface style={{ aspectRatio: 1, zIndex: 0 }}>
|
||||||
<Image source={logo} style={{ height: '100%', width: undefined, resizeMode: 'contain' }}/>
|
<Image source={logo} style={{ height: '100%', width: undefined, resizeMode: 'contain' }}/>
|
||||||
</Surface>
|
</Surface>
|
||||||
</View>
|
</View>
|
||||||
<View style={{ flex: 3, padding: 10 }}>
|
<View style={{ flex: 0.5 }}/>
|
||||||
<Text>{data.title}</Text>
|
<View style={{ flex: 3, padding: 10, flexDirection: 'column', justifyContent: 'space-between' }}>
|
||||||
<Text></Text>
|
<View>
|
||||||
|
<Text style={{ fontWeight: 'bold', fontSize: 25 }}>{songQuery.data!.title}</Text>
|
||||||
|
<Text>{'3:20'} - {translate('level')} { chaptersQuery.data!.reduce((a, b) => a + b.difficulty, 0) / chaptersQuery.data!.length }</Text>
|
||||||
|
</View>
|
||||||
|
<Button icon="play" mode="contained" labelStyle={{ color: 'white' }} contentStyle={{ flexDirection: 'row-reverse' }}>
|
||||||
|
{ translate('playBtn') }
|
||||||
|
</Button>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
<View style={{ paddingVertical: 10 }}/>
|
<View style={{ flexDirection: 'row', justifyContent: 'space-between', padding: 30}}>
|
||||||
<Text>{data.description}</Text>
|
<View style={{ flexDirection: 'column', alignItems: 'center' }}>
|
||||||
|
<Text style={{ fontWeight: 'bold', fontSize: 15 }}>Best Score</Text>
|
||||||
|
<Text>{scoresQuery.data!.sort()[0]?.score}</Text>
|
||||||
|
</View>
|
||||||
|
<View style={{ flexDirection: 'column', alignItems: 'center' }}>
|
||||||
|
<Text style={{ fontWeight: 'bold', fontSize: 15}}>Last Score</Text>
|
||||||
|
<Text>{scoresQuery.data!.slice(-1)[0]!.score}</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
<Text style={{ paddingBottom: 10 }}>{songQuery.data!.description}</Text>
|
||||||
|
<List.Accordion
|
||||||
|
title={translate('chapters')}
|
||||||
|
expanded={chaptersOpen}
|
||||||
|
onPress={() => setChaptersOpen(!chaptersOpen)}>
|
||||||
|
{ chaptersQuery.isLoading && <LoadingComponent/>}
|
||||||
|
{ !chaptersQuery.isLoading && chaptersQuery.data!.map((chapter) =>
|
||||||
|
<>
|
||||||
|
<List.Item
|
||||||
|
key={chapter.id}
|
||||||
|
title={chapter.name}
|
||||||
|
description={`Level ${chapter.difficulty} - ${formatDuration((chapter.end - chapter.start) * 1000)}`}
|
||||||
|
/>
|
||||||
|
<Divider />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</List.Accordion>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+779
-679
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user