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,612 @@
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>Provider Console · EvalDoc</title>
7
+ <meta name="description" content="Manage your EvalDoc link, branding, topics, conversations, and analytics." />
8
+ <meta name="theme-color" content="#0e1a14" />
9
+ <meta name="robots" content="noindex" />
10
+ <link rel="icon" href="/favicon.svg" type="image/svg+xml" />
11
+ <link rel="apple-touch-icon" href="/favicon.svg" />
12
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
13
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
14
+ <link
15
+ href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap"
16
+ rel="stylesheet"
17
+ />
18
+ <link rel="stylesheet" href="/app/app.css" />
19
+ <!-- Google tag (gtag.js) -->
20
+ <script async src="https://www.googletagmanager.com/gtag/js?id=G-NPWYSPFSVG"></script>
21
+ <script>
22
+ window.dataLayer = window.dataLayer || [];
23
+ function gtag(){dataLayer.push(arguments);}
24
+ gtag("js", new Date());
25
+
26
+ gtag("config", "G-NPWYSPFSVG");
27
+ </script>
28
+ </head>
29
+ <body>
30
+ <div class="dashboard-bg"></div>
31
+ <header class="topbar">
32
+ <div class="brand">
33
+ <img src="/assets/logo.jpg" alt="EvalDoc Logo" class="logo-img" />
34
+ <span class="subtitle">Provider Console</span>
35
+ </div>
36
+ <div style="display:flex;align-items:center;gap:1rem;">
37
+ <button id="notificationBell" class="ghost notification-bell" title="Notifications" style="position:relative;font-size:1.25rem;padding:0.4rem;">
38
+ 🔔
39
+ <span id="notificationBadge" class="notification-badge" style="display:none;">0</span>
40
+ </button>
41
+ <button id="signOutBtn" class="ghost hidden">Sign out</button>
42
+ </div>
43
+ </header>
44
+
45
+ <main class="container">
46
+ <div class="nav-links" id="navLinks" style="display: none;">
47
+ <a href="/app" class="nav-link active">Dashboard</a>
48
+ <a href="/app/inbox" class="nav-link">Inbox</a>
49
+ <a href="/app/analytics" class="nav-link">Analytics</a>
50
+ <a href="#helpPanel" class="nav-link" onclick="document.getElementById('helpPanel').scrollIntoView({behavior:'smooth'});return false;">Help</a>
51
+ </div>
52
+
53
+ <section id="waitlistPanel" class="card hidden">
54
+ <div class="waitlist-badge">🚀 Launching April 1, 2026</div>
55
+ <h2>EvalDoc is coming soon</h2>
56
+ <p>Be among the first doctors on the platform. Request early access and we'll notify you when we go live.</p>
57
+ <form id="waitlistForm" class="form">
58
+ <input id="waitlistName" type="text" placeholder="Your full name" />
59
+ <input id="waitlistEmail" type="email" placeholder="Email address" required />
60
+ <input id="waitlistSpecialty" type="text" placeholder="Medical specialty (e.g. Family Medicine)" />
61
+ <button id="waitlistSubmitBtn" type="submit">Request Early Access</button>
62
+ <p class="hint" id="waitlistMessage"></p>
63
+ </form>
64
+ <p class="hint" style="margin-top: 1.5rem;">
65
+ Already approved? <a href="#" id="showAuthLink" style="color: var(--accent);">Sign in here</a>
66
+ </p>
67
+ </section>
68
+
69
+ <section id="authPanel" class="card">
70
+ <h1>Provider access</h1>
71
+ <p>Sign in to set up your link and manage your safe chat experience.</p>
72
+ <div class="auth-grid">
73
+ <form id="loginForm" class="form" novalidate>
74
+ <h3>Sign in</h3>
75
+ <label>
76
+ Email
77
+ <input id="loginEmail" type="email" placeholder="you@clinic.com" autocomplete="email" required />
78
+ </label>
79
+ <label>
80
+ Password
81
+ <input id="loginPassword" type="password" placeholder="Your password" autocomplete="current-password" required />
82
+ </label>
83
+ <button id="loginBtn" type="submit">Sign in</button>
84
+ <p class="hint" style="margin: 0;">
85
+ <a href="#" id="forgotPasswordLink" style="color: var(--accent);">Forgot password?</a>
86
+ </p>
87
+ </form>
88
+ <form id="signupForm" class="form" novalidate>
89
+ <h3>Create account</h3>
90
+ <label>
91
+ Email
92
+ <input id="signupEmail" type="email" placeholder="you@clinic.com" autocomplete="email" required />
93
+ </label>
94
+ <label>
95
+ Password
96
+ <input id="signupPassword" type="password" placeholder="At least 6 characters" autocomplete="new-password" minlength="6" required />
97
+ </label>
98
+ <button id="signupBtn" type="submit" class="secondary">Create account</button>
99
+ </form>
100
+ </div>
101
+ <p class="hint" id="authError" role="alert" aria-live="polite"></p>
102
+ </section>
103
+
104
+ <div id="onboardingProgress" class="onboarding-progress hidden">
105
+ <div class="progress-step completed" data-step="1"><span class="step-number">1</span><span class="step-label">Account</span></div>
106
+ <div class="progress-connector"></div>
107
+ <div class="progress-step active" data-step="2"><span class="step-number">2</span><span class="step-label">Profile</span></div>
108
+ <div class="progress-connector"></div>
109
+ <div class="progress-step" data-step="3"><span class="step-number">3</span><span class="step-label">Billing</span></div>
110
+ <div class="progress-connector"></div>
111
+ <div class="progress-step" data-step="4"><span class="step-number">4</span><span class="step-label">Launch</span></div>
112
+ </div>
113
+
114
+ <section id="onboardingPanel" class="card hidden">
115
+ <h2>Set up your link</h2>
116
+ <p>Finish onboarding to publish your provider link.</p>
117
+ <form id="onboardingForm" class="form">
118
+ <div class="grid">
119
+ <label>
120
+ Handle
121
+ <input id="handleInput" type="text" placeholder="dr-lee" required />
122
+ </label>
123
+ <label>
124
+ Display name
125
+ <input id="displayNameInput" type="text" placeholder="Dr. Ava Lee" required />
126
+ </label>
127
+ <label>
128
+ Specialty
129
+ <input id="specialtyInput" type="text" placeholder="Family Medicine" required />
130
+ </label>
131
+ <label>
132
+ Country
133
+ <select id="countryInput" required>
134
+ <option value="">Select Country</option>
135
+ <option value="US">United States</option>
136
+ <option value="CA">Canada</option>
137
+ <option value="GB">United Kingdom</option>
138
+ <option value="AU">Australia</option>
139
+ <option value="NZ">New Zealand</option>
140
+ <option value="DE">Germany</option>
141
+ <option value="FR">France</option>
142
+ <option value="IT">Italy</option>
143
+ <option value="ES">Spain</option>
144
+ <option value="NL">Netherlands</option>
145
+ <option value="SE">Sweden</option>
146
+ <option value="NO">Norway</option>
147
+ <option value="DK">Denmark</option>
148
+ <option value="FI">Finland</option>
149
+ <option value="IE">Ireland</option>
150
+ <option value="CH">Switzerland</option>
151
+ <option value="AT">Austria</option>
152
+ <option value="BE">Belgium</option>
153
+ <option value="JP">Japan</option>
154
+ <option value="SG">Singapore</option>
155
+ <option value="IN">India</option>
156
+ <option value="OTHER">Other</option>
157
+ </select>
158
+ </label>
159
+ </div>
160
+ <div class="grid">
161
+ <label>
162
+ Medical License Number
163
+ <input id="licenseNumberInput" type="text" placeholder="License #123456" required />
164
+ </label>
165
+ <label>
166
+ Doctor Certificate / Medical License (PDF or Image)
167
+ <input id="certificateInput" type="file" accept=".pdf,.jpg,.jpeg,.png" required />
168
+ <span class="hint">Upload your medical license or certificate (Max 5MB)</span>
169
+ </label>
170
+ </div>
171
+ <div class="grid">
172
+ <label>
173
+ Practice logo (optional)
174
+ <input id="logoInput" type="file" accept=".jpg,.jpeg,.png,.svg,.webp" />
175
+ <span class="hint">Square logo recommended (Max 2MB)</span>
176
+ </label>
177
+ <label>
178
+ Provider photo (optional)
179
+ <input id="photoInput" type="file" accept=".jpg,.jpeg,.png,.webp" />
180
+ <span class="hint">Professional headshot (Max 2MB)</span>
181
+ </label>
182
+ </div>
183
+ <div class="grid">
184
+ <label>
185
+ Primary color
186
+ <input id="primaryColorInput" type="text" placeholder="#0e1a14" />
187
+ </label>
188
+ <label>
189
+ Secondary color
190
+ <input id="secondaryColorInput" type="text" placeholder="#4fb3a4" />
191
+ </label>
192
+ </div>
193
+ <label>
194
+ Welcome message
195
+ <textarea id="welcomeInput" rows="3"></textarea>
196
+ </label>
197
+ <fieldset>
198
+ <legend>Topics</legend>
199
+ <div id="topicsList" class="topics"></div>
200
+ </fieldset>
201
+ <button id="createProviderBtn" type="submit">Create provider</button>
202
+ <p class="hint" id="onboardingError"></p>
203
+ </form>
204
+ </section>
205
+
206
+ <section id="billingSetupPanel" class="card hidden">
207
+ <h2>💳 Set Up Payment & Pricing</h2>
208
+ <p>Configure your Stripe account and pricing to start receiving payments from patients.</p>
209
+
210
+ <div class="billing-status" id="billingStatus">
211
+ <p class="hint">Checking Stripe connection...</p>
212
+ </div>
213
+
214
+ <div id="stripeNotConnected" class="hidden">
215
+ <h3>Connect Stripe Account</h3>
216
+ <p>You need a Stripe account to receive payments. We'll create one for you automatically.</p>
217
+ <button id="createStripeAccountBtn">Create Stripe Connect Account</button>
218
+ <p class="hint" id="stripeError"></p>
219
+ </div>
220
+
221
+ <div id="stripeOnboarding" class="hidden">
222
+ <h3>Complete Stripe Onboarding</h3>
223
+ <p>Your Stripe account has been created. Complete the onboarding to start receiving payments.</p>
224
+ <button id="completeStripeOnboardingBtn">Complete Stripe Setup</button>
225
+ <p class="hint">You'll be redirected to Stripe to verify your identity and bank details.</p>
226
+ </div>
227
+
228
+ <div id="stripeConnected" class="hidden">
229
+ <h3>✓ Stripe Connected</h3>
230
+ <p>Your Stripe account is set up and ready to receive payments!</p>
231
+
232
+ <h3 style="margin-top: 2rem;">Set Your Pricing</h3>
233
+ <div class="form">
234
+ <label>
235
+ Pricing Model
236
+ <select id="billingPricingModel">
237
+ <option value="free">Free (No Payment Required)</option>
238
+ <option value="subscription">Monthly Subscription</option>
239
+ <option value="per-chat">Pay Per Chat</option>
240
+ </select>
241
+ </label>
242
+
243
+ <div id="subscriptionPricingFields" class="hidden">
244
+ <label>
245
+ Monthly Subscription Price (USD)
246
+ <input id="billingSubscriptionPrice" type="number" step="0.01" min="0" max="10000" placeholder="29.00" />
247
+ </label>
248
+ </div>
249
+
250
+ <div id="perChatPricingFields" class="hidden">
251
+ <label>
252
+ Per-Chat Price (USD)
253
+ <input id="billingPerChatPrice" type="number" step="0.01" min="0" max="1000" placeholder="5.00" />
254
+ </label>
255
+ </div>
256
+
257
+ <button id="saveBillingPricingBtn">Save Pricing & Continue</button>
258
+ <p class="hint" id="billingPricingError"></p>
259
+ </div>
260
+ </div>
261
+
262
+ <button id="skipBillingBtn" class="ghost" style="margin-top: 2rem;">Skip for Now (Set up later)</button>
263
+ </section>
264
+
265
+ <section id="dashboardPanel" class="hidden">
266
+ <div class="card onboarding-card hidden" id="onboardingChecklistCard">
267
+ <div class="onboarding-head">
268
+ <h2>Get set up</h2>
269
+ <span class="onboarding-percent" id="onboardingPercent">0%</span>
270
+ </div>
271
+ <div class="onboarding-progress">
272
+ <div class="onboarding-progress-bar" id="onboardingProgressBar" style="width:0%"></div>
273
+ </div>
274
+ <div class="onboarding-next hidden" id="onboardingNext"></div>
275
+ <ul class="onboarding-steps" id="onboardingSteps"></ul>
276
+ </div>
277
+
278
+ <div class="card verification-banner hidden" id="verificationBanner"></div>
279
+
280
+ <div style="margin-bottom: 1.5rem; display: flex; gap: 1rem;">
281
+ <a href="/app/inbox" style="padding: 0.75rem 1.5rem; background: linear-gradient(135deg, #4fb3a4, #3a8a7e); color: white; text-decoration: none; border-radius: 8px; font-weight: 600; transition: all 0.2s;">
282
+ 📬 View Inbox
283
+ </a>
284
+ </div>
285
+
286
+ <div class="grid-2">
287
+ <div class="card">
288
+ <div class="export-bar">
289
+ <button id="exportCsvBtn" class="ghost" title="Export analytics as CSV">📊 Export CSV</button>
290
+ </div>
291
+ <h2>Overview</h2>
292
+ <div class="stats">
293
+ <div>
294
+ <span class="stat-label">Monthly chats</span>
295
+ <span class="stat" id="statMonthly">0</span>
296
+ </div>
297
+ <div>
298
+ <span class="stat-label">Escalations</span>
299
+ <span class="stat" id="statEscalations">0</span>
300
+ </div>
301
+ <div>
302
+ <span class="stat-label">Plan limit</span>
303
+ <span class="stat" id="statLimit">0</span>
304
+ </div>
305
+ <div>
306
+ <span class="stat-label">Escalation rate</span>
307
+ <span class="stat" id="statEscalationRate">0%</span>
308
+ </div>
309
+ <div>
310
+ <span class="stat-label">Satisfaction</span>
311
+ <span class="stat" id="statSatisfaction">—</span>
312
+ </div>
313
+ <div>
314
+ <span class="stat-label">Resolution rate</span>
315
+ <span class="stat" id="statResolutionRate">—</span>
316
+ </div>
317
+ <div>
318
+ <span class="stat-label">Total conversations</span>
319
+ <span class="stat" id="statTotalConversations">0</span>
320
+ </div>
321
+ <div>
322
+ <span class="stat-label">Unique patients</span>
323
+ <span class="stat" id="statUniquePatients">0</span>
324
+ </div>
325
+ </div>
326
+ <div style="display:flex;align-items:center;gap:0.75rem;">
327
+ <button id="refreshAnalyticsBtn" class="ghost">Refresh</button>
328
+ <span id="analyticsLastUpdated" style="font-size:0.75rem;color:var(--muted);"></span>
329
+ </div>
330
+ <div class="grid-2" style="margin-top:1.5rem;">
331
+ <div>
332
+ <h3 style="font-size:0.95rem;margin-bottom:0.5rem;">Top Topics</h3>
333
+ <div id="topTopicsList" style="font-size:0.85rem;color:var(--muted);">No data yet</div>
334
+ </div>
335
+ <div>
336
+ <h3 style="font-size:0.95rem;margin-bottom:0.5rem;">Common Questions</h3>
337
+ <div id="topQuestionsList" style="font-size:0.85rem;color:var(--muted);">No data yet</div>
338
+ </div>
339
+ <div>
340
+ <h3 style="font-size:0.95rem;margin-bottom:0.5rem;">AI Draft Performance</h3>
341
+ <div id="draftMetricsBreakdown" style="font-size:0.85rem;color:var(--muted);">No data yet</div>
342
+ </div>
343
+ </div>
344
+ </div>
345
+ <div class="card">
346
+ <h2>Share kit</h2>
347
+ <div class="preview-callout hidden" id="previewCallout">
348
+ <div class="preview-callout-head">
349
+ <span class="preview-pill">● Live preview</span>
350
+ </div>
351
+ <p class="preview-callout-text">Your preview link is live:</p>
352
+ <div class="preview-callout-link-row">
353
+ <span class="preview-callout-link" id="previewCalloutLink">-</span>
354
+ <button id="previewCopyBtn" class="secondary" style="padding:0.5rem 0.9rem;">Copy</button>
355
+ </div>
356
+ <p class="hint">Your link works right now. It switches to fully Published automatically once your credentials are verified.</p>
357
+ </div>
358
+ <p class="share-link" id="shareLink">-</p>
359
+ <canvas id="qrCanvas" width="160" height="160"></canvas>
360
+ <div style="display: flex; gap: 0.5rem; flex-direction: column;">
361
+ <button id="copyLinkBtn" class="secondary">Copy link</button>
362
+ <button id="downloadQRBtn" class="secondary">Download QR Code</button>
363
+ <button id="previewChatBtn" class="ghost">↗ Preview patient chat page</button>
364
+ </div>
365
+ <div class="share-templates" style="margin-top:1.25rem;border-top:1px solid var(--gray-200);padding-top:1rem;">
366
+ <h3 style="font-size:0.95rem;margin-bottom:0.75rem;">Copy templates</h3>
367
+ <div style="display:flex;flex-direction:column;gap:0.5rem;">
368
+ <button id="copySocialTemplate" class="ghost" style="text-align:left;font-size:0.85rem;">📱 Social media post</button>
369
+ <button id="copyEmailTemplate" class="ghost" style="text-align:left;font-size:0.85rem;">📧 Email / newsletter</button>
370
+ <button id="copySmsTemplate" class="ghost" style="text-align:left;font-size:0.85rem;">💬 SMS / text message</button>
371
+ </div>
372
+ </div>
373
+ </div>
374
+ </div>
375
+
376
+ <div class="grid-2">
377
+ <div class="card">
378
+ <h2>Topics</h2>
379
+ <div id="topicsManage" class="topics"></div>
380
+ <button id="saveTopicsBtn">Save topics</button>
381
+ </div>
382
+ <div class="card">
383
+ <h2>Brand & status</h2>
384
+ <label>
385
+ Welcome message
386
+ <textarea id="welcomeUpdate" rows="3"></textarea>
387
+ </label>
388
+ <label>
389
+ Status
390
+ <select id="statusSelect">
391
+ <option value="draft">Draft</option>
392
+ <option value="published">Published</option>
393
+ <option value="suspended">Suspended</option>
394
+ </select>
395
+ </label>
396
+ <div id="verificationBadge" class="verification-badge" style="display:none;"></div>
397
+ <fieldset style="margin-top:1rem;">
398
+ <legend>Branding</legend>
399
+ <div style="display:flex;gap:0.75rem;">
400
+ <label style="flex:1;">Primary color <input id="brandPrimaryUpdate" type="text" placeholder="#0e1a14" /></label>
401
+ <label style="flex:1;">Secondary color <input id="brandSecondaryUpdate" type="text" placeholder="#4fb3a4" /></label>
402
+ </div>
403
+ </fieldset>
404
+ <fieldset style="margin-top:0.75rem;">
405
+ <legend>Contact Info</legend>
406
+ <label>Phone <input id="contactPhone" type="tel" placeholder="e.g. +1 555-0100" /></label>
407
+ <label>Email <input id="contactEmail" type="email" placeholder="clinic@example.com" /></label>
408
+ <label>Address <input id="contactAddress" type="text" placeholder="123 Main St, City" /></label>
409
+ </fieldset>
410
+ <fieldset style="margin-top:0.75rem;">
411
+ <legend>Business Hours</legend>
412
+ <div style="display:flex;gap:0.75rem;">
413
+ <label style="flex:1;">Opens <input id="hoursOpen" type="time" /></label>
414
+ <label style="flex:1;">Closes <input id="hoursClose" type="time" /></label>
415
+ </div>
416
+ <label>Summary <input id="hoursSummary" type="text" placeholder="e.g. Mon-Fri 9am-5pm" /></label>
417
+ </fieldset>
418
+ <fieldset style="margin-top:0.75rem;">
419
+ <legend>Notification Preferences</legend>
420
+ <label style="display:flex;align-items:center;gap:0.5rem;margin-bottom:0.4rem;">
421
+ <input type="checkbox" id="notifEscalation" checked> Escalation alerts
422
+ </label>
423
+ <label style="display:flex;align-items:center;gap:0.5rem;margin-bottom:0.4rem;">
424
+ <input type="checkbox" id="notifUnread" checked> Unread message reminders
425
+ </label>
426
+ <label style="display:flex;align-items:center;gap:0.5rem;">
427
+ <input type="checkbox" id="notifDigest"> Daily digest email
428
+ </label>
429
+ </fieldset>
430
+ <button id="saveSettingsBtn" class="secondary" style="margin-top:1rem;">Save settings</button>
431
+ </div>
432
+ </div>
433
+
434
+ <div class="grid-2">
435
+ <div class="card">
436
+ <h2>💰 Revenue & Pricing</h2>
437
+ <div class="stats" style="margin-bottom: 1.5rem;">
438
+ <div>
439
+ <span class="stat-label">Total Revenue</span>
440
+ <span class="stat" id="statRevenue">$0</span>
441
+ </div>
442
+ <div>
443
+ <span class="stat-label">Transactions</span>
444
+ <span class="stat" id="statTransactions">0</span>
445
+ </div>
446
+ <div>
447
+ <span class="stat-label">Active Subscriptions</span>
448
+ <span class="stat" id="statSubscriptions">0</span>
449
+ </div>
450
+ </div>
451
+ <button id="viewTransactionsBtn" class="ghost">View Transaction History</button>
452
+ </div>
453
+ <div class="card">
454
+ <h2>Pricing Configuration</h2>
455
+ <p class="hint" style="margin-bottom:0.75rem;">Prices are in USD. Stripe auto-converts for patients in other currencies.</p>
456
+ <label>
457
+ Payment Status
458
+ <select id="paymentEnabledSelect">
459
+ <option value="false">Free (No Payment Required)</option>
460
+ <option value="true">Paid</option>
461
+ </select>
462
+ </label>
463
+ <label>
464
+ Pricing Model
465
+ <select id="pricingModelSelect">
466
+ <option value="free">Free</option>
467
+ <option value="per-chat">Pay Per Chat</option>
468
+ <option value="subscription">Monthly Subscription</option>
469
+ <option value="hybrid">Hybrid (Free first, Paid after)</option>
470
+ </select>
471
+ </label>
472
+ <label>
473
+ Per-Chat Price (USD)
474
+ <input id="perChatPriceInput" type="number" step="0.01" min="0" max="1000" placeholder="5.00" />
475
+ </label>
476
+ <label>
477
+ Monthly Subscription (USD)
478
+ <input id="subscriptionPriceInput" type="number" step="0.01" min="0" max="10000" placeholder="29.00" />
479
+ </label>
480
+ <button id="savePricingBtn">Save Pricing</button>
481
+ <p class="hint" id="pricingError"></p>
482
+ </div>
483
+ </div>
484
+
485
+ <div class="grid-2">
486
+ <div class="card" id="planPanel">
487
+ <h2>Your Plan</h2>
488
+ <p id="currentPlanLabel" style="color:#aaa;margin-bottom:1rem;">Current plan: <strong>Free</strong></p>
489
+ <div class="plan-comparison" id="planComparison"></div>
490
+ </div>
491
+ <div class="card" id="referralPanel">
492
+ <h2>Refer & Earn</h2>
493
+ <p style="color:#aaa;margin-bottom:1rem;">Invite another doctor and you both get <strong>1 month free Pro</strong>.</p>
494
+ <div style="display:flex;gap:0.5rem;align-items:center;">
495
+ <input type="text" id="referralLink" readonly style="flex:1;padding:0.5rem;border:1px solid #333;border-radius:6px;background:#1a1a1a;color:#e0e0e0;font-size:0.85rem;" />
496
+ <button id="copyReferralBtn" class="secondary" style="white-space:nowrap;">Copy</button>
497
+ </div>
498
+ <div style="margin-top:1rem;">
499
+ <span class="stat-label">Referrals</span>
500
+ <span class="stat" id="referralCount">0</span>
501
+ </div>
502
+ </div>
503
+ </div>
504
+
505
+ <div class="card" id="transactionsPanel" style="display: none;">
506
+ <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem;">
507
+ <h2>Transaction History</h2>
508
+ <button id="closeTransactionsBtn" class="ghost">Close</button>
509
+ </div>
510
+ <div id="transactionsList" style="max-height: 400px; overflow-y: auto;"></div>
511
+ </div>
512
+
513
+ <div class="card" id="planCard">
514
+ <h2>Plan & Usage</h2>
515
+ <div class="plan-info">
516
+ <div class="plan-badge" id="planBadge">Free</div>
517
+ <div class="plan-usage">
518
+ <div class="usage-bar-container">
519
+ <div class="usage-bar" id="usageBar" style="width:0%"></div>
520
+ </div>
521
+ <span class="usage-text" id="usageText">0 / 50 chats this month</span>
522
+ </div>
523
+ </div>
524
+ <div id="usageWarning" style="display:none;"></div>
525
+ <div class="card" id="helpPanel">
526
+ <h2>Help & Resources</h2>
527
+ <div class="help-grid" style="display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:1rem;margin-top:1rem;">
528
+ <div class="help-item" style="padding:1rem;border:1px solid #333;border-radius:8px;">
529
+ <h4 style="margin:0 0 0.5rem 0;">Getting Started</h4>
530
+ <p style="color:#aaa;font-size:0.85rem;margin:0;">Complete your profile, verify your credentials, set pricing, then publish your link to start receiving patients.</p>
531
+ </div>
532
+ <div class="help-item" style="padding:1rem;border:1px solid #333;border-radius:8px;">
533
+ <h4 style="margin:0 0 0.5rem 0;">Safety Pipeline</h4>
534
+ <p style="color:#aaa;font-size:0.85rem;margin:0;">AI never diagnoses or prescribes. Red-flag symptoms auto-escalate. All conversations are logged for your review.</p>
535
+ </div>
536
+ <div class="help-item" style="padding:1rem;border:1px solid #333;border-radius:8px;">
537
+ <h4 style="margin:0 0 0.5rem 0;">Sharing Your Link</h4>
538
+ <p style="color:#aaa;font-size:0.85rem;margin:0;">Use the Share Kit to copy your link, download a QR code, or share via WhatsApp/SMS/email.</p>
539
+ </div>
540
+ <div class="help-item" style="padding:1rem;border:1px solid #333;border-radius:8px;">
541
+ <h4 style="margin:0 0 0.5rem 0;">Need Help?</h4>
542
+ <p style="color:#aaa;font-size:0.85rem;margin:0;">Contact us at <a href="mailto:helpme@evaldoctor.ai" style="color:#4fb3a4;">helpme@evaldoctor.ai</a> or visit our <a href="/terms.html" style="color:#4fb3a4;">Terms</a> and <a href="/privacy.html" style="color:#4fb3a4;">Privacy Policy</a>.</p>
543
+ </div>
544
+ </div>
545
+ </div>
546
+
547
+ <div class="card">
548
+ <div style="display:flex;justify-content:space-between;align-items:center;">
549
+ <h2>Conversations</h2>
550
+ <button id="exportConversationsBtn" class="ghost" style="font-size:0.85rem;">Export CSV</button>
551
+ </div>
552
+ <div class="conversation-filters">
553
+ <input id="conversationSearch" type="text" placeholder="Search conversations..." style="flex:1;padding:0.5rem 0.75rem;border:1px solid #333;border-radius:6px;background:#1a1a1a;color:#e0e0e0;" />
554
+ <select id="conversationFilter" style="padding:0.5rem;border:1px solid #333;border-radius:6px;background:#1a1a1a;color:#e0e0e0;">
555
+ <option value="">All</option>
556
+ <option value="escalated">Escalated only</option>
557
+ <option value="high-satisfaction">High rating (4-5)</option>
558
+ <option value="low-satisfaction">Low rating (1-2)</option>
559
+ <option value="unrated">No rating</option>
560
+ </select>
561
+ </div>
562
+ <div id="conversations" class="conversation-list"></div>
563
+ </div>
564
+
565
+ <div class="card">
566
+ <div style="display:flex;justify-content:space-between;align-items:center;">
567
+ <h2>Safety Events</h2>
568
+ <button id="refreshSafetyBtn" class="ghost" style="font-size:0.85rem;">Refresh</button>
569
+ </div>
570
+ <div id="safetyEventsList" style="font-size:0.9rem;color:var(--muted);">Loading...</div>
571
+ </div>
572
+
573
+ <div class="card" id="accountManagementCard">
574
+ <h2>Account</h2>
575
+ <p>Download a full copy of your account data, or permanently delete your account.</p>
576
+ <div class="account-actions">
577
+ <button id="exportAccountBtn" class="secondary">Export my data</button>
578
+ <button id="deleteAccountBtn" class="danger-btn">Delete account</button>
579
+ </div>
580
+ <p class="hint" id="accountMessage"></p>
581
+
582
+ <div class="delete-confirm hidden" id="deleteConfirm">
583
+ <p class="delete-confirm-text">This permanently deletes your provider profile, conversations, and all related data. This cannot be undone.</p>
584
+ <label>
585
+ Type <strong>DELETE</strong> to confirm
586
+ <input id="deleteConfirmInput" type="text" placeholder="DELETE" autocomplete="off" />
587
+ </label>
588
+ <div class="account-actions">
589
+ <button id="cancelDeleteBtn" class="ghost">Cancel</button>
590
+ <button id="confirmDeleteBtn" class="danger-btn" disabled>Permanently delete</button>
591
+ </div>
592
+ <p class="hint" id="deleteError"></p>
593
+ </div>
594
+ </div>
595
+ </section>
596
+ </main>
597
+
598
+ <script src="https://www.gstatic.com/firebasejs/9.23.0/firebase-app-compat.js"></script>
599
+ <script src="https://www.gstatic.com/firebasejs/9.23.0/firebase-auth-compat.js"></script>
600
+ <script src="https://www.gstatic.com/firebasejs/9.23.0/firebase-storage-compat.js"></script>
601
+ <script src="https://cdn.jsdelivr.net/npm/qrcode@1.5.3/build/qrcode.min.js"></script>
602
+ <div id="notificationDropdown" class="notification-dropdown" style="display:none;">
603
+ <div class="notification-dropdown-header">
604
+ <strong>Notifications</strong>
605
+ <button id="markAllReadBtn" class="ghost" style="font-size:0.75rem;padding:0.25rem 0.5rem;">Mark all read</button>
606
+ </div>
607
+ <div id="notificationList" class="notification-list"></div>
608
+ </div>
609
+ <script src="/app/config.js"></script>
610
+ <script src="/app/app.js"></script>
611
+ </body>
612
+ </html>
Binary file