Cezarxil commited on
Commit
ada55c0
·
verified ·
1 Parent(s): 3527ed1

undefined - Initial Deployment

Browse files
Files changed (2) hide show
  1. README.md +6 -4
  2. index.html +491 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: App
3
- emoji: 🏆
4
- colorFrom: green
5
  colorTo: blue
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: app
3
+ emoji: 🐳
4
+ colorFrom: red
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,491 @@
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="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Client Tracker</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
+ .calendar-day {
11
+ min-height: 100px;
12
+ }
13
+ .calendar-day.today {
14
+ background-color: #f0f9ff;
15
+ }
16
+ .client-event {
17
+ font-size: 0.8rem;
18
+ border-left: 3px solid;
19
+ }
20
+ .client-event:hover {
21
+ transform: scale(1.02);
22
+ }
23
+ #addClientModal {
24
+ transition: all 0.3s ease;
25
+ }
26
+ .modal-open {
27
+ opacity: 1;
28
+ pointer-events: all;
29
+ }
30
+ .modal-closed {
31
+ opacity: 0;
32
+ pointer-events: none;
33
+ }
34
+ </style>
35
+ </head>
36
+ <body class="bg-gray-50">
37
+ <div class="container mx-auto px-4 py-8">
38
+ <!-- Header -->
39
+ <header class="flex flex-col md:flex-row justify-between items-center mb-8">
40
+ <h1 class="text-3xl font-bold text-blue-600 mb-4 md:mb-0">Client Tracker</h1>
41
+ <div class="flex items-center space-x-4">
42
+ <button id="prevMonth" class="p-2 rounded-full hover:bg-gray-200">
43
+ <i class="fas fa-chevron-left"></i>
44
+ </button>
45
+ <h2 id="currentMonth" class="text-xl font-semibold">January 2023</h2>
46
+ <button id="nextMonth" class="p-2 rounded-full hover:bg-gray-200">
47
+ <i class="fas fa-chevron-right"></i>
48
+ </button>
49
+ <button id="todayBtn" class="px-4 py-2 bg-blue-100 text-blue-600 rounded-lg hover:bg-blue-200">
50
+ Today
51
+ </button>
52
+ <button id="addClientBtn" class="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700">
53
+ <i class="fas fa-plus mr-2"></i>Add Client
54
+ </button>
55
+ </div>
56
+ </header>
57
+
58
+ <!-- Calendar Grid -->
59
+ <div class="bg-white rounded-lg shadow overflow-hidden">
60
+ <!-- Weekday Headers -->
61
+ <div class="grid grid-cols-7 bg-gray-100">
62
+ <div class="py-2 text-center font-medium text-gray-500">Sun</div>
63
+ <div class="py-2 text-center font-medium text-gray-500">Mon</div>
64
+ <div class="py-2 text-center font-medium text-gray-500">Tue</div>
65
+ <div class="py-2 text-center font-medium text-gray-500">Wed</div>
66
+ <div class="py-2 text-center font-medium text-gray-500">Thu</div>
67
+ <div class="py-2 text-center font-medium text-gray-500">Fri</div>
68
+ <div class="py-2 text-center font-medium text-gray-500">Sat</div>
69
+ </div>
70
+
71
+ <!-- Calendar Days -->
72
+ <div id="calendarDays" class="grid grid-cols-7 border-t border-l border-gray-200">
73
+ <!-- Days will be populated by JavaScript -->
74
+ </div>
75
+ </div>
76
+
77
+ <!-- Stats Section -->
78
+ <div class="mt-8 grid grid-cols-1 md:grid-cols-3 gap-4">
79
+ <div class="bg-white p-4 rounded-lg shadow">
80
+ <h3 class="text-lg font-semibold text-gray-700 mb-2">Upcoming Appointments</h3>
81
+ <p id="upcomingCount" class="text-3xl font-bold text-blue-600">0</p>
82
+ </div>
83
+ <div class="bg-white p-4 rounded-lg shadow">
84
+ <h3 class="text-lg font-semibold text-gray-700 mb-2">Total Clients</h3>
85
+ <p id="totalClients" class="text-3xl font-bold text-green-600">0</p>
86
+ </div>
87
+ <div class="bg-white p-4 rounded-lg shadow">
88
+ <h3 class="text-lg font-semibold text-gray-700 mb-2">Recent Follow-ups</h3>
89
+ <p id="recentFollowups" class="text-3xl font-bold text-purple-600">0</p>
90
+ </div>
91
+ </div>
92
+ </div>
93
+
94
+ <!-- Add Client Modal -->
95
+ <div id="addClientModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center modal-closed">
96
+ <div class="bg-white rounded-lg p-6 w-full max-w-md">
97
+ <div class="flex justify-between items-center mb-4">
98
+ <h3 class="text-xl font-semibold">Add New Client</h3>
99
+ <button id="closeModal" class="text-gray-500 hover:text-gray-700">
100
+ <i class="fas fa-times"></i>
101
+ </button>
102
+ </div>
103
+ <form id="clientForm" class="space-y-4">
104
+ <div>
105
+ <label for="clientName" class="block text-sm font-medium text-gray-700">Client Name</label>
106
+ <input type="text" id="clientName" required class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-blue-500 focus:border-blue-500">
107
+ </div>
108
+ <div>
109
+ <label for="appointmentDate" class="block text-sm font-medium text-gray-700">Appointment Date</label>
110
+ <input type="date" id="appointmentDate" required class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-blue-500 focus:border-blue-500">
111
+ </div>
112
+ <div>
113
+ <label for="appointmentTime" class="block text-sm font-medium text-gray-700">Appointment Time</label>
114
+ <input type="time" id="appointmentTime" required class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-blue-500 focus:border-blue-500">
115
+ </div>
116
+ <div>
117
+ <label for="clientEmail" class="block text-sm font-medium text-gray-700">Email</label>
118
+ <input type="email" id="clientEmail" class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-blue-500 focus:border-blue-500">
119
+ </div>
120
+ <div>
121
+ <label for="clientPhone" class="block text-sm font-medium text-gray-700">Phone</label>
122
+ <input type="tel" id="clientPhone" class="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-blue-500 focus:border-blue-500">
123
+ </div>
124
+ <div>
125
+ <label for="clientNotes" class="block text-sm font-medium text-gray-700">Notes</label>
126
+ <textarea id="clientNotes" 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-blue-500 focus:border-blue-500"></textarea>
127
+ </div>
128
+ <div class="flex justify-end space-x-3">
129
+ <button type="button" id="cancelAddClient" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 hover:bg-gray-50">
130
+ Cancel
131
+ </button>
132
+ <button type="submit" class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">
133
+ Save Client
134
+ </button>
135
+ </div>
136
+ </form>
137
+ </div>
138
+ </div>
139
+
140
+ <!-- Client Details Modal -->
141
+ <div id="clientDetailsModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center modal-closed">
142
+ <div class="bg-white rounded-lg p-6 w-full max-w-md">
143
+ <div class="flex justify-between items-center mb-4">
144
+ <h3 id="clientDetailsTitle" class="text-xl font-semibold">Client Details</h3>
145
+ <button id="closeDetailsModal" class="text-gray-500 hover:text-gray-700">
146
+ <i class="fas fa-times"></i>
147
+ </button>
148
+ </div>
149
+ <div id="clientDetailsContent" class="space-y-3">
150
+ <!-- Client details will be populated here -->
151
+ </div>
152
+ <div class="mt-6 flex justify-between">
153
+ <button id="deleteClientBtn" class="px-4 py-2 bg-red-100 text-red-600 rounded-md hover:bg-red-200">
154
+ Delete
155
+ </button>
156
+ <button id="editClientBtn" class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">
157
+ Edit
158
+ </button>
159
+ </div>
160
+ </div>
161
+ </div>
162
+
163
+ <script>
164
+ // Initialize variables
165
+ let currentDate = new Date();
166
+ let clients = JSON.parse(localStorage.getItem('clients')) || [];
167
+ let selectedClientId = null;
168
+
169
+ // DOM Elements
170
+ const calendarDays = document.getElementById('calendarDays');
171
+ const currentMonth = document.getElementById('currentMonth');
172
+ const prevMonthBtn = document.getElementById('prevMonth');
173
+ const nextMonthBtn = document.getElementById('nextMonth');
174
+ const todayBtn = document.getElementById('todayBtn');
175
+ const addClientBtn = document.getElementById('addClientBtn');
176
+ const addClientModal = document.getElementById('addClientModal');
177
+ const closeModal = document.getElementById('closeModal');
178
+ const cancelAddClient = document.getElementById('cancelAddClient');
179
+ const clientForm = document.getElementById('clientForm');
180
+ const clientDetailsModal = document.getElementById('clientDetailsModal');
181
+ const closeDetailsModal = document.getElementById('closeDetailsModal');
182
+ const deleteClientBtn = document.getElementById('deleteClientBtn');
183
+ const editClientBtn = document.getElementById('editClientBtn');
184
+ const upcomingCount = document.getElementById('upcomingCount');
185
+ const totalClients = document.getElementById('totalClients');
186
+ const recentFollowups = document.getElementById('recentFollowups');
187
+
188
+ // Event Listeners
189
+ prevMonthBtn.addEventListener('click', () => {
190
+ currentDate.setMonth(currentDate.getMonth() - 1);
191
+ renderCalendar();
192
+ });
193
+
194
+ nextMonthBtn.addEventListener('click', () => {
195
+ currentDate.setMonth(currentDate.getMonth() + 1);
196
+ renderCalendar();
197
+ });
198
+
199
+ todayBtn.addEventListener('click', () => {
200
+ currentDate = new Date();
201
+ renderCalendar();
202
+ });
203
+
204
+ addClientBtn.addEventListener('click', () => {
205
+ // Set default date to today
206
+ const today = new Date();
207
+ const formattedDate = today.toISOString().split('T')[0];
208
+ document.getElementById('appointmentDate').value = formattedDate;
209
+
210
+ // Set default time to next hour
211
+ const nextHour = today.getHours() + 1;
212
+ document.getElementById('appointmentTime').value = `${nextHour.toString().padStart(2, '0')}:00`;
213
+
214
+ addClientModal.classList.remove('modal-closed');
215
+ addClientModal.classList.add('modal-open');
216
+ });
217
+
218
+ closeModal.addEventListener('click', closeModals);
219
+ cancelAddClient.addEventListener('click', closeModals);
220
+ closeDetailsModal.addEventListener('click', closeModals);
221
+
222
+ clientForm.addEventListener('submit', (e) => {
223
+ e.preventDefault();
224
+ addNewClient();
225
+ });
226
+
227
+ deleteClientBtn.addEventListener('click', deleteClient);
228
+ editClientBtn.addEventListener('click', editClient);
229
+
230
+ // Functions
231
+ function renderCalendar() {
232
+ // Clear previous calendar days
233
+ calendarDays.innerHTML = '';
234
+
235
+ // Set current month text
236
+ currentMonth.textContent = new Intl.DateTimeFormat('en-US', {
237
+ month: 'long',
238
+ year: 'numeric'
239
+ }).format(currentDate);
240
+
241
+ // Get first day of month and total days in month
242
+ const firstDay = new Date(currentDate.getFullYear(), currentDate.getMonth(), 1);
243
+ const lastDay = new Date(currentDate.getFullYear(), currentDate.getMonth() + 1, 0);
244
+ const daysInMonth = lastDay.getDate();
245
+
246
+ // Get day of week for first day (0 = Sunday, 6 = Saturday)
247
+ const startingDay = firstDay.getDay();
248
+
249
+ // Get today's date for comparison
250
+ const today = new Date();
251
+ const isCurrentMonth = today.getFullYear() === currentDate.getFullYear() &&
252
+ today.getMonth() === currentDate.getMonth();
253
+
254
+ // Add empty cells for days before the first day of the month
255
+ for (let i = 0; i < startingDay; i++) {
256
+ const dayElement = document.createElement('div');
257
+ dayElement.className = 'calendar-day border-r border-b border-gray-200 p-2 bg-gray-50';
258
+ calendarDays.appendChild(dayElement);
259
+ }
260
+
261
+ // Add cells for each day of the month
262
+ for (let day = 1; day <= daysInMonth; day++) {
263
+ const dayElement = document.createElement('div');
264
+ dayElement.className = 'calendar-day border-r border-b border-gray-200 p-2';
265
+
266
+ // Highlight today's date
267
+ if (isCurrentMonth && day === today.getDate()) {
268
+ dayElement.classList.add('today');
269
+ }
270
+
271
+ // Add day number
272
+ const dayNumber = document.createElement('div');
273
+ dayNumber.className = 'text-right font-medium';
274
+ dayNumber.textContent = day;
275
+ dayElement.appendChild(dayNumber);
276
+
277
+ // Add client events for this day
278
+ const dayDate = new Date(currentDate.getFullYear(), currentDate.getMonth(), day);
279
+ const clientsForDay = getClientsForDate(dayDate);
280
+
281
+ clientsForDay.forEach(client => {
282
+ const eventElement = document.createElement('div');
283
+ eventElement.className = 'client-event mb-1 p-1 rounded bg-blue-50 border-l-blue-500 cursor-pointer hover:shadow';
284
+ eventElement.innerHTML = `
285
+ <div class="font-medium text-blue-700">${client.time}</div>
286
+ <div class="text-blue-600 truncate">${client.name}</div>
287
+ `;
288
+ eventElement.addEventListener('click', () => showClientDetails(client.id));
289
+ dayElement.appendChild(eventElement);
290
+ });
291
+
292
+ calendarDays.appendChild(dayElement);
293
+ }
294
+
295
+ updateStats();
296
+ }
297
+
298
+ function getClientsForDate(date) {
299
+ return clients.filter(client => {
300
+ const clientDate = new Date(client.date);
301
+ return clientDate.getFullYear() === date.getFullYear() &&
302
+ clientDate.getMonth() === date.getMonth() &&
303
+ clientDate.getDate() === date.getDate();
304
+ }).sort((a, b) => a.time.localeCompare(b.time));
305
+ }
306
+
307
+ function addNewClient() {
308
+ const name = document.getElementById('clientName').value;
309
+ const date = document.getElementById('appointmentDate').value;
310
+ const time = document.getElementById('appointmentTime').value;
311
+ const email = document.getElementById('clientEmail').value;
312
+ const phone = document.getElementById('clientPhone').value;
313
+ const notes = document.getElementById('clientNotes').value;
314
+
315
+ const newClient = {
316
+ id: Date.now().toString(),
317
+ name,
318
+ date,
319
+ time,
320
+ email,
321
+ phone,
322
+ notes,
323
+ createdAt: new Date().toISOString()
324
+ };
325
+
326
+ clients.push(newClient);
327
+ saveClients();
328
+ renderCalendar();
329
+ closeModals();
330
+ clientForm.reset();
331
+ }
332
+
333
+ function showClientDetails(clientId) {
334
+ selectedClientId = clientId;
335
+ const client = clients.find(c => c.id === clientId);
336
+
337
+ if (!client) return;
338
+
339
+ document.getElementById('clientDetailsTitle').textContent = client.name;
340
+
341
+ const detailsContent = document.getElementById('clientDetailsContent');
342
+ detailsContent.innerHTML = `
343
+ <div class="flex items-center">
344
+ <i class="fas fa-calendar-day text-blue-500 mr-2"></i>
345
+ <div>
346
+ <div class="text-sm text-gray-500">Date</div>
347
+ <div>${formatDate(client.date)} at ${client.time}</div>
348
+ </div>
349
+ </div>
350
+ ${client.email ? `
351
+ <div class="flex items-center">
352
+ <i class="fas fa-envelope text-blue-500 mr-2"></i>
353
+ <div>
354
+ <div class="text-sm text-gray-500">Email</div>
355
+ <div>${client.email}</div>
356
+ </div>
357
+ </div>` : ''}
358
+ ${client.phone ? `
359
+ <div class="flex items-center">
360
+ <i class="fas fa-phone text-blue-500 mr-2"></i>
361
+ <div>
362
+ <div class="text-sm text-gray-500">Phone</div>
363
+ <div>${client.phone}</div>
364
+ </div>
365
+ </div>` : ''}
366
+ ${client.notes ? `
367
+ <div class="flex items-start">
368
+ <i class="fas fa-sticky-note text-blue-500 mr-2 mt-1"></i>
369
+ <div>
370
+ <div class="text-sm text-gray-500">Notes</div>
371
+ <div>${client.notes}</div>
372
+ </div>
373
+ </div>` : ''}
374
+ `;
375
+
376
+ clientDetailsModal.classList.remove('modal-closed');
377
+ clientDetailsModal.classList.add('modal-open');
378
+ }
379
+
380
+ function deleteClient() {
381
+ clients = clients.filter(client => client.id !== selectedClientId);
382
+ saveClients();
383
+ renderCalendar();
384
+ closeModals();
385
+ }
386
+
387
+ function editClient() {
388
+ const client = clients.find(c => c.id === selectedClientId);
389
+ if (!client) return;
390
+
391
+ // Fill the form with client data
392
+ document.getElementById('clientName').value = client.name;
393
+ document.getElementById('appointmentDate').value = client.date;
394
+ document.getElementById('appointmentTime').value = client.time;
395
+ document.getElementById('clientEmail').value = client.email || '';
396
+ document.getElementById('clientPhone').value = client.phone || '';
397
+ document.getElementById('clientNotes').value = client.notes || '';
398
+
399
+ // Change form to update mode
400
+ clientForm.removeEventListener('submit', addNewClient);
401
+ clientForm.addEventListener('submit', updateClient);
402
+
403
+ // Show the add client modal
404
+ closeModals();
405
+ addClientModal.classList.remove('modal-closed');
406
+ addClientModal.classList.add('modal-open');
407
+ }
408
+
409
+ function updateClient(e) {
410
+ e.preventDefault();
411
+
412
+ const name = document.getElementById('clientName').value;
413
+ const date = document.getElementById('appointmentDate').value;
414
+ const time = document.getElementById('appointmentTime').value;
415
+ const email = document.getElementById('clientEmail').value;
416
+ const phone = document.getElementById('clientPhone').value;
417
+ const notes = document.getElementById('clientNotes').value;
418
+
419
+ const updatedClient = {
420
+ id: selectedClientId,
421
+ name,
422
+ date,
423
+ time,
424
+ email,
425
+ phone,
426
+ notes,
427
+ createdAt: clients.find(c => c.id === selectedClientId).createdAt
428
+ };
429
+
430
+ clients = clients.map(client =>
431
+ client.id === selectedClientId ? updatedClient : client
432
+ );
433
+
434
+ saveClients();
435
+ renderCalendar();
436
+ closeModals();
437
+ clientForm.reset();
438
+
439
+ // Reset form to add mode
440
+ clientForm.removeEventListener('submit', updateClient);
441
+ clientForm.addEventListener('submit', addNewClient);
442
+ }
443
+
444
+ function closeModals() {
445
+ addClientModal.classList.remove('modal-open');
446
+ addClientModal.classList.add('modal-closed');
447
+ clientDetailsModal.classList.remove('modal-open');
448
+ clientDetailsModal.classList.add('modal-closed');
449
+ }
450
+
451
+ function saveClients() {
452
+ localStorage.setItem('clients', JSON.stringify(clients));
453
+ updateStats();
454
+ }
455
+
456
+ function formatDate(dateString) {
457
+ const options = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' };
458
+ return new Date(dateString).toLocaleDateString('en-US', options);
459
+ }
460
+
461
+ function updateStats() {
462
+ // Upcoming appointments (next 7 days)
463
+ const today = new Date();
464
+ const nextWeek = new Date(today);
465
+ nextWeek.setDate(today.getDate() + 7);
466
+
467
+ const upcoming = clients.filter(client => {
468
+ const clientDate = new Date(client.date);
469
+ return clientDate >= today && clientDate <= nextWeek;
470
+ });
471
+
472
+ upcomingCount.textContent = upcoming.length;
473
+ totalClients.textContent = clients.length;
474
+
475
+ // Recent follow-ups (last 7 days)
476
+ const lastWeek = new Date(today);
477
+ lastWeek.setDate(today.getDate() - 7);
478
+
479
+ const recent = clients.filter(client => {
480
+ const clientDate = new Date(client.createdAt);
481
+ return clientDate >= lastWeek && clientDate <= today;
482
+ });
483
+
484
+ recentFollowups.textContent = recent.length;
485
+ }
486
+
487
+ // Initialize the calendar
488
+ renderCalendar();
489
+ </script>
490
+ <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=Cezarxil/app" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
491
+ </html>