diff --git a/App.tsx b/App.tsx index 0329d0c..f8a0251 100644 --- a/App.tsx +++ b/App.tsx @@ -1,11 +1,15 @@ import { StatusBar } from 'expo-status-bar'; -import { StyleSheet, Text, View } from 'react-native'; +import { StyleSheet, Text, View, Dimensions } from 'react-native'; +import StopWatch from './src/StopWatch'; + +const screenHeight = Dimensions.get('window').height; +const screenWidth = Dimensions.get('window').width; + export default function App() { return ( - Open up App.tsx to start working on your app! - + ); } @@ -13,7 +17,7 @@ export default function App() { const styles = StyleSheet.create({ container: { flex: 1, - backgroundColor: '#fff', + backgroundColor: '#00B09F', alignItems: 'center', justifyContent: 'center', }, diff --git a/assets/fonts/CuteFont-Regular.ttf b/assets/fonts/CuteFont-Regular.ttf new file mode 100644 index 0000000..d07b849 Binary files /dev/null and b/assets/fonts/CuteFont-Regular.ttf differ diff --git a/assets/fonts/SingleDay-Regular.ttf b/assets/fonts/SingleDay-Regular.ttf new file mode 100644 index 0000000..c70da6b Binary files /dev/null and b/assets/fonts/SingleDay-Regular.ttf differ diff --git a/package-lock.json b/package-lock.json index ea36168..2ef206c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,8 +12,10 @@ "expo-status-bar": "~1.6.0", "jest": "^29.2.1", "jest-expo": "~49.0.0", + "link": "^2.1.0", "react": "18.2.0", - "react-native": "0.72.6" + "react-native": "^0.72.6", + "react-native-triangle": "^0.0.9" }, "devDependencies": { "@babel/core": "^7.20.0", @@ -8571,6 +8573,15 @@ "node": ">=8" } }, + "node_modules/create-react-class": { + "version": "15.7.0", + "resolved": "https://registry.npmjs.org/create-react-class/-/create-react-class-15.7.0.tgz", + "integrity": "sha512-QZv4sFWG9S5RUvkTYWbflxeZX+JG7Cz0Tn33rQBJ+WFQTqTfUTjMjiv9tnfXazjsO5r0KhPs+AqCjyrQX6h2ng==", + "dependencies": { + "loose-envify": "^1.3.1", + "object-assign": "^4.1.1" + } + }, "node_modules/cross-fetch": { "version": "3.1.8", "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.8.tgz", @@ -14231,6 +14242,17 @@ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" }, + "node_modules/link": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/link/-/link-2.1.0.tgz", + "integrity": "sha512-6jgX7ejPBOQaKsFY/9aFEg0HW0JyFuMGDoN+KQX1W94t+8Fi5xwlSlGouRMDqDlrE46drqu4PYduAG7tUwdF7Q==", + "bin": { + "link": "dist/cli.js" + }, + "funding": { + "url": "https://github.com/privatenumber/link?sponsor=1" + } + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -16527,6 +16549,15 @@ "react": "18.2.0" } }, + "node_modules/react-native-triangle": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/react-native-triangle/-/react-native-triangle-0.0.9.tgz", + "integrity": "sha512-XoZGXXoQ6UDqbRnvsMzFFREBEcta/kKkwCgKqw13cLJvIYQBhvASrn3Un/4aF/jPYLyWtdztiEHuMpx0tMxQrA==", + "dependencies": { + "create-react-class": "^15.6.0", + "prop-types": "^15.5.10" + } + }, "node_modules/react-native/node_modules/promise": { "version": "8.3.0", "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz", diff --git a/package.json b/package.json index bf0f5a3..de725d0 100644 --- a/package.json +++ b/package.json @@ -12,10 +12,12 @@ "dependencies": { "expo": "~49.0.15", "expo-status-bar": "~1.6.0", - "react": "18.2.0", - "react-native": "0.72.6", + "jest": "^29.2.1", "jest-expo": "~49.0.0", - "jest": "^29.2.1" + "link": "^2.1.0", + "react": "18.2.0", + "react-native": "^0.72.6", + "react-native-triangle": "^0.0.9" }, "devDependencies": { "@babel/core": "^7.20.0", diff --git a/react-native.config.js b/react-native.config.js new file mode 100644 index 0000000..f25a142 --- /dev/null +++ b/react-native.config.js @@ -0,0 +1,7 @@ +module.exports = { + project: { + ios: {}, + android: {}, + }, + assets: ['./assets/fonts'], +}; \ No newline at end of file diff --git a/src/StopWatch.tsx b/src/StopWatch.tsx index 5c7eb74..4828133 100644 --- a/src/StopWatch.tsx +++ b/src/StopWatch.tsx @@ -1,8 +1,216 @@ -import { View } from 'react-native'; +import React, { useEffect, useState, useRef } from 'react'; +import { View, Text, Button, ScrollView, StyleSheet, Dimensions } from 'react-native'; + +const screenHeight = Dimensions.get('window').height; +const screenWidth = Dimensions.get('window').width; export default function StopWatch() { + + // formatting for timer 00:00.00 + const formatTime = (milliseconds: number) => { + const minutes = Math.floor(milliseconds / (60 * 1000)); + const seconds = Math.floor((milliseconds % (60 * 1000)) / 1000); + const ms = Math.floor((milliseconds % 1000) / 10); + + return `${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}:${String(ms).padStart(2, '0')}`; + }; + + const [intervalId, setIntervalId] = useState(null); + const [timer, setTimer] = useState(0); + const [time, setTime] = useState(formatTime(timer)); + const [laps, setLaps] = useState([]); + const [buttonName, setButtonName] = useState('START'); + const timerRef = useRef(timer); + + // for styling + const scrollViewRef = useRef(); + const handleContentSizeChange = (contentWidth?: number, contentHeight?: number) => { + scrollViewRef.current?.scrollToEnd({ animated: true }); + }; + + + const startTimer = () => { + if (intervalId === null) { + const interval = setInterval(handleTimer, 10); + setIntervalId(interval); + setButtonName('LAP'); + } else { + setLaps(oldLapTimes => [...oldLapTimes, formatTime(timerRef.current)]); + } + }; + + const handleTimer = () => { + timerRef.current += 10; + setTime(formatTime(timerRef.current)); + }; + + const stopTimer = () => { + if (intervalId !== null) { + clearInterval(intervalId); + setIntervalId(null); + setButtonName('START'); + } + }; + + const resetTimer = () => { + stopTimer(); + timerRef.current = 0; + setTime(formatTime(timerRef.current)); + setLaps([]); + }; + return ( - - - ); -} \ No newline at end of file + + + {time} + + + +