Skip to content

Commit

Permalink
FEATURE: Deleting cards
Browse files Browse the repository at this point in the history
Users may delete cards by accessing a deck and its cards list.
  • Loading branch information
diogosilverio committed Jan 27, 2018
1 parent 1573795 commit 6cc28ef
Show file tree
Hide file tree
Showing 7 changed files with 185 additions and 5 deletions.
9 changes: 9 additions & 0 deletions actions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export const NEW_DECK = "NEW_DECK";
export const DELETE_DECK = "DELETE_DECK";

export const ADD_CARD = "ADD_CARD";
export const DELETE_CARD = "DELETE_CARD";

export function loadDecks(decks){
return {
Expand Down Expand Up @@ -31,4 +32,12 @@ export function addCard(deckKey, card){
deckKey,
card
}
}

export function deleteCard(deckKey, cardName){
return {
type: DELETE_CARD,
deckKey,
cardName
}
}
51 changes: 51 additions & 0 deletions components/flashcards/CardList.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { ScrollView, StyleSheet, Text, View, TouchableOpacity, Alert } from 'react-native';
import CardItem from '../ui/CardItem';
import Entypo from '@expo/vector-icons/Entypo';

class CardList extends Component {

render() {
const { cards } = this.props;
const { deckKey, refresher } = this.props.navigation.state.params;

if (cards.length === 0) {

return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Entypo size={75} name="emoji-sad" />
<Text>You have no cards for this deck.</Text>
</View>
);
} else {

return (
<ScrollView style={styles.container}>
{cards.map(card => (
<CardItem key={card.question} card={card} deck={deckKey} refresher={refresher} />
))}

</ScrollView>
);
}
}

}

const styles = StyleSheet.create({
container: {
flex: 1
}
});

function mapStateToProps({ decks }, props) {
const { deckKey } = props.navigation.state.params;
const cards = decks[deckKey].cards;

return {
cards
}
}

export default connect(mapStateToProps)(CardList);
8 changes: 4 additions & 4 deletions components/flashcards/DeckDetails.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@ class DeckDetails extends Component {
]);
}

shouldComponentUpdate(nextProps, nextState){
if(nextProps.deck === null){
shouldComponentUpdate(nextProps, nextState) {
if (nextProps.deck === null) {
return false;
}

return true;
}

Expand Down Expand Up @@ -92,7 +92,7 @@ class DeckDetails extends Component {
<TouchableOpacity style={styles.btn} onPress={() => this.props.navigation.navigate('AddCard', { deckKey: deck.name, refresher: this.refresher.bind(this) })}>
<Text style={styles.btnText}>Add Card</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.btn}>
<TouchableOpacity style={styles.btn} onPress={() => this.props.navigation.navigate('Cards', { deckKey: deck.name, refresher: this.refresher.bind(this) })}>
<Text style={styles.btnText}>List Cards</Text>
</TouchableOpacity>
</View>
Expand Down
4 changes: 4 additions & 0 deletions components/navigators/FlashStackNavigator.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import AddCard from '../flashcards/AddCard';
import DeckDetails from '../flashcards/DeckDetails';

import { COLOR_A_1, COLOR_B_5 } from '../../utils/colors';
import CardList from '../flashcards/CardList';

export default class FlashStackNavigator extends Component {

Expand All @@ -21,6 +22,9 @@ export default class FlashStackNavigator extends Component {
},
DeckDetails: {
screen: DeckDetails
},
Cards: {
screen: CardList
}
}, {
navigationOptions: {
Expand Down
98 changes: 98 additions & 0 deletions components/ui/CardItem.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import React, { Component } from 'react';
import { View, TouchableOpacity, StyleSheet, Text, Alert } from 'react-native';
import { connect } from 'react-redux';

import { MaterialCommunityIcons } from '@expo/vector-icons';

import { deleteCardFromDeck } from '../../services';
import { deleteCard } from '../../actions';
import { COLOR_B_1, COLOR_WHITE, COLOR_FAILURE } from '../../utils/colors';

class CardItem extends Component {

async deleteCard(cardName) {
const { deck, refresher } = this.props;

Alert.alert(
'Delete card?',
`Do you confirm the deletion of the card '${cardName}'?`,
[
{
text: 'Yes', onPress: async () => {
try {
await deleteCardFromDeck(deck, cardName);
this.props.dispatch(deleteCard(deck, cardName));
refresher();
} catch (e) {
Alert.alert(
'Error',
'Error deleting card.',
[
{ text: 'Ok', onPress: () => { } }
]);
console.error(e);
}
}
},
{ text: 'No', onPress: () => { } }
]
);
}

render() {
const { card } = this.props;

return (
<View style={{ flex: 1, flexDirection: 'row' }}>
<View style={styles.mainContainer}>
<View style={styles.cardContainer}>
<Text style={styles.question}>{card.question}</Text>
<Text style={styles.answer}>{card.answer}</Text>
</View>
</View>
<View style={styles.deleteContainer}>
<TouchableOpacity style={styles.deleteBtn} onPress={this.deleteCard.bind(this, card.question)}>
<MaterialCommunityIcons name="delete" size={40} color={COLOR_WHITE} />
</TouchableOpacity>
</View>
</View>
);
}
}

const styles = StyleSheet.create({
mainContainer: {
flex: 8,
flexDirection: 'row',
alignItems: 'center',
padding: 5,
borderBottomWidth: 1,
borderBottomColor: COLOR_B_1
},
cardContainer: {
flex: 1
},
question: {
fontSize: 20,
fontWeight: 'bold'
},
answer: {
fontSize: 15,
color: 'gray',
fontStyle: 'italic',
flexWrap: 'wrap'
},
deleteContainer: {
flex: 2,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: COLOR_FAILURE
},
deleteBtn: {
flex: 1,
alignItems: 'center',
justifyContent: 'center'
}
});

export default connect()(CardItem);
13 changes: 12 additions & 1 deletion reducers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import {
LOAD_DECKS,
NEW_DECK,
ADD_CARD,
DELETE_DECK
DELETE_DECK,
DELETE_CARD
} from '../actions';

function decks(state = { decks: {} }, action) {
Expand Down Expand Up @@ -52,6 +53,16 @@ function decks(state = { decks: {} }, action) {
}

}
case DELETE_CARD: {
const { deckKey, cardName } = action;
const freshDecks = decks;

freshDecks[deckKey].cards = freshDecks[deckKey].cards.filter(card => card.question !== cardName);

return {
decks: freshDecks
}
}
default: {
return state;
}
Expand Down
7 changes: 7 additions & 0 deletions services/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,12 @@ export async function addCardToDeck(deckKey, card){
}

deck.cards.push(card)
await persistDeck(deck);
}

export async function deleteCardFromDeck(deckKey, cardName){
const deck = await getDeck(deckKey);
deck.cards = deck.cards.filter(card => card.question !== cardName);

await persistDeck(deck);
}

0 comments on commit 6cc28ef

Please sign in to comment.