diff --git a/App.tsx b/App.tsx index 0329d0c..fbe36a9 100644 --- a/App.tsx +++ b/App.tsx @@ -1,20 +1,21 @@ -import { StatusBar } from 'expo-status-bar'; -import { StyleSheet, Text, View } from 'react-native'; +import {SafeAreaView, StyleSheet} from 'react-native'; +import StopWatch from "./src/StopWatch"; +import React from "react"; export default function App() { - return ( - - Open up App.tsx to start working on your app! - - - ); + return ( + + + + ) } + const styles = StyleSheet.create({ - container: { - flex: 1, - backgroundColor: '#fff', - alignItems: 'center', - justifyContent: 'center', - }, -}); + container: { + flex: 1, + flexDirection: 'column', + alignItems: 'center', + backgroundColor: 'black' + } +}) \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index ea36168..a360b56 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9208,9 +9208,9 @@ } }, "node_modules/expo": { - "version": "49.0.21", - "resolved": "https://registry.npmjs.org/expo/-/expo-49.0.21.tgz", - "integrity": "sha512-JpHL6V0yt8/fzsmkAdPdtsah+lU6Si4ac7MDklLYvzEil7HAFEsN/pf06wQ21ax4C+BL27hI6JJoD34tzXUCJA==", + "version": "49.0.22", + "resolved": "https://registry.npmjs.org/expo/-/expo-49.0.22.tgz", + "integrity": "sha512-1hhcphaKN74gDqEmGzU4sqxnusLi/i8SsWZ04rRn7b6zdyEchyudVLN3SOzeIUgfGmn7AcXm78JAQ7+e0WqSyw==", "dependencies": { "@babel/runtime": "^7.20.0", "@expo/cli": "0.10.16", @@ -9225,7 +9225,7 @@ "expo-font": "~11.4.0", "expo-keep-awake": "~12.3.0", "expo-modules-autolinking": "1.5.1", - "expo-modules-core": "1.5.12", + "expo-modules-core": "1.5.13", "fbemitter": "^3.0.0", "invariant": "^2.2.4", "md5-file": "^3.2.3", @@ -9415,9 +9415,9 @@ } }, "node_modules/expo-modules-core": { - "version": "1.5.12", - "resolved": "https://registry.npmjs.org/expo-modules-core/-/expo-modules-core-1.5.12.tgz", - "integrity": "sha512-mY4wTDU458dhwk7IVxLNkePlYXjs9BTgk4NQHBUXf0LapXsvr+i711qPZaFNO4egf5qq6fQV+Yfd/KUguHstnQ==", + "version": "1.5.13", + "resolved": "https://registry.npmjs.org/expo-modules-core/-/expo-modules-core-1.5.13.tgz", + "integrity": "sha512-cKRsiHKwpDPRkBgMW3XdUWmEUDzihEPWXAyeo629BXpJ6uX6a66Zbz63SEXhlgsbLq8FB77gvYku3ceBqb+hHg==", "dependencies": { "compare-versions": "^3.4.0", "invariant": "^2.2.4" diff --git a/package.json b/package.json index bf0f5a3..ac35609 100644 --- a/package.json +++ b/package.json @@ -12,10 +12,10 @@ "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" + "react": "18.2.0", + "react-native": "0.72.6" }, "devDependencies": { "@babel/core": "^7.20.0", diff --git a/src/StopWatch.tsx b/src/StopWatch.tsx index 5c7eb74..75aad88 100644 --- a/src/StopWatch.tsx +++ b/src/StopWatch.tsx @@ -1,8 +1,112 @@ -import { View } from 'react-native'; +import {StyleSheet, Text, View} from 'react-native'; +import React, {useEffect, useState} from "react"; +import LapList, {LapModel} from "./components/LapList"; +import StopWatchButton from "./StopWatchButton"; +import {formatTime} from "./common/TimeFormatter"; export default function StopWatch() { - return ( - - - ); -} \ No newline at end of file + + const [elapsedTime, setElapsedTime] = useState(0) + const [isRunning, setIsRunning] = useState(false) + const [laps, setLaps] = useState([]) + const [lastLapTime, setLastLapTime] = useState(0) + + const onLapClicked = () => { + if (isRunning) { + // Calculate the lap time + const lapTime = elapsedTime - lastLapTime; + setLaps((prevLaps) => [...prevLaps, lapTime]); + setLastLapTime(elapsedTime); + } + } + + const onResetClicked = () => { + setIsRunning(false) + setLaps([]) + setLastLapTime(0) + setElapsedTime(0) + + } + + const onStopClicked = () => { + setIsRunning(false) + } + + const onStartClicked = () => { + setIsRunning(true) + } + + useEffect(() => { + let intervalId: number; + + if (isRunning) { + intervalId = setInterval(() => { + setElapsedTime((prevElapsedTime) => prevElapsedTime + 100); + }, 100); + } + + return () => { + if (intervalId) { + clearInterval(intervalId); + } + }; + }, [isRunning]); + + return ( + <> + + {formatTime(elapsedTime)} + + + + + + + + + + + {laps.length > 0 && ({ + title: `Lap ${index + 1}`, + time: lap, + })) + }/>} + + + + ) +} + +const styles = StyleSheet.create({ + displayTIme: { + flex: 1, + alignItems: 'flex-end', + flexDirection: 'row', + paddingHorizontal: 10, + }, + + buttons: { + flex: 1, + flexDirection: 'row', + gap: 10, + alignItems: 'flex-end', + paddingHorizontal: 10, + }, + + lapList: { + flex: 2, + width: '100%', + paddingHorizontal: 16, + marginTop: 16 + }, + + time: { + fontSize: 70, + fontWeight: 'normal', + width: "100%", + textAlign: 'center', + color: 'white' + + } +}) \ No newline at end of file diff --git a/src/StopWatchButton.tsx b/src/StopWatchButton.tsx index 8768555..06403a2 100644 --- a/src/StopWatchButton.tsx +++ b/src/StopWatchButton.tsx @@ -1,8 +1,30 @@ -import { View } from 'react-native'; - -export default function StopWatchButton() { - return ( - - - ); -} \ No newline at end of file +import {Button, StyleSheet, View} from 'react-native'; + +interface StopWatchButtonProps { + label: string + onPress: () => void + +} + +export default function StopWatchButton({label, onPress}: StopWatchButtonProps) { + return ( + +