parent
42f873b48c
commit
b59f0d961c
@ -1,8 +1,8 @@
|
||||
import {SafeAreaView, StyleSheet} from 'react-native';
|
||||
import React from "react";
|
||||
import BottomTabNavigator from "@react-navigation/bottom-tabs/src/navigators/createBottomTabNavigator";
|
||||
import NavigationBar from "./componente/NavigationBar";
|
||||
import NavigationBar from "./componente/Navigation/NavigationBar";
|
||||
import {Provider} from "react-redux";
|
||||
|
||||
import store from "./redux/store";
|
||||
|
||||
export default function App() {
|
@ -0,0 +1,45 @@
|
||||
export class Album{
|
||||
private _id: number;
|
||||
private _name: string;
|
||||
private _coverUrl: string
|
||||
private _date: Date;
|
||||
|
||||
constructor(id: number, name: string, coverUrl: string, date: Date) {
|
||||
this._id = id;
|
||||
this._name = name;
|
||||
this._coverUrl = coverUrl;
|
||||
this._date = date;
|
||||
}
|
||||
|
||||
get id(): number {
|
||||
return this._id;
|
||||
}
|
||||
|
||||
set id(value: number) {
|
||||
this._id = value;
|
||||
}
|
||||
|
||||
get name(): string {
|
||||
return this._name;
|
||||
}
|
||||
|
||||
set name(value: string) {
|
||||
this._name = value;
|
||||
}
|
||||
|
||||
get coverUrl(): string {
|
||||
return this._coverUrl;
|
||||
}
|
||||
|
||||
set coverUrl(value: string) {
|
||||
this._coverUrl = value;
|
||||
}
|
||||
|
||||
get date(): Date {
|
||||
return this._date;
|
||||
}
|
||||
|
||||
set date(value: Date) {
|
||||
this._date = value;
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
// @ts-ignore
|
||||
import React from 'react';
|
||||
import {View, Image, Text, StyleSheet} from 'react-native';
|
||||
|
||||
const AlbumCard = ({ album }) => {
|
||||
console.log(album);
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Image source={{ uri: album.coverUrl }} style={styles.image}/>
|
||||
<Text style={styles.name}>{album.name}</Text>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
margin: 10,
|
||||
},
|
||||
image: {
|
||||
width: 50,
|
||||
height: 50,
|
||||
marginRight: 10,
|
||||
},
|
||||
name: {
|
||||
fontSize: 20,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
});
|
||||
|
||||
export default AlbumCard;
|
@ -0,0 +1,27 @@
|
||||
import React from "react";
|
||||
import {FlatList, ScrollView, StyleSheet, View} from "react-native";
|
||||
import AlbumCard from "./AlbumCard";
|
||||
|
||||
const ArtistList = ({ALBUM_LIST}) => {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<FlatList
|
||||
data={ALBUM_LIST}
|
||||
renderItem={({ item }) => (
|
||||
<AlbumCard album={item} />
|
||||
)}
|
||||
keyExtractor={(item) => item.name}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
height: 400,
|
||||
}
|
||||
});
|
||||
|
||||
export default ArtistList;
|
||||
|
||||
|
@ -1,19 +1,23 @@
|
||||
import {createBottomTabNavigator} from "@react-navigation/bottom-tabs";
|
||||
import {NavigationContainer} from "@react-navigation/native";
|
||||
import {AntDesign, Ionicons} from '@expo/vector-icons';
|
||||
import SettingsPage from "./SettingsPage";
|
||||
import HomePage from "./HomePage";
|
||||
import StackNavigation from "./StackNavigation";
|
||||
import SettingsPage from "../SettingsPage";
|
||||
import StackNavigationHomePage from "./StackNavigationHomePage";
|
||||
import StackNavigationSearchPage from "./StackNavigationSearchPage";
|
||||
|
||||
export default function NavigationBar() {
|
||||
const BottomTabNavigator = createBottomTabNavigator();
|
||||
return (
|
||||
<NavigationContainer >
|
||||
<BottomTabNavigator.Navigator initialRouteName="HomeNav" screenOptions={{headerShown: false}}>
|
||||
<BottomTabNavigator.Screen name="HomeNav" component={StackNavigation} options={{
|
||||
<BottomTabNavigator.Screen name="HomeNav" component={StackNavigationHomePage} options={{
|
||||
title: 'Home',
|
||||
tabBarIcon: () => (<AntDesign name="home" size={24} color="black" />)
|
||||
}}/>
|
||||
<BottomTabNavigator.Screen name="Search" component={StackNavigationSearchPage} options={{
|
||||
title: 'Search',
|
||||
tabBarIcon: () => (<AntDesign name="search1" size={24} color="black" />)
|
||||
}}/>
|
||||
<BottomTabNavigator.Screen name="Settings" component={SettingsPage} options={{
|
||||
title: 'Settings',
|
||||
tabBarIcon: () => (<Ionicons name="settings-outline" size={24} color="black" />)
|
@ -1,15 +1,12 @@
|
||||
// @ts-ignore
|
||||
import React from "react";
|
||||
import {NavigationContainer} from "@react-navigation/native";
|
||||
import {createStackNavigator} from "@react-navigation/stack";
|
||||
import SettingsPage from "./SettingsPage";
|
||||
import HomePage from "./HomePage";
|
||||
import ArtistePage from "./Artist/ArtistePage";
|
||||
import NavigationBar from "./NavigationBar";
|
||||
import HomePage from "../HomePage";
|
||||
import ArtistePage from "../Artist/ArtistePage";
|
||||
|
||||
const Stack = createStackNavigator();
|
||||
|
||||
export default function StackNavigation() {
|
||||
export default function StackNavigationHomePage() {
|
||||
return (
|
||||
<Stack.Navigator initialRouteName="Home">
|
||||
<Stack.Screen name="Home" component={HomePage}/>
|
@ -0,0 +1,17 @@
|
||||
// @ts-ignore
|
||||
import React from "react";
|
||||
import {createStackNavigator} from "@react-navigation/stack";
|
||||
import HomePage from "../HomePage";
|
||||
import ArtistePage from "../Artist/ArtistePage";
|
||||
import SearchPage from "../SearchPage";
|
||||
|
||||
const Stack = createStackNavigator();
|
||||
|
||||
export default function StackNavigationSearchPage() {
|
||||
return (
|
||||
<Stack.Navigator initialRouteName="Home">
|
||||
<Stack.Screen name="Search" component={SearchPage}/>
|
||||
<Stack.Screen name="ArtistDetail" component={ArtistePage}/>
|
||||
</Stack.Navigator>
|
||||
)
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
import React, { useState } from "react";
|
||||
import { TextInput, TouchableOpacity, View, StyleSheet } from "react-native";
|
||||
import { AntDesign } from "@expo/vector-icons";
|
||||
import {searchArtists} from "../redux/actions/action";
|
||||
import {useDispatch, useSelector} from "react-redux";
|
||||
|
||||
const SearchBar = () => {
|
||||
const [searchText, setSearchText] = useState("");
|
||||
|
||||
const dispatch = useDispatch();
|
||||
const handleSearch = () => {
|
||||
console.log(searchText)
|
||||
const loadArtist = async () => {
|
||||
// @ts-ignore
|
||||
await dispatch(searchArtists(searchText));
|
||||
};
|
||||
loadArtist();
|
||||
};
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<TextInput style={styles.input} value={searchText} onChangeText={setSearchText} placeholder="Search"/>
|
||||
<TouchableOpacity onPress={handleSearch}>
|
||||
<AntDesign name="search1" size={24} color="black" />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
backgroundColor: "#FFFFFF",
|
||||
borderRadius: 5,
|
||||
margin: 10,
|
||||
paddingHorizontal: 5,
|
||||
},
|
||||
input: {
|
||||
flex: 1,
|
||||
fontSize: 18,
|
||||
paddingVertical: 10,
|
||||
},
|
||||
});
|
||||
|
||||
export default SearchBar;
|
@ -0,0 +1,18 @@
|
||||
import React from "react";
|
||||
import ArtistList from "./Artist/ArtistList";
|
||||
import {View} from "react-native";
|
||||
import SearchBar from "./SearchBar";
|
||||
|
||||
|
||||
const SearchPage = ({ navigation }) => {
|
||||
return (
|
||||
<View>
|
||||
<SearchBar/>
|
||||
<ArtistList navigation={navigation} type={"search"}/>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default SearchPage;
|
||||
|
||||
|
@ -1,68 +0,0 @@
|
||||
import {FETCH_ARTISTE,ACCESS_TOKEN} from '../constants';
|
||||
import {Artist} from "../../Model/Artist";
|
||||
|
||||
|
||||
export const setArtistList = (artistList: Artist[]) => {
|
||||
return {
|
||||
type: FETCH_ARTISTE,
|
||||
payload: artistList,
|
||||
};
|
||||
}
|
||||
|
||||
export const getArtistList = (recherche) => {
|
||||
return async dispatch => {
|
||||
try{
|
||||
const response = await fetch(`https://genius.com/api/search/artists?q=${encodeURIComponent(recherche)}`);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Network response was not ok');
|
||||
}
|
||||
|
||||
const artistListJson = await response.json();
|
||||
console.log(artistListJson);
|
||||
|
||||
|
||||
/*artistListJson.response.hits.map((hit: any) =>
|
||||
/*new Artist(hit.result.name, hit.result.image_url)*/
|
||||
//console.log(hit)
|
||||
//);
|
||||
const artistList: Artist[] = artistListJson.response.sections[0].hits.map(hit => new Artist(hit.result.name, hit.result.image_url));
|
||||
|
||||
console.log(artistList);
|
||||
|
||||
|
||||
dispatch(setArtistList(artistList));
|
||||
} catch (error) {
|
||||
console.error('Error:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const getArtistInfo = (idArtist) => {
|
||||
return async dispatch => {
|
||||
try{
|
||||
const response = await fetch(`https://api.genius.com/artists/${idArtist}`, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${ACCESS_TOKEN}`
|
||||
}
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Network response was not ok');
|
||||
}
|
||||
|
||||
const artistInfoJson = await response.json();
|
||||
console.log(artistInfoJson);
|
||||
|
||||
|
||||
/*const artistList: Artist[] = artistListJson.response.hits.map((hit: any) =>
|
||||
new Artist(hit.result.primary_artist.name, hit.result.primary_artist.age)
|
||||
);*/
|
||||
|
||||
|
||||
//dispatch(setArtistList(artistList));
|
||||
} catch (error) {
|
||||
console.error('Error:', error);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,114 @@
|
||||
import {FETCH_ARTISTE_SEARCH,ACCESS_TOKEN} from '../constants';
|
||||
import {Artist} from "../../Model/Artist";
|
||||
import {Album} from "../../Model/Album";
|
||||
|
||||
|
||||
export const setArtistList = (artistList: Artist[]) => {
|
||||
return {
|
||||
type: FETCH_ARTISTE_SEARCH,
|
||||
payload: artistList,
|
||||
};
|
||||
}
|
||||
|
||||
export const searchArtists = (recherche) => {
|
||||
console.log("getArtistList");
|
||||
return async dispatch => {
|
||||
try{
|
||||
const response = await fetch(`https://genius.com/api/search/artists?page=1&q=${encodeURIComponent(recherche)}`);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('[searchArtists] Network response was not ok');
|
||||
}
|
||||
|
||||
const artistListJson = await response.json();
|
||||
console.log(artistListJson);
|
||||
|
||||
console.log("ici")
|
||||
const artistList: Artist[] = artistListJson.response.sections[0].hits.map(hit =>
|
||||
new Artist(hit.result.id, hit.result.name, hit.result.image_url,"")
|
||||
);
|
||||
|
||||
dispatch(setArtistList(artistList));
|
||||
} catch (error) {
|
||||
console.error('Error:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const getArtistInfo = (artist) => {
|
||||
console.log(artist._id)
|
||||
return async dispatch => {
|
||||
try{
|
||||
const response = await fetch(`https://api.genius.com/artists/${artist._id}`, {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${ACCESS_TOKEN}`,
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
console.log(response);
|
||||
throw new Error('[getArtistInfo] Network response was not ok');
|
||||
}
|
||||
|
||||
const artistInfoJson = await response.json();
|
||||
artist.bio = artistInfoJson.response.artist.description.dom.children[0].children[0];
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const getSongByArtist = (artist) => {
|
||||
return async dispatch => {
|
||||
try{
|
||||
const response = await fetch(`https://api.genius.com/artists/${artist.id}/songs`, {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${ACCESS_TOKEN}`,
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
console.log(response);
|
||||
throw new Error('[getSongByArtist] Network response was not ok');
|
||||
}
|
||||
|
||||
const artistSongsJson = await response.json();
|
||||
console.log(artistSongsJson);
|
||||
artistSongsJson.response.songs.map((hit: any) => console.log(hit));
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const getAlbumByArtist = (artist) => {
|
||||
return async dispatch => {
|
||||
try{
|
||||
const response = await fetch(`https://genius.com/api/artists/${artist.id}/albums`)
|
||||
|
||||
if (!response.ok) {
|
||||
console.log(response);
|
||||
throw new Error('[getAlbumByArtist] Network response was not ok');
|
||||
}
|
||||
|
||||
const artistAlbumJson = await response.json();
|
||||
const albumList: Album[] = artistAlbumJson.response.albums.map((album: any) =>
|
||||
new Album(album.id,
|
||||
album.name,
|
||||
album.cover_art_thumbnail_url,
|
||||
// @ts-ignore
|
||||
Date(album.release_date_components.day, album.release_date_components.month, album.release_date_components.year)
|
||||
)
|
||||
);
|
||||
artist.listAlbum = albumList;
|
||||
console.log(artist.listAlbum);
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error:', error);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
export const FETCH_ARTISTE = 'FETCH_ARTISTE';
|
||||
|
||||
export const ACCESS_TOKEN = 'nhmGn3gceDRH04YeeCqOSg1nD3cAXxIM_MOAOdh7lADuizSGEIuhAIT1dZ6hmkDU';
|
@ -0,0 +1,5 @@
|
||||
export const FETCH_ARTISTE = 'FETCH_ARTISTE';
|
||||
export const FETCH_ARTISTE_SEARCH = 'FETCH_ARTISTE_SEARCH';
|
||||
|
||||
|
||||
export const ACCESS_TOKEN = 'M0GAzZXbwqfifGOTxfB7lLmEWlRNadkFGV99E9SQCgirIX58kbcvEFYhu2WajbGH';
|
@ -1,14 +0,0 @@
|
||||
import {FETCH_ARTISTE} from '../constants';
|
||||
|
||||
const initialState = {
|
||||
artists: [],
|
||||
}
|
||||
|
||||
export default function appReducer(state = initialState, action){
|
||||
switch (action.type) {
|
||||
case FETCH_ARTISTE:
|
||||
return {...state, artists: action.payload};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
import {FETCH_ARTISTE, FETCH_ARTISTE_SEARCH} from '../constants';
|
||||
|
||||
const initialState = {
|
||||
artists: [],
|
||||
artistsSearch: []
|
||||
}
|
||||
|
||||
export default function ReducerArtist(state = initialState, action){
|
||||
switch (action.type) {
|
||||
case FETCH_ARTISTE:
|
||||
// @ts-ignore
|
||||
return {...state, artists: action.payload};
|
||||
case FETCH_ARTISTE_SEARCH:
|
||||
return {...state, artistsSearch: action.payload};
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
import {configureStore} from '@reduxjs/toolkit'
|
||||
import appReducer from './reducers/reducer';
|
||||
|
||||
// Reference here all your application reducers
|
||||
const reducer = {
|
||||
appReducer: appReducer,
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
const store = configureStore({
|
||||
reducer,
|
||||
},
|
||||
);
|
||||
|
||||
export default store;
|
@ -0,0 +1,15 @@
|
||||
import {configureStore} from '@reduxjs/toolkit'
|
||||
import ReducerArtist from './reducers/reducerArtist';
|
||||
|
||||
// Reference here all your application reducers
|
||||
const reducer = {
|
||||
ReducerArtist: ReducerArtist,
|
||||
}
|
||||
|
||||
const store = configureStore(
|
||||
{
|
||||
reducer,
|
||||
middleware: (getDefaultMiddleware ) => getDefaultMiddleware({serializableCheck : false})
|
||||
} );
|
||||
|
||||
export default store;
|
Loading…
Reference in new issue