feat: Add Todo List

Signed-off-by: SindreKjelsrud <sindre@kjelsrud.dev>
This commit is contained in:
Sid 2025-07-05 17:13:34 +02:00
parent 01cb1979aa
commit f212978588
Signed by: sidski
GPG key ID: D2BBDF3EDE6BA9A6
4 changed files with 189 additions and 10 deletions

View file

@ -5,6 +5,7 @@ export default function RootLayout() {
<Stack> <Stack>
<Stack.Screen name="index" options={{ headerShown: false }} /> <Stack.Screen name="index" options={{ headerShown: false }} />
<Stack.Screen name="nether-portal-calculator" options={{ headerShown: false }} /> <Stack.Screen name="nether-portal-calculator" options={{ headerShown: false }} />
<Stack.Screen name="todo" options={{ headerShown: false }} />
</Stack> </Stack>
); );
} }

View file

@ -53,6 +53,22 @@ export const styles = StyleSheet.create({
textShadowRadius: 3, textShadowRadius: 3,
fontFamily: "Minecraft", fontFamily: "Minecraft",
}, },
backButton: {
alignSelf: "flex-start",
marginTop: 0,
marginBottom: 20,
paddingVertical: 8,
paddingHorizontal: 15,
backgroundColor: "rgba(106, 90, 205, 0.7)",
borderRadius: 8,
marginLeft: 0,
},
backButtonText: {
color: "#fff",
fontSize: 16,
fontWeight: "bold",
fontFamily: "Minecraft",
},
// --- Nether Portal Calculator --- // --- Nether Portal Calculator ---
converterScreenRoot: { converterScreenRoot: {
@ -156,20 +172,81 @@ export const styles = StyleSheet.create({
fontWeight: "bold", fontWeight: "bold",
fontFamily: "Minecraft", fontFamily: "Minecraft",
}, },
backButton: {
alignSelf: "flex-start", // --- Todo List ---
marginTop: 0, todoInputContainer: {
flexDirection: "row",
width: "90%",
backgroundColor: "rgba(255,255,255,0.8)",
borderRadius: 10,
padding: 5,
marginBottom: 20, marginBottom: 20,
paddingVertical: 8, alignItems: "center",
paddingHorizontal: 15,
backgroundColor: "rgba(106, 90, 205, 0.7)",
borderRadius: 8,
marginLeft: 0,
}, },
backButtonText: { todoInputField: {
flex: 1,
paddingVertical: 10,
paddingHorizontal: 15,
fontSize: 16,
color: "#333",
fontFamily: "Minecraft",
},
addTodoButton: {
backgroundColor: "#4CAF50",
paddingVertical: 10,
paddingHorizontal: 20,
borderRadius: 8,
marginLeft: 10,
},
addTodoButtonText: {
color: "#fff", color: "#fff",
fontSize: 16, fontSize: 16,
fontWeight: "bold", fontWeight: "bold",
},
todoListContainer: {
width: "90%",
},
todoItem: {
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
backgroundColor: "rgba(255,255,255,0.9)",
borderRadius: 8,
paddingVertical: 12,
paddingHorizontal: 15,
marginBottom: 10,
shadowColor: "#000",
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.1,
shadowRadius: 3,
elevation: 3,
},
todoText: {
flex: 1,
fontSize: 18,
color: "#333",
},
removeTodoButton: {
backgroundColor: "#FF6347",
paddingVertical: 5,
paddingHorizontal: 10,
borderRadius: 5,
marginLeft: 15,
},
removeTodoButtonText: {
color: "#fff",
fontWeight: "bold",
fontSize: 16,
},
placeholderText: {
color: "#fff",
textAlign: "center",
marginTop: 20,
fontSize: 18,
fontStyle: "italic",
textShadowColor: "rgba(0, 0, 0, 0.75)",
textShadowOffset: { width: -1, height: 1 },
textShadowRadius: 5,
fontFamily: "Minecraft", fontFamily: "Minecraft",
}, },
}); });

101
app/todo.tsx Normal file
View file

@ -0,0 +1,101 @@
import { useRouter } from "expo-router";
import { useState } from "react";
import {
ImageBackground,
KeyboardAvoidingView,
Platform,
ScrollView,
Text,
TextInput,
TouchableOpacity,
View
} from "react-native";
import { SafeAreaView } from "react-native-safe-area-context";
import { styles } from "./styles";
const converterBgImage = require("../assets/images/todo.png");
export default function CoordinateConverter() {
const router = useRouter();
const [todos, setTodos] = useState<string[]>([]);
const [newTodo, setNewTodo] = useState<string>("");
const addTodo = () => {
if (newTodo.trim().length > 0) {
setTodos([...todos, newTodo.trim()]);
setNewTodo("");
}
};
const removeTodo = (index: number) => {
const updatedTodos = todos.filter((_, i) => i !== index);
setTodos(updatedTodos);
};
return (
<View style={styles.converterScreenRoot}>
<ImageBackground
source={converterBgImage}
style={styles.converterBackgroundImage}
resizeMode="cover"
>
<View style={styles.converterBackgroundOverlay} />
</ImageBackground>
<SafeAreaView style={styles.converterContentWrapper}>
<KeyboardAvoidingView
style={styles.converterContainer}
behavior={Platform.OS === "ios" ? "padding" : "height"}
>
<ScrollView contentContainerStyle={styles.converterScrollContent}>
{/* Custom Back Button */}
<TouchableOpacity
onPress={() => router.back()}
style={styles.backButton}
>
<Text style={styles.backButtonText}> Go Back</Text>
</TouchableOpacity>
<Text style={styles.converterTitle}>Todo List</Text>
{/* Todo Input Section */}
<View style={styles.todoInputContainer}>
<TextInput
style={styles.todoInputField}
placeholder="Add a new todo..."
placeholderTextColor="#666"
value={newTodo}
onChangeText={setNewTodo}
onSubmitEditing={addTodo}
/>
<TouchableOpacity onPress={addTodo} style={styles.addTodoButton}>
<Text style={styles.addTodoButtonText}>Add</Text>
</TouchableOpacity>
</View>
{/* Todo List Display */}
<View style={styles.todoListContainer}>
{todos.length === 0 ? (
<Text style={styles.placeholderText}>
Your todo list is empty. Add some tasks!
</Text>
) : (
todos.map((todo, index) => (
<View key={index} style={styles.todoItem}>
<Text style={styles.todoText}>{todo}</Text>
<TouchableOpacity
onPress={() => removeTodo(index)}
style={styles.removeTodoButton}
>
<Text style={styles.removeTodoButtonText}>X</Text>
</TouchableOpacity>
</View>
))
)}
</View>
</ScrollView>
</KeyboardAvoidingView>
</SafeAreaView>
</View>
);
}

BIN
assets/images/todo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB