) => {
+ e.preventDefault();
+
+ if (!value.trim().length) return;
+
+ addTodo(value);
+ setValue('');
+ };
+
+ return (
+
+ );
+}
diff --git a/src/components/toolbox/todo/form/index.ts b/src/components/toolbox/todo/form/index.ts
new file mode 100644
index 0000000..9398c9e
--- /dev/null
+++ b/src/components/toolbox/todo/form/index.ts
@@ -0,0 +1 @@
+export { Form } from './form';
diff --git a/src/components/toolbox/todo/index.ts b/src/components/toolbox/todo/index.ts
new file mode 100644
index 0000000..b54a84e
--- /dev/null
+++ b/src/components/toolbox/todo/index.ts
@@ -0,0 +1 @@
+export { Todo } from './todo';
diff --git a/src/components/toolbox/todo/todo.module.css b/src/components/toolbox/todo/todo.module.css
new file mode 100644
index 0000000..fdbd99d
--- /dev/null
+++ b/src/components/toolbox/todo/todo.module.css
@@ -0,0 +1 @@
+/* WIP */
diff --git a/src/components/toolbox/todo/todo.tsx b/src/components/toolbox/todo/todo.tsx
new file mode 100644
index 0000000..05663cd
--- /dev/null
+++ b/src/components/toolbox/todo/todo.tsx
@@ -0,0 +1,20 @@
+import { Modal } from '@/components/modal';
+import { Form } from './form';
+import { Todos } from './todos';
+
+import styles from './todo.module.css';
+
+interface TodoProps {
+ onClose: () => void;
+ show: boolean;
+}
+
+export function Todo({ onClose, show }: TodoProps) {
+ return (
+
+ Todos
+
+
+
+ );
+}
diff --git a/src/components/toolbox/todo/todos/index.ts b/src/components/toolbox/todo/todos/index.ts
new file mode 100644
index 0000000..55b9f3d
--- /dev/null
+++ b/src/components/toolbox/todo/todos/index.ts
@@ -0,0 +1 @@
+export { Todos } from './todos';
diff --git a/src/components/toolbox/todo/todos/todo/index.ts b/src/components/toolbox/todo/todos/todo/index.ts
new file mode 100644
index 0000000..b54a84e
--- /dev/null
+++ b/src/components/toolbox/todo/todos/todo/index.ts
@@ -0,0 +1 @@
+export { Todo } from './todo';
diff --git a/src/components/toolbox/todo/todos/todo/todo.module.css b/src/components/toolbox/todo/todos/todo/todo.module.css
new file mode 100644
index 0000000..b239bcd
--- /dev/null
+++ b/src/components/toolbox/todo/todos/todo/todo.module.css
@@ -0,0 +1,45 @@
+.wrapper {
+ display: flex;
+ column-gap: 4px;
+ align-items: center;
+ height: 45px;
+ padding: 4px;
+ margin-top: 12px;
+ background-color: var(--color-neutral-50);
+ border: 1px solid var(--color-neutral-200);
+ border-radius: 8px;
+
+ & .checkbox {
+ display: block;
+ margin: 0 8px 0 4px;
+ }
+
+ & .textbox {
+ flex-grow: 1;
+ min-width: 0;
+ height: 100%;
+ font-size: var(--font-sm);
+ color: var(--color-foreground);
+ background-color: transparent;
+ border: none;
+ outline: none;
+
+ &.done {
+ color: var(--color-foreground-subtle);
+ text-decoration: line-through;
+ }
+ }
+
+ & button {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: 100%;
+ aspect-ratio: 1 / 1;
+ color: #f43f5e;
+ cursor: pointer;
+ background-color: rgb(244 63 94 / 15%);
+ border: none;
+ border-radius: 4px;
+ }
+}
diff --git a/src/components/toolbox/todo/todos/todo/todo.tsx b/src/components/toolbox/todo/todos/todo/todo.tsx
new file mode 100644
index 0000000..3861d7f
--- /dev/null
+++ b/src/components/toolbox/todo/todos/todo/todo.tsx
@@ -0,0 +1,41 @@
+import { FaRegTrashAlt } from 'react-icons/fa/index';
+
+import { useTodoStore } from '@/stores/todo';
+import { cn } from '@/helpers/styles';
+
+import styles from './todo.module.css';
+
+interface TodoProps {
+ done: boolean;
+ id: string;
+ todo: string;
+}
+
+export function Todo({ done, id, todo }: TodoProps) {
+ const deleteTodo = useTodoStore(state => state.deleteTodo);
+ const toggleTodo = useTodoStore(state => state.toggleTodo);
+ const editTodo = useTodoStore(state => state.editTodo);
+
+ const handleCheck = () => toggleTodo(id);
+ const handleDelete = () => deleteTodo(id);
+
+ return (
+
+
+ editTodo(id, e.target.value)}
+ />
+
+
+ );
+}
diff --git a/src/components/toolbox/todo/todos/todos.module.css b/src/components/toolbox/todo/todos/todos.module.css
new file mode 100644
index 0000000..fdbd99d
--- /dev/null
+++ b/src/components/toolbox/todo/todos/todos.module.css
@@ -0,0 +1 @@
+/* WIP */
diff --git a/src/components/toolbox/todo/todos/todos.tsx b/src/components/toolbox/todo/todos/todos.tsx
new file mode 100644
index 0000000..0b81812
--- /dev/null
+++ b/src/components/toolbox/todo/todos/todos.tsx
@@ -0,0 +1,17 @@
+import { Todo } from './todo';
+
+import { useTodoStore } from '@/stores/todo';
+
+import styles from './todos.module.css';
+
+export function Todos() {
+ const todos = useTodoStore(state => state.todos);
+
+ return (
+
+ {todos.map(todo => (
+
+ ))}
+
+ );
+}
diff --git a/src/stores/todo.ts b/src/stores/todo.ts
new file mode 100644
index 0000000..eb2101e
--- /dev/null
+++ b/src/stores/todo.ts
@@ -0,0 +1,81 @@
+import { create } from 'zustand';
+import { createJSONStorage, persist } from 'zustand/middleware';
+import merge from 'deepmerge';
+import { v4 as uuid } from 'uuid';
+
+interface TodoStore {
+ addTodo: (todo: string) => void;
+ deleteTodo: (id: string) => void;
+ editTodo: (id: string, newTodo: string) => void;
+ todos: Array<{
+ createdAt: number;
+ done: boolean;
+ id: string;
+ todo: string;
+ }>;
+ toggleTodo: (id: string) => void;
+}
+
+export const useTodoStore = create()(
+ persist(
+ (set, get) => ({
+ addTodo(todo) {
+ set({
+ todos: [
+ {
+ createdAt: Date.now(),
+ done: false,
+ id: uuid(),
+ todo,
+ },
+ ...get().todos,
+ ],
+ });
+ },
+
+ deleteTodo(id) {
+ set({
+ todos: get().todos.filter(todo => todo.id !== id),
+ });
+ },
+
+ editTodo(id, newTodo) {
+ set({
+ todos: get().todos.map(todo => {
+ if (todo.id !== id) return todo;
+
+ return {
+ ...todo,
+ todo: newTodo,
+ };
+ }),
+ });
+ },
+
+ todos: [],
+
+ toggleTodo(id) {
+ set({
+ todos: get().todos.map(todo => {
+ if (todo.id !== id) return todo;
+
+ return {
+ ...todo,
+ done: !todo.done,
+ };
+ }),
+ });
+ },
+ }),
+ {
+ merge: (persisted, current) =>
+ merge(current, persisted as Partial),
+
+ name: 'moodist-todos',
+ partialize: state => ({ todos: state.todos }),
+ skipHydration: true,
+ storage: createJSONStorage(() => localStorage),
+ version: 0,
+ },
+ ),
+);