diff --git a/components/app-wrapper.js b/components/app-wrapper.js index 31419b9..fc70bcd 100644 --- a/components/app-wrapper.js +++ b/components/app-wrapper.js @@ -9,6 +9,9 @@ import PasswordPrompt from './password-prompt' import License from './license' import AppLoadingView from './app-loading' +import store from "../store" +import { Provider } from 'react-redux' + export default class AppWrapper extends Component { constructor() { super() @@ -69,18 +72,19 @@ export default class AppWrapper extends Component { shouldShowApp, } = this.state + let initialView = null + if (isCheckingLicenseAgreement) { - return + initialView = + } else if (shouldShowLicenseAgreement) { + initialView = + } else if (shouldShowPasswordPrompt) { + initialView = + } else if (shouldShowApp) { + initialView = } - if (shouldShowLicenseAgreement) { - return - } + return {initialView} - if (shouldShowPasswordPrompt) { - return - } - - return shouldShowApp && } } \ No newline at end of file diff --git a/components/app.js b/components/app.js index 3fd7bf4..b9838de 100644 --- a/components/app.js +++ b/components/app.js @@ -1,5 +1,9 @@ import React, { Component } from 'react' import { View, BackHandler } from 'react-native' +import { connect } from 'react-redux' + +import { getDate } from '../slices/date' + import Header from './header' import Menu from './menu' import Home from './home' @@ -25,7 +29,7 @@ const HOME_PAGE = 'Home' const CYCLE_DAY_PAGE = 'CycleDay' const SETTINGS_MENU_PAGE = 'SettingsMenu' -export default class App extends Component { +class App extends Component { constructor(props) { super(props) this.state = { @@ -55,14 +59,14 @@ export default class App extends Component { } handleBackButtonPress = () => { - const { currentPage, currentProps } = this.state + const { currentPage } = this.state if (currentPage === HOME_PAGE) { closeDb() return false } if (this.isSymptomView()) { this.navigate( - this.originForSymptomView, { date: currentProps.date } + this.originForSymptomView, { date: this.props.date } ) } else if (this.isSettingsView()) { this.navigate(SETTINGS_MENU_PAGE) @@ -92,7 +96,7 @@ export default class App extends Component { } render() { - const { currentPage, currentProps } = this.state + const { currentPage } = this.state const pages = { Home, Calendar, @@ -121,7 +125,6 @@ export default class App extends Component { @@ -132,3 +135,14 @@ export default class App extends Component { ) } } + +const mapStateToProps = (state) => { + return({ + date: getDate(state) + }) +} + +export default connect( + mapStateToProps, + null +)(App) \ No newline at end of file diff --git a/components/calendar.js b/components/calendar.js index 6c4ec69..faf4bea 100644 --- a/components/calendar.js +++ b/components/calendar.js @@ -1,5 +1,9 @@ import React, { Component } from 'react' import { CalendarList } from 'react-native-calendars' +import { connect } from 'react-redux' + +import { setDate } from '../slices/date' + import { LocalDate } from 'js-joda' import { getBleedingDaysSortedByDate } from '../db' import cycleModule from '../lib/cycle' @@ -7,7 +11,7 @@ import { shadesOfRed, calendarTheme } from '../styles/index' import styles from '../styles/index' import nothingChanged from '../db/db-unchanged' -export default class CalendarView extends Component { +class CalendarView extends Component { constructor(props) { super(props) this.bleedingDays = getBleedingDaysSortedByDate() @@ -36,9 +40,10 @@ export default class CalendarView extends Component { } passDateToDayView = (result) => { - const navigate = this.props.navigate - navigate('CycleDay', { date: result.dateString }) + this.props.setDate(result.dateString) + this.props.navigate('CycleDay') } + render() { return ( { + return({ + setDate: (date) => dispatch(setDate(date)), + }) +} + +export default connect( + null, + mapDispatchToProps, +)(CalendarView) + + function toCalFormat(bleedingDaysSortedByDate) { const todayDateString = LocalDate.now().toString() return bleedingDaysSortedByDate.reduce((acc, day) => { diff --git a/components/chart/day-column.js b/components/chart/day-column.js index 825cb69..834a618 100644 --- a/components/chart/day-column.js +++ b/components/chart/day-column.js @@ -2,7 +2,16 @@ import React, { Component } from 'react' import { Text, View, TouchableOpacity } from 'react-native' -import { Surface, Group as G, Path, Shape } from 'react-native/Libraries/ART/ReactNativeART' +import { + Surface, + Group as G, + Path, + Shape +} from 'react-native/Libraries/ART/ReactNativeART' +import { connect } from 'react-redux' + +import { setDate } from '../../slices/date' + import { LocalDate } from 'js-joda' import moment from 'moment' import styles from './styles' @@ -14,7 +23,7 @@ import { normalizeToScale } from './y-axis' const label = styles.column.label -export default class DayColumn extends Component { +class DayColumn extends Component { constructor(props) { super() const dateString = props.dateString @@ -61,6 +70,11 @@ export default class DayColumn extends Component { ) } + onDaySelect = (date) => { + this.props.setDate(date) + this.props.navigate('CycleDay') + } + shouldComponentUpdate() { return false } @@ -246,7 +260,7 @@ export default class DayColumn extends Component { return ( this.props.navigate('CycleDay', { date: dateString })} + onPress={() => this.onDaySelect(dateString)} activeOpacity={1} > @@ -268,6 +282,18 @@ export default class DayColumn extends Component { } } +const mapDispatchToProps = (dispatch) => { + return({ + setDate: (date) => dispatch(setDate(date)), + }) +} + +export default connect( + null, + mapDispatchToProps, +)(DayColumn) + + function SymptomIconView(props) { const style = [styles.symptomRow, {height: props.symptomHeight}] diff --git a/components/cycle-day/cycle-day-overview.js b/components/cycle-day/cycle-day-overview.js index 2961f81..914f212 100644 --- a/components/cycle-day/cycle-day-overview.js +++ b/components/cycle-day/cycle-day-overview.js @@ -1,5 +1,9 @@ import React, { Component } from 'react' import { ScrollView, View } from 'react-native' + +import { connect } from 'react-redux' +import { getDate, setDate } from '../../slices/date' + import { LocalDate } from 'js-joda' import Header from '../header' import FillerBoxes from './FillerBoxes' @@ -9,34 +13,34 @@ import { getCycleDay } from '../../db' import cycleModule from '../../lib/cycle' import styles from '../../styles' -export default class CycleDayOverView extends Component { +class CycleDayOverView extends Component { constructor(props) { super(props) - const { date } = this.props this.state = { - date, - cycleDay: getCycleDay(date) + cycleDay: getCycleDay(props.date) } } goToCycleDay = (target) => { - const localDate = LocalDate.parse(this.state.date) + const localDate = LocalDate.parse(this.props.date) const targetDate = target === 'before' ? localDate.minusDays(1).toString() : localDate.plusDays(1).toString() + this.props.setDate(targetDate) this.setState({ - date: targetDate, cycleDay: getCycleDay(targetDate) }) } navigate(symptom) { - this.props.navigate(symptom, this.state) + this.props.navigate(symptom) } render() { - const { date, cycleDay } = this.state const { getCycleDayNumber } = cycleModule() + const { cycleDay } = this.state + const { date } = this.props + const cycleDayNumber = getCycleDayNumber(date) const dateInFuture = LocalDate.now().isBefore(LocalDate.parse(date)) @@ -89,3 +93,20 @@ export default class CycleDayOverView extends Component { ) } } + +const mapStateToProps = (state) => { + return({ + date: getDate(state), + }) +} + +const mapDispatchToProps = (dispatch) => { + return({ + setDate: (date) => dispatch(setDate(date)), + }) +} + +export default connect( + mapStateToProps, + mapDispatchToProps, +)(CycleDayOverView) diff --git a/components/cycle-day/symptoms/bleeding.js b/components/cycle-day/symptoms/bleeding.js index 6893bfa..1d9cf71 100644 --- a/components/cycle-day/symptoms/bleeding.js +++ b/components/cycle-day/symptoms/bleeding.js @@ -1,15 +1,16 @@ import React from 'react' -import { - Switch, - ScrollView -} from 'react-native' +import { Switch, ScrollView } from 'react-native' +import { connect } from 'react-redux' + +import { getDate } from '../../../slices/date' + import styles from '../../../styles' import { bleeding } from '../../../i18n/en/cycle-day' import SelectTabGroup from '../select-tab-group' import SymptomSection from './symptom-section' import SymptomView from './symptom-view' -export default class Bleeding extends SymptomView { +class Bleeding extends SymptomView { constructor(props) { super(props) const cycleDay = props.cycleDay @@ -67,4 +68,15 @@ export default class Bleeding extends SymptomView { ) } -} \ No newline at end of file +} + +const mapStateToProps = (state) => { + return({ + date: getDate(state) + }) +} + +export default connect( + mapStateToProps, + null +)(Bleeding) \ No newline at end of file diff --git a/components/cycle-day/symptoms/cervix.js b/components/cycle-day/symptoms/cervix.js index 4515f5d..58fddf6 100644 --- a/components/cycle-day/symptoms/cervix.js +++ b/components/cycle-day/symptoms/cervix.js @@ -3,13 +3,17 @@ import { Switch, ScrollView } from 'react-native' +import { connect } from 'react-redux' + +import { getDate } from '../../../slices/date' + import styles from '../../../styles' import { cervix as labels } from '../../../i18n/en/cycle-day' import SelectTabGroup from '../select-tab-group' import SymptomSection from './symptom-section' import SymptomView from './symptom-view' -export default class Cervix extends SymptomView { +class Cervix extends SymptomView { constructor(props) { super(props) const cycleDay = props.cycleDay @@ -99,3 +103,14 @@ export default class Cervix extends SymptomView { ) } } + +const mapStateToProps = (state) => { + return({ + date: getDate(state) + }) +} + +export default connect( + mapStateToProps, + null +)(Cervix) diff --git a/components/cycle-day/symptoms/desire.js b/components/cycle-day/symptoms/desire.js index f28ff85..b395cb2 100644 --- a/components/cycle-day/symptoms/desire.js +++ b/components/cycle-day/symptoms/desire.js @@ -2,13 +2,17 @@ import React from 'react' import { ScrollView } from 'react-native' +import { connect } from 'react-redux' + +import { getDate } from '../../../slices/date' + import styles from '../../../styles' import { intensity, desire } from '../../../i18n/en/cycle-day' import SelectTabGroup from '../select-tab-group' import SymptomSection from './symptom-section' import SymptomView from './symptom-view' -export default class Desire extends SymptomView { +class Desire extends SymptomView { constructor(props) { super(props) const cycleDay = props.cycleDay @@ -49,3 +53,14 @@ export default class Desire extends SymptomView { ) } } + +const mapStateToProps = (state) => { + return({ + date: getDate(state) + }) +} + +export default connect( + mapStateToProps, + null +)(Desire) diff --git a/components/cycle-day/symptoms/mood.js b/components/cycle-day/symptoms/mood.js index 6b78891..eef3b18 100644 --- a/components/cycle-day/symptoms/mood.js +++ b/components/cycle-day/symptoms/mood.js @@ -2,13 +2,17 @@ import React from 'react' import { ScrollView, TextInput} from 'react-native' +import { connect } from 'react-redux' + +import { getDate } from '../../../slices/date' + import { mood as labels } from '../../../i18n/en/cycle-day' import SelectBoxGroup from '../select-box-group' import SymptomSection from './symptom-section' import styles from '../../../styles' import SymptomView from './symptom-view' -export default class Mood extends SymptomView { +class Mood extends SymptomView { constructor(props) { super(props) const cycleDay = props.cycleDay @@ -72,3 +76,14 @@ export default class Mood extends SymptomView { ) } } + +const mapStateToProps = (state) => { + return({ + date: getDate(state) + }) +} + +export default connect( + mapStateToProps, + null +)(Mood) diff --git a/components/cycle-day/symptoms/mucus.js b/components/cycle-day/symptoms/mucus.js index cc73591..ea9d5e6 100644 --- a/components/cycle-day/symptoms/mucus.js +++ b/components/cycle-day/symptoms/mucus.js @@ -3,6 +3,10 @@ import { Switch, ScrollView } from 'react-native' +import { connect } from 'react-redux' + +import { getDate } from '../../../slices/date' + import styles from '../../../styles' import { mucus as labels } from '../../../i18n/en/cycle-day' import computeNfpValue from '../../../lib/nfp-mucus' @@ -10,7 +14,7 @@ import SelectTabGroup from '../select-tab-group' import SymptomSection from './symptom-section' import SymptomView from './symptom-view' -export default class Mucus extends SymptomView { +class Mucus extends SymptomView { constructor(props) { super(props) const cycleDay = props.cycleDay @@ -89,3 +93,14 @@ export default class Mucus extends SymptomView { ) } } + +const mapStateToProps = (state) => { + return({ + date: getDate(state) + }) +} + +export default connect( + mapStateToProps, + null +)(Mucus) diff --git a/components/cycle-day/symptoms/note.js b/components/cycle-day/symptoms/note.js index e9a2df6..d7febcb 100644 --- a/components/cycle-day/symptoms/note.js +++ b/components/cycle-day/symptoms/note.js @@ -3,6 +3,9 @@ import { ScrollView, TextInput, } from 'react-native' +import { connect } from 'react-redux' + +import { getDate } from '../../../slices/date' import styles from '../../../styles' import SymptomSection from './symptom-section' @@ -10,7 +13,7 @@ import { noteExplainer } from '../../../i18n/en/cycle-day' import { shared as sharedLabels } from '../../../i18n/en/labels' import SymptomView from './symptom-view' -export default class Note extends SymptomView { +class Note extends SymptomView { constructor(props) { super(props) const cycleDay = props.cycleDay @@ -53,3 +56,14 @@ export default class Note extends SymptomView { ) } } + +const mapStateToProps = (state) => { + return({ + date: getDate(state) + }) +} + +export default connect( + mapStateToProps, + null +)(Note) diff --git a/components/cycle-day/symptoms/pain.js b/components/cycle-day/symptoms/pain.js index fdf3fec..a45a633 100644 --- a/components/cycle-day/symptoms/pain.js +++ b/components/cycle-day/symptoms/pain.js @@ -3,6 +3,10 @@ import { ScrollView, TextInput, } from 'react-native' +import { connect } from 'react-redux' + +import { getDate } from '../../../slices/date' + import { pain as labels } from '../../../i18n/en/cycle-day' import { shared as sharedLabels } from '../../../i18n/en/labels' import SelectBoxGroup from '../select-box-group' @@ -10,7 +14,7 @@ import SymptomSection from './symptom-section' import styles from '../../../styles' import SymptomView from './symptom-view' -export default class Pain extends SymptomView { +class Pain extends SymptomView { constructor(props) { super(props) const cycleDay = props.cycleDay @@ -74,3 +78,14 @@ export default class Pain extends SymptomView { ) } } + +const mapStateToProps = (state) => { + return({ + date: getDate(state) + }) +} + +export default connect( + mapStateToProps, + null +)(Pain) diff --git a/components/cycle-day/symptoms/sex.js b/components/cycle-day/symptoms/sex.js index 140afa3..5bdbd05 100644 --- a/components/cycle-day/symptoms/sex.js +++ b/components/cycle-day/symptoms/sex.js @@ -3,6 +3,10 @@ import { TextInput, ScrollView } from 'react-native' +import { connect } from 'react-redux' + +import { getDate } from '../../../slices/date' + import styles from '../../../styles' import { sex as sexLabels, contraceptives as contraceptivesLabels } from '../../../i18n/en/cycle-day' import { shared as sharedLabels } from '../../../i18n/en/labels' @@ -10,7 +14,7 @@ import SelectBoxGroup from '../select-box-group' import SymptomSection from './symptom-section' import SymptomView from './symptom-view' -export default class Sex extends SymptomView { +class Sex extends SymptomView { constructor(props) { super(props) const cycleDay = props.cycleDay @@ -87,3 +91,14 @@ export default class Sex extends SymptomView { ) } } + +const mapStateToProps = (state) => { + return({ + date: getDate(state) + }) +} + +export default connect( + mapStateToProps, + null +)(Sex) diff --git a/components/cycle-day/symptoms/symptom-view.js b/components/cycle-day/symptoms/symptom-view.js index d78b995..d2e9e3f 100644 --- a/components/cycle-day/symptoms/symptom-view.js +++ b/components/cycle-day/symptoms/symptom-view.js @@ -2,6 +2,7 @@ import React, { Component } from 'react' import { View, Alert, TouchableOpacity } from 'react-native' + import { saveSymptom } from '../../../db' import InfoPopUp from './info-symptom' import Header from '../../header/symptom-view' @@ -10,9 +11,10 @@ import { sharedDialogs } from '../../../i18n/en/cycle-day' import Icon from 'react-native-vector-icons/Entypo' import styles, { iconStyles } from '../../../styles' -export default class SymptomView extends Component { - constructor(props) { +class SymptomView extends Component { + constructor(props, symptomName) { super() + this.symptomName = symptomName this.date = props.date this.navigate = props.navigate this.state = { @@ -95,4 +97,6 @@ export default class SymptomView extends Component { ) } -} \ No newline at end of file +} + +export default SymptomView diff --git a/components/cycle-day/symptoms/temperature.js b/components/cycle-day/symptoms/temperature.js index 66715c8..f0db45a 100644 --- a/components/cycle-day/symptoms/temperature.js +++ b/components/cycle-day/symptoms/temperature.js @@ -5,6 +5,10 @@ import { Keyboard, ScrollView } from 'react-native' +import { connect } from 'react-redux' + +import { getDate } from '../../../slices/date' + import DateTimePicker from 'react-native-modal-datetime-picker-nevo' import padWithZeros from '../../helpers/pad-time-with-zeros' @@ -22,7 +26,7 @@ import SymptomView from './symptom-view' const minutes = ChronoUnit.MINUTES -export default class Temp extends SymptomView { +class Temp extends SymptomView { constructor(props) { super(props) const cycleDay = props.cycleDay @@ -175,6 +179,17 @@ export default class Temp extends SymptomView { } } +const mapStateToProps = (state) => { + return({ + date: getDate(state) + }) +} + +export default connect( + mapStateToProps, + null +)(Temp) + function makeOutOfRangeWarningMessage(temperature) { if (temperature === '') return const value = Number(temperature) diff --git a/components/header/cycle-day.js b/components/header/cycle-day.js index 33abfb1..57cf329 100644 --- a/components/header/cycle-day.js +++ b/components/header/cycle-day.js @@ -6,21 +6,22 @@ import styles from '../../styles' import NavigationArrow from './navigation-arrow' import formatDate from '../helpers/format-date' -export default function CycleDayHeader({ date, ...props }) { +export default function CycleDayHeader({ date, cycleDayNumber, ...props }) { return ( - + {formatDate(date)} - {props.cycleDayNumber && + { cycleDayNumber && - {`Cycle day ${props.cycleDayNumber}`.toLowerCase()} - } + {`Cycle day ${cycleDayNumber}`.toLowerCase()} + + } diff --git a/components/header/symptom-view.js b/components/header/symptom-view.js index f2797de..a1d5e10 100644 --- a/components/header/symptom-view.js +++ b/components/header/symptom-view.js @@ -26,9 +26,11 @@ export default function SymptomViewHeader(props) { {props.title} - - {formatDate(props.date)} - + { props.date && + + {formatDate(props.date)} + + } { props.deleteIconActive && { ) } -export default class Home extends Component { +class Home extends Component { constructor(props) { super(props) const { getCycleDayNumber, getPredictedMenses } = cycleModule() @@ -68,12 +70,18 @@ export default class Home extends Component { } } - passTodayTo(componentName) { - const { navigate } = this.props - navigate(componentName, { - date: this.todayDateString, - cycleDay: getCycleDay(this.todayDateString) - }) + setTodayDate = () => { + this.props.setDate(this.todayDateString) + } + + navigateToCycleDayView = () => { + this.setTodayDate() + this.props.navigate('CycleDay') + } + + navigateToBleedingEditView = () => { + this.setTodayDate() + this.props.navigate('BleedingEditView') } render() { @@ -91,7 +99,7 @@ export default class Home extends Component { this.passTodayTo('CycleDay') } + onPress={this.navigateToCycleDayView} buttonColor={ cycleDayColor } buttonLabel={ labels.editToday } > @@ -102,11 +110,13 @@ export default class Home extends Component { {cycleDayNumber || labels.unknown} - {cycleDayMoreText} + + {cycleDayMoreText} + this.passTodayTo('BleedingEditView') } + onPress={this.navigateToBleedingEditView} buttonColor={ periodColor } buttonLabel={ labels.trackPeriod } > @@ -148,18 +158,36 @@ export default class Home extends Component { } } +const mapDispatchToProps = (dispatch) => { + return({ + setDate: (date) => dispatch(setDate(date)), + }) +} + +export default connect( + null, + mapDispatchToProps, +)(Home) + + function getTimes(prediction) { const todayDate = LocalDate.now() const predictedBleedingStart = LocalDate.parse(prediction[0][0]) /* the range of predicted bleeding days can be either 3 or 5 */ - const predictedBleedingEnd = LocalDate.parse(prediction[0][ prediction[0].length - 1 ]) + const predictedBleedingEnd = + LocalDate.parse(prediction[0][ prediction[0].length - 1 ]) const daysToEnd = todayDate.until(predictedBleedingEnd, ChronoUnit.DAYS) return { todayDate, predictedBleedingStart, predictedBleedingEnd, daysToEnd } } function determinePredictionText(bleedingPrediction) { if (!bleedingPrediction.length) return predictLabels.noPrediction - const { todayDate, predictedBleedingStart, predictedBleedingEnd, daysToEnd } = getTimes(bleedingPrediction) + const { + todayDate, + predictedBleedingStart, + predictedBleedingEnd, + daysToEnd + } = getTimes(bleedingPrediction) if (todayDate.isBefore(predictedBleedingStart)) { return predictLabels.predictionInFuture( todayDate.until(predictedBleedingStart, ChronoUnit.DAYS), @@ -183,7 +211,12 @@ function determinePredictionText(bleedingPrediction) { function getBleedingPredictionRange(prediction) { if (!prediction.length) return labels.unknown - const { todayDate, predictedBleedingStart, predictedBleedingEnd, daysToEnd } = getTimes(prediction) + const { + todayDate, + predictedBleedingStart, + predictedBleedingEnd, + daysToEnd + } = getTimes(prediction) if (todayDate.isBefore(predictedBleedingStart)) { return `${todayDate.until(predictedBleedingStart, ChronoUnit.DAYS)}-${todayDate.until(predictedBleedingEnd, ChronoUnit.DAYS)}` } diff --git a/e2e/date.spec.js b/e2e/date.spec.js new file mode 100644 index 0000000..9934a48 --- /dev/null +++ b/e2e/date.spec.js @@ -0,0 +1,30 @@ +const LocalDate = require("js-joda").LocalDate +const moment = require('moment') + +describe('Date', () => { + beforeEach(async () => { + await device.reloadReactNative() + }) + + it('should have same date when navigating between cycle day and symptom view', async () => { + await element(by.id('licenseOkButton')).tap() + + await element(by.text('add data for today')).tap() + await expect( + element(by.id('cycleDayTitleDate').and(by.text('today'))) + ).toBeVisible() + await element(by.id('previousDateButton')).tap() + await element(by.id('drip-icon-bleeding')).tap() + + const today = LocalDate.now() + const yesterday = today.minusDays(1) + const yesterdayFormatted = moment( + yesterday.toString()).format('MMMM Do YYYY') + .toLowerCase() + + await expect( + element(by.id('symptomViewTitleDate').and(by.text(yesterdayFormatted))) + ).toBeVisible() + }) + +}) diff --git a/e2e/homeNavigation.spec.js b/e2e/homeNavigation.spec.js index ae39b9a..3447786 100644 --- a/e2e/homeNavigation.spec.js +++ b/e2e/homeNavigation.spec.js @@ -10,6 +10,9 @@ const isOnPage = async (page, parentPage) => { } describe('Home Navigation', () => { + before(async () => { + await device.launchApp({ newInstance: true }) + }) beforeEach(async () => { await device.reloadReactNative() }) @@ -21,11 +24,13 @@ describe('Home Navigation', () => { // await element(by.id('licenseOkCance')).tap(); // }); - it('should navigate to home on accepting the license agreement', async () => { - await expect(element(by.id('licensePage'))).toBeVisible() - await element(by.id('licenseOkButton')).tap() - await isOnPage('home') - }) + // TODO: figure out how to clean the localStorage between the different specs are running + // for now disabling the License Agreement test. + // it('should navigate to home on accepting the license agreement', async () => { + // await expect(element(by.id('licensePage'))).toBeVisible() + // await element(by.id('licenseOkButton')).tap() + // await isOnPage('home') + // }) it('should navigate to today bleeding symptom', async () => { await element(by.text('track your period')).tap() diff --git a/package-lock.json b/package-lock.json index 5f7b26e..db652bd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2122,6 +2122,11 @@ "strip-bom": "^2.0.0" } }, + "curriable": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/curriable/-/curriable-1.3.0.tgz", + "integrity": "sha512-7kfjDPRSF+pguU0TlfSFBMCd8XlmF29ZAiXcq/zaN4LhZvWdvV0Y72AvaWFqInXZG9Yg1kA1UMkpE9lFBKMpQA==" + }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -3369,6 +3374,11 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" }, + "fast-equals": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-1.6.3.tgz", + "integrity": "sha512-4WKW0AL5+WEqO0zWavAfYGY1qwLsBgE//DN4TTcVEN2UlINgkv9b3vm2iHicoenWKSX9mKWmGOsU/iI5IST7pQ==" + }, "fast-json-stable-stringify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", @@ -4381,6 +4391,14 @@ "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", "dev": true }, + "hoist-non-react-statics": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.0.tgz", + "integrity": "sha512-0XsbTXxgiaCDYDIWFcwkmerZPSwywfUqYmwT4jzewKTQSWoE6FCMoUVOeBJWK3E/CrWbxRG3m5GzY4lnIwGRBA==", + "requires": { + "react-is": "^16.7.0" + } + }, "hosted-git-info": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", @@ -4473,6 +4491,14 @@ "safer-buffer": ">= 2.1.2 < 3" } }, + "identitate": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/identitate/-/identitate-1.0.1.tgz", + "integrity": "sha512-xnDJ0JYhiZjBDuJRKbHoVzj5yP9FhATxLyUYswQyPdnJrwzGVBqS6DOmvKJi1lk7P+4dkL+hhUhuOZIcOUtG5A==", + "requires": { + "pathington": "^1.0.1" + } + }, "ieee754": { "version": "1.1.13", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", @@ -4497,6 +4523,11 @@ "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.6.3.tgz", "integrity": "sha512-47xSUiQioGaB96nqtp5/q55m0aBQSQdyIloMOc/x+QVTDZLNmXE892IIDrJ0hM1A5vcNUDD5tDffkSP5lCaIIA==" }, + "immer": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/immer/-/immer-2.1.5.tgz", + "integrity": "sha512-xyjQyTBYIeiz6jd02Hg12jV+9QISwF1crLcwTlzHpWH4e0ryNWj1kacpTwimK3bJV5NKKXw458G2vpqoB/inFA==" + }, "import-fresh": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", @@ -6605,6 +6636,11 @@ "pify": "^2.0.0" } }, + "pathington": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/pathington/-/pathington-1.1.7.tgz", + "integrity": "sha512-JxzhUzagDfNIOm4qqwQqP3rWeo7rNNOfIahy4n+3GTEdwXLqw5cJHUR0soSopQtNEv763lzxb6eA2xBllpR8zw==" + }, "pathval": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", @@ -7492,6 +7528,19 @@ "react-deep-force-update": "^1.0.0" } }, + "react-redux": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-6.0.1.tgz", + "integrity": "sha512-T52I52Kxhbqy/6TEfBv85rQSDz6+Y28V/pf52vDWs1YRXG19mcFOGfHnY2HsNFHyhP+ST34Aih98fvt6tqwVcQ==", + "requires": { + "@babel/runtime": "^7.3.1", + "hoist-non-react-statics": "^3.3.0", + "invariant": "^2.2.4", + "loose-envify": "^1.4.0", + "prop-types": "^15.7.2", + "react-is": "^16.8.2" + } + }, "react-transform-hmr": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/react-transform-hmr/-/react-transform-hmr-1.0.4.tgz", @@ -7599,6 +7648,47 @@ } } }, + "redux": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.0.4.tgz", + "integrity": "sha512-vKv4WdiJxOWKxK0yRoaK3Y4pxxB0ilzVx6dszU2W8wLxlb2yikRph4iV/ymtdJ6ZxpBLFbyrxklnT5yBbQSl3Q==", + "requires": { + "loose-envify": "^1.4.0", + "symbol-observable": "^1.2.0" + } + }, + "redux-devtools-extension": { + "version": "2.13.8", + "resolved": "https://registry.npmjs.org/redux-devtools-extension/-/redux-devtools-extension-2.13.8.tgz", + "integrity": "sha512-8qlpooP2QqPtZHQZRhx3x3OP5skEV1py/zUdMY28WNAocbafxdG2tRD1MWE7sp8obGMNYuLWanhhQ7EQvT1FBg==" + }, + "redux-immutable-state-invariant": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/redux-immutable-state-invariant/-/redux-immutable-state-invariant-2.1.0.tgz", + "integrity": "sha512-3czbDKs35FwiBRsx/3KabUk5zSOoTXC+cgVofGkpBNv3jQcqIe5JrHcF5AmVt7B/4hyJ8MijBIpCJ8cife6yJg==", + "requires": { + "invariant": "^2.1.0", + "json-stringify-safe": "^5.0.1" + } + }, + "redux-starter-kit": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/redux-starter-kit/-/redux-starter-kit-0.6.3.tgz", + "integrity": "sha512-A+7UjgmFrWdKksHl8xTGxDw6Bv8QJ+wrTubBscFNs5gIezGHOdwjqTTSVX4xMgQkgPtVfSPj/Bo+5o6f71/eTA==", + "requires": { + "immer": "^2.1.5", + "redux": "^4.0.0", + "redux-devtools-extension": "^2.13.8", + "redux-immutable-state-invariant": "^2.1.0", + "redux-thunk": "^2.2.0", + "selectorator": "^4.0.3" + } + }, + "redux-thunk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.3.0.tgz", + "integrity": "sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw==" + }, "regenerate": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", @@ -7808,6 +7898,11 @@ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" }, + "reselect": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.0.0.tgz", + "integrity": "sha512-qUgANli03jjAyGlnbYVAV5vvnOmJnODyABz51RdBN7M4WaVu8mecZWgyQNkG8Yqe3KRGRt0l4K4B3XVEULC4CA==" + }, "resolve": { "version": "1.10.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.1.tgz", @@ -8241,6 +8336,17 @@ } } }, + "selectorator": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/selectorator/-/selectorator-4.0.3.tgz", + "integrity": "sha512-A8+paRhzTab4Qm/38RAVnCgEZFbpn5xIWLyTCDqvyU3Obhmo94RS6UK1H00bVH7+U609sOhqbFJha09POsWURA==", + "requires": { + "fast-equals": "^1.2.1", + "identitate": "^1.0.0", + "reselect": "^4.0.0", + "unchanged": "^2.0.1" + } + }, "semver": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", @@ -8755,6 +8861,11 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" }, + "symbol-observable": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", + "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==" + }, "sympto": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/sympto/-/sympto-1.0.4.tgz", @@ -9245,6 +9356,15 @@ "through": "^2.3.8" } }, + "unchanged": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unchanged/-/unchanged-2.2.0.tgz", + "integrity": "sha512-L+MJNfyvFZkjw9WYRbmZBnYncBoASRNxE9eCm5SZWc2whdw19tPVigjJXNwu+/O+nCwp1kYYT8LX+jNuJakF9w==", + "requires": { + "curriable": "^1.3.0", + "pathington": "^1.1.7" + } + }, "unherit": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.1.tgz", diff --git a/package.json b/package.json index 2194d0c..4508bf9 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,9 @@ "react-native-share": "^1.1.3", "react-native-vector-icons": "^6.4.2", "realm": "^2.22.0", + "react-redux": "^6.0.0", + "redux": "^4.0.1", + "redux-starter-kit": "^0.6.3", "sympto": "^1.0.4" }, "devDependencies": { diff --git a/slices/date.js b/slices/date.js new file mode 100644 index 0000000..84ad7b1 --- /dev/null +++ b/slices/date.js @@ -0,0 +1,18 @@ +import { createSlice } from 'redux-starter-kit' + +const dateSlice = createSlice({ + slice: 'date', + initialState: null, + reducers: { + setDate: (state, action) => action.payload + } +}) + +// Extract the action creators object and the reducer +const { actions, reducer, selectors } = dateSlice +// Extract and export each action creator by name +export const { setDate } = actions + +export const { getDate } = selectors + +export default reducer diff --git a/store.js b/store.js new file mode 100644 index 0000000..7aa713d --- /dev/null +++ b/store.js @@ -0,0 +1,11 @@ +import { combineReducers, createStore } from "redux" + +import date from "./slices/date" + +const reducer = combineReducers({ + date +}) + +const store = createStore(reducer) + +export default store