diff --git a/.expo/README.md b/.expo/README.md new file mode 100644 index 0000000..fd146b4 --- /dev/null +++ b/.expo/README.md @@ -0,0 +1,15 @@ +> Why do I have a folder named ".expo" in my project? + +The ".expo" folder is created when an Expo project is started using "expo start" command. + +> What do the files contain? + +- "devices.json": contains information about devices that have recently opened this project. This is used to populate the "Development sessions" list in your development builds. +- "packager-info.json": contains port numbers and process PIDs that are used to serve the application to the mobile device/simulator. +- "settings.json": contains the server configuration that is used to serve the application manifest. + +> Should I commit the ".expo" folder? + +No, you should not share the ".expo" folder. It does not contain any information that is relevant for other developers working on the project, it is specific to your machine. + +Upon project creation, the ".expo" folder is already added to your ".gitignore" file. diff --git a/.expo/settings.json b/.expo/settings.json new file mode 100644 index 0000000..92bc513 --- /dev/null +++ b/.expo/settings.json @@ -0,0 +1,8 @@ +{ + "hostType": "lan", + "lanType": "ip", + "dev": true, + "minify": false, + "urlRandomness": null, + "https": false +} diff --git a/front/API.ts b/front/API.ts index 1e3a92f..90b6b11 100644 --- a/front/API.ts +++ b/front/API.ts @@ -19,7 +19,7 @@ export default class API { return { name: "User", email: "user@chromacase.com", - xp: 0, + xp: 2345, premium: false, metrics: {}, settings: {}, diff --git a/front/App.tsx b/front/App.tsx index 4cca4bf..46a8bd2 100644 --- a/front/App.tsx +++ b/front/App.tsx @@ -1,3 +1,4 @@ +import { NativeBaseProvider } from "native-base"; import Theme from './Theme'; import React from 'react'; import { QueryClient, QueryClientProvider } from 'react-query'; @@ -5,7 +6,6 @@ import { Provider } from 'react-redux'; import store from './state/Store'; import { Router } from './Navigation'; import './i18n/i18n'; -import { NativeBaseProvider } from "native-base"; const queryClient = new QueryClient(); diff --git a/front/Navigation.tsx b/front/Navigation.tsx index ff04104..466cfaa 100644 --- a/front/Navigation.tsx +++ b/front/Navigation.tsx @@ -10,7 +10,7 @@ import { translate } from './i18n/i18n'; const Stack = createNativeStackNavigator(); export const protectedRoutes = <> - + ; diff --git a/front/Theme.tsx b/front/Theme.tsx index 62725e9..5baa003 100644 --- a/front/Theme.tsx +++ b/front/Theme.tsx @@ -4,7 +4,6 @@ import { extendTheme } from 'native-base'; * Using the Material Color guidelines */ const Theme = extendTheme({ - roundness: 10, colors: { primary: { @@ -45,7 +44,7 @@ const Theme = extendTheme({ 800: '#262626', 900: '#0d0d0d', }, - accent: + secondary: { 50: '#d8ffff', 100: '#acffff', diff --git a/front/components/Card.tsx b/front/components/Card.tsx new file mode 100644 index 0000000..4ae34b6 --- /dev/null +++ b/front/components/Card.tsx @@ -0,0 +1,19 @@ +import { useTheme, Box } from 'native-base'; +import React from 'react'; + +export const CardBorderRadius = 10; + +const cardBorder = (theme: ReturnType) => ({ + borderColor: theme.colors.text[100], + borderRadius: CardBorderRadius, + borderWidth: 1 +}) + +const Card = (props: any) => { + const theme = useTheme(); + return + { props.children } + +} + +export default Card; \ No newline at end of file diff --git a/front/components/CompetenciesTable.tsx b/front/components/CompetenciesTable.tsx new file mode 100644 index 0000000..628d346 --- /dev/null +++ b/front/components/CompetenciesTable.tsx @@ -0,0 +1,38 @@ +import { useNavigation } from "@react-navigation/core"; +import { HStack, VStack, Text, Progress, Pressable } from "native-base"; +import { translate } from "../i18n/i18n"; +import Card from './Card'; + +type CompetenciesTableProps = { + pedalsCompetency: number; + rightHandCompetency: number; + leftHandCompetency: number; + accuracyCompetency: number; + arpegeCompetency: number; + chordsCompetency: number; +} + +const CompetenciesTable = (props: CompetenciesTableProps) => { + const navigation = useNavigation(); + return navigation.navigate('User')}> + {({ isHovered, isFocused }) => ( + + + + { Object.keys(props).map((competencyName) => ( + {translate(competencyName as keyof CompetenciesTableProps)} + ))} + + + { Object.keys(props).map((competencyName) => ( + + ))} + + + + + )} + +} + +export default CompetenciesTable \ No newline at end of file diff --git a/front/components/loading.tsx b/front/components/Loading.tsx similarity index 84% rename from front/components/loading.tsx rename to front/components/Loading.tsx index 019c4bb..e46a71c 100644 --- a/front/components/loading.tsx +++ b/front/components/Loading.tsx @@ -3,4 +3,6 @@ import { Spinner } from "native-base"; const LoadingComponent = () => { const theme = useTheme(); return -} \ No newline at end of file +} + +export default LoadingComponent; \ No newline at end of file diff --git a/front/components/SongCard.tsx b/front/components/SongCard.tsx new file mode 100644 index 0000000..98bc10a --- /dev/null +++ b/front/components/SongCard.tsx @@ -0,0 +1,41 @@ +import React from "react"; +import Card, { CardBorderRadius } from './Card'; +import { VStack, Text, Image, Pressable } from 'native-base'; +import { useNavigation } from "@react-navigation/core"; +type SongCardProps = { + albumCover: string; + songTitle: string; + artistName: string; + songId: number +} + +const SongCard = (props: SongCardProps) => { + const { albumCover, songTitle, artistName, songId } = props; + const navigation = useNavigation(); + return navigation.navigate('Song', { songId })}> + {({ isHovered, isFocused }) => ( + + {[props.songTitle, + + + {songTitle} + + + {artistName} + + + + )} + +} + +export default SongCard; \ No newline at end of file diff --git a/front/components/SongCardGrid.tsx b/front/components/SongCardGrid.tsx new file mode 100644 index 0000000..89ffeb7 --- /dev/null +++ b/front/components/SongCardGrid.tsx @@ -0,0 +1,26 @@ +import React from 'react'; +import SongCard from './SongCard'; +import { FlatGrid } from 'react-native-super-grid'; +import { Heading, VStack } from 'native-base'; + +type SongCardGrid = { + songs: Parameters[0][]; + maxItemPerRow?: number, + heading?: string +} + +const SongCardGrid = (props: SongCardGrid) => { + return + {props.heading} + } + spacing={20} + /> + + +} + +export default SongCardGrid; \ No newline at end of file diff --git a/front/i18n/Translations.ts b/front/i18n/Translations.ts index c0a6d94..3093038 100644 --- a/front/i18n/Translations.ts +++ b/front/i18n/Translations.ts @@ -1,23 +1,60 @@ export const en = { welcome: 'Welcome', + welcomeMessage: 'Welcome back ', signoutBtn: 'Sign out', signinBtn: 'Sign in', + changeLanguageBtn: "Change language", + searchBtn: "Search", playBtn: 'Play', + songPageBtn: 'Go to song page', level: 'Level', chapters: 'Chapters', bestScore: 'Best Score', lastScore: 'Last Score', - play: 'Play' + play: 'Play', + goNextStep: 'Step Up!', + mySkillsToImprove: "My Competencies to work on", + recentlyPlayed: 'Recently played', + search: 'Search', + lastSearched: "Last searched", + levelProgress: 'good notes', + + // competencies + pedalsCompetency: 'Pedals', + rightHandCompetency: 'Right hand', + leftHandCompetency: 'Left hand', + accuracyCompetency: 'Accuracy', + arpegeCompetency: 'Arpeges', + chordsCompetency: 'Chords', + }; export const fr: typeof en = { welcome: 'Bienvenue', + welcomeMessage: 'Re-Bonjour ', signoutBtn: 'Se déconnecter', signinBtn: 'Se connecter', + changeLanguageBtn: "Changer la langue", + searchBtn: "Rechercher", playBtn: 'Jouer', + songPageBtn: 'Aller sur la page de la chanson', level: 'Niveau', chapters: 'Chapitres', bestScore: 'Meilleur Score', lastScore: 'Dernier Score', - play: 'Jouer' + play: 'Jouer', + goNextStep: "Passer à l'étape supérieure", + mySkillsToImprove: 'Mes Competences à améliorer', + recentlyPlayed: "Récemment joués", + 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', }; \ No newline at end of file diff --git a/front/package.json b/front/package.json index 5d0a705..c7e7b49 100644 --- a/front/package.json +++ b/front/package.json @@ -36,6 +36,7 @@ "react-native": "0.68.2", "react-native-safe-area-context": "4.2.4", "react-native-screens": "~3.11.1", + "react-native-super-grid": "^4.6.1", "react-native-svg": "12.3.0", "react-native-testing-library": "^6.0.0", "react-native-web": "0.17.7", diff --git a/front/views/HomeView.test.tsx b/front/views/HomeView.test.tsx index bf0fe2c..e50b902 100644 --- a/front/views/HomeView.test.tsx +++ b/front/views/HomeView.test.tsx @@ -3,7 +3,7 @@ import { Provider } from 'react-redux'; import store from '../state/Store'; import { fireEvent, render, screen } from '@testing-library/react-native'; -import HomeView from '../views/HomeView'; +import HomeView from './HomeView'; import { en, fr } from '../i18n/Translations'; describe('', () => { diff --git a/front/views/HomeView.tsx b/front/views/HomeView.tsx index 3a3d0e3..951e135 100644 --- a/front/views/HomeView.tsx +++ b/front/views/HomeView.tsx @@ -1,34 +1,124 @@ -import { useNavigation } from "@react-navigation/native"; import React from "react"; -import { Center, Button, Text } from "native-base"; -import { useDispatch, useSelector } from "../state/Store"; -import { AvailableLanguages, DefaultLanguage, translate } from "../i18n/i18n"; -import { useLanguage } from "../state/LanguageSlice"; -import { unsetUserToken } from "../state/UserSlice"; +import { useQuery } from "react-query"; +import API from "../API"; +import LoadingComponent from "../components/Loading"; +import { Box, ScrollView, Flex, useBreakpointValue, Text, VStack, Progress, Button, useTheme, Heading, Divider } from 'native-base'; +import { useNavigation } from "@react-navigation/native"; +import SongCardGrid from '../components/SongCardGrid'; +import CompetenciesTable from '../components/CompetenciesTable' +import { translate } from "../i18n/i18n"; + +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 HomeView = () => { - const dispatch = useDispatch(); - const navigation = useNavigation(); - const language: AvailableLanguages = useSelector((state) => state.language.value); return ( -
- This is the Home Screen - - - - Current language: {language} -
+ + {`${translate('level')} ${level}`} + + + + {xp} / {nextLevelThreshold} {translate('levelProgress')} + ); } +const HomeView = () => { + const theme = useTheme(); + const navigation = useNavigation(); + const screenSize = useBreakpointValue({ base: 'small', md: "big"}); + const flexDirection = useBreakpointValue({ base: 'column', xl: "row"}); + const userQuery = useQuery(['user'], () => API.getUserInfo()); + + if (!userQuery.data) { + return + + + } + return + + + + {`${translate('welcome')} ${userQuery.data.name}!`} + + + + + + + + ({ + albumCover: "", + songTitle: "Song", + artistName: "Artist", + songId: 1 + }))} + /> + + + + {translate('mySkillsToImprove')} + + + + + + + + + ({ + albumCover: "", + songTitle: "Song", + artistName: "Artist", + songId: 1 + }))} + /> + + + + + + + + + + + + + + + + ({ + albumCover: "", + songTitle: "Song", + artistName: "Artist", + songId: 1 + }))} + /> + + + + + + + +} + export default HomeView; diff --git a/front/views/SongLobbyView.tsx b/front/views/SongLobbyView.tsx index 7b0d3d3..c8fbe57 100644 --- a/front/views/SongLobbyView.tsx +++ b/front/views/SongLobbyView.tsx @@ -2,7 +2,7 @@ import { useRoute } from "@react-navigation/native"; import { Button, Divider, Box, Center, Image, Text, VStack, PresenceTransition, Icon } from "native-base"; import API from "../API"; import { useQuery } from 'react-query'; -import LoadingComponent from "../components/loading"; +import LoadingComponent from "../components/Loading"; import React, { useEffect, useState } from "react"; import logo from '../assets/cover.png'; import { translate } from "../i18n/i18n"; diff --git a/front/yarn.lock b/front/yarn.lock index 68a597d..eae09d3 100644 --- a/front/yarn.lock +++ b/front/yarn.lock @@ -8201,6 +8201,13 @@ react-native-screens@~3.11.1: react-freeze "^1.0.0" warn-once "^0.1.0" +react-native-super-grid@^4.6.1: + version "4.6.1" + resolved "https://registry.yarnpkg.com/react-native-super-grid/-/react-native-super-grid-4.6.1.tgz#620a59e98375dd5138d3e6618991d09e93cbe318" + integrity sha512-YEKN//TT3DZlbz+1m6YqnclYS+T/Qn2ELrZ0fjoXzB2U/AQoBflvtw0VsJkcPkf3RGWLbD1GKbKN6Hz9fPCVfg== + dependencies: + prop-types "^15.6.0" + react-native-svg@12.3.0: version "12.3.0" resolved "https://registry.yarnpkg.com/react-native-svg/-/react-native-svg-12.3.0.tgz#40f657c5d1ee366df23f3ec8dae76fd276b86248"