Modified stock app to Todolist app
parent
a7ae56f99d
commit
c816eebbe5
76
src/App.tsx
76
src/App.tsx
|
@ -1,24 +1,66 @@
|
||||||
import React from 'react';
|
import React, {useState} from 'react';
|
||||||
import logo from './logo.svg';
|
|
||||||
import './App.css';
|
import './App.css';
|
||||||
|
import Todo from "./Todo";
|
||||||
|
|
||||||
|
interface TodoItem {
|
||||||
|
id: number;
|
||||||
|
text: string;
|
||||||
|
completed: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
|
const [todos, setTodos] = useState<TodoItem[]>([]);
|
||||||
|
const [text, setText] = useState("");
|
||||||
|
|
||||||
|
const handleAddTodo = () => {
|
||||||
|
if (text.trim() === "") return;
|
||||||
|
const newTodo: TodoItem = {
|
||||||
|
id: todos.length + 1,
|
||||||
|
text: text,
|
||||||
|
completed: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
setTodos([...todos, newTodo]);
|
||||||
|
setText("");
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleToggleTodo = (id: number) => {
|
||||||
|
const updatedTodos = todos.map((todo) => {
|
||||||
|
if (todo.id === id) {
|
||||||
|
return { ...todo, completed: !todo.completed };
|
||||||
|
}
|
||||||
|
return todo;
|
||||||
|
});
|
||||||
|
|
||||||
|
setTodos(updatedTodos);
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDeleteTodo = (id: number) => {
|
||||||
|
const updatedTodos = todos.filter((todo) => todo.id !== id);
|
||||||
|
setTodos(updatedTodos);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="App">
|
<div>
|
||||||
<header className="App-header">
|
<h1>Todo List</h1>
|
||||||
<img src={logo} className="App-logo" alt="logo" />
|
<input
|
||||||
<p>
|
type="text"
|
||||||
Edit <code>src/App.tsx</code> and save to reload.
|
value={text}
|
||||||
</p>
|
onChange={(e) => setText(e.target.value)}
|
||||||
<a
|
/>
|
||||||
className="App-link"
|
<button onClick={handleAddTodo}>Add Todo</button>
|
||||||
href="https://reactjs.org"
|
<ul>
|
||||||
target="_blank"
|
{todos.map((todo) => (
|
||||||
rel="noopener noreferrer"
|
<Todo
|
||||||
>
|
key={todo.id}
|
||||||
Learn React
|
id={todo.id}
|
||||||
</a>
|
text={todo.text}
|
||||||
</header>
|
completed={todo.completed}
|
||||||
|
onToggle={handleToggleTodo}
|
||||||
|
onDelete={handleDeleteTodo}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
interface TodoProps {
|
||||||
|
id: number;
|
||||||
|
text: string;
|
||||||
|
completed: boolean;
|
||||||
|
onToggle: (id: number) => void;
|
||||||
|
onDelete: (id: number) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Todo = ( { id, text, completed, onToggle, onDelete }: TodoProps) => {
|
||||||
|
const handleToggle = () => {
|
||||||
|
onToggle(id);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDelete = () => {
|
||||||
|
onDelete(id);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" checked={completed} onChange={handleToggle} />
|
||||||
|
<span style={{ textDecoration: completed ? "line-through" : "none"}}>
|
||||||
|
{text}
|
||||||
|
</span>
|
||||||
|
<button onClick={handleDelete}>Delete</button>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Todo;
|
Loading…
Reference in New Issue