From f444de0b8796b002fee96134b925f805ec34c7a7 Mon Sep 17 00:00:00 2001 From: Sofiya Tepikin Date: Sun, 15 Sep 2019 15:29:15 +0200 Subject: [PATCH 1/6] Removes the lowercasing to the header title component --- components/app.js | 9 +-------- components/cycle-day/cycle-day-overview.js | 3 +-- components/cycle-day/symptoms/symptom-view.js | 2 +- components/header/title.js | 12 +++++++++--- components/helpers/format-date.js | 5 +++-- 5 files changed, 15 insertions(+), 16 deletions(-) diff --git a/components/app.js b/components/app.js index 1d0151d..cef888e 100644 --- a/components/app.js +++ b/components/app.js @@ -18,13 +18,6 @@ import {headerTitles, menuTitles} from '../i18n/en/labels' import setupNotifications from '../lib/notifications' import { closeDb } from '../db' -// design wants everyhting lowercased, but we don't -// have CSS pseudo properties -const headerTitlesLowerCase = Object.keys(headerTitles).reduce((acc, curr) => { - acc[curr] = headerTitles[curr].toLowerCase() - return acc -}, {}) - const HOME_PAGE = 'Home' const CYCLE_DAY_PAGE = 'CycleDay' const SETTINGS_MENU_PAGE = 'SettingsMenu' @@ -107,7 +100,7 @@ class App extends Component { ...symptomViews } const Page = pages[currentPage] - const title = headerTitlesLowerCase[currentPage] + const title = headerTitles[currentPage] const hasDefaultHeader = !this.isSymptomView() && diff --git a/components/cycle-day/cycle-day-overview.js b/components/cycle-day/cycle-day-overview.js index 5a39306..4df2f28 100644 --- a/components/cycle-day/cycle-day-overview.js +++ b/components/cycle-day/cycle-day-overview.js @@ -66,8 +66,7 @@ class CycleDayOverView extends Component { const { getCycleDayNumber } = cycleModule() const cycleDayNumber = getCycleDayNumber(date) - const headerSubtitle = - cycleDayNumber && `Cycle day ${cycleDayNumber}`.toLowerCase() + const headerSubtitle = cycleDayNumber && `Cycle day ${cycleDayNumber}` return ( diff --git a/components/cycle-day/symptoms/symptom-view.js b/components/cycle-day/symptoms/symptom-view.js index 749a873..d192f67 100644 --- a/components/cycle-day/symptoms/symptom-view.js +++ b/components/cycle-day/symptoms/symptom-view.js @@ -106,7 +106,7 @@ class SymptomView extends Component { return (
- {title} + { // design wants everyhting lowercased, but we don't + // have CSS pseudo properties + title.toLowerCase()} { subtitle && - {subtitle} + {subtitle.toLowerCase()} } ) } - return {title} + return ( + + {title.toLowerCase()} + + ) } Title.propTypes = { diff --git a/components/helpers/format-date.js b/components/helpers/format-date.js index cf63f70..d353dc6 100644 --- a/components/helpers/format-date.js +++ b/components/helpers/format-date.js @@ -4,8 +4,9 @@ import moment from 'moment' export default function (date) { const today = LocalDate.now() const dateToDisplay = LocalDate.parse(date) - const formattedDate = today.equals(dateToDisplay) ? 'today' : moment(date).format('MMMM Do YYYY') - return formattedDate.toLowerCase() + return today.equals(dateToDisplay) ? + 'today' : + moment(date).format('MMMM Do YYYY') } export function formatDateForShortText (date) { From e479b93638d9826cd21ce231b13272b3d53a62d1 Mon Sep 17 00:00:00 2001 From: Sofiya Tepikin Date: Sun, 15 Sep 2019 18:59:11 +0200 Subject: [PATCH 2/6] Moves navigation to the state --- components/app.js | 136 ++++++++------------- components/calendar.js | 2 + components/chart/day-column.js | 2 + components/cycle-day/cycle-day-overview.js | 9 +- components/home.js | 23 ++-- components/menu.js | 87 ------------- components/menu/index.js | 54 ++++++++ components/menu/menu-config.js | 30 +++++ components/menu/menu-item.js | 32 +++++ components/pages.js | 25 ++++ components/settings/settings-menu.js | 26 +++- slices/navigation.js | 26 ++++ store.js | 4 +- 13 files changed, 254 insertions(+), 202 deletions(-) delete mode 100644 components/menu.js create mode 100644 components/menu/index.js create mode 100644 components/menu/menu-config.js create mode 100644 components/menu/menu-item.js create mode 100644 components/pages.js create mode 100644 slices/navigation.js diff --git a/components/app.js b/components/app.js index cef888e..53aa680 100644 --- a/components/app.js +++ b/components/app.js @@ -1,117 +1,74 @@ import React, { Component } from 'react' import { View, BackHandler } from 'react-native' +import PropTypes from 'prop-types' + +import { LocalDate } from 'js-joda' import { connect } from 'react-redux' -import { getDate } from '../slices/date' +import { getDate, setDate } from '../slices/date' +import { getNavigation, navigate } from '../slices/navigation' import Header from './header' import Menu from './menu' -import Home from './home' -import Calendar from './calendar' -import CycleDay from './cycle-day/cycle-day-overview' -import symptomViews from './cycle-day/symptoms' -import Chart from './chart/chart' -import SettingsMenu from './settings/settings-menu' -import settingsViews from './settings' -import Stats from './stats' -import {headerTitles, menuTitles} from '../i18n/en/labels' -import setupNotifications from '../lib/notifications' -import { closeDb } from '../db' +import { pagesList, isSymptomView, isSettingsView } from './pages' -const HOME_PAGE = 'Home' -const CYCLE_DAY_PAGE = 'CycleDay' -const SETTINGS_MENU_PAGE = 'SettingsMenu' +import { headerTitles } from '../i18n/en/labels' +import setupNotifications from '../lib/notifications' +import { closeDb, getCycleDay } from '../db' class App extends Component { + + static propTypes = { + date: PropTypes.string, + navigation: PropTypes.object.isRequired, + } + constructor(props) { super(props) + + this.todayDateString = LocalDate.now().toString() + props.setDate(this.todayDateString) + this.state = { - currentPage: HOME_PAGE, - cycleDay: {}, + cycleDay: getCycleDay(this.todayDateString), } - this.backHandler = BackHandler.addEventListener('hardwareBackPress', this.handleBackButtonPress) - setupNotifications(this.navigate) + + this.backHandler = BackHandler.addEventListener( + 'hardwareBackPress', + this.handleBackButtonPress + ) + + setupNotifications(this.props.navigate) } componentWillUnmount() { this.backHandler.remove() } - navigate = (pageName, cycleDay) => { - const { currentPage } = this.state - // for the back button to work properly, we want to - // remember two origins: which menu item we came from - // and from where we navigated to the symptom view (day - // view or home page) - if (this.isMenuItem()) { - this.menuOrigin = currentPage - } - if (!this.isSymptomView()) { - this.originForSymptomView = currentPage - } - this.setState({ currentPage: pageName, cycleDay }) - } - handleBackButtonPress = () => { - const { currentPage } = this.state - if (currentPage === HOME_PAGE) { + const { current, prev } = this.props.navigation + if (current === 'Home') { closeDb() return false } - if (this.isSymptomView()) { - this.navigate(this.originForSymptomView) - } else if (this.isSettingsView()) { - this.navigate(SETTINGS_MENU_PAGE) - } else if (currentPage === CYCLE_DAY_PAGE) { - this.navigate(this.menuOrigin) - } else { - this.navigate(HOME_PAGE) - } + this.props.navigate(prev) return true } - isMenuItem() { - return Object.keys(menuTitles).includes(this.state.currentPage) - } - - isSymptomView() { - return Object.keys(symptomViews).includes(this.state.currentPage) - } - - isSettingsView() { - return Object.keys(settingsViews).includes(this.state.currentPage) - } - - isDefaultView() { - const { currentPage } = this.state - return this.isMenuItem(currentPage) || currentPage === SETTINGS_MENU_PAGE - } - render() { - const { currentPage, cycleDay } = this.state - const pages = { - Home, - Calendar, - CycleDay, - Chart, - SettingsMenu, - ...settingsViews, - Stats, - ...symptomViews - } - const Page = pages[currentPage] + const { cycleDay } = this.state + const currentPage = this.props.navigation.current + + const Page = pagesList[currentPage] const title = headerTitles[currentPage] - const hasDefaultHeader = - !this.isSymptomView() && - currentPage !== CYCLE_DAY_PAGE - - const isSettingsSubView = this.isSettingsView() + const isSymptomEditView = isSymptomView(currentPage) + const isSettingsSubView = isSettingsView(currentPage) + const isCycleDayView = currentPage === 'CycleDay' return ( - - { hasDefaultHeader && + { !isSymptomEditView && !isCycleDayView &&
- {!this.isSymptomView() && - - } + { !isSymptomEditView && } ) } @@ -135,11 +89,19 @@ class App extends Component { const mapStateToProps = (state) => { return({ - date: getDate(state) + date: getDate(state), + navigation: getNavigation(state) + }) +} + +const mapDispatchToProps = (dispatch) => { + return({ + setDate: (date) => dispatch(setDate(date)), + navigate: (page) => dispatch(navigate(page)), }) } export default connect( mapStateToProps, - null + mapDispatchToProps )(App) \ No newline at end of file diff --git a/components/calendar.js b/components/calendar.js index faf4bea..9387e0c 100644 --- a/components/calendar.js +++ b/components/calendar.js @@ -3,6 +3,7 @@ import { CalendarList } from 'react-native-calendars' import { connect } from 'react-redux' import { setDate } from '../slices/date' +import { navigate } from '../slices/navigation' import { LocalDate } from 'js-joda' import { getBleedingDaysSortedByDate } from '../db' @@ -68,6 +69,7 @@ class CalendarView extends Component { const mapDispatchToProps = (dispatch) => { return({ setDate: (date) => dispatch(setDate(date)), + navigate: (page) => dispatch(navigate(page)), }) } diff --git a/components/chart/day-column.js b/components/chart/day-column.js index 633f636..fffc1fc 100644 --- a/components/chart/day-column.js +++ b/components/chart/day-column.js @@ -3,6 +3,7 @@ import { TouchableOpacity } from 'react-native' import { connect } from 'react-redux' import { setDate } from '../../slices/date' +import { navigate } from '../../slices/navigation' import { getCycleDay } from '../../db' @@ -109,6 +110,7 @@ class DayColumn extends Component { const mapDispatchToProps = (dispatch) => { return({ setDate: (date) => dispatch(setDate(date)), + navigate: (page) => dispatch(navigate(page)), }) } diff --git a/components/cycle-day/cycle-day-overview.js b/components/cycle-day/cycle-day-overview.js index 4df2f28..7415ab2 100644 --- a/components/cycle-day/cycle-day-overview.js +++ b/components/cycle-day/cycle-day-overview.js @@ -3,6 +3,7 @@ import { ScrollView, View } from 'react-native' import { connect } from 'react-redux' import { getDate, setDate } from '../../slices/date' +import { navigate } from '../../slices/navigation' import { LocalDate } from 'js-joda' import Header from '../header' @@ -41,11 +42,6 @@ class CycleDayOverView extends Component { this.updateCycleDay(nextDate) } - navigate(symptom) { - const { cycleDay } = this.state - this.props.navigate(symptom, cycleDay) - } - render() { const { cycleDay } = this.state const { date } = this.props @@ -89,7 +85,7 @@ class CycleDayOverView extends Component { key={symptom} symptom={symptom} symptomData={symptomData} - onPress={() => this.navigate(symptomEditView, symptomData)} + onPress={() => this.props.navigate(symptomEditView)} disabled={dateInFuture} />) }) @@ -115,6 +111,7 @@ const mapStateToProps = (state) => { const mapDispatchToProps = (dispatch) => { return({ setDate: (date) => dispatch(setDate(date)), + navigate: (page) => dispatch(navigate(page)), }) } diff --git a/components/home.js b/components/home.js index 25c46b8..a0c4e27 100644 --- a/components/home.js +++ b/components/home.js @@ -3,7 +3,7 @@ import React, { Component } from 'react' import { ScrollView, View } from 'react-native' import { connect } from 'react-redux' -import { setDate } from '../slices/date' +import { navigate } from '../slices/navigation' import DripHomeIcon from '../assets/drip-home-icons' import { @@ -17,7 +17,6 @@ import styles, { cycleDayColor, periodColor, secondaryColor } from '../styles' import AppText from './app-text' import Button from './button' import { formatDateForShortText } from './helpers/format-date' -import { getCycleDay } from '../db' const IconText = ({ children, wrapperStyles }) => { return ( @@ -71,26 +70,20 @@ class Home extends Component { } } - setTodayDate = () => { - this.props.setDate(this.todayDateString) - } - navigateToCycleDayView = () => { - this.setTodayDate() this.props.navigate('CycleDay') } navigateToBleedingEditView = () => { - this.setTodayDate() - this.props.navigate( - 'BleedingEditView', - getCycleDay(this.todayDateString) - ) + this.props.navigate('BleedingEditView') + } + + navigateToChart = () => { + this.props.navigate('Chart') } render() { const { cycleDayNumber, phase, status } = this.state - const { navigate } = this.props const cycleDayMoreText = cycleDayNumber ? labels.cycleDayKnown(cycleDayNumber) : labels.cycleDayNotEnoughInfo @@ -136,7 +129,7 @@ class Home extends Component { navigate('Chart') } + onPress={this.navigateToChart} buttonColor={ secondaryColor } buttonLabel={ labels.checkFertility } > @@ -164,7 +157,7 @@ class Home extends Component { const mapDispatchToProps = (dispatch) => { return({ - setDate: (date) => dispatch(setDate(date)), + navigate: (page) => dispatch(navigate(page)) }) } diff --git a/components/menu.js b/components/menu.js deleted file mode 100644 index 3664e15..0000000 --- a/components/menu.js +++ /dev/null @@ -1,87 +0,0 @@ -import React from 'react' -import { - View, - Text, - TouchableOpacity -} from 'react-native' - -import settingsViews from './settings' - -import { menuTitles } from '../i18n/en/labels' - -import styles, { iconStyles, secondaryColor } from '../styles' -import Icon from 'react-native-vector-icons/MaterialCommunityIcons' - -const menuTitlesLowerCase = Object.keys(menuTitles).reduce((acc, curr) => { - acc[curr] = menuTitles[curr].toLowerCase() - return acc -}, {}) - -const menuItems = [ - { - labelKey: 'Home', - icon: 'home', - component: 'Home', - }, - { - labelKey: 'Calendar', - icon: 'calendar-range', - component: 'Calendar', - }, - { - labelKey: 'Chart', - icon: 'chart-line', - component: 'Chart', - }, - { - labelKey: 'Stats', - icon: 'chart-pie', - component: 'Stats', - }, - { - labelKey: 'Settings', - icon: 'settings', - component: 'SettingsMenu', - children: Object.keys(settingsViews), - } -] - -const MenuItem = ({ icon, labelKey, active, onPress }) => { - const styleActive = active ? { color: secondaryColor } : null - return ( - - - - {menuTitlesLowerCase[labelKey]} - - - ) -} - -const Menu = ({ currentPage, navigate }) => { - return ( - - { menuItems.map(({ icon, labelKey, component, children }) => { - const isActive = (component === currentPage) || - (children && children.indexOf(currentPage) !== -1) - return ( - navigate(component)} - /> - )} - )} - - ) -} - -export default Menu \ No newline at end of file diff --git a/components/menu/index.js b/components/menu/index.js new file mode 100644 index 0000000..75dd335 --- /dev/null +++ b/components/menu/index.js @@ -0,0 +1,54 @@ +import React from 'react' +import { View } from 'react-native' +import PropTypes from 'prop-types' + +import MenuItem from './menu-item' + +import { connect } from 'react-redux' +import { getNavigation, navigate } from '../../slices/navigation' + +import { menuItems } from './menu-config' + +import styles from '../../styles' + +const Menu = ({ navigation, navigate }) => { + return ( + + { menuItems.map(({ icon, labelKey, component, children }) => { + const isActive = (component === navigation.current) || + (children && children.indexOf(navigation.current) !== -1) + return ( + navigate(component)} + /> + )} + )} + + ) +} + +Menu.propTypes = { + navigation: PropTypes.object, + navigate: PropTypes.func, +} + +const mapStateToProps = (state) => { + return({ + navigation: getNavigation(state), + }) +} + +const mapDispatchToProps = (dispatch) => { + return({ + navigate: (page) => dispatch(navigate(page)), + }) +} + +export default connect( + mapStateToProps, + mapDispatchToProps, +)(Menu) \ No newline at end of file diff --git a/components/menu/menu-config.js b/components/menu/menu-config.js new file mode 100644 index 0000000..e02dfd8 --- /dev/null +++ b/components/menu/menu-config.js @@ -0,0 +1,30 @@ +import settingsViews from '../settings' + +export const menuItems = [ + { + labelKey: 'Home', + icon: 'home', + component: 'Home', + }, + { + labelKey: 'Calendar', + icon: 'calendar-range', + component: 'Calendar', + }, + { + labelKey: 'Chart', + icon: 'chart-line', + component: 'Chart', + }, + { + labelKey: 'Stats', + icon: 'chart-pie', + component: 'Stats', + }, + { + labelKey: 'Settings', + icon: 'settings', + component: 'SettingsMenu', + children: Object.keys(settingsViews), + } +] \ No newline at end of file diff --git a/components/menu/menu-item.js b/components/menu/menu-item.js new file mode 100644 index 0000000..083dd23 --- /dev/null +++ b/components/menu/menu-item.js @@ -0,0 +1,32 @@ +import React from 'react' +import { Text, TouchableOpacity } from 'react-native' + +import styles, { iconStyles, secondaryColor } from '../../styles' +import Icon from 'react-native-vector-icons/MaterialCommunityIcons' + +import { menuTitles } from '../../i18n/en/labels' + +const menuTitlesLowerCase = Object.keys(menuTitles).reduce((acc, curr) => { + acc[curr] = menuTitles[curr].toLowerCase() + return acc +}, {}) + +const MenuItem = ({ icon, labelKey, active, onPress }) => { + const styleActive = active ? { color: secondaryColor } : null + return ( + + + + {menuTitlesLowerCase[labelKey]} + + + ) +} + +export default MenuItem \ No newline at end of file diff --git a/components/pages.js b/components/pages.js new file mode 100644 index 0000000..533f77b --- /dev/null +++ b/components/pages.js @@ -0,0 +1,25 @@ +import Home from './home' +import Calendar from './calendar' +import CycleDay from './cycle-day/cycle-day-overview' +import symptomViews from './cycle-day/symptoms' +import Chart from './chart/chart' +import SettingsMenu from './settings/settings-menu' +import settingsViews from './settings' +import Stats from './stats' + +export const pagesList = { + Home, + Calendar, + CycleDay, + Chart, + SettingsMenu, + ...settingsViews, + Stats, + ...symptomViews +} + +export const isSymptomView = + (page) => Object.keys(symptomViews).includes(page) + +export const isSettingsView = + (page) => Object.keys(settingsViews).includes(page) \ No newline at end of file diff --git a/components/settings/settings-menu.js b/components/settings/settings-menu.js index ad4915a..a622a1d 100644 --- a/components/settings/settings-menu.js +++ b/components/settings/settings-menu.js @@ -1,10 +1,13 @@ import React from 'react' -import { - TouchableOpacity, - ScrollView, -} from 'react-native' +import { TouchableOpacity, ScrollView } from 'react-native' +import { connect } from 'react-redux' + +import { navigate } from '../../slices/navigation' + import styles from '../../styles/index' + import settingsLabels from '../../i18n/en/settings' + import AppText from '../app-text' const labels = settingsLabels.menuTitles @@ -18,7 +21,7 @@ const menu = [ {title: labels.license, component: 'License'} ] -export default function SettingsMenu(props) { +const SettingsMenu = (props) => { return ( { menu.map(menuItem)} @@ -36,4 +39,15 @@ export default function SettingsMenu(props) { ) } -} \ No newline at end of file +} + +const mapDispatchToProps = (dispatch) => { + return({ + navigate: (page) => dispatch(navigate(page)), + }) +} + +export default connect( + null, + mapDispatchToProps +)(SettingsMenu) \ No newline at end of file diff --git a/slices/navigation.js b/slices/navigation.js new file mode 100644 index 0000000..5de20f1 --- /dev/null +++ b/slices/navigation.js @@ -0,0 +1,26 @@ +import { createSlice } from 'redux-starter-kit' + +const navigationSlice = createSlice({ + slice: 'navigation', + initialState: { + current: 'Home', + prev: null, + }, + reducers: { + navigate: (state, action) => { + return { + current: action.payload, + prev: state.current + } + } + } +}) + +// Extract the action creators object and the reducer +const { actions, reducer, selectors } = navigationSlice +// Extract and export each action creator by name +export const { navigate } = actions + +export const { getNavigation } = selectors + +export default reducer diff --git a/store.js b/store.js index 7aa713d..7887652 100644 --- a/store.js +++ b/store.js @@ -1,9 +1,11 @@ import { combineReducers, createStore } from "redux" import date from "./slices/date" +import navigation from "./slices/navigation" const reducer = combineReducers({ - date + date, + navigation }) const store = createStore(reducer) From e66ca3f8dbdb2af031095a58e7f3b832a4a79d03 Mon Sep 17 00:00:00 2001 From: Sofiya Tepikin Date: Wed, 6 Nov 2019 18:58:40 +0100 Subject: [PATCH 3/6] Adds navigation tree to define the hierarchy --- components/app.js | 16 ++++--- components/menu/index.js | 15 +++--- components/menu/menu-config.js | 30 ------------ components/menu/menu-item.js | 6 +-- components/pages.js | 84 +++++++++++++++++++++++++++++++++- slices/navigation.js | 6 +-- 6 files changed, 105 insertions(+), 52 deletions(-) delete mode 100644 components/menu/menu-config.js diff --git a/components/app.js b/components/app.js index 53aa680..256c18f 100644 --- a/components/app.js +++ b/components/app.js @@ -10,7 +10,7 @@ import { getNavigation, navigate } from '../slices/navigation' import Header from './header' import Menu from './menu' -import { pagesList, isSymptomView, isSettingsView } from './pages' +import { viewsList, isSymptomView, isSettingsView, pages } from './pages' import { headerTitles } from '../i18n/en/labels' import setupNotifications from '../lib/notifications' @@ -46,20 +46,24 @@ class App extends Component { } handleBackButtonPress = () => { - const { current, prev } = this.props.navigation - if (current === 'Home') { + const { currentPage } = this.props.navigation + + if (currentPage === 'Home') { closeDb() return false } - this.props.navigate(prev) + + const page = pages.find(item => item.component === currentPage) + this.props.navigate(page.parent) + return true } render() { const { cycleDay } = this.state - const currentPage = this.props.navigation.current + const { currentPage } = this.props.navigation - const Page = pagesList[currentPage] + const Page = viewsList[currentPage] const title = headerTitles[currentPage] const isSymptomEditView = isSymptomView(currentPage) diff --git a/components/menu/index.js b/components/menu/index.js index 75dd335..969082e 100644 --- a/components/menu/index.js +++ b/components/menu/index.js @@ -7,20 +7,21 @@ import MenuItem from './menu-item' import { connect } from 'react-redux' import { getNavigation, navigate } from '../../slices/navigation' -import { menuItems } from './menu-config' +import { pages } from '../pages' import styles from '../../styles' -const Menu = ({ navigation, navigate }) => { +const Menu = ({ navigate, navigation }) => { + const menuItems = pages.filter(page => page.isInMenu) return ( - { menuItems.map(({ icon, labelKey, component, children }) => { - const isActive = (component === navigation.current) || - (children && children.indexOf(navigation.current) !== -1) + { menuItems.map(({ icon, label, component, children }) => { + const isActive = (component === navigation.currentPage) || + (children && children.indexOf(navigation.currentPage) !== -1) return ( navigate(component)} diff --git a/components/menu/menu-config.js b/components/menu/menu-config.js deleted file mode 100644 index e02dfd8..0000000 --- a/components/menu/menu-config.js +++ /dev/null @@ -1,30 +0,0 @@ -import settingsViews from '../settings' - -export const menuItems = [ - { - labelKey: 'Home', - icon: 'home', - component: 'Home', - }, - { - labelKey: 'Calendar', - icon: 'calendar-range', - component: 'Calendar', - }, - { - labelKey: 'Chart', - icon: 'chart-line', - component: 'Chart', - }, - { - labelKey: 'Stats', - icon: 'chart-pie', - component: 'Stats', - }, - { - labelKey: 'Settings', - icon: 'settings', - component: 'SettingsMenu', - children: Object.keys(settingsViews), - } -] \ No newline at end of file diff --git a/components/menu/menu-item.js b/components/menu/menu-item.js index 083dd23..cf59c0e 100644 --- a/components/menu/menu-item.js +++ b/components/menu/menu-item.js @@ -11,7 +11,7 @@ const menuTitlesLowerCase = Object.keys(menuTitles).reduce((acc, curr) => { return acc }, {}) -const MenuItem = ({ icon, labelKey, active, onPress }) => { +const MenuItem = ({ icon, label, active, onPress }) => { const styleActive = active ? { color: secondaryColor } : null return ( { > - {menuTitlesLowerCase[labelKey]} + {menuTitlesLowerCase[label]} ) diff --git a/components/pages.js b/components/pages.js index 533f77b..3558ea8 100644 --- a/components/pages.js +++ b/components/pages.js @@ -7,7 +7,10 @@ import SettingsMenu from './settings/settings-menu' import settingsViews from './settings' import Stats from './stats' -export const pagesList = { +import settingsLabels from '../i18n/en/settings' +const labels = settingsLabels.menuTitles + +export const viewsList = { Home, Calendar, CycleDay, @@ -22,4 +25,81 @@ export const isSymptomView = (page) => Object.keys(symptomViews).includes(page) export const isSettingsView = - (page) => Object.keys(settingsViews).includes(page) \ No newline at end of file + (page) => Object.keys(settingsViews).includes(page) + +const symptomsPages = Object.keys(symptomViews).map(symptomView => ({ + component: symptomView, parent: 'CycleDay', +})) + +export const pages = [ + { + component: 'Home', + icon: 'home', + isInMenu: true, + label: 'Home', + }, + { + component: 'Calendar', + icon: 'calendar-range', + isInMenu: true, + label: 'Calendar', + parent: 'Home', + }, + { + component: 'Chart', + icon: 'chart-line', + isInMenu: true, + label: 'Chart', + parent: 'Home', + }, + { + component: 'Stats', + icon: 'chart-pie', + isInMenu: true, + label: 'Stats', + parent: 'Home', + }, + { + children: Object.keys(settingsViews), + component: 'SettingsMenu', + icon: 'settings', + isInMenu: true, + label: 'Settings', + parent: 'Home', + }, + { + component: 'Reminders', + label: labels.reminders, + parent: 'SettingsMenu', + }, + { + component: 'NfpSettings', + label: labels.nfpSettings, + parent: 'SettingsMenu', + }, + { + component: 'DataManagement', + label: labels.dataManagement, + parent: 'SettingsMenu', + }, + { + component: 'Password', + label: labels.password, + parent: 'SettingsMenu', + }, + { + component: 'About', + label: labels.about, + parent: 'SettingsMenu', + }, + { + component: 'License', + label: labels.license, + parent: 'SettingsMenu', + }, + { + component: 'CycleDay', + parent: 'Home', + }, + ...symptomsPages +] \ No newline at end of file diff --git a/slices/navigation.js b/slices/navigation.js index 5de20f1..bd53dd3 100644 --- a/slices/navigation.js +++ b/slices/navigation.js @@ -3,14 +3,12 @@ import { createSlice } from 'redux-starter-kit' const navigationSlice = createSlice({ slice: 'navigation', initialState: { - current: 'Home', - prev: null, + currentPage: 'Home', }, reducers: { navigate: (state, action) => { return { - current: action.payload, - prev: state.current + currentPage: action.payload, } } } From 026a9c17c3fa7b6a87face981495089162f9b748 Mon Sep 17 00:00:00 2001 From: Sofiya Tepikin Date: Fri, 22 Nov 2019 20:28:14 +0100 Subject: [PATCH 4/6] Add go back functionality --- components/app.js | 9 ++++----- components/pages.js | 3 ++- slices/navigation.js | 13 ++++++++++++- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/components/app.js b/components/app.js index 256c18f..3f6f2cd 100644 --- a/components/app.js +++ b/components/app.js @@ -6,11 +6,11 @@ import { LocalDate } from 'js-joda' import { connect } from 'react-redux' import { getDate, setDate } from '../slices/date' -import { getNavigation, navigate } from '../slices/navigation' +import { getNavigation, navigate, goBack } from '../slices/navigation' import Header from './header' import Menu from './menu' -import { viewsList, isSymptomView, isSettingsView, pages } from './pages' +import { viewsList, isSymptomView, isSettingsView } from './pages' import { headerTitles } from '../i18n/en/labels' import setupNotifications from '../lib/notifications' @@ -53,9 +53,7 @@ class App extends Component { return false } - const page = pages.find(item => item.component === currentPage) - this.props.navigate(page.parent) - + this.props.goBack() return true } @@ -102,6 +100,7 @@ const mapDispatchToProps = (dispatch) => { return({ setDate: (date) => dispatch(setDate(date)), navigate: (page) => dispatch(navigate(page)), + goBack: () => dispatch(goBack()), }) } diff --git a/components/pages.js b/components/pages.js index 3558ea8..26a281d 100644 --- a/components/pages.js +++ b/components/pages.js @@ -28,7 +28,8 @@ export const isSettingsView = (page) => Object.keys(settingsViews).includes(page) const symptomsPages = Object.keys(symptomViews).map(symptomView => ({ - component: symptomView, parent: 'CycleDay', + component: symptomView, + parent: 'CycleDay', })) export const pages = [ diff --git a/slices/navigation.js b/slices/navigation.js index bd53dd3..909610c 100644 --- a/slices/navigation.js +++ b/slices/navigation.js @@ -4,12 +4,23 @@ const navigationSlice = createSlice({ slice: 'navigation', initialState: { currentPage: 'Home', + history: [], }, reducers: { navigate: (state, action) => { + const { history, currentPage } = state return { + history: history.concat(currentPage), currentPage: action.payload, } + }, + goBack: (state) => { + const { history } = state + const lastIndex = history.length - 1 + return { + currentPage: history[lastIndex], + history: history.slice(0, lastIndex), + } } } }) @@ -17,7 +28,7 @@ const navigationSlice = createSlice({ // Extract the action creators object and the reducer const { actions, reducer, selectors } = navigationSlice // Extract and export each action creator by name -export const { navigate } = actions +export const { navigate, goBack } = actions export const { getNavigation } = selectors From 8cad357e607d4b997ba33cc3961ce3729d6d7847 Mon Sep 17 00:00:00 2001 From: Sofiya Tepikin Date: Wed, 5 Feb 2020 19:50:40 +0100 Subject: [PATCH 5/6] Fixes navigation logic --- components/app.js | 47 ++++++++++++++++++++++---------------------- components/pages.js | 25 ++++------------------- components/views.js | 19 ++++++++++++++++++ slices/navigation.js | 30 ++++++++++++++++++++-------- 4 files changed, 69 insertions(+), 52 deletions(-) create mode 100644 components/views.js diff --git a/components/app.js b/components/app.js index 3f6f2cd..a351513 100644 --- a/components/app.js +++ b/components/app.js @@ -10,11 +10,12 @@ import { getNavigation, navigate, goBack } from '../slices/navigation' import Header from './header' import Menu from './menu' -import { viewsList, isSymptomView, isSettingsView } from './pages' +import { viewsList } from './views' +import { isSymptomView, isSettingsView } from './pages' import { headerTitles } from '../i18n/en/labels' import setupNotifications from '../lib/notifications' -import { closeDb, getCycleDay } from '../db' +import { getCycleDay } from '../db' class App extends Component { @@ -35,7 +36,7 @@ class App extends Component { this.backHandler = BackHandler.addEventListener( 'hardwareBackPress', - this.handleBackButtonPress + props.goBack ) setupNotifications(this.props.navigate) @@ -45,21 +46,15 @@ class App extends Component { this.backHandler.remove() } - handleBackButtonPress = () => { - const { currentPage } = this.props.navigation + render() { + const { date, navigation, goBack } = this.props + const { currentPage } = navigation - if (currentPage === 'Home') { - closeDb() + if (!currentPage) { return false } - this.props.goBack() - return true - } - - render() { const { cycleDay } = this.state - const { currentPage } = this.props.navigation const Page = viewsList[currentPage] const title = headerTitles[currentPage] @@ -68,20 +63,26 @@ class App extends Component { const isSettingsSubView = isSettingsView(currentPage) const isCycleDayView = currentPage === 'CycleDay' + const headerProps = { + title, + handleBack: isSettingsSubView ? goBack : null, + } + + const pageProps = { + cycleDay, + date, + handleBackButtonPress: goBack, + } + return ( - { !isSymptomEditView && !isCycleDayView && -
+ { + !isSymptomEditView && + !isCycleDayView && +
} - + { !isSymptomEditView && } diff --git a/components/pages.js b/components/pages.js index 26a281d..943a6a9 100644 --- a/components/pages.js +++ b/components/pages.js @@ -1,25 +1,13 @@ -import Home from './home' -import Calendar from './calendar' -import CycleDay from './cycle-day/cycle-day-overview' import symptomViews from './cycle-day/symptoms' -import Chart from './chart/chart' -import SettingsMenu from './settings/settings-menu' import settingsViews from './settings' -import Stats from './stats' import settingsLabels from '../i18n/en/settings' const labels = settingsLabels.menuTitles -export const viewsList = { - Home, - Calendar, - CycleDay, - Chart, - SettingsMenu, - ...settingsViews, - Stats, - ...symptomViews -} +const symptomsPages = Object.keys(symptomViews).map(symptomView => ({ + component: symptomView, + parent: 'CycleDay', +})) export const isSymptomView = (page) => Object.keys(symptomViews).includes(page) @@ -27,11 +15,6 @@ export const isSymptomView = export const isSettingsView = (page) => Object.keys(settingsViews).includes(page) -const symptomsPages = Object.keys(symptomViews).map(symptomView => ({ - component: symptomView, - parent: 'CycleDay', -})) - export const pages = [ { component: 'Home', diff --git a/components/views.js b/components/views.js new file mode 100644 index 0000000..1cb8545 --- /dev/null +++ b/components/views.js @@ -0,0 +1,19 @@ +import Home from './home' +import Calendar from './calendar' +import CycleDay from './cycle-day/cycle-day-overview' +import symptomViews from './cycle-day/symptoms' +import Chart from './chart/chart' +import SettingsMenu from './settings/settings-menu' +import settingsViews from './settings' +import Stats from './stats' + +export const viewsList = { + Home, + Calendar, + CycleDay, + Chart, + SettingsMenu, + ...settingsViews, + Stats, + ...symptomViews +} diff --git a/slices/navigation.js b/slices/navigation.js index 909610c..13674fd 100644 --- a/slices/navigation.js +++ b/slices/navigation.js @@ -1,25 +1,39 @@ import { createSlice } from 'redux-starter-kit' +import { pages, isSymptomView } from '../components/pages' +import { closeDb } from '../db' +import { BackHandler } from 'react-native' const navigationSlice = createSlice({ slice: 'navigation', initialState: { currentPage: 'Home', - history: [], }, reducers: { navigate: (state, action) => { - const { history, currentPage } = state return { - history: history.concat(currentPage), currentPage: action.payload, + previousPage: state.currentPage, } }, - goBack: (state) => { - const { history } = state - const lastIndex = history.length - 1 + goBack: ({ currentPage, previousPage }) => { + + if (currentPage === 'Home') { + closeDb() + BackHandler.exitApp() + return false + } + + if (currentPage === 'CycleDay' || isSymptomView(currentPage)) { + if (previousPage) { + return { + currentPage: previousPage + } + } + } + + const page = pages.find(p => p.component === currentPage) return { - currentPage: history[lastIndex], - history: history.slice(0, lastIndex), + currentPage: page.parent } } } From e88f26dc16dd121b0274b0640460a734829a3f4a Mon Sep 17 00:00:00 2001 From: Sofiya Tepikin Date: Sun, 16 Feb 2020 16:26:37 +0100 Subject: [PATCH 6/6] Fixes missing navigation state on exiting the app --- slices/navigation.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slices/navigation.js b/slices/navigation.js index 13674fd..24991df 100644 --- a/slices/navigation.js +++ b/slices/navigation.js @@ -20,7 +20,7 @@ const navigationSlice = createSlice({ if (currentPage === 'Home') { closeDb() BackHandler.exitApp() - return false + return { currentPage } } if (currentPage === 'CycleDay' || isSymptomView(currentPage)) {