You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

115 lines
3.4 KiB

2 weeks ago
import { VStack } from "@/components/ui/vstack";
import { Text } from "@/components/ui/text";
import { View } from "react-native";
import {
Checkbox,
CheckboxIcon,
CheckboxIndicator,
CheckboxLabel,
} from "@/components/ui/checkbox";
import { useActionState, useEffect, useRef, useState } from "react";
import { AddIcon, CheckIcon } from "@/components/ui/icon";
import TodoContainer, { Todo } from "@/components/containers/todo-container";
import { FormControl } from "@/components/ui/form-control";
import { Input, InputField, InputIcon } from "@/components/ui/input";
import { Pressable } from "@/components/ui/pressable";
import uuid from "react-native-uuid";
import AsyncStorage from "@react-native-async-storage/async-storage";
const STORAGE_KEY = "todos:v1";
export default function TodoTab() {
const [item, setItem] = useState("");
const [todos, setTodos] = useState<Todo[]>([]);
// 초기 로드
useEffect(() => {
(async () => {
try {
const raw = await AsyncStorage.getItem(STORAGE_KEY);
if (raw) {
const parsed = JSON.parse(raw) as Todo[];
setTodos(parsed);
}
} catch (e) {
console.warn("Failed to load todos: ", e);
}
})();
}, []);
// 변경 시 저장 (디바운스 300ms)
const saveTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
useEffect(() => {
if (saveTimer.current) clearTimeout(saveTimer.current);
saveTimer.current = setTimeout(async () => {
try {
await AsyncStorage.setItem(STORAGE_KEY, JSON.stringify(todos));
} catch (e) {
console.warn("Failed to save todos: ", e);
}
}, 300);
return () => {
if (saveTimer.current) clearTimeout(saveTimer.current);
};
}, [todos]);
const addTodo = (task: string) => {
const lastTodo = todos[todos?.length - 1];
if (lastTodo?.task !== "" && task !== "") {
setTodos([
...todos,
{
id: uuid.v4(),
task: task,
completed: false,
},
]);
setItem("");
}
};
const toggleTodo = (id: string) => {
const updatedTodos = todos?.map((todo) => {
if (todo.id === id) {
todo.completed = !todo.completed;
}
return todo;
});
setTodos(updatedTodos);
};
const deleteTodo = (id: string) => {
const updatedTodos = todos.filter((todo) => todo.id !== id);
setTodos(updatedTodos);
};
return (
<VStack className="flex-1 bg-secondary-100 md:items-center md:justify-center">
<VStack className="rounded-md bg-secondary-100 md:h-[500px] md:w-[700px]">
<FormControl className="my-4">
<Input variant="underlined" size="sm" className="mx-6 my-2">
<InputField
placeholder="다음 할 일은 무엇인가요?"
value={item}
onChangeText={(value) => setItem(value)}
onSubmitEditing={() => addTodo(item)}
/>
<Pressable onPress={() => addTodo(item)}>
<InputIcon as={AddIcon} className="cursor-pointer h-3 w-3" />
</Pressable>
</Input>
</FormControl>
{todos?.map((todo: Todo, index: number) => (
<TodoContainer
key={index}
todo={todo}
toggleTodo={toggleTodo}
deleteTodo={deleteTodo}
/>
))}
</VStack>
</VStack>
);
}