diff --git a/README.md b/README.md
index d1c68b5..b2e843b 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,5 @@
-# Todo
\ No newline at end of file
+# Todo
+
+A task management app where users can add, complete, and remove tasks. Built in React with Zustand for managing global state. Features include task creation, completion toggling, and task counters.
+
+https://tthiry-todotaskmanagement.netlify.app
diff --git a/index.html b/index.html
index f7ac4e4..e36e70d 100644
--- a/index.html
+++ b/index.html
@@ -2,9 +2,19 @@
-
+
+
+
+
+
- Todo
+
+ Todo Task Management
diff --git a/package.json b/package.json
index caf6289..d9f66d6 100644
--- a/package.json
+++ b/package.json
@@ -11,7 +11,10 @@
},
"dependencies": {
"react": "^19.0.0",
- "react-dom": "^19.0.0"
+ "react-dom": "^19.0.0",
+ "react-icons": "^5.5.0",
+ "styled-components": "^6.1.18",
+ "zustand": "^5.0.5"
},
"devDependencies": {
"@eslint/js": "^9.21.0",
diff --git a/src/App.jsx b/src/App.jsx
index 5427540..2983af9 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -1,5 +1,15 @@
+import { GlobalStyle } from "./styles/GlobalStyle"
+import { Header } from "./components/Header"
+import { TaskForm } from "./components/TaskForm"
+import { TaskList } from "./components/TaskList"
+
export const App = () => {
return (
- React Boilerplate
+ <>
+
+
+
+
+ >
)
}
diff --git a/src/assets/images/Task_management.webp b/src/assets/images/Task_management.webp
new file mode 100644
index 0000000..cb6246e
Binary files /dev/null and b/src/assets/images/Task_management.webp differ
diff --git a/src/components/Header.jsx b/src/components/Header.jsx
new file mode 100644
index 0000000..b8b3c90
--- /dev/null
+++ b/src/components/Header.jsx
@@ -0,0 +1,66 @@
+import styled from "styled-components"
+import headerImg from "/src/assets/images/Task_management.webp"
+
+
+export const Header = () => {
+ return (
+
+
+ ToDo Task Management
+ Stay organized with your personal task manager
+
+
+
+ )
+}
+
+const StyledHeader = styled.header`
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+`
+
+const TextContent = styled.div`
+ text-align: center;
+ margin: 1rem 1rem 0 1rem;
+
+ h1 {
+ font-size: 1.5rem;
+ }
+
+ p {
+ font-size: 1rem;
+ padding: 0 1rem
+ }
+
+ @media (min-width: 768px) {
+ h1 {
+ font-size: 1.75rem;
+ }
+
+ p {
+ font-size: 1.125rem;
+ }
+
+ margin: 1rem;
+ }
+
+ @media (min-width: 1024px) {
+ h1 {
+ font-size: 2rem;
+ }
+ }
+`
+
+const HeaderImage = styled.img`
+ width: 100%;
+ max-width: 500px;
+ height: auto;
+ padding: 1rem;
+ box-sizing: border-box;
+
+ @media (min-width: 768px) {
+ padding: 0;
+ }
+`
\ No newline at end of file
diff --git a/src/components/Task.jsx b/src/components/Task.jsx
new file mode 100644
index 0000000..fab88be
--- /dev/null
+++ b/src/components/Task.jsx
@@ -0,0 +1,77 @@
+import styled from "styled-components"
+import { useTaskStore } from "../stores/useTaskStore"
+import { FaTrashAlt, FaCheckCircle, FaRegCircle } from "react-icons/fa"
+
+
+export const Task = ({ id, task, completed }) => {
+ const deleteTask = useTaskStore(state => state.deleteTask)
+ const toggleComplete = useTaskStore(state => state.toggleComplete)
+
+ return (
+
+
+ {task}
+
+ toggleComplete(id)}
+ >
+ {completed ? : }
+
+ deleteTask(id)}
+ >
+
+
+
+
+
+
+ )
+}
+
+const TaskWrapper = styled.div`
+ max-width: 500px;
+ padding: 0.7rem;
+ margin: 0 1rem 1rem 1rem;
+ background-color: #ededfb;
+ border-radius: 8px;
+ border-left: 3px solid #1c55e4;
+
+ @media (min-width: 768px) {
+ margin: 0 0 1rem 0;
+ }
+`
+
+const TaskContent = styled.div`
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+`
+
+const TaskMessage = styled.p`
+ margin: 0;
+ flex: 1;
+ padding-right: 1rem;
+ text-decoration: ${props => (props.completed ? "line-through" : "none")};
+`
+
+const Icons = styled.div`
+ display: flex;
+ gap: 0.5rem;
+`
+
+const IconButton = styled.button`
+ background: #1c55e4;
+ color: white;
+ border: none;
+ border-radius: 4px;
+ cursor: pointer;
+ padding: 0.5rem;
+ vertical-align: middle;
+
+ &:hover {
+ opacity: 0.8;
+ }
+`
\ No newline at end of file
diff --git a/src/components/TaskForm.jsx b/src/components/TaskForm.jsx
new file mode 100644
index 0000000..c9f6da6
--- /dev/null
+++ b/src/components/TaskForm.jsx
@@ -0,0 +1,66 @@
+import styled from "styled-components"
+import { useState } from "react"
+import { useTaskStore } from "../stores/useTaskStore"
+
+
+export const TaskForm = () => {
+ const [task, setTask] = useState("")
+ const createTask = useTaskStore(state => state.createTask)
+
+ const handleSubmit = e => {
+ e.preventDefault()
+ if (task.trim() === "") return
+ createTask(task)
+ setTask("")
+ }
+
+ return (
+
+
+
+ )
+}
+
+const PageWrapper = styled.main`
+ padding: 1rem;
+ display: flex;
+ justify-content: center;
+`
+
+const Form = styled.form`
+ display: flex;
+ flex-direction: column;
+ width: 100%;
+ max-width: 500px;
+ gap: 1rem;
+`
+
+const Textarea = styled.textarea`
+ width: 100%;
+ padding: 1rem;
+ font-size: 16px;
+ font-family: "Quicksand", sans-serif;
+ box-sizing: border-box;
+`
+
+const Button = styled.button`
+ padding: 0.5rem 1.5rem;
+ border-radius: 20px;
+ border: none;
+ background: #1c55e4;
+ color: white;
+ font-size: 16px;
+ font-weight: bold;
+ cursor: pointer;
+
+ &:hover {
+ opacity: 0.9;
+ }
+`
diff --git a/src/components/TaskList.jsx b/src/components/TaskList.jsx
new file mode 100644
index 0000000..bb90281
--- /dev/null
+++ b/src/components/TaskList.jsx
@@ -0,0 +1,47 @@
+import styled from "styled-components"
+import { useTaskStore } from "../stores/useTaskStore"
+import { Task } from "./Task"
+
+export const TaskList = () => {
+ const tasks = useTaskStore(state => state.tasks)
+ const total = tasks.length
+ const uncompleted = tasks.filter(t => !t.completed).length
+
+ if (total === 0) {
+ return (
+
+ No tasks yet. Add your first one!
+
+ )
+ }
+
+ return (
+
+
+ Total tasks: {total} | Uncompleted: {uncompleted}
+
+ {tasks.map(task => (
+
+ ))}
+
+ )
+}
+
+const Section = styled.section`
+ width: 100%;
+ max-width: 500px;
+ margin: 0 auto;
+`
+
+const TaskSummary = styled.p`
+ margin-bottom: 1rem;
+ font-weight: bold;
+ margin: 1rem;
+`
+
+const EmptyState = styled.div`
+ text-align: center;
+ padding: 2rem;
+ font-style: italic;
+ color: #777;
+`
\ No newline at end of file
diff --git a/src/stores/useTaskStore.jsx b/src/stores/useTaskStore.jsx
new file mode 100644
index 0000000..d51896d
--- /dev/null
+++ b/src/stores/useTaskStore.jsx
@@ -0,0 +1,44 @@
+import { create } from "zustand"
+
+
+const initialState = {
+ tasks: [
+ {
+ id: 1,
+ task: "My first task...",
+ completed: false
+ }
+ ]
+}
+
+export const useTaskStore = create((set) => ({
+ ...initialState,
+
+ createTask: (task) => {
+ const newTask = {
+ id: Date.now(),
+ task,
+ completed: false
+ }
+
+ set(state => ({ tasks: [newTask, ...state.tasks] }))
+ },
+
+ deleteTask: (id) => {
+ set(state => ({
+ tasks: state.tasks.filter(task => task.id !== id)
+ }))
+ },
+
+ toggleComplete: (id) => {
+ set(state => ({
+ tasks: state.tasks.map(task =>
+ task.id === id ? { ...task, completed: !task.completed } : task
+ )
+ }))
+ },
+
+ clearTasks: () => set({ tasks: [] }),
+
+ resetTasks: () => set(initialState)
+}))
diff --git a/src/styles/GlobalStyle.js b/src/styles/GlobalStyle.js
new file mode 100644
index 0000000..a0fb9b5
--- /dev/null
+++ b/src/styles/GlobalStyle.js
@@ -0,0 +1,12 @@
+import { createGlobalStyle } from 'styled-components';
+
+export const GlobalStyle = createGlobalStyle`
+ body {
+ margin: 0;
+ padding: 0;
+ font-family: "Quicksand", sans-serif;
+ background: #FFFFFF;
+ color: #1E1E1E;
+ box-sizing: border-box;
+ }
+`;
\ No newline at end of file