evaldoc 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. package/.env.staging.example +19 -0
  2. package/.firebaserc +6 -0
  3. package/.github/workflows/auto-merge-to-main.yml +28 -0
  4. package/.github/workflows/ci.yml +27 -0
  5. package/.github/workflows/npxhub-publish.yml +170 -0
  6. package/.prettierignore +4 -0
  7. package/.prettierrc.json +7 -0
  8. package/README.md +142 -0
  9. package/SRS.md +448 -0
  10. package/apphosting.staging.yaml +48 -0
  11. package/apphosting.yaml +50 -0
  12. package/bin/evaldoc.cjs +105 -0
  13. package/cors.json +8 -0
  14. package/docs/ARCHITECTURE.md +769 -0
  15. package/docs/ARCHITECTURE_SUMMARY.md +323 -0
  16. package/docs/DEPLOYMENT.md +86 -0
  17. package/docs/DEPLOYMENT_STEPS.md +373 -0
  18. package/docs/DEPLOY_FIRESTORE_RULES.md +239 -0
  19. package/docs/DEPLOY_STORAGE_RULES.md +82 -0
  20. package/docs/DOCTOR_TUTORIAL.md +467 -0
  21. package/docs/FIREBASE_STORAGE_CORS_FIX.md +131 -0
  22. package/docs/FIXES_APPLIED.md +128 -0
  23. package/docs/IMPLEMENTATION.md +498 -0
  24. package/docs/IMPLEMENTATION_COMPLETE.md +317 -0
  25. package/docs/LLM-SETUP.md +216 -0
  26. package/docs/MANUAL_TEST_GUIDE.md +327 -0
  27. package/docs/PATIENT_GUIDE.md +451 -0
  28. package/docs/PLATFORM_OVERVIEW.md +194 -0
  29. package/docs/QUICKSTART.md +252 -0
  30. package/docs/QUICK_REFERENCE.md +222 -0
  31. package/docs/READY_TO_TEST.md +383 -0
  32. package/docs/RUN.md +237 -0
  33. package/docs/START_TESTING.md +130 -0
  34. package/docs/STRIPE_CONNECT_SETUP.md +454 -0
  35. package/docs/SYSTEM_READY.md +345 -0
  36. package/docs/THREADS_IMPLEMENTATION_COMPLETE.md +431 -0
  37. package/docs/THREAD_IMPLEMENTATION_GUIDE.md +345 -0
  38. package/docs/firebasefiles.md +21 -0
  39. package/docs/homepage.md +1208 -0
  40. package/docs/payments.md +159 -0
  41. package/eslint.config.js +76 -0
  42. package/firebase.json +27 -0
  43. package/firestore.indexes.json +88 -0
  44. package/firestore.rules +125 -0
  45. package/functions/package-lock.json +2884 -0
  46. package/functions/package.json +20 -0
  47. package/functions/src/analytics.js +101 -0
  48. package/functions/src/audit.js +28 -0
  49. package/functions/src/auth.js +19 -0
  50. package/functions/src/drafts.js +128 -0
  51. package/functions/src/feedback.js +164 -0
  52. package/functions/src/firebase-init.js +29 -0
  53. package/functions/src/i18n.js +134 -0
  54. package/functions/src/limits.js +27 -0
  55. package/functions/src/llm.js +271 -0
  56. package/functions/src/ner.js +162 -0
  57. package/functions/src/notifications.js +273 -0
  58. package/functions/src/orgs.js +127 -0
  59. package/functions/src/patient-api.js +545 -0
  60. package/functions/src/payment.js +830 -0
  61. package/functions/src/safety.js +188 -0
  62. package/functions/src/stripe-config.js +33 -0
  63. package/functions/src/topics.js +94 -0
  64. package/functions/src/triage.js +191 -0
  65. package/functions/src/utils.js +28 -0
  66. package/functions/src/validate.js +177 -0
  67. package/functions/test-firebase.js +36 -0
  68. package/jest.config.js +18 -0
  69. package/package.json +52 -0
  70. package/public/404.html +93 -0
  71. package/public/app/analytics.html +336 -0
  72. package/public/app/analytics.js +177 -0
  73. package/public/app/app.css +1400 -0
  74. package/public/app/app.js +1754 -0
  75. package/public/app/config.js +14 -0
  76. package/public/app/inbox-threads.js +843 -0
  77. package/public/app/inbox.html +598 -0
  78. package/public/app/inbox.js +397 -0
  79. package/public/app/index.html +612 -0
  80. package/public/assets/logo.jpg +0 -0
  81. package/public/chat.html +137 -0
  82. package/public/css/chat.css +870 -0
  83. package/public/css/landing-enhance.css +298 -0
  84. package/public/css/styles.css +1198 -0
  85. package/public/favicon.svg +5 -0
  86. package/public/find-doctor.html +220 -0
  87. package/public/index.html +399 -0
  88. package/public/js/chat-threads.js +513 -0
  89. package/public/js/chat.js +832 -0
  90. package/public/js/search.js +41 -0
  91. package/public/privacy.html +101 -0
  92. package/public/robots.txt +6 -0
  93. package/public/site.webmanifest +12 -0
  94. package/public/terms.html +110 -0
  95. package/scripts/create-test-provider.js +55 -0
  96. package/scripts/deploy-staging.sh +51 -0
  97. package/scripts/fix-provider.js +39 -0
  98. package/scripts/quick-test.sh +37 -0
  99. package/scripts/test-chat.sh +54 -0
  100. package/scripts/test-multi-turn.js +137 -0
  101. package/scripts/test-ner-simple.js +28 -0
  102. package/scripts/test-ner.js +60 -0
  103. package/scripts/test-stripe-connect.js +304 -0
  104. package/scripts/test-webhook-secret.sh +24 -0
  105. package/server.js +3864 -0
  106. package/storage.rules +22 -0
  107. package/test-api.json +1 -0
  108. package/tests/emulator/README.md +38 -0
  109. package/tests/emulator/counters.emulator.test.js +81 -0
  110. package/tests/integration/api-account-selfserve.test.js +312 -0
  111. package/tests/integration/api-admin-digest.test.js +202 -0
  112. package/tests/integration/api-chat-satisfaction.test.js +259 -0
  113. package/tests/integration/api-doctor-drafts.test.js +236 -0
  114. package/tests/integration/api-doctor-inbox.test.js +401 -0
  115. package/tests/integration/api-org.test.js +328 -0
  116. package/tests/integration/api-payment.test.js +664 -0
  117. package/tests/integration/api-provider-settings.test.js +475 -0
  118. package/tests/integration/api-qr.test.js +121 -0
  119. package/tests/integration/api-security.test.js +241 -0
  120. package/tests/integration/api-stripe-search.test.js +303 -0
  121. package/tests/integration/api-webhook-deletion.test.js +231 -0
  122. package/tests/mocks/firebase-admin.js +220 -0
  123. package/tests/unit/analytics.test.js +151 -0
  124. package/tests/unit/audit-bugs.test.js +203 -0
  125. package/tests/unit/chat-ui-logic.test.js +283 -0
  126. package/tests/unit/drafts.test.js +104 -0
  127. package/tests/unit/feedback.test.js +148 -0
  128. package/tests/unit/i18n.test.js +229 -0
  129. package/tests/unit/llm-retry.test.js +122 -0
  130. package/tests/unit/notifications.test.js +155 -0
  131. package/tests/unit/orgs.test.js +328 -0
  132. package/tests/unit/payment.test.js +889 -0
  133. package/tests/unit/safety-edge-cases.test.js +509 -0
  134. package/tests/unit/safety-srs-compliance.test.js +252 -0
  135. package/tests/unit/safety.test.js +291 -0
  136. package/tests/unit/server-helpers.test.js +774 -0
  137. package/tests/unit/topics-limits.test.js +158 -0
  138. package/tests/unit/triage.test.js +152 -0
  139. package/tests/unit/validate.test.js +408 -0
@@ -0,0 +1,598 @@
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" />
6
+ <title>Inbox - EvalDoc Provider Console</title>
7
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
8
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
9
+ <link
10
+ href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&display=swap"
11
+ rel="stylesheet"
12
+ />
13
+ <link rel="stylesheet" href="/app/app.css" />
14
+ <style>
15
+ .inbox-container {
16
+ display: grid;
17
+ grid-template-columns: 340px 1fr;
18
+ gap: 1rem;
19
+ height: calc(100vh - 180px);
20
+ margin-top: 1rem;
21
+ }
22
+
23
+ .conversations-sidebar {
24
+ background: #ffffff;
25
+ border-radius: 12px;
26
+ padding: 1rem;
27
+ overflow-y: auto;
28
+ border: 1px solid #e5e7eb;
29
+ }
30
+
31
+ .conversation-item {
32
+ padding: 0.75rem;
33
+ margin-bottom: 0.5rem;
34
+ background: #f9fafb;
35
+ border: 1px solid #e5e7eb;
36
+ border-radius: 8px;
37
+ cursor: pointer;
38
+ transition: all 0.2s;
39
+ position: relative;
40
+ }
41
+
42
+ .conversation-item:hover {
43
+ background: #f3f4f6;
44
+ border-color: #4fb3a4;
45
+ }
46
+
47
+ .conversation-item.active {
48
+ background: #e6f7f4;
49
+ border-color: #4fb3a4;
50
+ border-width: 2px;
51
+ }
52
+
53
+ .conversation-header {
54
+ display: flex;
55
+ justify-content: space-between;
56
+ align-items: start;
57
+ margin-bottom: 0.25rem;
58
+ }
59
+
60
+ .conversation-client {
61
+ font-weight: 600;
62
+ font-size: 0.9rem;
63
+ color: #297B56;
64
+ }
65
+
66
+ .conversation-time {
67
+ font-size: 0.7rem;
68
+ color: #6b7280;
69
+ }
70
+
71
+ .conversation-topic {
72
+ display: none;
73
+ }
74
+
75
+ .conversation-preview {
76
+ font-size: 0.8rem;
77
+ color: #4b5563;
78
+ overflow: hidden;
79
+ text-overflow: ellipsis;
80
+ white-space: nowrap;
81
+ }
82
+
83
+ .conversation-badge {
84
+ display: inline-block;
85
+ font-size: 0.7rem;
86
+ padding: 0.2rem 0.5rem;
87
+ border-radius: 4px;
88
+ margin-top: 0.5rem;
89
+ margin-right: 0.25rem;
90
+ }
91
+
92
+ .conversation-badge.escalated {
93
+ background: rgba(255, 107, 107, 0.3);
94
+ color: #ff6b6b;
95
+ }
96
+
97
+ /* Triage badges */
98
+ .triage-badge {
99
+ display: inline-block;
100
+ font-size: 0.65rem;
101
+ font-weight: 600;
102
+ padding: 0.15rem 0.5rem;
103
+ border-radius: 10px;
104
+ text-transform: uppercase;
105
+ letter-spacing: 0.03em;
106
+ }
107
+
108
+ .triage-badge.urgent {
109
+ background: #fee2e2;
110
+ color: #dc2626;
111
+ border: 1px solid #fca5a5;
112
+ }
113
+
114
+ .triage-badge.needs_review {
115
+ background: #fff7ed;
116
+ color: #ea580c;
117
+ border: 1px solid #fdba74;
118
+ }
119
+
120
+ .triage-badge.informational {
121
+ background: #eff6ff;
122
+ color: #2563eb;
123
+ border: 1px solid #93c5fd;
124
+ }
125
+
126
+ .triage-badge.resolved {
127
+ background: #f0fdf4;
128
+ color: #16a34a;
129
+ border: 1px solid #86efac;
130
+ }
131
+
132
+ .conversation-detail {
133
+ background: #ffffff;
134
+ border-radius: 12px;
135
+ border: 1px solid #e5e7eb;
136
+ display: flex;
137
+ flex-direction: column;
138
+ overflow: hidden;
139
+ }
140
+
141
+ #conversationDetail {
142
+ flex: 1;
143
+ overflow-y: auto;
144
+ padding: 1.5rem;
145
+ }
146
+
147
+ .detail-header {
148
+ margin-bottom: 1rem;
149
+ padding-bottom: 1rem;
150
+ border-bottom: 1px solid #e5e7eb;
151
+ }
152
+
153
+ .detail-title {
154
+ font-size: 1.2rem;
155
+ font-weight: 600;
156
+ margin-bottom: 0.5rem;
157
+ color: #111827;
158
+ }
159
+
160
+ .detail-meta {
161
+ display: flex;
162
+ gap: 1rem;
163
+ flex-wrap: wrap;
164
+ font-size: 0.8rem;
165
+ color: #6b7280;
166
+ }
167
+
168
+ .detail-meta-item {
169
+ display: inline-flex;
170
+ align-items: center;
171
+ gap: 0.25rem;
172
+ }
173
+
174
+ .detail-meta-label {
175
+ font-size: 0.75rem;
176
+ color: #6b7280;
177
+ }
178
+
179
+ .detail-meta-value {
180
+ color: #297B56;
181
+ font-weight: 500;
182
+ }
183
+
184
+ .messages-list {
185
+ display: flex;
186
+ flex-direction: column;
187
+ gap: 1rem;
188
+ }
189
+
190
+ .message-block {
191
+ display: flex;
192
+ flex-direction: column;
193
+ gap: 0.35rem;
194
+ }
195
+
196
+ .message-label {
197
+ font-size: 0.7rem;
198
+ color: #6b7280;
199
+ font-weight: 600;
200
+ text-transform: uppercase;
201
+ letter-spacing: 0.05em;
202
+ }
203
+
204
+ .message-content {
205
+ padding: 0.75rem;
206
+ border-radius: 8px;
207
+ line-height: 1.5;
208
+ font-size: 0.9rem;
209
+ color: #111827;
210
+ }
211
+
212
+ .message-content.user {
213
+ background: #e6f7f4;
214
+ border-left: 3px solid #297B56;
215
+ }
216
+
217
+ .message-content.assistant {
218
+ background: #f3f4f6;
219
+ border-left: 3px solid #9ca3af;
220
+ }
221
+
222
+ .message-content.doctor {
223
+ background: #d1f4e8;
224
+ border-left: 3px solid #297B56;
225
+ font-weight: 500;
226
+ }
227
+
228
+ .empty-state {
229
+ display: flex;
230
+ flex-direction: column;
231
+ align-items: center;
232
+ justify-content: center;
233
+ height: 100%;
234
+ color: #6b7280;
235
+ text-align: center;
236
+ }
237
+
238
+ .empty-state h3 {
239
+ color: #111827;
240
+ }
241
+
242
+ .empty-state-icon {
243
+ font-size: 3rem;
244
+ margin-bottom: 1rem;
245
+ }
246
+
247
+ .filter-bar {
248
+ display: flex;
249
+ gap: 0.5rem;
250
+ margin-bottom: 0.75rem;
251
+ flex-wrap: wrap;
252
+ align-items: center;
253
+ }
254
+
255
+ .filter-btn {
256
+ padding: 0.4rem 0.75rem;
257
+ background: #ffffff;
258
+ border: 1px solid #e5e7eb;
259
+ border-radius: 6px;
260
+ color: #111827;
261
+ font-size: 0.8rem;
262
+ cursor: pointer;
263
+ transition: all 0.2s;
264
+ }
265
+
266
+ .filter-btn:hover {
267
+ background: #f3f4f6;
268
+ border-color: #297B56;
269
+ }
270
+
271
+ .filter-btn.active {
272
+ background: #e6f7f4;
273
+ border-color: #297B56;
274
+ color: #297B56;
275
+ font-weight: 600;
276
+ }
277
+
278
+ /* Notification bell */
279
+ .notification-bell {
280
+ position: relative;
281
+ cursor: pointer;
282
+ margin-left: auto;
283
+ padding: 0.4rem 0.6rem;
284
+ border-radius: 6px;
285
+ border: 1px solid #e5e7eb;
286
+ background: #fff;
287
+ font-size: 1.1rem;
288
+ }
289
+
290
+ .notification-bell:hover {
291
+ background: #f3f4f6;
292
+ }
293
+
294
+ .notification-badge {
295
+ position: absolute;
296
+ top: -4px;
297
+ right: -4px;
298
+ background: #dc2626;
299
+ color: white;
300
+ font-size: 0.6rem;
301
+ font-weight: 700;
302
+ min-width: 16px;
303
+ height: 16px;
304
+ border-radius: 8px;
305
+ display: flex;
306
+ align-items: center;
307
+ justify-content: center;
308
+ padding: 0 3px;
309
+ }
310
+
311
+ .notification-dropdown {
312
+ position: absolute;
313
+ top: 100%;
314
+ right: 0;
315
+ width: 320px;
316
+ max-height: 400px;
317
+ overflow-y: auto;
318
+ background: white;
319
+ border: 1px solid #e5e7eb;
320
+ border-radius: 8px;
321
+ box-shadow: 0 4px 12px rgba(0,0,0,0.1);
322
+ z-index: 100;
323
+ display: none;
324
+ }
325
+
326
+ .notification-dropdown.open {
327
+ display: block;
328
+ }
329
+
330
+ .notification-item {
331
+ padding: 0.75rem;
332
+ border-bottom: 1px solid #f3f4f6;
333
+ cursor: pointer;
334
+ }
335
+
336
+ .notification-item:hover {
337
+ background: #f9fafb;
338
+ }
339
+
340
+ .notification-item.unread {
341
+ background: #eff6ff;
342
+ }
343
+
344
+ .notification-item-title {
345
+ font-size: 0.85rem;
346
+ font-weight: 600;
347
+ color: #111827;
348
+ }
349
+
350
+ .notification-item-body {
351
+ font-size: 0.75rem;
352
+ color: #6b7280;
353
+ margin-top: 0.25rem;
354
+ }
355
+
356
+ /* AI Draft panel */
357
+ .ai-draft-panel {
358
+ margin-bottom: 1.5rem;
359
+ padding: 1rem;
360
+ background: #fffbeb;
361
+ border: 1px solid #fde68a;
362
+ border-radius: 10px;
363
+ position: relative;
364
+ }
365
+
366
+ .ai-draft-header {
367
+ display: flex;
368
+ align-items: center;
369
+ gap: 0.5rem;
370
+ font-size: 0.85rem;
371
+ font-weight: 600;
372
+ color: #92400e;
373
+ margin-bottom: 0.75rem;
374
+ }
375
+
376
+ .ai-draft-content {
377
+ font-size: 0.9rem;
378
+ color: #1f2937;
379
+ line-height: 1.6;
380
+ padding: 0.75rem;
381
+ background: white;
382
+ border-radius: 6px;
383
+ border: 1px solid #fde68a;
384
+ margin-bottom: 0.75rem;
385
+ }
386
+
387
+ .ai-draft-actions {
388
+ display: flex;
389
+ gap: 0.5rem;
390
+ flex-wrap: wrap;
391
+ }
392
+
393
+ .ai-draft-actions button {
394
+ padding: 0.4rem 0.75rem;
395
+ border-radius: 6px;
396
+ font-size: 0.8rem;
397
+ cursor: pointer;
398
+ border: 1px solid;
399
+ font-weight: 500;
400
+ }
401
+
402
+ .btn-accept {
403
+ background: #16a34a;
404
+ color: white;
405
+ border-color: #16a34a;
406
+ }
407
+
408
+ .btn-edit {
409
+ background: #2563eb;
410
+ color: white;
411
+ border-color: #2563eb;
412
+ }
413
+
414
+ .btn-reject {
415
+ background: white;
416
+ color: #dc2626;
417
+ border-color: #dc2626;
418
+ }
419
+
420
+ .btn-regenerate {
421
+ background: white;
422
+ color: #6b7280;
423
+ border-color: #d1d5db;
424
+ }
425
+
426
+ .nav-links {
427
+ display: flex;
428
+ gap: 1rem;
429
+ margin-bottom: 1rem;
430
+ }
431
+
432
+ .nav-link {
433
+ color: rgba(255, 255, 255, 0.6);
434
+ text-decoration: none;
435
+ padding: 0.5rem 1rem;
436
+ border-radius: 6px;
437
+ transition: all 0.2s;
438
+ }
439
+
440
+ .nav-link:hover {
441
+ background: rgba(255, 255, 255, 0.05);
442
+ color: #4fb3a4;
443
+ }
444
+
445
+ .nav-link.active {
446
+ background: rgba(79, 179, 164, 0.2);
447
+ color: #4fb3a4;
448
+ }
449
+
450
+ .reply-section {
451
+ padding: 1rem;
452
+ border-top: 1px solid #e5e7eb;
453
+ background: #f9fafb;
454
+ }
455
+
456
+ .reply-box {
457
+ display: flex;
458
+ flex-direction: column;
459
+ gap: 0.5rem;
460
+ }
461
+
462
+ .reply-textarea {
463
+ width: 100%;
464
+ min-height: 80px;
465
+ padding: 0.75rem;
466
+ background: #ffffff;
467
+ border: 1px solid #e5e7eb;
468
+ border-radius: 8px;
469
+ color: #111827;
470
+ font-family: inherit;
471
+ resize: none;
472
+ }
473
+
474
+ .reply-textarea:focus {
475
+ outline: none;
476
+ border-color: #4fb3a4;
477
+ background: #ffffff;
478
+ }
479
+
480
+ .reply-toolbar {
481
+ display: flex;
482
+ justify-content: flex-end;
483
+ gap: 0.5rem;
484
+ align-items: center;
485
+ }
486
+
487
+ .reply-status {
488
+ font-size: 0.85rem;
489
+ color: #6b7280;
490
+ }
491
+
492
+ /* Triage select for manual override */
493
+ .triage-select {
494
+ padding: 0.3rem 0.5rem;
495
+ border: 1px solid #d1d5db;
496
+ border-radius: 6px;
497
+ font-size: 0.8rem;
498
+ background: white;
499
+ color: #374151;
500
+ cursor: pointer;
501
+ }
502
+
503
+ @media (max-width: 768px) {
504
+ .inbox-container {
505
+ grid-template-columns: 1fr;
506
+ height: auto;
507
+ }
508
+ .conversations-sidebar {
509
+ max-height: 40vh;
510
+ }
511
+ .filter-bar {
512
+ flex-wrap: wrap;
513
+ }
514
+ .reply-textarea {
515
+ font-size: 16px;
516
+ }
517
+ }
518
+ </style>
519
+ <!-- Google tag (gtag.js) -->
520
+ <script async src="https://www.googletagmanager.com/gtag/js?id=G-NPWYSPFSVG"></script>
521
+ <script>
522
+ window.dataLayer = window.dataLayer || [];
523
+ function gtag(){dataLayer.push(arguments);}
524
+ gtag("js", new Date());
525
+
526
+ gtag("config", "G-NPWYSPFSVG");
527
+ </script>
528
+ </head>
529
+ <body>
530
+ <div class="dashboard-bg"></div>
531
+ <header class="topbar">
532
+ <div class="brand">
533
+ <img src="/assets/logo.jpg" alt="EvalDoc Logo" class="logo-img" />
534
+ <span class="subtitle">Provider Console</span>
535
+ </div>
536
+ <button id="signOutBtn" class="ghost">Sign out</button>
537
+ </header>
538
+
539
+ <main class="container">
540
+ <div class="nav-links">
541
+ <a href="/app" class="nav-link">Dashboard</a>
542
+ <a href="/app/inbox" class="nav-link active">Inbox</a>
543
+ <a href="/app/analytics" class="nav-link">Analytics</a>
544
+ </div>
545
+
546
+ <div id="authRequired" class="card hidden">
547
+ <h2>Authentication Required</h2>
548
+ <p>Please sign in to view your inbox.</p>
549
+ <a href="/app" class="button">Go to Sign In</a>
550
+ </div>
551
+
552
+ <div id="inboxContainer" class="hidden">
553
+ <div class="filter-bar">
554
+ <input type="text" id="threadSearchInput" placeholder="Search conversations..." style="padding:6px 10px;border:1px solid #d1d5db;border-radius:6px;font-size:0.85rem;width:180px;" aria-label="Search conversations">
555
+ <button class="filter-btn active" data-filter="all">All</button>
556
+ <button class="filter-btn" data-filter="urgent">Urgent</button>
557
+ <button class="filter-btn" data-filter="needs_review">Needs Review</button>
558
+ <button class="filter-btn" data-filter="informational">Informational</button>
559
+ <button class="filter-btn" data-filter="resolved">Resolved</button>
560
+ <button class="filter-btn" data-filter="escalated">Escalated</button>
561
+
562
+ <div id="notificationBell" class="notification-bell" style="position: relative;">
563
+ <span>&#128276;</span>
564
+ <span id="notificationCount" class="notification-badge" style="display: none;">0</span>
565
+ <div id="notificationDropdown" class="notification-dropdown">
566
+ <div style="padding: 0.75rem; border-bottom: 1px solid #e5e7eb; display: flex; justify-content: space-between; align-items: center;">
567
+ <strong style="font-size: 0.9rem;">Notifications</strong>
568
+ <button id="markAllReadBtn" style="font-size: 0.75rem; color: #2563eb; background: none; border: none; cursor: pointer;">Mark all read</button>
569
+ </div>
570
+ <div id="notificationList"></div>
571
+ </div>
572
+ </div>
573
+ </div>
574
+
575
+ <div class="inbox-container">
576
+ <div class="conversations-sidebar">
577
+ <div id="conversationsList"></div>
578
+ </div>
579
+
580
+ <div class="conversation-detail">
581
+ <div id="conversationDetail">
582
+ <div class="empty-state">
583
+ <div class="empty-state-icon">&#128172;</div>
584
+ <h3>Select a conversation</h3>
585
+ <p>Choose a conversation from the left to view details</p>
586
+ </div>
587
+ </div>
588
+ </div>
589
+ </div>
590
+ </div>
591
+ </main>
592
+
593
+ <script src="https://www.gstatic.com/firebasejs/9.23.0/firebase-app-compat.js"></script>
594
+ <script src="https://www.gstatic.com/firebasejs/9.23.0/firebase-auth-compat.js"></script>
595
+ <script src="/app/config.js"></script>
596
+ <script src="/app/inbox-threads.js"></script>
597
+ </body>
598
+ </html>