thors1 commited on
Commit
bf5cffe
·
verified ·
1 Parent(s): 4f425b2

Initial DeepSite commit

Browse files
Files changed (4) hide show
  1. README.md +8 -5
  2. index.html +537 -19
  3. script.js +554 -0
  4. style.css +131 -19
README.md CHANGED
@@ -1,10 +1,13 @@
1
  ---
2
- title: Deepsite Project Cfqed
3
- emoji: ⚡
4
  colorFrom: blue
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: DeepSite Project
 
3
  colorFrom: blue
4
+ colorTo: gray
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,537 @@
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>ClinicalConnect Pro - Patient Appointments</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
+ body { font-family: 'Inter', sans-serif; }
12
+ .hide-scrollbar::-webkit-scrollbar { display: none; }
13
+ .hide-scrollbar { -ms-overflow-style: none; scrollbar-width: none; }
14
+ .glass-effect { background: rgba(255, 255, 255, 0.95); backdrop-filter: blur(10px); }
15
+ .status-pill { transition: all 0.2s ease; }
16
+ .status-pill:hover { transform: translateY(-1px); }
17
+ .drawer-transition { transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1); }
18
+ .fade-in { animation: fadeIn 0.3s ease-in; }
19
+ @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
20
+ .slide-in { animation: slideIn 0.3s ease-out; }
21
+ @keyframes slideIn { from { transform: translateX(-10px); opacity: 0; } to { transform: translateX(0); opacity: 1; } }
22
+ .calendar-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 1px; background-color: #e5e7eb; }
23
+ .calendar-day { background-color: white; min-height: 120px; }
24
+ .calendar-event { transition: all 0.2s; }
25
+ .calendar-event:hover { transform: scale(1.02); box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); }
26
+ </style>
27
+ </head>
28
+ <body class="bg-gray-50 text-gray-900">
29
+
30
+ <!-- Sticky Header -->
31
+ <header class="sticky top-0 z-40 glass-effect border-b border-gray-200 h-16">
32
+ <div class="flex items-center justify-between h-full px-4 lg:px-6">
33
+ <!-- Left: Logo -->
34
+ <div class="flex items-center gap-4">
35
+ <button onclick="toggleSidebar()" class="p-2 hover:bg-gray-100 rounded-lg lg:hidden">
36
+ <i data-lucide="menu" class="w-5 h-5"></i>
37
+ </button>
38
+ <div class="flex items-center gap-3">
39
+ <div class="w-8 h-8 bg-teal-600 rounded-lg flex items-center justify-center">
40
+ <i data-lucide="activity" class="w-5 h-5 text-white"></i>
41
+ </div>
42
+ <span class="font-semibold text-lg tracking-tight">ClinicalConnect</span>
43
+ </div>
44
+ </div>
45
+
46
+ <!-- Center: Global Search -->
47
+ <div class="flex-1 max-w-2xl mx-4 hidden md:block">
48
+ <div class="relative">
49
+ <i data-lucide="search" class="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400"></i>
50
+ <input type="text" placeholder="Search patients, appointments, providers..."
51
+ class="w-full pl-10 pr-4 py-2 bg-gray-100 border-0 rounded-full text-sm focus:ring-2 focus:ring-teal-500 focus:bg-white transition-all">
52
+ </div>
53
+ </div>
54
+
55
+ <!-- Right: Actions -->
56
+ <div class="flex items-center gap-2">
57
+ <button class="relative p-2 hover:bg-gray-100 rounded-full transition-colors">
58
+ <i data-lucide="bell" class="w-5 h-5 text-gray-600"></i>
59
+ <span class="absolute top-1 right-1 w-2 h-2 bg-red-500 rounded-full border-2 border-white"></span>
60
+ </button>
61
+ <button class="p-2 hover:bg-gray-100 rounded-full transition-colors hidden sm:block">
62
+ <i data-lucide="help-circle" class="w-5 h-5 text-gray-600"></i>
63
+ </button>
64
+ <div class="relative ml-2">
65
+ <button onclick="toggleProfileDropdown()" class="flex items-center gap-2 p-1.5 hover:bg-gray-100 rounded-full transition-colors">
66
+ <img src="http://static.photos/people/320x240/1" alt="Admin" class="w-8 h-8 rounded-full object-cover border border-gray-200">
67
+ <i data-lucide="chevron-down" class="w-4 h-4 text-gray-400 hidden lg:block"></i>
68
+ </button>
69
+ <div id="profileDropdown" class="hidden absolute right-0 mt-2 w-48 bg-white rounded-xl shadow-lg border border-gray-200 py-1 z-50">
70
+ <a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-50">Profile Settings</a>
71
+ <a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-50">Admin Console</a>
72
+ <div class="border-t border-gray-100 my-1"></div>
73
+ <a href="#" class="block px-4 py-2 text-sm text-red-600 hover:bg-red-50">Sign Out</a>
74
+ </div>
75
+ </div>
76
+ </div>
77
+ </div>
78
+ </header>
79
+
80
+ <div class="flex h-[calc(100vh-64px)]">
81
+ <!-- Sidebar -->
82
+ <aside id="sidebar" class="w-64 bg-white border-r border-gray-200 flex flex-col sidebar-transition lg:translate-x-0 -translate-x-full fixed lg:static h-full z-30">
83
+ <nav class="flex-1 overflow-y-auto py-4 px-3 space-y-1">
84
+ <a href="#" class="flex items-center gap-3 px-3 py-2.5 text-gray-600 hover:bg-gray-50 rounded-lg transition-colors">
85
+ <i data-lucide="layout-dashboard" class="w-5 h-5"></i>
86
+ <span class="font-medium">Dashboard</span>
87
+ </a>
88
+ <a href="#" class="flex items-center gap-3 px-3 py-2.5 text-teal-700 bg-teal-50 rounded-lg transition-colors">
89
+ <i data-lucide="users" class="w-5 h-5"></i>
90
+ <span class="font-medium">Patients</span>
91
+ </a>
92
+ <a href="#" class="flex items-center gap-3 px-3 py-2.5 text-gray-600 hover:bg-gray-50 rounded-lg transition-colors">
93
+ <i data-lucide="calendar" class="w-5 h-5"></i>
94
+ <span class="font-medium">Appointments</span>
95
+ </a>
96
+ <a href="#" class="flex items-center gap-3 px-3 py-2.5 text-gray-600 hover:bg-gray-50 rounded-lg transition-colors">
97
+ <i data-lucide="stethoscope" class="w-5 h-5"></i>
98
+ <span class="font-medium">Providers</span>
99
+ </a>
100
+ <a href="#" class="flex items-center gap-3 px-3 py-2.5 text-gray-600 hover:bg-gray-50 rounded-lg transition-colors">
101
+ <i data-lucide="message-square" class="w-5 h-5"></i>
102
+ <span class="font-medium">Messages</span>
103
+ <span class="ml-auto bg-teal-100 text-teal-700 text-xs font-semibold px-2 py-0.5 rounded-full">3</span>
104
+ </a>
105
+ <a href="#" class="flex items-center gap-3 px-3 py-2.5 text-gray-600 hover:bg-gray-50 rounded-lg transition-colors">
106
+ <i data-lucide="file-text" class="w-5 h-5"></i>
107
+ <span class="font-medium">Billing</span>
108
+ </a>
109
+ <a href="#" class="flex items-center gap-3 px-3 py-2.5 text-gray-600 hover:bg-gray-50 rounded-lg transition-colors">
110
+ <i data-lucide="bar-chart-2" class="w-5 h-5"></i>
111
+ <span class="font-medium">Reports</span>
112
+ </a>
113
+ <a href="#" class="flex items-center gap-3 px-3 py-2.5 text-gray-600 hover:bg-gray-50 rounded-lg transition-colors">
114
+ <i data-lucide="settings" class="w-5 h-5"></i>
115
+ <span class="font-medium">Settings</span>
116
+ </a>
117
+ </nav>
118
+
119
+ <div class="p-4 border-t border-gray-200">
120
+ <button onclick="toggleSidebar()" class="hidden lg:flex items-center gap-2 text-sm text-gray-500 hover:text-gray-700 w-full">
121
+ <i data-lucide="chevrons-left" class="w-4 h-4"></i>
122
+ <span>Collapse</span>
123
+ </button>
124
+ </div>
125
+ </aside>
126
+
127
+ <!-- Overlay for mobile sidebar -->
128
+ <div id="sidebarOverlay" onclick="toggleSidebar()" class="fixed inset-0 bg-black/50 z-20 hidden lg:hidden"></div>
129
+
130
+ <!-- Main Content -->
131
+ <main class="flex-1 overflow-y-auto bg-gray-50/50">
132
+ <!-- Patient Profile Header Card -->
133
+ <div class="bg-white border-b border-gray-200 sticky top-0 z-10">
134
+ <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
135
+ <div class="flex flex-col lg:flex-row lg:items-start lg:justify-between gap-6">
136
+ <!-- Patient Info -->
137
+ <div class="flex gap-4">
138
+ <div class="w-20 h-20 bg-gradient-to-br from-teal-100 to-teal-200 rounded-full flex items-center justify-center text-2xl font-bold text-teal-700 border-4 border-white shadow-sm">
139
+ SM
140
+ </div>
141
+ <div class="flex-1">
142
+ <div class="flex flex-wrap items-center gap-3 mb-1">
143
+ <h1 class="text-2xl font-bold text-gray-900">Sarah Mitchell</h1>
144
+ <span class="px-2.5 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-700 border border-green-200">Active</span>
145
+ <span class="text-sm text-gray-500">ID: P-2024-0042</span>
146
+ </div>
147
+ <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-x-6 gap-y-2 text-sm text-gray-600 mt-2">
148
+ <div class="flex items-center gap-2">
149
+ <i data-lucide="cake" class="w-4 h-4 text-gray-400"></i>
150
+ <span>Mar 15, 1985 (39 yrs)</span>
151
+ </div>
152
+ <div class="flex items-center gap-2">
153
+ <i data-lucide="phone" class="w-4 h-4 text-gray-400"></i>
154
+ <span>(555) 123-4567</span>
155
+ </div>
156
+ <div class="flex items-center gap-2">
157
+ <i data-lucide="mail" class="w-4 h-4 text-gray-400"></i>
158
+ <span>sarah.mitchell@email.com</span>
159
+ </div>
160
+ <div class="flex items-center gap-2">
161
+ <i data-lucide="user-md" class="w-4 h-4 text-gray-400"></i>
162
+ <span>Dr. Emily Chen</span>
163
+ </div>
164
+ </div>
165
+ <div class="flex items-center gap-2 mt-2 text-sm text-gray-500">
166
+ <i data-lucide="shield" class="w-4 h-4"></i>
167
+ <span>BlueCross PPO • ID: BC8849210</span>
168
+ </div>
169
+ </div>
170
+ </div>
171
+
172
+ <!-- Quick Actions -->
173
+ <div class="flex flex-wrap gap-2">
174
+ <button onclick="openNewAppointmentModal()" class="inline-flex items-center gap-2 px-4 py-2 bg-teal-600 text-white rounded-lg hover:bg-teal-700 transition-colors font-medium text-sm shadow-sm">
175
+ <i data-lucide="plus" class="w-4 h-4"></i>
176
+ New Appointment
177
+ </button>
178
+ <button class="inline-flex items-center gap-2 px-4 py-2 bg-white border border-gray-300 text-gray-700 rounded-lg hover:bg-gray-50 transition-colors font-medium text-sm">
179
+ <i data-lucide="message-circle" class="w-4 h-4"></i>
180
+ Message
181
+ </button>
182
+ <button class="inline-flex items-center gap-2 px-4 py-2 bg-white border border-gray-300 text-gray-700 rounded-lg hover:bg-gray-50 transition-colors font-medium text-sm">
183
+ <i data-lucide="file-plus" class="w-4 h-4"></i>
184
+ Add Note
185
+ </button>
186
+ <div class="relative">
187
+ <button onclick="toggleMoreDropdown()" class="inline-flex items-center gap-2 px-3 py-2 bg-white border border-gray-300 text-gray-700 rounded-lg hover:bg-gray-50 transition-colors">
188
+ <i data-lucide="more-horizontal" class="w-4 h-4"></i>
189
+ </button>
190
+ <div id="moreDropdown" class="hidden absolute right-0 mt-2 w-48 bg-white rounded-lg shadow-lg border border-gray-200 py-1 z-20">
191
+ <a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-50">Print Profile</a>
192
+ <a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-50">Export Data</a>
193
+ <a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-50">Merge Records</a>
194
+ </div>
195
+ </div>
196
+ </div>
197
+ </div>
198
+
199
+ <!-- Profile Sub-navigation -->
200
+ <div class="mt-6 border-b border-gray-200">
201
+ <nav class="flex gap-1">
202
+ <a href="#" class="px-4 py-3 text-sm font-medium text-gray-500 hover:text-gray-700 border-b-2 border-transparent hover:border-gray-300 transition-colors">Overview</a>
203
+ <a href="#" class="px-4 py-3 text-sm font-medium text-gray-500 hover:text-gray-700 border-b-2 border-transparent hover:border-gray-300 transition-colors">Medical</a>
204
+ <a href="#" class="px-4 py-3 text-sm font-medium text-gray-500 hover:text-gray-700 border-b-2 border-transparent hover:border-gray-300 transition-colors">Documents</a>
205
+ <a href="#" class="px-4 py-3 text-sm font-medium text-gray-500 hover:text-gray-700 border-b-2 border-transparent hover:border-gray-300 transition-colors">Billing</a>
206
+ <a href="#" class="px-4 py-3 text-sm font-medium text-teal-600 border-b-2 border-teal-600">Appointments</a>
207
+ <a href="#" class="px-4 py-3 text-sm font-medium text-gray-500 hover:text-gray-700 border-b-2 border-transparent hover:border-gray-300 transition-colors">Messages</a>
208
+ </nav>
209
+ </div>
210
+ </div>
211
+ </div>
212
+
213
+ <!-- Appointments Content -->
214
+ <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
215
+ <!-- Page Header + View Toggle -->
216
+ <div class="flex flex-col sm:flex-row sm:items-center justify-between gap-4 mb-6">
217
+ <div>
218
+ <h2 class="text-xl font-semibold text-gray-900">Appointments</h2>
219
+ <p class="text-sm text-gray-500 mt-1">Upcoming and past visits for this patient.</p>
220
+ </div>
221
+ <div class="flex items-center gap-3">
222
+ <button onclick="openNewAppointmentModal()" class="inline-flex items-center gap-2 px-4 py-2 bg-teal-600 text-white rounded-lg hover:bg-teal-700 transition-colors text-sm font-medium shadow-sm">
223
+ <i data-lucide="plus" class="w-4 h-4"></i>
224
+ New Appointment
225
+ </button>
226
+ <div class="flex bg-white rounded-lg border border-gray-300 p-1">
227
+ <button onclick="switchView('list')" id="listViewBtn" class="px-3 py-1.5 rounded-md text-sm font-medium bg-teal-50 text-teal-700 flex items-center gap-2 transition-all">
228
+ <i data-lucide="list" class="w-4 h-4"></i>
229
+ List
230
+ </button>
231
+ <button onclick="switchView('calendar')" id="calendarViewBtn" class="px-3 py-1.5 rounded-md text-sm font-medium text-gray-600 hover:text-gray-900 flex items-center gap-2 transition-all">
232
+ <i data-lucide="calendar-days" class="w-4 h-4"></i>
233
+ Calendar
234
+ </button>
235
+ </div>
236
+ </div>
237
+ </div>
238
+
239
+ <!-- Filters Bar -->
240
+ <div class="bg-white rounded-xl border border-gray-200 p-4 mb-6 shadow-sm">
241
+ <div class="flex flex-col xl:flex-row gap-4">
242
+ <div class="flex flex-wrap items-center gap-3 flex-1">
243
+ <!-- Date Range -->
244
+ <div class="relative">
245
+ <div class="flex items-center gap-2 bg-gray-50 border border-gray-200 rounded-lg px-3 py-2">
246
+ <i data-lucide="calendar" class="w-4 h-4 text-gray-400"></i>
247
+ <input type="text" value="Jan 1, 2024 - Dec 31, 2024" class="bg-transparent text-sm text-gray-700 focus:outline-none w-48" readonly>
248
+ <i data-lucide="chevron-down" class="w-3 h-3 text-gray-400"></i>
249
+ </div>
250
+ </div>
251
+
252
+ <!-- Status -->
253
+ <select class="bg-white border border-gray-200 rounded-lg px-3 py-2 text-sm text-gray-700 focus:ring-2 focus:ring-teal-500 focus:border-teal-500 outline-none">
254
+ <option>All Statuses</option>
255
+ <option>Confirmed</option>
256
+ <option>Pending</option>
257
+ <option>Completed</option>
258
+ <option>Canceled</option>
259
+ <option>No-show</option>
260
+ </select>
261
+
262
+ <!-- Provider -->
263
+ <select class="bg-white border border-gray-200 rounded-lg px-3 py-2 text-sm text-gray-700 focus:ring-2 focus:ring-teal-500 focus:border-teal-500 outline-none">
264
+ <option>All Providers</option>
265
+ <option>Dr. Emily Chen</option>
266
+ <option>Dr. James Wilson</option>
267
+ <option>Dr. Sarah Park</option>
268
+ </select>
269
+
270
+ <!-- Category -->
271
+ <select class="bg-white border border-gray-200 rounded-lg px-3 py-2 text-sm text-gray-700 focus:ring-2 focus:ring-teal-500 focus:border-teal-500 outline-none">
272
+ <option>All Categories</option>
273
+ <option>Primary Care</option>
274
+ <option>Dental</option>
275
+ <option>Dermatology</option>
276
+ <option>Therapy</option>
277
+ <option>Lab</option>
278
+ <option>Imaging</option>
279
+ <option>Telehealth</option>
280
+ <option>Follow-up</option>
281
+ </select>
282
+
283
+ <!-- Type Toggle -->
284
+ <div class="flex items-center bg-gray-100 rounded-lg p-1">
285
+ <button class="px-3 py-1 rounded-md text-xs font-medium bg-white text-gray-900 shadow-sm">All</button>
286
+ <button class="px-3 py-1 rounded-md text-xs font-medium text-gray-600 hover:text-gray-900">In-person</button>
287
+ <button class="px-3 py-1 rounded-md text-xs font-medium text-gray-600 hover:text-gray-900">Telehealth</button>
288
+ </div>
289
+ </div>
290
+
291
+ <div class="flex items-center gap-3 border-t xl:border-t-0 xl:border-l border-gray-200 pt-3 xl:pt-0 xl:pl-3">
292
+ <div class="relative flex-1 xl:w-64">
293
+ <i data-lucide="search" class="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400"></i>
294
+ <input type="text" placeholder="Search reason, provider, category..." class="w-full pl-9 pr-4 py-2 bg-gray-50 border border-gray-200 rounded-lg text-sm focus:ring-2 focus:ring-teal-500 focus:bg-white outline-none">
295
+ </div>
296
+ <button class="text-sm text-gray-500 hover:text-gray-700 font-medium whitespace-nowrap">Clear</button>
297
+ <select id="sortDropdown" class="bg-white border border-gray-200 rounded-lg px-3 py-2 text-sm text-gray-700 focus:ring-2 focus:ring-teal-500 outline-none">
298
+ <option>Soonest</option>
299
+ <option>Latest</option>
300
+ </select>
301
+ </div>
302
+ </div>
303
+ </div>
304
+
305
+ <!-- LIST VIEW -->
306
+ <div id="listView" class="space-y-6">
307
+ <!-- Upcoming Appointments -->
308
+ <div class="bg-white rounded-xl border border-gray-200 shadow-sm overflow-hidden">
309
+ <div class="px-6 py-4 border-b border-gray-200 bg-gray-50/50">
310
+ <h3 class="font-semibold text-gray-900 flex items-center gap-2">
311
+ <i data-lucide="clock" class="w-4 h-4 text-teal-600"></i>
312
+ Upcoming Appointments
313
+ <span class="ml-2 text-xs font-normal text-gray-500">(3)</span>
314
+ </h3>
315
+ </div>
316
+ <div class="overflow-x-auto">
317
+ <table class="w-full">
318
+ <thead class="bg-gray-50 text-left text-xs font-semibold text-gray-500 uppercase tracking-wider">
319
+ <tr>
320
+ <th class="px-6 py-3">Date & Time</th>
321
+ <th class="px-6 py-3">Provider</th>
322
+ <th class="px-6 py-3">Category</th>
323
+ <th class="px-6 py-3">Type</th>
324
+ <th class="px-6 py-3">Location</th>
325
+ <th class="px-6 py-3">Status</th>
326
+ <th class="px-6 py-3 text-center">Notes</th>
327
+ <th class="px-6 py-3 text-right">Actions</th>
328
+ </tr>
329
+ </thead>
330
+ <tbody class="divide-y divide-gray-200" id="upcomingList">
331
+ <!-- Populated by JS -->
332
+ </tbody>
333
+ </table>
334
+ </div>
335
+ </div>
336
+
337
+ <!-- Appointment History -->
338
+ <div class="bg-white rounded-xl border border-gray-200 shadow-sm overflow-hidden">
339
+ <div class="px-6 py-4 border-b border-gray-200 bg-gray-50/50">
340
+ <h3 class="font-semibold text-gray-900 flex items-center gap-2">
341
+ <i data-lucide="history" class="w-4 h-4 text-gray-600"></i>
342
+ Appointment History
343
+ <span class="ml-2 text-xs font-normal text-gray-500">(12)</span>
344
+ </h3>
345
+ </div>
346
+ <div class="overflow-x-auto">
347
+ <table class="w-full">
348
+ <thead class="bg-gray-50 text-left text-xs font-semibold text-gray-500 uppercase tracking-wider">
349
+ <tr>
350
+ <th class="px-6 py-3">Date & Time</th>
351
+ <th class="px-6 py-3">Provider</th>
352
+ <th class="px-6 py-3">Category</th>
353
+ <th class="px-6 py-3">Type</th>
354
+ <th class="px-6 py-3">Location</th>
355
+ <th class="px-6 py-3">Status</th>
356
+ <th class="px-6 py-3 text-center">Notes</th>
357
+ <th class="px-6 py-3 text-right">Actions</th>
358
+ </tr>
359
+ </thead>
360
+ <tbody class="divide-y divide-gray-200" id="historyList">
361
+ <!-- Populated by JS -->
362
+ </tbody>
363
+ </table>
364
+ </div>
365
+ <div class="px-6 py-3 border-t border-gray-200 bg-gray-50/50 flex items-center justify-between">
366
+ <span class="text-xs text-gray-500">Showing 1-5 of 12</span>
367
+ <div class="flex gap-2">
368
+ <button class="px-3 py-1 text-xs font-medium text-gray-500 hover:text-gray-700 disabled:opacity-50">Previous</button>
369
+ <button class="px-3 py-1 text-xs font-medium text-teal-600 hover:text-teal-700">Next</button>
370
+ </div>
371
+ </div>
372
+ </div>
373
+ </div>
374
+
375
+ <!-- CALENDAR VIEW -->
376
+ <div id="calendarView" class="hidden">
377
+ <div class="flex flex-col lg:flex-row gap-6">
378
+ <!-- Main Calendar -->
379
+ <div class="flex-1 bg-white rounded-xl border border-gray-200 shadow-sm overflow-hidden">
380
+ <!-- Calendar Header -->
381
+ <div class="flex items-center justify-between px-6 py-4 border-b border-gray-200">
382
+ <div class="flex items-center gap-4">
383
+ <h3 class="text-lg font-semibold text-gray-900">January 2024</h3>
384
+ <div class="flex gap-1">
385
+ <button class="p-1 hover:bg-gray-100 rounded-lg transition-colors">
386
+ <i data-lucide="chevron-left" class="w-5 h-5 text-gray-600"></i>
387
+ </button>
388
+ <button class="px-3 py-1 text-sm font-medium text-gray-700 hover:bg-gray-100 rounded-lg transition-colors">Today</button>
389
+ <button class="p-1 hover:bg-gray-100 rounded-lg transition-colors">
390
+ <i data-lucide="chevron-right" class="w-5 h-5 text-gray-600"></i>
391
+ </button>
392
+ </div>
393
+ </div>
394
+ <div class="flex gap-2">
395
+ <button onclick="setCalendarView('month')" id="monthViewBtn" class="px-3 py-1.5 text-sm font-medium rounded-lg bg-teal-50 text-teal-700">Month</button>
396
+ <button onclick="setCalendarView('week')" id="weekViewBtn" class="px-3 py-1.5 text-sm font-medium rounded-lg text-gray-600 hover:bg-gray-50">Week</button>
397
+ <button onclick="setCalendarView('day')" id="dayViewBtn" class="px-3 py-1.5 text-sm font-medium rounded-lg text-gray-600 hover:bg-gray-50">Day</button>
398
+ </div>
399
+ </div>
400
+
401
+ <!-- Calendar Days Header -->
402
+ <div class="grid grid-cols-7 border-b border-gray-200 bg-gray-50/50">
403
+ <div class="py-2 text-center text-xs font-semibold text-gray-500">Sun</div>
404
+ <div class="py-2 text-center text-xs font-semibold text-gray-500">Mon</div>
405
+ <div class="py-2 text-center text-xs font-semibold text-gray-500">Tue</div>
406
+ <div class="py-2 text-center text-xs font-semibold text-gray-500">Wed</div>
407
+ <div class="py-2 text-center text-xs font-semibold text-gray-500">Thu</div>
408
+ <div class="py-2 text-center text-xs font-semibold text-gray-500">Fri</div>
409
+ <div class="py-2 text-center text-xs font-semibold text-gray-500">Sat</div>
410
+ </div>
411
+
412
+ <!-- Calendar Grid -->
413
+ <div id="calendarGrid" class="calendar-grid">
414
+ <!-- Populated by JS -->
415
+ </div>
416
+ </div>
417
+
418
+ <!-- Side Panel: Upcoming This Week -->
419
+ <div class="w-full lg:w-80 bg-white rounded-xl border border-gray-200 shadow-sm p-6">
420
+ <h3 class="font-semibold text-gray-900 mb-4 flex items-center gap-2">
421
+ <i data-lucide="calendar-clock" class="w-4 h-4 text-teal-600"></i>
422
+ Upcoming This Week
423
+ </h3>
424
+ <div class="space-y-3" id="upcomingWeekList">
425
+ <!-- Populated by JS -->
426
+ </div>
427
+ </div>
428
+ </div>
429
+ </div>
430
+ </div>
431
+ </main>
432
+ </div>
433
+
434
+ <!-- Appointment Details Drawer -->
435
+ <div id="drawerOverlay" onclick="closeDrawer()" class="fixed inset-0 bg-black/20 z-40 hidden opacity-0 transition-opacity duration-300"></div>
436
+ <div id="appointmentDrawer" class="fixed inset-y-0 right-0 w-full sm:w-[480px] bg-white shadow-2xl z-50 transform translate-x-full drawer-transition overflow-y-auto">
437
+ <div class="sticky top-0 bg-white border-b border-gray-200 px-6 py-4 flex items-center justify-between z-10">
438
+ <div>
439
+ <h2 class="text-lg font-bold text-gray-900">Appointment Details</h2>
440
+ <p class="text-xs text-gray-500 mt-0.5" id="drawerApptId">APT-2024-0089</p>
441
+ </div>
442
+ <button onclick="closeDrawer()" class="p-2 hover:bg-gray-100 rounded-lg transition-colors">
443
+ <i data-lucide="x" class="w-5 h-5 text-gray-500"></i>
444
+ </button>
445
+ </div>
446
+
447
+ <div class="p-6 space-y-6" id="drawerContent">
448
+ <!-- Populated by JS -->
449
+ </div>
450
+
451
+ <div class="sticky bottom-0 bg-white border-t border-gray-200 p-4 flex gap-3">
452
+ <button class="flex-1 px-4 py-2 bg-white border border-gray-300 text-gray-700 rounded-lg hover:bg-gray-50 font-medium text-sm flex items-center justify-center gap-2">
453
+ <i data-lucide="edit" class="w-4 h-4"></i>
454
+ Edit
455
+ </button>
456
+ <button class="flex-1 px-4 py-2 bg-teal-600 text-white rounded-lg hover:bg-teal-700 font-medium text-sm flex items-center justify-center gap-2">
457
+ <i data-lucide="calendar-clock" class="w-4 h-4"></i>
458
+ Reschedule
459
+ </button>
460
+ </div>
461
+ </div>
462
+
463
+ <!-- New Appointment Modal -->
464
+ <div id="newAppointmentModal" class="fixed inset-0 z-50 hidden">
465
+ <div class="absolute inset-0 bg-black/50 backdrop-blur-sm" onclick="closeNewAppointmentModal()"></div>
466
+ <div class="absolute inset-0 flex items-center justify-center p-4 pointer-events-none">
467
+ <div class="bg-white rounded-2xl shadow-xl w-full max-w-lg pointer-events-auto transform scale-100 opacity-100 transition-all">
468
+ <div class="flex items-center justify-between px-6 py-4 border-b border-gray-200">
469
+ <h3 class="text-lg font-semibold text-gray-900">New Appointment</h3>
470
+ <button onclick="closeNewAppointmentModal()" class="p-2 hover:bg-gray-100 rounded-lg transition-colors">
471
+ <i data-lucide="x" class="w-5 h-5 text-gray-500"></i>
472
+ </button>
473
+ </div>
474
+ <div class="p-6 space-y-4">
475
+ <div class="grid grid-cols-2 gap-4">
476
+ <div class="col-span-2">
477
+ <label class="block text-sm font-medium text-gray-700 mb-1">Date & Time</label>
478
+ <input type="datetime-local" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-teal-500 focus:border-teal-500 outline-none">
479
+ </div>
480
+ <div>
481
+ <label class="block text-sm font-medium text-gray-700 mb-1">Provider</label>
482
+ <select class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-teal-500 outline-none">
483
+ <option>Dr. Emily Chen</option>
484
+ <option>Dr. James Wilson</option>
485
+ </select>
486
+ </div>
487
+ <div>
488
+ <label class="block text-sm font-medium text-gray-700 mb-1">Category</label>
489
+ <select class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-teal-500 outline-none">
490
+ <option>Primary Care</option>
491
+ <option>Follow-up</option>
492
+ <option>Dental</option>
493
+ </select>
494
+ </div>
495
+ <div class="col-span-2">
496
+ <label class="block text-sm font-medium text-gray-700 mb-1">Reason for Visit</label>
497
+ <input type="text" placeholder="e.g., Annual physical, Follow-up labs" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-teal-500 outline-none">
498
+ </div>
499
+ <div>
500
+ <label class="block text-sm font-medium text-gray-700 mb-1">Type</label>
501
+ <div class="flex gap-4 mt-2">
502
+ <label class="flex items-center gap-2">
503
+ <input type="radio" name="type" checked class="text-teal-600 focus:ring-teal-500">
504
+ <span class="text-sm text-gray-700">In-person</span>
505
+ </label>
506
+ <label class="flex items-center gap-2">
507
+ <input type="radio" name="type" class="text-teal-600 focus:ring-teal-500">
508
+ <span class="text-sm text-gray-700">Telehealth</span>
509
+ </label>
510
+ </div>
511
+ </div>
512
+ <div>
513
+ <label class="block text-sm font-medium text-gray-700 mb-1">Duration</label>
514
+ <select class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-teal-500 outline-none">
515
+ <option>30 minutes</option>
516
+ <option>60 minutes</option>
517
+ <option>90 minutes</option>
518
+ </select>
519
+ </div>
520
+ </div>
521
+ </div>
522
+ <div class="flex items-center justify-end gap-3 px-6 py-4 border-t border-gray-200 bg-gray-50 rounded-b-2xl">
523
+ <button onclick="closeNewAppointmentModal()" class="px-4 py-2 text-sm font-medium text-gray-700 hover:text-gray-900">Cancel</button>
524
+ <button onclick="saveAppointment()" class="px-4 py-2 bg-teal-600 text-white rounded-lg hover:bg-teal-700 text-sm font-medium shadow-sm">Schedule Appointment</button>
525
+ </div>
526
+ </div>
527
+ </div>
528
+ </div>
529
+
530
+ <script src="script.js"></script>
531
+ <script>
532
+ // Initialize Lucide icons
533
+ lucide.createIcons();
534
+ </script>
535
+ <script src="https://deepsite.hf.co/deepsite-badge.js"></script>
536
+ </body>
537
+ </html>
script.js ADDED
@@ -0,0 +1,554 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Sample data
2
+ const appointments = [
3
+ {
4
+ id: 'APT-2024-0092',
5
+ date: '2024-01-15',
6
+ time: '09:00 AM',
7
+ duration: '30 min',
8
+ provider: { name: 'Dr. Emily Chen', specialty: 'Internal Medicine', avatar: 'http://static.photos/people/320x240/2' },
9
+ category: 'Primary Care',
10
+ type: 'In-person',
11
+ location: 'Main Clinic, Room 304',
12
+ status: 'Confirmed',
13
+ notes: 2,
14
+ reason: 'Annual physical examination',
15
+ isUpcoming: true,
16
+ history: [
17
+ { status: 'Created', time: 'Jan 8, 2024 2:30 PM', user: 'System' },
18
+ { status: 'Confirmed', time: 'Jan 8, 2024 2:35 PM', user: 'Dr. Chen' }
19
+ ]
20
+ },
21
+ {
22
+ id: 'APT-2024-0095',
23
+ date: '2024-01-18',
24
+ time: '02:30 PM',
25
+ duration: '45 min',
26
+ provider: { name: 'Dr. James Wilson', specialty: 'Dermatology', avatar: 'http://static.photos/people/320x240/3' },
27
+ category: 'Dermatology',
28
+ type: 'Telehealth',
29
+ location: 'Video Consultation',
30
+ status: 'Pending',
31
+ notes: 0,
32
+ reason: 'Rash follow-up consultation',
33
+ isUpcoming: true,
34
+ history: [
35
+ { status: 'Created', time: 'Jan 10, 2024 10:00 AM', user: 'Sarah Mitchell' }
36
+ ]
37
+ },
38
+ {
39
+ id: 'APT-2024-0100',
40
+ date: '2024-02-05',
41
+ time: '11:00 AM',
42
+ duration: '60 min',
43
+ provider: { name: 'Dr. Sarah Park', specialty: 'Lab Services', avatar: 'http://static.photos/people/320x240/4' },
44
+ category: 'Lab',
45
+ type: 'In-person',
46
+ location: 'Lab Center, 2nd Floor',
47
+ status: 'Confirmed',
48
+ notes: 1,
49
+ reason: 'Blood work and cholesterol panel',
50
+ isUpcoming: true,
51
+ history: [
52
+ { status: 'Created', time: 'Jan 20, 2024 9:00 AM', user: 'System' },
53
+ { status: 'Confirmed', time: 'Jan 20, 2024 9:15 AM', user: 'Staff' }
54
+ ]
55
+ },
56
+ {
57
+ id: 'APT-2024-0085',
58
+ date: '2023-12-15',
59
+ time: '10:00 AM',
60
+ duration: '30 min',
61
+ provider: { name: 'Dr. Emily Chen', specialty: 'Internal Medicine', avatar: 'http://static.photos/people/320x240/2' },
62
+ category: 'Follow-up',
63
+ type: 'In-person',
64
+ location: 'Main Clinic, Room 304',
65
+ status: 'Completed',
66
+ notes: 3,
67
+ reason: 'Medication review',
68
+ isUpcoming: false,
69
+ history: [
70
+ { status: 'Created', time: 'Dec 1, 2023 2:00 PM', user: 'System' },
71
+ { status: 'Confirmed', time: 'Dec 1, 2023 2:05 PM', user: 'Dr. Chen' },
72
+ { status: 'Checked-in', time: 'Dec 15, 2023 9:45 AM', user: 'Reception' },
73
+ { status: 'Completed', time: 'Dec 15, 2023 10:30 AM', user: 'Dr. Chen' }
74
+ ]
75
+ },
76
+ {
77
+ id: 'APT-2024-0078',
78
+ date: '2023-11-20',
79
+ time: '03:00 PM',
80
+ duration: '30 min',
81
+ provider: { name: 'Dr. James Wilson', specialty: 'Dermatology', avatar: 'http://static.photos/people/320x240/3' },
82
+ category: 'Dermatology',
83
+ type: 'In-person',
84
+ location: 'Dermatology Suite, Room 105',
85
+ status: 'Completed',
86
+ notes: 2,
87
+ reason: 'Skin examination',
88
+ isUpcoming: false,
89
+ history: [
90
+ { status: 'Created', time: 'Nov 10, 2023 11:00 AM', user: 'System' },
91
+ { status: 'Confirmed', time: 'Nov 10, 2023 11:05 AM', user: 'Auto-confirm' },
92
+ { status: 'Completed', time: 'Nov 20, 2023 3:30 PM', user: 'Dr. Wilson' }
93
+ ]
94
+ },
95
+ {
96
+ id: 'APT-2024-0072',
97
+ date: '2023-10-28',
98
+ time: '09:30 AM',
99
+ duration: '30 min',
100
+ provider: { name: 'Dr. Emily Chen', specialty: 'Internal Medicine', avatar: 'http://static.photos/people/320x240/2' },
101
+ category: 'Primary Care',
102
+ type: 'Telehealth',
103
+ location: 'Phone Consultation',
104
+ status: 'Canceled',
105
+ notes: 0,
106
+ reason: 'Prescription refill',
107
+ isUpcoming: false,
108
+ history: [
109
+ { status: 'Created', time: 'Oct 20, 2023 9:00 AM', user: 'Patient Portal' },
110
+ { status: 'Confirmed', time: 'Oct 20, 2023 9:05 AM', user: 'System' },
111
+ { status: 'Canceled', time: 'Oct 27, 2023 4:00 PM', user: 'Sarah Mitchell' }
112
+ ]
113
+ }
114
+ ];
115
+
116
+ // State
117
+ let currentView = 'list';
118
+ let currentCalendarView = 'month';
119
+ let selectedAppointment = null;
120
+
121
+ // Initialize
122
+ document.addEventListener('DOMContentLoaded', () => {
123
+ renderListView();
124
+ renderCalendar();
125
+ renderUpcomingWeek();
126
+ });
127
+
128
+ // Sidebar Toggle
129
+ function toggleSidebar() {
130
+ const sidebar = document.getElementById('sidebar');
131
+ const overlay = document.getElementById('sidebarOverlay');
132
+ sidebar.classList.toggle('-translate-x-full');
133
+ overlay.classList.toggle('hidden');
134
+ }
135
+
136
+ // Profile Dropdown
137
+ function toggleProfileDropdown() {
138
+ const dropdown = document.getElementById('profileDropdown');
139
+ dropdown.classList.toggle('hidden');
140
+ }
141
+
142
+ // More Dropdown
143
+ function toggleMoreDropdown() {
144
+ const dropdown = document.getElementById('moreDropdown');
145
+ dropdown.classList.toggle('hidden');
146
+ }
147
+
148
+ // Close dropdowns when clicking outside
149
+ document.addEventListener('click', (e) => {
150
+ if (!e.target.closest('.relative')) {
151
+ document.getElementById('profileDropdown')?.classList.add('hidden');
152
+ document.getElementById('moreDropdown')?.classList.add('hidden');
153
+ }
154
+ });
155
+
156
+ // View Switching
157
+ function switchView(view) {
158
+ currentView = view;
159
+ const listView = document.getElementById('listView');
160
+ const calendarView = document.getElementById('calendarView');
161
+ const listBtn = document.getElementById('listViewBtn');
162
+ const calendarBtn = document.getElementById('calendarViewBtn');
163
+ const sortDropdown = document.getElementById('sortDropdown');
164
+
165
+ if (view === 'list') {
166
+ listView.classList.remove('hidden');
167
+ calendarView.classList.add('hidden');
168
+ listBtn.classList.add('bg-teal-50', 'text-teal-700');
169
+ listBtn.classList.remove('text-gray-600', 'hover:text-gray-900');
170
+ calendarBtn.classList.remove('bg-teal-50', 'text-teal-700');
171
+ calendarBtn.classList.add('text-gray-600', 'hover:text-gray-900');
172
+ sortDropdown.parentElement.style.opacity = '1';
173
+ sortDropdown.parentElement.style.pointerEvents = 'auto';
174
+ } else {
175
+ listView.classList.add('hidden');
176
+ calendarView.classList.remove('hidden');
177
+ calendarBtn.classList.add('bg-teal-50', 'text-teal-700');
178
+ calendarBtn.classList.remove('text-gray-600', 'hover:text-gray-900');
179
+ listBtn.classList.remove('bg-teal-50', 'text-teal-700');
180
+ listBtn.classList.add('text-gray-600', 'hover:text-gray-900');
181
+ sortDropdown.parentElement.style.opacity = '0.5';
182
+ sortDropdown.parentElement.style.pointerEvents = 'none';
183
+ }
184
+
185
+ lucide.createIcons();
186
+ }
187
+
188
+ // Render List View
189
+ function renderListView() {
190
+ const upcomingList = document.getElementById('upcomingList');
191
+ const historyList = document.getElementById('historyList');
192
+
193
+ const upcoming = appointments.filter(a => a.isUpcoming);
194
+ const history = appointments.filter(a => !a.isUpcoming);
195
+
196
+ upcomingList.innerHTML = upcoming.map(appt => createAppointmentRow(appt)).join('');
197
+ historyList.innerHTML = history.map(appt => createAppointmentRow(appt)).join('');
198
+
199
+ lucide.createIcons();
200
+ }
201
+
202
+ function createAppointmentRow(appt) {
203
+ const statusColors = {
204
+ 'Confirmed': 'bg-green-100 text-green-700 border-green-200',
205
+ 'Pending': 'bg-yellow-100 text-yellow-700 border-yellow-200',
206
+ 'Completed': 'bg-gray-100 text-gray-700 border-gray-200',
207
+ 'Canceled': 'bg-red-100 text-red-700 border-red-200',
208
+ 'No-show': 'bg-orange-100 text-orange-700 border-orange-200'
209
+ };
210
+
211
+ const categoryColors = {
212
+ 'Primary Care': 'bg-blue-50 text-blue-700 border-blue-200',
213
+ 'Dermatology': 'bg-purple-50 text-purple-700 border-purple-200',
214
+ 'Lab': 'bg-pink-50 text-pink-700 border-pink-200',
215
+ 'Follow-up': 'bg-indigo-50 text-indigo-700 border-indigo-200'
216
+ };
217
+
218
+ return `
219
+ <tr class="hover:bg-gray-50 transition-colors cursor-pointer" onclick="openDrawer('${appt.id}')">
220
+ <td class="px-6 py-4 whitespace-nowrap">
221
+ <div class="text-sm font-medium text-gray-900">${formatDate(appt.date)}</div>
222
+ <div class="text-xs text-gray-500">${appt.time} • ${appt.duration}</div>
223
+ </td>
224
+ <td class="px-6 py-4">
225
+ <div class="flex items-center gap-3">
226
+ <img src="${appt.provider.avatar}" class="w-8 h-8 rounded-full object-cover">
227
+ <div>
228
+ <div class="text-sm font-medium text-gray-900">${appt.provider.name}</div>
229
+ <div class="text-xs text-gray-500">${appt.provider.specialty}</div>
230
+ </div>
231
+ </div>
232
+ </td>
233
+ <td class="px-6 py-4">
234
+ <span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium border ${categoryColors[appt.category] || 'bg-gray-100 text-gray-700 border-gray-200'}">
235
+ ${appt.category}
236
+ </span>
237
+ </td>
238
+ <td class="px-6 py-4">
239
+ <div class="flex items-center gap-1.5 text-sm text-gray-600">
240
+ <i data-lucide="${appt.type === 'Telehealth' ? 'video' : 'map-pin'}" class="w-3.5 h-3.5"></i>
241
+ ${appt.type}
242
+ </div>
243
+ </td>
244
+ <td class="px-6 py-4 text-sm text-gray-600 max-w-xs truncate">
245
+ ${appt.location}
246
+ </td>
247
+ <td class="px-6 py-4">
248
+ <span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium border ${statusColors[appt.status]} status-pill">
249
+ ${appt.status}
250
+ </span>
251
+ </td>
252
+ <td class="px-6 py-4 text-center">
253
+ ${appt.notes > 0 ? `<div class="inline-flex items-center gap-1 text-teal-600"><i data-lucide="file-text" class="w-4 h-4"></i><span class="text-xs font-medium">${appt.notes}</span></div>` : '<span class="text-gray-300">-</span>'}
254
+ </td>
255
+ <td class="px-6 py-4 text-right">
256
+ <div class="flex items-center justify-end gap-2">
257
+ <button onclick="event.stopPropagation(); openNewAppointmentModal()" class="p-1.5 hover:bg-gray-200 rounded-lg transition-colors text-gray-400 hover:text-gray-600">
258
+ <i data-lucide="pencil" class="w-4 h-4"></i>
259
+ </button>
260
+ <button onclick="event.stopPropagation()" class="p-1.5 hover:bg-gray-200 rounded-lg transition-colors text-gray-400 hover:text-gray-600">
261
+ <i data-lucide="more-vertical" class="w-4 h-4"></i>
262
+ </button>
263
+ </div>
264
+ </td>
265
+ </tr>
266
+ `;
267
+ }
268
+
269
+ // Calendar Functions
270
+ function setCalendarView(view) {
271
+ currentCalendarView = view;
272
+ document.getElementById('monthViewBtn').className = view === 'month' ? 'px-3 py-1.5 text-sm font-medium rounded-lg bg-teal-50 text-teal-700' : 'px-3 py-1.5 text-sm font-medium rounded-lg text-gray-600 hover:bg-gray-50';
273
+ document.getElementById('weekViewBtn').className = view === 'week' ? 'px-3 py-1.5 text-sm font-medium rounded-lg bg-teal-50 text-teal-700' : 'px-3 py-1.5 text-sm font-medium rounded-lg text-gray-600 hover:bg-gray-50';
274
+ document.getElementById('dayViewBtn').className = view === 'day' ? 'px-3 py-1.5 text-sm font-medium rounded-lg bg-teal-50 text-teal-700' : 'px-3 py-1.5 text-sm font-medium rounded-lg text-gray-600 hover:bg-gray-50';
275
+ }
276
+
277
+ function renderCalendar() {
278
+ const grid = document.getElementById('calendarGrid');
279
+ const daysInMonth = 31; // simplified
280
+ const startDay = 1; // Monday
281
+
282
+ let html = '';
283
+
284
+ // Empty cells for start of month
285
+ for (let i = 0; i < startDay; i++) {
286
+ html += `<div class="calendar-day bg-gray-50"></div>`;
287
+ }
288
+
289
+ // Days
290
+ for (let day = 1; day <= daysInMonth; day++) {
291
+ const dayAppointments = appointments.filter(a => new Date(a.date).getDate() === day);
292
+ const isToday = day === 15; // Example
293
+
294
+ html += `
295
+ <div class="calendar-day p-2 ${isToday ? 'bg-teal-50/30' : ''}">
296
+ <div class="flex items-center justify-between mb-1">
297
+ <span class="text-sm font-medium ${isToday ? 'text-teal-700 bg-teal-100 w-6 h-6 rounded-full flex items-center justify-center' : 'text-gray-700'}">${day}</span>
298
+ ${dayAppointments.length > 3 ? `<span class="text-xs text-gray-500 cursor-pointer hover:text-teal-600">+${dayAppointments.length - 2} more</span>` : ''}
299
+ </div>
300
+ <div class="space-y-1">
301
+ ${dayAppointments.slice(0, 3).map(appt => {
302
+ const statusColors = {
303
+ 'Confirmed': 'border-l-teal-500',
304
+ 'Pending': 'border-l-yellow-500',
305
+ 'Completed': 'border-l-gray-400',
306
+ 'Canceled': 'border-l-red-400'
307
+ };
308
+ return `
309
+ <div onclick="openDrawer('${appt.id}')" class="calendar-event text-xs p-1.5 bg-white border-l-2 ${statusColors[appt.status]} rounded shadow-sm cursor-pointer hover:bg-gray-50">
310
+ <div class="font-medium text-gray-900 truncate">${appt.time}</div>
311
+ <div class="text-gray-500 truncate">${appt.provider.name.split(' ')[1]}</div>
312
+ <div class="flex items-center gap-1 mt-0.5">
313
+ <span class="w-1.5 h-1.5 rounded-full bg-teal-500"></span>
314
+ <span class="text-[10px] text-gray-400">${appt.category}</span>
315
+ </div>
316
+ </div>
317
+ `;
318
+ }).join('')}
319
+ </div>
320
+ </div>
321
+ `;
322
+ }
323
+
324
+ grid.innerHTML = html;
325
+ }
326
+
327
+ function renderUpcomingWeek() {
328
+ const upcoming = appointments.filter(a => a.isUpcoming).slice(0, 5);
329
+ const container = document.getElementById('upcomingWeekList');
330
+
331
+ container.innerHTML = upcoming.map(appt => `
332
+ <div onclick="openDrawer('${appt.id}')" class="p-3 rounded-lg border border-gray-200 hover:border-teal-300 hover:shadow-sm cursor-pointer transition-all bg-white slide-in">
333
+ <div class="flex items-start justify-between mb-2">
334
+ <span class="text-xs font-semibold text-teal-700 bg-teal-50 px-2 py-0.5 rounded">${formatDayOfWeek(appt.date)}</span>
335
+ <span class="text-xs text-gray-500">${appt.time}</span>
336
+ </div>
337
+ <div class="text-sm font-medium text-gray-900 mb-0.5">${appt.category}</div>
338
+ <div class="text-xs text-gray-500 flex items-center gap-1">
339
+ <img src="${appt.provider.avatar}" class="w-4 h-4 rounded-full">
340
+ ${appt.provider.name}
341
+ </div>
342
+ </div>
343
+ `).join('');
344
+
345
+ lucide.createIcons();
346
+ }
347
+
348
+ // Drawer Functions
349
+ function openDrawer(appointmentId) {
350
+ const appt = appointments.find(a => a.id === appointmentId);
351
+ if (!appt) return;
352
+
353
+ selectedAppointment = appt;
354
+
355
+ const overlay = document.getElementById('drawerOverlay');
356
+ const drawer = document.getElementById('appointmentDrawer');
357
+ const content = document.getElementById('drawerContent');
358
+
359
+ document.getElementById('drawerApptId').textContent = appt.id;
360
+
361
+ const statusColors = {
362
+ 'Confirmed': 'text-green-700 bg-green-50 border-green-200',
363
+ 'Pending': 'text-yellow-700 bg-yellow-50 border-yellow-200',
364
+ 'Completed': 'text-gray-700 bg-gray-100 border-gray-200',
365
+ 'Canceled': 'text-red-700 bg-red-50 border-red-200'
366
+ };
367
+
368
+ content.innerHTML = `
369
+ <div class="space-y-6">
370
+ <!-- Header Info -->
371
+ <div class="text-center pb-6 border-b border-gray-100">
372
+ <div class="text-3xl font-bold text-gray-900 mb-1">${formatDateFull(appt.date)}</div>
373
+ <div class="text-lg text-gray-500 mb-3">${appt.time} • ${appt.duration}</div>
374
+ <span class="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium border ${statusColors[appt.status]}">
375
+ ${appt.status}
376
+ </span>
377
+ </div>
378
+
379
+ <!-- Status Timeline -->
380
+ <div>
381
+ <h4 class="text-xs font-semibold text-gray-500 uppercase tracking-wider mb-3">Status Timeline</h4>
382
+ <div class="space-y-3">
383
+ ${appt.history.map((h, i) => `
384
+ <div class="flex gap-3">
385
+ <div class="flex flex-col items-center">
386
+ <div class="w-2.5 h-2.5 rounded-full ${i === appt.history.length - 1 ? 'bg-teal-500' : 'bg-gray-300'}"></div>
387
+ ${i < appt.history.length - 1 ? '<div class="w-0.5 flex-1 bg-gray-200 my-1"></div>' : ''}
388
+ </div>
389
+ <div class="pb-3">
390
+ <div class="text-sm font-medium text-gray-900">${h.status}</div>
391
+ <div class="text-xs text-gray-500">${h.time} • ${h.user}</div>
392
+ </div>
393
+ </div>
394
+ `).join('')}
395
+ </div>
396
+ </div>
397
+
398
+ <!-- Provider -->
399
+ <div class="flex items-start gap-3 p-4 bg-gray-50 rounded-lg">
400
+ <img src="${appt.provider.avatar}" class="w-12 h-12 rounded-full object-cover border-2 border-white shadow-sm">
401
+ <div class="flex-1">
402
+ <div class="font-semibold text-gray-900">${appt.provider.name}</div>
403
+ <div class="text-sm text-gray-500 mb-2">${appt.provider.specialty}</div>
404
+ <button class="text-xs text-teal-600 hover:text-teal-700 font-medium flex items-center gap-1">
405
+ <i data-lucide="message-circle" class="w-3 h-3"></i>
406
+ Message Provider
407
+ </button>
408
+ </div>
409
+ </div>
410
+
411
+ <!-- Category & Type -->
412
+ <div class="grid grid-cols-2 gap-4">
413
+ <div>
414
+ <div class="text-xs text-gray-500 mb-1">Category</div>
415
+ <div class="inline-flex items-center px-2.5 py-1 rounded-md text-sm font-medium bg-blue-50 text-blue-700 border border-blue-200">
416
+ ${appt.category}
417
+ </div>
418
+ </div>
419
+ <div>
420
+ <div class="text-xs text-gray-500 mb-1">Type</div>
421
+ <div class="flex items-center gap-1.5 text-sm font-medium text-gray-900">
422
+ <i data-lucide="${appt.type === 'Telehealth' ? 'video' : 'map-pin'}" class="w-4 h-4 text-gray-400"></i>
423
+ ${appt.type}
424
+ </div>
425
+ ${appt.type === 'Telehealth' ? '<button class="mt-2 w-full px-3 py-1.5 bg-teal-600 text-white text-xs font-medium rounded hover:bg-teal-700 transition-colors">Join Video Link</button>' : ''}
426
+ </div>
427
+ </div>
428
+
429
+ <!-- Location -->
430
+ <div>
431
+ <div class="text-xs text-gray-500 mb-1 uppercase tracking-wider">Location</div>
432
+ <div class="flex items-start gap-2 text-sm text-gray-900">
433
+ <i data-lucide="map-pin" class="w-4 h-4 text-gray-400 mt-0.5"></i>
434
+ <span>${appt.location}</span>
435
+ </div>
436
+ </div>
437
+
438
+ <!-- Reason -->
439
+ <div>
440
+ <div class="text-xs text-gray-500 mb-1 uppercase tracking-wider">Reason for Visit</div>
441
+ <p class="text-sm text-gray-700 bg-gray-50 p-3 rounded-lg">${appt.reason}</p>
442
+ </div>
443
+
444
+ <!-- Notes Timeline -->
445
+ <div>
446
+ <div class="flex items-center justify-between mb-3">
447
+ <div class="text-xs font-semibold text-gray-500 uppercase tracking-wider">Notes</div>
448
+ <button class="text-xs text-teal-600 hover:text-teal-700 font-medium">+ Add Note</button>
449
+ </div>
450
+ ${appt.notes > 0 ? `
451
+ <div class="space-y-3">
452
+ <div class="border-l-2 border-teal-200 pl-3 py-1">
453
+ <div class="text-xs text-gray-500 mb-1">Jan 8, 2024 2:35 PM • Dr. Chen</div>
454
+ <p class="text-sm text-gray-700">Patient confirmed appointment via portal. No special requirements noted.</p>
455
+ </div>
456
+ ${appt.notes > 1 ? `
457
+ <div class="border-l-2 border-gray-200 pl-3 py-1">
458
+ <div class="text-xs text-gray-500 mb-1">Jan 5, 2024 9:00 AM • Sarah M.</div>
459
+ <p class="text-sm text-gray-700">Requested morning slot due to work schedule.</p>
460
+ </div>
461
+ ` : ''}
462
+ </div>
463
+ ` : '<div class="text-sm text-gray-400 italic">No notes added yet</div>'}
464
+ </div>
465
+
466
+ <!-- Actions -->
467
+ <div class="pt-4 border-t border-gray-100 flex gap-2">
468
+ <button onclick="event.stopPropagation(); cancelAppointment('${appt.id}')" class="flex-1 px-4 py-2 border border-red-200 text-red-600 rounded-lg hover:bg-red-50 text-sm font-medium transition-colors">
469
+ Cancel Appointment
470
+ </button>
471
+ <button onclick="event.stopPropagation(); sendReminder('${appt.id}')" class="flex-1 px-4 py-2 border border-gray-200 text-gray-700 rounded-lg hover:bg-gray-50 text-sm font-medium transition-colors flex items-center justify-center gap-2">
472
+ <i data-lucide="bell" class="w-4 h-4"></i>
473
+ Send Reminder
474
+ </button>
475
+ </div>
476
+ </div>
477
+ `;
478
+
479
+ overlay.classList.remove('hidden');
480
+ setTimeout(() => overlay.classList.remove('opacity-0'), 10);
481
+ drawer.classList.remove('translate-x-full');
482
+
483
+ lucide.createIcons();
484
+ }
485
+
486
+ function closeDrawer() {
487
+ const overlay = document.getElementById('drawerOverlay');
488
+ const drawer = document.getElementById('appointmentDrawer');
489
+
490
+ overlay.classList.add('opacity-0');
491
+ drawer.classList.add('translate-x-full');
492
+
493
+ setTimeout(() => {
494
+ overlay.classList.add('hidden');
495
+ }, 300);
496
+
497
+ selectedAppointment = null;
498
+ }
499
+
500
+ // Modal Functions
501
+ function openNewAppointmentModal() {
502
+ const modal = document.getElementById('newAppointmentModal');
503
+ modal.classList.remove('hidden');
504
+ setTimeout(() => {
505
+ modal.querySelector('div[class*="scale-100"]').classList.remove('scale-95', 'opacity-0');
506
+ }, 10);
507
+ }
508
+
509
+ function closeNewAppointmentModal() {
510
+ const modal = document.getElementById('newAppointmentModal');
511
+ modal.classList.add('hidden');
512
+ }
513
+
514
+ function saveAppointment() {
515
+ // Simulate saving
516
+ closeNewAppointmentModal();
517
+ // Show success notification (simplified)
518
+ alert('Appointment scheduled successfully!');
519
+ }
520
+
521
+ // Helper Functions
522
+ function formatDate(dateStr) {
523
+ const date = new Date(dateStr);
524
+ return date.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' });
525
+ }
526
+
527
+ function formatDateFull(dateStr) {
528
+ const date = new Date(dateStr);
529
+ return date.toLocaleDateString('en-US', { weekday: 'long', month: 'long', day: 'numeric' });
530
+ }
531
+
532
+ function formatDayOfWeek(dateStr) {
533
+ const date = new Date(dateStr);
534
+ return date.toLocaleDateString('en-US', { weekday: 'short', month: 'short', day: 'numeric' });
535
+ }
536
+
537
+ function cancelAppointment(id) {
538
+ if (confirm('Are you sure you want to cancel this appointment?')) {
539
+ alert('Appointment canceled');
540
+ closeDrawer();
541
+ }
542
+ }
543
+
544
+ function sendReminder(id) {
545
+ alert('Reminder sent to patient');
546
+ }
547
+
548
+ // Keyboard shortcuts
549
+ document.addEventListener('keydown', (e) => {
550
+ if (e.key === 'Escape') {
551
+ closeDrawer();
552
+ closeNewAppointmentModal();
553
+ }
554
+ });
style.css CHANGED
@@ -1,28 +1,140 @@
1
- body {
2
- padding: 2rem;
3
- font-family: -apple-system, BlinkMacSystemFont, "Arial", sans-serif;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  }
5
 
6
- h1 {
7
- font-size: 16px;
8
- margin-top: 0;
9
  }
10
 
11
- p {
12
- color: rgb(107, 114, 128);
13
- font-size: 15px;
14
- margin-bottom: 10px;
15
- margin-top: 5px;
16
  }
17
 
18
- .card {
19
- max-width: 620px;
20
- margin: 0 auto;
21
- padding: 16px;
22
- border: 1px solid lightgray;
23
- border-radius: 16px;
24
  }
25
 
26
- .card p:last-child {
27
- margin-bottom: 0;
28
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Additional custom styles for ClinicalConnect Pro */
2
+
3
+ /* Smooth transitions for interactive elements */
4
+ .transition-all-200 {
5
+ transition: all 0.2s ease-in-out;
6
+ }
7
+
8
+ /* Custom scrollbar for webkit browsers */
9
+ .custom-scrollbar::-webkit-scrollbar {
10
+ width: 6px;
11
+ height: 6px;
12
+ }
13
+
14
+ .custom-scrollbar::-webkit-scrollbar-track {
15
+ background: #f1f5f9;
16
+ border-radius: 3px;
17
+ }
18
+
19
+ .custom-scrollbar::-webkit-scrollbar-thumb {
20
+ background: #cbd5e1;
21
+ border-radius: 3px;
22
+ }
23
+
24
+ .custom-scrollbar::-webkit-scrollbar-thumb:hover {
25
+ background: #94a3b8;
26
+ }
27
+
28
+ /* Status pill animations */
29
+ .status-pill {
30
+ transition: transform 0.15s ease, box-shadow 0.15s ease;
31
+ }
32
+
33
+ .status-pill:hover {
34
+ transform: translateY(-1px);
35
+ box-shadow: 0 2px 4px rgba(0,0,0,0.05);
36
+ }
37
+
38
+ /* Table row hover enhancement */
39
+ tr.hover-row {
40
+ transition: background-color 0.15s ease;
41
  }
42
 
43
+ tr.hover-row:hover {
44
+ background-color: #f8fafc;
 
45
  }
46
 
47
+ /* Drawer overlay backdrop blur */
48
+ @supports (backdrop-filter: blur(4px)) {
49
+ .backdrop-blur-custom {
50
+ backdrop-filter: blur(4px);
51
+ }
52
  }
53
 
54
+ /* Calendar day hover states */
55
+ .calendar-day {
56
+ transition: background-color 0.2s ease;
 
 
 
57
  }
58
 
59
+ .calendar-day:hover {
60
+ background-color: #f8fafc;
61
  }
62
+
63
+ /* Focus ring customization */
64
+ input:focus, select:focus, button:focus {
65
+ outline: none;
66
+ ring: 2px;
67
+ ring-color: rgb(13 148 136);
68
+ }
69
+
70
+ /* Loading state animation */
71
+ @keyframes pulse-soft {
72
+ 0%, 100% { opacity: 1; }
73
+ 50% { opacity: 0.6; }
74
+ }
75
+
76
+ .loading-pulse {
77
+ animation: pulse-soft 2s ease-in-out infinite;
78
+ }
79
+
80
+ /* Sticky header shadow on scroll */
81
+ .sticky-shadow {
82
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05);
83
+ }
84
+
85
+ /* Mobile optimizations */
86
+ @media (max-width: 640px) {
87
+ .calendar-grid {
88
+ grid-template-columns: repeat(7, minmax(0, 1fr));
89
+ }
90
+
91
+ .calendar-day {
92
+ min-height: 80px;
93
+ padding: 2px;
94
+ }
95
+
96
+ .calendar-event {
97
+ font-size: 10px;
98
+ padding: 2px;
99
+ }
100
+ }
101
+
102
+ /* Print styles for medical records */
103
+ @media print {
104
+ .no-print {
105
+ display: none !important;
106
+ }
107
+
108
+ .print-only {
109
+ display: block !important;
110
+ }
111
+
112
+ body {
113
+ background: white;
114
+ }
115
+
116
+ header, aside, .sticky {
117
+ position: static !important;
118
+ box-shadow: none !important;
119
+ }
120
+ }
121
+
122
+ /* Accessibility improvements */
123
+ @media (prefers-reduced-motion: reduce) {
124
+ * {
125
+ animation-duration: 0.01ms !important;
126
+ animation-iteration-count: 1 !important;
127
+ transition-duration: 0.01ms !important;
128
+ }
129
+ }
130
+
131
+ /* High contrast mode support */
132
+ @media (prefers-contrast: high) {
133
+ .border-gray-200 {
134
+ border-color: #000;
135
+ }
136
+
137
+ .text-gray-600 {
138
+ color: #000;
139
+ }
140
+ }