diff --git a/android/app/build.gradle b/android/app/build.gradle
index 1e5a0de..5da5bd0 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -78,9 +78,9 @@ import com.android.build.OutputFile
*/
project.ext.vectoricons = [
- iconFontNames: [ 'FontAwesome.ttf' ] // Name of the font files you want to copy
+ iconFontNames: ['FontAwesome.ttf']
]
-
+
apply from: "../../node_modules/react-native-vector-icons/fonts.gradle"
project.ext.react = [
diff --git a/app/components/SettingsCell.js b/app/components/SettingsCell.js
index 071e554..dad73fd 100644
--- a/app/components/SettingsCell.js
+++ b/app/components/SettingsCell.js
@@ -10,6 +10,7 @@ const SettingsCell = ({
title,
onCellPress,
onSwitchValueChange,
+ switchValue,
titleNumLines,
iconName,
}) => {
@@ -29,7 +30,7 @@ const SettingsCell = ({
{onCellPress == null ? (
-
+
) : (
)}
diff --git a/app/components/TimerButton.js b/app/components/TimerButton.js
new file mode 100644
index 0000000..80ed19e
--- /dev/null
+++ b/app/components/TimerButton.js
@@ -0,0 +1,95 @@
+import React, { useState, useEffect } from 'react'
+import { View, Text, StyleSheet } from 'react-native'
+import config, { colors, vectorIcons } from '../config'
+import { AnimatedCircularProgress } from 'react-native-circular-progress'
+import { useDispatch } from 'react-redux'
+import { addWashTime } from '../state/WashTimeHistory'
+
+const TimerButton = ({ timerStart, image, text }) => {
+ const dispatch = useDispatch()
+ const timerDefault = config.timerDefault
+ const [timer, setCounter] = useState(timerDefault)
+ const [bottomText, setBottomText] = useState(text)
+ const [timerStartNew, setTimerStart] = useState(timerStart)
+
+ const timerCounter = () => setCounter(timer - 1)
+
+ useEffect(() => {
+ if (timerStartNew) {
+ if (timer <= 0) {
+ setBottomText('Well Done')
+ setTimerStart(false)
+ dispatch(addWashTime({ datetime: Date.now() }))
+ return
+ }
+ const id = setInterval(timerCounter, 1000)
+ return () => {
+ clearInterval(id)
+ }
+ }
+ }, [timer])
+
+ const fill = timerStart ? 100 - (timer * 100) / timerDefault : 0
+
+ const { FontAwesome } = vectorIcons
+ const { white, green } = colors
+ const {
+ container,
+ textSeconds,
+ textSecondName,
+ viewStyle,
+ progressStyle,
+ } = styles
+
+ return (
+
+
+ {() => (
+
+ {timerStartNew ? (
+ {timer}
+ ) : (
+
+ )}
+
+ {bottomText}
+
+ )}
+
+
+ )
+}
+
+export default TimerButton
+
+const { white, circleBackground } = colors
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+ textSeconds: { fontSize: 30, color: white },
+ textSecondName: { color: white, marginTop: 25, fontSize: 18 },
+ viewStyle: { alignItems: 'center', justifyContent: 'center' },
+ progressStyle: {
+ backgroundColor: circleBackground,
+ borderRadius: 100,
+ },
+ circularView: {
+ height: 190,
+ width: 190,
+ borderRadius: 100,
+ backgroundColor: circleBackground,
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+})
diff --git a/app/components/index.js b/app/components/index.js
index a3b1110..e570c22 100644
--- a/app/components/index.js
+++ b/app/components/index.js
@@ -1,5 +1,6 @@
-import InstructionCell from './InstructionCell'
+import TimerButton from './TimerButton'
import MedicBleepLogo from './MedicBleepLogo'
import SettingsCell from './SettingsCell'
+import InstructionCell from './InstructionCell'
-export { MedicBleepLogo, SettingsCell, InstructionCell }
+export { MedicBleepLogo, SettingsCell, TimerButton, InstructionCell }
diff --git a/app/config/index.js b/app/config/index.js
index 232c42d..b19130e 100644
--- a/app/config/index.js
+++ b/app/config/index.js
@@ -4,9 +4,11 @@ import production from './production'
import colors from './colors'
import { store, persistor } from './store'
import routes from './routes'
+import vectorIcons from './vectorIcons'
let config = {
colors,
+ timerDefault: 20,
}
if (__DEV__) {
@@ -23,5 +25,5 @@ if (__DEV__) {
}
}
-export { colors, store, persistor, routes }
+export { colors, routes, store, vectorIcons, persistor }
export default config
diff --git a/app/config/vectorIcons.js b/app/config/vectorIcons.js
new file mode 100644
index 0000000..1501bce
--- /dev/null
+++ b/app/config/vectorIcons.js
@@ -0,0 +1,7 @@
+import FontAwesome from 'react-native-vector-icons/FontAwesome'
+
+const vectorIcons = {
+ FontAwesome,
+}
+
+export default vectorIcons
diff --git a/app/navigations/MainNavigation.js b/app/navigations/MainNavigation.js
index 4ec0817..cfbd287 100644
--- a/app/navigations/MainNavigation.js
+++ b/app/navigations/MainNavigation.js
@@ -1,6 +1,6 @@
import { createStackNavigator } from '@react-navigation/stack'
import React from 'react'
-import { Settings, TimerScreen, HomeScreen } from '../screens'
+import { HomeScreen, SettingsScreen, TimerScreen } from '../screens'
import { routes, colors } from '../config'
const { SETTINGS_SCREEN, TIMER_SCREEN, HOME_SCREEN } = routes
@@ -28,7 +28,7 @@ const MainNavigation = () => (
/>
{
+ const { FontAwesome } = vectorIcons
+ const { white } = colors
+ const { settingButtonStyle } = styles
+ navigation.setOptions({
+ headerRight: () => (
+
+ {}}>
+
+
+
+ ),
+ })
+
const dispatch = useDispatch()
const started = useSelector(selectShiftStarted)
const washTimes = useSelector(getWashTimes)
@@ -54,7 +71,7 @@ export const HomeScreen = ({ navigation }) => {
style={washButtonViewStyle}
onPress={washButtonClicked}
>
-
+
HISTORY
@@ -79,6 +96,7 @@ export default HomeScreen
const styles = StyleSheet.create({
mainViewStyle: {
flex: 1,
+ backgroundColor: colors.white,
},
washButtonBgViewStyle: {
marginTop: 25,
@@ -109,4 +127,5 @@ const styles = StyleSheet.create({
marginTop: 15,
color: colors.white,
},
+ settingButtonStyle: { marginRight: 15 },
})
diff --git a/app/screens/Settings.js b/app/screens/SettingsScreen.js
similarity index 55%
rename from app/screens/Settings.js
rename to app/screens/SettingsScreen.js
index 311ede5..ff11bb0 100644
--- a/app/screens/Settings.js
+++ b/app/screens/SettingsScreen.js
@@ -1,16 +1,28 @@
import React from 'react'
-import { View, StyleSheet, SafeAreaView } from 'react-native'
+import { View, StyleSheet, SafeAreaView, Linking } from 'react-native'
import MedicBleepLogo from '../components/MedicBleepLogo'
import { SettingsCell } from '../components'
import { colors } from '../config'
+import { storeHistory, shiftReminders } from '../state/Settings'
+import { useSelector, useDispatch } from 'react-redux'
+import { selectStoreHistory, selectShiftReminders } from 'app/state/Settings'
const { white } = colors
-const Settings = ({ started }) => {
- const storeHistoryValueChanged = (value) => {}
- const shiftReminderValueChanged = (value) => {}
- const aboutMbCellPressed = () => {}
- const followCellPressed = () => {}
+const medicBleepAboutUsUrl = 'https://www.medicbleep.com/about.html'
+const medicBleepFollowTwitterUrl = 'https://twitter.com/MedicBleep'
+
+const SettingsScreen = ({}) => {
+ const dispatch = useDispatch()
+ const isStoreHistory = useSelector(selectStoreHistory)
+ const isShiftRemindersAllow = useSelector(selectShiftReminders)
+
+ const storeHistoryValueChanged = (value) =>
+ isStoreHistory !== value ? dispatch(storeHistory(value)) : null
+ const shiftReminderValueChanged = (value) =>
+ isShiftRemindersAllow !== value ? dispatch(shiftReminders(value)) : null
+ const aboutMbCellPressed = () => Linking.openURL(medicBleepAboutUsUrl)
+ const followCellPressed = () => Linking.openURL(medicBleepFollowTwitterUrl)
const { container, contentWrapper } = styles
return (
@@ -20,6 +32,7 @@ const Settings = ({ started }) => {
title={'Store History'}
onCellPress={null}
onSwitchValueChange={storeHistoryValueChanged}
+ switchValue={isStoreHistory}
titleNumLines={1}
iconName={null}
/>
@@ -27,6 +40,7 @@ const Settings = ({ started }) => {
title={'Two Hour On Shift Reminders'}
onCellPress={null}
onSwitchValueChange={shiftReminderValueChanged}
+ switchValue={isShiftRemindersAllow}
titleNumLines={2}
iconName={null}
/>
@@ -50,7 +64,7 @@ const Settings = ({ started }) => {
)
}
-export default Settings
+export default SettingsScreen
const styles = StyleSheet.create({
container: { flex: 1, backgroundColor: white },
diff --git a/app/screens/TimerScreen.js b/app/screens/TimerScreen.js
index e3deaf5..1227af1 100644
--- a/app/screens/TimerScreen.js
+++ b/app/screens/TimerScreen.js
@@ -1,6 +1,7 @@
import React from 'react'
import { View, SafeAreaView, StyleSheet, FlatList } from 'react-native'
-import { InstructionCell } from '../components'
+import { InstructionCell, TimerButton } from '../components'
+import { colors } from '../config'
const TimerScreen = ({ navigation }) => {
const data = [
@@ -43,6 +44,7 @@ const TimerScreen = ({ navigation }) => {
return (
+
{
)
}
-
export default TimerScreen
+const { white } = colors
const styles = StyleSheet.create({
container: {
flex: 1,
+ backgroundColor: white,
},
flatListStyle: {
flex: 1,
diff --git a/app/screens/index.js b/app/screens/index.js
index b1e78a9..e179910 100644
--- a/app/screens/index.js
+++ b/app/screens/index.js
@@ -1,5 +1,5 @@
import TimerScreen from './TimerScreen'
import HomeScreen from './HomeScreen'
-import Settings from './Settings'
+import SettingsScreen from './SettingsScreen'
-export { HomeScreen, Settings, TimerScreen }
+export { HomeScreen, SettingsScreen, TimerScreen }
diff --git a/app/state/Settings.js b/app/state/Settings.js
new file mode 100644
index 0000000..80f5e97
--- /dev/null
+++ b/app/state/Settings.js
@@ -0,0 +1,37 @@
+const initialState = {
+ isToStoreHistory: false,
+ isToAllowShiftReminders: false,
+}
+
+// Types
+export const STORE_HISTORY = 'store_history'
+export const SHIFT_REMINDERS = 'shift_reminders'
+
+// Reducer
+export default (state = initialState, action = {}) => {
+ switch (action.type) {
+ case STORE_HISTORY:
+ return { ...state, isToStoreHistory: action.payload }
+ case SHIFT_REMINDERS:
+ return { ...state, isToAllowShiftReminders: action.payload }
+ default:
+ return state
+ }
+}
+
+// Action creators
+export const storeHistory = (isStoreHistory) => ({
+ type: STORE_HISTORY,
+ payload: isStoreHistory,
+})
+
+export const shiftReminders = (isShiftRemindersAllowed) => ({
+ type: SHIFT_REMINDERS,
+ payload: isShiftRemindersAllowed,
+})
+
+// Selectors
+export const selectStoreHistory = (state) =>
+ state.settingsReducer.isToStoreHistory
+export const selectShiftReminders = (state) =>
+ state.settingsReducer.isToAllowShiftReminders
diff --git a/app/state/index.js b/app/state/index.js
index 6dee145..1f815a9 100644
--- a/app/state/index.js
+++ b/app/state/index.js
@@ -1,9 +1,11 @@
import { combineReducers } from 'redux'
import Shift from './Shift'
import WashTimeHistory from './WashTimeHistory'
+import Settings from './Settings'
const rootReducer = combineReducers({
shiftReducer: Shift,
washTimeHistory: WashTimeHistory,
+ settingsReducer: Settings,
})
export default rootReducer
diff --git a/ios/HandWashTimer.xcodeproj/project.pbxproj b/ios/HandWashTimer.xcodeproj/project.pbxproj
index 92d21cf..e5e1313 100644
--- a/ios/HandWashTimer.xcodeproj/project.pbxproj
+++ b/ios/HandWashTimer.xcodeproj/project.pbxproj
@@ -165,6 +165,7 @@
83CBBA001A601CBA00E9B192 /* Products */,
2D16E6871FA4F8E400B85C8A /* Frameworks */,
CC978C4B58B4BDE357267E06 /* Pods */,
+ C0E11174777C47A7812291F7 /* Resources */,
);
indentWidth = 2;
sourceTree = "";
@@ -197,6 +198,14 @@
path = Pods;
sourceTree = "";
};
+ C0E11174777C47A7812291F7 /* Resources */ = {
+ isa = "PBXGroup";
+ children = (
+ );
+ name = Resources;
+ sourceTree = "";
+ path = "";
+ };
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -552,6 +561,54 @@
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
+ CB3F8E685B769FA20E94370F /* [CP] Copy Pods Resources */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ "${PODS_ROOT}/Target Support Files/Pods-HandWashTimer/Pods-HandWashTimer-resources.sh",
+ "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/AntDesign.ttf",
+ "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Entypo.ttf",
+ "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/EvilIcons.ttf",
+ "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Feather.ttf",
+ "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome.ttf",
+ "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Brands.ttf",
+ "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Regular.ttf",
+ "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Solid.ttf",
+ "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Fontisto.ttf",
+ "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Foundation.ttf",
+ "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Ionicons.ttf",
+ "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/MaterialCommunityIcons.ttf",
+ "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/MaterialIcons.ttf",
+ "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Octicons.ttf",
+ "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/SimpleLineIcons.ttf",
+ "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Zocial.ttf",
+ );
+ name = "[CP] Copy Pods Resources";
+ outputPaths = (
+ "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AntDesign.ttf",
+ "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Entypo.ttf",
+ "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EvilIcons.ttf",
+ "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Feather.ttf",
+ "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome.ttf",
+ "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome5_Brands.ttf",
+ "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome5_Regular.ttf",
+ "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome5_Solid.ttf",
+ "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Fontisto.ttf",
+ "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Foundation.ttf",
+ "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Ionicons.ttf",
+ "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/MaterialCommunityIcons.ttf",
+ "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/MaterialIcons.ttf",
+ "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Octicons.ttf",
+ "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/SimpleLineIcons.ttf",
+ "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Zocial.ttf",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-HandWashTimer/Pods-HandWashTimer-resources.sh\"\n";
+ showEnvVarsInLog = 0;
+ };
DF228B8E9BFEB12E7C8E7828 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
diff --git a/ios/HandWashTimer/AppDelegate.m b/ios/HandWashTimer/AppDelegate.m
index 94b0575..866f806 100644
--- a/ios/HandWashTimer/AppDelegate.m
+++ b/ios/HandWashTimer/AppDelegate.m
@@ -3,6 +3,7 @@
#import
#import
#import
+#import
#if DEBUG
#import
@@ -55,4 +56,11 @@ - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
#endif
}
+- (BOOL)application:(UIApplication *)application
+ openURL:(NSURL *)url
+ options:(NSDictionary *)options
+{
+ return [RCTLinkingManager application:application openURL:url options:options];
+}
+
@end
diff --git a/ios/HandWashTimer/Info.plist b/ios/HandWashTimer/Info.plist
index 01f31f8..5fc3adb 100644
--- a/ios/HandWashTimer/Info.plist
+++ b/ios/HandWashTimer/Info.plist
@@ -38,7 +38,7 @@
NSLocationWhenInUseUsageDescription
-
+
UILaunchStoryboardName
LaunchScreen
UIRequiredDeviceCapabilities
@@ -57,5 +57,9 @@
UIViewControllerBasedStatusBarAppearance
+ UIAppFonts
+
+ FontAwesome.ttf
+
diff --git a/ios/Podfile b/ios/Podfile
index 4d12347..9fc90f0 100644
--- a/ios/Podfile
+++ b/ios/Podfile
@@ -78,6 +78,7 @@ target 'HandWashTimer' do
pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec'
pod 'RNVectorIcons', :path => '../node_modules/react-native-vector-icons'
+
target 'HandWashTimerTests' do
inherit! :complete
diff --git a/package.json b/package.json
index 61e5518..d0bcec1 100644
--- a/package.json
+++ b/package.json
@@ -19,10 +19,12 @@
"moment": "^2.24.0",
"react": "16.11.0",
"react-native": "0.62.2",
+ "react-native-circular-progress": "^1.3.6",
"react-native-gesture-handler": "^1.6.1",
"react-native-reanimated": "^1.8.0",
"react-native-safe-area-context": "^0.7.3",
"react-native-screens": "^2.7.0",
+ "react-native-svg": "^12.1.0",
"react-native-vector-icons": "^6.6.0",
"react-redux": "^7.2.0",
"reactotron-react-native": "^5.0.0",