Sameh108 commited on
Commit
333c8a0
·
verified ·
1 Parent(s): a4f0bb0

add show suggestion button

Browse files
Files changed (1) hide show
  1. templates/index.html +164 -58
templates/index.html CHANGED
@@ -4,95 +4,201 @@
4
  <meta charset="UTF-8" />
5
  <link rel="icon" type="image/svg+xml" href="/brain.svg" />
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
- <meta name="description" content="NeuraScan - Advanced AI-powered brain MRI Alzheimer's disease analysis tool for medical professionals" />
8
- <meta name="author" content="Team 2 Batch 59 Biomedical Engineering Department Faculty of Engineering Helwan University" />
9
- <title>NeuraScan | AI Brain MRI Alzheimer's Disease Analysis</title>
10
  <script type="module" crossorigin src="/assets/index-DBG8gcSd.js"></script>
11
  <link rel="stylesheet" crossorigin href="/assets/index-CtQJEsfm.css">
12
 
13
  <style>
14
- #new-scan-btn {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  position: fixed;
16
  bottom: 20px;
17
  right: 20px;
18
- background-color: #2563eb; /* Blue to match medical theme */
19
  color: white;
20
  border: none;
21
  padding: 12px 24px;
22
  border-radius: 50px;
23
- font-family: system-ui, -apple-system, sans-serif;
24
- font-weight: 600;
25
  cursor: pointer;
26
- box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
27
- transition: all 0.2s;
28
- z-index: 9999;
29
- display: none; /* Hidden by default until needed */
30
- }
31
- #new-scan-btn:hover {
32
- background-color: #1d4ed8;
33
- transform: translateY(-2px);
34
- box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
35
  }
 
 
36
  </style>
37
  </head>
38
  <body>
 
39
  <div id="root"></div>
40
 
41
- <button id="new-scan-btn" onclick="resetApp()">Start New Scan</button>
 
 
42
 
43
- <script>
44
- // --- Feature 1: The "New Scan" Button ---
45
- // Since we can't easily reset React's state from outside,
46
- // the cleanest way to "clear" the result is to reload the page.
47
- function resetApp() {
48
- window.location.reload();
49
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
 
51
- // Automatically show the button when the user clicks "Analyze"
52
- // (We guess this by listening for clicks on the page)
53
- document.addEventListener('click', function(e) {
54
- // Simple logic: If they clicked a button, show the "New Scan" option after 2 seconds
55
- if (e.target.tagName === 'BUTTON' && e.target.id !== 'new-scan-btn') {
 
 
 
 
 
 
56
  setTimeout(() => {
57
- document.getElementById('new-scan-btn').style.display = 'block';
58
- }, 2000);
 
 
 
 
 
 
 
 
59
  }
60
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
 
62
- // --- Feature 2: Clipboard Paste Support (Ctrl+V) ---
63
  document.addEventListener('paste', function(event) {
64
- // 1. Find the file input in the React app
65
  const fileInput = document.querySelector('input[type="file"]');
66
-
67
- if (!fileInput) {
68
- console.log("No file input found. You might be on the results screen.");
69
- return;
70
- }
71
 
72
- // 2. Get the image from clipboard
73
  const items = (event.clipboardData || event.originalEvent.clipboardData).items;
74
- let blob = null;
75
-
76
  for (let i = 0; i < items.length; i++) {
77
  if (items[i].type.indexOf('image') !== -1) {
78
- blob = items[i].getAsFile();
79
- break;
 
 
 
 
 
 
 
 
 
80
  }
81
  }
82
-
83
- // 3. Force the image into React
84
- if (blob) {
85
- // We need to simulate a proper file upload event
86
- const dataTransfer = new DataTransfer();
87
- dataTransfer.items.add(blob);
88
- fileInput.files = dataTransfer.files;
89
-
90
- // Dispatch the 'change' event so React notices the new file
91
- const changeEvent = new Event('change', { bubbles: true });
92
- fileInput.dispatchEvent(changeEvent);
93
-
94
- console.log("Image pasted successfully!");
95
- }
96
  });
97
  </script>
98
  </body>
 
4
  <meta charset="UTF-8" />
5
  <link rel="icon" type="image/svg+xml" href="/brain.svg" />
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <meta name="description" content="NeuraScan - Advanced AI-powered brain MRI Alzheimer's disease analysis tool" />
8
+ <title>NeuraScan | AI Brain MRI Analysis</title>
9
+
10
  <script type="module" crossorigin src="/assets/index-DBG8gcSd.js"></script>
11
  <link rel="stylesheet" crossorigin href="/assets/index-CtQJEsfm.css">
12
 
13
  <style>
14
+ #uncertainty-modal {
15
+ display: none;
16
+ position: fixed;
17
+ bottom: 20px;
18
+ left: 50%;
19
+ transform: translateX(-50%);
20
+ width: 90%;
21
+ max-width: 480px;
22
+ background: #ffffff;
23
+ border-radius: 16px;
24
+ box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
25
+ z-index: 10000;
26
+ padding: 24px;
27
+ border: 1px solid #fee2e2;
28
+ font-family: system-ui, -apple-system, sans-serif;
29
+ animation: slideUp 0.5s cubic-bezier(0.16, 1, 0.3, 1);
30
+ }
31
+
32
+ @keyframes slideUp {
33
+ from { transform: translate(-50%, 100%); opacity: 0; }
34
+ to { transform: translate(-50%, 0); opacity: 1; }
35
+ }
36
+
37
+ .modal-header {
38
+ display: flex;
39
+ align-items: center;
40
+ gap: 12px;
41
+ color: #991b1b;
42
+ margin-bottom: 12px;
43
+ }
44
+
45
+ .modal-title { font-weight: 700; font-size: 1.125rem; }
46
+
47
+ .modal-body {
48
+ color: #374151;
49
+ font-size: 0.95rem;
50
+ line-height: 1.6;
51
+ margin-bottom: 20px;
52
+ }
53
+
54
+ .suggestion-box {
55
+ background: #eff6ff;
56
+ padding: 16px;
57
+ border-radius: 8px;
58
+ margin-top: 15px;
59
+ display: none;
60
+ border-left: 4px solid #3b82f6;
61
+ color: #1e3a8a;
62
+ }
63
+
64
+ .btn-group { display: flex; gap: 12px; margin-top: 5px; }
65
+
66
+ .btn {
67
+ flex: 1;
68
+ padding: 10px 16px;
69
+ border: none;
70
+ border-radius: 8px;
71
+ font-weight: 600;
72
+ cursor: pointer;
73
+ transition: all 0.2s;
74
+ font-size: 0.9rem;
75
+ }
76
+
77
+ .btn-reveal {
78
+ background-color: #2563eb;
79
+ color: white;
80
+ box-shadow: 0 4px 6px -1px rgba(37, 99, 235, 0.2);
81
+ }
82
+ .btn-reveal:hover { background-color: #1d4ed8; transform: translateY(-1px); }
83
+
84
+ .btn-reset {
85
+ background-color: #f3f4f6;
86
+ color: #4b5563;
87
+ border: 1px solid #e5e7eb;
88
+ }
89
+ .btn-reset:hover { background-color: #e5e7eb; }
90
+
91
+ #global-reset-btn {
92
  position: fixed;
93
  bottom: 20px;
94
  right: 20px;
95
+ background: #10b981;
96
  color: white;
97
  border: none;
98
  padding: 12px 24px;
99
  border-radius: 50px;
 
 
100
  cursor: pointer;
101
+ font-weight: 600;
102
+ z-index: 999;
103
+ display: none;
104
+ box-shadow: 0 4px 10px rgba(16, 185, 129, 0.3);
105
+ transition: transform 0.2s;
 
 
 
 
106
  }
107
+ #global-reset-btn:hover { transform: scale(1.05); }
108
+
109
  </style>
110
  </head>
111
  <body>
112
+
113
  <div id="root"></div>
114
 
115
+ <button id="global-reset-btn" onclick="window.location.reload()">
116
+ <span style="font-size: 1.2em; vertical-align: middle;">↻</span> New Scan
117
+ </button>
118
 
119
+ <div id="uncertainty-modal">
120
+ <div class="modal-header">
121
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"></path><line x1="12" y1="9" x2="12" y2="13"></line><line x1="12" y1="17" x2="12.01" y2="17"></line></svg>
122
+ <div class="modal-title">Low Confidence Warning</div>
123
+ </div>
124
+
125
+ <div class="modal-body">
126
+ The model is less than <strong>80% confident</strong>.
127
+ <br>This result is marked as "Not Sure" for safety.
128
+ <br>Would you like to see the AI's best guess?
129
+
130
+ <div id="suggestion-content" class="suggestion-box">
131
+ <strong>Top Suggestion:</strong> <span id="suggestion-text" style="font-size: 1.1em; font-weight: bold;">---</span>
132
+ </div>
133
+ </div>
134
+
135
+ <div class="btn-group">
136
+ <button class="btn btn-reset" onclick="window.location.reload()">Try Another Image</button>
137
+ <button class="btn btn-reveal" id="reveal-btn" onclick="revealSuggestion()">Show Suggestion</button>
138
+ </div>
139
+ </div>
140
 
141
+ <script>
142
+
143
+ const originalFetch = window.fetch;
144
+
145
+ window.fetch = async function(...args) {
146
+ const response = await originalFetch(...args);
147
+
148
+ const url = args[0].toString();
149
+
150
+ if (url.includes('/api/classify') && response.ok) {
151
+
152
  setTimeout(() => {
153
+ document.getElementById('global-reset-btn').style.display = 'block';
154
+ }, 1000);
155
+
156
+ const clone = response.clone();
157
+
158
+ clone.json().then(data => {
159
+ if (data.is_uncertain === true) {
160
+ showUncertaintyModal(data.top_class_suggestion);
161
+ }
162
+ }).catch(err => console.log("Silent interceptor error:", err));
163
  }
164
+
165
+ return response;
166
+ };
167
+
168
+ function showUncertaintyModal(suggestion) {
169
+ const modal = document.getElementById('uncertainty-modal');
170
+ const textSpan = document.getElementById('suggestion-text');
171
+
172
+ textSpan.innerText = suggestion || "Unknown Class";
173
+ modal.style.display = 'block';
174
+ }
175
+
176
+ function revealSuggestion() {
177
+ document.getElementById('suggestion-content').style.display = 'block';
178
+ document.getElementById('reveal-btn').style.display = 'none';
179
+ }
180
 
 
181
  document.addEventListener('paste', function(event) {
 
182
  const fileInput = document.querySelector('input[type="file"]');
183
+ if (!fileInput) return;
 
 
 
 
184
 
 
185
  const items = (event.clipboardData || event.originalEvent.clipboardData).items;
186
+
 
187
  for (let i = 0; i < items.length; i++) {
188
  if (items[i].type.indexOf('image') !== -1) {
189
+ const blob = items[i].getAsFile();
190
+
191
+ const dataTransfer = new DataTransfer();
192
+ dataTransfer.items.add(blob);
193
+ fileInput.files = dataTransfer.files;
194
+
195
+ const changeEvent = new Event('change', { bubbles: true });
196
+ fileInput.dispatchEvent(changeEvent);
197
+
198
+ console.log("Image pasted directly from clipboard!");
199
+ break;
200
  }
201
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
202
  });
203
  </script>
204
  </body>