Added placeholder task info and made some UI/UX improvements

This commit is contained in:
Chris Sanden
2026-04-22 20:41:19 +02:00
parent b7d62637e6
commit 1879c7c1f7

View File

@@ -19,32 +19,55 @@ const colors = {
const timers = [...Array(13).keys()].map((i) => (i === 0 ? 1 : i * 5));
const ITEM_SIZE = width * 0.38;
const ITEM_SPACING = (width - ITEM_SIZE) / 2;
const TIMER_UNIT_IN_SECONDS = 1; // Set to 60 for timer value to represent minutes
const placeholderTask = {
name: 'Read chapter 4',
description: 'Focus on the summary questions and write down anything unclear.',
};
/*
Har bare skrevet timeren som en egen tab til å begynne med.
Planen er at når bruker starter en task så vil de få opp denne timeren
som viser TaskName og Description der tallene står nå
Kanskje en animert figur hvis vi får tid
*/
function formatTime(totalSeconds: number) {
const minutes = Math.floor(totalSeconds / 60);
const seconds = totalSeconds % 60;
return `${minutes.toString().padStart(2, '0')}:${
seconds.toString().padStart(2, '0')}`;
}
export default function App() {
const [containerHeight, setContainerHeight] = React.useState(0)
const scrollX = React.useRef(new Animated.Value(0)).current;
const [duration, setDuration] = React.useState(timers[0])
const [isRunning, setIsRunning] = React.useState(false)
const [timeRemaining, setTimeRemaining] = React.useState(0)
const [selectedIndex, setSelectedIndex] = React.useState(0)
const [showCountdownText, setShowCountdownText] = React.useState(false)
const scrollX = React.useRef(new Animated.Value(0)).current;
const timerAnimation = React.useRef(new Animated.Value(0)).current
const buttonAnimation = React.useRef(new Animated.Value(0)).current
const taskDetailsAnimation = React.useRef(new Animated.Value(0)).current
const countdownAnimation = React.useRef(new Animated.Value(0)).current
const animation = React.useCallback(() => {
if (isRunning) {
if (isRunning || containerHeight === 0) {
return;
}
setIsRunning(true);
setShowCountdownText(true);
taskDetailsAnimation.setValue(0);
countdownAnimation.setValue(0);
const totalSeconds = duration * TIMER_UNIT_IN_SECONDS;
setTimeRemaining(totalSeconds);
const countdown = setInterval(() => {
setTimeRemaining((currentTime) => {
if (currentTime <= 1) {
clearInterval(countdown)
return 0;
}
return currentTime -1;
});
}, 1000);
Animated.sequence([
Animated.parallel([
@@ -58,6 +81,11 @@ export default function App() {
duration: 500,
useNativeDriver: true
}),
Animated.timing(countdownAnimation, {
toValue: 1,
duration: 300,
useNativeDriver: true
}),
]),
Animated.timing(timerAnimation, {
toValue: 0,
@@ -66,15 +94,22 @@ export default function App() {
}),
Animated.timing(timerAnimation, {
toValue: containerHeight,
duration: duration * 1000,
duration: totalSeconds * 1000,
useNativeDriver: true
}),
]) .start(({ finished }) => {
})
]).start(({ finished }) => {
if (!finished) {
setIsRunning(false);
return;
}
Animated.timing(countdownAnimation, {
toValue: 0,
duration: 200,
useNativeDriver: true
}).start(() => {
setShowCountdownText(false);
Animated.parallel([
Animated.timing(buttonAnimation, {
toValue: 0,
@@ -90,13 +125,14 @@ export default function App() {
setIsRunning(false);
})
})
}, [buttonAnimation, duration, isRunning, taskDetailsAnimation, timerAnimation])
})
}, [countdownAnimation, buttonAnimation, containerHeight, duration, isRunning, taskDetailsAnimation, timerAnimation])
React.useEffect(() => {
if (containerHeight > 0) {
if (containerHeight > 0 && !isRunning) {
timerAnimation.setValue(containerHeight);
}
})
}, [containerHeight, isRunning, timerAnimation])
const opacity = buttonAnimation.interpolate({
inputRange: [0, 1],
@@ -127,7 +163,7 @@ return (
<StatusBar hidden />
<Animated.View
style={[StyleSheet.absoluteFillObject, {
height,
height: containerHeight,
width,
backgroundColor: colors.red,
transform: [{
@@ -176,8 +212,10 @@ return (
showsHorizontalScrollIndicator={false}
onMomentumScrollEnd={ev => {
const index = Math.round(ev.nativeEvent.contentOffset.x / ITEM_SIZE)
setSelectedIndex(index);
setDuration(timers[index]);
}}
snapToInterval={ITEM_SIZE}
decelerationRate={"fast"}
style={{flexGrow: 0}}
@@ -185,12 +223,15 @@ return (
paddingHorizontal: ITEM_SPACING
}}
renderItem={({item, index}) => {
const isSelected = index === selectedIndex;
const timerText = showCountdownText && isSelected ? formatTime(timeRemaining) : item;
const inputRange = [
(index - 1) * ITEM_SIZE,
index * ITEM_SIZE,
(index + 1) * ITEM_SIZE,
]
const normalOpacity = scrollX.interpolate({
inputRange,
outputRange: [.4, 1, .4]
@@ -202,21 +243,21 @@ return (
})
const opacity = Animated.add(
Animated.multiply(normalOpacity, inactiveTimerNumberOpacity),
Animated.multiply(selectedOpacity, buttonAnimation)
Animated.multiply(selectedOpacity, countdownAnimation)
)
const scale = scrollX.interpolate({
inputRange,
outputRange: [.7, 1, .7]
})
return <View style={{width: ITEM_SIZE, justifyContent: 'center', alignItems: 'center'}}>
<Animated.Text style={[styles.text, {
<Animated.Text style={[showCountdownText && isSelected ? styles.countdownText : styles.text, {
opacity,
transform: [{
scale
}]
}]}>
{item}
{timerText}
</Animated.Text>
</View>
}
@@ -251,6 +292,7 @@ const styles = StyleSheet.create({
height: 80,
borderRadius: 80,
backgroundColor: colors.red,
textAlign: 'center',
},
text: {
fontSize: ITEM_SIZE * 0.8,
@@ -277,5 +319,11 @@ const styles = StyleSheet.create({
lineHeight: 22,
marginTop: 10,
textAlign: 'center',
},
countdownText: {
fontSize: ITEM_SIZE * 0.32,
fontFamily: 'Menlo',
color: colors.text,
fontWeight: '900',
}
});