afaceuser09 commited on
Commit
059ce2b
·
verified ·
1 Parent(s): d2c4592

Update static/index.html

Browse files
Files changed (1) hide show
  1. static/index.html +1 -79
static/index.html CHANGED
@@ -109,21 +109,17 @@ href="https://cdn.jsdelivr.net/npm/katex@0.16.10/dist/katex.min.css">
109
  line-height:1.8;
110
  font-size:16px;
111
  }
112
-
113
  .ai-response p{
114
  margin:1em 0;
115
  }
116
-
117
  .ai-response ul,
118
  .ai-response ol{
119
  margin:1em 0;
120
  padding-left:2rem;
121
  }
122
-
123
  .ai-response li{
124
  margin:.5em 0;
125
  }
126
-
127
  .ai-response pre{
128
  overflow:auto;
129
  padding:16px;
@@ -131,22 +127,18 @@ href="https://cdn.jsdelivr.net/npm/katex@0.16.10/dist/katex.min.css">
131
  background:#111827;
132
  color:white;
133
  }
134
-
135
  /* Gradio-style Clean Code Blocks */
136
  .ai-response code {
137
  font-family: Consolas, Montserrat, monospace;
138
  font-size: 14px;
139
  line-height: 1.5;
140
  display: block;
141
-
142
  /* Gradio Color Palette Variables */
143
  background-color: #F1F3F5; /* Soft gray background (neutral-50) */
144
  color: #000000; /* Dark charcoal text color (neutral-700) */
145
-
146
  /* Borders and Edges */
147
  border: 1px solid #e5e7eb; /* Soft border color (neutral-200) */
148
  border-radius: 8px; /* Clean rounded panel corners */
149
-
150
  /* Sizing and Real Estate */
151
  padding: 12px 16px; /* Precise internal spatial layout */
152
  margin: 0; /* Ensures the code drops completely flush to its frame */
@@ -154,7 +146,6 @@ href="https://cdn.jsdelivr.net/npm/katex@0.16.10/dist/katex.min.css">
154
  width: 100%;
155
  box-sizing: border-box;
156
  }
157
-
158
  /* Force-neutralize the default <pre> block settings wrapper */
159
  pre, .ai-response-container {
160
  background: transparent !important;
@@ -163,11 +154,9 @@ pre, .ai-response-container {
163
  border: none !important;
164
  box-shadow: none !important;
165
  }
166
-
167
  .ai-response table{
168
  border-collapse:collapse;
169
  }
170
-
171
  .ai-response th,
172
  .ai-response td{
173
  border:1px solid #ddd;
@@ -196,7 +185,7 @@ pre, .ai-response-container {
196
  </a>
197
  <!-- Stripe Subscription Navbar Trigger Element -->
198
  <button id="checkout-button" class="bg-white text-gray-800 px-4 py-2 rounded-full border-2 border-gray-200 hover:bg-gray-100 transition-colors duration-200 inline-flex items-center justify-center font-medium cursor-pointer">
199
- Create A Free Account
200
  </button>
201
  </div>
202
  </nav>
@@ -396,13 +385,10 @@ class="w-5 h-5"
396
  const chatModal = document.getElementById("chat-modal");
397
  const chatList = document.getElementById("chat-list");
398
  const closeModalBtn = document.getElementById("close-modal");
399
-
400
  // Chat management variables
401
  let chats = [];
402
  let currentChat = { id: Date.now(), messages: [] };
403
-
404
  const sessionId = "session_" + Math.random().toString(36).substring(2, 9);
405
-
406
  function showMessagesArea() {
407
  if (chatPage.getAttribute("data-state") === "initial") {
408
  chatPage.classList.remove("justify-center", "items-center");
@@ -411,14 +397,11 @@ class="w-5 h-5"
411
  chatPage.setAttribute("data-state", "expanded");
412
  }
413
  }
414
-
415
  function addMessage(content, sender) {
416
  const wrapper = document.createElement("div");
417
-
418
  if (sender === "user") {
419
  // User message stays as a bubble on the right
420
  wrapper.className = "flex justify-end";
421
-
422
  wrapper.innerHTML = `
423
  <div class="bg-gray-100 rounded-xl p-4 max-w-xl">
424
  ${content}
@@ -427,9 +410,7 @@ class="w-5 h-5"
427
  } else {
428
  // AI response is centered like a document
429
  wrapper.className = "w-full flex justify-center";
430
-
431
  let html = content;
432
-
433
  // If Markdown libraries are loaded, render Markdown + sanitize
434
  if (typeof marked !== "undefined" && typeof DOMPurify !== "undefined") {
435
  html = DOMPurify.sanitize(marked.parse(content));
@@ -437,54 +418,41 @@ class="w-5 h-5"
437
  // Fallback: preserve line breaks
438
  html = content.replace(/\n/g, "<br>");
439
  }
440
-
441
  wrapper.innerHTML = `
442
  <div class="ai-response">
443
  ${html}
444
  </div>
445
  `;
446
  }
447
-
448
  messagesContainer.appendChild(wrapper);
449
  messagesContainerWrapper.scrollTop = messagesContainerWrapper.scrollHeight;
450
  }
451
-
452
  function renderMessages() {
453
  messagesContainer.innerHTML = "";
454
  currentChat.messages.forEach(({ content, sender }) => addMessage(content, sender));
455
  messagesContainerWrapper.scrollTop = messagesContainerWrapper.scrollHeight;
456
  }
457
-
458
  // ✅ FIXED: always save chats (even empty ones)
459
  function saveCurrentChat() {
460
  const existingIndex = chats.findIndex(c => c.id === currentChat.id);
461
-
462
  if (existingIndex > -1) {
463
  chats[existingIndex] = { ...currentChat };
464
  } else {
465
  chats.push({ ...currentChat });
466
  }
467
  }
468
-
469
  function createNewChat() {
470
  saveCurrentChat();
471
-
472
  currentChat = { id: Date.now(), messages: [] };
473
-
474
  // ✅ ensure new chat is immediately logged
475
  chats.push({ ...currentChat });
476
-
477
  renderMessages();
478
  infinityAiText.style.opacity = '1';
479
-
480
  chatPage.classList.remove("justify-between", "flex-col", "items-center");
481
  chatPage.classList.add("justify-center", "items-center");
482
-
483
  messagesContainerWrapper.classList.add("hidden");
484
-
485
  chatPage.setAttribute("data-state", "initial");
486
  }
487
-
488
  async function sendMessage() {
489
  const userMessageContent = chatInput.innerHTML.trim();
490
  if (userMessageContent.length === 0) return;
@@ -506,9 +474,7 @@ const response = await fetch("/ai-bridge.php", {
506
  session_id: sessionId
507
  })
508
  });
509
-
510
  const data = await response.json();
511
-
512
  if (data.response) {
513
  currentChat.messages.push({
514
  content: data.response,
@@ -526,10 +492,8 @@ const response = await fetch("/ai-bridge.php", {
526
  sender: "ai"
527
  });
528
  }
529
-
530
  renderMessages();
531
  }
532
-
533
  function updateSendButton() {
534
  const hasText = chatInput.innerText.trim().length > 0;
535
  const hasImages = chatInput.querySelector("img");
@@ -541,7 +505,6 @@ renderMessages();
541
  sendBtn.classList.add("text-gray-500", "hover:bg-gray-200");
542
  }
543
  }
544
-
545
  dropZone.addEventListener("dragover", e => {
546
  e.preventDefault();
547
  dropZone.classList.add("drag-over");
@@ -568,7 +531,6 @@ renderMessages();
568
  }
569
  }
570
  });
571
-
572
  sendBtn.addEventListener("click", sendMessage);
573
  chatInput.addEventListener("input", updateSendButton);
574
  chatInput.addEventListener("keydown", e => {
@@ -577,14 +539,12 @@ renderMessages();
577
  if (sendBtn.classList.contains("send-btn-active")) sendMessage();
578
  }
579
  });
580
-
581
  const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
582
  if (!SpeechRecognition) {
583
  voiceBtn.style.display = "none";
584
  } else {
585
  const recognition = new SpeechRecognition();
586
  recognition.lang = "en-US";
587
-
588
  voiceBtn.addEventListener("click", () => {
589
  if (voiceBtn.classList.contains("listening")) {
590
  recognition.stop();
@@ -596,23 +556,19 @@ renderMessages();
596
  siriImage.classList.add("siri-animate");
597
  }
598
  });
599
-
600
  recognition.onresult = event => {
601
  const transcript = event.results[0][0].transcript;
602
  chatInput.innerText += (chatInput.innerText ? " " : "") + transcript;
603
  updateSendButton();
604
  };
605
-
606
  recognition.onend = () => {
607
  voiceBtn.classList.remove("listening");
608
  siriImage.classList.remove("siri-animate");
609
  };
610
  }
611
-
612
  // Chat Modal
613
  switchChatBtn.addEventListener("click", () => {
614
  saveCurrentChat();
615
-
616
  if (chats.length === 0) {
617
  chatList.innerHTML = `<li class='text-gray-400 text-sm'>No saved chats.</li>`;
618
  } else {
@@ -624,7 +580,6 @@ renderMessages();
624
  </button>
625
  </li>
626
  `).join("");
627
-
628
  chatList.querySelectorAll("button").forEach(btn => {
629
  btn.addEventListener("click", e => {
630
  const id = Number(e.currentTarget.getAttribute("data-id"));
@@ -639,50 +594,17 @@ renderMessages();
639
  });
640
  });
641
  }
642
-
643
  chatModal.classList.remove("hidden");
644
  });
645
-
646
  closeModalBtn.addEventListener("click", () => {
647
  chatModal.classList.add("hidden");
648
  });
649
-
650
  showPage('chat-page');
651
  updateSendButton();
652
  renderMessages();
653
-
654
  // ✅ New Chat button works
655
  newChatBtn.addEventListener("click", createNewChat);
656
  });
657
-
658
- // Stripe Checkout Portal Handshake Logic
659
- document.getElementById('checkout-button').addEventListener('click', async () => {
660
- const button = document.getElementById('checkout-button');
661
- button.disabled = true;
662
- button.innerText = 'Connecting...';
663
-
664
- try {
665
- // Forces your frontend button to talk safely to the root app server
666
- const response = await fetch(window.location.origin + '/create-checkout-session', {
667
- method: 'POST',
668
- headers: { 'Content-Type': 'application/json' }
669
- });
670
-
671
- const data = await response.json();
672
-
673
- if (data.url) {
674
- window.location.href = data.url;
675
- } else {
676
- alert('Unable to connect to your Stripe subscription endpoint.');
677
- button.disabled = false;
678
- button.innerText = 'Create A Free Account';
679
- }
680
- } catch (error) {
681
- console.error('Stripe Handshake Fail:', error);
682
- alert('Could not establish connection with backend handler.');
683
- button.disabled = false;
684
- button.innerText = 'Create A Free Account';
685
- }
686
  });
687
 
688
  function showPage(pageId) {
 
109
  line-height:1.8;
110
  font-size:16px;
111
  }
 
112
  .ai-response p{
113
  margin:1em 0;
114
  }
 
115
  .ai-response ul,
116
  .ai-response ol{
117
  margin:1em 0;
118
  padding-left:2rem;
119
  }
 
120
  .ai-response li{
121
  margin:.5em 0;
122
  }
 
123
  .ai-response pre{
124
  overflow:auto;
125
  padding:16px;
 
127
  background:#111827;
128
  color:white;
129
  }
 
130
  /* Gradio-style Clean Code Blocks */
131
  .ai-response code {
132
  font-family: Consolas, Montserrat, monospace;
133
  font-size: 14px;
134
  line-height: 1.5;
135
  display: block;
 
136
  /* Gradio Color Palette Variables */
137
  background-color: #F1F3F5; /* Soft gray background (neutral-50) */
138
  color: #000000; /* Dark charcoal text color (neutral-700) */
 
139
  /* Borders and Edges */
140
  border: 1px solid #e5e7eb; /* Soft border color (neutral-200) */
141
  border-radius: 8px; /* Clean rounded panel corners */
 
142
  /* Sizing and Real Estate */
143
  padding: 12px 16px; /* Precise internal spatial layout */
144
  margin: 0; /* Ensures the code drops completely flush to its frame */
 
146
  width: 100%;
147
  box-sizing: border-box;
148
  }
 
149
  /* Force-neutralize the default <pre> block settings wrapper */
150
  pre, .ai-response-container {
151
  background: transparent !important;
 
154
  border: none !important;
155
  box-shadow: none !important;
156
  }
 
157
  .ai-response table{
158
  border-collapse:collapse;
159
  }
 
160
  .ai-response th,
161
  .ai-response td{
162
  border:1px solid #ddd;
 
185
  </a>
186
  <!-- Stripe Subscription Navbar Trigger Element -->
187
  <button id="checkout-button" class="bg-white text-gray-800 px-4 py-2 rounded-full border-2 border-gray-200 hover:bg-gray-100 transition-colors duration-200 inline-flex items-center justify-center font-medium cursor-pointer">
188
+ Sign Up For Free
189
  </button>
190
  </div>
191
  </nav>
 
385
  const chatModal = document.getElementById("chat-modal");
386
  const chatList = document.getElementById("chat-list");
387
  const closeModalBtn = document.getElementById("close-modal");
 
388
  // Chat management variables
389
  let chats = [];
390
  let currentChat = { id: Date.now(), messages: [] };
 
391
  const sessionId = "session_" + Math.random().toString(36).substring(2, 9);
 
392
  function showMessagesArea() {
393
  if (chatPage.getAttribute("data-state") === "initial") {
394
  chatPage.classList.remove("justify-center", "items-center");
 
397
  chatPage.setAttribute("data-state", "expanded");
398
  }
399
  }
 
400
  function addMessage(content, sender) {
401
  const wrapper = document.createElement("div");
 
402
  if (sender === "user") {
403
  // User message stays as a bubble on the right
404
  wrapper.className = "flex justify-end";
 
405
  wrapper.innerHTML = `
406
  <div class="bg-gray-100 rounded-xl p-4 max-w-xl">
407
  ${content}
 
410
  } else {
411
  // AI response is centered like a document
412
  wrapper.className = "w-full flex justify-center";
 
413
  let html = content;
 
414
  // If Markdown libraries are loaded, render Markdown + sanitize
415
  if (typeof marked !== "undefined" && typeof DOMPurify !== "undefined") {
416
  html = DOMPurify.sanitize(marked.parse(content));
 
418
  // Fallback: preserve line breaks
419
  html = content.replace(/\n/g, "<br>");
420
  }
 
421
  wrapper.innerHTML = `
422
  <div class="ai-response">
423
  ${html}
424
  </div>
425
  `;
426
  }
 
427
  messagesContainer.appendChild(wrapper);
428
  messagesContainerWrapper.scrollTop = messagesContainerWrapper.scrollHeight;
429
  }
 
430
  function renderMessages() {
431
  messagesContainer.innerHTML = "";
432
  currentChat.messages.forEach(({ content, sender }) => addMessage(content, sender));
433
  messagesContainerWrapper.scrollTop = messagesContainerWrapper.scrollHeight;
434
  }
 
435
  // ✅ FIXED: always save chats (even empty ones)
436
  function saveCurrentChat() {
437
  const existingIndex = chats.findIndex(c => c.id === currentChat.id);
 
438
  if (existingIndex > -1) {
439
  chats[existingIndex] = { ...currentChat };
440
  } else {
441
  chats.push({ ...currentChat });
442
  }
443
  }
 
444
  function createNewChat() {
445
  saveCurrentChat();
 
446
  currentChat = { id: Date.now(), messages: [] };
 
447
  // ✅ ensure new chat is immediately logged
448
  chats.push({ ...currentChat });
 
449
  renderMessages();
450
  infinityAiText.style.opacity = '1';
 
451
  chatPage.classList.remove("justify-between", "flex-col", "items-center");
452
  chatPage.classList.add("justify-center", "items-center");
 
453
  messagesContainerWrapper.classList.add("hidden");
 
454
  chatPage.setAttribute("data-state", "initial");
455
  }
 
456
  async function sendMessage() {
457
  const userMessageContent = chatInput.innerHTML.trim();
458
  if (userMessageContent.length === 0) return;
 
474
  session_id: sessionId
475
  })
476
  });
 
477
  const data = await response.json();
 
478
  if (data.response) {
479
  currentChat.messages.push({
480
  content: data.response,
 
492
  sender: "ai"
493
  });
494
  }
 
495
  renderMessages();
496
  }
 
497
  function updateSendButton() {
498
  const hasText = chatInput.innerText.trim().length > 0;
499
  const hasImages = chatInput.querySelector("img");
 
505
  sendBtn.classList.add("text-gray-500", "hover:bg-gray-200");
506
  }
507
  }
 
508
  dropZone.addEventListener("dragover", e => {
509
  e.preventDefault();
510
  dropZone.classList.add("drag-over");
 
531
  }
532
  }
533
  });
 
534
  sendBtn.addEventListener("click", sendMessage);
535
  chatInput.addEventListener("input", updateSendButton);
536
  chatInput.addEventListener("keydown", e => {
 
539
  if (sendBtn.classList.contains("send-btn-active")) sendMessage();
540
  }
541
  });
 
542
  const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
543
  if (!SpeechRecognition) {
544
  voiceBtn.style.display = "none";
545
  } else {
546
  const recognition = new SpeechRecognition();
547
  recognition.lang = "en-US";
 
548
  voiceBtn.addEventListener("click", () => {
549
  if (voiceBtn.classList.contains("listening")) {
550
  recognition.stop();
 
556
  siriImage.classList.add("siri-animate");
557
  }
558
  });
 
559
  recognition.onresult = event => {
560
  const transcript = event.results[0][0].transcript;
561
  chatInput.innerText += (chatInput.innerText ? " " : "") + transcript;
562
  updateSendButton();
563
  };
 
564
  recognition.onend = () => {
565
  voiceBtn.classList.remove("listening");
566
  siriImage.classList.remove("siri-animate");
567
  };
568
  }
 
569
  // Chat Modal
570
  switchChatBtn.addEventListener("click", () => {
571
  saveCurrentChat();
 
572
  if (chats.length === 0) {
573
  chatList.innerHTML = `<li class='text-gray-400 text-sm'>No saved chats.</li>`;
574
  } else {
 
580
  </button>
581
  </li>
582
  `).join("");
 
583
  chatList.querySelectorAll("button").forEach(btn => {
584
  btn.addEventListener("click", e => {
585
  const id = Number(e.currentTarget.getAttribute("data-id"));
 
594
  });
595
  });
596
  }
 
597
  chatModal.classList.remove("hidden");
598
  });
 
599
  closeModalBtn.addEventListener("click", () => {
600
  chatModal.classList.add("hidden");
601
  });
 
602
  showPage('chat-page');
603
  updateSendButton();
604
  renderMessages();
 
605
  // ✅ New Chat button works
606
  newChatBtn.addEventListener("click", createNewChat);
607
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
608
  });
609
 
610
  function showPage(pageId) {