Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP - Refactor reusable components #133

Merged
merged 28 commits into from
May 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
be9270d
Used <Icon> for all icons for consistency
mxnyee Mar 28, 2020
094f1cc
Refactored IconButton
mxnyee Mar 28, 2020
63bb3de
Refactored Button
mxnyee Mar 28, 2020
11434f2
Refactored Switch
mxnyee Mar 28, 2020
30741cc
Refactored Spinner
mxnyee Mar 28, 2020
1939027
Refactored SearchBar
mxnyee Mar 28, 2020
0ef8477
Removed trailing commas from components
mxnyee Mar 28, 2020
4a7c650
Refactored layout components
mxnyee Mar 28, 2020
21d9c98
Refactored Segment
mxnyee Mar 28, 2020
d37d1e9
Refactored Header
mxnyee Mar 28, 2020
2d4a29a
Refactored Modal
mxnyee Mar 28, 2020
e5e7b14
Refactored Input
mxnyee Mar 28, 2020
5389a06
Cleaned up components some more
mxnyee Mar 28, 2020
02c3464
Refactored Input to do form validation using validate.js
mxnyee Mar 28, 2020
7fa70de
Testing form validations done by SignupScreen
mxnyee Mar 29, 2020
7b2e8e8
Revert "Testing form validations done by SignupScreen"
mxnyee Mar 29, 2020
1ca1268
Fixed animation bug in Input
mxnyee Mar 29, 2020
5ac9269
Cleaned Input, fixed form validation, and updated documentation
mxnyee Mar 29, 2020
45ab399
Merge branch 'master' into refactor-components
mxnyee May 15, 2020
a95245a
Fix multiline Input
mxnyee May 18, 2020
c69f6e5
Add missing semicolons
mxnyee May 18, 2020
4f92e85
Fix drawer buttons
mxnyee May 18, 2020
1a3ee8d
Update styling for the Timer component
mxnyee May 18, 2020
e1fd131
Prevent double tap on buttons
mxnyee May 18, 2020
ae300d4
Clean LocationScreen
mxnyee May 18, 2020
f732a9f
Prevent double tap on Button and IconButton
mxnyee May 19, 2020
023dad1
Clean UsingScreen
mxnyee May 19, 2020
5ab751a
Add loadingText prop to Button
mxnyee May 19, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 31 additions & 13 deletions components/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ Props:
- textStyles: additional styles to pass onto the Text component inside the Button
- optional
- type: object
- loadingText: text shown on the button when the "disabled" prop is set to true
- optional
- type: string


**Switch**
Expand Down Expand Up @@ -99,6 +102,14 @@ Props:
- optional
- type: number
- default: 0
- size: the size of the button
- optional
- type: number
- default: 42
- color: the color of the button
- optional
- type: string
- default: "#60A781" (green)
- onPress: the function to execute when the IconButton is pressed
- optional
- type: function
Expand All @@ -115,34 +126,38 @@ Every input should be wrapped in a Form element. This allows scrolling and keybo
```
<Form>
<Input
label="Phone Number"
variant="number"
hasError={false}
errorText="Format is invalid."
variant="email"
label="Email"
constraints={{presence: true, email: {message: "Email is not valid."}}}
onChangeText=((newValue, isValid) => {console.log(newValue, isValid)})
/>
</Form>
```

Props:

- label: acts as the placeholder, then floats up once the Input is selected
- required
- type: string
- variant: changes the keyboard type
- optional
- type: one of "text", "password", "number"
- default: "text"
- hasError: set to true if the current input value is invalid. Invalid inputs have a red underline.
- label: acts as the placeholder, then floats up once the Input is selected
- required
- type: string
- hasNext: set to true if onSubmitEditing is linked to another Input (see below)
- optional
- type: boolean
- default: false
- errorText: the message that shows whenever hasError is true. If not specified, no error message will ever be shown.
- constraints: the constraints object used to validate the input
- optional
- type: string
- hasNext: set to true if onSubmitEditing is linked to another Input (see below)
- type: object, see https://validatejs.org/#validate-single
- onChangeText: the callback invoked whenever the user types into the Input
- optional
- type: function
- if the constraints prop is supplied, onChangeText can take two parameters: onChangeText = (newValue, isValid) => {...}
- otherwise, onChangeText can be defined as normal: onChangeText = (newValue) => {...}
- refresh: can be used to force the Input to validate. Every time refresh is toggled, Input will simulate a call to onChangeText using the current input value
- optional
- type: boolean
- default: false

You can use refs to link multiple Inputs together. In the example below, pressing the return key on the Username field will shift focus to the Password field.

Expand Down Expand Up @@ -369,7 +384,7 @@ const alertTitle = "Reminder";
const alertBody = "Please update your profile.",
const positiveButton = {
text: "OK",
onPress: () => {console.log("Woo!")}
onPress: () => console.log("Woo!")
};
const negativeButton = {
text: "Cancel",
Expand All @@ -378,6 +393,7 @@ const negativeButton = {
const neutralButton = {
text: "Later"
}
const onCancel = () => console.log("Cancelled");

return (
<Alert
Expand All @@ -387,6 +403,7 @@ return (
negativeButton={negativeButton}
neutralButton={neutralButton}
cancelable={true}
onCancel={onCancel}
/>
);
```
Expand Down Expand Up @@ -426,6 +443,7 @@ Props:
- "body", "footnote", "title" (used for displaying text on screen)
- "header" (used in the Header component)
- "label" (used for very small text, e.g. button labels)
- "numeral" (used for digits on the countdown timer)
- default: "body"

## Timer
Expand Down
20 changes: 8 additions & 12 deletions components/Timer/SetTimeButton.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,21 @@
import React from "react";
import { Text, View, StyleSheet, TouchableOpacity } from "react-native";
import { StyleSheet, TouchableOpacity } from "react-native";
import { View } from "../layout";
import { Text } from "../typography";
import theme from "../../styles/base";

export default function SetTimeButton({ changeTimeHandler, children }) {
return (
<View>
<TouchableOpacity onPress={changeTimeHandler}>
<Text style={style.buttonText}>{children}</Text>
<Text style={style.secondsText}>seconds</Text>
<Text style={styles.buttonText}>{children} s</Text>
</TouchableOpacity>
</View>
)
);
};

const style = StyleSheet.create({
const styles = StyleSheet.create({
buttonText: {
paddingLeft: 8,
fontSize: 22,
color: "#67686B",
},
secondsText: {
fontSize: 14,
color: "#67686B",
fontSize: theme.fontSizes.large
}
});
111 changes: 79 additions & 32 deletions components/Timer/Timer.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,16 @@
import React, { Component } from "react";
import { Text, View } from "react-native";
import { StyleSheet } from "react-native";
import { Actions } from "react-native-router-flux";
import { connect } from 'react-redux';
import { increaseTime, decreaseTime, countdown, clearTime, resetTime, updateAlarmLog } from '../../store/actions';
import ProgressCircle from 'react-native-progress-circle';
import { connect } from "react-redux";
import { increaseTime, decreaseTime, countdown, clearTime, resetTime, updateAlarmLog } from "../../store/actions";
import ProgressCircle from "react-native-progress-circle";
import SetTimeButton from "./SetTimeButton";
import { View } from "../layout";
import { Text } from "../typography";
import theme from "../../styles/base";

class Timer extends Component {

constructor(props) {
super(props);
this.countdown = this.countdown.bind(this);
this.incrementTimer = this.incrementTimer.bind(this);
this.decrementTimer = this.decrementTimer.bind(this);
}

countdown() {
countdown = () => {
if (this.props.time.timeRemaining - 1 <= 15) {
clearInterval(this.interval);
Actions.snooze();
Expand All @@ -24,24 +19,24 @@ class Timer extends Component {
}
};

resetInterval() {
resetInterval = () => {
if (this.props.isUsing) {
clearInterval(this.interval);
this.interval = setInterval(() => { this.countdown(); }, 1000);
}
}
};

incrementTimer() {
incrementTimer = () => {
this.props.increaseTime(this.props.time.timeRemaining);
if (this.props.isUsing) {
this.props.updateAlarmLog(this.props.time.timeRemaining+15, null, this.props.currentAlarmLog, this.props.token);
this.props.updateAlarmLog(this.props.time.timeRemaining + 15, null, this.props.currentAlarmLog, this.props.token);
}
this.resetInterval();
};

decrementTimer() {
decrementTimer = () => {
if (this.props.isUsing) {
this.props.updateAlarmLog(this.props.time.timeRemaining-15, false, this.props.currentAlarmLog, this.props.token);
this.props.updateAlarmLog(this.props.time.timeRemaining - 15, false, this.props.currentAlarmLog, this.props.token);
}
if (this.props.time.timeRemaining > 15) {
this.props.decreaseTime(this.props.time.timeRemaining);
Expand Down Expand Up @@ -72,7 +67,7 @@ class Timer extends Component {

componentWillUnmount() {
clearInterval(this.interval);
}
};

render() {
const { time, timeRemaining } = this.props.time;
Expand All @@ -81,27 +76,79 @@ class Timer extends Component {
percent={(1 - timeRemaining / time) * 100}
radius={127.5}
borderWidth={8}
color="#999b9e"
shadowColor={timeRemaining < 30 ? "#FF0000" : "#60a781"}
bgColor="#ffffff"
color={theme.colors.lightGrey}
shadowColor={timeRemaining < 30 ? theme.colors.red : theme.colors.green}
bgColor={theme.colors.white}
>
<SetTimeButton changeTimeHandler={this.incrementTimer}>+15</SetTimeButton>
<Text style={{ fontSize: 72, fontWeight: "bold", color: "#67686B" }}>
{this.convertSecondsToMinutes(timeRemaining)}:{this.convertSeconds(timeRemaining)}
</Text>
<SetTimeButton changeTimeHandler={this.decrementTimer}>-15</SetTimeButton>

<SetTimeButton changeTimeHandler={this.incrementTimer}>+ 15</SetTimeButton>

<View style={styles.timerContainer}>
<View style={styles.timerTextContainer}>
<View style={styles.minutes}>
<Text variant="numeral" style={styles.numeral}>{this.convertSecondsToMinutes(timeRemaining)}</Text>
<Text variant="label" style={styles.text}>minutes</Text>
</View>
<View style={styles.separator}>
<Text variant="numeral" style={styles.numeral}>:</Text>
<Text variant="label" style={styles.text}> </Text>
</View>
<View style={styles.seconds}>
<Text variant="numeral" style={styles.numeral}>{this.convertSeconds(timeRemaining)}</Text>
<Text variant="label" style={styles.text}>seconds</Text>
</View>
</View>
</View>

<SetTimeButton changeTimeHandler={this.decrementTimer}>- 15</SetTimeButton>

</ProgressCircle>
)
);
}
};

function mapStateToProps(state) {
const styles = StyleSheet.create({
timerContainer: {
flex: 0,
width: "90%"
},
timerTextContainer: {
flex: 0,
alignSelf: "stretch",
flexDirection: "row",
justifyContent: "space-between"
},
numeral: {
marginVertical: -18
},
text: {
marginTop: -(theme.layout.padding)
},
minutes: {
flex: 2
},
separator: {
flex: 0,
paddingHorizontal: theme.layout.padding
},
seconds: {
flex: 3
}
});

const mapStateToProps = (state) => {
return {
time: state.timer,
token: state.auth.token,
currentAlarmLog: state.metricAlarm.currentAlarmLog
}
}
};

export default connect(mapStateToProps, { increaseTime, decreaseTime, countdown, clearTime, resetTime, updateAlarmLog })(Timer);
export default connect(mapStateToProps, {
increaseTime,
decreaseTime,
countdown,
clearTime,
resetTime,
updateAlarmLog
})(Timer);
Loading