diff --git a/App.tsx b/App.tsx index 0329d0c..dc01a8e 100644 --- a/App.tsx +++ b/App.tsx @@ -1,11 +1,11 @@ -import { StatusBar } from 'expo-status-bar'; -import { StyleSheet, Text, View } from 'react-native'; +import React from 'react'; +import { StyleSheet, View } from 'react-native'; +import StopWatch from './src/StopWatch'; export default function App() { return ( - Open up App.tsx to start working on your app! - + ); } diff --git a/README.md b/README.md index 6b8b50e..08de74e 100644 --- a/README.md +++ b/README.md @@ -1,84 +1,24 @@ -# Technical Instructions -1. Fork this repo to your local Github account. -2. Create a new branch to complete all your work in. -3. Test your work using the provided tests -4. Create a Pull Request against the Shopify Main branch when you're done and all tests are passing +# Tom Miller's Stopwatch -# Project Overview -The goal of this project is to implement a stopwatch application using React Native and TypeScript. The stopwatch should have the following functionality: +## Features -- Start the stopwatch to begin counting time. -- Stop the stopwatch to pause the timer. -- Displays Laps when a button is pressed. -- Reset the stopwatch to zero. +My stopwatch app has the following features: +- Start button to start/resume the timer and a stop button to pause it. +- Reset button to reset the times and laps to 0. +- Lap button to record the laps easily along with minimum and maximum laps colored in red and green respectively to identify your slowest and fastest times easily. -You will be provided with a basic project structure that includes the necessary files and dependencies. Your task is to write the code to implement the stopwatch functionality and ensure that it works correctly. -## Project Setup -To get started with the project, follow these steps: + -1. Clone the project repository to your local development environment. -2. Install the required dependencies by running npm install in the project directory. -3. Familiarize yourself with the project structure. The main files you will be working with are: - - /App.tsx: The main component that renders the stopwatch and handles its functionality. - - src/Stopwatch.tsx: A separate component that represents the stopwatch display. - - src/StopwatchButton.tsx: A separate component that represents the start, stop, and reset buttons. -4. Review the existing code in the above files to understand the initial structure and component hierarchy. +## Tests -## Project Goals -Your specific goals for this project are as follows: +I added a few extra tests along with the original ones, such as a test to see that the maximum and minimum laps are colored correctly +and a test to ensure you can't add laps while paused. -1. Implement the stopwatch functionality: - - The stopwatch should start counting when the user clicks the start button. - - The stopwatch should stop counting when the user clicks the stop button. - - The stopwatch should reset to zero when the user clicks the reset button. - - The stopwatch should record and display laps when user clicks the lap button. +## Design Choices -2. Ensure code quality: - - Write clean, well-structured, and maintainable code. - - Follow best practices and adhere to the React and TypeScript coding conventions. - - Pay attention to code readability, modularity, and performance. - -3. Test your code: - - Run the application and test the stopwatch functionality to ensure it works correctly. - - Verify that the stopwatch starts, stops, resets, and records laps as expected. - -4. Code documentation: - - Document your code by adding comments and explanatory notes where necessary. - - Provide clear explanations of the implemented functionality and any important details. - -5. Version control: - - Use Git for version control. Commit your changes regularly and push them to a branch in your forked repository. - - 6. Create a Pull Request: - - Once you have completed the project goals, create a pull request to merge your changes into the main repository. - - Provide a clear description of the changes made and any relevant information for the code review. - -## Getting Started -To start working on the project, follow these steps: - -1. Clone the repository to your local development environment. - -2. Install the required dependencies by running npm install in the project directory. - -3. Open the project in your preferred code editor. - -4. Review the existing code in the src directory to understand the initial structure and component hierarchy. - -5. Implement the stopwatch functionality by modifying the necessary components (App.tsx, Stopwatch.tsx, StopwatchButton.tsx). - -6. Run the application using npm start and test the stopwatch functionality. - -7. Commit your changes regularly and push them to a branch in your forked repository. - -8. Once you have completed the project goals, create a pull request to merge your changes into the main repository. - -## Resources -Here are some resources that may be helpful during your work on this project: - -- [TypeScript Documentation](https://www.typescriptlang.org/docs/) - Official documentation for TypeScript, offering guidance on TypeScript features and usage. - -- [React Testing Library](https://testing-library.com/docs/react-testing-library/intro/) - Explore React Testing Library, a popular testing library for React applications. +- I created a useStopWatch hook to help separate all the logic of the stopwatch and keep all components clean and simple. +- I used Date objects instead of setInterval due to it being less accurate, especially for something where every second is important like a stopwatch. diff --git a/src/StopWatch.tsx b/src/StopWatch.tsx index 5c7eb74..4e7560f 100644 --- a/src/StopWatch.tsx +++ b/src/StopWatch.tsx @@ -1,8 +1,118 @@ -import { View } from 'react-native'; +import React from 'react'; +import { ScrollView, StyleSheet, Text, View } from 'react-native'; +import StopwatchButton from './StopWatchButton'; +import { useStopWatch } from './hooks/useStopWatch'; -export default function StopWatch() { +function formatNumber(num: number) { + return String(num).padStart(2, '0'); +} + +const formatTime = (milliseconds: number) => { + const hours = formatNumber(Math.floor(milliseconds / 3600000)); + const minutes = formatNumber(Math.floor((milliseconds % 3600000) / 60000)); + const seconds = formatNumber(Math.floor((milliseconds % 60000) / 1000)); + const centiseconds = formatNumber(Math.floor((milliseconds % 1000) / 10)); + + return `${hours}:${minutes}:${seconds}.${centiseconds}`; +}; + +export const lapColors = { + default: 'black', + minLap: 'red', + maxLap: '#5ab068' +}; + +export default function Stopwatch() { + + const stopwatch = useStopWatch(); return ( - + + + + {formatTime(stopwatch.milliseconds)} + + + + + {stopwatch.laps.slice().reverse().map((lap, index) => { + let lapColor = lapColors.default; + + if (stopwatch.laps.length >= 3) { + if (lap === stopwatch.minLapTime) { + lapColor = lapColors.minLap; + } + else if (lap === stopwatch.maxLapTime) { + lapColor = lapColors.maxLap; + } + } + + return ( + + + + Lap {stopwatch.laps.length - index} + + + {formatTime(lap)} + + + + + ); + })} + + ); -} \ No newline at end of file +} + +const styles = StyleSheet.create({ + container: { + alignItems: 'center', + justifyContent: 'center', + }, + contentContainer: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + }, + lapContentContainer: { + flexDirection: 'row', + justifyContent: 'space-between', + width:'75%', + }, + time: { + fontSize: 56, + fontWeight: '500', + marginBottom: 20, + minWidth:320, + }, + lapScrollView: { + maxHeight: 210, + width: '100%', + marginTop:'10%', + }, + lapScrollViewContent: { + alignItems: 'center', + }, + lap: { + fontSize: 18, + marginTop: 12, + }, + divider: { + borderBottomColor: 'lightgray', + borderBottomWidth: 1, + width: '75%', + marginTop:6, + } +}); diff --git a/src/StopWatchButton.tsx b/src/StopWatchButton.tsx index 8768555..d6a9a85 100644 --- a/src/StopWatchButton.tsx +++ b/src/StopWatchButton.tsx @@ -1,8 +1,22 @@ -import { View } from 'react-native'; -export default function StopWatchButton() { +import React from 'react'; +import { Button, View } from 'react-native'; + +export default function StopwatchButton({ onResume, onReset, onLap, onPause, isPaused }: { + onReset: () => void; + onLap: () => void; + onPause: () => void; + onResume: () => void; + isPaused: boolean; +}) { + return ( - + +