federi commited on
Commit
3b10dbb
·
verified ·
1 Parent(s): bdfc7d7

Add 3 files

Browse files
Files changed (3) hide show
  1. README.md +6 -4
  2. index.html +1331 -19
  3. prompts.txt +1 -0
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Taskflow
3
- emoji:
4
  colorFrom: yellow
5
- colorTo: pink
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: taskflow
3
+ emoji: 🐳
4
  colorFrom: yellow
5
+ colorTo: blue
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,1331 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="it">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>TaskFlow - Gestione Attività</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
+ <style>
10
+ /* Custom scrollbar */
11
+ ::-webkit-scrollbar {
12
+ width: 8px;
13
+ }
14
+ ::-webkit-scrollbar-track {
15
+ background: #f1f1f1;
16
+ }
17
+ ::-webkit-scrollbar-thumb {
18
+ background: #888;
19
+ border-radius: 4px;
20
+ }
21
+ ::-webkit-scrollbar-thumb:hover {
22
+ background: #555;
23
+ }
24
+
25
+ /* Animation for task completion */
26
+ @keyframes fadeIn {
27
+ from { opacity: 0; transform: translateY(10px); }
28
+ to { opacity: 1; transform: translateY(0); }
29
+ }
30
+
31
+ .task-item {
32
+ animation: fadeIn 0.3s ease-out forwards;
33
+ }
34
+
35
+ /* Calendar day highlight */
36
+ .current-day {
37
+ background-color: #3b82f6;
38
+ color: white;
39
+ border-radius: 50%;
40
+ }
41
+ </style>
42
+ </head>
43
+ <body class="bg-gray-100 font-sans">
44
+ <div class="flex h-screen overflow-hidden">
45
+ <!-- Sidebar -->
46
+ <div class="hidden md:flex md:flex-shrink-0">
47
+ <div class="flex flex-col w-64 bg-indigo-700 text-white">
48
+ <div class="flex items-center justify-center h-16 px-4">
49
+ <div class="flex items-center">
50
+ <i class="fas fa-tasks text-2xl mr-2"></i>
51
+ <span class="text-xl font-semibold">TaskFlow</span>
52
+ </div>
53
+ </div>
54
+ <div class="flex flex-col flex-grow px-4 py-4 overflow-y-auto">
55
+ <div class="space-y-1">
56
+ <button id="all-tasks-btn" class="flex items-center w-full px-4 py-2 text-sm font-medium text-white bg-indigo-800 rounded-md group">
57
+ <i class="fas fa-list mr-3"></i>
58
+ Tutte le attività
59
+ </button>
60
+ <button id="today-tasks-btn" class="flex items-center w-full px-4 py-2 text-sm font-medium text-indigo-100 hover:text-white hover:bg-indigo-600 rounded-md group">
61
+ <i class="fas fa-calendar-day mr-3"></i>
62
+ Oggi
63
+ </button>
64
+ <button id="upcoming-tasks-btn" class="flex items-center w-full px-4 py-2 text-sm font-medium text-indigo-100 hover:text-white hover:bg-indigo-600 rounded-md group">
65
+ <i class="fas fa-calendar-week mr-3"></i>
66
+ Prossimi
67
+ </button>
68
+ <button id="important-tasks-btn" class="flex items-center w-full px-4 py-2 text-sm font-medium text-indigo-100 hover:text-white hover:bg-indigo-600 rounded-md group">
69
+ <i class="fas fa-star mr-3"></i>
70
+ Importanti
71
+ </button>
72
+ <button id="completed-tasks-btn" class="flex items-center w-full px-4 py-2 text-sm font-medium text-indigo-100 hover:text-white hover:bg-indigo-600 rounded-md group">
73
+ <i class="fas fa-check-circle mr-3"></i>
74
+ Completate
75
+ </button>
76
+ </div>
77
+
78
+ <div class="mt-8">
79
+ <h3 class="px-4 text-xs font-semibold text-indigo-200 uppercase tracking-wider">Categorie</h3>
80
+ <div class="mt-2 space-y-1" id="categories-list">
81
+ <!-- Categories will be added dynamically -->
82
+ </div>
83
+ <div class="mt-2">
84
+ <button id="add-category-btn" class="flex items-center w-full px-4 py-2 text-sm font-medium text-indigo-100 hover:text-white hover:bg-indigo-600 rounded-md group">
85
+ <i class="fas fa-plus mr-3"></i>
86
+ Aggiungi categoria
87
+ </button>
88
+ </div>
89
+ </div>
90
+
91
+ <div class="mt-auto mb-4">
92
+ <div class="flex items-center px-4 py-2 text-sm text-indigo-200">
93
+ <i class="fas fa-moon mr-3"></i>
94
+ Modalità scura
95
+ <label class="ml-auto relative inline-flex items-center cursor-pointer">
96
+ <input type="checkbox" id="dark-mode-toggle" class="sr-only peer">
97
+ <div class="w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-indigo-300 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-indigo-600"></div>
98
+ </label>
99
+ </div>
100
+ </div>
101
+ </div>
102
+ </div>
103
+ </div>
104
+
105
+ <!-- Mobile sidebar -->
106
+ <div class="md:hidden fixed bottom-0 left-0 right-0 bg-white shadow-lg z-10">
107
+ <div class="flex justify-around">
108
+ <button id="mobile-all-tasks" class="p-4 text-indigo-600">
109
+ <i class="fas fa-list text-xl"></i>
110
+ </button>
111
+ <button id="mobile-today-tasks" class="p-4 text-gray-500">
112
+ <i class="fas fa-calendar-day text-xl"></i>
113
+ </button>
114
+ <button id="mobile-add-task" class="p-4 text-gray-500">
115
+ <i class="fas fa-plus-circle text-2xl text-indigo-600"></i>
116
+ </button>
117
+ <button id="mobile-upcoming-tasks" class="p-4 text-gray-500">
118
+ <i class="fas fa-calendar-week text-xl"></i>
119
+ </button>
120
+ <button id="mobile-important-tasks" class="p-4 text-gray-500">
121
+ <i class="fas fa-star text-xl"></i>
122
+ </button>
123
+ </div>
124
+ </div>
125
+
126
+ <!-- Main content -->
127
+ <div class="flex flex-col flex-1 overflow-hidden">
128
+ <!-- Top navigation -->
129
+ <div class="flex items-center justify-between h-16 px-4 bg-white border-b border-gray-200">
130
+ <div class="flex items-center">
131
+ <button id="sidebar-toggle" class="md:hidden text-gray-500 focus:outline-none">
132
+ <i class="fas fa-bars text-xl"></i>
133
+ </button>
134
+ <h1 id="current-view" class="ml-4 text-lg font-semibold text-gray-900">Tutte le attività</h1>
135
+ </div>
136
+ <div class="flex items-center space-x-4">
137
+ <div class="relative">
138
+ <button id="search-btn" class="p-1 text-gray-500 hover:text-gray-700">
139
+ <i class="fas fa-search"></i>
140
+ </button>
141
+ <div id="search-container" class="hidden absolute right-0 mt-2 w-64 bg-white rounded-md shadow-lg z-10">
142
+ <input type="text" id="search-input" class="w-full px-4 py-2 border rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500" placeholder="Cerca attività...">
143
+ </div>
144
+ </div>
145
+ <button id="add-task-btn" class="flex items-center px-4 py-2 bg-indigo-600 text-white rounded-md hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500">
146
+ <i class="fas fa-plus mr-2"></i>
147
+ <span class="hidden md:inline">Nuova attività</span>
148
+ </button>
149
+ </div>
150
+ </div>
151
+
152
+ <!-- Content area -->
153
+ <div class="flex flex-1 overflow-hidden">
154
+ <!-- Task list -->
155
+ <div class="flex-1 overflow-y-auto p-4">
156
+ <div id="task-list-container">
157
+ <div id="no-tasks-message" class="flex flex-col items-center justify-center h-64 text-gray-500">
158
+ <i class="fas fa-tasks text-5xl mb-4"></i>
159
+ <p class="text-xl">Nessuna attività trovata</p>
160
+ <button id="add-first-task-btn" class="mt-4 px-4 py-2 bg-indigo-600 text-white rounded-md hover:bg-indigo-700">
161
+ Aggiungi la tua prima attività
162
+ </button>
163
+ </div>
164
+ <div id="task-list" class="space-y-3">
165
+ <!-- Tasks will be added dynamically -->
166
+ </div>
167
+ </div>
168
+ </div>
169
+
170
+ <!-- Calendar and task details (hidden on mobile) -->
171
+ <div class="hidden lg:flex lg:flex-col w-80 border-l border-gray-200 bg-white">
172
+ <div class="p-4 border-b border-gray-200">
173
+ <h2 class="text-lg font-semibold">Calendario</h2>
174
+ <div class="mt-4">
175
+ <div class="flex justify-between items-center mb-4">
176
+ <button id="prev-month" class="p-1 rounded-full hover:bg-gray-100">
177
+ <i class="fas fa-chevron-left"></i>
178
+ </button>
179
+ <h3 id="current-month" class="font-medium">Settembre 2023</h3>
180
+ <button id="next-month" class="p-1 rounded-full hover:bg-gray-100">
181
+ <i class="fas fa-chevron-right"></i>
182
+ </button>
183
+ </div>
184
+ <div id="calendar" class="grid grid-cols-7 gap-1">
185
+ <!-- Calendar days will be added dynamically -->
186
+ </div>
187
+ </div>
188
+ </div>
189
+
190
+ <div class="flex-1 overflow-y-auto p-4">
191
+ <h2 class="text-lg font-semibold mb-4">Dettagli attività</h2>
192
+ <div id="task-details" class="hidden">
193
+ <h3 id="task-detail-title" class="text-xl font-semibold mb-2"></h3>
194
+ <div class="flex items-center text-sm text-gray-500 mb-4">
195
+ <i class="far fa-calendar-alt mr-2"></i>
196
+ <span id="task-detail-date"></span>
197
+ </div>
198
+ <div class="mb-4">
199
+ <span id="task-detail-category" class="inline-block px-2 py-1 text-xs font-semibold rounded-full"></span>
200
+ </div>
201
+ <p id="task-detail-description" class="text-gray-700 mb-4"></p>
202
+ <div class="flex space-x-2">
203
+ <button id="edit-task-btn" class="px-4 py-2 bg-indigo-600 text-white rounded-md hover:bg-indigo-700">
204
+ Modifica
205
+ </button>
206
+ <button id="delete-task-btn" class="px-4 py-2 bg-red-600 text-white rounded-md hover:bg-red-700">
207
+ Elimina
208
+ </button>
209
+ </div>
210
+ </div>
211
+ <div id="no-task-selected" class="flex flex-col items-center justify-center h-64 text-gray-500">
212
+ <i class="fas fa-info-circle text-5xl mb-4"></i>
213
+ <p class="text-center">Seleziona un'attività per visualizzare i dettagli</p>
214
+ </div>
215
+ </div>
216
+ </div>
217
+ </div>
218
+ </div>
219
+ </div>
220
+
221
+ <!-- Add/Edit Task Modal -->
222
+ <div id="task-modal" class="fixed inset-0 z-50 hidden overflow-y-auto">
223
+ <div class="flex items-center justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
224
+ <div class="fixed inset-0 transition-opacity" aria-hidden="true">
225
+ <div class="absolute inset-0 bg-gray-500 opacity-75"></div>
226
+ </div>
227
+
228
+ <span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">&#8203;</span>
229
+
230
+ <div class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full">
231
+ <div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
232
+ <div class="sm:flex sm:items-start">
233
+ <div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left w-full">
234
+ <h3 id="modal-title" class="text-lg leading-6 font-medium text-gray-900 mb-4">
235
+ Nuova attività
236
+ </h3>
237
+ <form id="task-form" class="space-y-4">
238
+ <input type="hidden" id="task-id">
239
+ <div>
240
+ <label for="task-title" class="block text-sm font-medium text-gray-700">Titolo</label>
241
+ <input type="text" id="task-title" class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500" required>
242
+ </div>
243
+ <div>
244
+ <label for="task-description" class="block text-sm font-medium text-gray-700">Descrizione</label>
245
+ <textarea id="task-description" rows="3" class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500"></textarea>
246
+ </div>
247
+ <div class="grid grid-cols-2 gap-4">
248
+ <div>
249
+ <label for="task-date" class="block text-sm font-medium text-gray-700">Data</label>
250
+ <input type="date" id="task-date" class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500">
251
+ </div>
252
+ <div>
253
+ <label for="task-time" class="block text-sm font-medium text-gray-700">Ora</label>
254
+ <input type="time" id="task-time" class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500">
255
+ </div>
256
+ </div>
257
+ <div>
258
+ <label for="task-category" class="block text-sm font-medium text-gray-700">Categoria</label>
259
+ <div class="flex mt-1">
260
+ <select id="task-category" class="flex-1 border border-gray-300 rounded-l-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500">
261
+ <option value="">Nessuna categoria</option>
262
+ </select>
263
+ <button type="button" id="new-category-btn" class="inline-flex items-center px-3 py-2 border border-l-0 border-gray-300 bg-gray-50 text-gray-500 hover:bg-gray-100 rounded-r-md">
264
+ <i class="fas fa-plus"></i>
265
+ </button>
266
+ </div>
267
+ </div>
268
+ <div class="flex items-center">
269
+ <input type="checkbox" id="task-important" class="h-4 w-4 text-indigo-600 focus:ring-indigo-500 border-gray-300 rounded">
270
+ <label for="task-important" class="ml-2 block text-sm text-gray-700">Contrassegna come importante</label>
271
+ </div>
272
+ </form>
273
+ </div>
274
+ </div>
275
+ </div>
276
+ <div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
277
+ <button type="button" id="save-task-btn" class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-indigo-600 text-base font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:ml-3 sm:w-auto sm:text-sm">
278
+ Salva
279
+ </button>
280
+ <button type="button" id="cancel-task-btn" class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm">
281
+ Annulla
282
+ </button>
283
+ </div>
284
+ </div>
285
+ </div>
286
+ </div>
287
+
288
+ <!-- Add Category Modal -->
289
+ <div id="category-modal" class="fixed inset-0 z-50 hidden overflow-y-auto">
290
+ <div class="flex items-center justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
291
+ <div class="fixed inset-0 transition-opacity" aria-hidden="true">
292
+ <div class="absolute inset-0 bg-gray-500 opacity-75"></div>
293
+ </div>
294
+
295
+ <span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">&#8203;</span>
296
+
297
+ <div class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-md sm:w-full">
298
+ <div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
299
+ <div class="sm:flex sm:items-start">
300
+ <div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left w-full">
301
+ <h3 class="text-lg leading-6 font-medium text-gray-900 mb-4">
302
+ Nuova categoria
303
+ </h3>
304
+ <form id="category-form" class="space-y-4">
305
+ <div>
306
+ <label for="category-name" class="block text-sm font-medium text-gray-700">Nome categoria</label>
307
+ <input type="text" id="category-name" class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500" required>
308
+ </div>
309
+ <div>
310
+ <label for="category-color" class="block text-sm font-medium text-gray-700">Colore</label>
311
+ <select id="category-color" class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500">
312
+ <option value="bg-red-500 text-red-100">Rosso</option>
313
+ <option value="bg-blue-500 text-blue-100">Blu</option>
314
+ <option value="bg-green-500 text-green-100">Verde</option>
315
+ <option value="bg-yellow-500 text-yellow-100">Giallo</option>
316
+ <option value="bg-purple-500 text-purple-100">Viola</option>
317
+ <option value="bg-pink-500 text-pink-100">Rosa</option>
318
+ <option value="bg-indigo-500 text-indigo-100">Indaco</option>
319
+ <option value="bg-gray-500 text-gray-100">Grigio</option>
320
+ </select>
321
+ </div>
322
+ </form>
323
+ </div>
324
+ </div>
325
+ </div>
326
+ <div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
327
+ <button type="button" id="save-category-btn" class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-indigo-600 text-base font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:ml-3 sm:w-auto sm:text-sm">
328
+ Salva
329
+ </button>
330
+ <button type="button" id="cancel-category-btn" class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm">
331
+ Annulla
332
+ </button>
333
+ </div>
334
+ </div>
335
+ </div>
336
+ </div>
337
+
338
+ <script>
339
+ // State management
340
+ const state = {
341
+ tasks: [],
342
+ categories: [
343
+ { id: 1, name: "Lavoro", color: "bg-blue-500 text-blue-100" },
344
+ { id: 2, name: "Personale", color: "bg-green-500 text-green-100" },
345
+ { id: 3, name: "Studio", color: "bg-purple-500 text-purple-100" }
346
+ ],
347
+ currentView: 'all',
348
+ selectedTask: null,
349
+ currentMonth: new Date().getMonth(),
350
+ currentYear: new Date().getFullYear(),
351
+ darkMode: false
352
+ };
353
+
354
+ // DOM Elements
355
+ const elements = {
356
+ // Sidebar
357
+ sidebarToggle: document.getElementById('sidebar-toggle'),
358
+
359
+ // Views
360
+ currentView: document.getElementById('current-view'),
361
+ allTasksBtn: document.getElementById('all-tasks-btn'),
362
+ todayTasksBtn: document.getElementById('today-tasks-btn'),
363
+ upcomingTasksBtn: document.getElementById('upcoming-tasks-btn'),
364
+ importantTasksBtn: document.getElementById('important-tasks-btn'),
365
+ completedTasksBtn: document.getElementById('completed-tasks-btn'),
366
+
367
+ // Mobile views
368
+ mobileAllTasks: document.getElementById('mobile-all-tasks'),
369
+ mobileTodayTasks: document.getElementById('mobile-today-tasks'),
370
+ mobileUpcomingTasks: document.getElementById('mobile-upcoming-tasks'),
371
+ mobileImportantTasks: document.getElementById('mobile-important-tasks'),
372
+ mobileAddTask: document.getElementById('mobile-add-task'),
373
+
374
+ // Task list
375
+ taskListContainer: document.getElementById('task-list-container'),
376
+ noTasksMessage: document.getElementById('no-tasks-message'),
377
+ taskList: document.getElementById('task-list'),
378
+ addFirstTaskBtn: document.getElementById('add-first-task-btn'),
379
+
380
+ // Task details
381
+ taskDetails: document.getElementById('task-details'),
382
+ noTaskSelected: document.getElementById('no-task-selected'),
383
+ taskDetailTitle: document.getElementById('task-detail-title'),
384
+ taskDetailDate: document.getElementById('task-detail-date'),
385
+ taskDetailCategory: document.getElementById('task-detail-category'),
386
+ taskDetailDescription: document.getElementById('task-detail-description'),
387
+ editTaskBtn: document.getElementById('edit-task-btn'),
388
+ deleteTaskBtn: document.getElementById('delete-task-btn'),
389
+
390
+ // Calendar
391
+ calendar: document.getElementById('calendar'),
392
+ currentMonthDisplay: document.getElementById('current-month'),
393
+ prevMonth: document.getElementById('prev-month'),
394
+ nextMonth: document.getElementById('next-month'),
395
+
396
+ // Search
397
+ searchBtn: document.getElementById('search-btn'),
398
+ searchContainer: document.getElementById('search-container'),
399
+ searchInput: document.getElementById('search-input'),
400
+
401
+ // Add task
402
+ addTaskBtn: document.getElementById('add-task-btn'),
403
+
404
+ // Task modal
405
+ taskModal: document.getElementById('task-modal'),
406
+ modalTitle: document.getElementById('modal-title'),
407
+ taskForm: document.getElementById('task-form'),
408
+ taskId: document.getElementById('task-id'),
409
+ taskTitle: document.getElementById('task-title'),
410
+ taskDescription: document.getElementById('task-description'),
411
+ taskDate: document.getElementById('task-date'),
412
+ taskTime: document.getElementById('task-time'),
413
+ taskCategory: document.getElementById('task-category'),
414
+ taskImportant: document.getElementById('task-important'),
415
+ newCategoryBtn: document.getElementById('new-category-btn'),
416
+ saveTaskBtn: document.getElementById('save-task-btn'),
417
+ cancelTaskBtn: document.getElementById('cancel-task-btn'),
418
+
419
+ // Categories
420
+ categoriesList: document.getElementById('categories-list'),
421
+ addCategoryBtn: document.getElementById('add-category-btn'),
422
+
423
+ // Category modal
424
+ categoryModal: document.getElementById('category-modal'),
425
+ categoryForm: document.getElementById('category-form'),
426
+ categoryName: document.getElementById('category-name'),
427
+ categoryColor: document.getElementById('category-color'),
428
+ saveCategoryBtn: document.getElementById('save-category-btn'),
429
+ cancelCategoryBtn: document.getElementById('cancel-category-btn'),
430
+
431
+ // Dark mode
432
+ darkModeToggle: document.getElementById('dark-mode-toggle')
433
+ };
434
+
435
+ // Initialize the app
436
+ function init() {
437
+ // Load sample tasks if none exist
438
+ if (state.tasks.length === 0) {
439
+ loadSampleTasks();
440
+ }
441
+
442
+ // Set up event listeners
443
+ setupEventListeners();
444
+
445
+ // Render initial views
446
+ renderCategories();
447
+ renderTaskCategories();
448
+ renderCalendar();
449
+ renderTasks();
450
+
451
+ // Set current date in date picker
452
+ const today = new Date();
453
+ const formattedDate = today.toISOString().split('T')[0];
454
+ elements.taskDate.value = formattedDate;
455
+
456
+ // Check for dark mode preference
457
+ checkDarkModePreference();
458
+ }
459
+
460
+ // Load sample tasks
461
+ function loadSampleTasks() {
462
+ const sampleTasks = [
463
+ {
464
+ id: 1,
465
+ title: "Completare il progetto TaskFlow",
466
+ description: "Implementare tutte le funzionalità principali del task manager",
467
+ date: "2023-09-15",
468
+ time: "15:00",
469
+ category: 1,
470
+ important: true,
471
+ completed: false
472
+ },
473
+ {
474
+ id: 2,
475
+ title: "Fare la spesa settimanale",
476
+ description: "Acquistare frutta, verdura e altri generi alimentari",
477
+ date: "2023-09-10",
478
+ time: "10:00",
479
+ category: 2,
480
+ important: false,
481
+ completed: false
482
+ },
483
+ {
484
+ id: 3,
485
+ title: "Studiare per l'esame di JavaScript",
486
+ description: "Rivedere i concetti avanzati di JavaScript e fare esercizi pratici",
487
+ date: "2023-09-20",
488
+ time: "14:00",
489
+ category: 3,
490
+ important: true,
491
+ completed: false
492
+ },
493
+ {
494
+ id: 4,
495
+ title: "Incontrare il team di sviluppo",
496
+ description: "Discutere i progressi del progetto e pianificare le prossime attività",
497
+ date: "2023-09-12",
498
+ time: "09:30",
499
+ category: 1,
500
+ important: true,
501
+ completed: false
502
+ },
503
+ {
504
+ id: 5,
505
+ title: "Andare in palestra",
506
+ description: "Allenamento completo di 1 ora",
507
+ date: "2023-09-08",
508
+ time: "18:00",
509
+ category: 2,
510
+ important: false,
511
+ completed: true
512
+ }
513
+ ];
514
+
515
+ state.tasks = sampleTasks;
516
+ }
517
+
518
+ // Set up event listeners
519
+ function setupEventListeners() {
520
+ // Sidebar toggle
521
+ elements.sidebarToggle.addEventListener('click', toggleSidebar);
522
+
523
+ // View buttons
524
+ elements.allTasksBtn.addEventListener('click', () => switchView('all'));
525
+ elements.todayTasksBtn.addEventListener('click', () => switchView('today'));
526
+ elements.upcomingTasksBtn.addEventListener('click', () => switchView('upcoming'));
527
+ elements.importantTasksBtn.addEventListener('click', () => switchView('important'));
528
+ elements.completedTasksBtn.addEventListener('click', () => switchView('completed'));
529
+
530
+ // Mobile view buttons
531
+ elements.mobileAllTasks.addEventListener('click', () => switchView('all'));
532
+ elements.mobileTodayTasks.addEventListener('click', () => switchView('today'));
533
+ elements.mobileUpcomingTasks.addEventListener('click', () => switchView('upcoming'));
534
+ elements.mobileImportantTasks.addEventListener('click', () => switchView('important'));
535
+ elements.mobileAddTask.addEventListener('click', openAddTaskModal);
536
+
537
+ // Add task buttons
538
+ elements.addTaskBtn.addEventListener('click', openAddTaskModal);
539
+ elements.addFirstTaskBtn.addEventListener('click', openAddTaskModal);
540
+
541
+ // Task modal
542
+ elements.saveTaskBtn.addEventListener('click', saveTask);
543
+ elements.cancelTaskBtn.addEventListener('click', closeTaskModal);
544
+ elements.newCategoryBtn.addEventListener('click', openAddCategoryModal);
545
+
546
+ // Category modal
547
+ elements.addCategoryBtn.addEventListener('click', openAddCategoryModal);
548
+ elements.saveCategoryBtn.addEventListener('click', saveCategory);
549
+ elements.cancelCategoryBtn.addEventListener('click', closeCategoryModal);
550
+
551
+ // Search
552
+ elements.searchBtn.addEventListener('click', toggleSearch);
553
+ elements.searchInput.addEventListener('input', handleSearch);
554
+
555
+ // Calendar navigation
556
+ elements.prevMonth.addEventListener('click', goToPreviousMonth);
557
+ elements.nextMonth.addEventListener('click', goToNextMonth);
558
+
559
+ // Dark mode toggle
560
+ elements.darkModeToggle.addEventListener('change', toggleDarkMode);
561
+ }
562
+
563
+ // Toggle sidebar on mobile
564
+ function toggleSidebar() {
565
+ const sidebar = document.querySelector('.md\\:hidden');
566
+ if (sidebar) {
567
+ sidebar.classList.toggle('hidden');
568
+ }
569
+ }
570
+
571
+ // Switch between views
572
+ function switchView(view) {
573
+ state.currentView = view;
574
+
575
+ // Update active button in sidebar
576
+ updateActiveViewButton();
577
+
578
+ // Update current view title
579
+ updateViewTitle();
580
+
581
+ // Render tasks for the selected view
582
+ renderTasks();
583
+
584
+ // Close search if open
585
+ elements.searchContainer.classList.add('hidden');
586
+ }
587
+
588
+ // Update active view button in sidebar
589
+ function updateActiveViewButton() {
590
+ // Reset all buttons
591
+ const viewButtons = [
592
+ elements.allTasksBtn,
593
+ elements.todayTasksBtn,
594
+ elements.upcomingTasksBtn,
595
+ elements.importantTasksBtn,
596
+ elements.completedTasksBtn
597
+ ];
598
+
599
+ viewButtons.forEach(button => {
600
+ button.classList.remove('bg-indigo-800', 'text-white');
601
+ button.classList.add('text-indigo-100', 'hover:text-white', 'hover:bg-indigo-600');
602
+ });
603
+
604
+ // Set active button
605
+ let activeButton;
606
+ switch (state.currentView) {
607
+ case 'all':
608
+ activeButton = elements.allTasksBtn;
609
+ break;
610
+ case 'today':
611
+ activeButton = elements.todayTasksBtn;
612
+ break;
613
+ case 'upcoming':
614
+ activeButton = elements.upcomingTasksBtn;
615
+ break;
616
+ case 'important':
617
+ activeButton = elements.importantTasksBtn;
618
+ break;
619
+ case 'completed':
620
+ activeButton = elements.completedTasksBtn;
621
+ break;
622
+ }
623
+
624
+ if (activeButton) {
625
+ activeButton.classList.remove('text-indigo-100', 'hover:text-white', 'hover:bg-indigo-600');
626
+ activeButton.classList.add('bg-indigo-800', 'text-white');
627
+ }
628
+
629
+ // Update mobile buttons
630
+ const mobileButtons = [
631
+ elements.mobileAllTasks,
632
+ elements.mobileTodayTasks,
633
+ elements.mobileUpcomingTasks,
634
+ elements.mobileImportantTasks
635
+ ];
636
+
637
+ mobileButtons.forEach(button => {
638
+ button.classList.remove('text-indigo-600');
639
+ button.classList.add('text-gray-500');
640
+ });
641
+
642
+ let mobileActiveButton;
643
+ switch (state.currentView) {
644
+ case 'all':
645
+ mobileActiveButton = elements.mobileAllTasks;
646
+ break;
647
+ case 'today':
648
+ mobileActiveButton = elements.mobileTodayTasks;
649
+ break;
650
+ case 'upcoming':
651
+ mobileActiveButton = elements.mobileUpcomingTasks;
652
+ break;
653
+ case 'important':
654
+ mobileActiveButton = elements.mobileImportantTasks;
655
+ break;
656
+ }
657
+
658
+ if (mobileActiveButton) {
659
+ mobileActiveButton.classList.remove('text-gray-500');
660
+ mobileActiveButton.classList.add('text-indigo-600');
661
+ }
662
+ }
663
+
664
+ // Update view title
665
+ function updateViewTitle() {
666
+ let title;
667
+ switch (state.currentView) {
668
+ case 'all':
669
+ title = 'Tutte le attività';
670
+ break;
671
+ case 'today':
672
+ title = 'Attività di oggi';
673
+ break;
674
+ case 'upcoming':
675
+ title = 'Prossime attività';
676
+ break;
677
+ case 'important':
678
+ title = 'Attività importanti';
679
+ break;
680
+ case 'completed':
681
+ title = 'Attività completate';
682
+ break;
683
+ default:
684
+ title = 'Tutte le attività';
685
+ }
686
+
687
+ elements.currentView.textContent = title;
688
+ }
689
+
690
+ // Render tasks based on current view
691
+ function renderTasks() {
692
+ let filteredTasks = [];
693
+
694
+ switch (state.currentView) {
695
+ case 'all':
696
+ filteredTasks = state.tasks.filter(task => !task.completed);
697
+ break;
698
+ case 'today':
699
+ const today = new Date().toISOString().split('T')[0];
700
+ filteredTasks = state.tasks.filter(task => task.date === today && !task.completed);
701
+ break;
702
+ case 'upcoming':
703
+ const todayDate = new Date();
704
+ todayDate.setHours(0, 0, 0, 0);
705
+ filteredTasks = state.tasks.filter(task => {
706
+ const taskDate = new Date(task.date);
707
+ return taskDate >= todayDate && !task.completed;
708
+ });
709
+ break;
710
+ case 'important':
711
+ filteredTasks = state.tasks.filter(task => task.important && !task.completed);
712
+ break;
713
+ case 'completed':
714
+ filteredTasks = state.tasks.filter(task => task.completed);
715
+ break;
716
+ }
717
+
718
+ // Sort tasks by date and time
719
+ filteredTasks.sort((a, b) => {
720
+ const dateA = new Date(`${a.date}T${a.time || '00:00'}`);
721
+ const dateB = new Date(`${b.date}T${b.time || '00:00'}`);
722
+ return dateA - dateB;
723
+ });
724
+
725
+ // Clear task list
726
+ elements.taskList.innerHTML = '';
727
+
728
+ if (filteredTasks.length === 0) {
729
+ elements.noTasksMessage.classList.remove('hidden');
730
+ elements.taskListContainer.classList.add('flex', 'items-center', 'justify-center');
731
+ } else {
732
+ elements.noTasksMessage.classList.add('hidden');
733
+ elements.taskListContainer.classList.remove('flex', 'items-center', 'justify-center');
734
+
735
+ // Add tasks to the list
736
+ filteredTasks.forEach(task => {
737
+ const taskElement = createTaskElement(task);
738
+ elements.taskList.appendChild(taskElement);
739
+ });
740
+ }
741
+ }
742
+
743
+ // Create task element
744
+ function createTaskElement(task) {
745
+ const taskElement = document.createElement('div');
746
+ taskElement.className = 'task-item bg-white p-4 rounded-lg shadow hover:shadow-md transition-shadow cursor-pointer';
747
+ taskElement.dataset.taskId = task.id;
748
+
749
+ // Format date
750
+ const taskDate = new Date(task.date);
751
+ const formattedDate = taskDate.toLocaleDateString('it-IT', {
752
+ weekday: 'short',
753
+ day: 'numeric',
754
+ month: 'short'
755
+ });
756
+
757
+ // Format time if exists
758
+ let timeHtml = '';
759
+ if (task.time) {
760
+ timeHtml = `<span class="text-gray-500 ml-2">${task.time}</span>`;
761
+ }
762
+
763
+ // Get category
764
+ let categoryHtml = '';
765
+ if (task.category) {
766
+ const category = state.categories.find(cat => cat.id === task.category);
767
+ if (category) {
768
+ categoryHtml = `<span class="inline-block px-2 py-1 text-xs font-semibold rounded-full ${category.color}">${category.name}</span>`;
769
+ }
770
+ }
771
+
772
+ // Important icon
773
+ const importantIcon = task.important ? '<i class="fas fa-star text-yellow-500 mr-2"></i>' : '';
774
+
775
+ taskElement.innerHTML = `
776
+ <div class="flex items-start justify-between">
777
+ <div class="flex items-center">
778
+ <button class="complete-task-btn mr-3 p-1 rounded-full border border-gray-300 hover:bg-gray-100">
779
+ <i class="fas fa-check text-gray-400"></i>
780
+ </button>
781
+ <div>
782
+ <h3 class="font-medium text-gray-900">${importantIcon}${task.title}</h3>
783
+ <div class="flex items-center mt-1 text-sm text-gray-500">
784
+ <i class="far fa-calendar-alt mr-1"></i>
785
+ <span>${formattedDate}</span>
786
+ ${timeHtml}
787
+ </div>
788
+ </div>
789
+ </div>
790
+ <div>
791
+ ${categoryHtml}
792
+ </div>
793
+ </div>
794
+ `;
795
+
796
+ // Add event listeners
797
+ const completeBtn = taskElement.querySelector('.complete-task-btn');
798
+ completeBtn.addEventListener('click', (e) => {
799
+ e.stopPropagation();
800
+ toggleTaskCompletion(task.id);
801
+ });
802
+
803
+ taskElement.addEventListener('click', () => showTaskDetails(task.id));
804
+
805
+ return taskElement;
806
+ }
807
+
808
+ // Toggle task completion
809
+ function toggleTaskCompletion(taskId) {
810
+ const taskIndex = state.tasks.findIndex(task => task.id === taskId);
811
+ if (taskIndex !== -1) {
812
+ state.tasks[taskIndex].completed = !state.tasks[taskIndex].completed;
813
+ renderTasks();
814
+
815
+ // If viewing completed tasks, keep the task in the list
816
+ if (state.currentView === 'completed' && state.tasks[taskIndex].completed) {
817
+ // Do nothing, task will stay in the list
818
+ } else {
819
+ // Otherwise, remove the task from the current view
820
+ const taskElement = document.querySelector(`.task-item[data-task-id="${taskId}"]`);
821
+ if (taskElement) {
822
+ taskElement.remove();
823
+
824
+ // Show no tasks message if list is empty
825
+ if (elements.taskList.children.length === 0) {
826
+ elements.noTasksMessage.classList.remove('hidden');
827
+ elements.taskListContainer.classList.add('flex', 'items-center', 'justify-center');
828
+ }
829
+ }
830
+ }
831
+
832
+ // Update task details if the task is selected
833
+ if (state.selectedTask && state.selectedTask.id === taskId) {
834
+ showTaskDetails(taskId);
835
+ }
836
+ }
837
+ }
838
+
839
+ // Show task details
840
+ function showTaskDetails(taskId) {
841
+ const task = state.tasks.find(task => task.id === taskId);
842
+ if (task) {
843
+ state.selectedTask = task;
844
+
845
+ // Format date
846
+ const taskDate = new Date(task.date);
847
+ const formattedDate = taskDate.toLocaleDateString('it-IT', {
848
+ weekday: 'long',
849
+ day: 'numeric',
850
+ month: 'long',
851
+ year: 'numeric'
852
+ });
853
+
854
+ // Format time if exists
855
+ let timeHtml = '';
856
+ if (task.time) {
857
+ timeHtml = ` alle ${task.time}`;
858
+ }
859
+
860
+ // Get category
861
+ let categoryHtml = '';
862
+ if (task.category) {
863
+ const category = state.categories.find(cat => cat.id === task.category);
864
+ if (category) {
865
+ categoryHtml = `<span class="${category.color}">${category.name}</span>`;
866
+ }
867
+ }
868
+
869
+ // Important icon
870
+ const importantIcon = task.important ? '<i class="fas fa-star text-yellow-500 mr-2"></i>' : '';
871
+
872
+ // Update task details
873
+ elements.taskDetailTitle.innerHTML = `${importantIcon}${task.title}`;
874
+ elements.taskDetailDate.textContent = `${formattedDate}${timeHtml}`;
875
+
876
+ if (categoryHtml) {
877
+ elements.taskDetailCategory.innerHTML = categoryHtml;
878
+ elements.taskDetailCategory.classList.remove('hidden');
879
+ } else {
880
+ elements.taskDetailCategory.classList.add('hidden');
881
+ }
882
+
883
+ elements.taskDetailDescription.textContent = task.description || 'Nessuna descrizione fornita';
884
+
885
+ // Show details and hide placeholder
886
+ elements.taskDetails.classList.remove('hidden');
887
+ elements.noTaskSelected.classList.add('hidden');
888
+ }
889
+ }
890
+
891
+ // Open add task modal
892
+ function openAddTaskModal() {
893
+ elements.modalTitle.textContent = 'Nuova attività';
894
+ elements.taskId.value = '';
895
+ elements.taskTitle.value = '';
896
+ elements.taskDescription.value = '';
897
+
898
+ // Set today's date as default
899
+ const today = new Date();
900
+ const formattedDate = today.toISOString().split('T')[0];
901
+ elements.taskDate.value = formattedDate;
902
+
903
+ elements.taskTime.value = '';
904
+ elements.taskCategory.value = '';
905
+ elements.taskImportant.checked = false;
906
+
907
+ elements.taskModal.classList.remove('hidden');
908
+ }
909
+
910
+ // Open edit task modal
911
+ function openEditTaskModal(taskId) {
912
+ const task = state.tasks.find(task => task.id === taskId);
913
+ if (task) {
914
+ elements.modalTitle.textContent = 'Modifica attività';
915
+ elements.taskId.value = task.id;
916
+ elements.taskTitle.value = task.title;
917
+ elements.taskDescription.value = task.description || '';
918
+ elements.taskDate.value = task.date;
919
+ elements.taskTime.value = task.time || '';
920
+ elements.taskCategory.value = task.category || '';
921
+ elements.taskImportant.checked = task.important || false;
922
+
923
+ elements.taskModal.classList.remove('hidden');
924
+ }
925
+ }
926
+
927
+ // Close task modal
928
+ function closeTaskModal() {
929
+ elements.taskModal.classList.add('hidden');
930
+ }
931
+
932
+ // Save task
933
+ function saveTask() {
934
+ const title = elements.taskTitle.value.trim();
935
+ if (!title) {
936
+ alert('Il titolo è obbligatorio');
937
+ return;
938
+ }
939
+
940
+ const taskData = {
941
+ id: elements.taskId.value ? parseInt(elements.taskId.value) : Date.now(),
942
+ title: title,
943
+ description: elements.taskDescription.value.trim(),
944
+ date: elements.taskDate.value,
945
+ time: elements.taskTime.value || null,
946
+ category: elements.taskCategory.value ? parseInt(elements.taskCategory.value) : null,
947
+ important: elements.taskImportant.checked,
948
+ completed: false
949
+ };
950
+
951
+ if (elements.taskId.value) {
952
+ // Update existing task
953
+ const taskIndex = state.tasks.findIndex(task => task.id === taskData.id);
954
+ if (taskIndex !== -1) {
955
+ state.tasks[taskIndex] = {
956
+ ...state.tasks[taskIndex],
957
+ ...taskData
958
+ };
959
+ }
960
+ } else {
961
+ // Add new task
962
+ state.tasks.push(taskData);
963
+ }
964
+
965
+ closeTaskModal();
966
+ renderTasks();
967
+
968
+ // If we're editing, update the task details
969
+ if (state.selectedTask && state.selectedTask.id === taskData.id) {
970
+ showTaskDetails(taskData.id);
971
+ }
972
+ }
973
+
974
+ // Delete task
975
+ function deleteTask() {
976
+ if (state.selectedTask) {
977
+ if (confirm('Sei sicuro di voler eliminare questa attività?')) {
978
+ const taskId = state.selectedTask.id;
979
+ state.tasks = state.tasks.filter(task => task.id !== taskId);
980
+
981
+ // Remove task from list
982
+ const taskElement = document.querySelector(`.task-item[data-task-id="${taskId}"]`);
983
+ if (taskElement) {
984
+ taskElement.remove();
985
+ }
986
+
987
+ // Hide task details
988
+ elements.taskDetails.classList.add('hidden');
989
+ elements.noTaskSelected.classList.remove('hidden');
990
+ state.selectedTask = null;
991
+
992
+ // Show no tasks message if list is empty
993
+ if (elements.taskList.children.length === 0) {
994
+ elements.noTasksMessage.classList.remove('hidden');
995
+ elements.taskListContainer.classList.add('flex', 'items-center', 'justify-center');
996
+ }
997
+
998
+ renderTasks();
999
+ }
1000
+ }
1001
+ }
1002
+
1003
+ // Render categories in sidebar and task form
1004
+ function renderCategories() {
1005
+ // Clear categories list
1006
+ elements.categoriesList.innerHTML = '';
1007
+
1008
+ // Add categories to sidebar
1009
+ state.categories.forEach(category => {
1010
+ const categoryElement = document.createElement('button');
1011
+ categoryElement.className = 'flex items-center w-full px-4 py-2 text-sm font-medium text-indigo-100 hover:text-white hover:bg-indigo-600 rounded-md group';
1012
+ categoryElement.dataset.categoryId = category.id;
1013
+ categoryElement.innerHTML = `
1014
+ <span class="inline-block w-3 h-3 rounded-full ${category.color.replace('text-', 'bg-').split(' ')[0]} mr-3"></span>
1015
+ ${category.name}
1016
+ `;
1017
+
1018
+ categoryElement.addEventListener('click', () => filterByCategory(category.id));
1019
+ elements.categoriesList.appendChild(categoryElement);
1020
+ });
1021
+ }
1022
+
1023
+ // Render task categories in select dropdown
1024
+ function renderTaskCategories() {
1025
+ // Clear select
1026
+ elements.taskCategory.innerHTML = '<option value="">Nessuna categoria</option>';
1027
+
1028
+ // Add categories to select
1029
+ state.categories.forEach(category => {
1030
+ const option = document.createElement('option');
1031
+ option.value = category.id;
1032
+ option.textContent = category.name;
1033
+ elements.taskCategory.appendChild(option);
1034
+ });
1035
+ }
1036
+
1037
+ // Filter tasks by category
1038
+ function filterByCategory(categoryId) {
1039
+ state.currentView = 'category';
1040
+ state.selectedCategory = categoryId;
1041
+
1042
+ // Update view title
1043
+ const category = state.categories.find(cat => cat.id === categoryId);
1044
+ elements.currentView.textContent = `Categoria: ${category.name}`;
1045
+
1046
+ // Render tasks
1047
+ renderTasksByCategory(categoryId);
1048
+
1049
+ // Update active buttons
1050
+ updateActiveViewButton();
1051
+ }
1052
+
1053
+ // Render tasks by category
1054
+ function renderTasksByCategory(categoryId) {
1055
+ const filteredTasks = state.tasks.filter(task =>
1056
+ task.category === categoryId && !task.completed
1057
+ );
1058
+
1059
+ // Clear task list
1060
+ elements.taskList.innerHTML = '';
1061
+
1062
+ if (filteredTasks.length === 0) {
1063
+ elements.noTasksMessage.classList.remove('hidden');
1064
+ elements.taskListContainer.classList.add('flex', 'items-center', 'justify-center');
1065
+ } else {
1066
+ elements.noTasksMessage.classList.add('hidden');
1067
+ elements.taskListContainer.classList.remove('flex', 'items-center', 'justify-center');
1068
+
1069
+ // Add tasks to the list
1070
+ filteredTasks.forEach(task => {
1071
+ const taskElement = createTaskElement(task);
1072
+ elements.taskList.appendChild(taskElement);
1073
+ });
1074
+ }
1075
+ }
1076
+
1077
+ // Open add category modal
1078
+ function openAddCategoryModal() {
1079
+ elements.categoryName.value = '';
1080
+ elements.categoryColor.value = 'bg-blue-500 text-blue-100';
1081
+ elements.categoryModal.classList.remove('hidden');
1082
+
1083
+ // Close task modal if open
1084
+ closeTaskModal();
1085
+ }
1086
+
1087
+ // Close category modal
1088
+ function closeCategoryModal() {
1089
+ elements.categoryModal.classList.add('hidden');
1090
+ }
1091
+
1092
+ // Save category
1093
+ function saveCategory() {
1094
+ const name = elements.categoryName.value.trim();
1095
+ if (!name) {
1096
+ alert('Il nome della categoria è obbligatorio');
1097
+ return;
1098
+ }
1099
+
1100
+ const categoryData = {
1101
+ id: Date.now(),
1102
+ name: name,
1103
+ color: elements.categoryColor.value
1104
+ };
1105
+
1106
+ state.categories.push(categoryData);
1107
+
1108
+ closeCategoryModal();
1109
+ renderCategories();
1110
+ renderTaskCategories();
1111
+ }
1112
+
1113
+ // Toggle search
1114
+ function toggleSearch() {
1115
+ elements.searchContainer.classList.toggle('hidden');
1116
+ if (!elements.searchContainer.classList.contains('hidden')) {
1117
+ elements.searchInput.focus();
1118
+ }
1119
+ }
1120
+
1121
+ // Handle search
1122
+ function handleSearch() {
1123
+ const query = elements.searchInput.value.toLowerCase();
1124
+
1125
+ if (query === '') {
1126
+ renderTasks();
1127
+ return;
1128
+ }
1129
+
1130
+ const filteredTasks = state.tasks.filter(task =>
1131
+ task.title.toLowerCase().includes(query) ||
1132
+ (task.description && task.description.toLowerCase().includes(query))
1133
+ );
1134
+
1135
+ // Clear task list
1136
+ elements.taskList.innerHTML = '';
1137
+
1138
+ if (filteredTasks.length === 0) {
1139
+ elements.noTasksMessage.classList.remove('hidden');
1140
+ elements.taskListContainer.classList.add('flex', 'items-center', 'justify-center');
1141
+ } else {
1142
+ elements.noTasksMessage.classList.add('hidden');
1143
+ elements.taskListContainer.classList.remove('flex', 'items-center', 'justify-center');
1144
+
1145
+ // Add tasks to the list
1146
+ filteredTasks.forEach(task => {
1147
+ const taskElement = createTaskElement(task);
1148
+ elements.taskList.appendChild(taskElement);
1149
+ });
1150
+ }
1151
+ }
1152
+
1153
+ // Render calendar
1154
+ function renderCalendar() {
1155
+ // Clear calendar
1156
+ elements.calendar.innerHTML = '';
1157
+
1158
+ // Set month and year in header
1159
+ const monthNames = ['Gennaio', 'Febbraio', 'Marzo', 'Aprile', 'Maggio', 'Giugno', 'Luglio', 'Agosto', 'Settembre', 'Ottobre', 'Novembre', 'Dicembre'];
1160
+ elements.currentMonthDisplay.textContent = `${monthNames[state.currentMonth]} ${state.currentYear}`;
1161
+
1162
+ // Get first day of month and total days in month
1163
+ const firstDay = new Date(state.currentYear, state.currentMonth, 1).getDay();
1164
+ const daysInMonth = new Date(state.currentYear, state.currentMonth + 1, 0).getDate();
1165
+
1166
+ // Adjust first day (Sunday = 0 in JavaScript, but we want Monday as first day)
1167
+ const adjustedFirstDay = firstDay === 0 ? 6 : firstDay - 1;
1168
+
1169
+ // Add day names
1170
+ const dayNames = ['Lun', 'Mar', 'Mer', 'Gio', 'Ven', 'Sab', 'Dom'];
1171
+ dayNames.forEach(day => {
1172
+ const dayElement = document.createElement('div');
1173
+ dayElement.className = 'text-center text-sm font-medium text-gray-500 py-1';
1174
+ dayElement.textContent = day;
1175
+ elements.calendar.appendChild(dayElement);
1176
+ });
1177
+
1178
+ // Add empty cells for days before the first day of the month
1179
+ for (let i = 0; i < adjustedFirstDay; i++) {
1180
+ const emptyElement = document.createElement('div');
1181
+ emptyElement.className = 'h-8';
1182
+ elements.calendar.appendChild(emptyElement);
1183
+ }
1184
+
1185
+ // Add day cells
1186
+ const today = new Date();
1187
+ const currentDay = today.getDate();
1188
+ const currentMonth = today.getMonth();
1189
+ const currentYear = today.getFullYear();
1190
+
1191
+ for (let day = 1; day <= daysInMonth; day++) {
1192
+ const dayElement = document.createElement('div');
1193
+ dayElement.className = 'text-center py-1 cursor-pointer hover:bg-gray-100';
1194
+
1195
+ // Highlight current day
1196
+ if (day === currentDay && state.currentMonth === currentMonth && state.currentYear === currentYear) {
1197
+ dayElement.classList.add('current-day');
1198
+ }
1199
+
1200
+ dayElement.textContent = day;
1201
+
1202
+ // Add event listener
1203
+ dayElement.addEventListener('click', () => {
1204
+ filterByDate(day);
1205
+ });
1206
+
1207
+ elements.calendar.appendChild(dayElement);
1208
+ }
1209
+
1210
+ // Add tasks indicators
1211
+ state.tasks.forEach(task => {
1212
+ if (!task.completed) {
1213
+ const taskDate = new Date(task.date);
1214
+ if (taskDate.getMonth() === state.currentMonth && taskDate.getFullYear() === state.currentYear) {
1215
+ const day = taskDate.getDate();
1216
+ const dayElement = elements.calendar.children[adjustedFirstDay + day + 6]; // +6 for day names
1217
+
1218
+ if (dayElement) {
1219
+ const indicator = document.createElement('div');
1220
+ indicator.className = 'w-1 h-1 mx-auto rounded-full bg-indigo-500';
1221
+ dayElement.appendChild(indicator);
1222
+ }
1223
+ }
1224
+ }
1225
+ });
1226
+ }
1227
+
1228
+ // Filter by date
1229
+ function filterByDate(day) {
1230
+ const date = new Date(state.currentYear, state.currentMonth, day);
1231
+ const formattedDate = date.toISOString().split('T')[0];
1232
+
1233
+ state.currentView = 'date';
1234
+ elements.currentView.textContent = `Attività per ${day}/${state.currentMonth + 1}/${state.currentYear}`;
1235
+
1236
+ const filteredTasks = state.tasks.filter(task =>
1237
+ task.date === formattedDate && !task.completed
1238
+ );
1239
+
1240
+ // Clear task list
1241
+ elements.taskList.innerHTML = '';
1242
+
1243
+ if (filteredTasks.length === 0) {
1244
+ elements.noTasksMessage.classList.remove('hidden');
1245
+ elements.taskListContainer.classList.add('flex', 'items-center', 'justify-center');
1246
+ } else {
1247
+ elements.noTasksMessage.classList.add('hidden');
1248
+ elements.taskListContainer.classList.remove('flex', 'items-center', 'justify-center');
1249
+
1250
+ // Add tasks to the list
1251
+ filteredTasks.forEach(task => {
1252
+ const taskElement = createTaskElement(task);
1253
+ elements.taskList.appendChild(taskElement);
1254
+ });
1255
+ }
1256
+
1257
+ // Update active buttons
1258
+ updateActiveViewButton();
1259
+ }
1260
+
1261
+ // Go to previous month
1262
+ function goToPreviousMonth() {
1263
+ if (state.currentMonth === 0) {
1264
+ state.currentMonth = 11;
1265
+ state.currentYear--;
1266
+ } else {
1267
+ state.currentMonth--;
1268
+ }
1269
+ renderCalendar();
1270
+ }
1271
+
1272
+ // Go to next month
1273
+ function goToNextMonth() {
1274
+ if (state.currentMonth === 11) {
1275
+ state.currentMonth = 0;
1276
+ state.currentYear++;
1277
+ } else {
1278
+ state.currentMonth++;
1279
+ }
1280
+ renderCalendar();
1281
+ }
1282
+
1283
+ // Check dark mode preference
1284
+ function checkDarkModePreference() {
1285
+ const darkModePref = localStorage.getItem('darkMode') === 'true';
1286
+ if (darkModePref) {
1287
+ enableDarkMode();
1288
+ } else {
1289
+ disableDarkMode();
1290
+ }
1291
+ }
1292
+
1293
+ // Toggle dark mode
1294
+ function toggleDarkMode() {
1295
+ if (state.darkMode) {
1296
+ disableDarkMode();
1297
+ } else {
1298
+ enableDarkMode();
1299
+ }
1300
+ }
1301
+
1302
+ // Enable dark mode
1303
+ function enableDarkMode() {
1304
+ document.documentElement.classList.add('dark');
1305
+ localStorage.setItem('darkMode', 'true');
1306
+ state.darkMode = true;
1307
+ elements.darkModeToggle.checked = true;
1308
+ }
1309
+
1310
+ // Disable dark mode
1311
+ function disableDarkMode() {
1312
+ document.documentElement.classList.remove('dark');
1313
+ localStorage.setItem('darkMode', 'false');
1314
+ state.darkMode = false;
1315
+ elements.darkModeToggle.checked = false;
1316
+ }
1317
+
1318
+ // Initialize the app when DOM is loaded
1319
+ document.addEventListener('DOMContentLoaded', init);
1320
+
1321
+ // Add event listeners for task details buttons
1322
+ document.addEventListener('click', function(e) {
1323
+ if (e.target.id === 'edit-task-btn') {
1324
+ openEditTaskModal(state.selectedTask.id);
1325
+ } else if (e.target.id === 'delete-task-btn') {
1326
+ deleteTask();
1327
+ }
1328
+ });
1329
+ </script>
1330
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=federi/taskflow" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
1331
+ </html>
prompts.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ Creare una web application per la gestione delle attività (task manager) che permetta agli utenti di visualizzare, creare e gestire le proprie attività con integrazione al calendario per promemoria e pianificazione.