Skip to content

Instantly share code, notes, and snippets.

@nahidmbstu
Last active January 1, 2025 17:12
Show Gist options
  • Select an option

  • Save nahidmbstu/2e85c2c61396b5374f959e76c03d9b9a to your computer and use it in GitHub Desktop.

Select an option

Save nahidmbstu/2e85c2c61396b5374f959e76c03d9b9a to your computer and use it in GitHub Desktop.
react native muti-level task app.js
import React, { useState } from "react";
import {
View,
Text,
TextInput,
Button,
FlatList,
TouchableOpacity,
StyleSheet,
} from "react-native";
import { MaterialIcons } from "@expo/vector-icons"; // Install via `expo install @expo/vector-icons`
export default function App() {
const [tasks, setTasks] = useState([]); // Stores tasks
const [inputValue, setInputValue] = useState(""); // Stores text input
const [selectedTask, setSelectedTask] = useState(null); // Tracks selected parent task
// Function to add a task or subtask
const addTask = () => {
if (inputValue.trim() === "") return; // Prevent empty tasks
if (selectedTask) {
// Add as a subtask to the selected task
const addSubtask = (taskList) =>
taskList.map((task) => {
if (task.id === selectedTask) {
return {
...task,
subtasks: [
...task.subtasks,
{ id: Date.now(), title: inputValue, subtasks: [], done: false },
],
};
}
return {
...task,
subtasks: addSubtask(task.subtasks),
};
});
setTasks(addSubtask(tasks));
setSelectedTask(null); // Clear selection
} else {
// Add as a root-level task
setTasks([
...tasks,
{ id: Date.now(), title: inputValue, subtasks: [], done: false },
]);
}
setInputValue(""); // Clear input
};
// Function to toggle task as done
const toggleDone = (id) => {
const toggleTaskStatus = (taskList) =>
taskList.map((task) => {
if (task.id === id) {
return { ...task, done: !task.done };
}
return {
...task,
subtasks: toggleTaskStatus(task.subtasks),
};
});
setTasks(toggleTaskStatus(tasks));
};
// Recursive component to render tasks and subtasks
const TaskItem = ({ task }) => {
return (
<View style={styles.taskContainer}>
<TouchableOpacity
onPress={() => setSelectedTask(task.id)}
style={[
styles.task,
selectedTask === task.id && styles.selectedTask,
task.done && styles.doneTask, // Apply "done" style if task is completed
]}
>
<Text style={task.done ? styles.doneText : undefined}>{task.title}</Text>
<TouchableOpacity onPress={() => toggleDone(task.id)}>
<MaterialIcons
name={task.done ? "check-box" : "check-box-outline-blank"}
size={24}
color="green"
style={styles.doneIcon}
/>
</TouchableOpacity>
</TouchableOpacity>
{/* Render subtasks */}
<FlatList
data={task.subtasks}
keyExtractor={(item) => item.id.toString()}
renderItem={({ item }) => <TaskItem task={item} />}
/>
</View>
);
};
return (
<View style={styles.container}>
{/* Input and Add Button */}
<View style={styles.inputContainer}>
<TextInput
style={styles.input}
placeholder="Enter task or subtask"
value={inputValue}
onChangeText={setInputValue}
/>
<Button title="Add" onPress={addTask} />
</View>
{/* Task List */}
<FlatList
data={tasks}
keyExtractor={(item) => item.id.toString()}
renderItem={({ item }) => <TaskItem task={item} />}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20,
},
inputContainer: {
flexDirection: "row",
marginBottom: 20,
},
input: {
flex: 1,
borderWidth: 1,
borderColor: "#ccc",
padding: 10,
marginRight: 10,
borderRadius: 5,
},
taskContainer: {
marginLeft: 20,
marginTop: 10,
flexDirection: "column",
},
task: {
padding: 10,
backgroundColor: "#f9f9f9",
borderRadius: 5,
borderWidth: 1,
borderColor: "#ddd",
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
},
selectedTask: {
backgroundColor: "#d3f4ff",
borderColor: "#87ceeb",
},
doneTask: {
backgroundColor: "#e0ffe0",
borderColor: "#87ff87",
},
doneText: {
textDecorationLine: "line-through",
color: "#888",
},
doneIcon: {
marginLeft: 10,
},
});
@nahidmbstu
Copy link
Author

very useful for understanding recursion and its application in real apps.

@nahidmbstu
Copy link
Author

Screenshot 2025-01-01 at 11 11 39 PM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment