Vineela Gampa commited on
Commit
7c726af
·
unverified ·
1 Parent(s): 732e860

fixes for web

Browse files
.gitignore ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ .venv
2
+ /api_key.py
3
+ api_key.py
4
+ .DS_Store
about.html → web/about.html RENAMED
@@ -1,258 +1,258 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <title>About Us | CTRL + ALT + HEAL</title>
6
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
- <script src="https://cdn.tailwindcss.com"></script>
8
- <script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.4.120/pdf.min.js"></script>
9
- <script src="https://cdn.jsdelivr.net/npm/tesseract.js@5.0.3/dist/tesseract.min.js"></script>
10
- <link href="https://unpkg.com/aos@2.3.1/dist/aos.css" rel="stylesheet" />
11
- <link
12
- href="https://fonts.googleapis.com/css2?family=Rubik:wght@400;700&display=swap"
13
- rel="stylesheet"
14
- />
15
-
16
- <style>
17
- :root {
18
- --tropical-indigo: rgb(120, 187, 242);
19
- --wisteria: rgb(197, 217, 251);
20
- --latte-cream: #ffffff;
21
- }
22
-
23
- body {
24
- font-family: "Rubik", sans-serif;
25
- background-color: var(--latte-cream);
26
- color: #333;
27
- }
28
-
29
- .btn-primary {
30
- background-color: var(--tropical-indigo);
31
- color: white;
32
- transition: background-color 0.3s ease;
33
- }
34
-
35
- .btn-primary:hover {
36
- background-color: var(--wisteria);
37
- color: #333;
38
- }
39
- </style>
40
- </head>
41
- <body class="min-h-screen">
42
- <!-- Navbar -->
43
- <nav
44
- class="fixed top-0 left-0 w-full z-50 backdrop-blur-md bg-white/20 border-b border-white/30 shadow-md"
45
- >
46
- <div
47
- class="max-w-6xl mx-auto px-6 py-4 flex justify-between items-center"
48
- >
49
- <!-- Logo -->
50
- <a
51
- href="index.html"
52
- class="text-2xl font-bold hover:text-[var(--tropical-indigo)] transition"
53
- >
54
- CTRL + ALT + HEAL
55
- </a>
56
-
57
- <!-- Desktop Menu -->
58
- <ul class="hidden md:flex space-x-6 font-medium text-gray-800">
59
- <li><a href="index.html" class="nav-link">Home</a></li>
60
- <li><a href="analyzer.html" class="nav-link">Analyzer</a></li>
61
- <li><a href="profile.html" class="nav-link">Profile</a></li>
62
- <li><a href="login.html" class="nav-link">Login</a></li>
63
- <li><a href="about.html" class="nav-link">About</a></li>
64
- </ul>
65
-
66
- <!-- Hamburger Menu -->
67
- <button id="hamburger" class="md:hidden text-[#000000] text-2xl">
68
-
69
- </button>
70
- </div>
71
-
72
- <!-- Mobile Menu -->
73
- <ul
74
- id="mobile-menu"
75
- class="hidden flex-col space-y-4 bg-white/30 backdrop-blur-lg border border-white/20 rounded-xl shadow-lg mt-2 p-4 mx-6 md:hidden"
76
- >
77
- <li>
78
- <a
79
- href="index.html"
80
- class="block text-gray-800 hover:text-[var(--neon-green)]"
81
- >Home</a
82
- >
83
- </li>
84
- <li>
85
- <a
86
- href="analyzer.html"
87
- class="block text-gray-800 hover:text-[var(--neon-green)]"
88
- >Analyzer</a
89
- >
90
- </li>
91
- <li>
92
- <a
93
- href="profile.html"
94
- class="block text-gray-800 hover:text-[var(--neon-green)]"
95
- >Profile</a
96
- >
97
- </li>
98
- <li>
99
- <a
100
- href="login.html"
101
- class="block text-gray-800 hover:text-[var(--neon-green)]"
102
- >Login</a
103
- >
104
- </li>
105
- <li>
106
- <a
107
- href="about.html"
108
- class="block text-gray-800 hover:text-[var(--neon-green)]"
109
- >About</a
110
- >
111
- </li>
112
- </ul>
113
- </nav>
114
-
115
- <script>
116
- const hamburger = document.getElementById("hamburger");
117
- const mobileMenu = document.getElementById("mobile-menu");
118
-
119
- hamburger.addEventListener("click", () => {
120
- mobileMenu.classList.toggle("hidden");
121
- });
122
- </script>
123
-
124
- <!-- About Section -->
125
- <section id="about" class="max-w-3xl mx-auto px-6 py-12 pt-24 font-sans">
126
- <h1 class="text-3xl md:text-4xl font-bold mb-6">
127
- About
128
- <span class="text-[var(--tropical-indigo)]">CTRL + ALT + HEAL</span>
129
- </h1>
130
-
131
- <p class="mb-4">
132
- <strong>CTRL + ALT + HEAL</strong> is a web platform designed to
133
- simplify medical reports and empower patients (and their families) to
134
- actually <em>understand</em> what’s going on.
135
- </p>
136
-
137
- <p class="mb-4">
138
- We take complicated medical language — the kind that sounds like it was
139
- written by a robot with a thesaurus — and translate it into clear,
140
- human-readable explanations. No more Googling your labs and spiraling.
141
- </p>
142
-
143
- <p class="mb-8">
144
- Built by students passionate about medicine, coding, and accessibility,
145
- CTRL + ALT + HEAL is a tool for anyone who’s ever looked at a test
146
- result and thought,<br />
147
- <em class="text-gray-500">“...Is this bad??”</em>
148
- </p>
149
-
150
- <hr class="my-8 border-[var(--wisteria)]" />
151
-
152
- <h2 class="text-2xl font-semibold mb-4 text-[var(--tropical-indigo)]">
153
- Our Mission
154
- </h2>
155
- <p class="mb-8">
156
- To make medical knowledge understandable, actionable, and a little less
157
- scary — no med degree required. We believe that information is power,
158
- and everyone deserves access to it.
159
- </p>
160
-
161
- <h2 class="text-2xl font-semibold mb-4 text-[var(--tropical-indigo)]">
162
- What We Do
163
- </h2>
164
- <ul class="list-disc list-inside mb-8 space-y-2">
165
- <li>
166
- <strong>Simplify medical reports</strong> using clear language and
167
- explainers.
168
- </li>
169
- <li>
170
- <strong>Break down each section line-by-line</strong>, so nothing gets
171
- missed.
172
- </li>
173
- <li>
174
- <strong>Provide helpful context</strong>: what’s normal, what might
175
- need attention, and what you can ask your doctor.
176
- </li>
177
- <li>
178
- <strong>Give next steps</strong> when possible, so you’re not left
179
- hanging.
180
- </li>
181
- </ul>
182
-
183
- <h2 class="text-2xl font-semibold mb-4 text-[var(--tropical-indigo)]">
184
- Who We Are
185
- </h2>
186
- <p class="mb-8">
187
- A team of curious students (and hopefully future healthcare pros!)
188
- combining coding skills, science brains, and a love for clarity. We
189
- believe in tech that helps people — especially when it comes to their
190
- health.
191
- </p>
192
-
193
- <h2 class="text-2xl font-semibold mb-4 text-[var(--tropical-indigo)]">
194
- Our Origin Story
195
- </h2>
196
- <p class="mb-4">
197
- This project started the way many great things do — with confusion and a
198
- “Wait, what?” moment. After reading a real medical report full of jargon
199
- and vague terms, we realized that even smart, curious people struggle to
200
- understand their own health info.
201
- </p>
202
- <p class="mb-8">
203
- So we decided to do something about it. CTRL + ALT + HEAL began as a
204
- small idea:<br />
205
- <em class="text-gray-500">“What if we made this easier to read?”</em
206
- ><br />
207
- That idea turned into a tool, then a platform — and now a growing
208
- project to make health literacy more accessible to everyone.
209
- </p>
210
-
211
- <h2 class="text-2xl font-semibold mb-4 text-[var(--tropical-indigo)]">
212
- What’s Next
213
- </h2>
214
- <p class="mb-4">
215
- We're just getting started. Here's what's on the roadmap:
216
- </p>
217
- <ul class="list-disc list-inside mb-8 space-y-2">
218
- <li>
219
- Support for more types of medical documents (e.g., imaging,
220
- prescriptions).
221
- </li>
222
- <li>A user-friendly dashboard to save and track reports over time.</li>
223
- <li>Mobile optimization and offline support.</li>
224
- </ul>
225
- <p class="mb-8">
226
- We're always building, always improving — and we’re listening. Got
227
- ideas? Let us know!
228
- </p>
229
-
230
- <h2 class="text-2xl font-semibold mb-4 text-[var(--tropical-indigo)]">
231
- Disclaimer
232
- </h2>
233
- <p class="text-sm text-gray-600">
234
- <strong>CTRL + ALT + HEAL</strong> does not replace professional medical
235
- advice, diagnosis, or treatment. Always consult with your healthcare
236
- provider — we just make it easier to <em>understand</em> what’s being
237
- said.
238
- </p>
239
- </section>
240
-
241
- <!-- Footer -->
242
- <footer class="bg-white py-8 mt-12 border-t border-[var(--wisteria)]">
243
- <div
244
- class="max-w-4xl mx-auto px-6 flex flex-col items-center justify-center text-center gap-6"
245
- >
246
- <p class="text-lg font-medium text-gray-700">
247
- Got Ideas? Feedback? Or just wanna Vibe with us?
248
- </p>
249
- <a
250
- href="mailto:cataanya77@gmail.com"
251
- class="inline-block btn-primary px-6 py-2 rounded-full"
252
- >
253
- Contact the Team
254
- </a>
255
- </div>
256
- </footer>
257
- </body>
258
- </html>
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <title>About Us | CTRL + ALT + HEAL</title>
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.4.120/pdf.min.js"></script>
9
+ <script src="https://cdn.jsdelivr.net/npm/tesseract.js@5.0.3/dist/tesseract.min.js"></script>
10
+ <link href="https://unpkg.com/aos@2.3.1/dist/aos.css" rel="stylesheet" />
11
+ <link
12
+ href="https://fonts.googleapis.com/css2?family=Rubik:wght@400;700&display=swap"
13
+ rel="stylesheet"
14
+ />
15
+
16
+ <style>
17
+ :root {
18
+ --tropical-indigo: rgb(120, 187, 242);
19
+ --wisteria: rgb(197, 217, 251);
20
+ --latte-cream: #ffffff;
21
+ }
22
+
23
+ body {
24
+ font-family: "Rubik", sans-serif;
25
+ background-color: var(--latte-cream);
26
+ color: #333;
27
+ }
28
+
29
+ .btn-primary {
30
+ background-color: var(--tropical-indigo);
31
+ color: white;
32
+ transition: background-color 0.3s ease;
33
+ }
34
+
35
+ .btn-primary:hover {
36
+ background-color: var(--wisteria);
37
+ color: #333;
38
+ }
39
+ </style>
40
+ </head>
41
+ <body class="min-h-screen">
42
+ <!-- Navbar -->
43
+ <nav
44
+ class="fixed top-0 left-0 w-full z-50 backdrop-blur-md bg-white/20 border-b border-white/30 shadow-md"
45
+ >
46
+ <div
47
+ class="max-w-6xl mx-auto px-6 py-4 flex justify-between items-center"
48
+ >
49
+ <!-- Logo -->
50
+ <a
51
+ href="index.html"
52
+ class="text-2xl font-bold hover:text-[var(--tropical-indigo)] transition"
53
+ >
54
+ CTRL + ALT + HEAL
55
+ </a>
56
+
57
+ <!-- Desktop Menu -->
58
+ <ul class="hidden md:flex space-x-6 font-medium text-gray-800">
59
+ <li><a href="index.html" class="nav-link">Home</a></li>
60
+ <li><a href="analyzer.html" class="nav-link">Analyzer</a></li>
61
+ <li><a href="profile.html" class="nav-link">Profile</a></li>
62
+ <li><a href="login.html" class="nav-link">Login</a></li>
63
+ <li><a href="about.html" class="nav-link">About</a></li>
64
+ </ul>
65
+
66
+ <!-- Hamburger Menu -->
67
+ <button id="hamburger" class="md:hidden text-[#000000] text-2xl">
68
+
69
+ </button>
70
+ </div>
71
+
72
+ <!-- Mobile Menu -->
73
+ <ul
74
+ id="mobile-menu"
75
+ class="hidden flex-col space-y-4 bg-white/30 backdrop-blur-lg border border-white/20 rounded-xl shadow-lg mt-2 p-4 mx-6 md:hidden"
76
+ >
77
+ <li>
78
+ <a
79
+ href="index.html"
80
+ class="block text-gray-800 hover:text-[var(--neon-green)]"
81
+ >Home</a
82
+ >
83
+ </li>
84
+ <li>
85
+ <a
86
+ href="analyzer.html"
87
+ class="block text-gray-800 hover:text-[var(--neon-green)]"
88
+ >Analyzer</a
89
+ >
90
+ </li>
91
+ <li>
92
+ <a
93
+ href="profile.html"
94
+ class="block text-gray-800 hover:text-[var(--neon-green)]"
95
+ >Profile</a
96
+ >
97
+ </li>
98
+ <li>
99
+ <a
100
+ href="login.html"
101
+ class="block text-gray-800 hover:text-[var(--neon-green)]"
102
+ >Login</a
103
+ >
104
+ </li>
105
+ <li>
106
+ <a
107
+ href="about.html"
108
+ class="block text-gray-800 hover:text-[var(--neon-green)]"
109
+ >About</a
110
+ >
111
+ </li>
112
+ </ul>
113
+ </nav>
114
+
115
+ <script>
116
+ const hamburger = document.getElementById("hamburger");
117
+ const mobileMenu = document.getElementById("mobile-menu");
118
+
119
+ hamburger.addEventListener("click", () => {
120
+ mobileMenu.classList.toggle("hidden");
121
+ });
122
+ </script>
123
+
124
+ <!-- About Section -->
125
+ <section id="about" class="max-w-3xl mx-auto px-6 py-12 pt-24 font-sans">
126
+ <h1 class="text-3xl md:text-4xl font-bold mb-6">
127
+ About
128
+ <span class="text-[var(--tropical-indigo)]">CTRL + ALT + HEAL</span>
129
+ </h1>
130
+
131
+ <p class="mb-4">
132
+ <strong>CTRL + ALT + HEAL</strong> is a web platform designed to
133
+ simplify medical reports and empower patients (and their families) to
134
+ actually <em>understand</em> what’s going on.
135
+ </p>
136
+
137
+ <p class="mb-4">
138
+ We take complicated medical language — the kind that sounds like it was
139
+ written by a robot with a thesaurus — and translate it into clear,
140
+ human-readable explanations. No more Googling your labs and spiraling.
141
+ </p>
142
+
143
+ <p class="mb-8">
144
+ Built by students passionate about medicine, coding, and accessibility,
145
+ CTRL + ALT + HEAL is a tool for anyone who’s ever looked at a test
146
+ result and thought,<br />
147
+ <em class="text-gray-500">“...Is this bad??”</em>
148
+ </p>
149
+
150
+ <hr class="my-8 border-[var(--wisteria)]" />
151
+
152
+ <h2 class="text-2xl font-semibold mb-4 text-[var(--tropical-indigo)]">
153
+ Our Mission
154
+ </h2>
155
+ <p class="mb-8">
156
+ To make medical knowledge understandable, actionable, and a little less
157
+ scary — no med degree required. We believe that information is power,
158
+ and everyone deserves access to it.
159
+ </p>
160
+
161
+ <h2 class="text-2xl font-semibold mb-4 text-[var(--tropical-indigo)]">
162
+ What We Do
163
+ </h2>
164
+ <ul class="list-disc list-inside mb-8 space-y-2">
165
+ <li>
166
+ <strong>Simplify medical reports</strong> using clear language and
167
+ explainers.
168
+ </li>
169
+ <li>
170
+ <strong>Break down each section line-by-line</strong>, so nothing gets
171
+ missed.
172
+ </li>
173
+ <li>
174
+ <strong>Provide helpful context</strong>: what’s normal, what might
175
+ need attention, and what you can ask your doctor.
176
+ </li>
177
+ <li>
178
+ <strong>Give next steps</strong> when possible, so you’re not left
179
+ hanging.
180
+ </li>
181
+ </ul>
182
+
183
+ <h2 class="text-2xl font-semibold mb-4 text-[var(--tropical-indigo)]">
184
+ Who We Are
185
+ </h2>
186
+ <p class="mb-8">
187
+ A team of curious students (and hopefully future healthcare pros!)
188
+ combining coding skills, science brains, and a love for clarity. We
189
+ believe in tech that helps people — especially when it comes to their
190
+ health.
191
+ </p>
192
+
193
+ <h2 class="text-2xl font-semibold mb-4 text-[var(--tropical-indigo)]">
194
+ Our Origin Story
195
+ </h2>
196
+ <p class="mb-4">
197
+ This project started the way many great things do — with confusion and a
198
+ “Wait, what?” moment. After reading a real medical report full of jargon
199
+ and vague terms, we realized that even smart, curious people struggle to
200
+ understand their own health info.
201
+ </p>
202
+ <p class="mb-8">
203
+ So we decided to do something about it. CTRL + ALT + HEAL began as a
204
+ small idea:<br />
205
+ <em class="text-gray-500">“What if we made this easier to read?”</em
206
+ ><br />
207
+ That idea turned into a tool, then a platform — and now a growing
208
+ project to make health literacy more accessible to everyone.
209
+ </p>
210
+
211
+ <h2 class="text-2xl font-semibold mb-4 text-[var(--tropical-indigo)]">
212
+ What’s Next
213
+ </h2>
214
+ <p class="mb-4">
215
+ We're just getting started. Here's what's on the roadmap:
216
+ </p>
217
+ <ul class="list-disc list-inside mb-8 space-y-2">
218
+ <li>
219
+ Support for more types of medical documents (e.g., imaging,
220
+ prescriptions).
221
+ </li>
222
+ <li>A user-friendly dashboard to save and track reports over time.</li>
223
+ <li>Mobile optimization and offline support.</li>
224
+ </ul>
225
+ <p class="mb-8">
226
+ We're always building, always improving — and we’re listening. Got
227
+ ideas? Let us know!
228
+ </p>
229
+
230
+ <h2 class="text-2xl font-semibold mb-4 text-[var(--tropical-indigo)]">
231
+ Disclaimer
232
+ </h2>
233
+ <p class="text-sm text-gray-600">
234
+ <strong>CTRL + ALT + HEAL</strong> does not replace professional medical
235
+ advice, diagnosis, or treatment. Always consult with your healthcare
236
+ provider — we just make it easier to <em>understand</em> what’s being
237
+ said.
238
+ </p>
239
+ </section>
240
+
241
+ <!-- Footer -->
242
+ <footer class="bg-white py-8 mt-12 border-t border-[var(--wisteria)]">
243
+ <div
244
+ class="max-w-4xl mx-auto px-6 flex flex-col items-center justify-center text-center gap-6"
245
+ >
246
+ <p class="text-lg font-medium text-gray-700">
247
+ Got Ideas? Feedback? Or just wanna Vibe with us?
248
+ </p>
249
+ <a
250
+ href="mailto:cataanya77@gmail.com"
251
+ class="inline-block btn-primary px-6 py-2 rounded-full"
252
+ >
253
+ Contact the Team
254
+ </a>
255
+ </div>
256
+ </footer>
257
+ </body>
258
+ </html>
analyzer.html → web/analyzer.html RENAMED
@@ -1,194 +1,194 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <title>Document Analyzer | CTRL + ALT + HEAL</title>
6
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
- <script src="https://cdn.tailwindcss.com"></script>
8
- </head>
9
- <body class="bg-[#F7F8F9] font-sans text-gray-800 min-h-screen">
10
-
11
- <!-- Navbar -->
12
- <nav class="bg-white border border-gray-200 px-6 py-4 mb-8">
13
- <div class="container mx-auto flex justify-between items-center">
14
- <a href="index.html" class="text-2xl font-bold text-[#6B9080]">CTRL + ALT + HEAL</a>
15
- <ul class="flex space-x-6 text-sm font-medium text-gray-700">
16
- <li><a href="index.html" class="hover:text-[#6B9080]">Home</a></li>
17
- <li><a href="analyzer.html" class="hover:text-[#6B9080]">Analyzer</a></li>
18
- <li><a href="profile.html" class="hover:text-[#6B9080]">Profile</a></li>
19
- <li><a href="login.html" class="hover:text-[#6B9080]">Login</a></li>
20
- <li><a href="about.html" class="hover:text-[#6B9080]">About Us</a></li>
21
- </ul>
22
- </div>
23
- </nav>
24
-
25
- <main class="max-w-5xl mx-auto px-4 mb-16">
26
- <!-- Upload & Score Section -->
27
- <div class="bg-white border border-gray-200 rounded-lg p-6 mb-8">
28
- <h2 class="text-xl font-semibold text-[#6B9080] mb-4">Upload & Analyze Your Medical PDF or Image</h2>
29
- <input type="file" id="pdf-upload" accept=".pdf, image/*"
30
- class="w-full mb-4 border border-gray-300 rounded px-3 py-2" />
31
- <input type="date" id="report-date"
32
- class="w-full mb-4 border border-gray-300 rounded px-3 py-2"
33
- placeholder="Report Date" />
34
- <button id="analyze-btn"
35
- class="bg-[#6B9080] text-white px-4 py-2 rounded hover:bg-[#5B7A6F]">
36
- Analyze with AI
37
- </button>
38
- <p id="loading" class="text-gray-600 mt-2">No file uploaded yet.</p>
39
- </div>
40
-
41
- <!-- Extracted Text -->
42
- <div class="bg-white border border-gray-200 rounded-lg p-6 mb-8">
43
- <h3 class="text-lg font-semibold text-[#6B9080] mb-3">Extracted Text</h3>
44
- <div id="text-output" class="whitespace-pre-wrap h-60 overflow-auto bg-[#FAFBFC] text-sm text-gray-800 border border-gray-200 rounded p-4">
45
- OCR results will appear here.
46
- </div>
47
- </div>
48
-
49
- <!-- AI Recommendations -->
50
- <div class="bg-white border border-gray-200 rounded-lg p-6 mb-8">
51
- <h3 class="text-lg font-semibold text-[#6B9080] mb-3">AI Recommendations</h3>
52
- <div id="recommendations-output" class="whitespace-pre-wrap h-60 overflow-auto bg-[#FAFBFC] text-sm text-gray-800 border border-gray-200 rounded p-4">
53
- Recommendations will appear here.
54
- </div>
55
- </div>
56
-
57
- <!-- QA Chatbot -->
58
- <div class="bg-white border border-gray-200 rounded-lg p-6 mb-8">
59
- <h3 class="text-lg font-semibold text-[#6B9080] mb-3">Ask Chatbot</h3>
60
- <div id="chat-output" class="space-y-2 h-48 overflow-auto bg-[#FAFBFC] text-sm text-gray-800 border border-gray-200 rounded p-4">
61
- <p><strong>Chatbot:</strong> Ask me something about your report</p>
62
- </div>
63
- <div class="flex mt-4 gap-2">
64
- <input type="text" id="user-question" placeholder="Ask a question..."
65
- class="flex-1 border border-gray-300 rounded px-3 py-2 focus:outline-none focus:ring-2 focus:ring-[#6B9080]" />
66
- <button id="ask-btn" class="bg-[#6B9080] text-white px-4 py-2 rounded hover:bg-[#5B7A6F]">
67
- Ask
68
- </button>
69
- </div>
70
- </div>
71
- </main>
72
-
73
- <script type="module">
74
- import { pipeline, env } from 'https://cdn.jsdelivr.net/npm/@xenova/transformers@2.6.0';
75
-
76
- const loadingEl = document.getElementById('loading');
77
- const textOutput = document.getElementById('text-output');
78
- const recsOutput = document.getElementById('recommendations-output');
79
- let extractedText = "";
80
-
81
- document.getElementById('pdf-upload').addEventListener('change', function() {
82
- loadingEl.textContent = this.files.length
83
- ? `File selected: ${this.files[0].name}`
84
- : 'No file uploaded yet.';
85
- });
86
-
87
- document.getElementById('analyze-btn').addEventListener('click', async () => {
88
- const file = document.getElementById('pdf-upload').files[0];
89
- const date = document.getElementById('report-date').value;
90
- if (!file) { loadingEl.textContent = "Please upload a file first."; return; }
91
- if (!date) { loadingEl.textContent = "Please select the report date."; return; }
92
-
93
- loadingEl.textContent = "Processing with AI...";
94
- textOutput.textContent = "";
95
- recsOutput.textContent = "";
96
-
97
- const formData = new FormData();
98
- formData.append('file', file);
99
- formData.append('model', 'bert');
100
- try {
101
- const res = await fetch('http://localhost:9000/analyze/', {
102
- method: 'POST', body: formData
103
- });
104
- if (!res.ok) throw new Error(await res.text());
105
- const data = await res.json();
106
-
107
- // OCR text
108
- extractedText = data.ocr_text || "";
109
- textOutput.textContent = extractedText;
110
-
111
-
112
- console.log("AI recs from backend:", data.resolutions);
113
- let recs = [];
114
- if (Array.isArray(data.resolutions)) {
115
- recs = data.resolutions;
116
- } else if (data.resolutions && typeof data.resolutions === 'object') {
117
- recs = [data.resolutions];
118
- }
119
-
120
- if (recs.length) {
121
- recsOutput.innerHTML = `
122
- <ul class="list-disc list-inside space-y-4">
123
- ${recs.map((rec, i) => `
124
- <li>
125
- <strong>Finding ${i+1}:</strong> ${rec.findings} (Severity: ${rec.severity})
126
- <ul class="list-disc list-inside ml-6 space-y-1">
127
- <li><em>Recommendations:</em>
128
- <ul class="list-disc list-inside ml-6">
129
- ${(rec.recommendations || []).map(r=>`<li>${r}</li>`).join('')}
130
- </ul>
131
- </li>
132
- <li><em>Treatment:</em> ${rec.treatment_suggestions || 'Not available'}</li>
133
- <li><em>Home Care:</em>
134
- <ul class="list-disc list-inside ml-6">
135
- ${(rec.home_care_guidance || []).map(r=>`<li>${r}</li>`).join('')}
136
- </ul>
137
- </li>
138
- ${rec.info_link
139
- ? `<li><a href="${rec.info_link}" target="_blank" class="text-blue-600 underline">Learn more</a></li>`
140
- : ''}
141
- </ul>
142
- </li>
143
- `).join('')}
144
- </ul>
145
- `;
146
- } else {
147
- recsOutput.textContent = "No recommendations found.";
148
- }
149
-
150
- } catch (err) {
151
- console.error(err);
152
- loadingEl.textContent = "Error during analysis: " + err.message;
153
- return;
154
- }
155
-
156
- // fake score(random)
157
- try {
158
- const scoreRes = await fetch('http://localhost:9000/api/analyze-health', {
159
- method: 'POST',
160
- headers: {'Content-Type':'application/json'},
161
- body: JSON.stringify({ text: extractedText })
162
- });
163
- if (!scoreRes.ok) throw new Error(await scoreRes.text());
164
- const { score, rationale } = await scoreRes.json();
165
- loadingEl.textContent = `Last health score: ${score} (${rationale})`;
166
-
167
-
168
- const progressData = JSON.parse(localStorage.getItem('progressData') || '[]');
169
- progressData.push({ date: new Date().toISOString().split('T')[0], score });
170
- localStorage.setItem('progressData', JSON.stringify(progressData));
171
-
172
- } catch (err) {
173
- console.error(err);
174
- loadingEl.textContent = "Error during scoring: " + err.message;
175
- }
176
-
177
- //q&a chatbo t
178
- document.getElementById('ask-btn').onclick = async () => {
179
- const q = document.getElementById('user-question').value.trim();
180
- if (!q) return;
181
- const chat = document.getElementById('chat-output');
182
- chat.innerHTML += `<p><strong>You:</strong> ${q}</p>`;
183
- chat.scrollTop = chat.scrollHeight;
184
- env.allowLocalModels = false;
185
- const qa = await pipeline('question-answering','Xenova/distilbert-base-uncased-distilled-squad');
186
- const out = await qa(q, extractedText);
187
- chat.innerHTML += `<p><strong>Chatbot:</strong> ${out.answer}</p>`;
188
- document.getElementById('user-question').value = '';
189
- chat.scrollTop = chat.scrollHeight;
190
- };
191
- });
192
- </script>
193
- </body>
194
- </html>
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <title>Document Analyzer | CTRL + ALT + HEAL</title>
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ </head>
9
+ <body class="bg-[#F7F8F9] font-sans text-gray-800 min-h-screen">
10
+
11
+ <!-- Navbar -->
12
+ <nav class="bg-white border border-gray-200 px-6 py-4 mb-8">
13
+ <div class="container mx-auto flex justify-between items-center">
14
+ <a href="index.html" class="text-2xl font-bold text-[#6B9080]">CTRL + ALT + HEAL</a>
15
+ <ul class="flex space-x-6 text-sm font-medium text-gray-700">
16
+ <li><a href="index.html" class="hover:text-[#6B9080]">Home</a></li>
17
+ <li><a href="analyzer.html" class="hover:text-[#6B9080]">Analyzer</a></li>
18
+ <li><a href="profile.html" class="hover:text-[#6B9080]">Profile</a></li>
19
+ <li><a href="login.html" class="hover:text-[#6B9080]">Login</a></li>
20
+ <li><a href="about.html" class="hover:text-[#6B9080]">About Us</a></li>
21
+ </ul>
22
+ </div>
23
+ </nav>
24
+
25
+ <main class="max-w-5xl mx-auto px-4 mb-16">
26
+ <!-- Upload & Score Section -->
27
+ <div class="bg-white border border-gray-200 rounded-lg p-6 mb-8">
28
+ <h2 class="text-xl font-semibold text-[#6B9080] mb-4">Upload & Analyze Your Medical PDF or Image</h2>
29
+ <input type="file" id="pdf-upload" accept=".pdf, image/*"
30
+ class="w-full mb-4 border border-gray-300 rounded px-3 py-2" />
31
+ <input type="date" id="report-date"
32
+ class="w-full mb-4 border border-gray-300 rounded px-3 py-2"
33
+ placeholder="Report Date" />
34
+ <button id="analyze-btn"
35
+ class="bg-[#6B9080] text-white px-4 py-2 rounded hover:bg-[#5B7A6F]">
36
+ Analyze with AI
37
+ </button>
38
+ <p id="loading" class="text-gray-600 mt-2">No file uploaded yet.</p>
39
+ </div>
40
+
41
+ <!-- Extracted Text -->
42
+ <div class="bg-white border border-gray-200 rounded-lg p-6 mb-8">
43
+ <h3 class="text-lg font-semibold text-[#6B9080] mb-3">Extracted Text</h3>
44
+ <div id="text-output" class="whitespace-pre-wrap h-60 overflow-auto bg-[#FAFBFC] text-sm text-gray-800 border border-gray-200 rounded p-4">
45
+ OCR results will appear here.
46
+ </div>
47
+ </div>
48
+
49
+ <!-- AI Recommendations -->
50
+ <div class="bg-white border border-gray-200 rounded-lg p-6 mb-8">
51
+ <h3 class="text-lg font-semibold text-[#6B9080] mb-3">AI Recommendations</h3>
52
+ <div id="recommendations-output" class="whitespace-pre-wrap h-60 overflow-auto bg-[#FAFBFC] text-sm text-gray-800 border border-gray-200 rounded p-4">
53
+ Recommendations will appear here.
54
+ </div>
55
+ </div>
56
+
57
+ <!-- QA Chatbot -->
58
+ <div class="bg-white border border-gray-200 rounded-lg p-6 mb-8">
59
+ <h3 class="text-lg font-semibold text-[#6B9080] mb-3">Ask Chatbot</h3>
60
+ <div id="chat-output" class="space-y-2 h-48 overflow-auto bg-[#FAFBFC] text-sm text-gray-800 border border-gray-200 rounded p-4">
61
+ <p><strong>Chatbot:</strong> Ask me something about your report</p>
62
+ </div>
63
+ <div class="flex mt-4 gap-2">
64
+ <input type="text" id="user-question" placeholder="Ask a question..."
65
+ class="flex-1 border border-gray-300 rounded px-3 py-2 focus:outline-none focus:ring-2 focus:ring-[#6B9080]" />
66
+ <button id="ask-btn" class="bg-[#6B9080] text-white px-4 py-2 rounded hover:bg-[#5B7A6F]">
67
+ Ask
68
+ </button>
69
+ </div>
70
+ </div>
71
+ </main>
72
+
73
+ <script type="module">
74
+ import { pipeline, env } from 'https://cdn.jsdelivr.net/npm/@xenova/transformers@2.6.0';
75
+
76
+ const loadingEl = document.getElementById('loading');
77
+ const textOutput = document.getElementById('text-output');
78
+ const recsOutput = document.getElementById('recommendations-output');
79
+ let extractedText = "";
80
+
81
+ document.getElementById('pdf-upload').addEventListener('change', function() {
82
+ loadingEl.textContent = this.files.length
83
+ ? `File selected: ${this.files[0].name}`
84
+ : 'No file uploaded yet.';
85
+ });
86
+
87
+ document.getElementById('analyze-btn').addEventListener('click', async () => {
88
+ const file = document.getElementById('pdf-upload').files[0];
89
+ const date = document.getElementById('report-date').value;
90
+ if (!file) { loadingEl.textContent = "Please upload a file first."; return; }
91
+ if (!date) { loadingEl.textContent = "Please select the report date."; return; }
92
+
93
+ loadingEl.textContent = "Processing with AI...";
94
+ textOutput.textContent = "";
95
+ recsOutput.textContent = "";
96
+
97
+ const formData = new FormData();
98
+ formData.append('file', file);
99
+ formData.append('model', 'bert');
100
+ try {
101
+ const res = await fetch('http://localhost:9000/analyze/', {
102
+ method: 'POST', body: formData
103
+ });
104
+ if (!res.ok) throw new Error(await res.text());
105
+ const data = await res.json();
106
+
107
+ // OCR text
108
+ extractedText = data.ocr_text || "";
109
+ textOutput.textContent = extractedText;
110
+
111
+
112
+ console.log("AI recs from backend:", data.resolutions);
113
+ let recs = [];
114
+ if (Array.isArray(data.resolutions)) {
115
+ recs = data.resolutions;
116
+ } else if (data.resolutions && typeof data.resolutions === 'object') {
117
+ recs = [data.resolutions];
118
+ }
119
+
120
+ if (recs.length) {
121
+ recsOutput.innerHTML = `
122
+ <ul class="list-disc list-inside space-y-4">
123
+ ${recs.map((rec, i) => `
124
+ <li>
125
+ <strong>Finding ${i+1}:</strong> ${rec.findings} (Severity: ${rec.severity})
126
+ <ul class="list-disc list-inside ml-6 space-y-1">
127
+ <li><em>Recommendations:</em>
128
+ <ul class="list-disc list-inside ml-6">
129
+ ${(rec.recommendations || []).map(r=>`<li>${r}</li>`).join('')}
130
+ </ul>
131
+ </li>
132
+ <li><em>Treatment:</em> ${rec.treatment_suggestions || 'Not available'}</li>
133
+ <li><em>Home Care:</em>
134
+ <ul class="list-disc list-inside ml-6">
135
+ ${(rec.home_care_guidance || []).map(r=>`<li>${r}</li>`).join('')}
136
+ </ul>
137
+ </li>
138
+ ${rec.info_link
139
+ ? `<li><a href="${rec.info_link}" target="_blank" class="text-blue-600 underline">Learn more</a></li>`
140
+ : ''}
141
+ </ul>
142
+ </li>
143
+ `).join('')}
144
+ </ul>
145
+ `;
146
+ } else {
147
+ recsOutput.textContent = "No recommendations found.";
148
+ }
149
+
150
+ } catch (err) {
151
+ console.error(err);
152
+ loadingEl.textContent = "Error during analysis: " + err.message;
153
+ return;
154
+ }
155
+
156
+ // fake score(random)
157
+ try {
158
+ const scoreRes = await fetch('http://localhost:9000/api/analyze-health', {
159
+ method: 'POST',
160
+ headers: {'Content-Type':'application/json'},
161
+ body: JSON.stringify({ text: extractedText })
162
+ });
163
+ if (!scoreRes.ok) throw new Error(await scoreRes.text());
164
+ const { score, rationale } = await scoreRes.json();
165
+ loadingEl.textContent = `Last health score: ${score} (${rationale})`;
166
+
167
+
168
+ const progressData = JSON.parse(localStorage.getItem('progressData') || '[]');
169
+ progressData.push({ date: new Date().toISOString().split('T')[0], score });
170
+ localStorage.setItem('progressData', JSON.stringify(progressData));
171
+
172
+ } catch (err) {
173
+ console.error(err);
174
+ loadingEl.textContent = "Error during scoring: " + err.message;
175
+ }
176
+
177
+ //q&a chatbo t
178
+ document.getElementById('ask-btn').onclick = async () => {
179
+ const q = document.getElementById('user-question').value.trim();
180
+ if (!q) return;
181
+ const chat = document.getElementById('chat-output');
182
+ chat.innerHTML += `<p><strong>You:</strong> ${q}</p>`;
183
+ chat.scrollTop = chat.scrollHeight;
184
+ env.allowLocalModels = false;
185
+ const qa = await pipeline('question-answering','Xenova/distilbert-base-uncased-distilled-squad');
186
+ const out = await qa(q, extractedText);
187
+ chat.innerHTML += `<p><strong>Chatbot:</strong> ${out.answer}</p>`;
188
+ document.getElementById('user-question').value = '';
189
+ chat.scrollTop = chat.scrollHeight;
190
+ };
191
+ });
192
+ </script>
193
+ </body>
194
+ </html>
analyzer_new.html → web/analyzer_new.html RENAMED
File without changes
index.html → web/index.html RENAMED
@@ -1,336 +1,336 @@
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>CTRL + ALT + HEAL</title>
7
- <script src="https://cdn.tailwindcss.com"></script>
8
- <link
9
- href="https://fonts.googleapis.com/css2?family=Rubik:wght@400;700&display=swap"
10
- rel="stylesheet"
11
- />
12
- <style>
13
- :root {
14
- --tropical-indigo: rgb(120, 187, 242);
15
- --wisteria: rgb(197, 217, 251);
16
- --latte-cream: #ffffff;
17
- }
18
-
19
- body {
20
- font-family: "Rubik", sans-serif;
21
- background-color: var(--latte-cream);
22
- color: #333;
23
- }
24
-
25
- .fade-in {
26
- opacity: 0;
27
- transform: translateY(30px);
28
- transition: all 0.8s ease-out;
29
- }
30
- .fade-in.show {
31
- opacity: 1;
32
- transform: translateY(0);
33
- }
34
-
35
- .glass-card {
36
- background: rgba(162, 160, 160, 0.075);
37
- backdrop-filter: blur(12px);
38
- border-radius: 1rem;
39
- border: 1px solid rgba(255, 255, 255, 0.3);
40
- padding: 2rem;
41
- text-align: center;
42
- transition: transform 0.3s ease, box-shadow 0.3s ease;
43
- }
44
- .glass-card:hover {
45
- transform: translateY(-5px);
46
- box-shadow: 0 15px 25px rgba(0, 0, 0, 0.2);
47
- }
48
-
49
- .nav-link {
50
- position: relative;
51
- padding-bottom: 4px;
52
- transition: color 0.3s;
53
- }
54
- .nav-link::after {
55
- content: "";
56
- position: absolute;
57
- width: 0%;
58
- height: 2px;
59
- bottom: 0;
60
- left: 0;
61
- background-color: var(--tropical-indigo);
62
- transition: width 0.3s ease;
63
- }
64
- .nav-link:hover::after {
65
- width: 100%;
66
- }
67
-
68
- .parallax {
69
- background-attachment: fixed;
70
- background-size: cover;
71
- background-position: center;
72
- position: relative;
73
- }
74
-
75
- /* Typing effect styles */
76
- #typed-heading,
77
- #typed-paragraph {
78
- overflow: hidden;
79
- white-space: nowrap;
80
- border-right: 2px solid var(--tropical-indigo);
81
- }
82
- </style>
83
- </head>
84
- <body>
85
- <!-- NAVBAR -->
86
- <nav
87
- class="fixed top-0 left-0 w-full z-50 backdrop-blur-md bg-white/20 border-b border-white/30 shadow-md"
88
- >
89
- <div
90
- class="max-w-6xl mx-auto px-6 py-4 flex justify-between items-center"
91
- >
92
- <!-- Logo -->
93
- <a
94
- href="index.html"
95
- class="text-2xl font-bold text-[#FOE3CE hover:text-[var(--tropical-indigo)] transition"
96
- >
97
- CTRL + ALT + HEAL
98
- </a>
99
-
100
- <!-- Desktop Menu -->
101
- <ul class="hidden md:flex space-x-6 font-medium text-gray-800">
102
- <li><a href="index.html" class="nav-link">Home</a></li>
103
- <li><a href="analyzer.html" class="nav-link">Analyzer</a></li>
104
- <li><a href="profile.html" class="nav-link">Profile</a></li>
105
- <li><a href="login.html" class="nav-link">Login</a></li>
106
- <li><a href="about.html" class="nav-link">About</a></li>
107
- </ul>
108
-
109
- <!-- Hamburger Menu -->
110
- <button
111
- id="hamburger"
112
- class="md:hidden text-[var(--latte-cream)] text-2xl"
113
- >
114
-
115
- </button>
116
- </div>
117
-
118
- <!-- Mobile Menu -->
119
- <ul
120
- id="mobile-menu"
121
- class="hidden flex-col space-y-4 bg-white/30 backdrop-blur-lg border border-white/20 rounded-xl shadow-lg mt-2 p-4 mx-6 md:hidden"
122
- >
123
- <li>
124
- <a
125
- href="index.html"
126
- class="block text-gray-800 hover:text-[var(--neon-green)]"
127
- >Home</a
128
- >
129
- </li>
130
- <li>
131
- <a
132
- href="analyzer.html"
133
- class="block text-gray-800 hover:text-[var(--neon-green)]"
134
- >Analyzer</a
135
- >
136
- </li>
137
- <li>
138
- <a
139
- href="profile.html"
140
- class="block text-gray-800 hover:text-[var(--neon-green)]"
141
- >Profile</a
142
- >
143
- </li>
144
- <li>
145
- <a
146
- href="login.html"
147
- class="block text-gray-800 hover:text-[var(--neon-green)]"
148
- >Login</a
149
- >
150
- </li>
151
- <li>
152
- <a
153
- href="about.html"
154
- class="block text-gray-800 hover:text-[var(--neon-green)]"
155
- >About</a
156
- >
157
- </li>
158
- </ul>
159
- </nav>
160
-
161
- <script>
162
- const hamburger = document.getElementById("hamburger");
163
- const mobileMenu = document.getElementById("mobile-menu");
164
-
165
- hamburger.addEventListener("click", () => {
166
- mobileMenu.classList.toggle("hidden");
167
- });
168
- </script>
169
-
170
- <!-- HERO SECTION -->
171
- <section
172
- class="relative min-h-[600px] flex items-center justify-center"
173
- style="
174
- background-image: url('https://videos.openai.com/vg-assets/assets%2Ftask_01k2qzfsscev8vmftcka1wp2et%2F1755299042_img_1.webp?st=2025-08-15T21%3A17%3A52Z&se=2025-08-21T22%3A17%3A52Z&sks=b&skt=2025-08-15T21%3A17%3A52Z&ske=2025-08-21T22%3A17%3A52Z&sktid=a48cca56-e6da-484e-a814-9c849652bcb3&skoid=3d249c53-07fa-4ba4-9b65-0bf8eb4ea46a&skv=2019-02-02&sv=2018-11-09&sr=b&sp=r&spr=https%2Chttp&sig=j0aFWc%2BchHFLtaa8JPylXkDFsrtP8zazpKyO8Edy5n8%3D&az=oaivgprodscus');
175
- background-size: cover;
176
- background-position: center;
177
- "
178
- >
179
- <div class="absolute inset-0 bg-black/40"></div>
180
- <div class="relative z-10 text-center px-6 fade-in">
181
- <h1 class="text-5xl md:text-6xl font-bold text-white mb-4">
182
- CTRL + ALT + HEAL
183
- </h1>
184
- <p class="text-lg text-gray-200 mb-2">
185
- From medical chaos to clarity. Upload your report, get real answers —
186
- fast.
187
- </p>
188
- <p class="text-sm text-gray-300 mb-6">
189
- No stress, no spiraling. Just answers that feel human.
190
- </p>
191
- <a href="login.html"
192
- ><button
193
- class="bg-[var(--tropical-indigo)] hover:bg-[var(--wisteria)] text-white px-8 py-3 rounded-lg shadow-lg transition"
194
- >
195
- Sign Up / Login
196
- </button></a
197
- >
198
- </div>
199
- </section>
200
-
201
- <!-- FEATURES -->
202
- <section class="py-20 bg-[var(--latte-cream)]">
203
- <div class="max-w-6xl mx-auto px-6 grid md:grid-cols-3 gap-8 fade-in">
204
- <div class="glass-card">
205
- <h3 class="text-2xl font-bold text-[var(--tropical-indigo)] mb-2">
206
- Fast Results
207
- </h3>
208
- <p>Upload your report and get human-readable answers instantly.</p>
209
- </div>
210
- <div class="glass-card">
211
- <h3 class="text-2xl font-bold text-[var(--tropical-indigo)] mb-2">
212
- Clear Language
213
- </h3>
214
- <p>No medical jargon, just plain language you can understand.</p>
215
- </div>
216
- <div class="glass-card">
217
- <h3 class="text-2xl font-bold text-[var(--tropical-indigo)] mb-2">
218
- Actionable Steps
219
- </h3>
220
- <p>Know what to do next without the stress and confusion.</p>
221
- </div>
222
- </div>
223
- </section>
224
-
225
- <!-- PARALLAX INFO SECTION -->
226
- <section
227
- class="relative h-[200px] flex items-center justify-center text-center text-white parallax"
228
- >
229
- <div class="absolute inset-0 bg-black/40"></div>
230
- <div class="relative z-10 px-6 fade-in">
231
- <h2 id="typed-heading" class="text-4xl font-bold mb-4"></h2>
232
- <p id="typed-paragraph" class="text-lg max-w-xl mx-auto"></p>
233
- </div>
234
- </section>
235
-
236
- <!-- BEEN THERE -->
237
- <section class="py-20 bg-[var(--latte-cream)] fade-in">
238
- <div
239
- class="max-w-6xl mx-auto px-6 grid md:grid-cols-2 gap-12 items-center"
240
- >
241
- <div>
242
- <h3 class="text-3xl font-bold text-[var(--tropical-indigo)] mb-4">
243
- Been There.
244
- </h3>
245
- <p class="mb-4">
246
- That’s exactly why we built this app — to stop the health spiral
247
- before it even starts. We know what it’s like to open a medical
248
- report and immediately feel overwhelmed. Weird abbreviations.
249
- Numbers with no context. Pages that feel like they were written for
250
- robots, not real people. It’s confusing, it’s stressful, and it’s
251
- usually a late‐night Google rabbit hole that somehow ends in you
252
- thinking you’ve got 3 rare conditions and a 2-day countdown.
253
- </p>
254
- <p>
255
- So we made something better. Just upload your report. We’ll break it
256
- down into plain, human language. We’ll highlight what actually
257
- matters, skip the jargon, and explain everything in a way that
258
- actually makes sense. Most importantly, we’ll give you real,
259
- practical steps — no guessing, no spiraling. You don’t need a
260
- medical degree to understand your own health. You just need the
261
- right guide. That’s us.
262
- </p>
263
- </div>
264
- <div class="w-full h-80 rounded-lg overflow-hidden shadow-lg">
265
- <img
266
- src="https://i.pinimg.com/originals/44/c7/c1/44c7c1f3fbd68b2151c37af5f08198f1.gif"
267
- class="object-cover w-full h-full rounded-lg"
268
- />
269
- </div>
270
- </div>
271
- </section>
272
-
273
- <!-- FOOTER -->
274
- <footer class="py-12 bg-[var(--wisteria)] text-white fade-in">
275
- <div
276
- class="max-w-6xl mx-auto px-6 flex flex-col md:flex-row justify-between items-center"
277
- >
278
- <p>&copy; 2025 CTRL + ALT + HEAL. All rights reserved.</p>
279
- <div class="flex space-x-4 mt-4 md:mt-0">
280
- <a href="#" class="hover:underline">Privacy Policy</a>
281
- <a href="#" class="hover:underline">Terms of Service</a>
282
- </div>
283
- </div>
284
- </footer>
285
-
286
- <script>
287
- // Fade-in on scroll
288
- const fadeObserver = new IntersectionObserver(
289
- (entries) => {
290
- entries.forEach((entry) => {
291
- if (entry.isIntersecting) entry.target.classList.add("show");
292
- });
293
- },
294
- { threshold: 0.1 }
295
- );
296
- document
297
- .querySelectorAll(".fade-in")
298
- .forEach((el) => fadeObserver.observe(el));
299
-
300
- // Typing effect on scroll
301
- const typeObserver = new IntersectionObserver(
302
- (entries) => {
303
- entries.forEach((entry) => {
304
- if (entry.isIntersecting) {
305
- typeText("typed-heading", "Your Health, Your Clarity", 80);
306
- typeText(
307
- "typed-paragraph",
308
- "We make complex medical reports simple and easy to understand.",
309
- 30
310
- );
311
- typeObserver.unobserve(entry.target);
312
- }
313
- });
314
- },
315
- { threshold: 0.5 }
316
- );
317
-
318
- typeObserver.observe(
319
- document.querySelector("#typed-heading").parentElement
320
- );
321
-
322
- function typeText(id, text, speed) {
323
- const el = document.getElementById(id);
324
- let i = 0;
325
- function type() {
326
- if (i < text.length) {
327
- el.innerHTML += text.charAt(i);
328
- i++;
329
- setTimeout(type, speed);
330
- }
331
- }
332
- type();
333
- }
334
- </script>
335
- </body>
336
- </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>CTRL + ALT + HEAL</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link
9
+ href="https://fonts.googleapis.com/css2?family=Rubik:wght@400;700&display=swap"
10
+ rel="stylesheet"
11
+ />
12
+ <style>
13
+ :root {
14
+ --tropical-indigo: rgb(120, 187, 242);
15
+ --wisteria: rgb(197, 217, 251);
16
+ --latte-cream: #ffffff;
17
+ }
18
+
19
+ body {
20
+ font-family: "Rubik", sans-serif;
21
+ background-color: var(--latte-cream);
22
+ color: #333;
23
+ }
24
+
25
+ .fade-in {
26
+ opacity: 0;
27
+ transform: translateY(30px);
28
+ transition: all 0.8s ease-out;
29
+ }
30
+ .fade-in.show {
31
+ opacity: 1;
32
+ transform: translateY(0);
33
+ }
34
+
35
+ .glass-card {
36
+ background: rgba(162, 160, 160, 0.075);
37
+ backdrop-filter: blur(12px);
38
+ border-radius: 1rem;
39
+ border: 1px solid rgba(255, 255, 255, 0.3);
40
+ padding: 2rem;
41
+ text-align: center;
42
+ transition: transform 0.3s ease, box-shadow 0.3s ease;
43
+ }
44
+ .glass-card:hover {
45
+ transform: translateY(-5px);
46
+ box-shadow: 0 15px 25px rgba(0, 0, 0, 0.2);
47
+ }
48
+
49
+ .nav-link {
50
+ position: relative;
51
+ padding-bottom: 4px;
52
+ transition: color 0.3s;
53
+ }
54
+ .nav-link::after {
55
+ content: "";
56
+ position: absolute;
57
+ width: 0%;
58
+ height: 2px;
59
+ bottom: 0;
60
+ left: 0;
61
+ background-color: var(--tropical-indigo);
62
+ transition: width 0.3s ease;
63
+ }
64
+ .nav-link:hover::after {
65
+ width: 100%;
66
+ }
67
+
68
+ .parallax {
69
+ background-attachment: fixed;
70
+ background-size: cover;
71
+ background-position: center;
72
+ position: relative;
73
+ }
74
+
75
+ /* Typing effect styles */
76
+ #typed-heading,
77
+ #typed-paragraph {
78
+ overflow: hidden;
79
+ white-space: nowrap;
80
+ border-right: 2px solid var(--tropical-indigo);
81
+ }
82
+ </style>
83
+ </head>
84
+ <body>
85
+ <!-- NAVBAR -->
86
+ <nav
87
+ class="fixed top-0 left-0 w-full z-50 backdrop-blur-md bg-white/20 border-b border-white/30 shadow-md"
88
+ >
89
+ <div
90
+ class="max-w-6xl mx-auto px-6 py-4 flex justify-between items-center"
91
+ >
92
+ <!-- Logo -->
93
+ <a
94
+ href="index.html"
95
+ class="text-2xl font-bold text-[#FOE3CE hover:text-[var(--tropical-indigo)] transition"
96
+ >
97
+ CTRL + ALT + HEAL
98
+ </a>
99
+
100
+ <!-- Desktop Menu -->
101
+ <ul class="hidden md:flex space-x-6 font-medium text-gray-800">
102
+ <li><a href="index.html" class="nav-link">Home</a></li>
103
+ <li><a href="analyzer.html" class="nav-link">Analyzer</a></li>
104
+ <li><a href="profile.html" class="nav-link">Profile</a></li>
105
+ <li><a href="login.html" class="nav-link">Login</a></li>
106
+ <li><a href="about.html" class="nav-link">About</a></li>
107
+ </ul>
108
+
109
+ <!-- Hamburger Menu -->
110
+ <button
111
+ id="hamburger"
112
+ class="md:hidden text-[var(--latte-cream)] text-2xl"
113
+ >
114
+
115
+ </button>
116
+ </div>
117
+
118
+ <!-- Mobile Menu -->
119
+ <ul
120
+ id="mobile-menu"
121
+ class="hidden flex-col space-y-4 bg-white/30 backdrop-blur-lg border border-white/20 rounded-xl shadow-lg mt-2 p-4 mx-6 md:hidden"
122
+ >
123
+ <li>
124
+ <a
125
+ href="index.html"
126
+ class="block text-gray-800 hover:text-[var(--neon-green)]"
127
+ >Home</a
128
+ >
129
+ </li>
130
+ <li>
131
+ <a
132
+ href="analyzer.html"
133
+ class="block text-gray-800 hover:text-[var(--neon-green)]"
134
+ >Analyzer</a
135
+ >
136
+ </li>
137
+ <li>
138
+ <a
139
+ href="profile.html"
140
+ class="block text-gray-800 hover:text-[var(--neon-green)]"
141
+ >Profile</a
142
+ >
143
+ </li>
144
+ <li>
145
+ <a
146
+ href="login.html"
147
+ class="block text-gray-800 hover:text-[var(--neon-green)]"
148
+ >Login</a
149
+ >
150
+ </li>
151
+ <li>
152
+ <a
153
+ href="about.html"
154
+ class="block text-gray-800 hover:text-[var(--neon-green)]"
155
+ >About</a
156
+ >
157
+ </li>
158
+ </ul>
159
+ </nav>
160
+
161
+ <script>
162
+ const hamburger = document.getElementById("hamburger");
163
+ const mobileMenu = document.getElementById("mobile-menu");
164
+
165
+ hamburger.addEventListener("click", () => {
166
+ mobileMenu.classList.toggle("hidden");
167
+ });
168
+ </script>
169
+
170
+ <!-- HERO SECTION -->
171
+ <section
172
+ class="relative min-h-[600px] flex items-center justify-center"
173
+ style="
174
+ background-image: url('https://videos.openai.com/vg-assets/assets%2Ftask_01k2qzfsscev8vmftcka1wp2et%2F1755299042_img_1.webp?st=2025-08-15T21%3A17%3A52Z&se=2025-08-21T22%3A17%3A52Z&sks=b&skt=2025-08-15T21%3A17%3A52Z&ske=2025-08-21T22%3A17%3A52Z&sktid=a48cca56-e6da-484e-a814-9c849652bcb3&skoid=3d249c53-07fa-4ba4-9b65-0bf8eb4ea46a&skv=2019-02-02&sv=2018-11-09&sr=b&sp=r&spr=https%2Chttp&sig=j0aFWc%2BchHFLtaa8JPylXkDFsrtP8zazpKyO8Edy5n8%3D&az=oaivgprodscus');
175
+ background-size: cover;
176
+ background-position: center;
177
+ "
178
+ >
179
+ <div class="absolute inset-0 bg-black/40"></div>
180
+ <div class="relative z-10 text-center px-6 fade-in">
181
+ <h1 class="text-5xl md:text-6xl font-bold text-white mb-4">
182
+ CTRL + ALT + HEAL
183
+ </h1>
184
+ <p class="text-lg text-gray-200 mb-2">
185
+ From medical chaos to clarity. Upload your report, get real answers —
186
+ fast.
187
+ </p>
188
+ <p class="text-sm text-gray-300 mb-6">
189
+ No stress, no spiraling. Just answers that feel human.
190
+ </p>
191
+ <a href="login.html"
192
+ ><button
193
+ class="bg-[var(--tropical-indigo)] hover:bg-[var(--wisteria)] text-white px-8 py-3 rounded-lg shadow-lg transition"
194
+ >
195
+ Sign Up / Login
196
+ </button></a
197
+ >
198
+ </div>
199
+ </section>
200
+
201
+ <!-- FEATURES -->
202
+ <section class="py-20 bg-[var(--latte-cream)]">
203
+ <div class="max-w-6xl mx-auto px-6 grid md:grid-cols-3 gap-8 fade-in">
204
+ <div class="glass-card">
205
+ <h3 class="text-2xl font-bold text-[var(--tropical-indigo)] mb-2">
206
+ Fast Results
207
+ </h3>
208
+ <p>Upload your report and get human-readable answers instantly.</p>
209
+ </div>
210
+ <div class="glass-card">
211
+ <h3 class="text-2xl font-bold text-[var(--tropical-indigo)] mb-2">
212
+ Clear Language
213
+ </h3>
214
+ <p>No medical jargon, just plain language you can understand.</p>
215
+ </div>
216
+ <div class="glass-card">
217
+ <h3 class="text-2xl font-bold text-[var(--tropical-indigo)] mb-2">
218
+ Actionable Steps
219
+ </h3>
220
+ <p>Know what to do next without the stress and confusion.</p>
221
+ </div>
222
+ </div>
223
+ </section>
224
+
225
+ <!-- PARALLAX INFO SECTION -->
226
+ <section
227
+ class="relative h-[200px] flex items-center justify-center text-center text-white parallax"
228
+ >
229
+ <div class="absolute inset-0 bg-black/40"></div>
230
+ <div class="relative z-10 px-6 fade-in">
231
+ <h2 id="typed-heading" class="text-4xl font-bold mb-4"></h2>
232
+ <p id="typed-paragraph" class="text-lg max-w-xl mx-auto"></p>
233
+ </div>
234
+ </section>
235
+
236
+ <!-- BEEN THERE -->
237
+ <section class="py-20 bg-[var(--latte-cream)] fade-in">
238
+ <div
239
+ class="max-w-6xl mx-auto px-6 grid md:grid-cols-2 gap-12 items-center"
240
+ >
241
+ <div>
242
+ <h3 class="text-3xl font-bold text-[var(--tropical-indigo)] mb-4">
243
+ Been There.
244
+ </h3>
245
+ <p class="mb-4">
246
+ That’s exactly why we built this app — to stop the health spiral
247
+ before it even starts. We know what it’s like to open a medical
248
+ report and immediately feel overwhelmed. Weird abbreviations.
249
+ Numbers with no context. Pages that feel like they were written for
250
+ robots, not real people. It’s confusing, it’s stressful, and it’s
251
+ usually a late‐night Google rabbit hole that somehow ends in you
252
+ thinking you’ve got 3 rare conditions and a 2-day countdown.
253
+ </p>
254
+ <p>
255
+ So we made something better. Just upload your report. We’ll break it
256
+ down into plain, human language. We’ll highlight what actually
257
+ matters, skip the jargon, and explain everything in a way that
258
+ actually makes sense. Most importantly, we’ll give you real,
259
+ practical steps — no guessing, no spiraling. You don’t need a
260
+ medical degree to understand your own health. You just need the
261
+ right guide. That’s us.
262
+ </p>
263
+ </div>
264
+ <div class="w-full h-80 rounded-lg overflow-hidden shadow-lg">
265
+ <img
266
+ src="https://i.pinimg.com/originals/44/c7/c1/44c7c1f3fbd68b2151c37af5f08198f1.gif"
267
+ class="object-cover w-full h-full rounded-lg"
268
+ />
269
+ </div>
270
+ </div>
271
+ </section>
272
+
273
+ <!-- FOOTER -->
274
+ <footer class="py-12 bg-[var(--wisteria)] text-white fade-in">
275
+ <div
276
+ class="max-w-6xl mx-auto px-6 flex flex-col md:flex-row justify-between items-center"
277
+ >
278
+ <p>&copy; 2025 CTRL + ALT + HEAL. All rights reserved.</p>
279
+ <div class="flex space-x-4 mt-4 md:mt-0">
280
+ <a href="#" class="hover:underline">Privacy Policy</a>
281
+ <a href="#" class="hover:underline">Terms of Service</a>
282
+ </div>
283
+ </div>
284
+ </footer>
285
+
286
+ <script>
287
+ // Fade-in on scroll
288
+ const fadeObserver = new IntersectionObserver(
289
+ (entries) => {
290
+ entries.forEach((entry) => {
291
+ if (entry.isIntersecting) entry.target.classList.add("show");
292
+ });
293
+ },
294
+ { threshold: 0.1 }
295
+ );
296
+ document
297
+ .querySelectorAll(".fade-in")
298
+ .forEach((el) => fadeObserver.observe(el));
299
+
300
+ // Typing effect on scroll
301
+ const typeObserver = new IntersectionObserver(
302
+ (entries) => {
303
+ entries.forEach((entry) => {
304
+ if (entry.isIntersecting) {
305
+ typeText("typed-heading", "Your Health, Your Clarity", 80);
306
+ typeText(
307
+ "typed-paragraph",
308
+ "We make complex medical reports simple and easy to understand.",
309
+ 30
310
+ );
311
+ typeObserver.unobserve(entry.target);
312
+ }
313
+ });
314
+ },
315
+ { threshold: 0.5 }
316
+ );
317
+
318
+ typeObserver.observe(
319
+ document.querySelector("#typed-heading").parentElement
320
+ );
321
+
322
+ function typeText(id, text, speed) {
323
+ const el = document.getElementById(id);
324
+ let i = 0;
325
+ function type() {
326
+ if (i < text.length) {
327
+ el.innerHTML += text.charAt(i);
328
+ i++;
329
+ setTimeout(type, speed);
330
+ }
331
+ }
332
+ type();
333
+ }
334
+ </script>
335
+ </body>
336
+ </html>
login.html → web/login.html RENAMED
@@ -1,348 +1,348 @@
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>Login / Signup - CTRL + ALT + HEAL</title>
7
- <script src="https://cdn.tailwindcss.com"></script>
8
- <style>
9
- :root {
10
- --blue: rgb(120, 187, 242);
11
- --l-blue: rgb(197, 217, 251);
12
- --latte-cream: #ffffff;
13
- --red: #ff746c;
14
- --l-red: #faa0a0;
15
- }
16
-
17
- body {
18
- font-family: "Rubik", sans-serif;
19
- background-color: var(--cream);
20
- color: #333;
21
- }
22
-
23
- /* Navbar styles */
24
- nav {
25
- backdrop-filter: blur(10px);
26
- background: rgba(255, 255, 255, 0.85);
27
- transition: transform 0.3s ease, background-color 0.3s ease,
28
- box-shadow 0.3s ease;
29
- }
30
-
31
- nav.scrolled {
32
- background: rgba(255, 255, 255, 1);
33
- box-shadow: 0 8px 20px rgba(0, 0, 0, 0.1);
34
- transform: translateY(-5px);
35
- }
36
-
37
- nav a {
38
- transition: color 0.3s ease, transform 0.2s ease;
39
- }
40
-
41
- nav a:hover {
42
- color: var(--blue);
43
- transform: translateY(-2px);
44
- }
45
-
46
- /* Form card animation */
47
- @keyframes fadeSlideUp {
48
- 0% {
49
- opacity: 0;
50
- transform: translateY(20px);
51
- }
52
- 100% {
53
- opacity: 1;
54
- transform: translateY(0);
55
- }
56
- }
57
-
58
- .fade-slide-up {
59
- animation: fadeSlideUp 0.6s ease forwards;
60
- }
61
-
62
- .form-card {
63
- background: rgba(255, 255, 255, 0.85);
64
- backdrop-filter: blur(10px);
65
- border-radius: 1rem;
66
- padding: 2rem;
67
- box-shadow: 0 8px 20px rgba(0, 0, 0, 0.15);
68
- transition: transform 0.3s ease, box-shadow 0.3s ease;
69
- }
70
-
71
- .form-card:hover {
72
- transform: translateY(-5px);
73
- box-shadow: 0 15px 30px rgba(0, 0, 0, 0.2);
74
- }
75
-
76
- .form-input {
77
- width: 100%;
78
- padding: 0.5rem 1rem;
79
- border-radius: 0.5rem;
80
- border: 1px solid #ccc;
81
- transition: border-color 0.3s ease, box-shadow 0.3s ease;
82
- }
83
-
84
- .form-input:focus {
85
- outline: none;
86
- border-color: var(--blue);
87
- box-shadow: 0 0 0 3px rgba(120, 187, 242, 0.3);
88
- }
89
-
90
- .btn-primary {
91
- width: 100%;
92
- padding: 0.75rem;
93
- border-radius: 0.75rem;
94
- background-color: var(--blue);
95
- color: white;
96
- font-weight: 600;
97
- transition: background-color 0.3s ease, transform 0.2s ease,
98
- box-shadow 0.2s ease;
99
- }
100
-
101
- .btn-primary:hover {
102
- background-color: var(--l-blue);
103
- color: #333;
104
- transform: translateY(-2px);
105
- box-shadow: 0 6px 15px rgba(0, 0, 0, 0.15);
106
- }
107
-
108
- .btn-red {
109
- width: 100%;
110
- padding: 0.75rem;
111
- border-radius: 0.75rem;
112
- background-color: var(--red);
113
- color: white;
114
- font-weight: 600;
115
- transition: background-color 0.3s ease, transform 0.2s ease,
116
- box-shadow 0.2s ease;
117
- }
118
-
119
- .btn-red:hover {
120
- background-color: var(--l-red);
121
- transform: translateY(-2px);
122
- box-shadow: 0 6px 15px rgba(0, 0, 0, 0.15);
123
- }
124
- </style>
125
- </head>
126
- <body
127
- class="min-h-screen flex flex-col items-center justify-start px-4 pt-24"
128
- >
129
- <!-- Navbar -->
130
- <nav
131
- class="fixed top-0 left-0 w-full z-50 backdrop-blur-md bg-white/20 border-b border-white/30 shadow-md"
132
- >
133
- <div
134
- class="max-w-6xl mx-auto px-6 py-4 flex justify-between items-center"
135
- >
136
- <!-- Logo -->
137
- <a
138
- href="index.html"
139
- class="text-2xl font-bold hover:text-[var(--tropical-indigo)] transition"
140
- >
141
- CTRL + ALT + HEAL
142
- </a>
143
-
144
- <!-- Desktop Menu -->
145
- <ul class="hidden md:flex space-x-6 font-medium text-gray-800">
146
- <li><a href="index.html" class="nav-link">Home</a></li>
147
- <li><a href="analyzer.html" class="nav-link">Analyzer</a></li>
148
- <li><a href="profile.html" class="nav-link">Profile</a></li>
149
- <li><a href="login.html" class="nav-link">Login</a></li>
150
- <li><a href="about.html" class="nav-link">About</a></li>
151
- </ul>
152
-
153
- <!-- Hamburger Menu -->
154
- <button id="hamburger" class="md:hidden text-[#000000] text-2xl">
155
-
156
- </button>
157
- </div>
158
-
159
- <!-- Mobile Menu -->
160
- <ul
161
- id="mobile-menu"
162
- class="hidden flex-col space-y-4 bg-white/30 backdrop-blur-lg border border-white/20 rounded-xl shadow-lg mt-2 p-4 mx-6 md:hidden"
163
- >
164
- <li>
165
- <a
166
- href="index.html"
167
- class="block text-bold text-gray-800 hover:text-[var(--neon-green)]"
168
- >Home</a
169
- >
170
- </li>
171
- <li>
172
- <a
173
- href="analyzer.html"
174
- class="block text-gray-800 hover:text-[var(--neon-green)]"
175
- >Analyzer</a
176
- >
177
- </li>
178
- <li>
179
- <a
180
- href="profile.html"
181
- class="block text-gray-800 hover:text-[var(--neon-green)]"
182
- >Profile</a
183
- >
184
- </li>
185
- <li>
186
- <a
187
- href="login.html"
188
- class="block text-gray-800 hover:text-[var(--neon-green)]"
189
- >Login</a
190
- >
191
- </li>
192
- <li>
193
- <a
194
- href="about.html"
195
- class="block text-gray-800 hover:text-[var(--neon-green)]"
196
- >About</a
197
- >
198
- </li>
199
- </ul>
200
- </nav>
201
-
202
- <!-- Login Form -->
203
- <div class="form-card w-full max-w-md fade-slide-up mt-8">
204
- <h2 id="formTitle" class="text-2xl font-semibold text-[var(--blue)] mb-6">
205
- Log In
206
- </h2>
207
- <input type="hidden" id="mode" value="login" />
208
-
209
- <label class="block mb-2 text-sm font-medium">Mode</label>
210
- <select
211
- id="modeSelector"
212
- onchange="toggleMode(this.value)"
213
- class="form-input mb-4"
214
- >
215
- <option value="login">Log In</option>
216
- <option value="signup">Sign Up</option>
217
- </select>
218
-
219
- <label class="block mb-2 text-sm font-medium">Email</label>
220
- <input
221
- type="email"
222
- id="email"
223
- placeholder="you@example.com"
224
- class="form-input mb-4"
225
- />
226
-
227
- <label class="block mb-2 text-sm font-medium">Password</label>
228
- <input
229
- type="password"
230
- id="password"
231
- placeholder="••••••••"
232
- class="form-input mb-4"
233
- />
234
-
235
- <div id="nameGroup" style="display: none">
236
- <label class="block mb-2 text-sm font-medium">Name</label>
237
- <input
238
- type="text"
239
- id="name"
240
- placeholder="Your Name"
241
- class="form-input mb-4"
242
- />
243
- </div>
244
-
245
- <div id="dobGroup" style="display: none">
246
- <label class="block mb-2 text-sm font-medium">Date of Birth</label>
247
- <input type="date" id="dob" class="form-input mb-6" />
248
- </div>
249
-
250
- <button onclick="submitForm()" id="submitBtn" class="btn-primary mb-2">
251
- Log In
252
- </button>
253
- <button onclick="resetPassword()" class="btn-red">Reset Password</button>
254
- </div>
255
-
256
- <!-- Firebase & JS -->
257
- <script type="module">
258
- import { initializeApp } from "https://www.gstatic.com/firebasejs/9.22.0/firebase-app.js";
259
- import {
260
- getAuth,
261
- createUserWithEmailAndPassword,
262
- signInWithEmailAndPassword,
263
- sendPasswordResetEmail,
264
- } from "https://www.gstatic.com/firebasejs/9.22.0/firebase-auth.js";
265
- import {
266
- getFirestore,
267
- doc,
268
- setDoc,
269
- } from "https://www.gstatic.com/firebasejs/9.22.0/firebase-firestore.js";
270
-
271
- const firebaseConfig = {
272
- apiKey: "",
273
- authDomain: "",
274
- projectId: "",
275
- storageBucket: "",
276
- messagingSenderId: "",
277
- appId: "",
278
- measurementId: "",
279
- };
280
-
281
- const app = initializeApp(firebaseConfig);
282
- const auth = getAuth(app);
283
- const db = getFirestore(app);
284
-
285
- window.toggleMode = (mode) => {
286
- document.getElementById("formTitle").textContent =
287
- mode === "signup" ? "Sign Up" : "Log In";
288
- document.getElementById("nameGroup").style.display =
289
- mode === "signup" ? "block" : "none";
290
- document.getElementById("dobGroup").style.display =
291
- mode === "signup" ? "block" : "none";
292
- document.getElementById("submitBtn").textContent =
293
- mode === "signup" ? "Sign Up" : "Log In";
294
- document.getElementById("mode").value = mode;
295
- };
296
-
297
- window.submitForm = async () => {
298
- const mode = document.getElementById("mode").value;
299
- const email = document.getElementById("email").value;
300
- const password = document.getElementById("password").value;
301
- try {
302
- if (mode === "signup") {
303
- const name = document.getElementById("name").value;
304
- const dob = document.getElementById("dob").value;
305
- const userCredential = await createUserWithEmailAndPassword(
306
- auth,
307
- email,
308
- password
309
- );
310
- const user = userCredential.user;
311
- await setDoc(doc(db, "users", user.uid), { name, email, dob });
312
- } else {
313
- await signInWithEmailAndPassword(auth, email, password);
314
- }
315
- window.location.href = "profile.html";
316
- } catch (err) {
317
- alert(
318
- (mode === "signup" ? "Sign Up" : "Log In") +
319
- " error: " +
320
- err.message
321
- );
322
- }
323
- };
324
-
325
- window.resetPassword = async () => {
326
- const email = document.getElementById("email").value;
327
- if (!email) return alert("Please enter your email to reset password.");
328
- try {
329
- await sendPasswordResetEmail(auth, email);
330
- alert("Password reset email sent to " + email);
331
- } catch (err) {
332
- alert("Error sending password reset: " + err.message);
333
- }
334
- };
335
-
336
- document.addEventListener("DOMContentLoaded", () => {
337
- toggleMode("login");
338
-
339
- // Navbar scroll animation
340
- const navbar = document.getElementById("navbar");
341
- window.addEventListener("scroll", () => {
342
- if (window.scrollY > 20) navbar.classList.add("scrolled");
343
- else navbar.classList.remove("scrolled");
344
- });
345
- });
346
- </script>
347
- </body>
348
- </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>Login / Signup - CTRL + ALT + HEAL</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <style>
9
+ :root {
10
+ --blue: rgb(120, 187, 242);
11
+ --l-blue: rgb(197, 217, 251);
12
+ --latte-cream: #ffffff;
13
+ --red: #ff746c;
14
+ --l-red: #faa0a0;
15
+ }
16
+
17
+ body {
18
+ font-family: "Rubik", sans-serif;
19
+ background-color: var(--cream);
20
+ color: #333;
21
+ }
22
+
23
+ /* Navbar styles */
24
+ nav {
25
+ backdrop-filter: blur(10px);
26
+ background: rgba(255, 255, 255, 0.85);
27
+ transition: transform 0.3s ease, background-color 0.3s ease,
28
+ box-shadow 0.3s ease;
29
+ }
30
+
31
+ nav.scrolled {
32
+ background: rgba(255, 255, 255, 1);
33
+ box-shadow: 0 8px 20px rgba(0, 0, 0, 0.1);
34
+ transform: translateY(-5px);
35
+ }
36
+
37
+ nav a {
38
+ transition: color 0.3s ease, transform 0.2s ease;
39
+ }
40
+
41
+ nav a:hover {
42
+ color: var(--blue);
43
+ transform: translateY(-2px);
44
+ }
45
+
46
+ /* Form card animation */
47
+ @keyframes fadeSlideUp {
48
+ 0% {
49
+ opacity: 0;
50
+ transform: translateY(20px);
51
+ }
52
+ 100% {
53
+ opacity: 1;
54
+ transform: translateY(0);
55
+ }
56
+ }
57
+
58
+ .fade-slide-up {
59
+ animation: fadeSlideUp 0.6s ease forwards;
60
+ }
61
+
62
+ .form-card {
63
+ background: rgba(255, 255, 255, 0.85);
64
+ backdrop-filter: blur(10px);
65
+ border-radius: 1rem;
66
+ padding: 2rem;
67
+ box-shadow: 0 8px 20px rgba(0, 0, 0, 0.15);
68
+ transition: transform 0.3s ease, box-shadow 0.3s ease;
69
+ }
70
+
71
+ .form-card:hover {
72
+ transform: translateY(-5px);
73
+ box-shadow: 0 15px 30px rgba(0, 0, 0, 0.2);
74
+ }
75
+
76
+ .form-input {
77
+ width: 100%;
78
+ padding: 0.5rem 1rem;
79
+ border-radius: 0.5rem;
80
+ border: 1px solid #ccc;
81
+ transition: border-color 0.3s ease, box-shadow 0.3s ease;
82
+ }
83
+
84
+ .form-input:focus {
85
+ outline: none;
86
+ border-color: var(--blue);
87
+ box-shadow: 0 0 0 3px rgba(120, 187, 242, 0.3);
88
+ }
89
+
90
+ .btn-primary {
91
+ width: 100%;
92
+ padding: 0.75rem;
93
+ border-radius: 0.75rem;
94
+ background-color: var(--blue);
95
+ color: white;
96
+ font-weight: 600;
97
+ transition: background-color 0.3s ease, transform 0.2s ease,
98
+ box-shadow 0.2s ease;
99
+ }
100
+
101
+ .btn-primary:hover {
102
+ background-color: var(--l-blue);
103
+ color: #333;
104
+ transform: translateY(-2px);
105
+ box-shadow: 0 6px 15px rgba(0, 0, 0, 0.15);
106
+ }
107
+
108
+ .btn-red {
109
+ width: 100%;
110
+ padding: 0.75rem;
111
+ border-radius: 0.75rem;
112
+ background-color: var(--red);
113
+ color: white;
114
+ font-weight: 600;
115
+ transition: background-color 0.3s ease, transform 0.2s ease,
116
+ box-shadow 0.2s ease;
117
+ }
118
+
119
+ .btn-red:hover {
120
+ background-color: var(--l-red);
121
+ transform: translateY(-2px);
122
+ box-shadow: 0 6px 15px rgba(0, 0, 0, 0.15);
123
+ }
124
+ </style>
125
+ </head>
126
+ <body
127
+ class="min-h-screen flex flex-col items-center justify-start px-4 pt-24"
128
+ >
129
+ <!-- Navbar -->
130
+ <nav
131
+ class="fixed top-0 left-0 w-full z-50 backdrop-blur-md bg-white/20 border-b border-white/30 shadow-md"
132
+ >
133
+ <div
134
+ class="max-w-6xl mx-auto px-6 py-4 flex justify-between items-center"
135
+ >
136
+ <!-- Logo -->
137
+ <a
138
+ href="index.html"
139
+ class="text-2xl font-bold hover:text-[var(--tropical-indigo)] transition"
140
+ >
141
+ CTRL + ALT + HEAL
142
+ </a>
143
+
144
+ <!-- Desktop Menu -->
145
+ <ul class="hidden md:flex space-x-6 font-medium text-gray-800">
146
+ <li><a href="index.html" class="nav-link">Home</a></li>
147
+ <li><a href="analyzer.html" class="nav-link">Analyzer</a></li>
148
+ <li><a href="profile.html" class="nav-link">Profile</a></li>
149
+ <li><a href="login.html" class="nav-link">Login</a></li>
150
+ <li><a href="about.html" class="nav-link">About</a></li>
151
+ </ul>
152
+
153
+ <!-- Hamburger Menu -->
154
+ <button id="hamburger" class="md:hidden text-[#000000] text-2xl">
155
+
156
+ </button>
157
+ </div>
158
+
159
+ <!-- Mobile Menu -->
160
+ <ul
161
+ id="mobile-menu"
162
+ class="hidden flex-col space-y-4 bg-white/30 backdrop-blur-lg border border-white/20 rounded-xl shadow-lg mt-2 p-4 mx-6 md:hidden"
163
+ >
164
+ <li>
165
+ <a
166
+ href="index.html"
167
+ class="block text-bold text-gray-800 hover:text-[var(--neon-green)]"
168
+ >Home</a
169
+ >
170
+ </li>
171
+ <li>
172
+ <a
173
+ href="analyzer.html"
174
+ class="block text-gray-800 hover:text-[var(--neon-green)]"
175
+ >Analyzer</a
176
+ >
177
+ </li>
178
+ <li>
179
+ <a
180
+ href="profile.html"
181
+ class="block text-gray-800 hover:text-[var(--neon-green)]"
182
+ >Profile</a
183
+ >
184
+ </li>
185
+ <li>
186
+ <a
187
+ href="login.html"
188
+ class="block text-gray-800 hover:text-[var(--neon-green)]"
189
+ >Login</a
190
+ >
191
+ </li>
192
+ <li>
193
+ <a
194
+ href="about.html"
195
+ class="block text-gray-800 hover:text-[var(--neon-green)]"
196
+ >About</a
197
+ >
198
+ </li>
199
+ </ul>
200
+ </nav>
201
+
202
+ <!-- Login Form -->
203
+ <div class="form-card w-full max-w-md fade-slide-up mt-8">
204
+ <h2 id="formTitle" class="text-2xl font-semibold text-[var(--blue)] mb-6">
205
+ Log In
206
+ </h2>
207
+ <input type="hidden" id="mode" value="login" />
208
+
209
+ <label class="block mb-2 text-sm font-medium">Mode</label>
210
+ <select
211
+ id="modeSelector"
212
+ onchange="toggleMode(this.value)"
213
+ class="form-input mb-4"
214
+ >
215
+ <option value="login">Log In</option>
216
+ <option value="signup">Sign Up</option>
217
+ </select>
218
+
219
+ <label class="block mb-2 text-sm font-medium">Email</label>
220
+ <input
221
+ type="email"
222
+ id="email"
223
+ placeholder="you@example.com"
224
+ class="form-input mb-4"
225
+ />
226
+
227
+ <label class="block mb-2 text-sm font-medium">Password</label>
228
+ <input
229
+ type="password"
230
+ id="password"
231
+ placeholder="••••••••"
232
+ class="form-input mb-4"
233
+ />
234
+
235
+ <div id="nameGroup" style="display: none">
236
+ <label class="block mb-2 text-sm font-medium">Name</label>
237
+ <input
238
+ type="text"
239
+ id="name"
240
+ placeholder="Your Name"
241
+ class="form-input mb-4"
242
+ />
243
+ </div>
244
+
245
+ <div id="dobGroup" style="display: none">
246
+ <label class="block mb-2 text-sm font-medium">Date of Birth</label>
247
+ <input type="date" id="dob" class="form-input mb-6" />
248
+ </div>
249
+
250
+ <button onclick="submitForm()" id="submitBtn" class="btn-primary mb-2">
251
+ Log In
252
+ </button>
253
+ <button onclick="resetPassword()" class="btn-red">Reset Password</button>
254
+ </div>
255
+
256
+ <!-- Firebase & JS -->
257
+ <script type="module">
258
+ import { initializeApp } from "https://www.gstatic.com/firebasejs/9.22.0/firebase-app.js";
259
+ import {
260
+ getAuth,
261
+ createUserWithEmailAndPassword,
262
+ signInWithEmailAndPassword,
263
+ sendPasswordResetEmail,
264
+ } from "https://www.gstatic.com/firebasejs/9.22.0/firebase-auth.js";
265
+ import {
266
+ getFirestore,
267
+ doc,
268
+ setDoc,
269
+ } from "https://www.gstatic.com/firebasejs/9.22.0/firebase-firestore.js";
270
+
271
+ const firebaseConfig = {
272
+ apiKey: "",
273
+ authDomain: "",
274
+ projectId: "",
275
+ storageBucket: "",
276
+ messagingSenderId: "",
277
+ appId: "",
278
+ measurementId: "",
279
+ };
280
+
281
+ const app = initializeApp(firebaseConfig);
282
+ const auth = getAuth(app);
283
+ const db = getFirestore(app);
284
+
285
+ window.toggleMode = (mode) => {
286
+ document.getElementById("formTitle").textContent =
287
+ mode === "signup" ? "Sign Up" : "Log In";
288
+ document.getElementById("nameGroup").style.display =
289
+ mode === "signup" ? "block" : "none";
290
+ document.getElementById("dobGroup").style.display =
291
+ mode === "signup" ? "block" : "none";
292
+ document.getElementById("submitBtn").textContent =
293
+ mode === "signup" ? "Sign Up" : "Log In";
294
+ document.getElementById("mode").value = mode;
295
+ };
296
+
297
+ window.submitForm = async () => {
298
+ const mode = document.getElementById("mode").value;
299
+ const email = document.getElementById("email").value;
300
+ const password = document.getElementById("password").value;
301
+ try {
302
+ if (mode === "signup") {
303
+ const name = document.getElementById("name").value;
304
+ const dob = document.getElementById("dob").value;
305
+ const userCredential = await createUserWithEmailAndPassword(
306
+ auth,
307
+ email,
308
+ password
309
+ );
310
+ const user = userCredential.user;
311
+ await setDoc(doc(db, "users", user.uid), { name, email, dob });
312
+ } else {
313
+ await signInWithEmailAndPassword(auth, email, password);
314
+ }
315
+ window.location.href = "profile.html";
316
+ } catch (err) {
317
+ alert(
318
+ (mode === "signup" ? "Sign Up" : "Log In") +
319
+ " error: " +
320
+ err.message
321
+ );
322
+ }
323
+ };
324
+
325
+ window.resetPassword = async () => {
326
+ const email = document.getElementById("email").value;
327
+ if (!email) return alert("Please enter your email to reset password.");
328
+ try {
329
+ await sendPasswordResetEmail(auth, email);
330
+ alert("Password reset email sent to " + email);
331
+ } catch (err) {
332
+ alert("Error sending password reset: " + err.message);
333
+ }
334
+ };
335
+
336
+ document.addEventListener("DOMContentLoaded", () => {
337
+ toggleMode("login");
338
+
339
+ // Navbar scroll animation
340
+ const navbar = document.getElementById("navbar");
341
+ window.addEventListener("scroll", () => {
342
+ if (window.scrollY > 20) navbar.classList.add("scrolled");
343
+ else navbar.classList.remove("scrolled");
344
+ });
345
+ });
346
+ </script>
347
+ </body>
348
+ </html>
profile.html → web/profile.html RENAMED
@@ -1,624 +1,624 @@
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>Profile - CTRL + ALT + HEAL</title>
7
- <script src="https://cdn.tailwindcss.com"></script>
8
- <style>
9
- :root {
10
- --tropical-indigo: rgb(120, 187, 242);
11
- --wisteria: rgb(197, 217, 251);
12
- --latte-cream: #ffffff;
13
- }
14
- body {
15
- font-family: "Rubik", sans-serif;
16
- background-color: var(--latte-cream);
17
- color: #333;
18
- }
19
- .btn-primary {
20
- background-color: var(--tropical-indigo);
21
- color: white;
22
- transition: 0.3s;
23
- }
24
- .btn-primary:hover {
25
- background-color: var(--wisteria);
26
- color: #333;
27
- }
28
- .avatar {
29
- width: 128px;
30
- height: 128px;
31
- border-radius: 50%;
32
- object-fit: cover;
33
- cursor: pointer;
34
- background-color: #e5e7eb;
35
- }
36
- </style>
37
- </head>
38
- <body class="text-gray-800 min-h-screen flex flex-col">
39
- <!-- Navbar -->
40
- <nav
41
- class="fixed top-0 left-0 w-full z-50 backdrop-blur-md bg-white/20 border-b border-white/30 shadow-md"
42
- >
43
- <div
44
- class="max-w-6xl mx-auto px-6 py-4 flex justify-between items-center"
45
- >
46
- <a
47
- href="index.html"
48
- class="text-2xl font-bold hover:text-[var(--tropical-indigo)] transition"
49
- >CTRL + ALT + HEAL</a
50
- >
51
- <ul class="hidden md:flex space-x-6 font-medium text-gray-800">
52
- <li><a href="index.html">Home</a></li>
53
- <li><a href="analyzer.html">Analyzer</a></li>
54
- <li><a href="profile.html">Profile</a></li>
55
- <li><a href="login.html">Logout</a></li>
56
- <li><a href="about.html">About</a></li>
57
- </ul>
58
- <button id="hamburger" class="md:hidden text-2xl">☰</button>
59
- </div>
60
- </nav>
61
-
62
- <main class="flex-grow container mx-auto px-6 pt-24 space-y-6">
63
- <div class="flex justify-between items-center mb-4">
64
-
65
- <button id="togglePastReportsBtn" class="btn-primary px-4 py-2 rounded text-sm">
66
- Show/Hide Past Reports
67
- </button>
68
- </div>
69
-
70
- <!-- Welcome -->
71
- <div class="bg-white rounded-lg p-6 shadow">
72
- <h2 class="text-2xl font-bold text-[var(--tropical-indigo)] mb-2">
73
- Welcome to CTRL + ALT + HEAL! 🎉
74
- </h2>
75
- <p class="text-gray-700 mb-2">
76
- Track progress, crush goals, and vibe with your health journey.
77
- </p>
78
- </div>
79
- <!-- Profile + Stats -->
80
- <div class="flex flex-col lg:flex-row gap-6 mt-10 items-stretch">
81
- <!-- LEFT: Profile Container -->
82
- <div class="flex-1 flex flex-col">
83
- <!-- PROFILE VIEW -->
84
- <div
85
- id="profileViewSection"
86
- class="bg-white shadow rounded-lg p-6 flex-1 flex flex-col justify-between"
87
- >
88
- <div class="flex flex-col lg:flex-row gap-6 items-start">
89
- <div class="flex flex-col items-center space-y-4">
90
- <img
91
- id="profilePic"
92
- class="avatar"
93
- src=""
94
- alt="Profile Picture"
95
- />
96
- <input
97
- type="file"
98
- id="fileInput"
99
- accept="image/*"
100
- class="hidden"
101
- />
102
- <button
103
- id="editProfileBtn"
104
- class="btn-primary px-4 py-2 rounded"
105
- >
106
- Edit Profile
107
- </button>
108
- </div>
109
- <div class="flex-1 flex flex-col justify-start space-y-2">
110
- <h1 class="text-3xl font-semibold text-gray-800">
111
- Your Profile
112
- </h1>
113
- <p class="text-gray-700">
114
- Name: <span id="userName" class="font-medium"></span>
115
- </p>
116
- <p class="text-gray-700">
117
- DOB: <span id="userDOB" class="font-medium"></span>
118
- </p>
119
- <p class="text-gray-700">
120
- Big Things We Should Fix:
121
- <span id="userFix" class="font-medium"></span>
122
- </p>
123
- <p class="text-gray-700">
124
- Health Goals: <span id="userGoals" class="font-medium"></span>
125
- </p>
126
- <p class="text-gray-700">
127
- Bio:
128
- <span id="userBio" class="font-medium">No bio yet 📝</span>
129
- </p>
130
- </div>
131
- </div>
132
- </div>
133
-
134
- <!-- PROFILE EDIT -->
135
- <div
136
- id="profileEditSection"
137
- class="hidden bg-white shadow rounded-lg p-6 flex-1 flex flex-col justify-between"
138
- >
139
- <div class="flex flex-col sm:flex-row items-start space-x-6">
140
- <div class="flex flex-col items-center mb-4 sm:mb-0">
141
- <img
142
- id="editProfilePic"
143
- class="avatar"
144
- src=""
145
- alt="Profile Picture"
146
- />
147
- <input
148
- type="file"
149
- id="editFileInput"
150
- accept="image/*"
151
- class="hidden"
152
- />
153
- </div>
154
- <div class="flex-1">
155
- <h1 class="text-3xl font-semibold text-gray-800 mb-4">
156
- Edit Profile
157
- </h1>
158
- <div class="space-y-4">
159
- <div>
160
- <label
161
- for="inputName"
162
- class="block text-sm font-medium text-gray-600"
163
- >Name</label
164
- >
165
- <input
166
- type="text"
167
- id="inputName"
168
- class="w-full border border-gray-300 rounded px-3 py-2 focus:ring-2 focus:ring-[var(--tropical-indigo)] focus:outline-none"
169
- />
170
- </div>
171
- <div>
172
- <label
173
- for="inputDOB"
174
- class="block text-sm font-medium text-gray-600"
175
- >Date of Birth</label
176
- >
177
- <input
178
- type="date"
179
- id="inputDOB"
180
- class="w-full border border-gray-300 rounded px-3 py-2 focus:ring-2 focus:ring-[var(--tropical-indigo)] focus:outline-none"
181
- />
182
- </div>
183
- <div>
184
- <label
185
- for="inputFix"
186
- class="block text-sm font-medium text-gray-600"
187
- >Big Things We Should Fix</label
188
- >
189
- <textarea
190
- id="inputFix"
191
- rows="2"
192
- class="w-full border border-gray-300 rounded px-3 py-2 focus:ring-2 focus:ring-[var(--tropical-indigo)] focus:outline-none"
193
- ></textarea>
194
- </div>
195
- <div>
196
- <label
197
- for="inputGoals"
198
- class="block text-sm font-medium text-gray-600"
199
- >Health Goals</label
200
- >
201
- <textarea
202
- id="inputGoals"
203
- rows="2"
204
- class="w-full border border-gray-300 rounded px-3 py-2 focus:ring-2 focus:ring-[var(--tropical-indigo)] focus:outline-none"
205
- ></textarea>
206
- </div>
207
- </div>
208
- <div class="flex space-x-2 mt-4">
209
- <button
210
- id="saveProfileBtn"
211
- class="btn-primary px-4 py-2 rounded"
212
- >
213
- Save
214
- </button>
215
- <button
216
- id="cancelProfileBtn"
217
- class="bg-gray-300 text-gray-700 px-4 py-2 rounded hover:bg-gray-400 transition"
218
- >
219
- Cancel
220
- </button>
221
- </div>
222
- </div>
223
- </div>
224
- </div>
225
- </div>
226
-
227
- <!-- RIGHT: Mini Stats -->
228
- <div class="w-full lg:w-1/3 flex flex-col justify-between gap-4">
229
- <!-- Reports Uploaded -->
230
- <div class="bg-white shadow rounded-lg p-4 flex-1 flex items-center gap-2">
231
- <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-[var(--tropical-indigo)]" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
232
- <path stroke-linecap="round" stroke-linejoin="round" d="M3 7h5l2 3h11v11H3V7z" />
233
- </svg>
234
- <div class="flex-1">
235
- <p class="text-sm text-gray-500">Reports Uploaded</p>
236
- <p class="font-semibold text-lg" id="reportsCount">0</p>
237
- </div>
238
- </div>
239
-
240
- <!-- Tests In Range -->
241
- <div class="bg-white shadow rounded-lg p-4 flex-1 flex items-center gap-2">
242
- <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-green-400" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
243
- <path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7" />
244
- </svg>
245
- <div class="flex-1">
246
- <p class="text-sm text-gray-500">Tests In Range In Latest Report</p>
247
- <p class="font-semibold text-lg" id="testsInRange">0</p>
248
- </div>
249
- </div>
250
-
251
- <!-- Tests Out of Range -->
252
- <div class="bg-white shadow rounded-lg p-4 flex-1 flex items-center gap-2">
253
- <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-red-400" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
254
- <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
255
- </svg>
256
- <div class="flex-1">
257
- <p class="text-sm text-gray-500">Tests Out of Range In Latest Report</p>
258
- <p class="font-semibold text-lg" id="testsOutOfRange">0</p>
259
- </div>
260
- </div>
261
- </div>
262
-
263
-
264
- </div>
265
-
266
-
267
-
268
-
269
-
270
- <!-- Reports Section -->
271
- <div class="bg-white shadow rounded-lg p-6">
272
- <h3 class="text-lg font-semibold text-[var(--tropical-indigo)] mb-3">
273
- Your Reports
274
- </h3>
275
- <div id="reportsSection" class="text-gray-600 text-center space-y-3">
276
- <p id="reportStatus">📂 No reports uploaded yet.</p>
277
- <a
278
- id="sampleReportLink"
279
- href="/sample_report.pdf"
280
- target="_blank"
281
- class="text-blue-600 hover:underline hidden"
282
- >sample_report.pdf</a
283
- >
284
- <div class="mt-2 flex justify-center gap-4">
285
- <button id="uploadBtn" class="btn-primary px-4 py-2 rounded" onclick="window.location.href='analyzer.html'">
286
- Upload Report
287
- </button>
288
- <button id="toggleReportBtn" class="btn-primary px-4 py-2 rounded">
289
- Use Sample Report
290
- </button>
291
- </div>
292
- </div>
293
- </div>
294
- </div>
295
-
296
- <!-- Past Reports Section with Number-Line Bars -->
297
- <div class="bg-white shadow rounded-lg p-6 mt-6 ">
298
- <h3 class="text-lg font-semibold text-[var(--tropical-indigo)] mb-4">
299
- Past Reports
300
- </h3>
301
- <div id="pastReportsSection" class="flex flex-col gap-4 ">
302
- <!-- Report 3 -->
303
- <div class="flex flex-col bg-[var(--wisteria)] p-4 rounded-lg shadow hover:shadow-md transition">
304
- <div class="flex justify-between items-center cursor-pointer report-header" onclick="toggleDetails(this)">
305
- <div class="flex items-center gap-3">
306
- <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-[var(--tropical-indigo)]" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
307
- <path stroke-linecap="round" stroke-linejoin="round" d="M12 4v16m8-8H4" />
308
- </svg>
309
- <p class="font-medium text-gray-800">Annual_Physical_Mar2025.pdf</p>
310
- </div>
311
- <div class="flex gap-2 flex-shrink-0">
312
- <span class="px-2 py-1 rounded-full bg-green-200 text-green-800 text-xs font-semibold">In Range: 2</span>
313
- <span class="px-2 py-1 rounded-full bg-red-200 text-red-800 text-xs font-semibold">Out of Range: 0</span>
314
- </div>
315
- </div>
316
- <div class="report-details mt-2 hidden w-full bg-white rounded p-3 border border-gray-300 text-gray-700">
317
- <ul class="space-y-4 text-sm">
318
- <li>
319
- <div class="flex justify-between mb-1">
320
- <span>Hemoglobin: 14.2 g/dL</span>
321
- <span class="text-xs text-gray-500">(12-16)</span>
322
- </div>
323
- <div class="relative w-full h-4 bg-gray-200 rounded">
324
- <div class="absolute h-4 rounded bg-green-400" style="width: 70.5%;"></div>
325
- <span class="absolute -top-5 text-xs font-semibold text-gray-800" style="left: 70.5%;">14.2</span>
326
- <div class="absolute top-full left-0 w-full flex justify-between mt-1 text-xs text-gray-500">
327
- <span>12</span>
328
- <span>16</span>
329
- </div>
330
- </div>
331
- </li>
332
- <li>
333
- <div class="flex justify-between mb-1">
334
- <span>Cholesterol: 180 mg/dL</span>
335
- <span class="text-xs text-gray-500">(125-200)</span>
336
- </div>
337
- <div class="relative w-full h-6 bg-gray-200 rounded overflow-hidden">
338
- <div class="absolute h-6 rounded bg-green-400" style="width: 90%;"></div>
339
- <span class="absolute top-1/2 transform -translate-y-1/2 text-xs font-semibold text-gray-800" style="left: 90%;">180</span>
340
- <div class="absolute top-full left-0 w-full flex justify-between mt-1 text-xs text-gray-500">
341
- <span>125</span>
342
- <span>200</span>
343
- </div>
344
- </div>
345
- </li>
346
- </ul>
347
- </div>
348
- </div>
349
- <!-- Report 2 -->
350
- <div class="flex flex-col bg-[var(--wisteria)] p-4 rounded-lg shadow hover:shadow-md transition">
351
- <div class="flex justify-between items-center cursor-pointer report-header" onclick="toggleDetails(this)">
352
- <div class="flex items-center gap-3">
353
- <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-[var(--tropical-indigo)]" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
354
- <path stroke-linecap="round" stroke-linejoin="round" d="M12 4v16m8-8H4" />
355
- </svg>
356
- <p class="font-medium text-gray-800">Checkup_Feb2025.pdf</p>
357
- </div>
358
- <div class="flex gap-2 flex-shrink-0">
359
- <span class="px-2 py-1 rounded-full bg-green-200 text-green-800 text-xs font-semibold">In Range: 1</span>
360
- <span class="px-2 py-1 rounded-full bg-red-200 text-red-800 text-xs font-semibold">Out of Range: 1</span>
361
- </div>
362
- </div>
363
- <div class="report-details mt-2 hidden w-full bg-white rounded p-3 border border-gray-300 text-gray-700">
364
- <ul class="space-y-4 text-sm">
365
- <li>
366
- <div class="flex justify-between mb-1">
367
- <span>Glucose: 105 mg/dL</span>
368
- <span class="text-xs text-gray-500">(70-99)</span>
369
- </div>
370
- <div class="relative w-full h-4 bg-gray-200 rounded">
371
- <div class="absolute h-4 rounded bg-red-400" style="width: calc(105/99*100%);"></div>
372
- <span class="absolute -top-5 text-xs font-semibold text-gray-800" style="left: 100%;">105</span>
373
- <div class="absolute top-full left-0 w-full flex justify-between mt-1 text-xs text-gray-500">
374
- <span>70</span>
375
- <span>99</span>
376
- </div>
377
- </div>
378
- </li>
379
- <li>
380
- <div class="flex justify-between mb-1">
381
- <span>Vitamin D: 40 ng/mL</span>
382
- <span class="text-xs text-gray-500">(30-100)</span>
383
- </div>
384
- <div class="relative w-full h-4 bg-gray-200 rounded">
385
- <div class="absolute h-4 rounded bg-green-400" style="width: 12.5%;"></div>
386
- <span class="absolute -top-5 text-xs font-semibold text-gray-800" style="left: 12.5%;">40</span>
387
- <div class="absolute top-full left-0 w-full flex justify-between mt-1 text-xs text-gray-500">
388
- <span>30</span>
389
- <span>100</span>
390
- </div>
391
- </div>
392
- </li>
393
- </ul>
394
- </div>
395
- </div>
396
- <!-- Report 1 -->
397
- <div class="flex flex-col bg-[var(--wisteria)] p-4 rounded-lg shadow hover:shadow-md transition">
398
- <div class="flex justify-between items-center cursor-pointer report-header" onclick="toggleDetails(this)">
399
- <div class="flex items-center gap-3">
400
- <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-[var(--tropical-indigo)]" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
401
- <path stroke-linecap="round" stroke-linejoin="round" d="M12 4v16m8-8H4" />
402
- </svg>
403
- <p class="font-medium text-gray-800">Bloodwork_Jan2025.pdf</p>
404
- </div>
405
- <div class="flex gap-2 flex-shrink-0">
406
- <span class="px-2 py-1 rounded-full bg-green-200 text-green-800 text-xs font-semibold">In Range: 1</span>
407
- <span class="px-2 py-1 rounded-full bg-red-200 text-red-800 text-xs font-semibold">Out of Range: 1</span>
408
- </div>
409
- </div>
410
- <div class="report-details mt-2 hidden w-full bg-white rounded p-3 border border-gray-300 text-gray-700">
411
- <ul class="space-y-4 text-sm">
412
- <li>
413
- <div class="flex justify-between mb-1">
414
- <span>Hemoglobin: 13.5 g/dL</span>
415
- <span class="text-xs text-gray-500">(12-16)</span>
416
- </div>
417
- <div class="relative w-full h-4 bg-gray-200 rounded">
418
- <div class="absolute h-4 rounded bg-green-400" style="width: 56.25%;"></div>
419
- <span class="absolute -top-5 text-xs font-semibold text-gray-800" style="left: 56.25%;">13.5</span>
420
- <div class="absolute top-full left-0 w-full flex justify-between mt-1 text-xs text-gray-500">
421
- <span>12</span>
422
- <span>16</span>
423
- </div>
424
- </div>
425
- </li>
426
- <li>
427
- <div class="flex justify-between mb-1">
428
- <span>Cholesterol: 210 mg/dL</span>
429
- <span class="text-xs text-gray-500">(125-200)</span>
430
- </div>
431
- <div class="relative w-full h-6 bg-gray-200 rounded overflow-hidden">
432
- <div class="absolute h-6 rounded" style="width: calc(min(210/200*100%, 100%)); background-color: #f87171;"></div>
433
- <span class="absolute top-1/2 transform -translate-y-1/2 text-xs font-semibold text-gray-800" style="left: calc(min(210/200*100%, 95%));">210</span>
434
- <div class="absolute top-full left-0 w-full flex justify-between mt-1 text-xs text-gray-500">
435
- <span>125</span>
436
- <span>200</span>
437
- </div>
438
- </div>
439
- </li>
440
- </ul>
441
- </div>
442
- </div>
443
-
444
-
445
-
446
-
447
-
448
- </div>
449
- </div>
450
-
451
- <script>
452
- function toggleDetails(element) {
453
- const details = element.parentElement.querySelector('.report-details');
454
- if (details) details.classList.toggle('hidden');
455
- }
456
- </script>
457
-
458
-
459
-
460
- </main>
461
-
462
-
463
-
464
- <footer class="py-6 bg-[var(--wisteria)] text-gray-800 mt-8">
465
- <div
466
- class="max-w-6xl mx-auto px-6 flex flex-col md:flex-row justify-between items-center text-sm"
467
- >
468
- <p>&copy; 2025 CTRL + ALT + HEAL. All rights reserved.</p>
469
- <div class="flex space-x-4 mt-3 md:mt-0">
470
- <a href="#" class="hover:text-[var(--tropical-indigo)] transition"
471
- >Privacy Policy</a
472
- >
473
- <a href="#" class="hover:text-[var(--tropical-indigo)] transition"
474
- >Terms of Service</a
475
- >
476
- </div>
477
- </div>
478
- </footer>
479
-
480
- <script>
481
- // Profile Section
482
- const profileView = document.getElementById("profileViewSection");
483
- const profileEdit = document.getElementById("profileEditSection");
484
- const editBtn = document.getElementById("editProfileBtn");
485
- const saveBtn = document.getElementById("saveProfileBtn");
486
- const cancelBtn = document.getElementById("cancelProfileBtn");
487
-
488
- const inputName = document.getElementById("inputName");
489
- const inputDOB = document.getElementById("inputDOB");
490
- const inputFix = document.getElementById("inputFix");
491
- const inputGoals = document.getElementById("inputGoals");
492
-
493
- const profilePic = document.getElementById("profilePic");
494
- const editProfilePic = document.getElementById("editProfilePic");
495
- const fileInput = document.getElementById("fileInput");
496
- const editFileInput = document.getElementById("editFileInput");
497
-
498
- editBtn.addEventListener("click", () => {
499
- inputName.value = localStorage.getItem("userName") || "";
500
- inputDOB.value = localStorage.getItem("userDOB") || "";
501
- inputFix.value = localStorage.getItem("userFix") || "";
502
- inputGoals.value = localStorage.getItem("userGoals") || "";
503
- profileView.classList.add("hidden");
504
- profileEdit.classList.remove("hidden");
505
- });
506
-
507
- cancelBtn.addEventListener("click", () => {
508
- profileEdit.classList.add("hidden");
509
- profileView.classList.remove("hidden");
510
- });
511
-
512
- saveBtn.addEventListener("click", () => {
513
- localStorage.setItem("userName", inputName.value.trim());
514
- localStorage.setItem("userDOB", inputDOB.value);
515
- localStorage.setItem("userFix", inputFix.value.trim());
516
- localStorage.setItem("userGoals", inputGoals.value.trim());
517
-
518
- document.getElementById("userName").textContent =
519
- inputName.value.trim() || "Name";
520
- document.getElementById("userDOB").textContent =
521
- inputDOB.value || "DOB";
522
- document.getElementById("userFix").textContent =
523
- inputFix.value.trim() || "None set";
524
- document.getElementById("userGoals").textContent =
525
- inputGoals.value.trim() || "None set";
526
-
527
- profileEdit.classList.add("hidden");
528
- profileView.classList.remove("hidden");
529
- });
530
-
531
- profilePic.addEventListener("click", () => fileInput.click());
532
- editProfilePic.addEventListener("click", () => editFileInput.click());
533
-
534
- function handleFileUpload(file, targetImg) {
535
- const reader = new FileReader();
536
- reader.onload = () => {
537
- targetImg.src = reader.result;
538
- localStorage.setItem("profilePic", reader.result);
539
- };
540
- reader.readAsDataURL(file);
541
- }
542
-
543
- fileInput.addEventListener("change", (e) => {
544
- if (e.target.files[0]) handleFileUpload(e.target.files[0], profilePic);
545
- });
546
- editFileInput.addEventListener("change", (e) => {
547
- if (e.target.files[0])
548
- handleFileUpload(e.target.files[0], editProfilePic);
549
- });
550
-
551
- // Load saved profile
552
- document.addEventListener("DOMContentLoaded", () => {
553
- document.getElementById("userName").textContent =
554
- localStorage.getItem("userName") || "Name";
555
- document.getElementById("userDOB").textContent =
556
- localStorage.getItem("userDOB") || "DOB";
557
- document.getElementById("userFix").textContent =
558
- localStorage.getItem("userFix") || "None set";
559
- document.getElementById("userGoals").textContent =
560
- localStorage.getItem("userGoals") || "None set";
561
-
562
- const savedPic = localStorage.getItem("profilePic");
563
- if (savedPic) {
564
- profilePic.src = savedPic;
565
- editProfilePic.src = savedPic;
566
- }
567
- });
568
- const pastReportsSection = document.getElementById("pastReportsSection");
569
- const togglePastReportsBtn = document.getElementById("togglePastReportsBtn");
570
-
571
- togglePastReportsBtn.addEventListener("click", () => {
572
- pastReportsSection.classList.toggle("hidden");
573
- });
574
-
575
-
576
- // Toggle Sample Report
577
- const reportsCountEl = document.getElementById("reportsCount");
578
- const goalsCompletedEl = document.getElementById("goalsCompleted");
579
- const achievementsEl = document.getElementById("achievements");
580
- const reportStatusEl = document.getElementById("reportStatus");
581
- const sampleReportLink = document.getElementById("sampleReportLink");
582
- const toggleReportBtn = document.getElementById("toggleReportBtn");
583
-
584
- let sampleActive = false;
585
-
586
- const sampleReport = {
587
- name: "sample_report.pdf",
588
- goalsCompleted: 2,
589
- totalGoals: 2,
590
- improvements: ["Hydration", "Sleep", "Exercise"],
591
- };
592
- function updateMiniStats() {
593
- if (sampleActive) {
594
- reportsCountEl.textContent = 1;
595
-
596
- // Count tests in range vs out of range
597
- const inRange = sampleReport.goalsCompleted; // using sample data
598
- const outOfRange = sampleReport.totalGoals - sampleReport.goalsCompleted;
599
-
600
- document.getElementById("testsInRange").textContent = inRange;
601
- document.getElementById("testsOutOfRange").textContent = outOfRange;
602
-
603
- reportStatusEl.textContent = "📂 Sample report uploaded!";
604
- sampleReportLink.classList.remove("hidden");
605
- } else {
606
- reportsCountEl.textContent = 0;
607
- document.getElementById("testsInRange").textContent = 0;
608
- document.getElementById("testsOutOfRange").textContent = 0;
609
- reportStatusEl.textContent = "📂 No reports uploaded yet.";
610
- sampleReportLink.classList.add("hidden");
611
- }
612
- }
613
-
614
-
615
- toggleReportBtn.addEventListener("click", () => {
616
- sampleActive = !sampleActive;
617
- updateMiniStats();
618
- });
619
-
620
- updateMiniStats();
621
-
622
- </script>
623
- </body>
624
- </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" />
6
+ <title>Profile - CTRL + ALT + HEAL</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <style>
9
+ :root {
10
+ --tropical-indigo: rgb(120, 187, 242);
11
+ --wisteria: rgb(197, 217, 251);
12
+ --latte-cream: #ffffff;
13
+ }
14
+ body {
15
+ font-family: "Rubik", sans-serif;
16
+ background-color: var(--latte-cream);
17
+ color: #333;
18
+ }
19
+ .btn-primary {
20
+ background-color: var(--tropical-indigo);
21
+ color: white;
22
+ transition: 0.3s;
23
+ }
24
+ .btn-primary:hover {
25
+ background-color: var(--wisteria);
26
+ color: #333;
27
+ }
28
+ .avatar {
29
+ width: 128px;
30
+ height: 128px;
31
+ border-radius: 50%;
32
+ object-fit: cover;
33
+ cursor: pointer;
34
+ background-color: #e5e7eb;
35
+ }
36
+ </style>
37
+ </head>
38
+ <body class="text-gray-800 min-h-screen flex flex-col">
39
+ <!-- Navbar -->
40
+ <nav
41
+ class="fixed top-0 left-0 w-full z-50 backdrop-blur-md bg-white/20 border-b border-white/30 shadow-md"
42
+ >
43
+ <div
44
+ class="max-w-6xl mx-auto px-6 py-4 flex justify-between items-center"
45
+ >
46
+ <a
47
+ href="index.html"
48
+ class="text-2xl font-bold hover:text-[var(--tropical-indigo)] transition"
49
+ >CTRL + ALT + HEAL</a
50
+ >
51
+ <ul class="hidden md:flex space-x-6 font-medium text-gray-800">
52
+ <li><a href="index.html">Home</a></li>
53
+ <li><a href="analyzer.html">Analyzer</a></li>
54
+ <li><a href="profile.html">Profile</a></li>
55
+ <li><a href="login.html">Logout</a></li>
56
+ <li><a href="about.html">About</a></li>
57
+ </ul>
58
+ <button id="hamburger" class="md:hidden text-2xl">☰</button>
59
+ </div>
60
+ </nav>
61
+
62
+ <main class="flex-grow container mx-auto px-6 pt-24 space-y-6">
63
+ <div class="flex justify-between items-center mb-4">
64
+
65
+ <button id="togglePastReportsBtn" class="btn-primary px-4 py-2 rounded text-sm">
66
+ Show/Hide Past Reports
67
+ </button>
68
+ </div>
69
+
70
+ <!-- Welcome -->
71
+ <div class="bg-white rounded-lg p-6 shadow">
72
+ <h2 class="text-2xl font-bold text-[var(--tropical-indigo)] mb-2">
73
+ Welcome to CTRL + ALT + HEAL! 🎉
74
+ </h2>
75
+ <p class="text-gray-700 mb-2">
76
+ Track progress, crush goals, and vibe with your health journey.
77
+ </p>
78
+ </div>
79
+ <!-- Profile + Stats -->
80
+ <div class="flex flex-col lg:flex-row gap-6 mt-10 items-stretch">
81
+ <!-- LEFT: Profile Container -->
82
+ <div class="flex-1 flex flex-col">
83
+ <!-- PROFILE VIEW -->
84
+ <div
85
+ id="profileViewSection"
86
+ class="bg-white shadow rounded-lg p-6 flex-1 flex flex-col justify-between"
87
+ >
88
+ <div class="flex flex-col lg:flex-row gap-6 items-start">
89
+ <div class="flex flex-col items-center space-y-4">
90
+ <img
91
+ id="profilePic"
92
+ class="avatar"
93
+ src=""
94
+ alt="Profile Picture"
95
+ />
96
+ <input
97
+ type="file"
98
+ id="fileInput"
99
+ accept="image/*"
100
+ class="hidden"
101
+ />
102
+ <button
103
+ id="editProfileBtn"
104
+ class="btn-primary px-4 py-2 rounded"
105
+ >
106
+ Edit Profile
107
+ </button>
108
+ </div>
109
+ <div class="flex-1 flex flex-col justify-start space-y-2">
110
+ <h1 class="text-3xl font-semibold text-gray-800">
111
+ Your Profile
112
+ </h1>
113
+ <p class="text-gray-700">
114
+ Name: <span id="userName" class="font-medium"></span>
115
+ </p>
116
+ <p class="text-gray-700">
117
+ DOB: <span id="userDOB" class="font-medium"></span>
118
+ </p>
119
+ <p class="text-gray-700">
120
+ Big Things We Should Fix:
121
+ <span id="userFix" class="font-medium"></span>
122
+ </p>
123
+ <p class="text-gray-700">
124
+ Health Goals: <span id="userGoals" class="font-medium"></span>
125
+ </p>
126
+ <p class="text-gray-700">
127
+ Bio:
128
+ <span id="userBio" class="font-medium">No bio yet 📝</span>
129
+ </p>
130
+ </div>
131
+ </div>
132
+ </div>
133
+
134
+ <!-- PROFILE EDIT -->
135
+ <div
136
+ id="profileEditSection"
137
+ class="hidden bg-white shadow rounded-lg p-6 flex-1 flex flex-col justify-between"
138
+ >
139
+ <div class="flex flex-col sm:flex-row items-start space-x-6">
140
+ <div class="flex flex-col items-center mb-4 sm:mb-0">
141
+ <img
142
+ id="editProfilePic"
143
+ class="avatar"
144
+ src=""
145
+ alt="Profile Picture"
146
+ />
147
+ <input
148
+ type="file"
149
+ id="editFileInput"
150
+ accept="image/*"
151
+ class="hidden"
152
+ />
153
+ </div>
154
+ <div class="flex-1">
155
+ <h1 class="text-3xl font-semibold text-gray-800 mb-4">
156
+ Edit Profile
157
+ </h1>
158
+ <div class="space-y-4">
159
+ <div>
160
+ <label
161
+ for="inputName"
162
+ class="block text-sm font-medium text-gray-600"
163
+ >Name</label
164
+ >
165
+ <input
166
+ type="text"
167
+ id="inputName"
168
+ class="w-full border border-gray-300 rounded px-3 py-2 focus:ring-2 focus:ring-[var(--tropical-indigo)] focus:outline-none"
169
+ />
170
+ </div>
171
+ <div>
172
+ <label
173
+ for="inputDOB"
174
+ class="block text-sm font-medium text-gray-600"
175
+ >Date of Birth</label
176
+ >
177
+ <input
178
+ type="date"
179
+ id="inputDOB"
180
+ class="w-full border border-gray-300 rounded px-3 py-2 focus:ring-2 focus:ring-[var(--tropical-indigo)] focus:outline-none"
181
+ />
182
+ </div>
183
+ <div>
184
+ <label
185
+ for="inputFix"
186
+ class="block text-sm font-medium text-gray-600"
187
+ >Big Things We Should Fix</label
188
+ >
189
+ <textarea
190
+ id="inputFix"
191
+ rows="2"
192
+ class="w-full border border-gray-300 rounded px-3 py-2 focus:ring-2 focus:ring-[var(--tropical-indigo)] focus:outline-none"
193
+ ></textarea>
194
+ </div>
195
+ <div>
196
+ <label
197
+ for="inputGoals"
198
+ class="block text-sm font-medium text-gray-600"
199
+ >Health Goals</label
200
+ >
201
+ <textarea
202
+ id="inputGoals"
203
+ rows="2"
204
+ class="w-full border border-gray-300 rounded px-3 py-2 focus:ring-2 focus:ring-[var(--tropical-indigo)] focus:outline-none"
205
+ ></textarea>
206
+ </div>
207
+ </div>
208
+ <div class="flex space-x-2 mt-4">
209
+ <button
210
+ id="saveProfileBtn"
211
+ class="btn-primary px-4 py-2 rounded"
212
+ >
213
+ Save
214
+ </button>
215
+ <button
216
+ id="cancelProfileBtn"
217
+ class="bg-gray-300 text-gray-700 px-4 py-2 rounded hover:bg-gray-400 transition"
218
+ >
219
+ Cancel
220
+ </button>
221
+ </div>
222
+ </div>
223
+ </div>
224
+ </div>
225
+ </div>
226
+
227
+ <!-- RIGHT: Mini Stats -->
228
+ <div class="w-full lg:w-1/3 flex flex-col justify-between gap-4">
229
+ <!-- Reports Uploaded -->
230
+ <div class="bg-white shadow rounded-lg p-4 flex-1 flex items-center gap-2">
231
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-[var(--tropical-indigo)]" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
232
+ <path stroke-linecap="round" stroke-linejoin="round" d="M3 7h5l2 3h11v11H3V7z" />
233
+ </svg>
234
+ <div class="flex-1">
235
+ <p class="text-sm text-gray-500">Reports Uploaded</p>
236
+ <p class="font-semibold text-lg" id="reportsCount">0</p>
237
+ </div>
238
+ </div>
239
+
240
+ <!-- Tests In Range -->
241
+ <div class="bg-white shadow rounded-lg p-4 flex-1 flex items-center gap-2">
242
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-green-400" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
243
+ <path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7" />
244
+ </svg>
245
+ <div class="flex-1">
246
+ <p class="text-sm text-gray-500">Tests In Range In Latest Report</p>
247
+ <p class="font-semibold text-lg" id="testsInRange">0</p>
248
+ </div>
249
+ </div>
250
+
251
+ <!-- Tests Out of Range -->
252
+ <div class="bg-white shadow rounded-lg p-4 flex-1 flex items-center gap-2">
253
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-red-400" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
254
+ <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
255
+ </svg>
256
+ <div class="flex-1">
257
+ <p class="text-sm text-gray-500">Tests Out of Range In Latest Report</p>
258
+ <p class="font-semibold text-lg" id="testsOutOfRange">0</p>
259
+ </div>
260
+ </div>
261
+ </div>
262
+
263
+
264
+ </div>
265
+
266
+
267
+
268
+
269
+
270
+ <!-- Reports Section -->
271
+ <div class="bg-white shadow rounded-lg p-6">
272
+ <h3 class="text-lg font-semibold text-[var(--tropical-indigo)] mb-3">
273
+ Your Reports
274
+ </h3>
275
+ <div id="reportsSection" class="text-gray-600 text-center space-y-3">
276
+ <p id="reportStatus">📂 No reports uploaded yet.</p>
277
+ <a
278
+ id="sampleReportLink"
279
+ href="/sample_report.pdf"
280
+ target="_blank"
281
+ class="text-blue-600 hover:underline hidden"
282
+ >sample_report.pdf</a
283
+ >
284
+ <div class="mt-2 flex justify-center gap-4">
285
+ <button id="uploadBtn" class="btn-primary px-4 py-2 rounded" onclick="window.location.href='analyzer.html'">
286
+ Upload Report
287
+ </button>
288
+ <button id="toggleReportBtn" class="btn-primary px-4 py-2 rounded">
289
+ Use Sample Report
290
+ </button>
291
+ </div>
292
+ </div>
293
+ </div>
294
+ </div>
295
+
296
+ <!-- Past Reports Section with Number-Line Bars -->
297
+ <div class="bg-white shadow rounded-lg p-6 mt-6 ">
298
+ <h3 class="text-lg font-semibold text-[var(--tropical-indigo)] mb-4">
299
+ Past Reports
300
+ </h3>
301
+ <div id="pastReportsSection" class="flex flex-col gap-4 ">
302
+ <!-- Report 3 -->
303
+ <div class="flex flex-col bg-[var(--wisteria)] p-4 rounded-lg shadow hover:shadow-md transition">
304
+ <div class="flex justify-between items-center cursor-pointer report-header" onclick="toggleDetails(this)">
305
+ <div class="flex items-center gap-3">
306
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-[var(--tropical-indigo)]" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
307
+ <path stroke-linecap="round" stroke-linejoin="round" d="M12 4v16m8-8H4" />
308
+ </svg>
309
+ <p class="font-medium text-gray-800">Annual_Physical_Mar2025.pdf</p>
310
+ </div>
311
+ <div class="flex gap-2 flex-shrink-0">
312
+ <span class="px-2 py-1 rounded-full bg-green-200 text-green-800 text-xs font-semibold">In Range: 2</span>
313
+ <span class="px-2 py-1 rounded-full bg-red-200 text-red-800 text-xs font-semibold">Out of Range: 0</span>
314
+ </div>
315
+ </div>
316
+ <div class="report-details mt-2 hidden w-full bg-white rounded p-3 border border-gray-300 text-gray-700">
317
+ <ul class="space-y-4 text-sm">
318
+ <li>
319
+ <div class="flex justify-between mb-1">
320
+ <span>Hemoglobin: 14.2 g/dL</span>
321
+ <span class="text-xs text-gray-500">(12-16)</span>
322
+ </div>
323
+ <div class="relative w-full h-4 bg-gray-200 rounded">
324
+ <div class="absolute h-4 rounded bg-green-400" style="width: 70.5%;"></div>
325
+ <span class="absolute -top-5 text-xs font-semibold text-gray-800" style="left: 70.5%;">14.2</span>
326
+ <div class="absolute top-full left-0 w-full flex justify-between mt-1 text-xs text-gray-500">
327
+ <span>12</span>
328
+ <span>16</span>
329
+ </div>
330
+ </div>
331
+ </li>
332
+ <li>
333
+ <div class="flex justify-between mb-1">
334
+ <span>Cholesterol: 180 mg/dL</span>
335
+ <span class="text-xs text-gray-500">(125-200)</span>
336
+ </div>
337
+ <div class="relative w-full h-6 bg-gray-200 rounded overflow-hidden">
338
+ <div class="absolute h-6 rounded bg-green-400" style="width: 90%;"></div>
339
+ <span class="absolute top-1/2 transform -translate-y-1/2 text-xs font-semibold text-gray-800" style="left: 90%;">180</span>
340
+ <div class="absolute top-full left-0 w-full flex justify-between mt-1 text-xs text-gray-500">
341
+ <span>125</span>
342
+ <span>200</span>
343
+ </div>
344
+ </div>
345
+ </li>
346
+ </ul>
347
+ </div>
348
+ </div>
349
+ <!-- Report 2 -->
350
+ <div class="flex flex-col bg-[var(--wisteria)] p-4 rounded-lg shadow hover:shadow-md transition">
351
+ <div class="flex justify-between items-center cursor-pointer report-header" onclick="toggleDetails(this)">
352
+ <div class="flex items-center gap-3">
353
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-[var(--tropical-indigo)]" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
354
+ <path stroke-linecap="round" stroke-linejoin="round" d="M12 4v16m8-8H4" />
355
+ </svg>
356
+ <p class="font-medium text-gray-800">Checkup_Feb2025.pdf</p>
357
+ </div>
358
+ <div class="flex gap-2 flex-shrink-0">
359
+ <span class="px-2 py-1 rounded-full bg-green-200 text-green-800 text-xs font-semibold">In Range: 1</span>
360
+ <span class="px-2 py-1 rounded-full bg-red-200 text-red-800 text-xs font-semibold">Out of Range: 1</span>
361
+ </div>
362
+ </div>
363
+ <div class="report-details mt-2 hidden w-full bg-white rounded p-3 border border-gray-300 text-gray-700">
364
+ <ul class="space-y-4 text-sm">
365
+ <li>
366
+ <div class="flex justify-between mb-1">
367
+ <span>Glucose: 105 mg/dL</span>
368
+ <span class="text-xs text-gray-500">(70-99)</span>
369
+ </div>
370
+ <div class="relative w-full h-4 bg-gray-200 rounded">
371
+ <div class="absolute h-4 rounded bg-red-400" style="width: calc(105/99*100%);"></div>
372
+ <span class="absolute -top-5 text-xs font-semibold text-gray-800" style="left: 100%;">105</span>
373
+ <div class="absolute top-full left-0 w-full flex justify-between mt-1 text-xs text-gray-500">
374
+ <span>70</span>
375
+ <span>99</span>
376
+ </div>
377
+ </div>
378
+ </li>
379
+ <li>
380
+ <div class="flex justify-between mb-1">
381
+ <span>Vitamin D: 40 ng/mL</span>
382
+ <span class="text-xs text-gray-500">(30-100)</span>
383
+ </div>
384
+ <div class="relative w-full h-4 bg-gray-200 rounded">
385
+ <div class="absolute h-4 rounded bg-green-400" style="width: 12.5%;"></div>
386
+ <span class="absolute -top-5 text-xs font-semibold text-gray-800" style="left: 12.5%;">40</span>
387
+ <div class="absolute top-full left-0 w-full flex justify-between mt-1 text-xs text-gray-500">
388
+ <span>30</span>
389
+ <span>100</span>
390
+ </div>
391
+ </div>
392
+ </li>
393
+ </ul>
394
+ </div>
395
+ </div>
396
+ <!-- Report 1 -->
397
+ <div class="flex flex-col bg-[var(--wisteria)] p-4 rounded-lg shadow hover:shadow-md transition">
398
+ <div class="flex justify-between items-center cursor-pointer report-header" onclick="toggleDetails(this)">
399
+ <div class="flex items-center gap-3">
400
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-[var(--tropical-indigo)]" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
401
+ <path stroke-linecap="round" stroke-linejoin="round" d="M12 4v16m8-8H4" />
402
+ </svg>
403
+ <p class="font-medium text-gray-800">Bloodwork_Jan2025.pdf</p>
404
+ </div>
405
+ <div class="flex gap-2 flex-shrink-0">
406
+ <span class="px-2 py-1 rounded-full bg-green-200 text-green-800 text-xs font-semibold">In Range: 1</span>
407
+ <span class="px-2 py-1 rounded-full bg-red-200 text-red-800 text-xs font-semibold">Out of Range: 1</span>
408
+ </div>
409
+ </div>
410
+ <div class="report-details mt-2 hidden w-full bg-white rounded p-3 border border-gray-300 text-gray-700">
411
+ <ul class="space-y-4 text-sm">
412
+ <li>
413
+ <div class="flex justify-between mb-1">
414
+ <span>Hemoglobin: 13.5 g/dL</span>
415
+ <span class="text-xs text-gray-500">(12-16)</span>
416
+ </div>
417
+ <div class="relative w-full h-4 bg-gray-200 rounded">
418
+ <div class="absolute h-4 rounded bg-green-400" style="width: 56.25%;"></div>
419
+ <span class="absolute -top-5 text-xs font-semibold text-gray-800" style="left: 56.25%;">13.5</span>
420
+ <div class="absolute top-full left-0 w-full flex justify-between mt-1 text-xs text-gray-500">
421
+ <span>12</span>
422
+ <span>16</span>
423
+ </div>
424
+ </div>
425
+ </li>
426
+ <li>
427
+ <div class="flex justify-between mb-1">
428
+ <span>Cholesterol: 210 mg/dL</span>
429
+ <span class="text-xs text-gray-500">(125-200)</span>
430
+ </div>
431
+ <div class="relative w-full h-6 bg-gray-200 rounded overflow-hidden">
432
+ <div class="absolute h-6 rounded" style="width: calc(min(210/200*100%, 100%)); background-color: #f87171;"></div>
433
+ <span class="absolute top-1/2 transform -translate-y-1/2 text-xs font-semibold text-gray-800" style="left: calc(min(210/200*100%, 95%));">210</span>
434
+ <div class="absolute top-full left-0 w-full flex justify-between mt-1 text-xs text-gray-500">
435
+ <span>125</span>
436
+ <span>200</span>
437
+ </div>
438
+ </div>
439
+ </li>
440
+ </ul>
441
+ </div>
442
+ </div>
443
+
444
+
445
+
446
+
447
+
448
+ </div>
449
+ </div>
450
+
451
+ <script>
452
+ function toggleDetails(element) {
453
+ const details = element.parentElement.querySelector('.report-details');
454
+ if (details) details.classList.toggle('hidden');
455
+ }
456
+ </script>
457
+
458
+
459
+
460
+ </main>
461
+
462
+
463
+
464
+ <footer class="py-6 bg-[var(--wisteria)] text-gray-800 mt-8">
465
+ <div
466
+ class="max-w-6xl mx-auto px-6 flex flex-col md:flex-row justify-between items-center text-sm"
467
+ >
468
+ <p>&copy; 2025 CTRL + ALT + HEAL. All rights reserved.</p>
469
+ <div class="flex space-x-4 mt-3 md:mt-0">
470
+ <a href="#" class="hover:text-[var(--tropical-indigo)] transition"
471
+ >Privacy Policy</a
472
+ >
473
+ <a href="#" class="hover:text-[var(--tropical-indigo)] transition"
474
+ >Terms of Service</a
475
+ >
476
+ </div>
477
+ </div>
478
+ </footer>
479
+
480
+ <script>
481
+ // Profile Section
482
+ const profileView = document.getElementById("profileViewSection");
483
+ const profileEdit = document.getElementById("profileEditSection");
484
+ const editBtn = document.getElementById("editProfileBtn");
485
+ const saveBtn = document.getElementById("saveProfileBtn");
486
+ const cancelBtn = document.getElementById("cancelProfileBtn");
487
+
488
+ const inputName = document.getElementById("inputName");
489
+ const inputDOB = document.getElementById("inputDOB");
490
+ const inputFix = document.getElementById("inputFix");
491
+ const inputGoals = document.getElementById("inputGoals");
492
+
493
+ const profilePic = document.getElementById("profilePic");
494
+ const editProfilePic = document.getElementById("editProfilePic");
495
+ const fileInput = document.getElementById("fileInput");
496
+ const editFileInput = document.getElementById("editFileInput");
497
+
498
+ editBtn.addEventListener("click", () => {
499
+ inputName.value = localStorage.getItem("userName") || "";
500
+ inputDOB.value = localStorage.getItem("userDOB") || "";
501
+ inputFix.value = localStorage.getItem("userFix") || "";
502
+ inputGoals.value = localStorage.getItem("userGoals") || "";
503
+ profileView.classList.add("hidden");
504
+ profileEdit.classList.remove("hidden");
505
+ });
506
+
507
+ cancelBtn.addEventListener("click", () => {
508
+ profileEdit.classList.add("hidden");
509
+ profileView.classList.remove("hidden");
510
+ });
511
+
512
+ saveBtn.addEventListener("click", () => {
513
+ localStorage.setItem("userName", inputName.value.trim());
514
+ localStorage.setItem("userDOB", inputDOB.value);
515
+ localStorage.setItem("userFix", inputFix.value.trim());
516
+ localStorage.setItem("userGoals", inputGoals.value.trim());
517
+
518
+ document.getElementById("userName").textContent =
519
+ inputName.value.trim() || "Name";
520
+ document.getElementById("userDOB").textContent =
521
+ inputDOB.value || "DOB";
522
+ document.getElementById("userFix").textContent =
523
+ inputFix.value.trim() || "None set";
524
+ document.getElementById("userGoals").textContent =
525
+ inputGoals.value.trim() || "None set";
526
+
527
+ profileEdit.classList.add("hidden");
528
+ profileView.classList.remove("hidden");
529
+ });
530
+
531
+ profilePic.addEventListener("click", () => fileInput.click());
532
+ editProfilePic.addEventListener("click", () => editFileInput.click());
533
+
534
+ function handleFileUpload(file, targetImg) {
535
+ const reader = new FileReader();
536
+ reader.onload = () => {
537
+ targetImg.src = reader.result;
538
+ localStorage.setItem("profilePic", reader.result);
539
+ };
540
+ reader.readAsDataURL(file);
541
+ }
542
+
543
+ fileInput.addEventListener("change", (e) => {
544
+ if (e.target.files[0]) handleFileUpload(e.target.files[0], profilePic);
545
+ });
546
+ editFileInput.addEventListener("change", (e) => {
547
+ if (e.target.files[0])
548
+ handleFileUpload(e.target.files[0], editProfilePic);
549
+ });
550
+
551
+ // Load saved profile
552
+ document.addEventListener("DOMContentLoaded", () => {
553
+ document.getElementById("userName").textContent =
554
+ localStorage.getItem("userName") || "Name";
555
+ document.getElementById("userDOB").textContent =
556
+ localStorage.getItem("userDOB") || "DOB";
557
+ document.getElementById("userFix").textContent =
558
+ localStorage.getItem("userFix") || "None set";
559
+ document.getElementById("userGoals").textContent =
560
+ localStorage.getItem("userGoals") || "None set";
561
+
562
+ const savedPic = localStorage.getItem("profilePic");
563
+ if (savedPic) {
564
+ profilePic.src = savedPic;
565
+ editProfilePic.src = savedPic;
566
+ }
567
+ });
568
+ const pastReportsSection = document.getElementById("pastReportsSection");
569
+ const togglePastReportsBtn = document.getElementById("togglePastReportsBtn");
570
+
571
+ togglePastReportsBtn.addEventListener("click", () => {
572
+ pastReportsSection.classList.toggle("hidden");
573
+ });
574
+
575
+
576
+ // Toggle Sample Report
577
+ const reportsCountEl = document.getElementById("reportsCount");
578
+ const goalsCompletedEl = document.getElementById("goalsCompleted");
579
+ const achievementsEl = document.getElementById("achievements");
580
+ const reportStatusEl = document.getElementById("reportStatus");
581
+ const sampleReportLink = document.getElementById("sampleReportLink");
582
+ const toggleReportBtn = document.getElementById("toggleReportBtn");
583
+
584
+ let sampleActive = false;
585
+
586
+ const sampleReport = {
587
+ name: "sample_report.pdf",
588
+ goalsCompleted: 2,
589
+ totalGoals: 2,
590
+ improvements: ["Hydration", "Sleep", "Exercise"],
591
+ };
592
+ function updateMiniStats() {
593
+ if (sampleActive) {
594
+ reportsCountEl.textContent = 1;
595
+
596
+ // Count tests in range vs out of range
597
+ const inRange = sampleReport.goalsCompleted; // using sample data
598
+ const outOfRange = sampleReport.totalGoals - sampleReport.goalsCompleted;
599
+
600
+ document.getElementById("testsInRange").textContent = inRange;
601
+ document.getElementById("testsOutOfRange").textContent = outOfRange;
602
+
603
+ reportStatusEl.textContent = "📂 Sample report uploaded!";
604
+ sampleReportLink.classList.remove("hidden");
605
+ } else {
606
+ reportsCountEl.textContent = 0;
607
+ document.getElementById("testsInRange").textContent = 0;
608
+ document.getElementById("testsOutOfRange").textContent = 0;
609
+ reportStatusEl.textContent = "📂 No reports uploaded yet.";
610
+ sampleReportLink.classList.add("hidden");
611
+ }
612
+ }
613
+
614
+
615
+ toggleReportBtn.addEventListener("click", () => {
616
+ sampleActive = !sampleActive;
617
+ updateMiniStats();
618
+ });
619
+
620
+ updateMiniStats();
621
+
622
+ </script>
623
+ </body>
624
+ </html>