gallabs commited on
Commit
7cbaf8f
·
verified ·
1 Parent(s): 939d97e

Add 2 files

Browse files
Files changed (2) hide show
  1. README.md +7 -5
  2. index.html +1798 -18
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Calendar Lucas
3
- emoji: 🐢
4
- colorFrom: indigo
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: calendar-lucas
3
+ emoji: 🐳
4
+ colorFrom: purple
5
+ colorTo: purple
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,1799 @@
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="pt-BR">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>General Labs - Calendário</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link
9
+ rel="stylesheet"
10
+ href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"
11
+ />
12
+ <style>
13
+ .event-planning {
14
+ background-color: #166534;
15
+ }
16
+ .event-meeting {
17
+ background-color: #164e63;
18
+ }
19
+ .event-reports {
20
+ background-color: #854d0e;
21
+ }
22
+ .event-theme {
23
+ background-color: #991b1b;
24
+ }
25
+ .event-birthday {
26
+ background-color: #0d9488;
27
+ }
28
+
29
+ .sidebar-item:hover .sidebar-tooltip {
30
+ display: block;
31
+ }
32
+
33
+ .calendar-day:hover {
34
+ background-color: #1e293b;
35
+ }
36
+
37
+ .event-item:hover {
38
+ transform: translateX(5px);
39
+ }
40
+
41
+ .dropdown-notifications {
42
+ max-height: 0;
43
+ overflow: hidden;
44
+ transition: max-height 0.3s ease-out;
45
+ }
46
+
47
+ .dropdown-notifications.show {
48
+ max-height: 500px;
49
+ }
50
+
51
+ .modal {
52
+ transition: opacity 0.3s ease, transform 0.3s ease;
53
+ }
54
+
55
+ .modal.hidden {
56
+ opacity: 0;
57
+ pointer-events: none;
58
+ transform: translateY(-20px);
59
+ }
60
+
61
+ .week-view .hour-slot {
62
+ height: 60px;
63
+ border-bottom: 1px solid #374151;
64
+ }
65
+
66
+ .day-view .hour-slot {
67
+ height: 80px;
68
+ border-bottom: 1px solid #374151;
69
+ }
70
+
71
+ .list-view .event-item {
72
+ border-left: 4px solid;
73
+ }
74
+
75
+ @media (max-width: 1024px) {
76
+ .sidebar {
77
+ transform: translateX(-100%);
78
+ transition: transform 0.3s ease;
79
+ }
80
+
81
+ .sidebar.open {
82
+ transform: translateX(0);
83
+ }
84
+
85
+ .sidebar-overlay {
86
+ display: none;
87
+ position: fixed;
88
+ top: 0;
89
+ left: 0;
90
+ right: 0;
91
+ bottom: 0;
92
+ background-color: rgba(0, 0, 0, 0.5);
93
+ z-index: 40;
94
+ }
95
+
96
+ .sidebar-overlay.open {
97
+ display: block;
98
+ }
99
+ }
100
+ </style>
101
+ </head>
102
+ <body class="bg-gray-900 text-gray-200">
103
+ <!-- Layout Container -->
104
+ <div class="flex h-screen overflow-hidden">
105
+ <!-- Sidebar Overlay (Mobile) -->
106
+ <div id="sidebarOverlay" class="sidebar-overlay"></div>
107
+
108
+ <!-- Sidebar -->
109
+ <aside
110
+ id="sidebar"
111
+ class="sidebar w-64 bg-gray-800 border-r border-gray-700 flex-shrink-0 fixed lg:static h-full z-50"
112
+ >
113
+ <div class="p-4 border-b border-gray-700">
114
+ <h1 class="text-xl font-bold text-white flex items-center">
115
+ <span
116
+ class="bg-blue-600 w-8 h-8 rounded flex items-center justify-center mr-2"
117
+ >
118
+ <i class="fas fa-flask text-white"></i>
119
+ </span>
120
+ General Labs
121
+ </h1>
122
+ </div>
123
+
124
+ <div class="p-4 overflow-y-auto h-[calc(100%-65px)]">
125
+ <ul class="space-y-2">
126
+ <li>
127
+ <a
128
+ href="#"
129
+ class="flex items-center p-2 text-base font-normal rounded-lg text-white hover:bg-gray-700 group"
130
+ >
131
+ <i
132
+ class="fas fa-tachometer-alt w-6 text-gray-400 group-hover:text-white"
133
+ ></i>
134
+ <span class="ml-3">Dashboards</span>
135
+ <span
136
+ class="bg-blue-600 text-xs font-medium px-2 py-0.5 rounded-full ml-auto"
137
+ >New</span
138
+ >
139
+ </a>
140
+ </li>
141
+ <li>
142
+ <a
143
+ href="#"
144
+ class="flex items-center p-2 text-base font-normal rounded-lg bg-gray-700 text-white group"
145
+ >
146
+ <i class="fas fa-th w-6 text-white"></i>
147
+ <span class="ml-3">Apps</span>
148
+ </a>
149
+ </li>
150
+ <li>
151
+ <a
152
+ href="#"
153
+ class="flex items-center p-2 text-base font-normal rounded-lg text-white hover:bg-gray-700 group"
154
+ >
155
+ <i
156
+ class="fas fa-chart-pie w-6 text-gray-400 group-hover:text-white"
157
+ ></i>
158
+ <span class="ml-3">Consolidados</span>
159
+ </a>
160
+ </li>
161
+ <li>
162
+ <a
163
+ href="#"
164
+ class="flex items-center p-2 text-base font-normal rounded-lg text-white hover:bg-gray-700 group"
165
+ >
166
+ <i
167
+ class="fas fa-cubes w-6 text-gray-400 group-hover:text-white"
168
+ ></i>
169
+ <span class="ml-3">Aplicativos</span>
170
+ <span
171
+ class="bg-red-600 text-xs font-medium px-2 py-0.5 rounded-full ml-auto"
172
+ >Hot</span
173
+ >
174
+ </a>
175
+ </li>
176
+ <li>
177
+ <a
178
+ href="#"
179
+ class="flex items-center p-2 text-base font-normal rounded-lg text-white hover:bg-gray-700 group"
180
+ >
181
+ <i
182
+ class="fas fa-user-plus w-6 text-gray-400 group-hover:text-white"
183
+ ></i>
184
+ <span class="ml-3">Cadastros</span>
185
+ </a>
186
+ </li>
187
+ <li>
188
+ <a
189
+ href="#"
190
+ class="flex items-center p-2 text-base font-normal rounded-lg text-white hover:bg-gray-700 group"
191
+ >
192
+ <i
193
+ class="fas fa-tasks w-6 text-gray-400 group-hover:text-white"
194
+ ></i>
195
+ <span class="ml-3">Processos</span>
196
+ </a>
197
+ </li>
198
+ <li>
199
+ <a
200
+ href="#"
201
+ class="flex items-center p-2 text-base font-normal rounded-lg text-white hover:bg-gray-700 group"
202
+ >
203
+ <i
204
+ class="fas fa-layer-group w-6 text-gray-400 group-hover:text-white"
205
+ ></i>
206
+ <span class="ml-3">Layouts</span>
207
+ </a>
208
+ </li>
209
+ </ul>
210
+ </div>
211
+ </aside>
212
+
213
+ <!-- Main Content -->
214
+ <div class="flex-1 overflow-auto">
215
+ <!-- Top Navigation -->
216
+ <nav
217
+ class="bg-gray-800 border-b border-gray-700 px-4 py-3 flex items-center justify-between"
218
+ >
219
+ <!-- Mobile menu button -->
220
+ <button
221
+ id="sidebarToggle"
222
+ class="lg:hidden text-gray-400 hover:text-white"
223
+ >
224
+ <i class="fas fa-bars text-xl"></i>
225
+ </button>
226
+
227
+ <!-- Search Bar -->
228
+ <div class="flex-1 mx-4 lg:mx-8">
229
+ <div class="relative max-w-md">
230
+ <div
231
+ class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none"
232
+ >
233
+ <i class="fas fa-search text-gray-400"></i>
234
+ </div>
235
+ <input
236
+ type="text"
237
+ class="bg-gray-700 border border-gray-600 text-white text-sm rounded-lg block w-full pl-10 p-2.5 focus:ring-blue-500 focus:border-blue-500"
238
+ placeholder="Pesquisar..."
239
+ />
240
+ </div>
241
+ </div>
242
+
243
+ <!-- Right Icons -->
244
+ <div class="flex items-center space-x-4">
245
+ <!-- Language Selector -->
246
+ <div class="flex items-center space-x-1">
247
+ <button class="text-gray-400 hover:text-white">
248
+ <span class="text-xl">🇧🇷</span>
249
+ </button>
250
+ <button class="text-gray-400 hover:text-white">
251
+ <span class="text-xl">🇺🇸</span>
252
+ </button>
253
+ </div>
254
+
255
+ <!-- Notifications -->
256
+ <div class="relative">
257
+ <button
258
+ id="notificationsButton"
259
+ class="text-gray-400 hover:text-white relative"
260
+ >
261
+ <i class="fas fa-bell text-xl"></i>
262
+ <span
263
+ class="absolute -top-1 -right-1 bg-red-500 text-white text-xs rounded-full h-5 w-5 flex items-center justify-center"
264
+ >3</span
265
+ >
266
+ </button>
267
+
268
+ <!-- Notifications Dropdown -->
269
+ <div
270
+ id="notificationsDropdown"
271
+ class="dropdown-notifications absolute right-0 mt-2 w-72 bg-gray-800 rounded-md shadow-lg z-50 border border-gray-700"
272
+ >
273
+ <div class="p-3 border-b border-gray-700">
274
+ <h3 class="text-white font-medium">Notificações</h3>
275
+ </div>
276
+ <div class="divide-y divide-gray-700">
277
+ <a href="#" class="flex items-start p-3 hover:bg-gray-700">
278
+ <div class="bg-blue-600 rounded-full p-2 mr-3">
279
+ <i class="fas fa-envelope text-white text-sm"></i>
280
+ </div>
281
+ <div>
282
+ <p class="text-white">Nova mensagem de Juliana</p>
283
+ <p class="text-gray-400 text-sm">2 minutos atrás</p>
284
+ </div>
285
+ </a>
286
+ <a href="#" class="flex items-start p-3 hover:bg-gray-700">
287
+ <div class="bg-yellow-600 rounded-full p-2 mr-3">
288
+ <i
289
+ class="fas fa-exclamation-triangle text-white text-sm"
290
+ ></i>
291
+ </div>
292
+ <div>
293
+ <p class="text-white">
294
+ Evento 'Client Meeting' começa em 1h
295
+ </p>
296
+ <p class="text-gray-400 text-sm">30 minutos atrás</p>
297
+ </div>
298
+ </a>
299
+ <a href="#" class="flex items-start p-3 hover:bg-gray-700">
300
+ <div class="bg-green-600 rounded-full p-2 mr-3">
301
+ <i class="fas fa-calendar-plus text-white text-sm"></i>
302
+ </div>
303
+ <div>
304
+ <p class="text-white">Novo evento adicionado por Anna</p>
305
+ <p class="text-gray-400 text-sm">1 hora atrás</p>
306
+ </div>
307
+ </a>
308
+ </div>
309
+ <div class="p-3 border-t border-gray-700 text-center">
310
+ <a href="#" class="text-blue-400 text-sm hover:underline"
311
+ >Ver todas</a
312
+ >
313
+ </div>
314
+ </div>
315
+ </div>
316
+
317
+ <!-- Settings -->
318
+ <button class="text-gray-400 hover:text-white">
319
+ <i class="fas fa-cog text-xl"></i>
320
+ </button>
321
+
322
+ <!-- Profile -->
323
+ <div class="flex items-center">
324
+ <img
325
+ class="w-8 h-8 rounded-full"
326
+ src="https://randomuser.me/api/portraits/women/44.jpg"
327
+ alt="User photo"
328
+ />
329
+ </div>
330
+ </div>
331
+ </nav>
332
+
333
+ <!-- Breadcrumb and Page Title -->
334
+ <div class="px-6 py-4 border-b border-gray-700">
335
+ <nav class="flex" aria-label="Breadcrumb">
336
+ <ol class="inline-flex items-center space-x-1 md:space-x-3">
337
+ <li class="inline-flex items-center">
338
+ <a
339
+ href="#"
340
+ class="inline-flex items-center text-sm font-medium text-gray-400 hover:text-white"
341
+ >
342
+ <i class="fas fa-home mr-2"></i>
343
+ Home
344
+ </a>
345
+ </li>
346
+ <li>
347
+ <div class="flex items-center">
348
+ <i class="fas fa-chevron-right text-gray-600 text-xs"></i>
349
+ <a
350
+ href="#"
351
+ class="ml-1 text-sm font-medium text-gray-400 hover:text-white md:ml-2"
352
+ >Apps</a
353
+ >
354
+ </div>
355
+ </li>
356
+ <li aria-current="page">
357
+ <div class="flex items-center">
358
+ <i class="fas fa-chevron-right text-gray-600 text-xs"></i>
359
+ <span class="ml-1 text-sm font-medium text-white md:ml-2"
360
+ >Calendar</span
361
+ >
362
+ </div>
363
+ </li>
364
+ </ol>
365
+ </nav>
366
+
367
+ <h1 class="text-2xl font-bold text-white mt-2">CALENDAR</h1>
368
+ </div>
369
+
370
+ <!-- Main Content Area -->
371
+ <div class="p-6 flex flex-col lg:flex-row">
372
+ <!-- Left Column - Upcoming Events -->
373
+ <div class="w-full lg:w-1/4 lg:pr-4 mb-6 lg:mb-0">
374
+ <div class="bg-gray-800 rounded-lg p-4 h-full">
375
+ <div class="flex justify-between items-center mb-4">
376
+ <h2 class="text-lg font-semibold text-white">
377
+ Eventos Agendados
378
+ </h2>
379
+ <button
380
+ id="createEventButton"
381
+ class="bg-blue-700 hover:bg-blue-800 text-white px-3 py-1 rounded text-sm"
382
+ >
383
+ + Criar Novo Evento
384
+ </button>
385
+ </div>
386
+
387
+ <p class="text-gray-400 text-sm mb-4">
388
+ Arraste e solte seu evento ou clique no calendário
389
+ </p>
390
+
391
+ <div class="mb-6">
392
+ <h3 class="text-sm font-medium text-gray-300 mb-2">Legenda</h3>
393
+ <div class="space-y-2">
394
+ <div class="flex items-center">
395
+ <span class="w-3 h-3 rounded-full bg-green-800 mr-2"></span>
396
+ <span class="text-gray-300 text-sm"
397
+ >Planejamento de Novo Evento</span
398
+ >
399
+ </div>
400
+ <div class="flex items-center">
401
+ <span class="w-3 h-3 rounded-full bg-blue-900 mr-2"></span>
402
+ <span class="text-gray-300 text-sm">Reunião</span>
403
+ </div>
404
+ <div class="flex items-center">
405
+ <span
406
+ class="w-3 h-3 rounded-full bg-yellow-800 mr-2"
407
+ ></span>
408
+ <span class="text-gray-300 text-sm"
409
+ >Geração de Relatórios</span
410
+ >
411
+ </div>
412
+ <div class="flex items-center">
413
+ <span class="w-3 h-3 rounded-full bg-red-800 mr-2"></span>
414
+ <span class="text-gray-300 text-sm">Criar Novo Tema</span>
415
+ </div>
416
+ </div>
417
+ </div>
418
+
419
+ <div>
420
+ <h3 class="text-sm font-medium text-gray-300 mb-2">
421
+ Próximos Eventos
422
+ </h3>
423
+ <div id="upcomingEventsList" class="space-y-3">
424
+ <!-- Events will be populated by JavaScript -->
425
+ </div>
426
+ </div>
427
+ </div>
428
+ </div>
429
+
430
+ <!-- Right Column - Calendar -->
431
+ <div class="w-full lg:w-3/4">
432
+ <div class="bg-gray-800 rounded-lg p-4 h-full">
433
+ <div
434
+ class="flex flex-col md:flex-row md:items-center md:justify-between mb-6"
435
+ >
436
+ <div class="flex items-center space-x-2 mb-4 md:mb-0">
437
+ <button
438
+ id="prevPeriodButton"
439
+ class="bg-gray-700 hover:bg-gray-600 text-white px-3 py-1 rounded"
440
+ >
441
+ <i class="fas fa-chevron-left"></i>
442
+ </button>
443
+ <button
444
+ id="todayButton"
445
+ class="bg-blue-700 hover:bg-blue-800 text-white px-4 py-1 rounded"
446
+ >
447
+ Hoje
448
+ </button>
449
+ <button
450
+ id="nextPeriodButton"
451
+ class="bg-gray-700 hover:bg-gray-600 text-white px-3 py-1 rounded"
452
+ >
453
+ <i class="fas fa-chevron-right"></i>
454
+ </button>
455
+ <h3
456
+ id="currentPeriodTitle"
457
+ class="text-lg font-semibold text-white ml-2"
458
+ >
459
+ Abril 2025
460
+ </h3>
461
+ </div>
462
+
463
+ <div class="flex space-x-1 bg-gray-700 p-1 rounded">
464
+ <button
465
+ data-view="month"
466
+ class="view-button px-3 py-1 text-sm rounded text-white bg-gray-800"
467
+ >
468
+ Mês
469
+ </button>
470
+ <button
471
+ data-view="week"
472
+ class="view-button px-3 py-1 text-sm rounded text-gray-300 hover:text-white"
473
+ >
474
+ Semana
475
+ </button>
476
+ <button
477
+ data-view="day"
478
+ class="view-button px-3 py-1 text-sm rounded text-gray-300 hover:text-white"
479
+ >
480
+ Dia
481
+ </button>
482
+ <button
483
+ data-view="list"
484
+ class="view-button px-3 py-1 text-sm rounded text-gray-300 hover:text-white"
485
+ >
486
+ Lista
487
+ </button>
488
+ </div>
489
+ </div>
490
+
491
+ <!-- Calendar Views -->
492
+ <div id="calendarViews">
493
+ <!-- Month View (default) -->
494
+ <div id="monthView">
495
+ <!-- Calendar Header -->
496
+ <div class="grid grid-cols-7 gap-1 mb-2">
497
+ <div class="text-center text-gray-400 text-sm font-medium">
498
+ Dom
499
+ </div>
500
+ <div class="text-center text-gray-400 text-sm font-medium">
501
+ Seg
502
+ </div>
503
+ <div class="text-center text-gray-400 text-sm font-medium">
504
+ Ter
505
+ </div>
506
+ <div class="text-center text-gray-400 text-sm font-medium">
507
+ Qua
508
+ </div>
509
+ <div class="text-center text-gray-400 text-sm font-medium">
510
+ Qui
511
+ </div>
512
+ <div class="text-center text-gray-400 text-sm font-medium">
513
+ Sex
514
+ </div>
515
+ <div class="text-center text-gray-400 text-sm font-medium">
516
+ Sáb
517
+ </div>
518
+ </div>
519
+
520
+ <!-- Calendar Grid -->
521
+ <div id="monthGrid" class="grid grid-cols-7 gap-1">
522
+ <!-- Days will be populated by JavaScript -->
523
+ </div>
524
+ </div>
525
+
526
+ <!-- Week View -->
527
+ <div id="weekView" class="hidden week-view">
528
+ <div id="weekHeader" class="grid grid-cols-8 gap-1 mb-2">
529
+ <div class="text-center text-gray-400 text-sm font-medium">
530
+ Hora
531
+ </div>
532
+ <!-- Days will be populated by JavaScript -->
533
+ </div>
534
+ <div id="weekGrid" class="grid grid-cols-8 gap-1">
535
+ <!-- Time slots will be populated by JavaScript -->
536
+ </div>
537
+ </div>
538
+
539
+ <!-- Day View -->
540
+ <div id="dayView" class="hidden day-view">
541
+ <div
542
+ id="dayHeader"
543
+ class="text-center text-gray-400 text-sm font-medium mb-2"
544
+ >
545
+ <!-- Day will be populated by JavaScript -->
546
+ </div>
547
+ <div id="dayGrid">
548
+ <!-- Time slots will be populated by JavaScript -->
549
+ </div>
550
+ </div>
551
+
552
+ <!-- List View -->
553
+ <div id="listView" class="hidden list-view">
554
+ <div
555
+ id="listHeader"
556
+ class="text-center text-gray-400 text-sm font-medium mb-2"
557
+ >
558
+ <!-- Period will be populated by JavaScript -->
559
+ </div>
560
+ <div id="listGrid" class="space-y-2">
561
+ <!-- Events will be populated by JavaScript -->
562
+ </div>
563
+ </div>
564
+ </div>
565
+ </div>
566
+ </div>
567
+ </div>
568
+ </div>
569
+ </div>
570
+
571
+ <!-- Event Modal -->
572
+ <div
573
+ id="eventModal"
574
+ class="modal fixed inset-0 bg-gray-900 bg-opacity-75 flex items-center justify-center z-50 hidden"
575
+ >
576
+ <div class="bg-gray-800 rounded-lg w-full max-w-md mx-4">
577
+ <div
578
+ class="p-4 border-b border-gray-700 flex justify-between items-center"
579
+ >
580
+ <h3 id="modalTitle" class="text-lg font-semibold text-white">
581
+ Novo Evento
582
+ </h3>
583
+ <button id="closeModalButton" class="text-gray-400 hover:text-white">
584
+ <i class="fas fa-times"></i>
585
+ </button>
586
+ </div>
587
+ <div class="p-4">
588
+ <form id="eventForm">
589
+ <input type="hidden" id="eventId" />
590
+ <div class="mb-4">
591
+ <label
592
+ for="eventTitle"
593
+ class="block text-sm font-medium text-gray-300 mb-1"
594
+ >Título do Evento</label
595
+ >
596
+ <input
597
+ type="text"
598
+ id="eventTitle"
599
+ class="bg-gray-700 border border-gray-600 text-white text-sm rounded-lg block w-full p-2.5 focus:ring-blue-500 focus:border-blue-500"
600
+ required
601
+ />
602
+ </div>
603
+ <div class="mb-4">
604
+ <label
605
+ for="eventCategory"
606
+ class="block text-sm font-medium text-gray-300 mb-1"
607
+ >Categoria</label
608
+ >
609
+ <select
610
+ id="eventCategory"
611
+ class="bg-gray-700 border border-gray-600 text-white text-sm rounded-lg block w-full p-2.5 focus:ring-blue-500 focus:border-blue-500"
612
+ >
613
+ <option value="event-planning">
614
+ Planejamento de Novo Evento
615
+ </option>
616
+ <option value="event-meeting">Reunião</option>
617
+ <option value="event-reports">Geração de Relatórios</option>
618
+ <option value="event-theme">Criar Novo Tema</option>
619
+ <option value="event-birthday">Festa de Aniversário</option>
620
+ </select>
621
+ </div>
622
+ <div class="grid grid-cols-2 gap-4 mb-4">
623
+ <div>
624
+ <label
625
+ for="eventStartDate"
626
+ class="block text-sm font-medium text-gray-300 mb-1"
627
+ >Data Início</label
628
+ >
629
+ <input
630
+ type="date"
631
+ id="eventStartDate"
632
+ class="bg-gray-700 border border-gray-600 text-white text-sm rounded-lg block w-full p-2.5 focus:ring-blue-500 focus:border-blue-500"
633
+ required
634
+ />
635
+ </div>
636
+ <div>
637
+ <label
638
+ for="eventStartTime"
639
+ class="block text-sm font-medium text-gray-300 mb-1"
640
+ >Hora Início</label
641
+ >
642
+ <input
643
+ type="time"
644
+ id="eventStartTime"
645
+ class="bg-gray-700 border border-gray-600 text-white text-sm rounded-lg block w-full p-2.5 focus:ring-blue-500 focus:border-blue-500"
646
+ />
647
+ </div>
648
+ </div>
649
+ <div class="grid grid-cols-2 gap-4 mb-4">
650
+ <div>
651
+ <label
652
+ for="eventEndDate"
653
+ class="block text-sm font-medium text-gray-300 mb-1"
654
+ >Data Fim</label
655
+ >
656
+ <input
657
+ type="date"
658
+ id="eventEndDate"
659
+ class="bg-gray-700 border border-gray-600 text-white text-sm rounded-lg block w-full p-2.5 focus:ring-blue-500 focus:border-blue-500"
660
+ />
661
+ </div>
662
+ <div>
663
+ <label
664
+ for="eventEndTime"
665
+ class="block text-sm font-medium text-gray-300 mb-1"
666
+ >Hora Fim</label
667
+ >
668
+ <input
669
+ type="time"
670
+ id="eventEndTime"
671
+ class="bg-gray-700 border border-gray-600 text-white text-sm rounded-lg block w-full p-2.5 focus:ring-blue-500 focus:border-blue-500"
672
+ />
673
+ </div>
674
+ </div>
675
+ <div class="mb-4">
676
+ <label
677
+ for="eventDescription"
678
+ class="block text-sm font-medium text-gray-300 mb-1"
679
+ >Descrição</label
680
+ >
681
+ <textarea
682
+ id="eventDescription"
683
+ rows="3"
684
+ class="bg-gray-700 border border-gray-600 text-white text-sm rounded-lg block w-full p-2.5 focus:ring-blue-500 focus:border-blue-500"
685
+ ></textarea>
686
+ </div>
687
+ <div class="flex justify-end space-x-2">
688
+ <button
689
+ type="button"
690
+ id="deleteEventButton"
691
+ class="text-white bg-red-700 hover:bg-red-800 px-4 py-2 rounded-lg hidden"
692
+ >
693
+ Excluir
694
+ </button>
695
+ <button
696
+ type="button"
697
+ id="cancelEventButton"
698
+ class="text-white bg-gray-700 hover:bg-gray-600 px-4 py-2 rounded-lg"
699
+ >
700
+ Cancelar
701
+ </button>
702
+ <button
703
+ type="submit"
704
+ id="saveEventButton"
705
+ class="text-white bg-blue-700 hover:bg-blue-800 px-4 py-2 rounded-lg"
706
+ >
707
+ Salvar
708
+ </button>
709
+ </div>
710
+ </form>
711
+ </div>
712
+ </div>
713
+ </div>
714
+
715
+ <script>
716
+ // Sample events data
717
+ let events = [
718
+ {
719
+ id: "1",
720
+ title: "Evento de dia inteiro",
721
+ category: "event-meeting",
722
+ start: "2025-04-01",
723
+ end: "2025-04-01",
724
+ allDay: true,
725
+ description: "Evento que dura o dia todo",
726
+ },
727
+ {
728
+ id: "2",
729
+ title: "Visitar Curso Online",
730
+ category: "event-reports",
731
+ start: "2025-04-08T09:00:00",
732
+ end: "2025-04-09T17:00:00",
733
+ allDay: false,
734
+ description: "Participar do curso online sobre desenvolvimento web",
735
+ },
736
+ {
737
+ id: "3",
738
+ title: "Reunião com equipe",
739
+ category: "event-planning",
740
+ start: "2025-04-11T14:00:00",
741
+ end: "2025-04-11T15:30:00",
742
+ allDay: false,
743
+ description: "Reunião semanal com a equipe de desenvolvimento",
744
+ },
745
+ {
746
+ id: "4",
747
+ title: "Festa de Aniversário",
748
+ category: "event-birthday",
749
+ start: "2025-04-13T19:00:00",
750
+ end: "2025-04-14T01:00:00",
751
+ allDay: false,
752
+ description: "Festa de aniversário do colega de trabalho",
753
+ },
754
+ {
755
+ id: "5",
756
+ title: "Evento Repetitivo",
757
+ category: "event-theme",
758
+ start: "2025-04-16T10:00:00",
759
+ end: "2025-04-18T16:00:00",
760
+ allDay: false,
761
+ description: "Evento que se repete por vários dias",
762
+ },
763
+ {
764
+ id: "6",
765
+ title: "Planejamento de Estratégia Semanal",
766
+ category: "event-planning",
767
+ start: "2025-04-21T09:00:00",
768
+ end: "2025-04-21T11:00:00",
769
+ allDay: false,
770
+ description: "Planejamento da estratégia para a semana",
771
+ },
772
+ {
773
+ id: "7",
774
+ title: "Reunião com o Cliente Alexis",
775
+ category: "event-theme",
776
+ start: "2025-05-04T13:00:00",
777
+ end: "2025-05-04T15:00:00",
778
+ allDay: false,
779
+ description: "Reunião importante com o cliente principal",
780
+ },
781
+ {
782
+ id: "8",
783
+ title: "Projeto Velzon",
784
+ category: "event-meeting",
785
+ start: "2025-05-05T08:00:00",
786
+ end: "2025-05-05T17:00:00",
787
+ allDay: true,
788
+ description: "Início do novo projeto Velzon",
789
+ },
790
+ {
791
+ id: "9",
792
+ title: "Dia Mundial do Braille",
793
+ category: "event-planning",
794
+ start: "2022-01-03T21:00:00",
795
+ end: "2022-01-04T00:00:00",
796
+ allDay: false,
797
+ description: "Evento comemorativo",
798
+ },
799
+ {
800
+ id: "10",
801
+ title: "Dia Mundial da Hanseníase",
802
+ category: "event-reports",
803
+ start: "2022-01-29T21:00:00",
804
+ end: "2022-01-30T00:00:00",
805
+ allDay: false,
806
+ description: "Evento comemorativo",
807
+ },
808
+ {
809
+ id: "11",
810
+ title: "Dia Internacional da Língua Materna",
811
+ category: "event-birthday",
812
+ start: "2022-02-20T21:00:00",
813
+ end: "2022-02-21T00:00:00",
814
+ allDay: false,
815
+ description: "Evento comemorativo",
816
+ },
817
+ {
818
+ id: "12",
819
+ title: "Reunião de Equipe",
820
+ category: "event-meeting",
821
+ start: "2022-02-21T21:00:00",
822
+ end: "2022-02-22T00:00:00",
823
+ allDay: false,
824
+ description: "Reunião mensal da equipe",
825
+ },
826
+ ];
827
+
828
+ // Calendar state
829
+ let currentView = "month";
830
+ let currentDate = new Date(2025, 3, 1); // April 2025
831
+
832
+ // DOM Elements
833
+ const sidebarToggle = document.getElementById("sidebarToggle");
834
+ const sidebar = document.getElementById("sidebar");
835
+ const sidebarOverlay = document.getElementById("sidebarOverlay");
836
+ const notificationsButton = document.getElementById(
837
+ "notificationsButton"
838
+ );
839
+ const notificationsDropdown = document.getElementById(
840
+ "notificationsDropdown"
841
+ );
842
+ const createEventButton = document.getElementById("createEventButton");
843
+ const upcomingEventsList = document.getElementById("upcomingEventsList");
844
+ const currentPeriodTitle = document.getElementById("currentPeriodTitle");
845
+ const prevPeriodButton = document.getElementById("prevPeriodButton");
846
+ const nextPeriodButton = document.getElementById("nextPeriodButton");
847
+ const todayButton = document.getElementById("todayButton");
848
+ const viewButtons = document.querySelectorAll(".view-button");
849
+ const monthView = document.getElementById("monthView");
850
+ const monthGrid = document.getElementById("monthGrid");
851
+ const weekView = document.getElementById("weekView");
852
+ const weekHeader = document.getElementById("weekHeader");
853
+ const weekGrid = document.getElementById("weekGrid");
854
+ const dayView = document.getElementById("dayView");
855
+ const dayHeader = document.getElementById("dayHeader");
856
+ const dayGrid = document.getElementById("dayGrid");
857
+ const listView = document.getElementById("listView");
858
+ const listHeader = document.getElementById("listHeader");
859
+ const listGrid = document.getElementById("listGrid");
860
+ const eventModal = document.getElementById("eventModal");
861
+ const modalTitle = document.getElementById("modalTitle");
862
+ const closeModalButton = document.getElementById("closeModalButton");
863
+ const eventForm = document.getElementById("eventForm");
864
+ const eventIdInput = document.getElementById("eventId");
865
+ const eventTitleInput = document.getElementById("eventTitle");
866
+ const eventCategoryInput = document.getElementById("eventCategory");
867
+ const eventStartDateInput = document.getElementById("eventStartDate");
868
+ const eventStartTimeInput = document.getElementById("eventStartTime");
869
+ const eventEndDateInput = document.getElementById("eventEndDate");
870
+ const eventEndTimeInput = document.getElementById("eventEndTime");
871
+ const eventDescriptionInput = document.getElementById("eventDescription");
872
+ const deleteEventButton = document.getElementById("deleteEventButton");
873
+ const cancelEventButton = document.getElementById("cancelEventButton");
874
+ const saveEventButton = document.getElementById("saveEventButton");
875
+
876
+ // Initialize the calendar
877
+ document.addEventListener("DOMContentLoaded", () => {
878
+ renderCalendar();
879
+ renderUpcomingEvents();
880
+
881
+ // Set today's date in the date inputs
882
+ const today = new Date();
883
+ const todayStr = today.toISOString().split("T")[0];
884
+ eventStartDateInput.value = todayStr;
885
+ eventEndDateInput.value = todayStr;
886
+ });
887
+
888
+ // Toggle sidebar on mobile
889
+ sidebarToggle.addEventListener("click", () => {
890
+ sidebar.classList.toggle("open");
891
+ sidebarOverlay.classList.toggle("open");
892
+ });
893
+
894
+ sidebarOverlay.addEventListener("click", () => {
895
+ sidebar.classList.remove("open");
896
+ sidebarOverlay.classList.remove("open");
897
+ });
898
+
899
+ // Toggle notifications dropdown
900
+ notificationsButton.addEventListener("click", () => {
901
+ notificationsDropdown.classList.toggle("show");
902
+ });
903
+
904
+ // Close dropdown when clicking outside
905
+ document.addEventListener("click", (event) => {
906
+ if (
907
+ !notificationsButton.contains(event.target) &&
908
+ !notificationsDropdown.contains(event.target)
909
+ ) {
910
+ notificationsDropdown.classList.remove("show");
911
+ }
912
+ });
913
+
914
+ // View buttons
915
+ viewButtons.forEach((button) => {
916
+ button.addEventListener("click", () => {
917
+ currentView = button.dataset.view;
918
+ updateActiveViewButton();
919
+ renderCalendar();
920
+ });
921
+ });
922
+
923
+ // Navigation buttons
924
+ prevPeriodButton.addEventListener("click", () => {
925
+ navigatePeriod(-1);
926
+ });
927
+
928
+ nextPeriodButton.addEventListener("click", () => {
929
+ navigatePeriod(1);
930
+ });
931
+
932
+ todayButton.addEventListener("click", () => {
933
+ currentDate = new Date();
934
+ renderCalendar();
935
+ });
936
+
937
+ // Event modal
938
+ createEventButton.addEventListener("click", () => {
939
+ openEventModal();
940
+ });
941
+
942
+ closeModalButton.addEventListener("click", () => {
943
+ closeEventModal();
944
+ });
945
+
946
+ cancelEventButton.addEventListener("click", () => {
947
+ closeEventModal();
948
+ });
949
+
950
+ // Form submission
951
+ eventForm.addEventListener("submit", (e) => {
952
+ e.preventDefault();
953
+ saveEvent();
954
+ });
955
+
956
+ deleteEventButton.addEventListener("click", () => {
957
+ deleteEvent();
958
+ });
959
+
960
+ // Calendar functions
961
+ function renderCalendar() {
962
+ updatePeriodTitle();
963
+
964
+ switch (currentView) {
965
+ case "month":
966
+ renderMonthView();
967
+ break;
968
+ case "week":
969
+ renderWeekView();
970
+ break;
971
+ case "day":
972
+ renderDayView();
973
+ break;
974
+ case "list":
975
+ renderListView();
976
+ break;
977
+ }
978
+ }
979
+
980
+ function renderMonthView() {
981
+ // Hide other views and show month view
982
+ hideAllViews();
983
+ monthView.classList.remove("hidden");
984
+
985
+ // Clear the grid
986
+ monthGrid.innerHTML = "";
987
+
988
+ // Add day headers
989
+ const daysOfWeek = ["Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb"];
990
+ daysOfWeek.forEach((day) => {
991
+ const dayElement = document.createElement("div");
992
+ dayElement.className =
993
+ "text-center text-gray-400 text-sm font-medium";
994
+ dayElement.textContent = day;
995
+ monthGrid.appendChild(dayElement);
996
+ });
997
+
998
+ // Get first day of month and how many days to show from previous month
999
+ const firstDay = new Date(
1000
+ currentDate.getFullYear(),
1001
+ currentDate.getMonth(),
1002
+ 1
1003
+ );
1004
+ const startingDayOfWeek = firstDay.getDay();
1005
+
1006
+ // Get last day of month and how many days to show from next month
1007
+ const lastDay = new Date(
1008
+ currentDate.getFullYear(),
1009
+ currentDate.getMonth() + 1,
1010
+ 0
1011
+ );
1012
+ const daysInMonth = lastDay.getDate();
1013
+
1014
+ // Calculate how many rows we need
1015
+ const totalDaysToShow = startingDayOfWeek + daysInMonth;
1016
+ const rowsNeeded = Math.ceil(totalDaysToShow / 7);
1017
+
1018
+ // Get previous month's days if needed
1019
+ const prevMonthLastDay = new Date(
1020
+ currentDate.getFullYear(),
1021
+ currentDate.getMonth(),
1022
+ 0
1023
+ ).getDate();
1024
+
1025
+ // Add days from previous month
1026
+ for (let i = 0; i < startingDayOfWeek; i++) {
1027
+ const dayElement = createDayElement(
1028
+ prevMonthLastDay - startingDayOfWeek + i + 1,
1029
+ true
1030
+ );
1031
+ monthGrid.appendChild(dayElement);
1032
+ }
1033
+
1034
+ // Add days of current month
1035
+ for (let i = 1; i <= daysInMonth; i++) {
1036
+ const dayElement = createDayElement(i, false);
1037
+
1038
+ // Add events for this day
1039
+ const dateStr = `${currentDate.getFullYear()}-${(
1040
+ currentDate.getMonth() + 1
1041
+ )
1042
+ .toString()
1043
+ .padStart(2, "0")}-${i.toString().padStart(2, "0")}`;
1044
+ const dayEvents = getEventsForDate(dateStr);
1045
+
1046
+ if (dayEvents.length > 0) {
1047
+ const eventsContainer = document.createElement("div");
1048
+ eventsContainer.className = "text-xs mt-1 space-y-1";
1049
+
1050
+ dayEvents.forEach((event) => {
1051
+ const eventElement = document.createElement("span");
1052
+ eventElement.className = `inline-block ${event.category} text-white rounded px-1 truncate`;
1053
+ eventElement.textContent = event.title;
1054
+ eventElement.dataset.eventId = event.id;
1055
+ eventElement.addEventListener("click", (e) => {
1056
+ e.stopPropagation();
1057
+ openEventModal(event.id);
1058
+ });
1059
+ eventsContainer.appendChild(eventElement);
1060
+ });
1061
+
1062
+ dayElement.appendChild(eventsContainer);
1063
+ }
1064
+
1065
+ monthGrid.appendChild(dayElement);
1066
+ }
1067
+
1068
+ // Add days from next month if needed
1069
+ const daysToAdd = rowsNeeded * 7 - (startingDayOfWeek + daysInMonth);
1070
+ for (let i = 1; i <= daysToAdd; i++) {
1071
+ const dayElement = createDayElement(i, true);
1072
+ monthGrid.appendChild(dayElement);
1073
+ }
1074
+ }
1075
+
1076
+ function createDayElement(day, isOtherMonth) {
1077
+ const dayElement = document.createElement("div");
1078
+ dayElement.className = `calendar-day bg-gray-900 h-24 p-1 rounded cursor-pointer ${
1079
+ isOtherMonth ? "text-gray-600" : "text-gray-300"
1080
+ }`;
1081
+
1082
+ const dayNumber = document.createElement("div");
1083
+ dayNumber.className = "text-right";
1084
+ dayNumber.textContent = day;
1085
+ dayElement.appendChild(dayNumber);
1086
+
1087
+ // Highlight today
1088
+ const today = new Date();
1089
+ if (
1090
+ !isOtherMonth &&
1091
+ currentDate.getFullYear() === today.getFullYear() &&
1092
+ currentDate.getMonth() === today.getMonth() &&
1093
+ day === today.getDate()
1094
+ ) {
1095
+ dayNumber.className += " font-bold text-blue-400";
1096
+ }
1097
+
1098
+ // Add click event to create new event
1099
+ dayElement.addEventListener("click", () => {
1100
+ const dateStr = `${currentDate.getFullYear()}-${(
1101
+ currentDate.getMonth() + 1
1102
+ )
1103
+ .toString()
1104
+ .padStart(2, "0")}-${day.toString().padStart(2, "0")}`;
1105
+ openEventModal(null, dateStr);
1106
+ });
1107
+
1108
+ return dayElement;
1109
+ }
1110
+
1111
+ function renderWeekView() {
1112
+ // Hide other views and show week view
1113
+ hideAllViews();
1114
+ weekView.classList.remove("hidden");
1115
+
1116
+ // Clear the grid
1117
+ weekHeader.innerHTML = "";
1118
+ weekGrid.innerHTML = "";
1119
+
1120
+ // Add time column header
1121
+ const timeHeader = document.createElement("div");
1122
+ timeHeader.className = "text-center text-gray-400 text-sm font-medium";
1123
+ timeHeader.textContent = "Hora";
1124
+ weekHeader.appendChild(timeHeader);
1125
+
1126
+ // Get start and end of week
1127
+ const weekStart = new Date(currentDate);
1128
+ weekStart.setDate(currentDate.getDate() - currentDate.getDay());
1129
+
1130
+ const weekEnd = new Date(weekStart);
1131
+ weekEnd.setDate(weekStart.getDate() + 6);
1132
+
1133
+ // Add day headers
1134
+ for (let i = 0; i < 7; i++) {
1135
+ const day = new Date(weekStart);
1136
+ day.setDate(weekStart.getDate() + i);
1137
+
1138
+ const dayHeader = document.createElement("div");
1139
+ dayHeader.className = "text-center text-gray-400 text-sm font-medium";
1140
+
1141
+ const dayName = ["Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb"][
1142
+ day.getDay()
1143
+ ];
1144
+ dayHeader.textContent = `${dayName} ${day.getDate()}/${
1145
+ day.getMonth() + 1
1146
+ }`;
1147
+
1148
+ weekHeader.appendChild(dayHeader);
1149
+ }
1150
+
1151
+ // Add time slots
1152
+ for (let hour = 8; hour < 20; hour++) {
1153
+ // Time label
1154
+ const timeLabel = document.createElement("div");
1155
+ timeLabel.className = "text-xs text-gray-400 text-right pr-2";
1156
+ timeLabel.textContent = `${hour}:00`;
1157
+ timeLabel.style.gridColumn = "1";
1158
+ timeLabel.style.gridRow = `${hour - 7}`;
1159
+ weekGrid.appendChild(timeLabel);
1160
+
1161
+ // Day columns
1162
+ for (let day = 0; day < 7; day++) {
1163
+ const dayDate = new Date(weekStart);
1164
+ dayDate.setDate(weekStart.getDate() + day);
1165
+ dayDate.setHours(hour);
1166
+
1167
+ const dayStr = dayDate.toISOString().split("T")[0];
1168
+ const hourEvents = getEventsForDateAndHour(dayStr, hour);
1169
+
1170
+ const timeSlot = document.createElement("div");
1171
+ timeSlot.className = "hour-slot relative border-r border-gray-700";
1172
+ timeSlot.style.gridColumn = `${day + 2}`;
1173
+ timeSlot.style.gridRow = `${hour - 7}`;
1174
+
1175
+ if (hourEvents.length > 0) {
1176
+ hourEvents.forEach((event) => {
1177
+ const eventElement = document.createElement("div");
1178
+ eventElement.className = `absolute inset-1 ${event.category} text-white text-xs p-1 rounded overflow-hidden`;
1179
+ eventElement.textContent = event.title;
1180
+ eventElement.dataset.eventId = event.id;
1181
+ eventElement.addEventListener("click", (e) => {
1182
+ e.stopPropagation();
1183
+ openEventModal(event.id);
1184
+ });
1185
+ timeSlot.appendChild(eventElement);
1186
+ });
1187
+ } else {
1188
+ timeSlot.addEventListener("click", () => {
1189
+ const dateStr = dayDate.toISOString().split("T")[0];
1190
+ const timeStr = `${hour.toString().padStart(2, "0")}:00`;
1191
+ openEventModal(null, dateStr, timeStr);
1192
+ });
1193
+ }
1194
+
1195
+ weekGrid.appendChild(timeSlot);
1196
+ }
1197
+ }
1198
+ }
1199
+
1200
+ function renderDayView() {
1201
+ // Hide other views and show day view
1202
+ hideAllViews();
1203
+ dayView.classList.remove("hidden");
1204
+
1205
+ // Clear the grid
1206
+ dayHeader.innerHTML = "";
1207
+ dayGrid.innerHTML = "";
1208
+
1209
+ // Set day header
1210
+ const dayName = [
1211
+ "Domingo",
1212
+ "Segunda",
1213
+ "Terça",
1214
+ "Quarta",
1215
+ "Quinta",
1216
+ "Sexta",
1217
+ "Sábado",
1218
+ ][currentDate.getDay()];
1219
+ dayHeader.textContent = `${dayName}, ${currentDate.getDate()} de ${
1220
+ [
1221
+ "Janeiro",
1222
+ "Fevereiro",
1223
+ "Março",
1224
+ "Abril",
1225
+ "Maio",
1226
+ "Junho",
1227
+ "Julho",
1228
+ "Agosto",
1229
+ "Setembro",
1230
+ "Outubro",
1231
+ "Novembro",
1232
+ "Dezembro",
1233
+ ][currentDate.getMonth()]
1234
+ } de ${currentDate.getFullYear()}`;
1235
+
1236
+ // Add time slots
1237
+ for (let hour = 8; hour < 20; hour++) {
1238
+ const timeSlot = document.createElement("div");
1239
+ timeSlot.className = "hour-slot flex";
1240
+
1241
+ // Time label
1242
+ const timeLabel = document.createElement("div");
1243
+ timeLabel.className = "text-xs text-gray-400 w-16 text-right pr-2";
1244
+ timeLabel.textContent = `${hour}:00`;
1245
+ timeSlot.appendChild(timeLabel);
1246
+
1247
+ // Event area
1248
+ const eventArea = document.createElement("div");
1249
+ eventArea.className = "flex-1 relative";
1250
+
1251
+ const dayStr = currentDate.toISOString().split("T")[0];
1252
+ const hourEvents = getEventsForDateAndHour(dayStr, hour);
1253
+
1254
+ if (hourEvents.length > 0) {
1255
+ hourEvents.forEach((event) => {
1256
+ const eventElement = document.createElement("div");
1257
+ eventElement.className = `absolute inset-1 ${event.category} text-white text-xs p-1 rounded overflow-hidden`;
1258
+ eventElement.textContent = event.title;
1259
+ eventElement.dataset.eventId = event.id;
1260
+ eventElement.addEventListener("click", (e) => {
1261
+ e.stopPropagation();
1262
+ openEventModal(event.id);
1263
+ });
1264
+ eventArea.appendChild(eventElement);
1265
+ });
1266
+ } else {
1267
+ eventArea.addEventListener("click", () => {
1268
+ const dateStr = currentDate.toISOString().split("T")[0];
1269
+ const timeStr = `${hour.toString().padStart(2, "0")}:00`;
1270
+ openEventModal(null, dateStr, timeStr);
1271
+ });
1272
+ }
1273
+
1274
+ timeSlot.appendChild(eventArea);
1275
+ dayGrid.appendChild(timeSlot);
1276
+ }
1277
+ }
1278
+
1279
+ function renderListView() {
1280
+ // Hide other views and show list view
1281
+ hideAllViews();
1282
+ listView.classList.remove("hidden");
1283
+
1284
+ // Clear the grid
1285
+ listHeader.innerHTML = "";
1286
+ listGrid.innerHTML = "";
1287
+
1288
+ // Set list header
1289
+ if (currentView === "month") {
1290
+ const monthName = [
1291
+ "Janeiro",
1292
+ "Fevereiro",
1293
+ "Março",
1294
+ "Abril",
1295
+ "Maio",
1296
+ "Junho",
1297
+ "Julho",
1298
+ "Agosto",
1299
+ "Setembro",
1300
+ "Outubro",
1301
+ "Novembro",
1302
+ "Dezembro",
1303
+ ][currentDate.getMonth()];
1304
+ listHeader.textContent = `Eventos de ${monthName} ${currentDate.getFullYear()}`;
1305
+
1306
+ // Get events for the month
1307
+ const monthEvents = getEventsForMonth(
1308
+ currentDate.getFullYear(),
1309
+ currentDate.getMonth() + 1
1310
+ );
1311
+ renderEventList(monthEvents);
1312
+ } else if (currentView === "week") {
1313
+ const weekStart = new Date(currentDate);
1314
+ weekStart.setDate(currentDate.getDate() - currentDate.getDay());
1315
+
1316
+ const weekEnd = new Date(weekStart);
1317
+ weekEnd.setDate(weekStart.getDate() + 6);
1318
+
1319
+ listHeader.textContent = `Eventos de ${weekStart.getDate()}/${
1320
+ weekStart.getMonth() + 1
1321
+ } a ${weekEnd.getDate()}/${weekEnd.getMonth() + 1}`;
1322
+
1323
+ // Get events for the week
1324
+ const weekEvents = getEventsForWeek(weekStart, weekEnd);
1325
+ renderEventList(weekEvents);
1326
+ } else if (currentView === "day") {
1327
+ listHeader.textContent = `Eventos de ${currentDate.getDate()}/${
1328
+ currentDate.getMonth() + 1
1329
+ }/${currentDate.getFullYear()}`;
1330
+
1331
+ // Get events for the day
1332
+ const dayEvents = getEventsForDate(
1333
+ currentDate.toISOString().split("T")[0]
1334
+ );
1335
+ renderEventList(dayEvents);
1336
+ }
1337
+ }
1338
+
1339
+ function renderEventList(events) {
1340
+ if (events.length === 0) {
1341
+ const noEvents = document.createElement("div");
1342
+ noEvents.className = "text-center text-gray-400 py-4";
1343
+ noEvents.textContent = "Nenhum evento encontrado";
1344
+ listGrid.appendChild(noEvents);
1345
+ return;
1346
+ }
1347
+
1348
+ events.sort((a, b) => new Date(a.start) - new Date(b.start));
1349
+
1350
+ events.forEach((event) => {
1351
+ const eventElement = document.createElement("div");
1352
+ eventElement.className =
1353
+ "event-item bg-gray-700 rounded p-3 transition-transform duration-200 cursor-pointer mb-2";
1354
+ eventElement.dataset.eventId = event.id;
1355
+
1356
+ const startDate = new Date(event.start);
1357
+ const endDate = new Date(event.end);
1358
+
1359
+ let dateStr, timeStr;
1360
+
1361
+ if (event.allDay) {
1362
+ dateStr = startDate.toLocaleDateString("pt-BR");
1363
+ timeStr = "Dia inteiro";
1364
+ } else {
1365
+ dateStr = startDate.toLocaleDateString("pt-BR");
1366
+ const startTime = startDate.toLocaleTimeString("pt-BR", {
1367
+ hour: "2-digit",
1368
+ minute: "2-digit",
1369
+ });
1370
+ const endTime = endDate.toLocaleTimeString("pt-BR", {
1371
+ hour: "2-digit",
1372
+ minute: "2-digit",
1373
+ });
1374
+ timeStr = `${startTime} - ${endTime}`;
1375
+ }
1376
+
1377
+ eventElement.innerHTML = `
1378
+ <div class="flex justify-between items-start">
1379
+ <div>
1380
+ <h4 class="text-white font-medium">${event.title}</h4>
1381
+ <p class="text-gray-400 text-sm">${dateStr}</p>
1382
+ </div>
1383
+ <span class="bg-blue-600 text-white text-xs px-2 py-1 rounded">${timeStr}</span>
1384
+ </div>
1385
+ `;
1386
+
1387
+ eventElement.addEventListener("click", () => {
1388
+ openEventModal(event.id);
1389
+ });
1390
+
1391
+ listGrid.appendChild(eventElement);
1392
+ });
1393
+ }
1394
+
1395
+ function renderUpcomingEvents() {
1396
+ upcomingEventsList.innerHTML = "";
1397
+
1398
+ // Get upcoming events (next 30 days)
1399
+ const today = new Date();
1400
+ today.setHours(0, 0, 0, 0);
1401
+
1402
+ const nextMonth = new Date(today);
1403
+ nextMonth.setMonth(today.getMonth() + 1);
1404
+
1405
+ const upcomingEvents = events.filter((event) => {
1406
+ const eventDate = new Date(event.start);
1407
+ return eventDate >= today && eventDate <= nextMonth;
1408
+ });
1409
+
1410
+ if (upcomingEvents.length === 0) {
1411
+ const noEvents = document.createElement("div");
1412
+ noEvents.className = "text-center text-gray-400 py-4";
1413
+ noEvents.textContent = "Nenhum evento próximo";
1414
+ upcomingEventsList.appendChild(noEvents);
1415
+ return;
1416
+ }
1417
+
1418
+ upcomingEvents.sort((a, b) => new Date(a.start) - new Date(b.start));
1419
+
1420
+ upcomingEvents.slice(0, 5).forEach((event) => {
1421
+ const eventElement = document.createElement("div");
1422
+ eventElement.className =
1423
+ "event-item bg-gray-700 rounded p-3 transition-transform duration-200 cursor-pointer mb-2";
1424
+ eventElement.dataset.eventId = event.id;
1425
+
1426
+ const startDate = new Date(event.start);
1427
+ const endDate = new Date(event.end);
1428
+
1429
+ let dateStr, timeStr;
1430
+
1431
+ if (event.allDay) {
1432
+ dateStr = startDate.toLocaleDateString("pt-BR");
1433
+ timeStr = "Dia inteiro";
1434
+ } else {
1435
+ dateStr = startDate.toLocaleDateString("pt-BR");
1436
+ const startTime = startDate.toLocaleTimeString("pt-BR", {
1437
+ hour: "2-digit",
1438
+ minute: "2-digit",
1439
+ });
1440
+ const endTime = endDate.toLocaleTimeString("pt-BR", {
1441
+ hour: "2-digit",
1442
+ minute: "2-digit",
1443
+ });
1444
+ timeStr = `${startTime} - ${endTime}`;
1445
+ }
1446
+
1447
+ eventElement.innerHTML = `
1448
+ <div class="flex justify-between items-start">
1449
+ <div>
1450
+ <h4 class="text-white font-medium">${event.title}</h4>
1451
+ <p class="text-gray-400 text-sm">${dateStr}</p>
1452
+ </div>
1453
+ <span class="bg-blue-600 text-white text-xs px-2 py-1 rounded">${timeStr}</span>
1454
+ </div>
1455
+ `;
1456
+
1457
+ eventElement.addEventListener("click", () => {
1458
+ openEventModal(event.id);
1459
+ });
1460
+
1461
+ upcomingEventsList.appendChild(eventElement);
1462
+ });
1463
+ }
1464
+
1465
+ function hideAllViews() {
1466
+ monthView.classList.add("hidden");
1467
+ weekView.classList.add("hidden");
1468
+ dayView.classList.add("hidden");
1469
+ listView.classList.add("hidden");
1470
+ }
1471
+
1472
+ function updateActiveViewButton() {
1473
+ viewButtons.forEach((button) => {
1474
+ if (button.dataset.view === currentView) {
1475
+ button.classList.add("bg-gray-800", "text-white");
1476
+ button.classList.remove("text-gray-300", "hover:text-white");
1477
+ } else {
1478
+ button.classList.remove("bg-gray-800", "text-white");
1479
+ button.classList.add("text-gray-300", "hover:text-white");
1480
+ }
1481
+ });
1482
+ }
1483
+
1484
+ function updatePeriodTitle() {
1485
+ if (currentView === "month") {
1486
+ const monthName = [
1487
+ "Janeiro",
1488
+ "Fevereiro",
1489
+ "Março",
1490
+ "Abril",
1491
+ "Maio",
1492
+ "Junho",
1493
+ "Julho",
1494
+ "Agosto",
1495
+ "Setembro",
1496
+ "Outubro",
1497
+ "Novembro",
1498
+ "Dezembro",
1499
+ ][currentDate.getMonth()];
1500
+ currentPeriodTitle.textContent = `${monthName} ${currentDate.getFullYear()}`;
1501
+ } else if (currentView === "week") {
1502
+ const weekStart = new Date(currentDate);
1503
+ weekStart.setDate(currentDate.getDate() - currentDate.getDay());
1504
+
1505
+ const weekEnd = new Date(weekStart);
1506
+ weekEnd.setDate(weekStart.getDate() + 6);
1507
+
1508
+ currentPeriodTitle.textContent = `${weekStart.getDate()}/${
1509
+ weekStart.getMonth() + 1
1510
+ } - ${weekEnd.getDate()}/${
1511
+ weekEnd.getMonth() + 1
1512
+ } ${weekEnd.getFullYear()}`;
1513
+ } else if (currentView === "day") {
1514
+ const dayName = [
1515
+ "Domingo",
1516
+ "Segunda",
1517
+ "Terça",
1518
+ "Quarta",
1519
+ "Quinta",
1520
+ "Sexta",
1521
+ "Sábado",
1522
+ ][currentDate.getDay()];
1523
+ currentPeriodTitle.textContent = `${dayName}, ${currentDate.getDate()} de ${
1524
+ [
1525
+ "Janeiro",
1526
+ "Fevereiro",
1527
+ "Março",
1528
+ "Abril",
1529
+ "Maio",
1530
+ "Junho",
1531
+ "Julho",
1532
+ "Agosto",
1533
+ "Setembro",
1534
+ "Outubro",
1535
+ "Novembro",
1536
+ "Dezembro",
1537
+ ][currentDate.getMonth()]
1538
+ } de ${currentDate.getFullYear()}`;
1539
+ } else if (currentView === "list") {
1540
+ if (currentView === "month") {
1541
+ const monthName = [
1542
+ "Janeiro",
1543
+ "Fevereiro",
1544
+ "Março",
1545
+ "Abril",
1546
+ "Maio",
1547
+ "Junho",
1548
+ "Julho",
1549
+ "Agosto",
1550
+ "Setembro",
1551
+ "Outubro",
1552
+ "Novembro",
1553
+ "Dezembro",
1554
+ ][currentDate.getMonth()];
1555
+ currentPeriodTitle.textContent = `Lista: ${monthName} ${currentDate.getFullYear()}`;
1556
+ } else if (currentView === "week") {
1557
+ const weekStart = new Date(currentDate);
1558
+ weekStart.setDate(currentDate.getDate() - currentDate.getDay());
1559
+
1560
+ const weekEnd = new Date(weekStart);
1561
+ weekEnd.setDate(weekStart.getDate() + 6);
1562
+
1563
+ currentPeriodTitle.textContent = `Lista: ${weekStart.getDate()}/${
1564
+ weekStart.getMonth() + 1
1565
+ } - ${weekEnd.getDate()}/${weekEnd.getMonth() + 1}`;
1566
+ } else if (currentView === "day") {
1567
+ currentPeriodTitle.textContent = `Lista: ${currentDate.getDate()}/${
1568
+ currentDate.getMonth() + 1
1569
+ }/${currentDate.getFullYear()}`;
1570
+ }
1571
+ }
1572
+ }
1573
+
1574
+ function navigatePeriod(direction) {
1575
+ if (currentView === "month") {
1576
+ currentDate.setMonth(currentDate.getMonth() + direction);
1577
+ } else if (currentView === "week") {
1578
+ currentDate.setDate(currentDate.getDate() + direction * 7);
1579
+ } else if (currentView === "day") {
1580
+ currentDate.setDate(currentDate.getDate() + direction);
1581
+ }
1582
+
1583
+ renderCalendar();
1584
+ }
1585
+
1586
+ // Event modal functions
1587
+ function openEventModal(eventId = null, dateStr = null, timeStr = null) {
1588
+ if (eventId) {
1589
+ // Edit existing event
1590
+ const event = events.find((e) => e.id === eventId);
1591
+ if (event) {
1592
+ modalTitle.textContent = "Editar Evento";
1593
+ eventIdInput.value = event.id;
1594
+ eventTitleInput.value = event.title;
1595
+ eventCategoryInput.value = event.category;
1596
+ eventDescriptionInput.value = event.description || "";
1597
+
1598
+ // Set start date/time
1599
+ const startDate = new Date(event.start);
1600
+ eventStartDateInput.value = startDate.toISOString().split("T")[0];
1601
+
1602
+ if (!event.allDay) {
1603
+ eventStartTimeInput.value = startDate
1604
+ .toTimeString()
1605
+ .substring(0, 5);
1606
+ } else {
1607
+ eventStartTimeInput.value = "";
1608
+ }
1609
+
1610
+ // Set end date/time
1611
+ const endDate = new Date(event.end);
1612
+ eventEndDateInput.value = endDate.toISOString().split("T")[0];
1613
+
1614
+ if (!event.allDay) {
1615
+ eventEndTimeInput.value = endDate.toTimeString().substring(0, 5);
1616
+ } else {
1617
+ eventEndTimeInput.value = "";
1618
+ }
1619
+
1620
+ // Show delete button
1621
+ deleteEventButton.classList.remove("hidden");
1622
+ }
1623
+ } else {
1624
+ // Create new event
1625
+ modalTitle.textContent = "Novo Evento";
1626
+ eventIdInput.value = "";
1627
+ eventTitleInput.value = "";
1628
+ eventCategoryInput.value = "event-planning";
1629
+ eventDescriptionInput.value = "";
1630
+
1631
+ // Set default dates/times
1632
+ if (dateStr) {
1633
+ eventStartDateInput.value = dateStr;
1634
+ eventEndDateInput.value = dateStr;
1635
+ } else {
1636
+ const today = new Date();
1637
+ const todayStr = today.toISOString().split("T")[0];
1638
+ eventStartDateInput.value = todayStr;
1639
+ eventEndDateInput.value = todayStr;
1640
+ }
1641
+
1642
+ if (timeStr) {
1643
+ eventStartTimeInput.value = timeStr;
1644
+
1645
+ // Set end time to 1 hour later
1646
+ const [hours, minutes] = timeStr.split(":");
1647
+ const endTime = new Date();
1648
+ endTime.setHours(parseInt(hours) + 1, parseInt(minutes), 0, 0);
1649
+ eventEndTimeInput.value = endTime.toTimeString().substring(0, 5);
1650
+ } else {
1651
+ eventStartTimeInput.value = "";
1652
+ eventEndTimeInput.value = "";
1653
+ }
1654
+
1655
+ // Hide delete button
1656
+ deleteEventButton.classList.add("hidden");
1657
+ }
1658
+
1659
+ eventModal.classList.remove("hidden");
1660
+ }
1661
+
1662
+ function closeEventModal() {
1663
+ eventModal.classList.add("hidden");
1664
+ }
1665
+
1666
+ function saveEvent() {
1667
+ const id = eventIdInput.value || generateId();
1668
+ const title = eventTitleInput.value.trim();
1669
+ const category = eventCategoryInput.value;
1670
+ const description = eventDescriptionInput.value.trim();
1671
+ const startDate = eventStartDateInput.value;
1672
+ const startTime = eventStartTimeInput.value;
1673
+ const endDate = eventEndDateInput.value;
1674
+ const endTime = eventEndTimeInput.value;
1675
+
1676
+ if (!title) {
1677
+ alert("Por favor, insira um título para o evento");
1678
+ return;
1679
+ }
1680
+
1681
+ // Determine if it's an all-day event
1682
+ const allDay = !startTime || !endTime;
1683
+
1684
+ // Format start and end dates
1685
+ let start, end;
1686
+
1687
+ if (allDay) {
1688
+ start = startDate;
1689
+ end = endDate;
1690
+ } else {
1691
+ start = `${startDate}T${startTime}:00`;
1692
+ end = `${endDate}T${endTime}:00`;
1693
+ }
1694
+
1695
+ // Check if end is before start
1696
+ if (new Date(end) < new Date(start)) {
1697
+ alert(
1698
+ "A data/hora de término não pode ser anterior à data/hora de início"
1699
+ );
1700
+ return;
1701
+ }
1702
+
1703
+ // Create or update event
1704
+ const eventIndex = events.findIndex((e) => e.id === id);
1705
+ const event = {
1706
+ id,
1707
+ title,
1708
+ category,
1709
+ description,
1710
+ start,
1711
+ end,
1712
+ allDay,
1713
+ };
1714
+
1715
+ if (eventIndex >= 0) {
1716
+ // Update existing event
1717
+ events[eventIndex] = event;
1718
+ } else {
1719
+ // Add new event
1720
+ events.push(event);
1721
+ }
1722
+
1723
+ // Close modal and refresh calendar
1724
+ closeEventModal();
1725
+ renderCalendar();
1726
+ renderUpcomingEvents();
1727
+ }
1728
+
1729
+ function deleteEvent() {
1730
+ const id = eventIdInput.value;
1731
+
1732
+ if (confirm("Tem certeza que deseja excluir este evento?")) {
1733
+ events = events.filter((e) => e.id !== id);
1734
+ closeEventModal();
1735
+ renderCalendar();
1736
+ renderUpcomingEvents();
1737
+ }
1738
+ }
1739
+
1740
+ function generateId() {
1741
+ return Math.random().toString(36).substring(2, 9);
1742
+ }
1743
+
1744
+ // Event filtering functions
1745
+ function getEventsForDate(dateStr) {
1746
+ return events.filter((event) => {
1747
+ const eventStart = new Date(event.start);
1748
+ const eventEnd = new Date(event.end);
1749
+ const targetDate = new Date(dateStr);
1750
+
1751
+ // Check if target date is between event start and end (inclusive)
1752
+ targetDate.setHours(0, 0, 0, 0);
1753
+ eventStart.setHours(0, 0, 0, 0);
1754
+ eventEnd.setHours(0, 0, 0, 0);
1755
+
1756
+ return targetDate >= eventStart && targetDate <= eventEnd;
1757
+ });
1758
+ }
1759
+
1760
+ function getEventsForDateAndHour(dateStr, hour) {
1761
+ return events.filter((event) => {
1762
+ if (event.allDay) return false;
1763
+
1764
+ const eventStart = new Date(event.start);
1765
+ const eventEnd = new Date(event.end);
1766
+ const targetDate = new Date(dateStr);
1767
+ targetDate.setHours(hour, 0, 0, 0);
1768
+
1769
+ // Check if target hour is between event start and end (inclusive)
1770
+ return targetDate >= eventStart && targetDate < eventEnd;
1771
+ });
1772
+ }
1773
+
1774
+ function getEventsForMonth(year, month) {
1775
+ return events.filter((event) => {
1776
+ const eventStart = new Date(event.start);
1777
+ return (
1778
+ eventStart.getFullYear() === year &&
1779
+ eventStart.getMonth() + 1 === month
1780
+ );
1781
+ });
1782
+ }
1783
+
1784
+ function getEventsForWeek(startDate, endDate) {
1785
+ return events.filter((event) => {
1786
+ const eventStart = new Date(event.start);
1787
+ const eventEnd = new Date(event.end);
1788
+
1789
+ // Check if event overlaps with the week
1790
+ return (
1791
+ (eventStart >= startDate && eventStart <= endDate) ||
1792
+ (eventEnd >= startDate && eventEnd <= endDate) ||
1793
+ (eventStart <= startDate && eventEnd >= endDate)
1794
+ );
1795
+ });
1796
+ }
1797
+ </script>
1798
+ <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=gallabs/calendar-lucas" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
1799
  </html>