elhamshari commited on
Commit
cc1fe30
·
verified ·
1 Parent(s): 5a31672

add import and export excel file for employee list - Initial Deployment

Browse files
Files changed (2) hide show
  1. README.md +7 -5
  2. index.html +803 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Employee Automation
3
- emoji: 🐨
4
- colorFrom: gray
5
- colorTo: indigo
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: employee-automation
3
+ emoji: 🐳
4
+ colorFrom: yellow
5
+ colorTo: yellow
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,803 @@
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>Employee Celebration Manager</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
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>
10
+ <style>
11
+ .fade-in {
12
+ animation: fadeIn 0.3s ease-in-out;
13
+ }
14
+
15
+ @keyframes fadeIn {
16
+ from { opacity: 0; transform: translateY(10px); }
17
+ to { opacity: 1; transform: translateY(0); }
18
+ }
19
+
20
+ .toast {
21
+ position: fixed;
22
+ top: 20px;
23
+ right: 20px;
24
+ z-index: 1000;
25
+ animation: slideIn 0.3s ease-out;
26
+ }
27
+
28
+ @keyframes slideIn {
29
+ from { transform: translateX(100%); }
30
+ to { transform: translateX(0); }
31
+ }
32
+
33
+ .calendar-icon {
34
+ position: absolute;
35
+ right: 10px;
36
+ top: 50%;
37
+ transform: translateY(-50%);
38
+ pointer-events: none;
39
+ }
40
+ </style>
41
+ </head>
42
+ <body class="bg-gray-50 min-h-screen">
43
+ <!-- Toast Notification -->
44
+ <div id="toast" class="toast hidden">
45
+ <div class="bg-green-500 text-white px-4 py-2 rounded shadow-lg flex items-center">
46
+ <span id="toast-message"></span>
47
+ <button onclick="hideToast()" class="ml-4">
48
+ <i class="fas fa-times"></i>
49
+ </button>
50
+ </div>
51
+ </div>
52
+
53
+ <div class="container mx-auto px-4 py-8">
54
+ <header class="mb-8">
55
+ <h1 class="text-3xl font-bold text-indigo-700">🎉 Employee Celebration Manager</h1>
56
+ <p class="text-gray-600 mt-2">Automatically send birthday and work anniversary emails to your employees</p>
57
+ </header>
58
+
59
+ <div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
60
+ <!-- Employee Form -->
61
+ <div class="bg-white p-6 rounded-lg shadow-md lg:col-span-1">
62
+ <h2 class="text-xl font-semibold mb-4 text-indigo-600 border-b pb-2">
63
+ <i class="fas fa-user-plus mr-2"></i>Add Employee
64
+ </h2>
65
+ <form id="employeeForm" class="space-y-4">
66
+ <div>
67
+ <label for="name" class="block text-sm font-medium text-gray-700">Full Name</label>
68
+ <input type="text" id="name" name="name" required
69
+ class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 p-2 border">
70
+ </div>
71
+
72
+ <div>
73
+ <label for="email" class="block text-sm font-medium text-gray-700">Email</label>
74
+ <input type="email" id="email" name="email" required
75
+ class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 p-2 border">
76
+ </div>
77
+
78
+ <div class="relative">
79
+ <label for="birthday" class="block text-sm font-medium text-gray-700">Birthday</label>
80
+ <input type="date" id="birthday" name="birthday" required
81
+ class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 p-2 border">
82
+ <div class="calendar-icon">
83
+ <i class="fas fa-calendar-alt text-gray-400"></i>
84
+ </div>
85
+ </div>
86
+
87
+ <div class="relative">
88
+ <label for="appointmentDate" class="block text-sm font-medium text-gray-700">Appointment Date</label>
89
+ <input type="date" id="appointmentDate" name="appointmentDate" required
90
+ class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 p-2 border">
91
+ <div class="calendar-icon">
92
+ <i class="fas fa-calendar-alt text-gray-400"></i>
93
+ </div>
94
+ </div>
95
+
96
+ <div>
97
+ <label for="department" class="block text-sm font-medium text-gray-700">Department</label>
98
+ <select id="department" name="department"
99
+ class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 p-2 border">
100
+ <option value="Engineering">Engineering</option>
101
+ <option value="Marketing">Marketing</option>
102
+ <option value="Sales">Sales</option>
103
+ <option value="HR">Human Resources</option>
104
+ <option value="Finance">Finance</option>
105
+ <option value="Operations">Operations</option>
106
+ </select>
107
+ </div>
108
+
109
+ <div class="pt-2">
110
+ <button type="submit" class="w-full bg-indigo-600 text-white py-2 px-4 rounded-md hover:bg-indigo-700 transition duration-200 flex items-center justify-center">
111
+ <i class="fas fa-save mr-2"></i> Save Employee
112
+ </button>
113
+ </div>
114
+ </form>
115
+ </div>
116
+
117
+ <!-- Employee List -->
118
+ <div class="bg-white p-6 rounded-lg shadow-md lg:col-span-2">
119
+ <div class="flex justify-between items-center mb-4">
120
+ <h2 class="text-xl font-semibold text-indigo-600 border-b pb-2">
121
+ <i class="fas fa-users mr-2"></i>Employee List
122
+ </h2>
123
+ <div class="flex space-x-2">
124
+ <button id="sendTestEmail" class="bg-blue-500 text-white py-1 px-3 rounded-md hover:bg-blue-600 transition duration-200 text-sm flex items-center">
125
+ <i class="fas fa-paper-plane mr-1"></i> Send Test
126
+ </button>
127
+ <button id="scheduleAll" class="bg-green-500 text-white py-1 px-3 rounded-md hover:bg-green-600 transition duration-200 text-sm flex items-center">
128
+ <i class="fas fa-clock mr-1"></i> Schedule All
129
+ </button>
130
+ <button id="exportExcel" class="bg-purple-500 text-white py-1 px-3 rounded-md hover:bg-purple-600 transition duration-200 text-sm flex items-center">
131
+ <i class="fas fa-file-export mr-1"></i> Export
132
+ </button>
133
+ <label for="importExcel" class="bg-indigo-500 text-white py-1 px-3 rounded-md hover:bg-indigo-600 transition duration-200 text-sm flex items-center cursor-pointer">
134
+ <i class="fas fa-file-import mr-1"></i> Import
135
+ <input type="file" id="importExcel" accept=".xlsx,.xls,.csv" class="hidden">
136
+ </label>
137
+ </div>
138
+ </div>
139
+
140
+ <div class="overflow-x-auto">
141
+ <table class="min-w-full divide-y divide-gray-200">
142
+ <thead class="bg-gray-50">
143
+ <tr>
144
+ <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Name</th>
145
+ <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Email</th>
146
+ <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Birthday</th>
147
+ <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Appointment</th>
148
+ <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Department</th>
149
+ <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Actions</th>
150
+ </tr>
151
+ </thead>
152
+ <tbody id="employeeTableBody" class="bg-white divide-y divide-gray-200">
153
+ <!-- Employee data will be inserted here -->
154
+ </tbody>
155
+ </table>
156
+ </div>
157
+
158
+ <div id="noEmployees" class="text-center py-8 text-gray-500">
159
+ <i class="fas fa-user-slash text-4xl mb-2"></i>
160
+ <p>No employees added yet. Add your first employee to get started!</p>
161
+ </div>
162
+ </div>
163
+ </div>
164
+
165
+ <!-- SMTP Settings Section -->
166
+ <div class="mt-8 bg-white p-6 rounded-lg shadow-md">
167
+ <h2 class="text-xl font-semibold mb-4 text-indigo-600 border-b pb-2">
168
+ <i class="fas fa-server mr-2"></i>SMTP Server Settings
169
+ </h2>
170
+
171
+ <form id="smtpForm" class="space-y-4">
172
+ <div>
173
+ <label class="block text-sm font-medium text-gray-700">SMTP Host</label>
174
+ <input type="text" id="smtpHost" required
175
+ class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 p-2 border">
176
+ </div>
177
+
178
+ <div>
179
+ <label class="block text-sm font-medium text-gray-700">SMTP Port</label>
180
+ <input type="number" id="smtpPort" required
181
+ class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 p-2 border">
182
+ </div>
183
+
184
+ <div>
185
+ <label class="block text-sm font-medium text-gray-700">SMTP Username</label>
186
+ <input type="text" id="smtpUsername" required
187
+ class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 p-2 border">
188
+ </div>
189
+
190
+ <div>
191
+ <label class="block text-sm font-medium text-gray-700">SMTP Password</label>
192
+ <input type="password" id="smtpPassword" required
193
+ class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 p-2 border">
194
+ </div>
195
+
196
+ <div>
197
+ <label class="block text-sm font-medium text-gray-700">From Email</label>
198
+ <input type="email" id="smtpFromEmail" required
199
+ class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 p-2 border">
200
+ </div>
201
+
202
+ <div class="pt-2">
203
+ <button type="submit" class="w-full bg-indigo-600 text-white py-2 px-4 rounded-md hover:bg-indigo-700 transition duration-200">
204
+ <i class="fas fa-save mr-2"></i> Save SMTP Settings
205
+ </button>
206
+ </div>
207
+ </form>
208
+ </div>
209
+
210
+ <!-- Email Templates Section -->
211
+ <div class="mt-8 bg-white p-6 rounded-lg shadow-md">
212
+ <h2 class="text-xl font-semibold mb-4 text-indigo-600 border-b pb-2">
213
+ <i class="fas fa-envelope mr-2"></i>Email Templates
214
+ </h2>
215
+
216
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
217
+ <!-- Birthday Template -->
218
+ <div class="border rounded-lg p-4">
219
+ <div class="flex justify-between items-center mb-3">
220
+ <h3 class="font-medium text-indigo-600">
221
+ <i class="fas fa-birthday-cake mr-2"></i>Birthday Email
222
+ </h3>
223
+ <button id="previewBirthday" class="text-sm bg-gray-100 hover:bg-gray-200 px-2 py-1 rounded">
224
+ Preview
225
+ </button>
226
+ </div>
227
+ <div class="space-y-3">
228
+ <div>
229
+ <label class="block text-sm font-medium text-gray-700">Subject</label>
230
+ <input type="text" id="birthdaySubject" value="Happy Birthday, {name}!"
231
+ class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 p-2 border">
232
+ </div>
233
+ <div>
234
+ <label class="block text-sm font-medium text-gray-700">Message</label>
235
+ <textarea id="birthdayMessage" rows="5"
236
+ class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 p-2 border">Dear {name},
237
+
238
+ Wishing you a fantastic birthday filled with joy and happiness!
239
+
240
+ Thank you for being an invaluable part of our team.
241
+
242
+ Best regards,
243
+ The Management</textarea>
244
+ </div>
245
+ <button id="saveBirthdayTemplate" class="w-full bg-indigo-100 text-indigo-700 py-2 px-4 rounded-md hover:bg-indigo-200 transition duration-200">
246
+ Save Template
247
+ </button>
248
+ </div>
249
+ </div>
250
+
251
+ <!-- Appointment Template -->
252
+ <div class="border rounded-lg p-4">
253
+ <div class="flex justify-between items-center mb-3">
254
+ <h3 class="font-medium text-indigo-600">
255
+ <i class="fas fa-briefcase mr-2"></i>Appiversary Email
256
+ </h3>
257
+ <button id="previewAppointment" class="text-sm bg-gray-100 hover:bg-gray-200 px-2 py-1 rounded">
258
+ Preview
259
+ </button>
260
+ </div>
261
+ <div class="space-y-3">
262
+ <div>
263
+ <label class="block text-sm font-medium text-gray-700">Subject</label>
264
+ <input type="text" id="appointmentSubject" value="Happy {years} Work Anniversary, {name}!"
265
+ class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 p-2 border">
266
+ </div>
267
+ <div>
268
+ <label class="block text-sm font-medium text-gray-700">Message</label>
269
+ <textarea id="appointmentMessage" rows="5"
270
+ class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 p-2 border">Dear {name},
271
+
272
+ Congratulations on your {years} year work anniversary with us!
273
+
274
+ We appreciate your dedication and contributions to our team's success.
275
+
276
+ Here's to many more years together!
277
+
278
+ Best regards,
279
+ The Management</textarea>
280
+ </div>
281
+ <button id="saveAppointmentTemplate" class="w-full bg-indigo-100 text-indigo-700 py-2 px-4 rounded-md hover:bg-indigo-200 transition duration-200">
282
+ Save Template
283
+ </button>
284
+ </div>
285
+ </div>
286
+ </div>
287
+ </div>
288
+
289
+ <!-- Email Preview Modal -->
290
+ <div id="emailPreviewModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center hidden z-50">
291
+ <div class="bg-white rounded-lg w-full max-w-2xl max-h-[90vh] overflow-auto">
292
+ <div class="flex justify-between items-center border-b p-4">
293
+ <h3 class="text-lg font-semibold" id="previewTitle">Email Preview</h3>
294
+ <button id="closePreview" class="text-gray-500 hover:text-gray-700">
295
+ <i class="fas fa-times"></i>
296
+ </button>
297
+ </div>
298
+ <div class="p-4">
299
+ <div class="border-b pb-2 mb-4">
300
+ <p class="font-medium" id="previewSubject">Subject: Email Subject</p>
301
+ <p class="text-sm text-gray-500">To: [email protected]</p>
302
+ </div>
303
+ <div id="previewContent" class="whitespace-pre-line">
304
+ Email content will appear here...
305
+ </div>
306
+ </div>
307
+ <div class="border-t p-4 flex justify-end">
308
+ <button id="sendPreviewEmail" class="bg-indigo-600 text-white py-2 px-4 rounded-md hover:bg-indigo-700 mr-2">
309
+ Send Test Email
310
+ </button>
311
+ <button id="closePreviewBtn" class="bg-gray-200 text-gray-700 py-2 px-4 rounded-md hover:bg-gray-300">
312
+ Close
313
+ </button>
314
+ </div>
315
+ </div>
316
+ </div>
317
+ </div>
318
+
319
+ <script>
320
+ // Employee data storage
321
+ let employees = JSON.parse(localStorage.getItem('employees')) || [];
322
+ let smtpSettings = JSON.parse(localStorage.getItem('smtpSettings')) || {
323
+ host: '',
324
+ port: 587,
325
+ username: '',
326
+ password: '',
327
+ fromEmail: ''
328
+ };
329
+
330
+ let emailTemplates = JSON.parse(localStorage.getItem('emailTemplates')) || {
331
+ birthday: {
332
+ subject: "Happy Birthday, {name}!",
333
+ message: "Dear {name},\n\nWishing you a fantastic birthday filled with joy and happiness! \n\nThank you for being an invaluable part of our team.\n\nBest regards,\nThe Management"
334
+ },
335
+ appointment: {
336
+ subject: "Happy {years} Work Anniversary, {name}!",
337
+ message: "Dear {name},\n\nCongratulations on your {years} year work anniversary with us!\n\nWe appreciate your dedication and contributions to our team's success.\n\nHere's to many more years together!\n\nBest regards,\nThe Management"
338
+ }
339
+ };
340
+
341
+ // DOM elements
342
+ const employeeForm = document.getElementById('employeeForm');
343
+ const employeeTableBody = document.getElementById('employeeTableBody');
344
+ const noEmployees = document.getElementById('noEmployees');
345
+ const toast = document.getElementById('toast');
346
+ const toastMessage = document.getElementById('toast-message');
347
+
348
+ // Initialize the app
349
+ document.addEventListener('DOMContentLoaded', () => {
350
+ renderEmployeeTable();
351
+ loadEmailTemplates();
352
+
353
+ // Form submission
354
+ employeeForm.addEventListener('submit', handleFormSubmit);
355
+
356
+ // Template buttons
357
+ document.getElementById('saveBirthdayTemplate').addEventListener('click', saveBirthdayTemplate);
358
+ document.getElementById('saveAppointmentTemplate').addEventListener('click', saveAppointmentTemplate);
359
+ document.getElementById('previewBirthday').addEventListener('click', () => previewEmail('birthday'));
360
+ document.getElementById('previewAppointment').addEventListener('click', () => previewEmail('appointment'));
361
+
362
+ // Modal buttons
363
+ document.getElementById('closePreview').addEventListener('click', closePreview);
364
+ document.getElementById('closePreviewBtn').addEventListener('click', closePreview);
365
+ document.getElementById('sendPreviewEmail').addEventListener('click', sendTestEmailFromPreview);
366
+
367
+ // Action buttons
368
+ document.getElementById('sendTestEmail').addEventListener('click', sendTestEmailToAll);
369
+ document.getElementById('scheduleAll').addEventListener('click', scheduleAllEmails);
370
+ document.getElementById('exportExcel').addEventListener('click', exportToExcel);
371
+ document.getElementById('importExcel').addEventListener('change', importFromExcel);
372
+
373
+ // SMTP form
374
+ document.getElementById('smtpForm').addEventListener('submit', saveSmtpSettings);
375
+ loadSmtpSettings();
376
+ });
377
+
378
+ // Form submission handler
379
+ function handleFormSubmit(e) {
380
+ e.preventDefault();
381
+
382
+ const formData = new FormData(employeeForm);
383
+ const employee = {
384
+ id: Date.now().toString(),
385
+ name: formData.get('name'),
386
+ email: formData.get('email'),
387
+ birthday: formData.get('birthday'),
388
+ appointmentDate: formData.get('appointmentDate'),
389
+ department: formData.get('department')
390
+ };
391
+
392
+ employees.push(employee);
393
+ saveEmployees();
394
+ renderEmployeeTable();
395
+
396
+ showToast('Employee added successfully!');
397
+ employeeForm.reset();
398
+ }
399
+
400
+ // Render employee table
401
+ function renderEmployeeTable() {
402
+ if (employees.length === 0) {
403
+ employeeTableBody.innerHTML = '';
404
+ noEmployees.classList.remove('hidden');
405
+ return;
406
+ }
407
+
408
+ noEmployees.classList.add('hidden');
409
+
410
+ employeeTableBody.innerHTML = employees.map(employee => `
411
+ <tr class="fade-in">
412
+ <td class="px-6 py-4 whitespace-nowrap">${employee.name}</td>
413
+ <td class="px-6 py-4 whitespace-nowrap">${employee.email}</td>
414
+ <td class="px-6 py-4 whitespace-nowrap">${formatDate(employee.birthday)}</td>
415
+ <td class="px-6 py-4 whitespace-nowrap">${formatDate(employee.appointmentDate)}</td>
416
+ <td class="px-6 py-4 whitespace-nowrap">${employee.department}</td>
417
+ <td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
418
+ <button onclick="sendTestEmail('${employee.id}')" class="text-blue-600 hover:text-blue-900 mr-2" title="Send Test Email">
419
+ <i class="fas fa-paper-plane"></i>
420
+ </button>
421
+ <button onclick="scheduleEmployeeEmails('${employee.id}')" class="text-green-600 hover:text-green-900 mr-2" title="Schedule Emails">
422
+ <i class="fas fa-clock"></i>
423
+ </button>
424
+ <button onclick="deleteEmployee('${employee.id}')" class="text-red-600 hover:text-red-900" title="Delete">
425
+ <i class="fas fa-trash"></i>
426
+ </button>
427
+ </td>
428
+ </tr>
429
+ `).join('');
430
+ }
431
+
432
+ // Delete employee
433
+ function deleteEmployee(id) {
434
+ if (confirm('Are you sure you want to delete this employee?')) {
435
+ employees = employees.filter(emp => emp.id !== id);
436
+ saveEmployees();
437
+ renderEmployeeTable();
438
+ showToast('Employee deleted successfully!');
439
+ }
440
+ }
441
+
442
+ // Save employees to localStorage
443
+ function saveEmployees() {
444
+ localStorage.setItem('employees', JSON.stringify(employees));
445
+ }
446
+
447
+ // Load email templates
448
+ function loadEmailTemplates() {
449
+ document.getElementById('birthdaySubject').value = emailTemplates.birthday.subject;
450
+ document.getElementById('birthdayMessage').value = emailTemplates.birthday.message;
451
+ document.getElementById('appointmentSubject').value = emailTemplates.appointment.subject;
452
+ document.getElementById('appointmentMessage').value = emailTemplates.appointment.message;
453
+ }
454
+
455
+ // Save birthday template
456
+ function saveBirthdayTemplate() {
457
+ emailTemplates.birthday = {
458
+ subject: document.getElementById('birthdaySubject').value,
459
+ message: document.getElementById('birthdayMessage').value
460
+ };
461
+ localStorage.setItem('emailTemplates', JSON.stringify(emailTemplates));
462
+ showToast('Birthday template saved!');
463
+ }
464
+
465
+ // Save appointment template
466
+ function saveAppointmentTemplate() {
467
+ emailTemplates.appointment = {
468
+ subject: document.getElementById('appointmentSubject').value,
469
+ message: document.getElementById('appointmentMessage').value
470
+ };
471
+ localStorage.setItem('emailTemplates', JSON.stringify(emailTemplates));
472
+ showToast('Appointment template saved!');
473
+ }
474
+
475
+ // Preview email
476
+ function previewEmail(type) {
477
+ const modal = document.getElementById('emailPreviewModal');
478
+ const previewTitle = document.getElementById('previewTitle');
479
+ const previewSubject = document.getElementById('previewSubject');
480
+ const previewContent = document.getElementById('previewContent');
481
+
482
+ // Use a sample employee for preview
483
+ const sampleEmployee = {
484
+ name: "John Doe",
485
+ email: "[email protected]",
486
+ birthday: "1990-01-01",
487
+ appointmentDate: "2020-01-01"
488
+ };
489
+
490
+ const years = new Date().getFullYear() - new Date(sampleEmployee.appointmentDate).getFullYear();
491
+
492
+ if (type === 'birthday') {
493
+ previewTitle.textContent = 'Birthday Email Preview';
494
+ let subject = emailTemplates.birthday.subject.replace(/{name}/g, sampleEmployee.name);
495
+ let message = emailTemplates.birthday.message.replace(/{name}/g, sampleEmployee.name);
496
+
497
+ previewSubject.textContent = `Subject: ${subject}`;
498
+ previewContent.innerHTML = message;
499
+
500
+ // Store preview data for possible test send
501
+ modal.dataset.type = 'birthday';
502
+ modal.dataset.employeeId = 'preview';
503
+ } else {
504
+ previewTitle.textContent = 'Appointment Anniversary Email Preview';
505
+ let subject = emailTemplates.appointment.subject
506
+ .replace(/{name}/g, sampleEmployee.name)
507
+ .replace(/{years}/g, years);
508
+ let message = emailTemplates.appointment.message
509
+ .replace(/{name}/g, sampleEmployee.name)
510
+ .replace(/{years}/g, years);
511
+
512
+ previewSubject.textContent = `Subject: ${subject}`;
513
+ previewContent.innerHTML = message;
514
+
515
+ // Store preview data for possible test send
516
+ modal.dataset.type = 'appointment';
517
+ modal.dataset.employeeId = 'preview';
518
+ }
519
+
520
+ modal.classList.remove('hidden');
521
+ }
522
+
523
+ // Close preview modal
524
+ function closePreview() {
525
+ document.getElementById('emailPreviewModal').classList.add('hidden');
526
+ }
527
+
528
+ // Send test email from preview
529
+ function sendTestEmailFromPreview() {
530
+ const modal = document.getElementById('emailPreviewModal');
531
+ const type = modal.dataset.type;
532
+ const employeeId = modal.dataset.employeeId;
533
+
534
+ if (employeeId === 'preview') {
535
+ // This is a preview with sample data
536
+ showToast('Test email sent to console (simulated)');
537
+ console.log(`Would send ${type} email to sample employee`);
538
+ } else {
539
+ // This would be for a real employee
540
+ const employee = employees.find(emp => emp.id === employeeId);
541
+ if (employee) {
542
+ sendEmailToEmployee(employee, type, true);
543
+ }
544
+ }
545
+
546
+ closePreview();
547
+ }
548
+
549
+ // Send test email to a specific employee
550
+ function sendTestEmail(employeeId) {
551
+ const employee = employees.find(emp => emp.id === employeeId);
552
+ if (employee) {
553
+ // In a real app, you would send both types or let user choose
554
+ // For demo, we'll send birthday email
555
+ sendEmailToEmployee(employee, 'birthday', true);
556
+ sendEmailToEmployee(employee, 'appointment', true);
557
+ }
558
+ }
559
+
560
+ // Send test email to all employees
561
+ function sendTestEmailToAll() {
562
+ if (employees.length === 0) {
563
+ showToast('No employees to send emails to', 'error');
564
+ return;
565
+ }
566
+
567
+ if (confirm('Send test emails to all employees? This will simulate sending to console.')) {
568
+ employees.forEach(employee => {
569
+ sendEmailToEmployee(employee, 'birthday', true);
570
+ sendEmailToEmployee(employee, 'appointment', true);
571
+ });
572
+ showToast(`Test emails sent for ${employees.length} employees (check console)`);
573
+ }
574
+ }
575
+
576
+ // Schedule emails for a specific employee
577
+ function scheduleEmployeeEmails(employeeId) {
578
+ const employee = employees.find(emp => emp.id === employeeId);
579
+ if (employee) {
580
+ // In a real app, this would connect to your backend scheduling system
581
+ // For demo, we'll just show a message
582
+ showToast(`Scheduled birthday and anniversary emails for ${employee.name}`);
583
+ console.log(`Would schedule emails for ${employee.name}`);
584
+ }
585
+ }
586
+
587
+ // Schedule emails for all employees
588
+ function scheduleAllEmails() {
589
+ if (employees.length === 0) {
590
+ showToast('No employees to schedule emails for', 'error');
591
+ return;
592
+ }
593
+
594
+ if (confirm('Schedule birthday and anniversary emails for all employees?')) {
595
+ employees.forEach(employee => {
596
+ // In a real app, this would connect to your backend scheduling system
597
+ console.log(`Would schedule emails for ${employee.name}`);
598
+ });
599
+ showToast(`Scheduled emails for ${employees.length} employees`);
600
+ }
601
+ }
602
+
603
+ // Send email to employee
604
+ function sendEmailToEmployee(employee, type, isTest = false) {
605
+ if (!smtpSettings.host || !smtpSettings.port || !smtpSettings.username || !smtpSettings.password) {
606
+ showToast('SMTP settings not configured', 'error');
607
+ return;
608
+ }
609
+ const years = new Date().getFullYear() - new Date(employee.appointmentDate).getFullYear();
610
+
611
+ let subject, message;
612
+
613
+ if (type === 'birthday') {
614
+ subject = emailTemplates.birthday.subject.replace(/{name}/g, employee.name);
615
+ message = emailTemplates.birthday.message.replace(/{name}/g, employee.name);
616
+ } else {
617
+ subject = emailTemplates.appointment.subject
618
+ .replace(/{name}/g, employee.name)
619
+ .replace(/{years}/g, years);
620
+ message = emailTemplates.appointment.message
621
+ .replace(/{name}/g, employee.name)
622
+ .replace(/{years}/g, years);
623
+ }
624
+
625
+ if (isTest) {
626
+ console.log(`=== TEST EMAIL (${type.toUpperCase()}) ===`);
627
+ console.log(`To: ${employee.email}`);
628
+ console.log(`Subject: ${subject}`);
629
+ console.log(`Body:\n${message}\n`);
630
+ } else {
631
+ // In a real app, this would actually send the email
632
+ console.log(`=== REAL EMAIL SENT (${type.toUpperCase()}) ===`);
633
+ console.log(`To: ${employee.email}`);
634
+ console.log(`Subject: ${subject}`);
635
+ console.log(`Body:\n${message}\n`);
636
+ }
637
+
638
+ if (isTest) {
639
+ showToast(`Test ${type} email sent for ${employee.name} (check console)`);
640
+ } else {
641
+ showToast(`${type} email sent to ${employee.name}`);
642
+ }
643
+ }
644
+
645
+ // Helper function to format date
646
+ function formatDate(dateString) {
647
+ const options = { year: 'numeric', month: 'short', day: 'numeric' };
648
+ return new Date(dateString).toLocaleDateString(undefined, options);
649
+ }
650
+
651
+ // Show toast notification
652
+ function showToast(message, type = 'success') {
653
+ toastMessage.textContent = message;
654
+ toast.classList.remove('hidden');
655
+
656
+ // Change color based on type
657
+ const toastInner = toast.querySelector('div');
658
+ toastInner.className = `px-4 py-2 rounded shadow-lg flex items-center ${
659
+ type === 'success' ? 'bg-green-500 text-white' :
660
+ type === 'error' ? 'bg-red-500 text-white' : 'bg-blue-500 text-white'
661
+ }`;
662
+
663
+ // Auto hide after 3 seconds
664
+ setTimeout(hideToast, 3000);
665
+ }
666
+
667
+ // Load SMTP settings
668
+ function loadSmtpSettings() {
669
+ document.getElementById('smtpHost').value = smtpSettings.host;
670
+ document.getElementById('smtpPort').value = smtpSettings.port;
671
+ document.getElementById('smtpUsername').value = smtpSettings.username;
672
+ document.getElementById('smtpPassword').value = smtpSettings.password;
673
+ document.getElementById('smtpFromEmail').value = smtpSettings.fromEmail;
674
+ }
675
+
676
+ // Save SMTP settings
677
+ function saveSmtpSettings(e) {
678
+ e.preventDefault();
679
+
680
+ smtpSettings = {
681
+ host: document.getElementById('smtpHost').value,
682
+ port: parseInt(document.getElementById('smtpPort').value),
683
+ username: document.getElementById('smtpUsername').value,
684
+ password: document.getElementById('smtpPassword').value,
685
+ fromEmail: document.getElementById('smtpFromEmail').value
686
+ };
687
+
688
+ localStorage.setItem('smtpSettings', JSON.stringify(smtpSettings));
689
+ showToast('SMTP settings saved successfully!');
690
+ }
691
+
692
+ // Check for birthdays and anniversaries daily
693
+ function checkForCelebrations() {
694
+ const today = new Date();
695
+ const todayStr = today.toISOString().split('T')[0];
696
+ const todayMonthDay = todayStr.substring(5);
697
+
698
+ employees.forEach(employee => {
699
+ // Check birthday (compare month and day)
700
+ const bdayMonthDay = employee.birthday.substring(5);
701
+ if (bdayMonthDay === todayMonthDay) {
702
+ sendEmailToEmployee(employee, 'birthday');
703
+ }
704
+
705
+ // Check work anniversary (compare month and day)
706
+ const appMonthDay = employee.appointmentDate.substring(5);
707
+ if (appMonthDay === todayMonthDay) {
708
+ sendEmailToEmployee(employee, 'appointment');
709
+ }
710
+ });
711
+ }
712
+
713
+ // Start daily checker
714
+ function startDailyChecker() {
715
+ // Check immediately on startup
716
+ checkForCelebrations();
717
+
718
+ // Then check every 24 hours
719
+ setInterval(checkForCelebrations, 24 * 60 * 60 * 1000);
720
+ }
721
+
722
+ // Hide toast
723
+ function hideToast() {
724
+ toast.classList.add('hidden');
725
+ }
726
+
727
+ // Export to Excel
728
+ function exportToExcel() {
729
+ if (employees.length === 0) {
730
+ showToast('No employees to export', 'error');
731
+ return;
732
+ }
733
+
734
+ try {
735
+ // Prepare data for export
736
+ const data = employees.map(emp => ({
737
+ 'Full Name': emp.name,
738
+ 'Email': emp.email,
739
+ 'Birthday': formatDate(emp.birthday),
740
+ 'Appointment Date': formatDate(emp.appointmentDate),
741
+ 'Department': emp.department
742
+ }));
743
+
744
+ // Create worksheet and workbook
745
+ const ws = XLSX.utils.json_to_sheet(data);
746
+ const wb = XLSX.utils.book_new();
747
+ XLSX.utils.book_append_sheet(wb, ws, "Employees");
748
+
749
+ // Generate and download the file
750
+ XLSX.writeFile(wb, "employees.xlsx");
751
+ showToast('Employee data exported successfully!');
752
+ } catch (error) {
753
+ console.error('Export error:', error);
754
+ showToast('Failed to export data', 'error');
755
+ }
756
+ }
757
+
758
+ // Import from Excel
759
+ function importFromExcel(event) {
760
+ const file = event.target.files[0];
761
+ if (!file) return;
762
+
763
+ const reader = new FileReader();
764
+ reader.onload = function(e) {
765
+ try {
766
+ const data = new Uint8Array(e.target.result);
767
+ const workbook = XLSX.read(data, { type: 'array' });
768
+
769
+ // Get first sheet
770
+ const firstSheet = workbook.Sheets[workbook.SheetNames[0]];
771
+ const jsonData = XLSX.utils.sheet_to_json(firstSheet);
772
+
773
+ // Map to our employee format
774
+ const newEmployees = jsonData.map(item => ({
775
+ id: Date.now().toString() + Math.random().toString(36).substr(2, 9),
776
+ name: item['Full Name'] || item['Name'] || '',
777
+ email: item['Email'] || '',
778
+ birthday: item['Birthday'] ? new Date(item['Birthday']).toISOString().split('T')[0] : '',
779
+ appointmentDate: item['Appointment Date'] ? new Date(item['Appointment Date']).toISOString().split('T')[0] : '',
780
+ department: item['Department'] || 'General'
781
+ }));
782
+
783
+ if (confirm(`Import ${newEmployees.length} employees? This will add them to your current list.`)) {
784
+ employees = [...employees, ...newEmployees];
785
+ saveEmployees();
786
+ renderEmployeeTable();
787
+ showToast(`Successfully imported ${newEmployees.length} employees`);
788
+ }
789
+ } catch (error) {
790
+ console.error('Import error:', error);
791
+ showToast('Failed to import data. Please check file format.', 'error');
792
+ }
793
+ // Reset file input
794
+ event.target.value = '';
795
+ };
796
+ reader.readAsArrayBuffer(file);
797
+ }
798
+
799
+ // Initialize daily checker when page loads
800
+ startDailyChecker();
801
+ </script>
802
+ <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=elhamshari/employee-automation" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
803
+ </html>