ihtesham0345 commited on
Commit
7ebc393
·
0 Parent(s):

Initial clean deploy to Hugging Face

Browse files
.gitignore ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ venv/
2
+ db.sqlite3
3
+ *.pyc
4
+ __pycache__/
5
+ .env
README.md ADDED
Binary file (26 Bytes). View file
 
manage.py ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+ """Django's command-line utility for administrative tasks."""
3
+
4
+ import os
5
+ import sys
6
+
7
+
8
+ def main():
9
+ """Run administrative tasks."""
10
+ os.environ.setdefault("DJANGO_SETTINGS_MODULE", "todo_project.settings")
11
+ try:
12
+ from django.core.management import execute_from_command_line
13
+ except ImportError as exc:
14
+ raise ImportError(
15
+ "Couldn't import Django. Are you sure it's installed and "
16
+ "available on your PYTHONPATH environment variable? Did you "
17
+ "forget to activate a virtual environment?"
18
+ ) from exc
19
+ execute_from_command_line(sys.argv)
20
+
21
+
22
+ if __name__ == "__main__":
23
+ main()
requirements.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ django
2
+ django-todo
3
+ gunicorn
tasks/__init__.py ADDED
File without changes
tasks/admin.py ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ from django.contrib import admin
2
+
3
+ # Register your models here.
4
+ from .models import Task
5
+
6
+ admin.site.register(Task)
tasks/apps.py ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ from django.apps import AppConfig
2
+
3
+
4
+ class TasksConfig(AppConfig):
5
+ default_auto_field = "django.db.models.BigAutoField"
6
+ name = "tasks"
tasks/forms.py ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from django import forms
2
+ from .models import Task
3
+
4
+ class TaskForm(forms.ModelForm):
5
+ class Meta:
6
+ model = Task
7
+ fields = ['title'] # <-- Changed this back to only the title!
8
+ widgets = {
9
+ 'title': forms.TextInput(attrs={
10
+ 'class': 'w-full px-4 py-3 rounded-xl bg-slate-50 border border-slate-200 focus:bg-white focus:ring-2 focus:ring-indigo-500 transition-all outline-none text-slate-700 placeholder-slate-400 shadow-sm',
11
+ 'placeholder': 'What do you need to do?'
12
+ }),
13
+ }
tasks/migrations/0001_initial.py ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Generated by Django 5.2.11 on 2026-02-23 05:46
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ initial = True
9
+
10
+ dependencies = []
11
+
12
+ operations = [
13
+ migrations.CreateModel(
14
+ name="Task",
15
+ fields=[
16
+ (
17
+ "id",
18
+ models.BigAutoField(
19
+ auto_created=True,
20
+ primary_key=True,
21
+ serialize=False,
22
+ verbose_name="ID",
23
+ ),
24
+ ),
25
+ ("title", models.CharField(max_length=200)),
26
+ ("completed", models.BooleanField(default=False)),
27
+ ("created_at", models.DateTimeField(auto_now_add=True)),
28
+ ("updated_at", models.DateTimeField(auto_now=True)),
29
+ ],
30
+ ),
31
+ ]
tasks/migrations/0002_remove_task_updated_at_task_completed_at.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Generated by Django 5.2.11 on 2026-02-23 06:20
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ("tasks", "0001_initial"),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.RemoveField(
14
+ model_name="task",
15
+ name="updated_at",
16
+ ),
17
+ migrations.AddField(
18
+ model_name="task",
19
+ name="completed_at",
20
+ field=models.DateTimeField(blank=True, null=True),
21
+ ),
22
+ ]
tasks/migrations/__init__.py ADDED
File without changes
tasks/models.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from django.db import models
2
+
3
+ # Create your models here.
4
+ from django.db import models
5
+
6
+ class Task(models.Model):
7
+ title = models.CharField(max_length=200)
8
+ completed = models.BooleanField(default=False)
9
+ created_at = models.DateTimeField(auto_now_add=True)
10
+ # NEW: We allow this to be blank because new tasks aren't completed yet!
11
+ completed_at = models.DateTimeField(null=True, blank=True)
12
+
13
+ def __str__(self):
14
+ return self.title
15
+
16
+ from django import forms
17
+ from .models import Task
18
+
19
+ class TaskForm(forms.ModelForm):
20
+ class Meta:
21
+ model = Task
22
+ fields = ['title'] # We only need the user to type the title!
tasks/templates/tasks/base.html ADDED
@@ -0,0 +1,254 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>TaskPro | Intelligence in Organization</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <style>
9
+ :root { --bg-color: #f8fafc; --orb-1: #c084fc; --orb-2: #818cf8; --orb-3: #f472b6; }
10
+ body { background-color: var(--bg-color); transition: background-color 0.5s ease; }
11
+ .orb-1 { background-color: var(--orb-1); transition: background-color 0.5s ease; }
12
+ .orb-2 { background-color: var(--orb-2); transition: background-color 0.5s ease; }
13
+ .orb-3 { background-color: var(--orb-3); transition: background-color 0.5s ease; }
14
+ @keyframes float { 0% { transform: translate(0px, 0px) scale(1); } 33% { transform: translate(30px, -50px) scale(1.1); } 66% { transform: translate(-20px, 20px) scale(0.9); } 100% { transform: translate(0px, 0px) scale(1); } }
15
+ .animate-float { animation: float 10s infinite ease-in-out; }
16
+ .animation-delay-2000 { animation-delay: 2s; } .animation-delay-4000 { animation-delay: 4s; }
17
+
18
+ /* Smooth transition for dropdown */
19
+ .dropdown-animate { transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); }
20
+ </style>
21
+ </head>
22
+ <body class="relative flex flex-col min-h-screen font-sans text-slate-800 selection:bg-indigo-200 selection:text-indigo-900 overflow-x-hidden">
23
+
24
+ <div id="custom-bg-layer" class="fixed inset-0 w-full h-full z-[-2] bg-cover bg-center bg-no-repeat transition-opacity duration-500 opacity-0"></div>
25
+
26
+ <div class="fixed inset-0 w-full h-full z-[-1]" id="orb-container">
27
+ <div class="orb-1 absolute top-[-10%] left-[-10%] w-96 h-96 rounded-full mix-blend-multiply filter blur-[100px] opacity-60 animate-float"></div>
28
+ <div class="orb-2 absolute top-[20%] right-[-5%] w-96 h-96 rounded-full mix-blend-multiply filter blur-[100px] opacity-60 animate-float animation-delay-2000"></div>
29
+ <div class="orb-3 absolute bottom-[-10%] left-[20%] w-96 h-96 rounded-full mix-blend-multiply filter blur-[100px] opacity-60 animate-float animation-delay-4000"></div>
30
+ </div>
31
+
32
+ <header class="sticky top-0 z-50 bg-white/70 backdrop-blur-md border-b border-white/50 shadow-sm py-2 sm:py-0">
33
+ <div class="max-w-6xl mx-auto px-4 sm:px-6 min-h-[4.5rem] flex flex-wrap sm:flex-nowrap items-center justify-between gap-4">
34
+
35
+ <a href="/" class="flex items-center gap-2 cursor-pointer transform hover:scale-105 transition-transform shrink-0">
36
+ <div class="w-8 h-8 rounded-xl bg-gradient-to-br from-indigo-600 to-purple-600 flex items-center justify-center text-white shadow-md">
37
+ <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="3" d="M5 13l4 4L19 7"></path></svg>
38
+ </div>
39
+ <span class="text-xl font-extrabold bg-clip-text text-transparent bg-gradient-to-r from-indigo-700 to-purple-700 tracking-tight">TaskPro</span>
40
+ </a>
41
+
42
+ <div class="order-last sm:order-none w-full sm:w-auto flex-1 flex flex-col items-center justify-center max-w-lg mx-auto">
43
+ <div class="relative w-full">
44
+ <input type="text" id="searchInput" onkeyup="filterTasks()" placeholder="Search your tasks..." class="w-full pl-10 pr-4 py-2 rounded-full bg-white/60 border border-white focus:bg-white focus:ring-2 focus:ring-indigo-400 outline-none transition-all text-sm shadow-sm placeholder-slate-400">
45
+ <svg class="w-4 h-4 absolute left-4 top-2.5 text-slate-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path></svg>
46
+ </div>
47
+ <div class="text-[10px] font-bold text-slate-500 mt-1.5 uppercase tracking-widest" id="current-date-display">
48
+ </div>
49
+ </div>
50
+
51
+ <div class="flex items-center gap-2 sm:gap-4 shrink-0">
52
+
53
+ <button class="relative p-2 text-slate-400 hover:text-indigo-600 transition-colors transform hover:scale-110 group">
54
+ <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9"></path></svg>
55
+ {% if pending_count and pending_count > 0 %}
56
+ <span class="absolute top-1 right-1 flex h-4 w-4 items-center justify-center rounded-full bg-red-500 text-[9px] font-bold text-white shadow-sm ring-2 ring-white animate-pulse">
57
+ {{ pending_count }}
58
+ </span>
59
+ {% endif %}
60
+ </button>
61
+
62
+ <button onclick="toggleThemeModal()" class="flex items-center gap-2 text-sm font-bold text-slate-600 bg-white/80 hover:bg-white px-3 sm:px-4 py-2 rounded-full shadow-sm border border-slate-200 transition-all hover:scale-105">
63
+ 🎨 <span class="hidden sm:inline">Themes</span>
64
+ </button>
65
+
66
+ <div class="relative shrink-0" id="avatar-container">
67
+ <button onclick="toggleAvatarMenu()" class="w-10 h-10 rounded-full bg-slate-200 border-2 border-white shadow-sm overflow-hidden cursor-pointer hover:ring-2 hover:ring-indigo-400 transition-all flex items-center justify-center">
68
+ <img src="https://api.dicebear.com/7.x/avataaars/svg?seed=Felix&backgroundColor=e2e8f0" alt="Profile" class="w-full h-full object-cover">
69
+ </button>
70
+
71
+ <div id="avatar-menu" class="dropdown-animate absolute right-0 mt-3 w-64 bg-white/90 backdrop-blur-xl rounded-2xl shadow-2xl border border-white hidden opacity-0 transform scale-95 origin-top-right z-[100] overflow-hidden">
72
+ <div class="p-5 bg-gradient-to-br from-indigo-50 to-purple-50 border-b border-slate-100">
73
+ <p class="text-sm font-extrabold text-slate-800">Ihta (IAR Soft)</p>
74
+ <p class="text-[11px] text-indigo-600 font-bold uppercase tracking-wide mt-0.5">AI Engineer @ Jabiru Labs</p>
75
+ </div>
76
+ <div class="p-2 space-y-1">
77
+ <a href="/support" class="flex items-center gap-3 px-4 py-2.5 rounded-xl text-sm font-bold text-slate-600 hover:bg-white hover:text-indigo-600 transition-all shadow-sm shadow-transparent hover:shadow-slate-200">
78
+ <span class="text-lg">⚙️</span> Settings
79
+ </a>
80
+ <a href="/privacy" class="flex items-center gap-3 px-4 py-2.5 rounded-xl text-sm font-bold text-slate-600 hover:bg-white hover:text-indigo-600 transition-all shadow-sm shadow-transparent hover:shadow-slate-200">
81
+ <span class="text-lg">🛡️</span> Privacy Control
82
+ </a>
83
+ </div>
84
+ <div class="p-2 border-t border-slate-100 bg-slate-50/50">
85
+ <a href="{% url 'logout' %}" class="w-full flex items-center gap-3 px-4 py-2.5 rounded-xl text-sm font-bold text-red-500 hover:bg-red-50 transition-colors">
86
+ <span class="text-lg">🚪</span> Sign Out
87
+ </a>
88
+ </div>
89
+ </div>
90
+ </div>
91
+ </div>
92
+ </div>
93
+ </header>
94
+
95
+ <div id="theme-modal" class="fixed inset-0 z-[100] bg-slate-900/40 backdrop-blur-sm hidden flex items-center justify-center transition-opacity opacity-0">
96
+ <div class="bg-white/90 backdrop-blur-xl rounded-3xl shadow-2xl p-8 max-w-md w-full mx-4 transform scale-95 transition-transform duration-300 border border-white" id="theme-modal-content">
97
+ <div class="flex justify-between items-center mb-6">
98
+ <h2 class="text-2xl font-extrabold text-slate-800">Choose Theme 🎨</h2>
99
+ <button onclick="toggleThemeModal()" class="text-slate-400 hover:text-red-500 transition-colors">
100
+ <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path></svg>
101
+ </button>
102
+ </div>
103
+ <div class="grid grid-cols-2 gap-4 mb-6">
104
+ <button onclick="setTheme('default')" class="h-24 rounded-xl shadow-inner bg-slate-50 border-2 border-slate-200 hover:border-indigo-500 overflow-hidden relative group">
105
+ <div class="absolute inset-0 opacity-40 bg-gradient-to-br from-purple-400 via-indigo-400 to-pink-400 group-hover:opacity-60 transition-opacity"></div>
106
+ <span class="relative z-10 font-bold text-slate-800 bg-white/80 px-2 py-1 rounded-md text-sm">Lavender Glass</span>
107
+ </button>
108
+ <button onclick="setTheme('ocean')" class="h-24 rounded-xl shadow-inner bg-cyan-50 border-2 border-slate-200 hover:border-cyan-500 overflow-hidden relative group">
109
+ <div class="absolute inset-0 opacity-40 bg-gradient-to-br from-blue-400 via-teal-400 to-cyan-400 group-hover:opacity-60 transition-opacity"></div>
110
+ <span class="relative z-10 font-bold text-slate-800 bg-white/80 px-2 py-1 rounded-md text-sm">Ocean Breeze</span>
111
+ </button>
112
+ <button onclick="setTheme('sunset')" class="h-24 rounded-xl shadow-inner bg-orange-50 border-2 border-slate-200 hover:border-orange-500 overflow-hidden relative group">
113
+ <div class="absolute inset-0 opacity-40 bg-gradient-to-br from-orange-400 via-red-400 to-yellow-400 group-hover:opacity-60 transition-opacity"></div>
114
+ <span class="relative z-10 font-bold text-slate-800 bg-white/80 px-2 py-1 rounded-md text-sm">Sunset Glow</span>
115
+ </button>
116
+ <button onclick="setTheme('forest')" class="h-24 rounded-xl shadow-inner bg-green-50 border-2 border-slate-200 hover:border-emerald-500 overflow-hidden relative group">
117
+ <div class="absolute inset-0 opacity-40 bg-gradient-to-br from-green-400 via-emerald-400 to-teal-400 group-hover:opacity-60 transition-opacity"></div>
118
+ <span class="relative z-10 font-bold text-slate-800 bg-white/80 px-2 py-1 rounded-md text-sm">Enchanted Forest</span>
119
+ </button>
120
+ <button onclick="setTheme('midnight')" class="h-24 rounded-xl shadow-inner bg-slate-900 border-2 border-slate-700 hover:border-purple-500 overflow-hidden relative group col-span-2">
121
+ <div class="absolute inset-0 opacity-40 bg-gradient-to-br from-indigo-900 via-purple-900 to-slate-800 group-hover:opacity-60 transition-opacity"></div>
122
+ <span class="relative z-10 font-bold text-white bg-black/50 px-2 py-1 rounded-md text-sm">Midnight Dark</span>
123
+ </button>
124
+ </div>
125
+ <div class="border-t border-slate-200 pt-6">
126
+ <label class="block text-sm font-bold text-slate-700 mb-2">Or Upload Custom Background 🖼️</label>
127
+ <input type="file" id="custom-image-upload" accept="image/*" class="block w-full text-sm text-slate-500 file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 file:text-sm file:font-semibold file:bg-indigo-50 file:text-indigo-700 hover:file:bg-indigo-100 cursor-pointer">
128
+ </div>
129
+ </div>
130
+ </div>
131
+
132
+ <main class="flex-grow py-8 px-4 sm:py-12 relative z-10">
133
+ {% block content %}{% endblock %}
134
+ </main>
135
+
136
+ <footer class="bg-white/40 backdrop-blur-md border-t border-white/50 mt-auto relative z-10">
137
+ <div class="max-w-5xl mx-auto px-4 py-6 flex flex-col sm:flex-row items-center justify-between gap-4">
138
+ <p class="text-sm text-slate-600 font-medium">© 2026 TaskPro. Built by Ihta <span class="text-red-500">❤️</span> in Django.</p>
139
+ <div class="flex gap-5">
140
+ <a href="{% url 'privacy' %}" class="text-slate-500 hover:text-indigo-700 transition-colors font-medium text-sm">Privacy Policy</a>
141
+ <a href="{% url 'terms' %}" class="text-slate-500 hover:text-indigo-700 transition-colors font-medium text-sm">Terms of Service</a>
142
+ <a href="{% url 'support' %}" class="text-slate-500 hover:text-indigo-700 transition-colors font-medium text-sm">Support</a>
143
+ </div>
144
+ </div>
145
+ </footer>
146
+
147
+ <script>
148
+ // --- 1. AVATAR DROPDOWN ---
149
+ const avatarMenu = document.getElementById('avatar-menu');
150
+ function toggleAvatarMenu() {
151
+ if (avatarMenu.classList.contains('hidden')) {
152
+ avatarMenu.classList.remove('hidden');
153
+ setTimeout(() => { avatarMenu.classList.remove('opacity-0', 'scale-95'); }, 10);
154
+ } else {
155
+ avatarMenu.classList.add('opacity-0', 'scale-95');
156
+ setTimeout(() => { avatarMenu.classList.add('hidden'); }, 200);
157
+ }
158
+ }
159
+ window.addEventListener('click', (e) => {
160
+ if (!document.getElementById('avatar-container').contains(e.target)) {
161
+ avatarMenu.classList.add('opacity-0', 'scale-95');
162
+ setTimeout(() => { avatarMenu.classList.add('hidden'); }, 200);
163
+ }
164
+ });
165
+
166
+ // --- 2. DATE & PROGRESS ---
167
+ window.addEventListener('DOMContentLoaded', () => {
168
+ const dateOptions = { weekday: 'long', month: 'short', day: 'numeric' };
169
+ const today = new Date().toLocaleDateString('en-US', dateOptions);
170
+ const pendingCount = "{{ pending_count|default:'0' }}";
171
+ document.getElementById('current-date-display').innerText = `${today} • ${pendingCount} Tasks Left`;
172
+ });
173
+
174
+ // --- 3. LIVE SEARCH ---
175
+ function filterTasks() {
176
+ let input = document.getElementById('searchInput').value.toLowerCase();
177
+ let taskItems = document.querySelectorAll('.task-item');
178
+ taskItems.forEach(item => {
179
+ let title = item.querySelector('.task-title').innerText.toLowerCase();
180
+ item.style.display = title.includes(input) ? "" : "none";
181
+ });
182
+ }
183
+
184
+ // --- 4. THEMES ---
185
+ const themes = {
186
+ 'default': { bg: '#f8fafc', o1: '#c084fc', o2: '#818cf8', o3: '#f472b6' },
187
+ 'ocean': { bg: '#ecfeff', o1: '#38bdf8', o2: '#2dd4bf', o3: '#22d3ee' },
188
+ 'sunset': { bg: '#fff7ed', o1: '#fb923c', o2: '#f87171', o3: '#facc15' },
189
+ 'forest': { bg: '#f0fdf4', o1: '#4ade80', o2: '#34d399', o3: '#2dd4bf' },
190
+ 'midnight': { bg: '#0f172a', o1: '#312e81', o2: '#4c1d95', o3: '#1e293b' }
191
+ };
192
+ const modal = document.getElementById('theme-modal');
193
+ const modalContent = document.getElementById('theme-modal-content');
194
+ const bgLayer = document.getElementById('custom-bg-layer');
195
+ const orbContainer = document.getElementById('orb-container');
196
+
197
+ function toggleThemeModal() {
198
+ if (modal.classList.contains('hidden')) {
199
+ modal.classList.remove('hidden');
200
+ setTimeout(() => { modal.classList.remove('opacity-0'); modalContent.classList.remove('scale-95'); }, 10);
201
+ } else {
202
+ modal.classList.add('opacity-0', 'scale-95');
203
+ setTimeout(() => { modal.classList.add('hidden'); }, 300);
204
+ }
205
+ }
206
+
207
+ function setTheme(themeName) {
208
+ const t = themes[themeName];
209
+ document.documentElement.style.setProperty('--bg-color', t.bg);
210
+ document.documentElement.style.setProperty('--orb-1', t.o1);
211
+ document.documentElement.style.setProperty('--orb-2', t.o2);
212
+ document.documentElement.style.setProperty('--orb-3', t.o3);
213
+ bgLayer.classList.replace('opacity-100', 'opacity-0');
214
+ orbContainer.style.display = 'block';
215
+ localStorage.setItem('taskpro-theme', themeName);
216
+ localStorage.removeItem('taskpro-custom-img');
217
+ if (!modal.classList.contains('hidden')) toggleThemeModal();
218
+ }
219
+
220
+ document.getElementById('custom-image-upload').addEventListener('change', function(e) {
221
+ const file = e.target.files[0];
222
+ if (file) {
223
+ const reader = new FileReader();
224
+ reader.onload = (event) => {
225
+ const imgData = event.target.result;
226
+ bgLayer.style.backgroundImage = `url(${imgData})`;
227
+ bgLayer.classList.replace('opacity-0', 'opacity-100');
228
+ orbContainer.style.display = 'none';
229
+ localStorage.setItem('taskpro-custom-img', imgData);
230
+ localStorage.setItem('taskpro-theme', 'custom');
231
+ if (!modal.classList.contains('hidden')) toggleThemeModal();
232
+ };
233
+ reader.readAsDataURL(file);
234
+ }
235
+ });
236
+
237
+ window.onload = () => {
238
+ const savedTheme = localStorage.getItem('taskpro-theme');
239
+ const savedImage = localStorage.getItem('taskpro-custom-img');
240
+ if (savedTheme === 'custom' && savedImage) {
241
+ bgLayer.style.backgroundImage = `url(${savedImage})`;
242
+ bgLayer.classList.replace('opacity-0', 'opacity-100');
243
+ orbContainer.style.display = 'none';
244
+ } else if (savedTheme && themes[savedTheme]) {
245
+ const t = themes[savedTheme];
246
+ document.documentElement.style.setProperty('--bg-color', t.bg);
247
+ document.documentElement.style.setProperty('--orb-1', t.o1);
248
+ document.documentElement.style.setProperty('--orb-2', t.o2);
249
+ document.documentElement.style.setProperty('--orb-3', t.o3);
250
+ }
251
+ };
252
+ </script>
253
+ </body>
254
+ </html>
tasks/templates/tasks/delete_task.html ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends 'tasks/base.html' %}
2
+
3
+ {% block content %}
4
+ <div class="w-full max-w-md mx-auto bg-white/70 backdrop-blur-2xl rounded-3xl shadow-[0_8px_30px_rgb(0,0,0,0.12)] overflow-hidden p-8 text-center border-t-4 border-red-500">
5
+
6
+ <div class="w-16 h-16 bg-red-100 text-red-500 rounded-full flex items-center justify-center mx-auto mb-6 text-3xl shadow-inner">
7
+ 🗑️
8
+ </div>
9
+
10
+ <h2 class="text-2xl font-extrabold text-slate-800 mb-2">Delete Task?</h2>
11
+ <p class="text-slate-500 text-sm mb-8 px-2 font-medium">
12
+ Are you sure you want to delete "<span class="font-bold text-slate-700 italic">{{ item }}</span>"? This action cannot be undone.
13
+ </p>
14
+
15
+ <form method="POST" action="">
16
+ {% csrf_token %}
17
+ <div class="flex gap-3">
18
+ <a href="/" class="flex-1 py-3 bg-white/50 hover:bg-white text-slate-700 font-bold rounded-xl transition-all border border-slate-100 shadow-sm">
19
+ Cancel
20
+ </a>
21
+ <button type="submit" class="flex-1 py-3 bg-red-500 hover:bg-red-600 text-white font-bold rounded-xl shadow-lg hover:shadow-red-500/30 transition-all transform hover:-translate-y-0.5 active:scale-95">
22
+ Yes, Delete
23
+ </button>
24
+ </div>
25
+ </form>
26
+ </div>
27
+ {% endblock %}
tasks/templates/tasks/list.html ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends 'tasks/base.html' %}
2
+
3
+ {% block content %}
4
+ <div class="max-w-lg mx-auto bg-white/70 backdrop-blur-2xl rounded-3xl shadow-[0_8px_30px_rgb(0,0,0,0.12)] overflow-hidden transition-all duration-300 border border-white">
5
+
6
+ <div class="bg-gradient-to-r from-indigo-600 via-purple-600 to-indigo-700 p-8 text-center relative overflow-hidden shadow-inner">
7
+ <div class="absolute top-0 left-0 w-full h-full bg-white opacity-10 pattern-dots"></div>
8
+ <h2 class="text-3xl font-extrabold text-white mb-2 relative z-10 tracking-tight">My Tasks</h2>
9
+ <p class="text-indigo-100 text-sm font-medium relative z-10">Stay organized, stay productive </p>
10
+ </div>
11
+
12
+ <div class="p-6 sm:p-8 border-b border-slate-100/50 bg-white/50">
13
+ <form method="POST" action="/" class="flex gap-3 relative">
14
+ {% csrf_token %}
15
+ <div class="flex-1">
16
+ {{ form.title }}
17
+ </div>
18
+ <button type="submit" class="bg-indigo-600 hover:bg-indigo-700 text-white px-6 py-3 rounded-xl font-bold shadow-lg transition-all transform hover:-translate-y-0.5 active:scale-95">
19
+ Add
20
+ </button>
21
+ </form>
22
+ </div>
23
+
24
+ <div class="p-6 sm:p-8 space-y-4 bg-slate-50/30">
25
+ <h3 class="font-bold text-slate-500 uppercase tracking-wider text-xs mb-4 flex items-center gap-2">
26
+ <span class="w-2 h-2 rounded-full bg-amber-400 animate-pulse"></span> Pending Tasks
27
+ </h3>
28
+
29
+ {% for task in pending_tasks %}
30
+ <div class="task-item flex items-center justify-between p-4 bg-white/80 backdrop-blur-sm border border-white rounded-2xl shadow-sm hover:shadow-md hover:-translate-y-0.5 transition-all group">
31
+ <div class="flex items-center gap-4 overflow-hidden flex-1">
32
+ <a href="{% url 'complete_task' task.id %}" class="w-6 h-6 rounded-full border-2 border-slate-300 hover:border-emerald-500 hover:bg-emerald-50 flex items-center justify-center transition-all group/check shrink-0">
33
+ <svg class="w-3.5 h-3.5 text-emerald-500 opacity-0 group-hover/check:opacity-100 transition-opacity" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="3" d="M5 13l4 4L19 7"></path></svg>
34
+ </a>
35
+ <div class="flex-1 truncate pr-2">
36
+ <p class="task-title text-slate-700 font-bold text-[17px] leading-tight truncate group-hover:text-indigo-600 transition-colors">{{ task.title }}</p>
37
+ </div>
38
+ </div>
39
+ <div class="flex gap-2 shrink-0 opacity-100 sm:opacity-0 sm:group-hover:opacity-100 transition-opacity">
40
+ <a href="{% url 'update_task' task.id %}" class="w-8 h-8 flex items-center justify-center bg-slate-100 hover:bg-indigo-50 text-slate-400 hover:text-indigo-600 rounded-lg transition-colors">✏️</a>
41
+ <a href="{% url 'delete_task' task.id %}" class="w-8 h-8 flex items-center justify-center bg-slate-100 hover:bg-red-50 text-slate-400 hover:text-red-500 rounded-lg transition-colors">🗑️</a>
42
+ </div>
43
+ </div>
44
+ {% empty %}
45
+ <div class="text-center py-6 px-4 border-2 border-dashed border-slate-300 rounded-2xl bg-white/40">
46
+ <p class="text-slate-500 text-sm font-medium">No pending tasks right now! </p>
47
+ </div>
48
+ {% endfor %}
49
+ </div>
50
+
51
+ <div class="p-6 sm:p-8 border-t border-slate-100/50 bg-white/60">
52
+ <h3 class="font-bold text-slate-500 uppercase tracking-wider text-xs mb-4 flex items-center gap-2">
53
+ <span class="w-2 h-2 rounded-full bg-emerald-500"></span> Completed History
54
+ </h3>
55
+ <div class="space-y-3">
56
+ {% for task in completed_tasks %}
57
+ <div class="task-item flex items-center justify-between p-3 bg-white/50 border border-white rounded-xl group shadow-sm">
58
+ <div class="flex items-center gap-3 overflow-hidden flex-1">
59
+ <div class="w-6 h-6 rounded-full bg-emerald-500 flex items-center justify-center shrink-0">
60
+ <svg class="w-3.5 h-3.5 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="3" d="M5 13l4 4L19 7"></path></svg>
61
+ </div>
62
+ <div class="truncate pr-2">
63
+ <p class="task-title text-slate-500 line-through font-semibold text-sm truncate">{{ task.title }}</p>
64
+ </div>
65
+ </div>
66
+ <div class="flex gap-1 shrink-0 opacity-100 sm:opacity-0 sm:group-hover:opacity-100 transition-opacity">
67
+ <a href="{% url 'undo_task' task.id %}" class="text-[11px] font-bold text-slate-500 hover:text-indigo-600 px-3 py-1.5 bg-white rounded-md shadow-sm border border-slate-100">Undo</a>
68
+ <a href="{% url 'delete_task' task.id %}" class="text-[11px] font-bold text-slate-500 hover:text-red-500 px-3 py-1.5 bg-white rounded-md shadow-sm border border-slate-100">Del</a>
69
+ </div>
70
+ </div>
71
+ {% empty %}
72
+ <p class="text-slate-500 text-sm italic text-center py-2">Finish a task to see your history!</p>
73
+ {% endfor %}
74
+ </div>
75
+ </div>
76
+ </div>
77
+ {% endblock %}
tasks/templates/tasks/privacy.html ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends 'tasks/base.html' %}
2
+
3
+ {% block content %}
4
+ <div class="max-w-3xl mx-auto bg-white/80 backdrop-blur-xl border border-white rounded-3xl shadow-xl p-8 sm:p-12">
5
+ <h1 class="text-3xl font-extrabold text-indigo-600 mb-6">Privacy Policy</h1>
6
+ <p class="text-slate-600 mb-4">This is a demo To-Do list app. We do not collect or sell your personal data.</p>
7
+ <a href="/" class="inline-block mt-8 font-bold text-white bg-indigo-600 hover:bg-indigo-700 px-6 py-3 rounded-xl transition-colors">
8
+ ⬅️ Back to Dashboard
9
+ </a>
10
+ </div>
11
+ {% endblock %}
tasks/templates/tasks/support.html ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends 'tasks/base.html' %}
2
+
3
+ {% block content %}
4
+ <div class="max-w-3xl mx-auto bg-white/80 backdrop-blur-xl border border-white rounded-3xl shadow-xl p-8 sm:p-12 text-center border-t-4 border-indigo-500">
5
+ <div class="text-5xl mb-4">👋</div>
6
+ <h1 class="text-3xl font-extrabold text-slate-800 mb-4">Need Help?</h1>
7
+ <p class="text-slate-600 mb-8 max-w-md mx-auto">
8
+ If you are experiencing issues with the To-Do app, feel free to reach out. We are always looking to squash bugs and improve the UX!
9
+ </p>
10
+
11
+ <a href="mailto:khanihtesham0332@gmail.com" class="inline-block font-bold text-white bg-indigo-600 hover:bg-indigo-700 px-8 py-4 rounded-xl shadow-lg transition-transform hover:-translate-y-1">
12
+ 📧 Email Support
13
+ </a>
14
+
15
+ <div class="mt-12">
16
+ <a href="/" class="font-bold text-slate-500 hover:text-indigo-600 transition-colors">
17
+ ⬅️ Back to Dashboard
18
+ </a>
19
+ </div>
20
+ </div>
21
+ {% endblock %}
tasks/templates/tasks/terms.html ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends 'tasks/base.html' %}
2
+
3
+ {% block content %}
4
+ <div class="max-w-3xl mx-auto bg-white/80 backdrop-blur-xl border border-white rounded-3xl shadow-xl p-8 sm:p-12">
5
+ <h1 class="text-3xl font-extrabold text-indigo-600 mb-6">Terms of Service</h1>
6
+ <p class="text-slate-600 mb-4">
7
+ Welcome to TaskPro, operated by IAR Soft. By using this application, you agree to organize your tasks efficiently and boost your daily productivity.
8
+ </p>
9
+ <p class="text-slate-600 mb-4">
10
+ These terms are for demonstration purposes as part of this portfolio project.
11
+ </p>
12
+ <a href="/" class="inline-block mt-8 font-bold text-slate-600 bg-white/50 hover:bg-white px-6 py-3 rounded-xl transition-colors shadow-sm">
13
+ ⬅️ Back to Dashboard
14
+ </a>
15
+ </div>
16
+ {% endblock %}
tasks/templates/tasks/update_task.html ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends 'tasks/base.html' %}
2
+
3
+ {% block content %}
4
+ <div class="w-full max-w-md mx-auto bg-white/70 backdrop-blur-2xl rounded-3xl shadow-[0_8px_30px_rgb(0,0,0,0.12)] overflow-hidden p-8 border border-white">
5
+
6
+ <div class="mb-8 text-center">
7
+ <h2 class="text-2xl font-extrabold text-slate-800">Update Task ✏️</h2>
8
+ <p class="text-slate-500 text-sm mt-1 font-medium">Refine your plans</p>
9
+ </div>
10
+
11
+ <form method="POST" action="" class="space-y-6">
12
+ {% csrf_token %}
13
+
14
+ <div class="space-y-2">
15
+ <label class="text-sm font-bold text-slate-700 ml-1">Task Title</label>
16
+ {{ form.title }}
17
+ </div>
18
+
19
+ <div class="pt-4 flex gap-3">
20
+ <a href="/" class="flex-1 text-center py-3 bg-white/50 hover:bg-white text-slate-700 font-bold rounded-xl transition-all shadow-sm border border-slate-100">
21
+ Cancel
22
+ </a>
23
+ <button type="submit" class="flex-1 py-3 bg-indigo-600 hover:bg-indigo-700 text-white font-bold rounded-xl shadow-lg hover:shadow-indigo-500/30 transition-all transform hover:-translate-y-0.5 active:scale-95">
24
+ Save Changes
25
+ </button>
26
+ </div>
27
+ </form>
28
+
29
+ </div>
30
+ {% endblock %}
tasks/tests.py ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ from django.test import TestCase
2
+
3
+ # Create your tests here.
tasks/urls.py ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from django.urls import path
2
+ from . import views
3
+
4
+ urlpatterns = [
5
+ path('', views.index, name='list'), # type: ignore
6
+ path('update_task/<str:pk>/', views.updateTask, name='update_task'),
7
+ path('delete_task/<str:pk>/', views.deleteTask, name='delete_task'),
8
+ path('complete_task/<str:pk>/', views.completeTask, name='complete_task'),
9
+ path('undo_task/<str:pk>/', views.undoTask, name='undo_task'),
10
+ path('privacy/', views.privacyPolicy, name='privacy'),
11
+ path('terms/', views.termsOfService, name='terms'), # <-- New!
12
+ path('support/', views.support, name='support'), # <-- New!
13
+ path('logout/', views.logoutUser, name='logout'),
14
+ ]
tasks/views.py ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from django.shortcuts import render, redirect
2
+ from django.utils import timezone
3
+ from .models import Task
4
+ from .forms import TaskForm
5
+ from django.contrib.auth import logout
6
+ # A quick helper function to grab the pending count for the header
7
+ def get_global_context():
8
+ return {
9
+ 'pending_count': Task.objects.filter(completed=False).count()
10
+ }
11
+
12
+ def index(request):
13
+ pending_tasks = Task.objects.filter(completed=False).order_by('-created_at')
14
+ completed_tasks = Task.objects.filter(completed=True).order_by('-completed_at')
15
+ form = TaskForm()
16
+
17
+ if request.method == 'POST':
18
+ form = TaskForm(request.POST)
19
+ if form.is_valid():
20
+ form.save()
21
+ return redirect('/')
22
+
23
+ context = {'pending_tasks': pending_tasks, 'completed_tasks': completed_tasks, 'form': form}
24
+ context.update(get_global_context()) # Add the bell count!
25
+ return render(request, 'tasks/list.html', context)
26
+
27
+ def updateTask(request, pk):
28
+ task = Task.objects.get(id=pk)
29
+ form = TaskForm(instance=task)
30
+
31
+ if request.method == 'POST':
32
+ form = TaskForm(request.POST, instance=task)
33
+ if form.is_valid():
34
+ form.save()
35
+ return redirect('/')
36
+
37
+ context = {'form': form}
38
+ context.update(get_global_context())
39
+ return render(request, 'tasks/update_task.html', context)
40
+
41
+ def deleteTask(request, pk):
42
+ item = Task.objects.get(id=pk)
43
+ if request.method == 'POST':
44
+ item.delete()
45
+ return redirect('/')
46
+
47
+ context = {'item': item}
48
+ context.update(get_global_context())
49
+ return render(request, 'tasks/delete_task.html', context)
50
+
51
+ def completeTask(request, pk):
52
+ task = Task.objects.get(id=pk)
53
+ task.completed = True
54
+ task.completed_at = timezone.now()
55
+ task.save()
56
+ return redirect('/')
57
+
58
+ def undoTask(request, pk):
59
+ task = Task.objects.get(id=pk)
60
+ task.completed = False
61
+ task.completed_at = None
62
+ task.save()
63
+ return redirect('/')
64
+
65
+ # --- Static Pages ---
66
+ def privacyPolicy(request):
67
+ context = get_global_context()
68
+ return render(request, 'tasks/privacy.html', context)
69
+
70
+ def termsOfService(request):
71
+ context = get_global_context()
72
+ return render(request, 'tasks/terms.html', context)
73
+
74
+ def support(request):
75
+ context = get_global_context()
76
+ return render(request, 'tasks/support.html', context)
77
+
78
+
79
+ def logoutUser(request):
80
+ logout(request)
81
+ return redirect('/') # Or redirect to a login page if you have one
todo_project/__init__.py ADDED
File without changes
todo_project/asgi.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ ASGI config for todo_project project.
3
+
4
+ It exposes the ASGI callable as a module-level variable named ``application``.
5
+
6
+ For more information on this file, see
7
+ https://docs.djangoproject.com/en/5.2/howto/deployment/asgi/
8
+ """
9
+
10
+ import os
11
+
12
+ from django.core.asgi import get_asgi_application
13
+
14
+ os.environ.setdefault("DJANGO_SETTINGS_MODULE", "todo_project.settings")
15
+
16
+ application = get_asgi_application()
todo_project/settings.py ADDED
@@ -0,0 +1,125 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Django settings for todo_project project.
3
+
4
+ Generated by 'django-admin startproject' using Django 5.2.11.
5
+
6
+ For more information on this file, see
7
+ https://docs.djangoproject.com/en/5.2/topics/settings/
8
+
9
+ For the full list of settings and their values, see
10
+ https://docs.djangoproject.com/en/5.2/ref/settings/
11
+ """
12
+
13
+ from pathlib import Path
14
+
15
+ # Build paths inside the project like this: BASE_DIR / 'subdir'.
16
+ BASE_DIR = Path(__file__).resolve().parent.parent
17
+
18
+
19
+ # Quick-start development settings - unsuitable for production
20
+ # See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/
21
+
22
+ # SECURITY WARNING: keep the secret key used in production secret!
23
+ SECRET_KEY = "django-insecure-=ob5++5d=xr84)fsaqj$2wexu_)b*mp56s&#$x1un^n4q_$c7$"
24
+
25
+ # SECURITY WARNING: don't run with debug turned on in production!
26
+ DEBUG = True
27
+
28
+ # Allow all hosts so Hugging Face can display the app
29
+ ALLOWED_HOSTS = ['*']
30
+
31
+ # Required for the styles (Tailwind CDN) to work through the HF frame
32
+ CSRF_TRUSTED_ORIGINS = ['https://*.hf.space']
33
+ # Application definition
34
+
35
+ INSTALLED_APPS = [
36
+ "django.contrib.admin",
37
+ "django.contrib.auth",
38
+ "django.contrib.contenttypes",
39
+ "django.contrib.sessions",
40
+ "django.contrib.messages",
41
+ "django.contrib.staticfiles",
42
+ 'tasks',
43
+ ]
44
+
45
+ MIDDLEWARE = [
46
+ "django.middleware.security.SecurityMiddleware",
47
+ "django.contrib.sessions.middleware.SessionMiddleware",
48
+ "django.middleware.common.CommonMiddleware",
49
+ "django.middleware.csrf.CsrfViewMiddleware",
50
+ "django.contrib.auth.middleware.AuthenticationMiddleware",
51
+ "django.contrib.messages.middleware.MessageMiddleware",
52
+ "django.middleware.clickjacking.XFrameOptionsMiddleware",
53
+ ]
54
+
55
+ ROOT_URLCONF = "todo_project.urls"
56
+
57
+ TEMPLATES = [
58
+ {
59
+ "BACKEND": "django.template.backends.django.DjangoTemplates",
60
+ "DIRS": [],
61
+ "APP_DIRS": True,
62
+ "OPTIONS": {
63
+ "context_processors": [
64
+ "django.template.context_processors.request",
65
+ "django.contrib.auth.context_processors.auth",
66
+ "django.contrib.messages.context_processors.messages",
67
+ ],
68
+ },
69
+ },
70
+ ]
71
+
72
+ WSGI_APPLICATION = "todo_project.wsgi.application"
73
+
74
+
75
+ # Database
76
+ # https://docs.djangoproject.com/en/5.2/ref/settings/#databases
77
+
78
+ DATABASES = {
79
+ "default": {
80
+ "ENGINE": "django.db.backends.sqlite3",
81
+ "NAME": BASE_DIR / "db.sqlite3",
82
+ }
83
+ }
84
+
85
+
86
+ # Password validation
87
+ # https://docs.djangoproject.com/en/5.2/ref/settings/#auth-password-validators
88
+
89
+ AUTH_PASSWORD_VALIDATORS = [
90
+ {
91
+ "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
92
+ },
93
+ {
94
+ "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
95
+ },
96
+ {
97
+ "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
98
+ },
99
+ {
100
+ "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
101
+ },
102
+ ]
103
+
104
+
105
+ # Internationalization
106
+ # https://docs.djangoproject.com/en/5.2/topics/i18n/
107
+
108
+ LANGUAGE_CODE = "en-us"
109
+
110
+ TIME_ZONE = "UTC"
111
+
112
+ USE_I18N = True
113
+
114
+ USE_TZ = True
115
+
116
+
117
+ # Static files (CSS, JavaScript, Images)
118
+ # https://docs.djangoproject.com/en/5.2/howto/static-files/
119
+
120
+ STATIC_URL = "static/"
121
+
122
+ # Default primary key field type
123
+ # https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field
124
+
125
+ DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
todo_project/urls.py ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ URL configuration for todo_project project.
3
+
4
+ The `urlpatterns` list routes URLs to views. For more information please see:
5
+ https://docs.djangoproject.com/en/5.2/topics/http/urls/
6
+ Examples:
7
+ Function views
8
+ 1. Add an import: from my_app import views
9
+ 2. Add a URL to urlpatterns: path('', views.home, name='home')
10
+ Class-based views
11
+ 1. Add an import: from other_app.views import Home
12
+ 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
13
+ Including another URLconf
14
+ 1. Import the include() function: from django.urls import include, path
15
+ 2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
16
+ """
17
+
18
+ from django.contrib import admin
19
+ from django.urls import path , include
20
+
21
+ urlpatterns = [
22
+ path("admin/", admin.site.urls),
23
+ path('', include('tasks.urls')),
24
+ ]
todo_project/wsgi.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ WSGI config for todo_project project.
3
+
4
+ It exposes the WSGI callable as a module-level variable named ``application``.
5
+
6
+ For more information on this file, see
7
+ https://docs.djangoproject.com/en/5.2/howto/deployment/wsgi/
8
+ """
9
+
10
+ import os
11
+
12
+ from django.core.wsgi import get_wsgi_application
13
+
14
+ os.environ.setdefault("DJANGO_SETTINGS_MODULE", "todo_project.settings")
15
+
16
+ application = get_wsgi_application()