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 { Card } from "../models/Card";
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';
import { View } from 'react-native';
import { Image } 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}>
<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>
type ItemProps = {
url : string //Image URL
}
export function ListItemComponent(props : ItemProps){
return (
<View>
<Image
source={{uri: props.url}}
style={{flex:1, minHeight:250, minWidth:180}}
/>
</View>
);
)
}
const styles = StyleSheet.create({
item: {
},
favoriteButtonNonFav: {
position: 'absolute',
top: 10,
right: 10,
backgroundColor: 'red',
borderRadius: 50,
padding: 10,
},
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 {
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.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.imgGold = imgGold
this.cropImage = cropImage
this.fav = fav
}
// ID //
public id;
public id: string;
// 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;
//IMG//
public img;
//IMGGOLD//
public imgGold;
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;
// }
public img : string;
public imgGold : string;
public cropImage : string;
//FAV//
public fav;
public fav : boolean;
}

@ -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 StackNavigation from './StackNavigation';
import DetailStackNav from './DetailStackNav';
export default function Navigation() {
const BottomTabNavigator = createBottomTabNavigator();
return (
<NavigationContainer>
<BottomTabNavigator.Navigator initialRouteName="Home">
<BottomTabNavigator.Screen name="List" component={ListScreen}
<BottomTabNavigator.Screen name="List" component={DetailStackNav}
options={{
title: 'List',
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"
},
"jest": {
"setupFiles": ["./test/setup/jestSetupFile.js"],
"setupFiles": [
"./test/setup/jestSetupFile.js"
],
"preset": "jest-expo",
"verbose": true,
"transformIgnorePatterns": [
@ -30,6 +32,7 @@
},
"dependencies": {
"@jest/globals": "^29.5.0",
"@react-native-async-storage/async-storage": "1.17.11",
"@react-navigation/bottom-tabs": "^6.5.5",
"@react-navigation/native": "^6.1.4",
"@react-navigation/native-stack": "^6.9.10",
@ -46,6 +49,7 @@
"react-native": "0.71.3",
"react-native-gesture-handler": "~2.9.0",
"react-native-safe-area-context": "4.5.0",
"react-native-table-component": "^1.2.2",
"react-native-web": "~0.18.11",
"react-redux": "^8.0.5",
"redux": "^4.2.1"
@ -56,6 +60,7 @@
"@types/jest": "^29.5.0",
"@types/react": "~18.0.27",
"@types/react-native": "~0.70.6",
"@types/react-native-table-component": "^1.2.4",
"typescript": "^4.9.4"
},
"private": true

@ -28,8 +28,17 @@ export const getAllCards = () => {
//@ts-ignore
const CardsList: Card[] = CardsListJson['cards'].map(elt => new Card(elt["id"] ? elt["id"] : 1,
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["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["cardId"] == null ? elt["cardId"] : ""

@ -20,7 +20,8 @@ export default appReducer = (state = initialState, action) => {
StorageHeart.setItem("favoriteList",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
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 () => {
//@ts-ignore
const list = await StorageHeart.getItem("favoriteList")
if(list!=null){
//@ts-ignore
dispatch(setList(list))
}
};
loadFavCards();
@ -32,7 +35,6 @@ export default function HomeScreen({navigation}) {
loadCards();
}, [dispatch]);
const tabNav = Navigation()
// affichage de la homePage

@ -5,7 +5,7 @@ import { FlatList } from 'react-native-gesture-handler';
import {useSelector} from 'react-redux';
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}
value={searchValue}
onChangeText={text => setSearchValue(text)}
placeholder="Rechercher une carte..."
placeholder="Rechercher une carte...."
/>
<FlatList
numColumns={2}
data={filteredList}
renderItem={({item}) =>
<TouchableHighlight onPress={() => navigation.navigate("ListFav")}>
<TouchableHighlight onPress={() => navigation.navigate("DetailCard", {card :item, other : 'anything'})}>
<Item route={{
card: item,
bool: true

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