Spaces:
Sleeping
Sleeping
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>QuickBrief</title> | |
| <link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700&family=Papyrus&display=swap" rel="stylesheet"> | |
| <style> | |
| /* Same styles as before */ | |
| * { | |
| box-sizing: border-box; | |
| margin: 0; | |
| padding: 0; | |
| } | |
| html, body { | |
| font-family: Arial, sans-serif; | |
| background-color: #000000; | |
| color: #e0e0e0; | |
| margin: 0; | |
| padding: 0; | |
| width: 100%; | |
| height: auto; | |
| overflow-y: auto; | |
| } | |
| body { | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| padding: 10px; | |
| } | |
| .container { | |
| max-width: 1000px; | |
| width: 100%; | |
| padding: 0 10px; | |
| margin: 0 auto; | |
| box-sizing: border-box; | |
| } | |
| .header { | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| margin-bottom: 10px; | |
| width: 100%; | |
| } | |
| .header img { | |
| width: 50px; | |
| height: auto; | |
| margin-right: 10px; | |
| } | |
| .header h1 { | |
| font-family: 'Papyrus', sans-serif; | |
| font-size: 24px; | |
| margin: 0; | |
| color: #ffffff; | |
| text-shadow: 2px 2px 5px rgba(107, 72, 255, 0.5); | |
| } | |
| .tagline { | |
| font-family: 'Orbitron', sans-serif; | |
| font-size: 14px; | |
| font-weight: 700; | |
| color: #b0b0b0; | |
| text-align: center; | |
| margin-bottom: 20px; | |
| letter-spacing: 1px; | |
| } | |
| .summarize-section { | |
| display: flex; | |
| flex-wrap: wrap; | |
| gap: 10px; | |
| margin-bottom: 20px; | |
| width: 100%; | |
| } | |
| .summarize-section div { | |
| flex: 1; | |
| min-width: 100%; | |
| width: 100%; | |
| } | |
| .summarize-section label { | |
| display: block; | |
| font-size: 16px; | |
| color: #ffffff; | |
| margin-bottom: 5px; | |
| } | |
| textarea, .output { | |
| width: 100%; | |
| padding: 10px; | |
| border-radius: 5px; | |
| border: 2px solid #6b48ff; | |
| font-size: 14px; | |
| background-color: #1a1a1a; | |
| color: #ffffff; | |
| box-shadow: 0 0 5px rgba(107, 72, 255, 0.3); | |
| box-sizing: border-box; | |
| } | |
| textarea { | |
| height: 120px; | |
| resize: vertical; | |
| } | |
| .output { | |
| height: 120px; | |
| overflow-y: auto; | |
| } | |
| .translation-output { | |
| height: 80px; | |
| overflow-y: auto; | |
| } | |
| .button-container { | |
| width: 100%; | |
| text-align: left; | |
| margin-top: 5px; | |
| } | |
| button { | |
| background: linear-gradient(90deg, #6b48ff, #a73aff); | |
| color: white; | |
| padding: 10px 20px; | |
| border: none; | |
| border-radius: 20px; | |
| cursor: pointer; | |
| font-size: 14px; | |
| transition: transform 0.2s, box-shadow 0.3s; | |
| box-shadow: 0 4px 10px rgba(107, 72, 255, 0.4); | |
| width: 100%; | |
| } | |
| button:hover { | |
| background: linear-gradient(90deg, #5a38e7, #9632e6); | |
| transform: scale(1.05); | |
| box-shadow: 0 6px 15px rgba(107, 72, 255, 0.6); | |
| } | |
| .translate-section { | |
| margin-top: 20px; | |
| display: flex; | |
| flex-wrap: wrap; | |
| gap: 10px; | |
| align-items: center; | |
| margin-bottom: 10px; | |
| width: 100%; | |
| } | |
| .translate-section label { | |
| font-size: 16px; | |
| color: #ffffff; | |
| } | |
| select { | |
| padding: 8px; | |
| border-radius: 5px; | |
| border: 2px solid #a73aff; | |
| font-size: 14px; | |
| background-color: #1a1a1a; | |
| color: #ffffff; | |
| cursor: pointer; | |
| width: 100%; | |
| appearance: none; | |
| background-image: url('data:image/svg+xml;utf8,<svg fill="white" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M7 10l5 5 5-5z"/></svg>'); | |
| background-repeat: no-repeat; | |
| background-position: right 10px center; | |
| } | |
| select:focus { | |
| outline: none; | |
| border-color: #6b48ff; | |
| } | |
| @media (max-width: 768px) { | |
| .summarize-section { | |
| flex-direction: column; | |
| } | |
| .summarize-section div { | |
| min-width: 100%; | |
| } | |
| .translate-section { | |
| flex-direction: column; | |
| align-items: flex-start; | |
| } | |
| select { | |
| width: 100%; | |
| } | |
| button { | |
| width: 100%; | |
| } | |
| } | |
| @media (max-width: 480px) { | |
| .header h1 { | |
| font-size: 20px; | |
| } | |
| .tagline { | |
| font-size: 12px; | |
| } | |
| textarea, .output { | |
| height: 100px; | |
| } | |
| .translation-output { | |
| height: 60px; | |
| } | |
| button { | |
| padding: 8px 15px; | |
| font-size: 12px; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <div class="header"> | |
| <img src="/assets/Moon.PNG" alt="QuickBrief Logo"> | |
| <h1>QuickBrief</h1> | |
| </div> | |
| <p class="tagline">Simplify. Summarize. Translate. Understand.</p> | |
| <div class="summarize-section"> | |
| <div> | |
| <label>Input Text</label> | |
| <textarea id="inputText" placeholder="Enter your text here..."></textarea> | |
| <div class="button-container"> | |
| <button onclick="summarize()">SUMMARIZE</button> | |
| </div> | |
| </div> | |
| <div> | |
| <label>Summary</label> | |
| <div id="summary" class="output"></div> | |
| </div> | |
| </div> | |
| <div class="translate-section"> | |
| <label>Translate Summary</label> | |
| <select id="language"> | |
| <option value="default">Select Language</option> | |
| <option value="fr">French</option> | |
| <option value="de">German</option> | |
| <option value="es">Spanish</option> | |
| <option value="ar">Arabic</option> | |
| </select> | |
| <button onclick="doTranslate()">TRANSLATE</button> | |
| </div> | |
| <div> | |
| <label>Translation</label> | |
| <div id="translation" class="output translation-output"></div> | |
| </div> | |
| </div> | |
| <script> | |
| console.log("Script loaded successfully"); | |
| async function summarize() { | |
| const text = document.getElementById("inputText").value; | |
| const summaryDiv = document.getElementById("summary"); | |
| if (text.length > 1000) { | |
| summaryDiv.innerText = "Input too long; please use less than 1000 characters."; | |
| return; | |
| } | |
| summaryDiv.innerText = "Summarizing..."; | |
| try { | |
| const controller = new AbortController(); | |
| const timeoutId = setTimeout(() => { | |
| controller.abort(); | |
| console.warn("Summarize timed out after 300 seconds"); | |
| }, 300000); // Increased to 5 minutes | |
| const response = await fetch("/summarize", { | |
| method: "POST", | |
| headers: { "Content-Type": "application/json" }, | |
| body: JSON.stringify({ text: text }), | |
| signal: controller.signal | |
| }); | |
| clearTimeout(timeoutId); | |
| const data = await response.json(); | |
| console.log("Summarize response:", JSON.stringify(data, null, 2)); | |
| summaryDiv.innerText = data.summary || "Error: " + (data.error || "No summary returned"); | |
| } catch (error) { | |
| console.error("Summarize error:", error.name, error.message); | |
| summaryDiv.innerText = `Failed to summarize: ${error.message}${error.name === "AbortError" ? " (Timeout?)" : ""}`; | |
| } | |
| } | |
| async function doTranslate() { | |
| const summary = document.getElementById("summary").innerText; | |
| const lang = document.getElementById("language").value; | |
| const translationDiv = document.getElementById("translation"); | |
| if (lang === "default" || summary === "") { | |
| translationDiv.innerText = "Please select a language and ensure a summary is available."; | |
| return; | |
| } | |
| translationDiv.innerText = "Translating..."; | |
| console.log("Translate called with lang:", lang, "Text:", summary); | |
| try { | |
| const controller = new AbortController(); | |
| const timeoutId = setTimeout(() => { | |
| controller.abort(); | |
| console.warn("Translate timed out after 300 seconds"); | |
| }, 300000); // Increased to 5 minutes | |
| const response = await fetch("/translate", { | |
| method: "POST", | |
| headers: { "Content-Type": "application/json" }, | |
| body: JSON.stringify({ text: summary, lang: lang }), | |
| signal: controller.signal | |
| }); | |
| clearTimeout(timeoutId); | |
| const data = await response.json(); | |
| console.log("Translate response:", JSON.stringify(data, null, 2)); | |
| translationDiv.innerText = data.translation || "Error: " + (data.error || "No translation returned"); | |
| } catch (error) { | |
| console.error("Translate error:", error.name, error.message); | |
| translationDiv.innerText = `Failed to translate: ${error.message}${error.name === "AbortError" ? " (Timeout?)" : ""}`; | |
| } | |
| } | |
| </script> | |
| </body> | |
| </html> |