diff --git a/assets/cycle-icon.png b/assets/cycle-icon.png new file mode 100644 index 0000000..aa225b3 Binary files /dev/null and b/assets/cycle-icon.png differ diff --git a/components/common/table.js b/components/common/table.js new file mode 100644 index 0000000..f1e024f --- /dev/null +++ b/components/common/table.js @@ -0,0 +1,79 @@ +import React from 'react' +import { StyleSheet, View } from 'react-native' +import PropTypes from 'prop-types' + +import AppText from './app-text' + +import { Spacing, Typography } from '../../styles/redesign' + +const Table = ({ tableContent }) => { + return ( + tableContent.map((rowContent, i) => ) + ) +} + +Table.propTypes = { + tableContent: PropTypes.array.isRequired +} + +const Row = ({ rowContent }) => { + return( + + + + + ) +} + +Row.propTypes = { + rowContent: PropTypes.array.isRequired +} + +const Cell = ({ content, isLeft }) => { + const styleContainer = isLeft ? styles.cellLeft : styles.cellRight + const styleText = isLeft ? styles.accentPurpleBig : styles.accentOrange + const numberOfLines = isLeft ? 1 : 2 + const ellipsizeMode = isLeft ? 'clip' : 'tail' + + return( + + + {content} + + + ) +} + +Cell.propTypes = { + content: PropTypes.node.isRequired, + isLeft: PropTypes.bool +} + +const styles = StyleSheet.create({ + accentOrange: { + ...Typography.accentOrange + }, + accentPurpleBig: { + ...Typography.accentPurpleBig, + marginRight: Spacing.base + }, + cellLeft: { + alignItems: 'flex-end', + flex: 5, + justifyContent: 'center' + }, + cellRight: { + flex: 6, + justifyContent: 'center' + }, + row: { + flexDirection: 'row', + marginBottom: Spacing.tiny + } +}) + +export default Table \ No newline at end of file diff --git a/components/stats.js b/components/stats.js index a89ddcc..213ae7d 100644 --- a/components/stats.js +++ b/components/stats.js @@ -1,77 +1,114 @@ -import React, { Component } from 'react' -import { - View, - ScrollView -} from 'react-native' +import React from 'react' +import { ImageBackground, StyleSheet, View } from 'react-native' + +import AppPage from './common/app-page' +import AppText from './common/app-text' +import Segment from './common/segment' +import Table from './common/table' -import styles from '../styles/index' import cycleModule from '../lib/cycle' import {getCycleLengthStats as getCycleInfo} from '../lib/cycle-length' import {stats as labels} from '../i18n/en/labels' -import AppText from './common/app-text' -import Segment from './common/segment' -export default class Stats extends Component { - render() { - const cycleLengths = cycleModule().getAllCycleLengths() - const atLeastOneCycle = cycleLengths.length >= 1 - let numberOfCycles - let cycleInfo - if (atLeastOneCycle) { - numberOfCycles = cycleLengths.length - if (numberOfCycles > 1) { - cycleInfo = getCycleInfo(cycleLengths) - } - } - return ( - - - - {labels.cycleLengthExplainer} - +import { Sizes, Spacing, Typography } from '../styles/redesign' - {!atLeastOneCycle && - {labels.emptyStats} - } - {atLeastOneCycle && numberOfCycles === 1 && - - {labels.oneCycleStats} - {cycleLengths[0]} - {labels.daysLabel}. - - } - {atLeastOneCycle && numberOfCycles > 1 && - - - {labels.averageLabel}: {cycleInfo.mean} {labels.daysLabel} - - - - - {labels.minLabel}: {cycleInfo.minimum} {labels.daysLabel} - - - - - {labels.maxLabel}: {cycleInfo.maximum} {labels.daysLabel} - - - - - {labels.stdLabel}: {cycleInfo.stdDeviation} {labels.daysLabel} - - - - {labels.basisOfStatsBeginning} - {numberOfCycles} - {labels.basisOfStatsEnd} - - } - - - ) +const image = require('../assets/cycle-icon.png') + +const Stats = () => { + const cycleLengths = cycleModule().getAllCycleLengths() + const atLeastOneCycle = cycleLengths.length >= 1 + const numberOfCycles = cycleLengths.length + let cycleData + if (atLeastOneCycle) { + cycleData = getCycleInfo(cycleLengths) } + + const statsData = [ + [atLeastOneCycle ? cycleData.minimum : 0, labels.minLabel], + [atLeastOneCycle ? cycleData.maximum : 0, labels.maxLabel], + [atLeastOneCycle && cycleData.stdDeviation ? cycleData.stdDeviation : '—', labels.stdLabel], + [numberOfCycles, labels.basisOfStatsEnd] + ] + return ( + + + {labels.cycleLengthExplainer} + {!atLeastOneCycle && {labels.emptyStats}} + {atLeastOneCycle && + + + + + {cycleData.mean} + + + {labels.daysLabel} + + + + {labels.averageLabel} + + + + + + + } + + + ) } + +const column = { + flexDirection: 'column' +} + +const styles = StyleSheet.create({ + accentOrange: { + ...Typography.accentOrange + }, + accentPurpleGiant: { + ...Typography.accentPurpleGiant, + marginVertical: Sizes.giant * (-0.5) + }, + accentPurpleHuge: { + ...Typography.accentPurpleHuge, + marginRight: Spacing.base + }, + container: { + alignItems: 'center', + flexDirection: 'row', + justifyContent: 'space-between', + }, + columnLeft: { + ...column, + flex: 4 + }, + columnRight: { + ...column, + flex: 5 + }, + image: { + height: Sizes.huge * 3, + marginLeft: Sizes.huge / 2, + resizeMode: 'contain', + width: Sizes.huge * 3 + }, + imageContainter: { + paddingTop: Sizes.huge, + marginBottom: Sizes.huge / 4 + }, + pageContainer: { + marginVertical: Spacing.large + } +}) + +export default Stats \ No newline at end of file diff --git a/i18n/en/labels.js b/i18n/en/labels.js index 4dd59fe..3b5e8df 100644 --- a/i18n/en/labels.js +++ b/i18n/en/labels.js @@ -61,19 +61,14 @@ export const menuTitles = { } export const stats = { - cycleLengthTitle: 'Cycle length', cycleLengthExplainer: 'Basic statistics about the length of your cycles.', emptyStats: 'At least one completed cycle is needed to display stats.', - //oneCycleStats: (number) => `You have documented one cycle of ${number} days.`, - oneCycleStats: 'You have documented one cycle of', daysLabel: 'days', - //getBasisOfStats: (numberOfCycles) => `Stats are based on ${numberOfCycles} completed cycles.`, - basisOfStatsBeginning: 'Stats are based on', - basisOfStatsEnd: 'completed cycles.', - averageLabel: 'Average cycle length', - minLabel: 'Shortest cycle', - maxLabel: 'Longest cycle', - stdLabel: 'Standard deviation' + basisOfStatsEnd: 'completed\ncycles', + averageLabel: 'Average cycle', + minLabel: `Shortest`, + maxLabel: `Longest`, + stdLabel: `Standard\ndeviation` } export const bleedingPrediction = { diff --git a/styles/typography.js b/styles/typography.js index 59892e8..bfc5173 100644 --- a/styles/typography.js +++ b/styles/typography.js @@ -12,7 +12,9 @@ export const sizes = { base: 18, subtitle: 22, title: 24, - huge: 40 + big: 30, + huge: 40, + giant: 50 } const title = { @@ -20,7 +22,49 @@ const title = { marginVertical: Spacing.large } +const accentText = { + fontFamily: fonts.bold, + textAlignVertical: 'center', + textTransform: 'uppercase' +} + +const accentTextBig = { + ...accentText, + fontSize: sizes.big, +} + +const accentTextGiant = { + ...accentText, + fontSize: sizes.giant, +} + +const accentTextHuge = { + ...accentText, + fontSize: sizes.huge, +} + +const accentTextSmall = { + ...accentText, + fontSize: sizes.small +} + export default { + accentOrange: { + ...accentTextSmall, + color: Colors.orange + }, + accentPurpleBig: { + ...accentTextBig, + color: Colors.purple + }, + accentPurpleGiant: { + ...accentTextGiant, + color: Colors.purple + }, + accentPurpleHuge: { + ...accentTextHuge, + color: Colors.purple + }, mainText: { fontFamily: fonts.main, fontSize: sizes.base