diff --git a/src/app/page.tsx b/src/app/page.tsx index 79ca5b1..c1baa81 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,8 +1,89 @@ -// src/app/page.tsx +'use client'; // ← 重要!状態管理を使う時は必須 + +import { useState } from 'react'; + +// TypeScriptの型定義 +type Todo = { + id: number; // 一意の識別子 + text: string; // TODOの内容 + completed: boolean; // 完了状態 +}; + export default function Home() { + // useState フックの使い方 + const [todos, setTodos] = useState([]); + const [inputValue, setInputValue] = useState(''); + const addTodo = () => { + // 空の入力をチェック(バリデーション) + if (inputValue.trim() === '') { + alert('TODOを入力してください'); + return; + } + const newTodo: Todo = { + id: Date.now(), // 簡易的なID生成(本番ではuuidを推奨) + text: inputValue, + completed: false + }; + setTodos([...todos, newTodo]); + setInputValue(''); + }; + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault(); // ページのリロードを防ぐ + addTodo(); + }; + + const toggleTodo = (id: number) => { + // mapを使って新しい配列を作成(イミュータビリティ) + const updatedTodos = todos.map(todo => { + if (todo.id === id) { + // 該当するTODOを見つけたら、completedを反転 + return { ...todo, completed: !todo.completed }; + } + return todo; // それ以外はそのまま + }); + + setTodos(updatedTodos); + }; + return ( -
-

私のTODOアプリ

+
+
+

TODOアプリ

+{/* JSX部分 */} +
+ setInputValue(e.target.value)} + placeholder="TODOを入力してEnterキー" + className="w-full p-3 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500" + /> + +
+
+ {todos.map((todo) => ( +
+ toggleTodo(todo.id)} + className="mr-3 h-5 w-5 cursor-pointer" + /> + + {todo.text} + +
+ ))} +
+
); } \ No newline at end of file