Subh775 commited on
Commit
9db75b8
·
1 Parent(s): 4ca0250

minor improvements; fixes..

Browse files
Files changed (3) hide show
  1. static/app.js +45 -22
  2. static/index.html +4 -11
  3. static/style.css +61 -7
static/app.js CHANGED
@@ -20,7 +20,7 @@ let currentPersona = localStorage.getItem('stemcopilot_persona') || 'vidyut';
20
  let currentLanguage = localStorage.getItem('stemcopilot_language') || 'auto';
21
  let currentUsername = localStorage.getItem('stemcopilot_username') || '';
22
 
23
- const _PERSONA_LABELS = { vidyut: 'Vidyut', nerd: 'Nerd', noob: 'Beginner', thoughtful: 'Thoughtful', panic: 'Panic' };
24
 
25
 
26
  /* ── DOM References ─────────────────────────────────────────── */
@@ -104,7 +104,6 @@ const historyOverlayClose = document.getElementById('historyOverlayClose');
104
  const overlayHistoryList = document.getElementById('overlayHistoryList');
105
  const overlayHistoryEmpty = document.getElementById('overlayHistoryEmpty');
106
  const overlaySettingsBtn = document.getElementById('overlaySettingsBtn');
107
- const overlayProfileBtn = document.getElementById('overlayProfileBtn');
108
  const overlayLogoutBtn = document.getElementById('overlayLogoutBtn');
109
  const overlayUserAvatar = document.getElementById('overlayUserAvatar');
110
  const overlayUserName = document.getElementById('overlayUserName');
@@ -473,23 +472,14 @@ if (overlaySettingsBtn) overlaySettingsBtn.addEventListener('click', () => {
473
  settingsOverlay.classList.add('show');
474
  });
475
 
476
- if (overlayProfileBtn) overlayProfileBtn.addEventListener('click', () => {
477
- _closeAllOverlays();
478
- // Open settings on Profile tab
479
- document.querySelectorAll('.settings-nav-btn').forEach(b => b.classList.remove('active'));
480
- document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
481
- const btn = document.querySelector('.settings-nav-btn[data-tab="personalization"]');
482
- const tab = document.getElementById('tab-personalization');
483
- if (btn) btn.classList.add('active');
484
- if (tab) tab.classList.add('active');
485
- settingsOverlay.classList.add('show');
486
- });
487
 
488
  if (overlayLogoutBtn) overlayLogoutBtn.addEventListener('click', () => {
489
- localStorage.removeItem('stemcopilot_user');
490
- localStorage.removeItem('stemcopilot_username');
491
- currentUser = null;
492
- location.reload();
 
 
493
  });
494
 
495
  function _renderOverlayHistory() {
@@ -501,16 +491,49 @@ function _renderOverlayHistory() {
501
  }
502
  if (overlayHistoryEmpty) overlayHistoryEmpty.style.display = 'none';
503
  threads.forEach(thread => {
504
- const item = document.createElement('button');
505
  item.className = `overlay-history-item ${thread.id === currentThreadId ? 'active' : ''}`;
506
  item.innerHTML = `
507
- <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>
508
- <span class="overlay-history-title">${escapeHtml(thread.title)}</span>
 
 
 
 
 
 
 
 
 
 
509
  `;
510
- item.addEventListener('click', () => {
511
  _closeAllOverlays();
512
  loadThread(thread.id);
513
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
514
  overlayHistoryList.appendChild(item);
515
  });
516
  }
@@ -770,7 +793,7 @@ if (userProfileBtn) userProfileBtn.addEventListener('click', (e) => { e.stopProp
770
  if (openSettingsBtn) openSettingsBtn.addEventListener('click', () => { userMenu.classList.remove('show'); settingsOverlay.classList.add('show'); });
771
  if (settingsCloseBtn) settingsCloseBtn.addEventListener('click', () => settingsOverlay.classList.remove('show'));
772
  if (settingsOverlay) settingsOverlay.addEventListener('click', (e) => { if (e.target === settingsOverlay) settingsOverlay.classList.remove('show'); });
773
- if (logoutBtn) logoutBtn.addEventListener('click', () => { localStorage.removeItem('stemcopilot_user'); localStorage.removeItem('stemcopilot_username'); currentUser = null; location.reload(); });
774
 
775
  document.querySelectorAll('.settings-nav-btn').forEach(btn => {
776
  btn.addEventListener('click', () => {
 
20
  let currentLanguage = localStorage.getItem('stemcopilot_language') || 'auto';
21
  let currentUsername = localStorage.getItem('stemcopilot_username') || '';
22
 
23
+ const _PERSONA_LABELS = { vidyut: 'Guru', nerd: 'Nerd', noob: 'Beginner', thoughtful: 'Thoughtful', panic: 'Panic' };
24
 
25
 
26
  /* ── DOM References ─────────────────────────────────────────── */
 
104
  const overlayHistoryList = document.getElementById('overlayHistoryList');
105
  const overlayHistoryEmpty = document.getElementById('overlayHistoryEmpty');
106
  const overlaySettingsBtn = document.getElementById('overlaySettingsBtn');
 
107
  const overlayLogoutBtn = document.getElementById('overlayLogoutBtn');
108
  const overlayUserAvatar = document.getElementById('overlayUserAvatar');
109
  const overlayUserName = document.getElementById('overlayUserName');
 
472
  settingsOverlay.classList.add('show');
473
  });
474
 
 
 
 
 
 
 
 
 
 
 
 
475
 
476
  if (overlayLogoutBtn) overlayLogoutBtn.addEventListener('click', () => {
477
+ if (confirm('Do you want to log out?')) {
478
+ localStorage.removeItem('stemcopilot_user');
479
+ localStorage.removeItem('stemcopilot_username');
480
+ currentUser = null;
481
+ location.reload();
482
+ }
483
  });
484
 
485
  function _renderOverlayHistory() {
 
491
  }
492
  if (overlayHistoryEmpty) overlayHistoryEmpty.style.display = 'none';
493
  threads.forEach(thread => {
494
+ const item = document.createElement('div');
495
  item.className = `overlay-history-item ${thread.id === currentThreadId ? 'active' : ''}`;
496
  item.innerHTML = `
497
+ <div class="overlay-history-main">
498
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>
499
+ <span class="overlay-history-title">${escapeHtml(thread.title)}</span>
500
+ </div>
501
+ <div class="overlay-history-actions">
502
+ <button class="overlay-action-btn" data-action="rename" title="Rename">
503
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 20h9"/><path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z"/></svg>
504
+ </button>
505
+ <button class="overlay-action-btn overlay-action-delete" data-action="delete" title="Delete">
506
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/></svg>
507
+ </button>
508
+ </div>
509
  `;
510
+ item.querySelector('.overlay-history-main').addEventListener('click', () => {
511
  _closeAllOverlays();
512
  loadThread(thread.id);
513
  });
514
+ item.querySelector('[data-action="rename"]').addEventListener('click', (e) => {
515
+ e.stopPropagation();
516
+ const newTitle = prompt('Rename chat:', thread.title);
517
+ if (newTitle && newTitle.trim()) {
518
+ fetch('/rename', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ thread_id: thread.id, title: newTitle.trim() }) })
519
+ .then(() => { thread.title = newTitle.trim(); _renderOverlayHistory(); renderHistory(); })
520
+ .catch(() => showToast('Failed to rename.', 'error'));
521
+ }
522
+ });
523
+ item.querySelector('[data-action="delete"]').addEventListener('click', (e) => {
524
+ e.stopPropagation();
525
+ if (confirm('Delete this chat?')) {
526
+ fetch('/thread/' + thread.id, { method: 'DELETE' })
527
+ .then(() => {
528
+ const idx = threads.findIndex(t => t.id === thread.id);
529
+ if (idx !== -1) threads.splice(idx, 1);
530
+ if (thread.id === currentThreadId) startNewChat();
531
+ _renderOverlayHistory();
532
+ renderHistory();
533
+ })
534
+ .catch(() => showToast('Failed to delete.', 'error'));
535
+ }
536
+ });
537
  overlayHistoryList.appendChild(item);
538
  });
539
  }
 
793
  if (openSettingsBtn) openSettingsBtn.addEventListener('click', () => { userMenu.classList.remove('show'); settingsOverlay.classList.add('show'); });
794
  if (settingsCloseBtn) settingsCloseBtn.addEventListener('click', () => settingsOverlay.classList.remove('show'));
795
  if (settingsOverlay) settingsOverlay.addEventListener('click', (e) => { if (e.target === settingsOverlay) settingsOverlay.classList.remove('show'); });
796
+ if (logoutBtn) logoutBtn.addEventListener('click', () => { if (confirm('Do you want to log out?')) { localStorage.removeItem('stemcopilot_user'); localStorage.removeItem('stemcopilot_username'); currentUser = null; location.reload(); } });
797
 
798
  document.querySelectorAll('.settings-nav-btn').forEach(btn => {
799
  btn.addEventListener('click', () => {
static/index.html CHANGED
@@ -69,7 +69,7 @@
69
  <span>Sign in with Google</span>
70
  </button>
71
  </div>
72
- <p class="login-footer">By signing in, you agree to our Terms of Service.</p>
73
  </div>
74
  </div>
75
 
@@ -150,13 +150,6 @@
150
  </svg>
151
  Settings
152
  </button>
153
- <button class="overlay-menu-item" id="overlayProfileBtn">
154
- <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
155
- <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" />
156
- <circle cx="12" cy="7" r="4" />
157
- </svg>
158
- Profile
159
- </button>
160
  <button class="overlay-menu-item overlay-menu-logout" id="overlayLogoutBtn">
161
  <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
162
  <path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" />
@@ -300,7 +293,7 @@
300
  </button>
301
  <div class="style-dropdown" id="heroStyleDropdown">
302
  <div class="style-option active" data-persona="vidyut">
303
- <div class="style-option-name">Vidyut</div>
304
  <div class="style-option-desc">Calm, clear, step-by-step master teacher. Makes hard concepts obvious.</div>
305
  </div>
306
  <div class="style-option" data-persona="nerd">
@@ -353,12 +346,12 @@
353
  <!-- Teaching style selector -->
354
  <div class="style-selector-wrap" id="styleSelectorWrap">
355
  <button class="style-selector-btn" id="styleSelectorBtn" title="Teaching style">
356
- <span id="styleSelectorLabel">Vidyut</span>
357
  <svg viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9" /></svg>
358
  </button>
359
  <div class="style-dropdown" id="styleDropdown">
360
  <div class="style-option active" data-persona="vidyut">
361
- <div class="style-option-name">Vidyut</div>
362
  <div class="style-option-desc">Calm, clear, step-by-step master teacher. Makes hard concepts obvious.</div>
363
  </div>
364
  <div class="style-option" data-persona="nerd">
 
69
  <span>Sign in with Google</span>
70
  </button>
71
  </div>
72
+ <p class="login-footer">By signing in, you agree to our <a href="https://www.stembotix.com/terms-policy" target="_blank" rel="noopener" class="terms-link">Terms of Service</a>.</p>
73
  </div>
74
  </div>
75
 
 
150
  </svg>
151
  Settings
152
  </button>
 
 
 
 
 
 
 
153
  <button class="overlay-menu-item overlay-menu-logout" id="overlayLogoutBtn">
154
  <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
155
  <path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" />
 
293
  </button>
294
  <div class="style-dropdown" id="heroStyleDropdown">
295
  <div class="style-option active" data-persona="vidyut">
296
+ <div class="style-option-name">Guru</div>
297
  <div class="style-option-desc">Calm, clear, step-by-step master teacher. Makes hard concepts obvious.</div>
298
  </div>
299
  <div class="style-option" data-persona="nerd">
 
346
  <!-- Teaching style selector -->
347
  <div class="style-selector-wrap" id="styleSelectorWrap">
348
  <button class="style-selector-btn" id="styleSelectorBtn" title="Teaching style">
349
+ <span id="styleSelectorLabel">Guru</span>
350
  <svg viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9" /></svg>
351
  </button>
352
  <div class="style-dropdown" id="styleDropdown">
353
  <div class="style-option active" data-persona="vidyut">
354
+ <div class="style-option-name">Guru</div>
355
  <div class="style-option-desc">Calm, clear, step-by-step master teacher. Makes hard concepts obvious.</div>
356
  </div>
357
  <div class="style-option" data-persona="nerd">
static/style.css CHANGED
@@ -211,11 +211,23 @@ textarea, input, select {
211
  }
212
 
213
  .login-footer {
214
- font-size: 11px;
215
- color: var(--text-muted);
216
  margin-top: 16px;
217
  }
218
 
 
 
 
 
 
 
 
 
 
 
 
 
219
 
220
  /* ============================================================
221
  BYOK ONBOARDING
@@ -583,14 +595,15 @@ textarea, input, select {
583
  }
584
 
585
  .overlay-history-item {
586
- padding: 12px 14px;
587
  border-radius: 10px;
588
  cursor: pointer;
589
  color: var(--text-secondary);
590
  font-size: 14px;
591
  display: flex;
592
  align-items: center;
593
- gap: 10px;
 
594
  transition: background 0.2s, color 0.2s;
595
  border: none;
596
  background: none;
@@ -599,6 +612,47 @@ textarea, input, select {
599
  font-family: inherit;
600
  }
601
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
602
  .overlay-history-item:hover,
603
  .overlay-history-item:active {
604
  background: var(--bg-hover);
@@ -1019,8 +1073,8 @@ textarea, input, select {
1019
  }
1020
 
1021
  .hero-bot-icon {
1022
- width: 120px;
1023
- height: 120px;
1024
  object-fit: contain;
1025
  filter: drop-shadow(0 8px 24px var(--brand-glow));
1026
  }
@@ -2066,7 +2120,7 @@ textarea, input, select {
2066
  }
2067
 
2068
  .hero-title { font-size: 22px; }
2069
- .hero-bot-icon { width: 80px; height: 80px; }
2070
 
2071
  .hero-welcome {
2072
  justify-content: center;
 
211
  }
212
 
213
  .login-footer {
214
+ font-size: 13px;
215
+ color: var(--text-secondary);
216
  margin-top: 16px;
217
  }
218
 
219
+ .terms-link {
220
+ color: #EC642B;
221
+ font-weight: 600;
222
+ text-decoration: underline;
223
+ text-underline-offset: 2px;
224
+ transition: opacity 0.2s;
225
+ }
226
+
227
+ .terms-link:hover { opacity: 0.8; }
228
+
229
+ [data-theme="light"] .terms-link { color: #2C2872; }
230
+
231
 
232
  /* ============================================================
233
  BYOK ONBOARDING
 
595
  }
596
 
597
  .overlay-history-item {
598
+ padding: 10px 14px;
599
  border-radius: 10px;
600
  cursor: pointer;
601
  color: var(--text-secondary);
602
  font-size: 14px;
603
  display: flex;
604
  align-items: center;
605
+ justify-content: space-between;
606
+ gap: 8px;
607
  transition: background 0.2s, color 0.2s;
608
  border: none;
609
  background: none;
 
612
  font-family: inherit;
613
  }
614
 
615
+ .overlay-history-main {
616
+ display: flex;
617
+ align-items: center;
618
+ gap: 10px;
619
+ flex: 1;
620
+ min-width: 0;
621
+ cursor: pointer;
622
+ }
623
+
624
+ .overlay-history-actions {
625
+ display: flex;
626
+ gap: 4px;
627
+ flex-shrink: 0;
628
+ opacity: 0.5;
629
+ transition: opacity 0.2s;
630
+ }
631
+
632
+ .overlay-history-item:hover .overlay-history-actions { opacity: 1; }
633
+
634
+ .overlay-action-btn {
635
+ background: none;
636
+ border: none;
637
+ color: var(--text-muted);
638
+ cursor: pointer;
639
+ padding: 4px;
640
+ border-radius: 6px;
641
+ display: flex;
642
+ align-items: center;
643
+ justify-content: center;
644
+ transition: background 0.2s, color 0.2s;
645
+ }
646
+
647
+ .overlay-action-btn:hover {
648
+ background: var(--bg-hover);
649
+ color: var(--text-primary);
650
+ }
651
+
652
+ .overlay-action-delete:hover {
653
+ color: #ff4a4a;
654
+ }
655
+
656
  .overlay-history-item:hover,
657
  .overlay-history-item:active {
658
  background: var(--bg-hover);
 
1073
  }
1074
 
1075
  .hero-bot-icon {
1076
+ width: 160px;
1077
+ height: 160px;
1078
  object-fit: contain;
1079
  filter: drop-shadow(0 8px 24px var(--brand-glow));
1080
  }
 
2120
  }
2121
 
2122
  .hero-title { font-size: 22px; }
2123
+ .hero-bot-icon { width: 110px; height: 110px; }
2124
 
2125
  .hero-welcome {
2126
  justify-content: center;