Merge pull request 'CardDetail' (#9) from CardDetail into master

Reviewed-on: #9
master
Corentin RICHARD 2 years ago
commit d1f1268395

@ -1,52 +1,18 @@
import { useDispatch } from "react-redux"; import { View } from 'react-native';
import { Card } from "../models/Card"; import { Image } from 'react-native';
import { setFavList } from "../redux/actions/action_setFavList";
import { ImageBackground, TouchableHighlight, View } from "react-native";
import React, { useEffect } from "react";
import {CardProps} from "../props/favProps"
import { FontAwesome } from '@expo/vector-icons';
import { StyleSheet} from 'react-native';
export default function Item(props: CardProps){ // a mettre dans components et definir une props pour passer le param
const {route} = props; type ItemProps = {
const item: Card = route.card; url : string //Image URL
const bool: boolean = route.bool;
const dispatch = useDispatch()
const HandleAddFav = (props : CardProps) => {
dispatch(setFavList(props));
}
return(
/* dispatch , */
<View style={styles.item}>
<ImageBackground testID="card-url" source={{uri:item.img}} style={{flex:1, minHeight:250, minWidth:180}}>
<TouchableHighlight testID="button" style={item.fav?styles.favoriteButtonFav:styles.favoriteButtonNonFav} onPress={() => HandleAddFav(props)} >
<FontAwesome name="heart-o" size={50} color="#fff" />
</TouchableHighlight>
</ImageBackground>
</View>
);
} }
const styles = StyleSheet.create({
item: {
}, export function ListItemComponent(props : ItemProps){
favoriteButtonNonFav: { return (
position: 'absolute', <View>
top: 10, <Image
right: 10, source={{uri: props.url}}
backgroundColor: 'red', style={{flex:1, minHeight:250, minWidth:180}}
borderRadius: 50, />
padding: 10, </View>
}, )
favoriteButtonFav: { }
position: 'absolute',
top: 10,
right: 10,
backgroundColor: 'red',
borderRadius: 50,
padding: 10,
},});

@ -0,0 +1,55 @@
import { useDispatch } from "react-redux";
import { Card } from "../models/Card";
import { setFavList } from "../redux/actions/action_setFavList";
import { Image, TouchableHighlight, View } from "react-native";
import React, { useEffect } from "react";
import {CardProps} from "../props/favProps"
import { FontAwesome } from '@expo/vector-icons';
import { StyleSheet} from 'react-native';
export default function Item(props: CardProps){ // a mettre dans components et definir une props pour passer le param
const {route} = props;
const item: Card = route.card;
const bool: boolean = route.bool;
const dispatch = useDispatch()
const HandleAddFav = (props : CardProps) => {
dispatch(setFavList(props));
}
return(
/* dispatch , */
<View style={styles.item}>
<TouchableHighlight testID="button" style={item.fav?styles.favoriteButtonFav:styles.favoriteButtonNonFav} onPress={() => HandleAddFav(props)} >
<FontAwesome name="heart-o" size={50} color="#fff" />
</TouchableHighlight>
<Image
source={{uri:item.img}}
style={{flex:1, minHeight:250, minWidth:180}}/>
</View>
);
}
const styles = StyleSheet.create({
item: {
zIndex:0
},
favoriteButtonNonFav: {
position: 'absolute',
top: 10,
right: 10,
backgroundColor: 'red',
borderRadius: 50,
padding: 10,
zIndex:1
},
favoriteButtonFav: {
position: 'absolute',
top: 10,
right: 10,
backgroundColor: 'red',
borderRadius: 50,
padding: 10,
zIndex:1
},});

@ -1,27 +1,107 @@
export class Card { export class Card {
constructor(id: string,name :string, img : string, imgGold : string,fav : boolean = true){ constructor(id: string,name :string,health : string, attack : string, manaCost : string, rarityId : string, flavorText : string, classId : string, multiClassIds : any, img : string, imgGold : string, cropImage : string, artistName : string, fav : boolean){
this.id=id this.id=id
this.name=name this.name=name
//this._set=set
// this._type=type
// this._class=clas
// this._rarity=rarity
this.manaCost=manaCost
this.attack = attack
this.health = health
this.rarityId = rarityId
// this._desc = desc
this.flavorText = flavorText
this.classId = classId
this.multiClassIds = multiClassIds
this.artistName = artistName
// this._collectible = collectible
this.img = img this.img = img
this.imgGold = imgGold this.imgGold = imgGold
this.cropImage = cropImage
this.fav = fav this.fav = fav
} }
// ID // // ID //
public id; public id: string;
// NAME // // NAME //
public name; public name: string
// set set(value : CardSet){
// this._set = value
// }
// private _type : Type;
// get type():Type{
// return this._type
// }
// set type(value : Type){
// this._type=value
// }
// private _class : Classe;
// get class():Classe{
// return this._class
// }
// set class(value : Classe){
// this._class=value
// }
// private _rarity : string
// get rarity(): string {
// return this._rarity;
// }
// set rarity(value: string) {
// this._rarity = value ;
// }
public manaCost : string;
public attack : string;
public health : string;
// private _desc : string
// get desc(): string {
// return this._desc;
// }
// set desc(value: string) {
// this._desc = value ;
// }
public classId : string;
public flavorText : string
public rarityId : string
public multiClassIds : any;
public artistName : string;
// private _collectible : boolean
// get collectible(): boolean {
// return this._collectible;
// }
// set collectible(value: boolean ){
// this._collectible = value;
// }
//IMG// public img : string;
public img; public imgGold : string;
//IMGGOLD// public cropImage : string;
public imgGold; //FAV//
public fav : boolean;
//FAV//
public fav;
} }

@ -0,0 +1,17 @@
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import {createNativeStackNavigator} from '@react-navigation/native-stack';
import ListScreen from '../screens/ListScreen';
import DetailCard from '../screens/DetailCard';
export default function DetailStackNav() {
const Stack = createStackNavigator();
return (
<Stack.Navigator initialRouteName="CardList">
<Stack.Screen name="CardList" component={ListScreen}/>
<Stack.Screen name="DetailCard" component={DetailCard}/>
</Stack.Navigator>
)
}

@ -7,13 +7,14 @@ import ListFav from '../screens/ListFav';
import TabBarIcon from '../components/TabBarIcon'; import TabBarIcon from '../components/TabBarIcon';
import StackNavigation from './StackNavigation'; import StackNavigation from './StackNavigation';
import DetailStackNav from './DetailStackNav';
export default function Navigation() { export default function Navigation() {
const BottomTabNavigator = createBottomTabNavigator(); const BottomTabNavigator = createBottomTabNavigator();
return ( return (
<NavigationContainer> <NavigationContainer>
<BottomTabNavigator.Navigator initialRouteName="Home"> <BottomTabNavigator.Navigator initialRouteName="Home">
<BottomTabNavigator.Screen name="List" component={ListScreen} <BottomTabNavigator.Screen name="List" component={DetailStackNav}
options={{ options={{
title: 'List', title: 'List',
tabBarIcon: ({color}) => <TabBarIcon name="th-large" color={color}/>, tabBarIcon: ({color}) => <TabBarIcon name="th-large" color={color}/>,

14037
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -10,7 +10,9 @@
"test": "jest" "test": "jest"
}, },
"jest": { "jest": {
"setupFiles": ["./test/setup/jestSetupFile.js"], "setupFiles": [
"./test/setup/jestSetupFile.js"
],
"preset": "jest-expo", "preset": "jest-expo",
"verbose": true, "verbose": true,
"transformIgnorePatterns": [ "transformIgnorePatterns": [
@ -30,6 +32,7 @@
}, },
"dependencies": { "dependencies": {
"@jest/globals": "^29.5.0", "@jest/globals": "^29.5.0",
"@react-native-async-storage/async-storage": "1.17.11",
"@react-navigation/bottom-tabs": "^6.5.5", "@react-navigation/bottom-tabs": "^6.5.5",
"@react-navigation/native": "^6.1.4", "@react-navigation/native": "^6.1.4",
"@react-navigation/native-stack": "^6.9.10", "@react-navigation/native-stack": "^6.9.10",
@ -46,6 +49,7 @@
"react-native": "0.71.3", "react-native": "0.71.3",
"react-native-gesture-handler": "~2.9.0", "react-native-gesture-handler": "~2.9.0",
"react-native-safe-area-context": "4.5.0", "react-native-safe-area-context": "4.5.0",
"react-native-table-component": "^1.2.2",
"react-native-web": "~0.18.11", "react-native-web": "~0.18.11",
"react-redux": "^8.0.5", "react-redux": "^8.0.5",
"redux": "^4.2.1" "redux": "^4.2.1"
@ -56,6 +60,7 @@
"@types/jest": "^29.5.0", "@types/jest": "^29.5.0",
"@types/react": "~18.0.27", "@types/react": "~18.0.27",
"@types/react-native": "~0.70.6", "@types/react-native": "~0.70.6",
"@types/react-native-table-component": "^1.2.4",
"typescript": "^4.9.4" "typescript": "^4.9.4"
}, },
"private": true "private": true

@ -28,8 +28,17 @@ export const getAllCards = () => {
//@ts-ignore //@ts-ignore
const CardsList: Card[] = CardsListJson['cards'].map(elt => new Card(elt["id"] ? elt["id"] : 1, const CardsList: Card[] = CardsListJson['cards'].map(elt => new Card(elt["id"] ? elt["id"] : 1,
elt["name"] ? elt["name"] : "", elt["name"] ? elt["name"] : "",
elt["health"] ? elt["health"] : 0,
elt["attack"] ? elt["attack"] : 0,
elt["manaCost"] ? elt["manaCost"] : 0,
elt["rarityId"] ? elt["rarityId"] : 0,
elt["flavorText"] ? elt["flavorText"] : "",
elt["classId"] ? elt["classId"] : 0,
elt["multiClassIds"] ? elt["multiClassIds"] : "Nothing",
elt["image"] ? elt["image"] : "", elt["image"] ? elt["image"] : "",
elt["imageGold"] ? elt["imageGold"] : "", elt["imageGold"] ? elt["imageGold"] : "",
elt["cropImage"] ? elt["cropImage"] : "",
elt["artistName"] ? elt["artistName"] : "",
)); //, elt["cardSet"], elt["type"], elt["faction"], elt["rarity"], elt["cost"], elt["attack"], elt["health"],elt["text"], elt["flavor"], elt["artist"], elt["collectible"], elt["elite"], elt["race"], elt["img"], elt["imgGold"] )); //, elt["cardSet"], elt["type"], elt["faction"], elt["rarity"], elt["cost"], elt["attack"], elt["health"],elt["text"], elt["flavor"], elt["artist"], elt["collectible"], elt["elite"], elt["race"], elt["img"], elt["imgGold"]
//elt["cardId"] == null ? elt["cardId"] : "" //elt["cardId"] == null ? elt["cardId"] : ""

@ -20,7 +20,8 @@ export default appReducer = (state = initialState, action) => {
StorageHeart.setItem("favoriteList",tab) StorageHeart.setItem("favoriteList",tab)
return {...state, favoriteCards : tab}; return {...state, favoriteCards : tab};
} }
if( Array.from(state.favoriteCards).every((elem) => elem != a.route.card)){ //@ts-ignore
if( Array.from(state.favoriteCards).every((elem) => elem.id != a.route.card.id)){
//@ts-ignore //@ts-ignore
const tab = state.favoriteCards.concat([a.route.card]) const tab = state.favoriteCards.concat([a.route.card])

@ -0,0 +1,91 @@
import { StyleSheet, Text, View, Button, FlatList } from 'react-native';
import { StatusBar } from 'expo-status-bar';
import React, { useState } from "react";
import { Card } from '../models/Card';
import { Table, Row, Rows } from 'react-native-table-component';
//* Components
import {ListItemComponent} from '../components/ListItemComponent'
import { ScrollView } from 'react-native-gesture-handler';
//@ts-ignore
export default function DetailMain({ route }){
const { card, other } = route.params;
const tableHead = ['Stat', 'Value'];
const tableData = [
['Mana cost :', card.manaCost],
['Attack : ', card.attack],
['Health : ', card.health],
['Rarity : ', card.rarity],
['Artist : ', card.artistName],
['Class : ', card.classId],
]
let pressed : Boolean = false
const [titleText, setTitleText] = useState(card.name)
const onPressTitle = () => {
pressed ? setTitleText(titleText + '\n' + 'Id : ' + card.id) : setTitleText(card.name)
pressed ? pressed = false :pressed = true
};
return (
<View style={styles.container}>
<View style={styles.titleView}>
<Text style={styles.title} onPress={onPressTitle} >{titleText}</Text>
<Text style={styles.flavor}>{card.flavorText}</Text>
</View>
<View style={styles.item}>
<ListItemComponent url={card.img}/>
</View>
<ScrollView>
<Table borderStyle={{borderWidth: 5, borderColor: '#c8e1ff'}}>
<Row data={tableHead} style={styles.head} textStyle={styles.text}/>
<Rows data={tableData} textStyle={styles.text}/>
</Table>
</ScrollView>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
item: {
borderRadius : 15,
backgroundColor: '#efefef',
padding: 15,
maxHeight:300,
maxWidth:350,
},
title: {
fontStyle: "italic",
fontWeight: "bold",
fontSize: 20,
},
flavor: {
fontStyle: "italic",
},
titleView: {
flex: 1,
justifyContent: 'center',
paddingVertical: 0,
paddingHorizontal : 15,
backgroundColor: '#fff',
borderRadius : 10,
borderWidth: 10,
borderColor: '#efefef',
maxHeight:100,
minHeight: 100
},
head: { height: 40, backgroundColor: '#f1f8ff', minWidth: '90%'},
text: { margin: 6 }
});

@ -17,8 +17,11 @@ export default function HomeScreen({navigation}) {
const loadFavCards = async () => { const loadFavCards = async () => {
//@ts-ignore //@ts-ignore
const list = await StorageHeart.getItem("favoriteList") const list = await StorageHeart.getItem("favoriteList")
//@ts-ignore
dispatch(setList(list)) if(list!=null){
//@ts-ignore
dispatch(setList(list))
}
}; };
loadFavCards(); loadFavCards();
@ -32,7 +35,6 @@ export default function HomeScreen({navigation}) {
loadCards(); loadCards();
}, [dispatch]); }, [dispatch]);
const tabNav = Navigation()
// affichage de la homePage // affichage de la homePage

@ -5,7 +5,7 @@ import { FlatList } from 'react-native-gesture-handler';
import {useSelector} from 'react-redux'; import {useSelector} from 'react-redux';
import { Card } from '../models/Card'; import { Card } from '../models/Card';
import Item from '../components/ListItemComponent'; import Item from '../components/ListeFavComponent';
@ -28,14 +28,14 @@ export default function ListScreen({navigation}){
style={styles.textInput} style={styles.textInput}
value={searchValue} value={searchValue}
onChangeText={text => setSearchValue(text)} onChangeText={text => setSearchValue(text)}
placeholder="Rechercher une carte..." placeholder="Rechercher une carte...."
/> />
<FlatList <FlatList
numColumns={2} numColumns={2}
data={filteredList} data={filteredList}
renderItem={({item}) => renderItem={({item}) =>
<TouchableHighlight onPress={() => navigation.navigate("ListFav")}> <TouchableHighlight onPress={() => navigation.navigate("DetailCard", {card :item, other : 'anything'})}>
<Item route={{ <Item route={{
card: item, card: item,
bool: true bool: true

@ -4,10 +4,14 @@ import React, { useState} from "react";
import { FlatList } from 'react-native-gesture-handler'; import { FlatList } from 'react-native-gesture-handler';
import {useSelector} from 'react-redux'; import {useSelector} from 'react-redux';
import { Card } from '../models/Card'; import { Card } from '../models/Card';
import { FontAwesome } from '@expo/vector-icons';
import { useDispatch } from "react-redux";
import {CardProps} from "../props/favProps";
import { setFavList } from "../redux/actions/action_setFavList";
//* Components //* Components
import Item from '../components/ListItemComponent'; import { ListItemComponent } from '../components/ListItemComponent';
import Item from '../components/ListeFavComponent';
//@ts-ignore //@ts-ignore
export default function ListScreen({navigation}){ export default function ListScreen({navigation}){
@ -20,6 +24,11 @@ export default function ListScreen({navigation}){
//@ts-ignore //@ts-ignore
const filteredList = nList.filter(item => item.name.toLowerCase().includes(searchValue.toLowerCase())); const filteredList = nList.filter(item => item.name.toLowerCase().includes(searchValue.toLowerCase()));
const dispatch = useDispatch()
const HandleAddFav = (props : CardProps) => {
dispatch(setFavList(props));
}
return ( return (
<View style={styles.container}> <View style={styles.container}>
@ -34,14 +43,18 @@ export default function ListScreen({navigation}){
numColumns={2} numColumns={2}
data={filteredList} data={filteredList}
renderItem={({item}) => renderItem={({item}) =>
<TouchableHighlight onPress={() => navigation.navigate("ListFav")}> <View>
<Item route={{
<TouchableHighlight style={styles.imageItem} onPress={() => navigation.navigate("DetailCard", {card :item, other : 'anything'})}>
<Item route={{
card: item, card: item,
bool: false bool: false
}} ></Item> }} ></Item>
</TouchableHighlight> </TouchableHighlight>
</View>
} }
keyExtractor={(item: Card) => item.id.toString()} keyExtractor={(item: Card) => item.id}
/> />
</View> </View>
@ -50,8 +63,10 @@ export default function ListScreen({navigation}){
} }
const styles = StyleSheet.create({ const styles = StyleSheet.create({
imageItem:{
zIndex : 0
},
container: { container: {
flex: 1, flex: 1,
backgroundColor: '#ac9585', backgroundColor: '#ac9585',
@ -67,6 +82,24 @@ const styles = StyleSheet.create({
borderRadius : 15, borderRadius : 15,
shadowColor: 'grey', shadowColor: 'grey',
textAlign:'center' textAlign:'center'
},
favoriteButtonNonFav: {
position: 'absolute',
top: 10,
right: 10,
backgroundColor: 'red',
borderRadius: 50,
padding: 10,
zIndex : 1,
},
favoriteButtonFav: {
position: 'absolute',
top: 10,
right: 10,
backgroundColor: 'red',
borderRadius: 50,
padding: 10,
zIndex : 1,
} }
}); });

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save