104 page du profil utilisateur (#116)
* [ADD] profile page * [DEL] empty lines * [UPD] added translation for the profile page * [UPD] link to the profile page * [ADD] profile page * [UPD] moved the progress bar component in its own file * [UPD] moved the progress bar component * [WIP] added all the elements to the profile view * [WIP] added all the elements to the profile view * User Slice: Use API Instance instead of access token * Front: Fix API calls with JWT Token * Front: Handle Empty Server response * Front: Fix User Model * Front: Signin Form: Fix submittingstate on error * Front: Remove logs * Front/translate refactor (#110) * Front: i18n: Create component * Front: Use new translation component * Front: Translation COmpoent: Change props name * Front: Fix merge * Front: settings persistance (#108) * Front: Add peristance dependencies * Front: Fix Cross-platform persistance * Front: Create Settings Slice * Front: Use Redux State for settings * Front: Check if access token is still valid * Front: Create Language Gate to set correct language at startup * Front: BEtter handling of Access Token validity * 54-écran-de-titre (#109) * [ADD] function to hide the splash screen * [DEL] useless lines * [ADD] compatibility * [UPD] settings for the splash screen * [ADD] chromacase logo on the splash screen * [UPD] splash logo * [UPD] set the timeout to 0 * [UPD] set the timeout to 500 * User Slice: Use API Instance instead of access token * Front: Fix API calls with JWT Token * Front: Handle Empty Server response * Front: Fix User Model * Front: Signin Form: Fix submittingstate on error * Front: Remove logs * Front/translate refactor (#110) * Front: i18n: Create component * Front: Use new translation component * Front: Translation COmpoent: Change props name * Front: Fix merge * Front: settings persistance (#108) * Front: Add peristance dependencies * Front: Fix Cross-platform persistance * Front: Create Settings Slice * Front: Use Redux State for settings * Front: Check if access token is still valid * Front: Create Language Gate to set correct language at startup * Front: BEtter handling of Access Token validity * [MERGE] * [DEL] useless lines * [UPD] settings for the splash screen * [UPD] set the timeout to 0 * [DEL] duplicated line * [REVERT] Co-authored-by: Arthi-chaud <arthur.jamet@gmail.com> Co-authored-by: Arthur Jamet <60505370+Arthi-chaud@users.noreply.github.com> * [FIX] splashscreen * [ADD] profile page * [UPD] link to the profile page * [UPD] moved the progress bar component * [FIX] translate * [UPD] reorganized all translations for ease of use * [UPD] translated all the texts and made the page more beautiful [TODO] get the informations of the user * [ADD] banner and level Co-authored-by: Arthi-chaud <arthur.jamet@gmail.com> Co-authored-by: Arthur Jamet <60505370+Arthi-chaud@users.noreply.github.com>
This commit is contained in:
@@ -1,15 +1,16 @@
|
|||||||
import { createNativeStackNavigator } from '@react-navigation/native-stack';
|
import { createNativeStackNavigator } from '@react-navigation/native-stack';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { NavigationContainer } from '@react-navigation/native';
|
||||||
|
import { useSelector } from './state/Store';
|
||||||
|
import { translate } from './i18n/i18n';
|
||||||
|
import SongLobbyView from './views/SongLobbyView';
|
||||||
import AuthenticationView from './views/AuthenticationView';
|
import AuthenticationView from './views/AuthenticationView';
|
||||||
import HomeView from './views/HomeView';
|
import HomeView from './views/HomeView';
|
||||||
import SearchView from './views/SearchView';
|
import SearchView from './views/SearchView';
|
||||||
import SetttingsNavigator from './views/SettingsView';
|
import SetttingsNavigator from './views/SettingsView';
|
||||||
import { NavigationContainer } from '@react-navigation/native';
|
|
||||||
import { useSelector } from './state/Store';
|
|
||||||
import SongLobbyView from './views/SongLobbyView';
|
|
||||||
import { translate } from './i18n/i18n';
|
|
||||||
import { useQuery } from 'react-query';
|
import { useQuery } from 'react-query';
|
||||||
import API from './API';
|
import API from './API';
|
||||||
|
import ProfileView from './views/ProfileView';
|
||||||
|
|
||||||
const Stack = createNativeStackNavigator();
|
const Stack = createNativeStackNavigator();
|
||||||
|
|
||||||
@@ -18,6 +19,7 @@ export const protectedRoutes = <>
|
|||||||
<Stack.Screen name="Settings" component={SetttingsNavigator} options={{ title: 'Settings' }} />
|
<Stack.Screen name="Settings" component={SetttingsNavigator} options={{ title: 'Settings' }} />
|
||||||
<Stack.Screen name="Song" component={SongLobbyView} options={{ title: translate('play') }} />
|
<Stack.Screen name="Song" component={SongLobbyView} options={{ title: translate('play') }} />
|
||||||
<Stack.Screen name="Search" component={SearchView} options={{ title: translate('search') }} />
|
<Stack.Screen name="Search" component={SearchView} options={{ title: translate('search') }} />
|
||||||
|
<Stack.Screen name="User" component={ProfileView} options={{ title: translate('user') }} />
|
||||||
</>;
|
</>;
|
||||||
|
|
||||||
export const publicRoutes = <React.Fragment>
|
export const publicRoutes = <React.Fragment>
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ const CompetenciesTable = (props: CompetenciesTableProps) => {
|
|||||||
))}
|
))}
|
||||||
</VStack>
|
</VStack>
|
||||||
</HStack>
|
</HStack>
|
||||||
|
|
||||||
</Card>
|
</Card>
|
||||||
)}
|
)}
|
||||||
</Pressable>
|
</Pressable>
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { translate } from "../i18n/i18n";
|
||||||
|
import { Box, useBreakpointValue, Text, VStack, Progress } from 'native-base';
|
||||||
|
import { useNavigation } from "@react-navigation/native";
|
||||||
|
import { Pressable, Image } from "native-base";
|
||||||
|
import Card from "../components/Card";
|
||||||
|
|
||||||
|
const ProgressBar = ({ xp }: { xp: number}) => {
|
||||||
|
const level = Math.floor(xp / 1000);
|
||||||
|
const nextLevel = level + 1;
|
||||||
|
const nextLevelThreshold = nextLevel * 1000;
|
||||||
|
const progessValue = 100 * xp / nextLevelThreshold;
|
||||||
|
|
||||||
|
const nav = useNavigation();
|
||||||
|
const flexDirection = useBreakpointValue({ base: 'column', xl: "row"});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Pressable onPress={() => nav.navigate('User')}>
|
||||||
|
{({ isHovered, isFocused }) => (
|
||||||
|
<Card w="90%" maxW='500' style={{flexDirection}}
|
||||||
|
bg={(isHovered || isFocused) ? 'coolGray.200' : undefined }>
|
||||||
|
<Box w="20%" paddingRight={2} paddingLeft={2} paddingY={2}>
|
||||||
|
<Image borderRadius={100} source={{
|
||||||
|
uri: "https://wallpaperaccess.com/full/317501.jpg" // TODO : put the actual profile pic
|
||||||
|
}} alt="Profile picture" size="sm"
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Box w='80%' paddingY={4}>
|
||||||
|
<VStack alignItems={'center'}>
|
||||||
|
<Text>{`${translate('level')} ${level}`}</Text>
|
||||||
|
<Box w="100%">
|
||||||
|
<Progress value={progessValue} mx="4" />
|
||||||
|
</Box>
|
||||||
|
<Text>{xp} / {nextLevelThreshold} {translate('levelProgress')}</Text>
|
||||||
|
</VStack>
|
||||||
|
</Box>
|
||||||
|
</Card>
|
||||||
|
)}
|
||||||
|
</Pressable>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ProgressBar;
|
||||||
@@ -20,7 +20,6 @@ const SongCardGrid = (props: SongCardGrid) => {
|
|||||||
spacing={20}
|
spacing={20}
|
||||||
/>
|
/>
|
||||||
</VStack>
|
</VStack>
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default SongCardGrid;
|
export default SongCardGrid;
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import { translate } from "../i18n/i18n";
|
import { translate } from "../i18n/i18n";
|
||||||
import { en } from "../i18n/Translations";
|
import { en } from "../i18n/Translations";
|
||||||
import { RootState, useSelector } from "../state/Store";
|
import { RootState, useSelector } from "../state/Store";
|
||||||
|
import { Text } from "native-base";
|
||||||
|
|
||||||
type TranslateProps = {
|
type TranslateProps = {
|
||||||
translationKey: keyof typeof en;
|
translationKey: keyof typeof en;
|
||||||
@@ -14,7 +15,7 @@ type TranslateProps = {
|
|||||||
const Translate = ({ translationKey, format }: TranslateProps) => {
|
const Translate = ({ translationKey, format }: TranslateProps) => {
|
||||||
const selectedLanguage = useSelector((state: RootState) => state.language.value);
|
const selectedLanguage = useSelector((state: RootState) => state.language.value);
|
||||||
const translated = translate(translationKey, selectedLanguage);
|
const translated = translate(translationKey, selectedLanguage);
|
||||||
return <>{format ? format(translated) : translated}</>;
|
return <Text>{format ? format(translated) : translated}</Text>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Translate;
|
export default Translate;
|
||||||
+143
-82
@@ -13,21 +13,11 @@ export const en = {
|
|||||||
lastScore: 'Last Score',
|
lastScore: 'Last Score',
|
||||||
play: 'Play',
|
play: 'Play',
|
||||||
langBtn: 'Language',
|
langBtn: 'Language',
|
||||||
diffBtn: 'Difficulty',
|
|
||||||
backBtn: 'Back',
|
backBtn: 'Back',
|
||||||
settingsBtn: 'Settings',
|
settingsBtn: 'Settings',
|
||||||
prefBtn: 'Preferences',
|
prefBtn: 'Preferences',
|
||||||
notifBtn: 'Notifications',
|
notifBtn: 'Notifications',
|
||||||
privBtn: 'Privacy',
|
privBtn: 'Privacy',
|
||||||
changepasswdBtn: 'Change Password',
|
|
||||||
changeemailBtn: 'Change Email',
|
|
||||||
googleacctBtn: 'Google Account',
|
|
||||||
easy: 'Beginner',
|
|
||||||
medium: 'Intermediate',
|
|
||||||
hard: 'Pro',
|
|
||||||
dark: 'Dark',
|
|
||||||
system: 'System',
|
|
||||||
light: 'Light',
|
|
||||||
goNextStep: 'Step Up!',
|
goNextStep: 'Step Up!',
|
||||||
mySkillsToImprove: "My Competencies to work on",
|
mySkillsToImprove: "My Competencies to work on",
|
||||||
recentlyPlayed: 'Recently played',
|
recentlyPlayed: 'Recently played',
|
||||||
@@ -35,6 +25,26 @@ export const en = {
|
|||||||
lastSearched: "Last searched",
|
lastSearched: "Last searched",
|
||||||
levelProgress: 'good notes',
|
levelProgress: 'good notes',
|
||||||
|
|
||||||
|
// profile page
|
||||||
|
user: 'Profile',
|
||||||
|
medals: 'Medals',
|
||||||
|
playerStats: 'My stats',
|
||||||
|
mostPlayedSong: 'Most played song : ',
|
||||||
|
goodNotesPlayed: 'Good notes played : ',
|
||||||
|
longestCombo: 'Longest combo : ',
|
||||||
|
favoriteGenre: 'Favorite genre : ',
|
||||||
|
|
||||||
|
// Difficulty settings
|
||||||
|
diffBtn: 'Difficulty',
|
||||||
|
easy: 'Beginner',
|
||||||
|
medium: 'Intermediate',
|
||||||
|
hard: 'Pro',
|
||||||
|
|
||||||
|
// theme settings
|
||||||
|
dark: 'Dark',
|
||||||
|
system: 'System',
|
||||||
|
light: 'Light',
|
||||||
|
|
||||||
// competencies
|
// competencies
|
||||||
pedalsCompetency: 'Pedals',
|
pedalsCompetency: 'Pedals',
|
||||||
rightHandCompetency: 'Right hand',
|
rightHandCompetency: 'Right hand',
|
||||||
@@ -43,25 +53,34 @@ export const en = {
|
|||||||
arpegeCompetency: 'Arpeges',
|
arpegeCompetency: 'Arpeges',
|
||||||
chordsCompetency: 'Chords',
|
chordsCompetency: 'Chords',
|
||||||
|
|
||||||
|
/* account settings and logs */
|
||||||
|
// buttons
|
||||||
|
signUp: 'Sign up',
|
||||||
|
signIn: 'Sign in',
|
||||||
|
"Must Contain 8 Characters, One Uppercase, One Lowercase, One Number and One Special Case Character": "Must Contain 8 Characters, One Uppercase, One Lowercase, One Number and One Special Case Character",
|
||||||
|
login: 'Login',
|
||||||
|
|
||||||
|
// feedback for the user
|
||||||
usernameTooShort: 'Username is too short',
|
usernameTooShort: 'Username is too short',
|
||||||
passwordTooShort: 'Password is too short',
|
passwordTooShort: 'Password is too short',
|
||||||
usernameTooLong: 'Username is too long',
|
usernameTooLong: 'Username is too long',
|
||||||
passwordTooLong: 'Password is too long',
|
passwordTooLong: 'Password is too long',
|
||||||
username: 'Username',
|
|
||||||
password: 'Password',
|
|
||||||
login: 'Login',
|
|
||||||
invalidCredentials: 'Invalid credentials',
|
|
||||||
forgottenPassword: 'Forgotten password',
|
|
||||||
invalidEmail: 'Invalid email',
|
|
||||||
email: 'Email',
|
|
||||||
repeatPassword: 'Repeat password',
|
|
||||||
passwordsDontMatch: 'Passwords don\'t match',
|
passwordsDontMatch: 'Passwords don\'t match',
|
||||||
signUp: 'Sign up',
|
invalidCredentials: 'Invalid credentials',
|
||||||
signIn: 'Sign in',
|
invalidEmail: 'Invalid email',
|
||||||
"Must Contain 8 Characters, One Uppercase, One Lowercase, One Number and One Special Case Character": "Must Contain 8 Characters, One Uppercase, One Lowercase, One Number and One Special Case Character",
|
|
||||||
accountCreated: 'Account created',
|
accountCreated: 'Account created',
|
||||||
loggedIn: 'Logged in',
|
loggedIn: 'Logged in',
|
||||||
usernameTaken: 'Username already taken',
|
usernameTaken: 'Username already taken',
|
||||||
|
|
||||||
|
// categories
|
||||||
|
username: 'Username',
|
||||||
|
password: 'Password',
|
||||||
|
email: 'Email',
|
||||||
|
repeatPassword: 'Repeat password',
|
||||||
|
changepasswdBtn: 'Change Password',
|
||||||
|
changeemailBtn: 'Change Email',
|
||||||
|
googleacctBtn: 'Google Account',
|
||||||
|
forgottenPassword: 'Forgotten password',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const fr: typeof en = {
|
export const fr: typeof en = {
|
||||||
@@ -79,89 +98,81 @@ export const fr: typeof en = {
|
|||||||
lastScore: 'Dernier Score',
|
lastScore: 'Dernier Score',
|
||||||
play: 'Jouer',
|
play: 'Jouer',
|
||||||
langBtn: 'Langage',
|
langBtn: 'Langage',
|
||||||
diffBtn: 'Difficulté',
|
|
||||||
backBtn: 'Retour',
|
backBtn: 'Retour',
|
||||||
|
settingsBtn: "Réglages",
|
||||||
prefBtn: 'Préférences',
|
prefBtn: 'Préférences',
|
||||||
notifBtn: 'Notifications',
|
notifBtn: 'Notifications',
|
||||||
privBtn: 'Confidentialité',
|
privBtn: 'Confidentialité',
|
||||||
changepasswdBtn: 'Changer le mot de pass',
|
|
||||||
changeemailBtn: 'Change l\'email',
|
|
||||||
googleacctBtn: 'Compte Google',
|
|
||||||
easy: 'Débutant',
|
|
||||||
medium: 'Intermédiaire',
|
|
||||||
hard: 'Avancé',
|
|
||||||
dark: 'Foncé',
|
|
||||||
system: 'Système',
|
|
||||||
light: 'Clair',
|
|
||||||
settingsBtn: "Réglages",
|
|
||||||
goNextStep: "Prochaine Etape",
|
goNextStep: "Prochaine Etape",
|
||||||
mySkillsToImprove: "Mes Skills",
|
mySkillsToImprove: "Mes Skills",
|
||||||
recentlyPlayed: "Joués récemment",
|
recentlyPlayed: "Joués récemment",
|
||||||
search: "Rechercher",
|
search: "Rechercher",
|
||||||
lastSearched: "Dernières recherches",
|
lastSearched: "Dernières recherches",
|
||||||
levelProgress: "Niveau",
|
levelProgress: "Niveau",
|
||||||
|
|
||||||
|
// profile page
|
||||||
|
user: 'Profil',
|
||||||
|
medals: 'Medailles',
|
||||||
|
playerStats: 'Mes statistiques',
|
||||||
|
mostPlayedSong: 'Chanson la plus jouée : ',
|
||||||
|
goodNotesPlayed: 'Bonnes notes jouées : ',
|
||||||
|
longestCombo: 'Combo le plus long : ',
|
||||||
|
favoriteGenre: 'Genre favorit : ',
|
||||||
|
|
||||||
|
// Difficulty settings
|
||||||
|
diffBtn: 'Difficulté',
|
||||||
|
easy: 'Débutant',
|
||||||
|
medium: 'Intermédiaire',
|
||||||
|
hard: 'Avancé',
|
||||||
|
|
||||||
|
// theme settings
|
||||||
|
dark: 'Foncé',
|
||||||
|
system: 'Système',
|
||||||
|
light: 'Clair',
|
||||||
|
|
||||||
|
// competencies
|
||||||
pedalsCompetency: "Pédales",
|
pedalsCompetency: "Pédales",
|
||||||
rightHandCompetency: "Main droite",
|
rightHandCompetency: "Main droite",
|
||||||
leftHandCompetency: "Main gauche",
|
leftHandCompetency: "Main gauche",
|
||||||
accuracyCompetency: "Justesse",
|
accuracyCompetency: "Justesse",
|
||||||
arpegeCompetency: "Arpege",
|
arpegeCompetency: "Arpege",
|
||||||
chordsCompetency: "Accords",
|
chordsCompetency: "Accords",
|
||||||
|
|
||||||
|
/* account settings and logs */
|
||||||
|
// buttons
|
||||||
|
signUp: "S'inscrire",
|
||||||
|
signIn: "Se connecter",
|
||||||
|
"Must Contain 8 Characters, One Uppercase, One Lowercase, One Number and One Special Case Character": "",
|
||||||
|
login: 'Se connecter',
|
||||||
|
|
||||||
|
// feedback for the user
|
||||||
usernameTooShort: 'Le nom d\'utilisateur est trop court',
|
usernameTooShort: 'Le nom d\'utilisateur est trop court',
|
||||||
passwordTooShort: 'Le mot de passe est trop court',
|
passwordTooShort: 'Le mot de passe est trop court',
|
||||||
usernameTooLong: 'Le nom d\'utilisateur est trop long',
|
usernameTooLong: 'Le nom d\'utilisateur est trop long',
|
||||||
passwordTooLong: 'Le mot de passe est trop long',
|
passwordTooLong: 'Le mot de passe est trop long',
|
||||||
username: 'Nom d\'utilisateur',
|
passwordsDontMatch: "Mots de passes différents",
|
||||||
password: 'Mot de passe',
|
|
||||||
login: 'Se connecter',
|
|
||||||
invalidCredentials: "Informations d'identification invalides",
|
invalidCredentials: "Informations d'identification invalides",
|
||||||
|
invalidEmail: "Email invalide",
|
||||||
loggedIn: 'Connecté',
|
loggedIn: 'Connecté',
|
||||||
usernameTaken: 'Nom d\'utilisateur déjà pris',
|
usernameTaken: 'Nom d\'utilisateur déjà pris',
|
||||||
forgottenPassword: "Mot de passe oublié",
|
accountCreated: "Compte créé",
|
||||||
invalidEmail: "Email invalide",
|
|
||||||
|
// categories
|
||||||
|
username: 'Nom d\'utilisateur',
|
||||||
|
password: 'Mot de passe',
|
||||||
email: "Email",
|
email: "Email",
|
||||||
repeatPassword: "Confirmer",
|
repeatPassword: "Confirmer",
|
||||||
passwordsDontMatch: "Mots de passes différents",
|
changepasswdBtn: 'Changer le mot de pass',
|
||||||
signUp: "S'inscrire",
|
changeemailBtn: 'Changer l\'email',
|
||||||
signIn: "Se connecter",
|
googleacctBtn: 'Compte Google',
|
||||||
"Must Contain 8 Characters, One Uppercase, One Lowercase, One Number and One Special Case Character": "",
|
forgottenPassword: "Mot de passe oublié",
|
||||||
accountCreated: "Compte créé"
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const sp: typeof en = {
|
export const sp: typeof en = {
|
||||||
welcome: 'Benvenido a Chromacase',
|
welcome: 'Benvenido a Chromacase',
|
||||||
|
welcomeMessage: "Bienvenue",
|
||||||
signoutBtn: 'Desconectarse',
|
signoutBtn: 'Desconectarse',
|
||||||
signinBtn: 'Connectarse',
|
signinBtn: 'Connectarse',
|
||||||
langBtn: 'Langua',
|
|
||||||
diffBtn: 'Dificultad',
|
|
||||||
backBtn: 'Volver',
|
|
||||||
settingsBtn: 'Settings',
|
|
||||||
prefBtn: 'Préférences',
|
|
||||||
notifBtn: 'Notifications',
|
|
||||||
privBtn: 'Confidentialité',
|
|
||||||
changepasswdBtn: 'Changer le mot de pass',
|
|
||||||
changeemailBtn: 'Change l\'email',
|
|
||||||
googleacctBtn: 'Compte Google',
|
|
||||||
easy: 'Principiante',
|
|
||||||
medium: 'Intermedio',
|
|
||||||
hard: 'Avanzado',
|
|
||||||
dark: 'Oscuro',
|
|
||||||
system: 'Sistema',
|
|
||||||
light: 'Claro',
|
|
||||||
play: 'Jouer',
|
|
||||||
goNextStep: "Passer à l'étape supérieure",
|
|
||||||
mySkillsToImprove: 'Mes Competences à améliorer',
|
|
||||||
lastSearched: "Dernières recherches",
|
|
||||||
search: 'Rechercher',
|
|
||||||
levelProgress: 'bonnes notes',
|
|
||||||
|
|
||||||
// competencies
|
|
||||||
pedalsCompetency: 'Pédales',
|
|
||||||
rightHandCompetency: 'Main droite',
|
|
||||||
leftHandCompetency: 'Main gauche',
|
|
||||||
accuracyCompetency: 'Précision',
|
|
||||||
arpegeCompetency: 'Arpèges',
|
|
||||||
chordsCompetency: 'Accords',
|
|
||||||
welcomeMessage: "Bienvenue",
|
|
||||||
changeLanguageBtn: "Changer de langue",
|
changeLanguageBtn: "Changer de langue",
|
||||||
searchBtn: "Rechercher",
|
searchBtn: "Rechercher",
|
||||||
playBtn: "Jouer",
|
playBtn: "Jouer",
|
||||||
@@ -170,24 +181,74 @@ export const sp: typeof en = {
|
|||||||
chapters: "Chapitres",
|
chapters: "Chapitres",
|
||||||
bestScore: "Meilleur Score",
|
bestScore: "Meilleur Score",
|
||||||
lastScore: "Dernier score",
|
lastScore: "Dernier score",
|
||||||
|
play: 'Jouer',
|
||||||
|
langBtn: 'Langua',
|
||||||
|
backBtn: 'Volver',
|
||||||
|
settingsBtn: 'Settings',
|
||||||
|
prefBtn: 'Préférences',
|
||||||
|
notifBtn: 'Notifications',
|
||||||
|
privBtn: 'Confidentialité',
|
||||||
|
goNextStep: "Passer à l'étape supérieure",
|
||||||
|
mySkillsToImprove: 'Mes Competences à améliorer',
|
||||||
recentlyPlayed: "Joués récemment",
|
recentlyPlayed: "Joués récemment",
|
||||||
|
lastSearched: "Dernières recherches",
|
||||||
|
search: 'Rechercher',
|
||||||
|
levelProgress: 'bonnes notes',
|
||||||
|
|
||||||
|
// profile page
|
||||||
|
user: 'Profil',
|
||||||
|
medals: 'Medailles',
|
||||||
|
playerStats: 'Mes statistiques',
|
||||||
|
mostPlayedSong: 'Chanson la plus jouée : ',
|
||||||
|
goodNotesPlayed: 'Bonnes notes jouées : ',
|
||||||
|
longestCombo: 'Combo le plus long : ',
|
||||||
|
favoriteGenre: 'Genre favorit : ',
|
||||||
|
|
||||||
|
// Difficulty settings
|
||||||
|
diffBtn: 'Dificultad',
|
||||||
|
easy: 'Principiante',
|
||||||
|
medium: 'Intermedio',
|
||||||
|
hard: 'Avanzado',
|
||||||
|
|
||||||
|
// theme settings
|
||||||
|
dark: 'Oscuro',
|
||||||
|
system: 'Sistema',
|
||||||
|
light: 'Claro',
|
||||||
|
|
||||||
|
// competencies
|
||||||
|
pedalsCompetency: 'Pédales',
|
||||||
|
rightHandCompetency: 'Main droite',
|
||||||
|
leftHandCompetency: 'Main gauche',
|
||||||
|
accuracyCompetency: 'Précision',
|
||||||
|
arpegeCompetency: 'Arpèges',
|
||||||
|
chordsCompetency: 'Accords',
|
||||||
|
|
||||||
|
/* account settings and logs */
|
||||||
|
// buttons
|
||||||
|
signUp: 'S\'inscrire',
|
||||||
|
signIn: 'Se connecter',
|
||||||
|
"Must Contain 8 Characters, One Uppercase, One Lowercase, One Number and One Special Case Character": "Doit contenir 8 caractères, une majuscule, une minuscule, un chiffre et un caractère spécial",
|
||||||
|
login: 'Se connecter',
|
||||||
|
|
||||||
|
// feedback for the user
|
||||||
usernameTooShort: 'Le nom d\'utilisateur est trop court',
|
usernameTooShort: 'Le nom d\'utilisateur est trop court',
|
||||||
passwordTooShort: 'Le mot de passe est trop court',
|
passwordTooShort: 'Le mot de passe est trop court',
|
||||||
usernameTooLong: 'Le nom d\'utilisateur est trop long',
|
usernameTooLong: 'Le nom d\'utilisateur est trop long',
|
||||||
passwordTooLong: 'Le mot de passe est trop long',
|
passwordTooLong: 'Le mot de passe est trop long',
|
||||||
username: 'Nom d\'utilisateur',
|
passwordsDontMatch: 'Les mots de passe ne correspondent pas',
|
||||||
password: 'Mot de passe',
|
|
||||||
login: 'Se connecter',
|
|
||||||
invalidCredentials: "Informations d'identification invalides",
|
invalidCredentials: "Informations d'identification invalides",
|
||||||
forgottenPassword: 'Mot de passe oublié',
|
forgottenPassword: 'Mot de passe oublié',
|
||||||
invalidEmail: 'Email invalide',
|
invalidEmail: 'Email invalide',
|
||||||
email: 'Email',
|
|
||||||
repeatPassword: 'Répéter le mot de passe',
|
|
||||||
passwordsDontMatch: 'Les mots de passe ne correspondent pas',
|
|
||||||
signUp: 'S\'inscrire',
|
|
||||||
signIn: 'Se connecter',
|
|
||||||
"Must Contain 8 Characters, One Uppercase, One Lowercase, One Number and One Special Case Character": "Doit contenir 8 caractères, une majuscule, une minuscule, un chiffre et un caractère spécial",
|
|
||||||
accountCreated: 'Compte créé',
|
accountCreated: 'Compte créé',
|
||||||
loggedIn: 'Connectado',
|
loggedIn: 'Connectado',
|
||||||
usernameTaken: 'Nombre de usuario ya tomado',
|
usernameTaken: 'Nombre de usuario ya tomado',
|
||||||
|
|
||||||
|
// categories
|
||||||
|
username: 'Nom d\'utilisateur',
|
||||||
|
password: 'Mot de passe',
|
||||||
|
email: 'Email',
|
||||||
|
repeatPassword: 'Répéter le mot de passe',
|
||||||
|
changepasswdBtn: 'Changer le mot de pass',
|
||||||
|
changeemailBtn: 'Change l\'email',
|
||||||
|
googleacctBtn: 'Compte Google',
|
||||||
};
|
};
|
||||||
@@ -2,34 +2,12 @@ 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, Progress, Button, useTheme, Heading } from 'native-base';
|
import { Box, ScrollView, Flex, useBreakpointValue, Text, VStack, Button, useTheme, Heading, Progress } 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'
|
||||||
import { Translate } from "../i18n/i18n";
|
import ProgressBar from "../components/ProgressBar";
|
||||||
|
import Translate from "../components/Translate";
|
||||||
const ProgressBar = ({ xp }: { xp: number}) => {
|
|
||||||
const level = Math.floor(xp / 1000);
|
|
||||||
const nextLevel = level + 1;
|
|
||||||
const nextLevelThreshold = nextLevel * 1000;
|
|
||||||
const progessValue = 100 * xp / nextLevelThreshold;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<VStack alignItems={'center'}>
|
|
||||||
<Text>
|
|
||||||
<Translate translationKey='level' format={(id) => `${id} ${level}`}/>
|
|
||||||
</Text>
|
|
||||||
<Box w="90%" maxW="400">
|
|
||||||
<Progress value={progessValue} mx="4" />
|
|
||||||
</Box>
|
|
||||||
<Text>
|
|
||||||
<Translate translationKey='levelProgress'
|
|
||||||
format={(levelProgress) => `${xp} / ${nextLevelThreshold} ${levelProgress}`}
|
|
||||||
/>
|
|
||||||
</Text>
|
|
||||||
</VStack>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const HomeView = () => {
|
const HomeView = () => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|||||||
@@ -0,0 +1,98 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Dimensions, View } from 'react-native';
|
||||||
|
import { Box, Image, Heading, HStack, Card, Button, Spacer, Text } from 'native-base';
|
||||||
|
import Translate from '../components/Translate';
|
||||||
|
import { useNavigation } from '@react-navigation/native';
|
||||||
|
|
||||||
|
const UserMedals = () => {
|
||||||
|
return (
|
||||||
|
<Card marginX={20} marginY={10}>
|
||||||
|
<Heading>
|
||||||
|
<Translate translationKey='medals'/>
|
||||||
|
</Heading>
|
||||||
|
<HStack alignItems={'row'} space='10'>
|
||||||
|
<Image source={{
|
||||||
|
uri: "https://wallpaperaccess.com/full/317501.jpg"
|
||||||
|
}} alt="Profile picture" size="lg"
|
||||||
|
/>
|
||||||
|
<Image source={{
|
||||||
|
uri: "https://wallpaperaccess.com/full/317501.jpg"
|
||||||
|
}} alt="Profile picture" size="lg"
|
||||||
|
/>
|
||||||
|
<Image source={{
|
||||||
|
uri: "https://wallpaperaccess.com/full/317501.jpg"
|
||||||
|
}} alt="Profile picture" size="lg"
|
||||||
|
/>
|
||||||
|
<Image source={{
|
||||||
|
uri: "https://wallpaperaccess.com/full/317501.jpg"
|
||||||
|
}} alt="Profile picture" size="lg"
|
||||||
|
/>
|
||||||
|
</HStack>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const PlayerStats = () => {
|
||||||
|
const answer = "Answer from back";
|
||||||
|
|
||||||
|
return(
|
||||||
|
<Card marginX={20} marginY={10}>
|
||||||
|
<Heading> <Translate translationKey='playerStats'/> </Heading>
|
||||||
|
<Text> <Translate translationKey='mostPlayedSong'/> {answer} </Text>
|
||||||
|
<Text> <Translate translationKey='goodNotesPlayed'/> {answer} </Text>
|
||||||
|
<Text> <Translate translationKey='longestCombo'/> {answer} </Text>
|
||||||
|
<Text> <Translate translationKey='favoriteGenre'/> {answer} </Text>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const ProfilePictureBannerAndLevel = () => {
|
||||||
|
const profilePic = "https://wallpaperaccess.com/full/317501.jpg"
|
||||||
|
const username = "Username"
|
||||||
|
const level = "1"
|
||||||
|
|
||||||
|
// banner size
|
||||||
|
const dimensions = Dimensions.get('window');
|
||||||
|
const imageHeight = dimensions.height / 5;
|
||||||
|
const imageWidth = dimensions.width;
|
||||||
|
|
||||||
|
// need to change the padding for the username and level
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={{flexDirection: 'row'}}>
|
||||||
|
<Image source={{ uri : "https://wallpaperaccess.com/full/317501.jpg" }} size="lg"
|
||||||
|
style={{ height: imageHeight, width: imageWidth, zIndex:0, opacity: 0.5 }}
|
||||||
|
/>
|
||||||
|
<Box zIndex={1} position={"absolute"} marginY={10} marginX={10}>
|
||||||
|
<Image borderRadius={100} source={{ uri: profilePic }}
|
||||||
|
alt="Profile picture" size="lg"
|
||||||
|
style= {{position: 'absolute'}}
|
||||||
|
/>
|
||||||
|
<Box w="100%" paddingY={3} paddingLeft={100}>
|
||||||
|
<Heading>{username}</Heading>
|
||||||
|
<Heading>Level : {level}</Heading>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const ProfileView = () => {
|
||||||
|
const navigation = useNavigation();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={{flexDirection: 'column'}}>
|
||||||
|
<ProfilePictureBannerAndLevel/>
|
||||||
|
<UserMedals/>
|
||||||
|
<PlayerStats/>
|
||||||
|
<Box w="10%" paddingY={10} paddingLeft={5} paddingRight={50} zIndex={1}>
|
||||||
|
<Button onPress={() => navigation.navigate('Settings')} style={{margin: 10}}>
|
||||||
|
<Translate translationKey='settingsBtn'/>
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ProfileView;
|
||||||
+1070
-1117
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user