Skip to content

Commit

Permalink
Finalized the Stopwatch
Browse files Browse the repository at this point in the history
* Improved the UI
* added comments
  • Loading branch information
WillAssaly committed Jan 29, 2024
1 parent 4ee4a7e commit 2a0df61
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 73 deletions.
43 changes: 35 additions & 8 deletions App.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,49 @@

import React, { useState, useEffect } from 'react';
import { View, StyleSheet } from 'react-native';
import { View, Text, StyleSheet } from 'react-native';
import Stopwatch from './src/StopWatch';
import StopwatchButton from './src/StopWatchButton';

export default function App() {
// State for tracking time, laps, and whether the stopwatch is running
const [time, setTime] = useState(0);
const [laps, setLaps] = useState<number[]>([]); // Explicitly typing laps
const [laps, setLaps] = useState<number[]>([]);
const [isRunning, setIsRunning] = useState(false);

// Effect for handling the stopwatch timing
useEffect(() => {
let interval: number | null = null; // Explicitly typing interval
let interval: number | null = null;

// Set an interval when the stopwatch is running
if (isRunning) {
interval = setInterval(() => {
setTime(time => time + 1);
}, 1000) as number; // Casting to number
setTime(time => time + 10); // Increment time every 10 milliseconds
}, 10);
} else if (interval) {
// Clear the interval if the stopwatch is stopped
clearInterval(interval as number);
}

// Cleanup function to clear the interval
return () => {
if (interval) {
clearInterval(interval as number);
}
};
}, [isRunning]);


return (
<View style={styles.container}>
<View style={styles.spacer} />

{/* Stopwatch header */}
<Text style={styles.header}>Stopwatch</Text>

{/* Stopwatch display */}
<Stopwatch time={time} laps={laps} />

<View style={styles.spacer} />

{/* Stopwatch control buttons */}
<StopwatchButton
isRunning={isRunning}
onStart={() => setIsRunning(true)}
Expand All @@ -40,8 +53,13 @@ export default function App() {
setTime(0);
setLaps([]);
}}
onLap={() => setLaps(currentLaps => [...currentLaps, time])}
onLap={() => {
// Add the current time to the laps array
setLaps(currentLaps => [...currentLaps, time]);
}}
/>

<View style={styles.spacer} />
</View>
);
}
Expand All @@ -51,7 +69,16 @@ const styles = StyleSheet.create({
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5F5F5',
padding: 20,
},
spacer: {
flex: 1,
},
header: {
fontSize: 24,
fontWeight: 'bold',
marginBottom: 20,
},
});

92 changes: 47 additions & 45 deletions src/StopWatch.tsx
Original file line number Diff line number Diff line change
@@ -1,61 +1,63 @@
// import React, { useState, useEffect } from 'react';
// import { View, Text } from 'react-native';

// export default function Stopwatch() {
// const [time, setTime] = useState(0);
// const [laps, setLaps] = useState([]);
// const [isRunning, setIsRunning] = useState(false);

// useEffect(() => {
// // Use ReturnType to infer the type returned by setInterval
// let interval: ReturnType<typeof setInterval>;
// if (isRunning) {
// interval = setInterval(() => {
// setTime(prevTime => prevTime + 1);
// }, 1000);
// }
// return () => clearInterval(interval as unknown as number);
// }, [isRunning]);



// return (
// <View>
// {/* Display time and laps */}
// <Text>{time}</Text>
// {/* Display laps */}
// {/* Display buttons */}
// </View>
// );
// }
// src/Stopwatch.tsx
import React from 'react';
import { View, Text } from 'react-native';
import { View, Text, ScrollView, StyleSheet } from 'react-native';

// Define a type for the props
// Defining the types for the component props
type StopwatchProps = {
time: number;
laps: number[];
time: number; // Current time of the stopwatch
laps: number[]; // Array to store lap times
};

const Stopwatch: React.FC<StopwatchProps> = ({ time, laps }) => {
// Function to format time in seconds to MM:SS format
// Function to format time into a readable format (MM:SS.ms)
const formatTime = (time: number): string => {
const minutes = Math.floor(time / 60);
const seconds = time % 60;
const miliseconds =
return `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}:${milliseconds.toString().padStart(3, '0')}`;
const minutes = Math.floor(time / 60000);
const seconds = Math.floor((time % 60000) / 1000);
const milliseconds = Math.floor((time % 1000) / 10);

return `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}.${milliseconds.toString().padStart(2, '0')}`;
};

return (
<View>
<Text>{formatTime(time)}</Text>
{laps.map((lap: number, index: number) => (
<Text key={index}>Lap {index + 1}: {formatTime(lap)}</Text>
))}
<View style={styles.container}>
{/* Displaying the formatted time */}
<Text style={styles.timerDisplay}>{formatTime(time)}</Text>

{/* ScrollView to list lap times */}
<ScrollView style={styles.lapList}>
{laps.map((lap, index) => (
<Text key={index} style={styles.lapTime}>
Lap {index + 1}: {formatTime(lap)}
</Text>
))}
</ScrollView>
</View>
);
};


const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
width: '100%',
padding: 20,
},
timerDisplay: {
fontSize: 48,
fontWeight: 'bold',
marginBottom: 30,
},
lapList: {
flex: 1,
width: '100%',
padding: 5,
},
lapTime: {
fontSize: 16,
color: '#333',
marginBottom: 5,
},
});

export default Stopwatch;

71 changes: 51 additions & 20 deletions src/StopWatchButton.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,7 @@
// import { View } from 'react-native';

// export default function StopWatchButton() {
// return (
// <View >
// </View>
// );
// }
// src/StopwatchButton.tsx
// src/StopwatchButton.tsx
import React from 'react';
import { View, Button } from 'react-native';
import { View, TouchableOpacity, Text, StyleSheet } from 'react-native';

// Define the types for the component props
type StopwatchButtonProps = {
isRunning: boolean;
onStart: () => void;
Expand All @@ -19,19 +10,59 @@ type StopwatchButtonProps = {
onLap: () => void;
};

// StopwatchButton component
const StopwatchButton: React.FC<StopwatchButtonProps> = ({ isRunning, onStart, onStop, onReset, onLap }) => {
return (
<View>
{isRunning ? (
<Button title="Stop" onPress={onStop} />
) : (
<Button title="Start" onPress={onStart} />
)}
<Button title="Lap" onPress={onLap} disabled={!isRunning} />
<Button title="Reset" onPress={onReset} />
<View style={styles.buttonContainer}>
{/* Start/Stop Button */}
<TouchableOpacity
style={[styles.button, { backgroundColor: isRunning ? '#F5AC76' : '#F57F76' }]}
onPress={isRunning ? onStop : onStart}
>
<Text style={styles.buttonText}>{isRunning ? "Stop" : "Start"}</Text>
</TouchableOpacity>

{/* Lap Button */}
<TouchableOpacity
style={[styles.button, { backgroundColor: '#F576A1' }]}
onPress={onLap}
disabled={!isRunning}
>
<Text style={styles.buttonText}>Lap</Text>
</TouchableOpacity>

{/* Reset Button */}
<TouchableOpacity
style={[styles.button, { backgroundColor: '#F59576' }]}
onPress={onReset}
>
<Text style={styles.buttonText}>Reset</Text>
</TouchableOpacity>
</View>
);
};

export default StopwatchButton;
// StyleSheet for the component
const styles = StyleSheet.create({
buttonContainer: {
flexDirection: 'row',
justifyContent: 'space-around',
width: '100%',
marginTop: 20,
},
button: {
width: 70,
height: 70,
borderRadius: 35,
justifyContent: 'center',
alignItems: 'center',
margin: 5,
},
buttonText: {
color: 'white',
fontSize: 16,
fontWeight: 'bold',
},
});

export default StopwatchButton;

0 comments on commit 2a0df61

Please sign in to comment.