thors1 commited on
Commit
5fc8d22
·
verified ·
1 Parent(s): 290edef

Initial DeepSite commit

Browse files
Files changed (3) hide show
  1. README.md +9 -6
  2. index.html +466 -19
  3. script.js +364 -0
README.md CHANGED
@@ -1,10 +1,13 @@
1
  ---
2
- title: Deepsite Project Haybs
3
- emoji: 🚀
4
- colorFrom: pink
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: DeepSite Project
3
+ colorFrom: red
4
+ colorTo: purple
 
5
  sdk: static
6
+ emoji: 🌟
7
+ tags:
8
+ - deepsite-v4
9
  ---
10
 
11
+ # DeepSite Project
12
+
13
+ This project has been created with [DeepSite](https://deepsite.hf.co) AI Vibe Coding.
index.html CHANGED
@@ -1,19 +1,466 @@
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>MediCare Admin - Add Appointment</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <script src="https://unpkg.com/lucide@latest"></script>
9
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
10
+ <style>
11
+ * {
12
+ font-family: 'Inter', sans-serif;
13
+ }
14
+
15
+ .sidebar-transition {
16
+ transition: width 0.3s cubic-bezier(0.4, 0, 0.2, 1);
17
+ }
18
+
19
+ .menu-text {
20
+ transition: opacity 0.2s ease-in-out, width 0.2s ease-in-out;
21
+ white-space: nowrap;
22
+ }
23
+
24
+ .collapsed .menu-text {
25
+ opacity: 0;
26
+ width: 0;
27
+ display: none;
28
+ }
29
+
30
+ .submenu {
31
+ max-height: 0;
32
+ overflow: hidden;
33
+ transition: max-height 0.3s ease-in-out;
34
+ }
35
+
36
+ .submenu.expanded {
37
+ max-height: 200px;
38
+ }
39
+
40
+ .time-slot {
41
+ transition: all 0.2s ease;
42
+ }
43
+
44
+ .time-slot:hover:not(:disabled) {
45
+ transform: translateY(-2px);
46
+ box-shadow: 0 4px 6px -1px rgba(59, 130, 246, 0.2);
47
+ }
48
+
49
+ .time-slot.selected {
50
+ background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);
51
+ color: white;
52
+ border-color: #2563eb;
53
+ }
54
+
55
+ .time-slot.booked {
56
+ background-color: #f3f4f6;
57
+ color: #9ca3af;
58
+ cursor: not-allowed;
59
+ text-decoration: line-through;
60
+ }
61
+
62
+ .patient-type-btn.active {
63
+ background-color: #eff6ff;
64
+ border-color: #3b82f6;
65
+ color: #2563eb;
66
+ }
67
+
68
+ /* Mobile sidebar overlay */
69
+ .sidebar-overlay {
70
+ display: none;
71
+ }
72
+
73
+ @media (max-width: 1024px) {
74
+ .sidebar-overlay.active {
75
+ display: block;
76
+ }
77
+ }
78
+
79
+ .scroll-hidden::-webkit-scrollbar {
80
+ display: none;
81
+ }
82
+ .scroll-hidden {
83
+ -ms-overflow-style: none;
84
+ scrollbar-width: none;
85
+ }
86
+
87
+ .fade-in {
88
+ animation: fadeIn 0.3s ease-in;
89
+ }
90
+
91
+ @keyframes fadeIn {
92
+ from { opacity: 0; transform: translateY(10px); }
93
+ to { opacity: 1; transform: translateY(0); }
94
+ }
95
+ </style>
96
+ </head>
97
+ <body class="bg-gray-50 text-gray-800">
98
+
99
+ <!-- Mobile Overlay -->
100
+ <div id="sidebarOverlay" class="sidebar-overlay fixed inset-0 bg-black bg-opacity-50 z-40 lg:hidden" onclick="toggleSidebar()"></div>
101
+
102
+ <div class="flex h-screen overflow-hidden">
103
+
104
+ <!-- Sidebar -->
105
+ <aside id="sidebar" class="sidebar-transition fixed lg:static inset-y-0 left-0 z-50 w-72 bg-white border-r border-gray-200 flex flex-col shadow-lg lg:shadow-none transform -translate-x-full lg:translate-x-0">
106
+
107
+ <!-- Logo Area -->
108
+ <div class="h-16 flex items-center px-6 border-b border-gray-100">
109
+ <div class="flex items-center gap-3 w-full">
110
+ <div class="w-10 h-10 bg-blue-600 rounded-xl flex items-center justify-center flex-shrink-0">
111
+ <i data-lucide="activity" class="w-6 h-6 text-white"></i>
112
+ </div>
113
+ <span class="menu-text font-bold text-xl text-gray-900 tracking-tight">MediCare</span>
114
+ </div>
115
+ </div>
116
+
117
+ <!-- Navigation -->
118
+ <nav class="flex-1 overflow-y-auto scroll-hidden py-4 px-3 space-y-1">
119
+
120
+ <!-- Dashboard -->
121
+ <a href="#" class="flex items-center gap-3 px-3 py-2.5 text-gray-600 hover:bg-gray-50 hover:text-gray-900 rounded-lg transition-colors group">
122
+ <i data-lucide="layout-dashboard" class="w-5 h-5 flex-shrink-0 group-hover:text-blue-600"></i>
123
+ <span class="menu-text font-medium">Dashboard</span>
124
+ </a>
125
+
126
+ <!-- Patients -->
127
+ <a href="#" class="flex items-center gap-3 px-3 py-2.5 text-gray-600 hover:bg-gray-50 hover:text-gray-900 rounded-lg transition-colors group">
128
+ <i data-lucide="users" class="w-5 h-5 flex-shrink-0 group-hover:text-blue-600"></i>
129
+ <span class="menu-text font-medium">Patients</span>
130
+ </a>
131
+
132
+ <!-- Appointments (Expanded) -->
133
+ <div class="space-y-1">
134
+ <button onclick="toggleSubmenu()" class="w-full flex items-center gap-3 px-3 py-2.5 text-blue-600 bg-blue-50 rounded-lg transition-colors font-medium">
135
+ <i data-lucide="calendar-check" class="w-5 h-5 flex-shrink-0"></i>
136
+ <span class="menu-text flex-1 text-left">Appointments</span>
137
+ <i data-lucide="chevron-down" id="submenuIcon" class="w-4 h-4 flex-shrink-0 menu-text transition-transform"></i>
138
+ </button>
139
+
140
+ <!-- Submenu -->
141
+ <div id="appointmentsSubmenu" class="submenu expanded ml-4 space-y-1 border-l-2 border-blue-200 pl-4">
142
+ <a href="#" class="flex items-center gap-3 px-3 py-2 text-sm font-medium text-blue-700 bg-blue-100/50 rounded-lg">
143
+ <i data-lucide="plus-circle" class="w-4 h-4"></i>
144
+ <span class="menu-text">Add Appointment</span>
145
+ </a>
146
+ <a href="#" class="flex items-center gap-3 px-3 py-2 text-sm font-medium text-gray-600 hover:text-blue-600 hover:bg-blue-50/50 rounded-lg transition-colors">
147
+ <i data-lucide="list" class="w-4 h-4"></i>
148
+ <span class="menu-text">View All</span>
149
+ </a>
150
+ <a href="#" class="flex items-center gap-3 px-3 py-2 text-sm font-medium text-gray-600 hover:text-blue-600 hover:bg-blue-50/50 rounded-lg transition-colors">
151
+ <i data-lucide="clock" class="w-4 h-4"></i>
152
+ <span class="menu-text">Upcoming</span>
153
+ </a>
154
+ </div>
155
+ </div>
156
+
157
+ <!-- Physicians -->
158
+ <a href="#" class="flex items-center gap-3 px-3 py-2.5 text-gray-600 hover:bg-gray-50 hover:text-gray-900 rounded-lg transition-colors group">
159
+ <i data-lucide="stethoscope" class="w-5 h-5 flex-shrink-0 group-hover:text-blue-600"></i>
160
+ <span class="menu-text font-medium">Physicians</span>
161
+ </a>
162
+
163
+ <!-- Medical Records -->
164
+ <a href="#" class="flex items-center gap-3 px-3 py-2.5 text-gray-600 hover:bg-gray-50 hover:text-gray-900 rounded-lg transition-colors group">
165
+ <i data-lucide="file-text" class="w-5 h-5 flex-shrink-0 group-hover:text-blue-600"></i>
166
+ <span class="menu-text font-medium">Medical Records</span>
167
+ </a>
168
+
169
+ <!-- Billing -->
170
+ <a href="#" class="flex items-center gap-3 px-3 py-2.5 text-gray-600 hover:bg-gray-50 hover:text-gray-900 rounded-lg transition-colors group">
171
+ <i data-lucide="credit-card" class="w-5 h-5 flex-shrink-0 group-hover:text-blue-600"></i>
172
+ <span class="menu-text font-medium">Billing</span>
173
+ </a>
174
+
175
+ <!-- Settings -->
176
+ <a href="#" class="flex items-center gap-3 px-3 py-2.5 text-gray-600 hover:bg-gray-50 hover:text-gray-900 rounded-lg transition-colors group">
177
+ <i data-lucide="settings" class="w-5 h-5 flex-shrink-0 group-hover:text-blue-600"></i>
178
+ <span class="menu-text font-medium">Settings</span>
179
+ </a>
180
+ </nav>
181
+
182
+ <!-- User Profile -->
183
+ <div class="border-t border-gray-200 p-4">
184
+ <div class="flex items-center gap-3">
185
+ <img src="https://static.photos/people/200x200/42" alt="Doctor" class="w-10 h-10 rounded-full object-cover border-2 border-white shadow-sm flex-shrink-0">
186
+ <div class="menu-text min-w-0">
187
+ <p class="text-sm font-semibold text-gray-900 truncate">Dr. Sarah Mitchell</p>
188
+ <p class="text-xs text-gray-500 truncate">Admin</p>
189
+ </div>
190
+ <button class="ml-auto menu-text text-gray-400 hover:text-gray-600">
191
+ <i data-lucide="log-out" class="w-5 h-5"></i>
192
+ </button>
193
+ </div>
194
+ </div>
195
+ </aside>
196
+
197
+ <!-- Main Content -->
198
+ <div class="flex-1 flex flex-col min-w-0 overflow-hidden">
199
+
200
+ <!-- Header -->
201
+ <header class="h-16 bg-white border-b border-gray-200 flex items-center justify-between px-4 lg:px-8 sticky top-0 z-30">
202
+ <div class="flex items-center gap-4">
203
+ <button onclick="toggleSidebar()" class="lg:hidden p-2 rounded-lg hover:bg-gray-100 text-gray-600">
204
+ <i data-lucide="menu" class="w-6 h-6"></i>
205
+ </button>
206
+ <button onclick="toggleSidebarDesktop()" class="hidden lg:flex p-2 rounded-lg hover:bg-gray-100 text-gray-600 transition-colors" id="desktopToggle">
207
+ <i data-lucide="panel-left" class="w-5 h-5"></i>
208
+ </button>
209
+ <h1 class="text-xl font-semibold text-gray-900 hidden sm:block">Add Appointment</h1>
210
+ </div>
211
+
212
+ <div class="flex items-center gap-4">
213
+ <button class="p-2 rounded-lg hover:bg-gray-100 text-gray-600 relative">
214
+ <i data-lucide="bell" class="w-5 h-5"></i>
215
+ <span class="absolute top-1.5 right-1.5 w-2 h-2 bg-red-500 rounded-full border-2 border-white"></span>
216
+ </button>
217
+ <div class="hidden sm:flex items-center gap-2 text-sm text-gray-600">
218
+ <i data-lucide="calendar" class="w-4 h-4"></i>
219
+ <span id="currentDate"></span>
220
+ </div>
221
+ </div>
222
+ </header>
223
+
224
+ <!-- Main Content Area -->
225
+ <main class="flex-1 overflow-y-auto p-4 lg:p-8 scroll-hidden">
226
+ <div class="max-w-6xl mx-auto">
227
+
228
+ <!-- Page Title Mobile -->
229
+ <div class="sm:hidden mb-6">
230
+ <h1 class="text-2xl font-bold text-gray-900">Add Appointment</h1>
231
+ <p class="text-gray-500 mt-1">Schedule a new patient appointment</p>
232
+ </div>
233
+
234
+ <!-- Breadcrumb -->
235
+ <div class="hidden sm:flex items-center gap-2 text-sm text-gray-500 mb-6">
236
+ <span>Appointments</span>
237
+ <i data-lucide="chevron-right" class="w-4 h-4"></i>
238
+ <span class="text-blue-600 font-medium">Add Appointment</span>
239
+ </div>
240
+
241
+ <div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
242
+
243
+ <!-- Left Column - Patient & Appointment Details -->
244
+ <div class="lg:col-span-2 space-y-6">
245
+
246
+ <!-- Patient Selection Card -->
247
+ <div class="bg-white rounded-2xl shadow-sm border border-gray-200 p-6 fade-in">
248
+ <div class="flex items-center gap-3 mb-6">
249
+ <div class="w-10 h-10 bg-blue-100 rounded-full flex items-center justify-center">
250
+ <i data-lucide="user" class="w-5 h-5 text-blue-600"></i>
251
+ </div>
252
+ <div>
253
+ <h2 class="text-lg font-semibold text-gray-900">Patient Information</h2>
254
+ <p class="text-sm text-gray-500">Select patient type and enter details</p>
255
+ </div>
256
+ </div>
257
+
258
+ <!-- Patient Type Toggle -->
259
+ <div class="flex p-1 bg-gray-100 rounded-xl mb-6 w-fit">
260
+ <button onclick="setPatientType('new')" id="btnNewPatient" class="patient-type-btn active px-4 py-2 rounded-lg text-sm font-medium transition-all flex items-center gap-2">
261
+ <i data-lucide="user-plus" class="w-4 h-4"></i>
262
+ <span>New Patient</span>
263
+ </button>
264
+ <button onclick="setPatientType('existing')" id="btnExistingPatient" class="patient-type-btn px-4 py-2 rounded-lg text-sm font-medium text-gray-600 transition-all flex items-center gap-2">
265
+ <i data-lucide="search" class="w-4 h-4"></i>
266
+ <span>Existing Patient</span>
267
+ </button>
268
+ </div>
269
+
270
+ <!-- New Patient Form -->
271
+ <div id="newPatientForm" class="space-y-4 fade-in">
272
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
273
+ <div>
274
+ <label class="block text-sm font-medium text-gray-700 mb-1.5">First Name *</label>
275
+ <input type="text" class="w-full px-4 py-2.5 border border-gray-300 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none transition-all" placeholder="Enter first name">
276
+ </div>
277
+ <div>
278
+ <label class="block text-sm font-medium text-gray-700 mb-1.5">Last Name *</label>
279
+ <input type="text" class="w-full px-4 py-2.5 border border-gray-300 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none transition-all" placeholder="Enter last name">
280
+ </div>
281
+ </div>
282
+
283
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
284
+ <div>
285
+ <label class="block text-sm font-medium text-gray-700 mb-1.5">Email Address *</label>
286
+ <input type="email" class="w-full px-4 py-2.5 border border-gray-300 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none transition-all" placeholder="patient@example.com">
287
+ </div>
288
+ <div>
289
+ <label class="block text-sm font-medium text-gray-700 mb-1.5">Phone Number *</label>
290
+ <input type="tel" class="w-full px-4 py-2.5 border border-gray-300 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none transition-all" placeholder="+1 (555) 000-0000">
291
+ </div>
292
+ </div>
293
+
294
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
295
+ <div>
296
+ <label class="block text-sm font-medium text-gray-700 mb-1.5">Date of Birth *</label>
297
+ <input type="date" class="w-full px-4 py-2.5 border border-gray-300 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none transition-all">
298
+ </div>
299
+ <div>
300
+ <label class="block text-sm font-medium text-gray-700 mb-1.5">Gender</label>
301
+ <select class="w-full px-4 py-2.5 border border-gray-300 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none transition-all bg-white">
302
+ <option value="">Select Gender</option>
303
+ <option value="male">Male</option>
304
+ <option value="female">Female</option>
305
+ <option value="other">Other</option>
306
+ <option value="prefer-not">Prefer not to say</option>
307
+ </select>
308
+ </div>
309
+ </div>
310
+ </div>
311
+
312
+ <!-- Existing Patient Search -->
313
+ <div id="existingPatientForm" class="hidden space-y-4 fade-in">
314
+ <div class="relative">
315
+ <i data-lucide="search" class="absolute left-3 top-1/2 -translate-y-1/2 w-5 h-5 text-gray-400"></i>
316
+ <input type="text" class="w-full pl-10 pr-4 py-2.5 border border-gray-300 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none transition-all" placeholder="Search by name, email, or phone number..." onkeyup="searchPatients(this.value)">
317
+ </div>
318
+
319
+ <!-- Search Results -->
320
+ <div id="patientResults" class="space-y-2 max-h-60 overflow-y-auto">
321
+ <!-- Results populated by JS -->
322
+ </div>
323
+ </div>
324
+ </div>
325
+
326
+ <!-- Appointment Details Card -->
327
+ <div class="bg-white rounded-2xl shadow-sm border border-gray-200 p-6 fade-in">
328
+ <div class="flex items-center gap-3 mb-6">
329
+ <div class="w-10 h-10 bg-green-100 rounded-full flex items-center justify-center">
330
+ <i data-lucide="clipboard-list" class="w-5 h-5 text-green-600"></i>
331
+ </div>
332
+ <div>
333
+ <h2 class="text-lg font-semibold text-gray-900">Appointment Details</h2>
334
+ <p class="text-sm text-gray-500">Select physician, category, and date</p>
335
+ </div>
336
+ </div>
337
+
338
+ <div class="space-y-5">
339
+ <!-- Physician Select -->
340
+ <div>
341
+ <label class="block text-sm font-medium text-gray-700 mb-1.5">Select Physician *</label>
342
+ <div class="relative">
343
+ <select id="physicianSelect" class="w-full px-4 py-2.5 border border-gray-300 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none transition-all bg-white appearance-none cursor-pointer" onchange="updateTimeSlots()">
344
+ <option value="">Choose a physician</option>
345
+ <option value="dr-mitchell">Dr. Sarah Mitchell - Cardiology</option>
346
+ <option value="dr-johnson">Dr. James Johnson - General Medicine</option>
347
+ <option value="dr-williams">Dr. Emily Williams - Pediatrics</option>
348
+ <option value="dr-brown">Dr. Michael Brown - Orthopedics</option>
349
+ <option value="dr-davis">Dr. Lisa Davis - Dermatology</option>
350
+ </select>
351
+ <i data-lucide="chevron-down" class="absolute right-3 top-1/2 -translate-y-1/2 w-5 h-5 text-gray-400 pointer-events-none"></i>
352
+ </div>
353
+ </div>
354
+
355
+ <!-- Category Select -->
356
+ <div>
357
+ <label class="block text-sm font-medium text-gray-700 mb-1.5">Appointment Category *</label>
358
+ <div class="grid grid-cols-2 md:grid-cols-3 gap-3">
359
+ <button onclick="selectCategory('consultation')" class="category-btn p-3 border-2 border-gray-200 rounded-xl text-center hover:border-blue-500 hover:bg-blue-50 transition-all group" data-category="consultation">
360
+ <i data-lucide="message-circle" class="w-5 h-5 mx-auto mb-1 text-gray-500 group-hover:text-blue-600"></i>
361
+ <span class="text-sm font-medium text-gray-700 group-hover:text-blue-700">Consultation</span>
362
+ </button>
363
+ <button onclick="selectCategory('follow-up')" class="category-btn p-3 border-2 border-gray-200 rounded-xl text-center hover:border-blue-500 hover:bg-blue-50 transition-all group" data-category="follow-up">
364
+ <i data-lucide="refresh-cw" class="w-5 h-5 mx-auto mb-1 text-gray-500 group-hover:text-blue-600"></i>
365
+ <span class="text-sm font-medium text-gray-700 group-hover:text-blue-700">Follow-up</span>
366
+ </button>
367
+ <button onclick="selectCategory('routine')" class="category-btn p-3 border-2 border-gray-200 rounded-xl text-center hover:border-blue-500 hover:bg-blue-50 transition-all group" data-category="routine">
368
+ <i data-lucide="activity" class="w-5 h-5 mx-auto mb-1 text-gray-500 group-hover:text-blue-600"></i>
369
+ <span class="text-sm font-medium text-gray-700 group-hover:text-blue-700">Routine Check</span>
370
+ </button>
371
+ <button onclick="selectCategory('emergency')" class="category-btn p-3 border-2 border-gray-200 rounded-xl text-center hover:border-red-500 hover:bg-red-50 transition-all group" data-category="emergency">
372
+ <i data-lucide="alert-circle" class="w-5 h-5 mx-auto mb-1 text-gray-500 group-hover:text-red-600"></i>
373
+ <span class="text-sm font-medium text-gray-700 group-hover:text-red-700">Emergency</span>
374
+ </button>
375
+ <button onclick="selectCategory('surgery')" class="category-btn p-3 border-2 border-gray-200 rounded-xl text-center hover:border-blue-500 hover:bg-blue-50 transition-all group" data-category="surgery">
376
+ <i data-lucide="scissors" class="w-5 h-5 mx-auto mb-1 text-gray-500 group-hover:text-blue-600"></i>
377
+ <span class="text-sm font-medium text-gray-700 group-hover:text-blue-700">Surgery</span>
378
+ </button>
379
+ <button onclick="selectCategory('vaccination')" class="category-btn p-3 border-2 border-gray-200 rounded-xl text-center hover:border-blue-500 hover:bg-blue-50 transition-all group" data-category="vaccination">
380
+ <i data-lucide="syringe" class="w-5 h-5 mx-auto mb-1 text-gray-500 group-hover:text-blue-600"></i>
381
+ <span class="text-sm font-medium text-gray-700 group-hover:text-blue-700">Vaccination</span>
382
+ </button>
383
+ </div>
384
+ <input type="hidden" id="selectedCategory" value="">
385
+ </div>
386
+
387
+ <!-- Date Selection -->
388
+ <div>
389
+ <label class="block text-sm font-medium text-gray-700 mb-1.5">Select Date *</label>
390
+ <input type="date" id="appointmentDate" class="w-full px-4 py-2.5 border border-gray-300 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none transition-all" onchange="updateTimeSlots()">
391
+ </div>
392
+
393
+ <!-- Notes -->
394
+ <div>
395
+ <label class="block text-sm font-medium text-gray-700 mb-1.5">Notes / Symptoms</label>
396
+ <textarea rows="3" class="w-full px-4 py-2.5 border border-gray-300 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none transition-all resize-none" placeholder="Describe symptoms or add special notes..."></textarea>
397
+ </div>
398
+ </div>
399
+ </div>
400
+ </div>
401
+
402
+ <!-- Right Column - Time Slots -->
403
+ <div class="lg:col-span-1">
404
+ <div class="bg-white rounded-2xl shadow-sm border border-gray-200 p-6 sticky top-6 fade-in">
405
+ <div class="flex items-center gap-3 mb-6">
406
+ <div class="w-10 h-10 bg-purple-100 rounded-full flex items-center justify-center">
407
+ <i data-lucide="clock" class="w-5 h-5 text-purple-600"></i>
408
+ </div>
409
+ <div>
410
+ <h2 class="text-lg font-semibold text-gray-900">Available Times</h2>
411
+ <p class="text-sm text-gray-500" id="selectedDateDisplay">Select a date to view times</p>
412
+ </div>
413
+ </div>
414
+
415
+ <div id="timeSlotsContainer" class="space-y-4">
416
+ <div class="text-center py-12 text-gray-400">
417
+ <i data-lucide="calendar-days" class="w-12 h-12 mx-auto mb-3 opacity-50"></i>
418
+ <p class="text-sm">Please select a physician and date to view available time slots</p>
419
+ </div>
420
+ </div>
421
+
422
+ <!-- Selected Time Display -->
423
+ <div id="selectedTimeDisplay" class="hidden mt-6 p-4 bg-blue-50 rounded-xl border border-blue-100">
424
+ <div class="flex items-center gap-3">
425
+ <i data-lucide="check-circle" class="w-5 h-5 text-blue-600"></i>
426
+ <div>
427
+ <p class="text-sm font-medium text-blue-900">Selected Time</p>
428
+ <p class="text-lg font-bold text-blue-700" id="confirmedTime">--:--</p>
429
+ </div>
430
+ </div>
431
+ </div>
432
+
433
+ <!-- Action Buttons -->
434
+ <div class="mt-6 space-y-3">
435
+ <button onclick="saveAppointment()" class="w-full py-3 bg-blue-600 hover:bg-blue-700 text-white font-semibold rounded-xl transition-all flex items-center justify-center gap-2 shadow-lg shadow-blue-200">
436
+ <i data-lucide="check" class="w-5 h-5"></i>
437
+ Confirm Appointment
438
+ </button>
439
+ <button onclick="resetForm()" class="w-full py-3 bg-white border border-gray-300 hover:bg-gray-50 text-gray-700 font-semibold rounded-xl transition-all flex items-center justify-center gap-2">
440
+ <i data-lucide="x" class="w-5 h-5"></i>
441
+ Cancel
442
+ </button>
443
+ </div>
444
+ </div>
445
+ </div>
446
+ </div>
447
+ </div>
448
+ </main>
449
+ </div>
450
+ </div>
451
+
452
+ <!-- Toast Notification -->
453
+ <div id="toast" class="fixed bottom-4 right-4 transform translate-y-20 opacity-0 transition-all duration-300 z-50">
454
+ <div class="bg-gray-900 text-white px-6 py-3 rounded-lg shadow-lg flex items-center gap-3">
455
+ <i data-lucide="check-circle" class="w-5 h-5 text-green-400"></i>
456
+ <span id="toastMessage">Appointment saved successfully!</span>
457
+ </div>
458
+ </div>
459
+
460
+ <script src="script.js"></script>
461
+ <script>
462
+ lucide.createIcons();
463
+ </script>
464
+ <script src="https://deepsite.hf.co/deepsite-badge.js"></script>
465
+ </body>
466
+ </html>
script.js ADDED
@@ -0,0 +1,364 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Initialize Lucide icons
2
+ document.addEventListener('DOMContentLoaded', function() {
3
+ lucide.createIcons();
4
+ initializeDate();
5
+ initializeMockPatients();
6
+ });
7
+
8
+ // Sidebar Management
9
+ let sidebarCollapsed = false;
10
+
11
+ function toggleSidebar() {
12
+ const sidebar = document.getElementById('sidebar');
13
+ const overlay = document.getElementById('sidebarOverlay');
14
+
15
+ sidebar.classList.toggle('-translate-x-full');
16
+ overlay.classList.toggle('active');
17
+ }
18
+
19
+ function toggleSidebarDesktop() {
20
+ const sidebar = document.getElementById('sidebar');
21
+ const mainContent = document.querySelector('.flex-1.flex.flex-col');
22
+
23
+ sidebarCollapsed = !sidebarCollapsed;
24
+
25
+ if (sidebarCollapsed) {
26
+ sidebar.classList.remove('w-72');
27
+ sidebar.classList.add('w-20', 'collapsed');
28
+ } else {
29
+ sidebar.classList.remove('w-20', 'collapsed');
30
+ sidebar.classList.add('w-72');
31
+ }
32
+
33
+ // Re-render icons to ensure proper sizing
34
+ setTimeout(() => lucide.createIcons(), 300);
35
+ }
36
+
37
+ function toggleSubmenu() {
38
+ const submenu = document.getElementById('appointmentsSubmenu');
39
+ const icon = document.getElementById('submenuIcon');
40
+
41
+ submenu.classList.toggle('expanded');
42
+
43
+ if (submenu.classList.contains('expanded')) {
44
+ icon.style.transform = 'rotate(180deg)';
45
+ } else {
46
+ icon.style.transform = 'rotate(0deg)';
47
+ }
48
+ }
49
+
50
+ // Patient Type Management
51
+ let currentPatientType = 'new';
52
+
53
+ function setPatientType(type) {
54
+ currentPatientType = type;
55
+ const btnNew = document.getElementById('btnNewPatient');
56
+ const btnExisting = document.getElementById('btnExistingPatient');
57
+ const newForm = document.getElementById('newPatientForm');
58
+ const existingForm = document.getElementById('existingPatientForm');
59
+
60
+ if (type === 'new') {
61
+ btnNew.classList.add('active');
62
+ btnExisting.classList.remove('active');
63
+ newForm.classList.remove('hidden');
64
+ existingForm.classList.add('hidden');
65
+ } else {
66
+ btnNew.classList.remove('active');
67
+ btnExisting.classList.add('active');
68
+ newForm.classList.add('hidden');
69
+ existingForm.classList.remove('hidden');
70
+ }
71
+ }
72
+
73
+ // Mock Patient Data
74
+ const mockPatients = [
75
+ { id: 1, name: 'John Anderson', email: 'john.a@email.com', phone: '(555) 123-4567', age: 45, lastVisit: '2024-01-15' },
76
+ { id: 2, name: 'Maria Garcia', email: 'maria.g@email.com', phone: '(555) 234-5678', age: 32, lastVisit: '2024-02-20' },
77
+ { id: 3, name: 'Robert Chen', email: 'robert.c@email.com', phone: '(555) 345-6789', age: 28, lastVisit: '2024-03-01' },
78
+ { id: 4, name: 'Sarah Johnson', email: 'sarah.j@email.com', phone: '(555) 456-7890', age: 56, lastVisit: '2024-01-28' },
79
+ { id: 5, name: 'Michael Brown', email: 'mike.b@email.com', phone: '(555) 567-8901', age: 41, lastVisit: '2024-02-14' },
80
+ { id: 6, name: 'Emily Davis', email: 'emily.d@email.com', phone: '(555) 678-9012', age: 29, lastVisit: '2024-03-10' }
81
+ ];
82
+
83
+ function initializeMockPatients() {
84
+ // Pre-populate with all patients
85
+ displayPatientResults(mockPatients);
86
+ }
87
+
88
+ function searchPatients(query) {
89
+ const filtered = mockPatients.filter(patient =>
90
+ patient.name.toLowerCase().includes(query.toLowerCase()) ||
91
+ patient.email.toLowerCase().includes(query.toLowerCase()) ||
92
+ patient.phone.includes(query)
93
+ );
94
+ displayPatientResults(filtered);
95
+ }
96
+
97
+ function displayPatientResults(patients) {
98
+ const container = document.getElementById('patientResults');
99
+
100
+ if (patients.length === 0) {
101
+ container.innerHTML = `
102
+ <div class="text-center py-8 text-gray-400">
103
+ <p class="text-sm">No patients found</p>
104
+ </div>
105
+ `;
106
+ return;
107
+ }
108
+
109
+ container.innerHTML = patients.map(patient => `
110
+ <div onclick="selectPatient(${patient.id})" class="flex items-center gap-3 p-3 rounded-xl border border-gray-200 hover:border-blue-500 hover:bg-blue-50 cursor-pointer transition-all group">
111
+ <div class="w-10 h-10 bg-gradient-to-br from-blue-400 to-blue-600 rounded-full flex items-center justify-center text-white font-semibold text-sm">
112
+ ${patient.name.split(' ').map(n => n[0]).join('')}
113
+ </div>
114
+ <div class="flex-1 min-w-0">
115
+ <p class="font-medium text-gray-900 truncate group-hover:text-blue-700">${patient.name}</p>
116
+ <p class="text-xs text-gray-500 truncate">${patient.email} • ${patient.phone}</p>
117
+ </div>
118
+ <div class="text-xs text-gray-400">
119
+ Age: ${patient.age}
120
+ </div>
121
+ </div>
122
+ `).join('');
123
+ }
124
+
125
+ function selectPatient(id) {
126
+ const patient = mockPatients.find(p => p.id === id);
127
+ showToast(`Selected patient: ${patient.name}`);
128
+ // In a real app, this would fill the form or mark as selected
129
+ }
130
+
131
+ // Category Selection
132
+ function selectCategory(category) {
133
+ // Remove active class from all
134
+ document.querySelectorAll('.category-btn').forEach(btn => {
135
+ btn.classList.remove('border-blue-500', 'bg-blue-50', 'border-red-500', 'bg-red-50');
136
+ btn.classList.add('border-gray-200');
137
+ });
138
+
139
+ // Add active class to selected
140
+ const selectedBtn = document.querySelector(`[data-category="${category}"]`);
141
+ if (category === 'emergency') {
142
+ selectedBtn.classList.remove('border-gray-200');
143
+ selectedBtn.classList.add('border-red-500', 'bg-red-50');
144
+ } else {
145
+ selectedBtn.classList.remove('border-gray-200');
146
+ selectedBtn.classList.add('border-blue-500', 'bg-blue-50');
147
+ }
148
+
149
+ document.getElementById('selectedCategory').value = category;
150
+ }
151
+
152
+ // Time Slot Management
153
+ const timeSlotsData = {
154
+ 'dr-mitchell': ['09:00 AM', '09:30 AM', '10:00 AM', '10:30 AM', '11:00 AM', '02:00 PM', '02:30 PM', '03:00 PM', '03:30 PM', '04:00 PM'],
155
+ 'dr-johnson': ['08:00 AM', '08:30 AM', '09:00 AM', '11:30 AM', '01:00 PM', '01:30 PM', '03:30 PM', '04:30 PM'],
156
+ 'dr-williams': ['09:00 AM', '10:30 AM', '12:00 PM', '02:30 PM', '03:30 PM', '04:30 PM'],
157
+ 'dr-brown': ['08:30 AM', '09:30 AM', '10:30 AM', '01:30 PM', '02:30 PM', '03:00 PM'],
158
+ 'dr-davis': ['09:00 AM', '11:00 AM', '01:00 PM', '02:00 PM', '04:00 PM', '04:30 PM']
159
+ };
160
+
161
+ // Randomly book some slots to simulate reality
162
+ const bookedSlots = {};
163
+
164
+ function initializeDate() {
165
+ const today = new Date().toISOString().split('T')[0];
166
+ document.getElementById('appointmentDate').value = today;
167
+ document.getElementById('appointmentDate').min = today;
168
+ document.getElementById('currentDate').textContent = new Date().toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' });
169
+ }
170
+
171
+ function updateTimeSlots() {
172
+ const physician = document.getElementById('physicianSelect').value;
173
+ const date = document.getElementById('appointmentDate').value;
174
+ const container = document.getElementById('timeSlotsContainer');
175
+ const dateDisplay = document.getElementById('selectedDateDisplay');
176
+
177
+ if (!physician || !date) {
178
+ container.innerHTML = `
179
+ <div class="text-center py-12 text-gray-400">
180
+ <i data-lucide="calendar-days" class="w-12 h-12 mx-auto mb-3 opacity-50"></i>
181
+ <p class="text-sm">Please select a physician and date to view available time slots</p>
182
+ </div>
183
+ `;
184
+ lucide.createIcons();
185
+ return;
186
+ }
187
+
188
+ dateDisplay.textContent = new Date(date).toLocaleDateString('en-US', { weekday: 'long', month: 'short', day: 'numeric' });
189
+
190
+ const slots = timeSlotsData[physician] || [];
191
+ const booked = bookedSlots[`${physician}-${date}`] || [];
192
+
193
+ // Generate morning and afternoon sections
194
+ const morningSlots = slots.filter(time => {
195
+ const hour = parseInt(time.split(':')[0]);
196
+ const isPM = time.includes('PM');
197
+ return (!isPM && hour < 12) || (isPM && hour === 12);
198
+ });
199
+
200
+ const afternoonSlots = slots.filter(time => {
201
+ const hour = parseInt(time.split(':')[0]);
202
+ const isPM = time.includes('PM');
203
+ return isPM && hour !== 12;
204
+ });
205
+
206
+ let html = '';
207
+
208
+ if (morningSlots.length > 0) {
209
+ html += `
210
+ <div class="mb-4">
211
+ <p class="text-xs font-semibold text-gray-500 uppercase tracking-wider mb-3">Morning</p>
212
+ <div class="grid grid-cols-2 gap-2">
213
+ ${morningSlots.map(time => createTimeSlotButton(time, booked.includes(time))).join('')}
214
+ </div>
215
+ </div>
216
+ `;
217
+ }
218
+
219
+ if (afternoonSlots.length > 0) {
220
+ html += `
221
+ <div>
222
+ <p class="text-xs font-semibold text-gray-500 uppercase tracking-wider mb-3">Afternoon</p>
223
+ <div class="grid grid-cols-2 gap-2">
224
+ ${afternoonSlots.map(time => createTimeSlotButton(time, booked.includes(time))).join('')}
225
+ </div>
226
+ </div>
227
+ `;
228
+ }
229
+
230
+ container.innerHTML = html;
231
+ }
232
+
233
+ function createTimeSlotButton(time, isBooked) {
234
+ if (isBooked) {
235
+ return `<button disabled class="time-slot booked py-2 px-3 rounded-lg border border-gray-200 text-sm font-medium">${time}</button>`;
236
+ }
237
+ return `<button onclick="selectTime('${time}')" class="time-slot py-2 px-3 rounded-lg border border-gray-200 text-sm font-medium text-gray-700 hover:border-blue-500 hover:text-blue-600 bg-white" data-time="${time}">${time}</button>`;
238
+ }
239
+
240
+ function selectTime(time) {
241
+ // Remove previous selection
242
+ document.querySelectorAll('.time-slot').forEach(btn => {
243
+ btn.classList.remove('selected');
244
+ });
245
+
246
+ // Add selection to clicked button
247
+ const buttons = document.querySelectorAll(`[data-time="${time}"]`);
248
+ buttons.forEach(btn => btn.classList.add('selected'));
249
+
250
+ // Show selected time display
251
+ document.getElementById('selectedTimeDisplay').classList.remove('hidden');
252
+ document.getElementById('confirmedTime').textContent = time;
253
+ }
254
+
255
+ // Form Actions
256
+ function saveAppointment() {
257
+ const physician = document.getElementById('physicianSelect').value;
258
+ const date = document.getElementById('appointmentDate').value;
259
+ const category = document.getElementById('selectedCategory').value;
260
+ const selectedTime = document.querySelector('.time-slot.selected');
261
+
262
+ if (!physician) {
263
+ showToast('Please select a physician', 'error');
264
+ return;
265
+ }
266
+ if (!date) {
267
+ showToast('Please select a date', 'error');
268
+ return;
269
+ }
270
+ if (!category) {
271
+ showToast('Please select an appointment category', 'error');
272
+ return;
273
+ }
274
+ if (!selectedTime) {
275
+ showToast('Please select a time slot', 'error');
276
+ return;
277
+ }
278
+
279
+ // Simulate saving
280
+ const time = selectedTime.getAttribute('data-time');
281
+
282
+ // Mark slot as booked
283
+ const key = `${physician}-${date}`;
284
+ if (!bookedSlots[key]) bookedSlots[key] = [];
285
+ bookedSlots[key].push(time);
286
+
287
+ showToast('Appointment scheduled successfully!');
288
+
289
+ // Reset after delay
290
+ setTimeout(() => {
291
+ resetForm();
292
+ }, 2000);
293
+ }
294
+
295
+ function resetForm() {
296
+ // Reset patient type
297
+ setPatientType('new');
298
+
299
+ // Reset inputs
300
+ document.querySelectorAll('input[type="text"], input[type="email"], input[type="tel"], textarea').forEach(input => {
301
+ input.value = '';
302
+ });
303
+ document.getElementById('physicianSelect').value = '';
304
+ document.getElementById('selectedCategory').value = '';
305
+
306
+ // Reset categories
307
+ document.querySelectorAll('.category-btn').forEach(btn => {
308
+ btn.classList.remove('border-blue-500', 'bg-blue-50', 'border-red-500', 'bg-red-50');
309
+ btn.classList.add('border-gray-200');
310
+ });
311
+
312
+ // Reset time slots
313
+ document.getElementById('timeSlotsContainer').innerHTML = `
314
+ <div class="text-center py-12 text-gray-400">
315
+ <i data-lucide="calendar-days" class="w-12 h-12 mx-auto mb-3 opacity-50"></i>
316
+ <p class="text-sm">Please select a physician and date to view available time slots</p>
317
+ </div>
318
+ `;
319
+ document.getElementById('selectedTimeDisplay').classList.add('hidden');
320
+ document.getElementById('selectedDateDisplay').textContent = 'Select a date to view times';
321
+
322
+ // Reset date to today
323
+ initializeDate();
324
+
325
+ lucide.createIcons();
326
+ }
327
+
328
+ function showToast(message, type = 'success') {
329
+ const toast = document.getElementById('toast');
330
+ const toastMessage = document.getElementById('toastMessage');
331
+
332
+ toastMessage.textContent = message;
333
+
334
+ if (type === 'error') {
335
+ toast.querySelector('i').classList.remove('text-green-400');
336
+ toast.querySelector('i').classList.add('text-red-400');
337
+ toast.querySelector('i').setAttribute('data-lucide', 'alert-circle');
338
+ } else {
339
+ toast.querySelector('i').classList.remove('text-red-400');
340
+ toast.querySelector('i').classList.add('text-green-400');
341
+ toast.querySelector('i').setAttribute('data-lucide', 'check-circle');
342
+ }
343
+
344
+ lucide.createIcons();
345
+
346
+ toast.classList.remove('translate-y-20', 'opacity-0');
347
+
348
+ setTimeout(() => {
349
+ toast.classList.add('translate-y-20', 'opacity-0');
350
+ }, 3000);
351
+ }
352
+
353
+ // Close sidebar when clicking outside on mobile
354
+ document.addEventListener('click', function(e) {
355
+ const sidebar = document.getElementById('sidebar');
356
+ const toggleBtn = document.querySelector('button[onclick="toggleSidebar()"]');
357
+
358
+ if (window.innerWidth < 1024) {
359
+ if (!sidebar.contains(e.target) && !toggleBtn.contains(e.target)) {
360
+ sidebar.classList.add('-translate-x-full');
361
+ document.getElementById('sidebarOverlay').classList.remove('active');
362
+ }
363
+ }
364
+ });