diff --git a/actions/index.js b/actions/index.js
index 676d4b2..0b767c3 100644
--- a/actions/index.js
+++ b/actions/index.js
@@ -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 {
@@ -31,4 +32,12 @@ export function addCard(deckKey, card){
deckKey,
card
}
+}
+
+export function deleteCard(deckKey, cardName){
+ return {
+ type: DELETE_CARD,
+ deckKey,
+ cardName
+ }
}
\ No newline at end of file
diff --git a/components/flashcards/CardList.js b/components/flashcards/CardList.js
new file mode 100644
index 0000000..1c1a695
--- /dev/null
+++ b/components/flashcards/CardList.js
@@ -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 (
+
+
+ You have no cards for this deck.
+
+ );
+ } else {
+
+ return (
+
+ {cards.map(card => (
+
+ ))}
+
+
+ );
+ }
+ }
+
+}
+
+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);
\ No newline at end of file
diff --git a/components/flashcards/DeckDetails.js b/components/flashcards/DeckDetails.js
index e8a1eaa..f83bb6d 100644
--- a/components/flashcards/DeckDetails.js
+++ b/components/flashcards/DeckDetails.js
@@ -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;
}
@@ -92,7 +92,7 @@ class DeckDetails extends Component {
this.props.navigation.navigate('AddCard', { deckKey: deck.name, refresher: this.refresher.bind(this) })}>
Add Card
-
+ this.props.navigation.navigate('Cards', { deckKey: deck.name, refresher: this.refresher.bind(this) })}>
List Cards
diff --git a/components/navigators/FlashStackNavigator.js b/components/navigators/FlashStackNavigator.js
index d46197a..9c97a97 100644
--- a/components/navigators/FlashStackNavigator.js
+++ b/components/navigators/FlashStackNavigator.js
@@ -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 {
@@ -21,6 +22,9 @@ export default class FlashStackNavigator extends Component {
},
DeckDetails: {
screen: DeckDetails
+ },
+ Cards: {
+ screen: CardList
}
}, {
navigationOptions: {
diff --git a/components/ui/CardItem.js b/components/ui/CardItem.js
new file mode 100644
index 0000000..7270989
--- /dev/null
+++ b/components/ui/CardItem.js
@@ -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 (
+
+
+
+ {card.question}
+ {card.answer}
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+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);
\ No newline at end of file
diff --git a/reducers/index.js b/reducers/index.js
index 55f9e7f..e97128c 100644
--- a/reducers/index.js
+++ b/reducers/index.js
@@ -2,7 +2,8 @@ import {
LOAD_DECKS,
NEW_DECK,
ADD_CARD,
- DELETE_DECK
+ DELETE_DECK,
+ DELETE_CARD
} from '../actions';
function decks(state = { decks: {} }, action) {
@@ -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;
}
diff --git a/services/index.js b/services/index.js
index d9c8bf7..98d28b6 100644
--- a/services/index.js
+++ b/services/index.js
@@ -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);
}
\ No newline at end of file