diff --git a/todo_app_backend/task_app/migrations/0004_task_priority.py b/todo_app_backend/task_app/migrations/0004_task_priority.py new file mode 100644 index 0000000..0619479 --- /dev/null +++ b/todo_app_backend/task_app/migrations/0004_task_priority.py @@ -0,0 +1,22 @@ +# Generated by Django 5.2.8 on 2026-04-16 10:37 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("task_app", "0003_alter_task_status"), + ] + + operations = [ + migrations.AddField( + model_name="task", + name="priority", + field=models.CharField( + choices=[("High", "High"), ("Medium", "Medium"), ("Low", "Low")], + default="Medium", + max_length=20, + ), + ), + ] diff --git a/todo_app_backend/task_app/models.py b/todo_app_backend/task_app/models.py index dff2f03..a7cc483 100644 --- a/todo_app_backend/task_app/models.py +++ b/todo_app_backend/task_app/models.py @@ -6,8 +6,14 @@ class Task(models.Model): ('In-Progress','In-progress'), ('Completed','Completed') ) + PRIORITY = ( + ('High','High'), + ('Medium','Medium'), + ('Low','Low') + ) task_name = models.CharField(max_length=100) description = models.TextField() status = models.CharField(max_length=20, choices=STATUS, default='In-Progress') + priority = models.CharField(max_length=20, choices=PRIORITY, default='Medium') created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) \ No newline at end of file diff --git a/todo_app_backend/todo_app/settings.py b/todo_app_backend/todo_app/settings.py index cdff89f..a0d7c9d 100644 --- a/todo_app_backend/todo_app/settings.py +++ b/todo_app_backend/todo_app/settings.py @@ -81,7 +81,7 @@ import dj_database_url DATABASES = { - "default": dj_database_url.config(default=os.environ.get("DATABASE_URL")) + "default": dj_database_url.config(default=os.environ.get("DATABASE_URL", "sqlite:///db.sqlite3")) } diff --git a/todo_app_frontend/src/App.tsx b/todo_app_frontend/src/App.tsx index c38f864..e617cce 100644 --- a/todo_app_frontend/src/App.tsx +++ b/todo_app_frontend/src/App.tsx @@ -7,16 +7,19 @@ function App() { const [error, setError] = useState(null); const [searchTerm, setSearchTerm] = useState(''); const [filterStatus, setFilterStatus] = useState('All'); + const [filterPriority, setFilterPriority] = useState('All'); + const [sortBy, setSortBy] = useState('None'); const [showAddForm, setShowAddForm] = useState(false); const [editingTask, setEditingTask] = useState(null); const [newTask, setNewTask] = useState({ task_name: '', - description: '' + description: '', + priority: 'Medium' }); // API Base URL - Update this to your Django backend URL - // const API_BASE_URL = 'http://localhost:8000/api'; // Change this to your backend URL - const API_BASE_URL = 'https://todo-app-fullstack-nrfk.onrender.com/api'; + const API_BASE_URL = 'http://localhost:8000/api'; // Change this to your backend URL + // const API_BASE_URL = 'https://todo-app-fullstack-nrfk.onrender.com/api'; // Fetch tasks from API const fetchTasks = async () => { @@ -47,12 +50,15 @@ function App() { const response = await fetch(`${API_BASE_URL}/tasks/`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(newTask) + body: JSON.stringify({ + ...newTask, + priority: newTask.priority || 'Medium' + }) }); if (!response.ok) throw new Error('Failed to create task'); await fetchTasks(); // Refresh tasks list - setNewTask({ task_name: '', description: '' }); + setNewTask({ task_name: '', description: '', priority: 'Medium' }); setShowAddForm(false); } catch (err) { setError(err.message); @@ -72,7 +78,8 @@ function App() { body: JSON.stringify({ task_name: editingTask.task_name, description: editingTask.description, - status: editingTask.status + status: editingTask.status, + priority: editingTask.priority || 'Medium' }) }); if (!response.ok) throw new Error('Failed to update task'); @@ -122,10 +129,11 @@ function App() { } }; - const getPriorityColor = (status) => { - switch(status) { - case 'In-Progress': return 'bg-orange-100 text-orange-800 border-orange-200'; - case 'Completed': return 'bg-green-100 text-green-800 border-green-200'; + const getPriorityColor = (priority) => { + switch(priority) { + case 'High': return 'bg-red-100 text-red-800 border-red-200'; + case 'Medium': return 'bg-yellow-100 text-yellow-800 border-yellow-200'; + case 'Low': return 'bg-green-100 text-green-800 border-green-200'; default: return 'bg-gray-100 text-gray-800 border-gray-200'; } }; @@ -142,7 +150,16 @@ function App() { const matchesSearch = task.task_name.toLowerCase().includes(searchTerm.toLowerCase()) || task.description.toLowerCase().includes(searchTerm.toLowerCase()); const matchesStatus = filterStatus === 'All' || task.status === filterStatus; - return matchesSearch && matchesStatus; + const matchesPriority = filterPriority === 'All' || task.priority === filterPriority; + return matchesSearch && matchesStatus && matchesPriority; + }); + + const sortedTasks = [...filteredTasks].sort((a, b) => { + if (sortBy === 'Priority') { + const priorityOrder = { 'High': 0, 'Medium': 1, 'Low': 2 }; + return priorityOrder[a.priority] - priorityOrder[b.priority]; + } + return 0; }); const taskStats = { @@ -228,6 +245,23 @@ function App() { className="w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-transparent text-sm sm:text-base" /> +