From 5d436630d36cab7558ad671afef2213a36454c11 Mon Sep 17 00:00:00 2001 From: Sofiya Tepikin Date: Sat, 14 Sep 2019 12:39:30 +0200 Subject: [PATCH] Refactors the header --- components/app.js | 17 +++--- components/cycle-day/cycle-day-overview.js | 40 +++++++++----- components/cycle-day/symptoms/symptom-view.js | 31 +++++++++-- components/header/back-button.js | 24 --------- components/header/cycle-day.js | 29 ---------- components/header/default.js | 16 ------ components/header/delete-icon.js | 26 +++++++++ components/header/index.js | 46 ++++++++++------ components/header/navigation-arrow.js | 40 ++++++-------- components/header/symptom-view.js | 54 ------------------- components/header/title.js | 30 +++++++++++ e2e/dataInput.spec.js | 2 +- e2e/date.spec.js | 6 +-- e2e/homeNavigation.spec.js | 6 +-- styles/index.js | 3 +- 15 files changed, 175 insertions(+), 195 deletions(-) delete mode 100644 components/header/back-button.js delete mode 100644 components/header/cycle-day.js delete mode 100644 components/header/default.js create mode 100644 components/header/delete-icon.js delete mode 100644 components/header/symptom-view.js create mode 100644 components/header/title.js diff --git a/components/app.js b/components/app.js index fd9a9fa..1d0151d 100644 --- a/components/app.js +++ b/components/app.js @@ -109,16 +109,19 @@ class App extends Component { const Page = pages[currentPage] const title = headerTitlesLowerCase[currentPage] + const hasDefaultHeader = + !this.isSymptomView() && + currentPage !== CYCLE_DAY_PAGE + + const isSettingsSubView = this.isSettingsView() + return ( - - {this.isDefaultView() && -
- } - {(this.isSettingsView()) && + + + { hasDefaultHeader &&
} diff --git a/components/cycle-day/cycle-day-overview.js b/components/cycle-day/cycle-day-overview.js index 93ccb9c..5a39306 100644 --- a/components/cycle-day/cycle-day-overview.js +++ b/components/cycle-day/cycle-day-overview.js @@ -9,8 +9,9 @@ import Header from '../header' import FillerBoxes from './FillerBoxes' import SymptomBox from './SymptomBox' -import { getCycleDay } from '../../db' import cycleModule from '../../lib/cycle' +import formatDate from '../helpers/format-date' +import { getCycleDay } from '../../db' import styles from '../../styles' class CycleDayOverView extends Component { @@ -21,28 +22,34 @@ class CycleDayOverView extends Component { } } - goToCycleDay = (target) => { - const localDate = LocalDate.parse(this.props.date) - const targetDate = target === 'before' ? - localDate.minusDays(1).toString() : - localDate.plusDays(1).toString() - this.props.setDate(targetDate) + updateCycleDay = (date) => { + this.props.setDate(date) this.setState({ - cycleDay: getCycleDay(targetDate) + cycleDay: getCycleDay(date) }) } + goToPrevDay = () => { + const { date } = this.props + const prevDate = LocalDate.parse(date).minusDays(1).toString() + this.updateCycleDay(prevDate) + } + + goToNextDay = () => { + const { date } = this.props + const nextDate = LocalDate.parse(date).plusDays(1).toString() + this.updateCycleDay(nextDate) + } + navigate(symptom) { const { cycleDay } = this.state this.props.navigate(symptom, cycleDay) } render() { - const { getCycleDayNumber } = cycleModule() const { cycleDay } = this.state const { date } = this.props - const cycleDayNumber = getCycleDayNumber(date) const dateInFuture = LocalDate.now().isBefore(LocalDate.parse(date)) const symptomBoxesList = [ @@ -57,13 +64,18 @@ class CycleDayOverView extends Component { 'note', ] + const { getCycleDayNumber } = cycleModule() + const cycleDayNumber = getCycleDayNumber(date) + const headerSubtitle = + cycleDayNumber && `Cycle day ${cycleDayNumber}`.toLowerCase() + return (
diff --git a/components/cycle-day/symptoms/symptom-view.js b/components/cycle-day/symptoms/symptom-view.js index 44052b6..c2a5dbc 100644 --- a/components/cycle-day/symptoms/symptom-view.js +++ b/components/cycle-day/symptoms/symptom-view.js @@ -6,8 +6,9 @@ import { connect } from 'react-redux' import { getDate } from '../../../slices/date' import { saveSymptom } from '../../../db' +import formatDate from '../../helpers/format-date' -import Header from '../../header/symptom-view' +import Header from '../../header' import SymptomInfo from './symptom-info' import { headerTitles } from '../../../i18n/en/labels' @@ -80,16 +81,36 @@ class SymptomView extends Component { ) } + showConfirmationAlert = () => { + + const cancelButton = { + text: sharedDialogs.cancel, + style: 'cancel' + } + + const confirmationButton = { + text: sharedDialogs.reallyDeleteData, + onPress: this.onDeleteConfirmation + } + + return Alert.alert( + sharedDialogs.areYouSureTitle, + sharedDialogs.areYouSureToDelete, + [cancelButton, confirmationButton] + ) + } + render() { const { symptom } = this.props return (
diff --git a/components/header/back-button.js b/components/header/back-button.js deleted file mode 100644 index be82802..0000000 --- a/components/header/back-button.js +++ /dev/null @@ -1,24 +0,0 @@ -import React from 'react' -import { - Text, - View -} from 'react-native' -import styles from '../../styles' -import NavigationArrow from './navigation-arrow' - -export default function BackButtonHeader(props) { - return ( - - - - - - {props.title} - - - - ) -} diff --git a/components/header/cycle-day.js b/components/header/cycle-day.js deleted file mode 100644 index 57cf329..0000000 --- a/components/header/cycle-day.js +++ /dev/null @@ -1,29 +0,0 @@ -import React from 'react' -import { - View, - Text} from 'react-native' -import styles from '../../styles' -import NavigationArrow from './navigation-arrow' -import formatDate from '../helpers/format-date' - -export default function CycleDayHeader({ date, cycleDayNumber, ...props }) { - return ( - - - - - {formatDate(date)} - - { cycleDayNumber && - - {`Cycle day ${cycleDayNumber}`.toLowerCase()} - - } - - - - ) -} diff --git a/components/header/default.js b/components/header/default.js deleted file mode 100644 index ab2ecaf..0000000 --- a/components/header/default.js +++ /dev/null @@ -1,16 +0,0 @@ -import React from 'react' -import { - View, - Text} from 'react-native' -import styles from '../../styles' - -export default function DefaultHeader(props) { - return ( - - - - {props.title} - - - ) -} diff --git a/components/header/delete-icon.js b/components/header/delete-icon.js new file mode 100644 index 0000000..ebcf9ba --- /dev/null +++ b/components/header/delete-icon.js @@ -0,0 +1,26 @@ +import React from 'react' +import { TouchableOpacity } from 'react-native' +import PropTypes from 'prop-types' + +import Icon from 'react-native-vector-icons/AntDesign' + +import styles, { iconStyles } from '../../styles' + +export default function DeleteIcon({ handleDelete }) { + + return ( + + + + ) +} + +DeleteIcon.propTypes = { + handleDelete: PropTypes.func, +} diff --git a/components/header/index.js b/components/header/index.js index 3de4034..d96856a 100644 --- a/components/header/index.js +++ b/components/header/index.js @@ -1,19 +1,35 @@ import React from 'react' -import { Dimensions } from 'react-native' -import CycleDayHeader from './cycle-day' -import DefaultHeader from './default' -import BackButtonHeader from './back-button' +import { View } from 'react-native' +import PropTypes from 'prop-types' -export default function Header(p) { - const middle = Dimensions.get('window').width / 2 - const props = Object.assign({}, p, {middle}) +import Title from './title' +import NavigationArrow from './navigation-arrow' +import DeleteIcon from './delete-icon' - if (props.isCycleDayOverView) { - return () - } else if (props.showBackButton) { - return () - } - else { - return () - } +import styles from '../../styles' + +export default function Header({ + handleBack, + handleNext, + handleDelete, + title, + subtitle, +}) { + + return ( + + + { handleBack && } + + { handleNext && <NavigationArrow handleNext={handleNext} /> } + { handleDelete && <DeleteIcon handleDelete={handleDelete} /> } + </View > + ) +} + +Header.propTypes = { + handleBack: PropTypes.func, + handleNext: PropTypes.func, + title: PropTypes.string, + subtitle: PropTypes.string, } diff --git a/components/header/navigation-arrow.js b/components/header/navigation-arrow.js index 336e2f6..7675893 100644 --- a/components/header/navigation-arrow.js +++ b/components/header/navigation-arrow.js @@ -1,36 +1,30 @@ import React from 'react' import { TouchableOpacity } from 'react-native' -import styles, { iconStyles } from '../../styles' +import PropTypes from 'prop-types' import Icon from 'react-native-vector-icons/Entypo' -export default function NavigationArrow(props) { - const iconName = { - left: 'chevron-thin-left', - right: 'chevron-thin-right' - }[props.direction] - const iconPosition = { - left: 'navigationArrowLeft', - right: 'navigationArrowRight' - }[props.direction] - let pressHandler - if (props.goBack) { - pressHandler = () => props.goBack() - } else { - pressHandler = () => { - const target = props.direction === 'left' ? 'before' : 'after' - props.goToCycleDay(target) - } - } +import styles, { iconStyles } from '../../styles' + +export default function NavigationArrow({ handleBack, handleNext }) { + const navigationDirection = handleBack ? 'Left' : 'Right' return ( <TouchableOpacity - style={[styles.navigationArrow, styles[iconPosition]]} - onPress={pressHandler} - testID={props.testID} + style={[ + styles.navigationArrow, + styles[`navigationArrow${navigationDirection}`] + ]} + onPress={ handleBack || handleNext } + testID={ handleBack ? 'backButton' : 'nextButton'} > <Icon - name={iconName} + name={`chevron-thin-${navigationDirection.toLowerCase()}`} {...iconStyles.navigationArrow} /> </TouchableOpacity> ) +} + +NavigationArrow.propTypes = { + handleBack: PropTypes.func, + handleNext: PropTypes.func, } \ No newline at end of file diff --git a/components/header/symptom-view.js b/components/header/symptom-view.js deleted file mode 100644 index c8e9560..0000000 --- a/components/header/symptom-view.js +++ /dev/null @@ -1,54 +0,0 @@ -import React from 'react' -import { - View, - Text, - TouchableOpacity, - Dimensions -} from 'react-native' -import PropTypes from 'prop-types' - -import styles, { iconStyles } from '../../styles' -import Icon from 'react-native-vector-icons/AntDesign' -import NavigationArrow from './navigation-arrow' -import formatDate from '../helpers/format-date' - -SymptomViewHeader.propTypes = { - title: PropTypes.string, - date: PropTypes.string, - goBack: PropTypes.func, - deleteIconActive: PropTypes.bool, - onDelete: PropTypes.func, -} - -export default function SymptomViewHeader(props) { - const { goBack, title, date, shouldShowDelete, onDelete } = props - const middle = Dimensions.get('window').width / 2 - return ( - <View style={[styles.header, styles.headerCycleDay, styles.headerSymptom]}> - <View - style={styles.accentCircle} - left={middle - styles.accentCircle.width / 2} - /> - <NavigationArrow direction='left' goBack={goBack} /> - <View> - <Text style={styles.dateHeader} testID='symptomViewTitleName'> - {title} - </Text> - { date && - <Text style={styles.cycleDayNumber} testID='symptomViewTitleDate'> - {formatDate(date)} - </Text> - } - </View > - { shouldShowDelete && <DeleteButton onDelete={onDelete} />} - </View> - ) -} - -const DeleteButton = ({ onDelete }) => { - return ( - <TouchableOpacity onPress={onDelete} style={styles.headerDeleteButton}> - <Icon name="delete" {...iconStyles.symptomHeaderIcons} /> - </TouchableOpacity> - ) -} diff --git a/components/header/title.js b/components/header/title.js new file mode 100644 index 0000000..eb5c8ba --- /dev/null +++ b/components/header/title.js @@ -0,0 +1,30 @@ +import React from 'react' +import { View, Text} from 'react-native' +import PropTypes from 'prop-types' + +import styles from '../../styles' + +export default function Title({ title, subtitle }) { + + if (subtitle !== undefined) { + return ( + <View> + <Text style={styles.dateHeader} testID='headerTitle'> + {title} + </Text> + { subtitle && + <Text style={styles.cycleDayNumber} testID='headerSubtitle'> + {subtitle} + </Text> + } + </View> + ) + } + + return <Text testID='headerTitle' style={styles.headerText}>{title}</Text> +} + +Title.propTypes = { + title: PropTypes.string, + subtitle: PropTypes.string, +} diff --git a/e2e/dataInput.spec.js b/e2e/dataInput.spec.js index 5877e93..39899bd 100644 --- a/e2e/dataInput.spec.js +++ b/e2e/dataInput.spec.js @@ -98,7 +98,7 @@ describe('Symptom Data Input', () => { await navigateToSymptomView(symptom) let expectedSymptomSummary - await expect(element(by.id('symptomViewTitleName').and(by.text(symptom)))) + await expect(element(by.id('headerTitle').and(by.text(symptom)))) .toBeVisible() switch (symptom) { diff --git a/e2e/date.spec.js b/e2e/date.spec.js index b11a985..1c3e240 100644 --- a/e2e/date.spec.js +++ b/e2e/date.spec.js @@ -10,9 +10,9 @@ describe('Date', () => { await element(by.text('add data for today')).tap() await expect( - element(by.id('cycleDayTitleDate').and(by.text('today'))) + element(by.id('headerTitle').and(by.text('today'))) ).toBeVisible() - await element(by.id('previousDateButton')).tap() + await element(by.id('backButton')).tap() await element(by.id('drip-icon-bleeding')).tap() const today = LocalDate.now() @@ -22,7 +22,7 @@ describe('Date', () => { .toLowerCase() await expect( - element(by.id('symptomViewTitleDate').and(by.text(yesterdayFormatted))) + element(by.id('headerSubtitle').and(by.text(yesterdayFormatted))) ).toBeVisible() }) diff --git a/e2e/homeNavigation.spec.js b/e2e/homeNavigation.spec.js index c3effcb..3302c0b 100644 --- a/e2e/homeNavigation.spec.js +++ b/e2e/homeNavigation.spec.js @@ -1,6 +1,6 @@ const isOnPage = async (page, parentPage) => { await expect( - element(by.id('pageTitle').and(by.text(page))) + element(by.id('headerTitle').and(by.text(page))) ).toBeVisible() await expect( element( @@ -35,10 +35,10 @@ describe('Home Navigation', () => { it('should navigate to today bleeding symptom', async () => { await element(by.text('track your period')).tap() await expect( - element(by.id('symptomViewTitleName').and(by.text('bleeding'))) + element(by.id('headerTitle').and(by.text('bleeding'))) ).toBeVisible() await expect( - element(by.id('symptomViewTitleDate').and(by.text('today'))) + element(by.id('headerSubtitle').and(by.text('today'))) ).toBeVisible() }) diff --git a/styles/index.js b/styles/index.js index fa766d6..7825d11 100644 --- a/styles/index.js +++ b/styles/index.js @@ -95,7 +95,8 @@ export default StyleSheet.create({ width: 40, height: 40, borderRadius: 100, - position: 'absolute' + position: 'absolute', + alignSelf: 'center', }, errorMessage: { color: shadesOfRed[2],