diff --git a/actions/deck.js b/actions/deck.js index 0b767c3..c1a7a6c 100644 --- a/actions/deck.js +++ b/actions/deck.js @@ -1,6 +1,7 @@ export const LOAD_DECKS = "LOAD_DECKS"; export const NEW_DECK = "NEW_DECK"; export const DELETE_DECK = "DELETE_DECK"; +export const UPDATE_DECK_SCORE = "UPDATE_DECK_SCORE"; export const ADD_CARD = "ADD_CARD"; export const DELETE_CARD = "DELETE_CARD"; @@ -40,4 +41,12 @@ export function deleteCard(deckKey, cardName){ deckKey, cardName } +} + +export function updateDeckScore(deckKey, score){ + return { + type: UPDATE_DECK_SCORE, + deckKey, + score + } } \ No newline at end of file diff --git a/actions/score.js b/actions/score.js index 2cdad94..ed7d4c9 100644 --- a/actions/score.js +++ b/actions/score.js @@ -1,8 +1,16 @@ +export const LOAD_SCORES = "LOAD_SCORE"; export const UPDATE_SCORE = "UPDATE_SCORE"; -export function updateScore(scores){ +export function loadScores(scores){ return { - type: UPDATE_SCORE, + type: LOAD_SCORES, scores } +} + +export function updateScores(score){ + return { + type: UPDATE_SCORE, + score + } } \ No newline at end of file diff --git a/components/flashcards/DeckList.js b/components/flashcards/DeckList.js index 122b656..950ce87 100644 --- a/components/flashcards/DeckList.js +++ b/components/flashcards/DeckList.js @@ -52,7 +52,7 @@ class DeckList extends Component { return ( - You have no registered decks. + You do not have registered decks. Add a new deck! diff --git a/components/flashcards/Quiz.js b/components/flashcards/Quiz.js index 1193d32..8f78511 100644 --- a/components/flashcards/Quiz.js +++ b/components/flashcards/Quiz.js @@ -7,6 +7,8 @@ import { MaterialCommunityIcons } from '@expo/vector-icons'; import { saveScore } from '../../services'; import { COLOR_WHITE, COLOR_B_4, COLOR_A_1, COLOR_B_6, COLOR_SUCCESS, COLOR_BLACK, COLOR_FAILURE } from '../../utils/colors'; +import { UPDATE_SCORE, updateScores } from '../../actions/score'; +import { updateDeckScore } from '../../actions/deck'; const ANSWER = 'A'; const QUESTION = 'Q'; @@ -165,7 +167,9 @@ class Quiz extends Component { const { navigation } = this.props; const { deckKey } = navigation.state.params; - await saveScore(deckKey, status); + const result = await saveScore(deckKey, status); + this.props.dispatch(updateScores(result.lastScore)); + this.props.dispatch(updateDeckScore(deckKey, result.deckScore)); Alert.alert( title, message, diff --git a/components/flashcards/Scores.js b/components/flashcards/Scores.js index eb5893a..1768b17 100644 --- a/components/flashcards/Scores.js +++ b/components/flashcards/Scores.js @@ -1,78 +1,59 @@ import React, { Component } from 'react'; -import { Text, View, ScrollView, StyleSheet } from 'react-native'; +import { Text, View, ScrollView, StyleSheet, ActivityIndicator, TouchableOpacity } from 'react-native'; +import { connect } from 'react-redux'; + +import ScoreItem from '../ui/ScoreItem'; import { getScores } from '../../services'; +import { loadScores } from '../../actions/score'; import { COLOR_B_1 } from '../../utils/colors'; +import Entypo from '@expo/vector-icons/Entypo'; -export default class Scores extends Component { +class Scores extends Component { async componentDidMount() { const scores = await getScores(); - // console.log(scores); + this.props.dispatch(loadScores(scores)); } render() { - return ( - - - - W - - - Deck 'A' @ 10/20/2017 19:22:40 - + const { scores } = this.props; + + if (this.props.scores === null) { + return ( + + - - - L - - - Deck 'A' @ 10/20/2017 19:22:40 - + ); + } else if (scores.length === 0) { + return ( + + + You have no scores. - - - ); + ); + } else { + return ( + + {scores.map(score => ())} + + ); + } } } const styles = StyleSheet.create({ container: { flex: 1 - }, - match: { - flex: 1, - flexDirection: 'row', - height: 64, - borderBottomWidth: 1, - borderBottomColor: COLOR_B_1 - }, - resultContainer: { - flex: 1, - backgroundColor: 'green', - alignItems: 'center', - justifyContent: 'center' - }, - resultContainerL: { - flex: 1, - backgroundColor: 'red', - alignItems: 'center', - justifyContent: 'center' - }, - resultText: { - color: 'white', - fontWeight: 'bold', - fontSize: 30 - }, - statusContainer: { - flex: 4, - alignItems: 'flex-start', - justifyContent: 'center', - paddingLeft: 5 - }, - statusText: { - fontSize: 17 } -}); \ No newline at end of file +}); + +function mapStateToProps({ scores }) { + return { + scores + } +} + +export default connect(mapStateToProps)(Scores); \ No newline at end of file diff --git a/components/ui/ScoreItem.js b/components/ui/ScoreItem.js new file mode 100644 index 0000000..c45f1d1 --- /dev/null +++ b/components/ui/ScoreItem.js @@ -0,0 +1,52 @@ +import React, { Component } from 'react'; +import { StyleSheet, View, Text } from 'react-native'; +import { COLOR_B_1 } from '../../utils/colors'; + +export default class ScoreItem extends Component { + + render() { + + const { score } = this.props; + const scoreColor = score.status === 'L' ? 'red' : (score.status === 'W') ? 'green' : 'gray'; + + return ( + + + {score.status} + + + Deck '{score.deck}' @ {new Date(score.date).toLocaleDateString()} + + + ); + } +} + +const styles = StyleSheet.create({ + match: { + flex: 1, + flexDirection: 'row', + height: 64, + borderBottomWidth: 1, + borderBottomColor: COLOR_B_1 + }, + resultContainer: { + flex: 1, + alignItems: 'center', + justifyContent: 'center' + }, + resultText: { + color: 'white', + fontWeight: 'bold', + fontSize: 30 + }, + statusContainer: { + flex: 4, + alignItems: 'flex-start', + justifyContent: 'center', + paddingLeft: 5 + }, + statusText: { + fontSize: 17 + } +}); \ No newline at end of file diff --git a/reducers/decks.js b/reducers/decks.js index 5768985..1e0be17 100644 --- a/reducers/decks.js +++ b/reducers/decks.js @@ -2,7 +2,9 @@ import { LOAD_DECKS, NEW_DECK, ADD_CARD, + UPDATE_DECK, DELETE_DECK, + UPDATE_DECK_SCORE, DELETE_CARD } from '../actions/deck'; @@ -27,11 +29,25 @@ function decks(state = {}, action) { } case DELETE_DECK: { const { deckKey } = action; - + const refreshedDecks = Object.assign({}, decks); delete refreshedDecks[deckKey]; return refreshedDecks; } + case UPDATE_DECK_SCORE: { + const { score, deckKey } = action; + + const refreshedDecks = { + ...decks, + [deckKey]: { + ...decks[deckKey], + won: score.won, + lost: score.lost + } + } + + return refreshedDecks; + } case ADD_CARD: { const { card, deckKey } = action; const freshDeck = decks[deckKey]; diff --git a/reducers/scores.js b/reducers/scores.js index 1611598..b786838 100644 --- a/reducers/scores.js +++ b/reducers/scores.js @@ -1,4 +1,4 @@ -import { UPDATE_SCORE } from '../actions/score'; +import { UPDATE_SCORE, LOAD_SCORES } from '../actions/score'; function scores(state = [], action) { const { type } = action; @@ -6,6 +6,10 @@ function scores(state = [], action) { switch (type) { case UPDATE_SCORE: { + const refreshedScores = [...scores, action.score]; + return refreshedScores; + } + case LOAD_SCORES: { return action.scores; } default: { diff --git a/services/index.js b/services/index.js index 5336258..172a50f 100644 --- a/services/index.js +++ b/services/index.js @@ -54,7 +54,24 @@ export async function getScores() { export async function saveScore(deck, status) { const scores = await getScores(); const date = Date.now(); - scores.push({ deck, status, date }); + const lastScore = { deck, status, date }; + scores.push(lastScore); + + const playedDeck = await getDeck(deck); + + if (status === 'W') { + playedDeck.won += 1; + } else if (status === 'L') { + playedDeck.lost += 1; + } + + const deckScore = { + won: playedDeck.won, + lost: playedDeck.lost + } + + persistDeck(playedDeck); await AsyncStorage.setItem(SCORES_STORAGE_KEY, JSON.stringify(scores)); + return { lastScore, deckScore }; } \ No newline at end of file