Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 46 additions & 41 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,60 +1,65 @@
# DevDone - A Developer's Todo App

A simple, clean, and efficient todo list application built with vanilla JavaScript, HTML, and CSS.
🚀 A beginner-friendly open-source project from the DevDotCom Community to help developers take their first step into open source! This simple and efficient task management app is built using Flask, JavaScript, HTML, and CSS to make learning fun and easy.

## Features
🌟 Features

- Add new tasks
- Mark tasks as complete
- Delete tasks
- Persistent storage using localStorage
- Clean and responsive design
- Keyboard accessible
- Mobile-friendly interface
Add Tasks: Easily create and manage tasks.

## Getting Started
Mark as Completed: Toggle tasks as done.

1. Clone the repository or download the files
2. Open `index.html` in your web browser
Delete Tasks: Remove completed tasks.

No build process or dependencies required!
Persistent Storage: Saves tasks using JSON.

## Project Structure
Minimalistic UI: Clean and user-friendly design.

```
🛠️ Technologies Used

Backend: Flask (Python)

Frontend: HTML, CSS, JavaScript

Storage: JSON

📁 Project Structure
DevDone/
├── index.html # Main HTML structure
├── styles.css # Styling and layout
├── script.js # Application logic
└── README.md # Project documentation
```
│── app.py # Flask backend
│── requirements.txt # Dependencies
│── static/
│ ├── styles.css # Stylesheet
│ ├── script.js # Frontend logic
│── templates/
│ ├── index.html # UI template
│── data/
│ ├── todos.json # Task storage
│── README.md # Documentation

🚀 Getting Started

Prerequisites

Python 3 installed

## Usage
Install Flask using:
pip install flask

- Type your task in the input field
- Click "Add Task" or press Enter to add the task
- Check the checkbox to mark a task as complete
- Click the "Delete" button to remove a task
# Clone the repository
git clone https://github.com/your-username/developer-todo-app.git
cd DevDone

## Browser Support
# Create a Simple environment using conda or pip

Works in all modern browsers (Chrome, Firefox, Safari, Edge)
# Install dependencies
pip install -r requirements.txt

## Contributing
# Run the Flask application
python app.py

1. Fork the repository
2. Create a new branch (`git checkout -b feature/improvement`)
3. Make your changes
4. Commit your changes (`git commit -am 'Add new feature'`)
5. Push to the branch (`git push origin feature/improvement`)
6. Create a Pull Request
🤝 Contributing

### Development Guidelines
- Follow existing code style and formatting
- Test your changes thoroughly
- Update documentation as needed
- Keep pull requests focused on a single feature or fix
This is an open-source project built for beginners! Contributions are highly encouraged. Feel free to fork, raise issues, or submit pull requests to improve this project.

## License
📜 License

MIT License
This project is licensed under the MIT License.
63 changes: 63 additions & 0 deletions app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
from flask import Flask, render_template, request, jsonify
import json
import os

app = Flask(__name__)

DATA_FILE = "data/todos.json"

# Ensure data directory exists
os.makedirs("data", exist_ok=True)

# Load todos from file
def load_todos():
if os.path.exists(DATA_FILE):
with open(DATA_FILE, "r") as file:
return json.load(file)
return []

# Save todos to file
def save_todos(todos):
with open(DATA_FILE, "w") as file:
json.dump(todos, file, indent=4)

@app.route("/")
def home():
return render_template("index.html")

@app.route("/todos", methods=["GET"])
def get_todos():
return jsonify(load_todos())

@app.route("/todos", methods=["POST"])
def add_todo():
todos = load_todos()
data = request.get_json()
new_todo = {
"id": data["id"],
"text": data["text"],
"completed": False
}
todos.append(new_todo)
save_todos(todos)
return jsonify(new_todo), 201

@app.route("/todos/<int:todo_id>", methods=["DELETE"])
def delete_todo(todo_id):
todos = load_todos()
todos = [todo for todo in todos if todo["id"] != todo_id]
save_todos(todos)
return jsonify({"message": "Todo deleted"}), 200

@app.route("/todos/<int:todo_id>", methods=["PUT"])
def update_todo(todo_id):
todos = load_todos()
for todo in todos:
if todo["id"] == todo_id:
todo["completed"] = not todo["completed"]
break
save_todos(todos)
return jsonify({"message": "Todo updated"}), 200

if __name__ == "__main__":
app.run(debug=True)
27 changes: 0 additions & 27 deletions index.html

This file was deleted.

72 changes: 0 additions & 72 deletions script.js

This file was deleted.

67 changes: 67 additions & 0 deletions static/script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
document.addEventListener("DOMContentLoaded", () => {
const todoForm = document.getElementById("todo-form");
const todoInput = document.getElementById("todo-input");
const todoList = document.getElementById("todo-list");
const itemCount = document.getElementById("itemcount");

// Fetch todos from backend
const fetchTodos = async () => {
const response = await fetch("/todos");
const todos = await response.json();
renderTodos(todos);
};

// Add a new todo
todoForm.addEventListener("submit", async (e) => {
e.preventDefault();
const text = todoInput.value.trim();
if (text) {
const response = await fetch("/todos", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ id: Date.now(), text })
});
const newTodo = await response.json();
renderTodos([...document.todos, newTodo]);
todoInput.value = "";
}
});

// Render Todos
const renderTodos = (todos) => {
document.todos = todos;
todoList.innerHTML = "";
todos.forEach((todo) => {
const li = document.createElement("li");
li.className = "todo-item";
li.innerHTML = `
<input type="checkbox" ${todo.completed ? "checked" : ""}>
<span class="${todo.completed ? "completed" : ""}">${todo.text}</span>
<button class="delete-btn">Delete</button>
`;

const checkbox = li.querySelector("input");
checkbox.addEventListener("change", async () => {
await fetch(`/todos/${todo.id}`, { method: "PUT" });
fetchTodos();
});

const deleteBtn = li.querySelector(".delete-btn");
deleteBtn.addEventListener("click", async () => {
await fetch(`/todos/${todo.id}`, { method: "DELETE" });
fetchTodos();
});

todoList.appendChild(li);
});
updateTaskCount(todos.length);
};

// Update Task Count
const updateTaskCount = (count) => {
itemCount.innerText = `Number of Tasks: ${count}`;
};

// Initial fetch
fetchTodos();
});
Loading