Brahtim47/Idea_Into_a_Website_Python
1
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>Gemini AI Python</title>7 8 <!-- Tailwind CSS from jsdelivr -->9 <link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">10 11 <!-- CodeMirror CSS -->12 <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/codemirror@5.65.5/lib/codemirror.min.css">13 <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/codemirror@5.65.5/theme/dracula.min.css">14 15 <!-- Font Awesome Icons -->16 <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.2.1/css/all.min.css">17 18 <style>19 :root {20 --bg-color: #111827;21 --text-color: #ffffff;22 --border-color: #374151;23 --highlight-color: #3b82f6; /* Blue instead of pink */24 --button-color: #3b82f6;25 --button-hover: #60a5fa;26 }27 28 * {29 box-sizing: border-box;30 margin: 0;31 padding: 0;32 }33 34 body {35 font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;36 background-color: var(--bg-color);37 color: var(--text-color);38 min-height: 100vh;39 display: flex;40 flex-direction: column;41 }42 43 .CodeMirror {44 height: 100%;45 font-family: 'Fira Code', 'Courier New', monospace;46 font-size: 14px;47 }48 49 .main-content {50 display: flex;51 flex: 1;52 overflow: hidden;53 position: relative;54 }55 56 .editor-container {57 flex: 1;58 display: flex;59 flex-direction: column;60 border-right: 1px solid var(--border-color);61 min-height: 500px;62 }63 64 .preview-container {65 flex: 1;66 display: flex;67 flex-direction: column;68 }69 70 #preview-frame {71 flex: 1;72 border: none;73 width: 100%;74 background-color: white;75 min-height: 500px;76 }77 78 .ai-container {79 position: fixed;80 bottom: 1rem;81 left: 1rem;82 width: calc(100% - 2rem);83 max-width: 800px;84 background-color: #1f2937;85 border-radius: 0.5rem;86 padding: 0.75rem 1rem;87 display: flex;88 align-items: center;89 box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);90 z-index: 10;91 }92 93 .loader {94 border: 2px solid #f3f3f3;95 border-top: 2px solid var(--highlight-color);96 border-radius: 50%;97 width: 1rem;98 height: 1rem;99 animation: spin 1s linear infinite;100 display: none;101 }102 103 @keyframes spin {104 0% { transform: rotate(0deg); }105 100% { transform: rotate(360deg); }106 }107 108 .conversion-status {109 position: absolute;110 top: 10px;111 right: 10px;112 background-color: rgba(31, 41, 55, 0.8);113 padding: 4px 8px;114 border-radius: 4px;115 font-size: 12px;116 z-index: 5;117 display: none;118 }119 120 /* For PDF export optimization */121 @media print {122 body {123 background-color: white;124 color: black;125 }126 127 .editor-container, .preview-container {128 break-inside: avoid;129 page-break-inside: avoid;130 }131 132 .ai-container {133 display: none;134 }135 136 /* Ensure all content is displayed in PDF */137 .CodeMirror {138 height: auto !important;139 }140 141 #preview-frame {142 height: auto !important;143 min-height: auto !important;144 }145 146 .conversion-status {147 display: none;148 }149 }150 151 /* Responsive design */152 @media (max-width: 768px) {153 .main-content {154 flex-direction: column;155 }156 157 .editor-container, .preview-container {158 width: 100%;159 }160 161 .editor-hidden {162 display: none;163 }164 165 .preview-full {166 flex: 1;167 }168 169 .view-toggle {170 display: flex !important;171 }172 }173 174 .view-toggle {175 display: none;176 position: fixed;177 top: 4.5rem;178 right: 1rem;179 z-index: 20;180 }181 182 .output-container {183 background-color: #1a202c;184 border-top: 1px solid #374151;185 padding: 0.5rem;186 font-family: 'Courier New', monospace;187 color: #e2e8f0;188 max-height: 100px;189 overflow-y: auto;190 }191 </style>192</head>193<body>194 <header class="flex justify-between items-center p-4 border-b border-gray-700">195 <div class="text-xl font-bold text-blue-500">196 <i class="fab fa-python mr-2"></i>Gemini AI Python197 </div>198 <div class="flex space-x-3">199 <button id="new-btn" class="bg-gray-700 hover:bg-gray-600 text-white px-3 py-1 rounded-md text-sm transition duration-200">200 <i class="fas fa-file-alt mr-1"></i>New201 </button>202 <span id="conversion-status" class="conversion-status">203 <i class="fas fa-sync-alt fa-spin mr-1"></i>Preview...204 </span>205 </div>206 </header>207 208 <button id="view-toggle" class="view-toggle bg-blue-600 hover:bg-blue-500 text-white px-3 py-2 rounded-md text-sm transition duration-200">209 <i class="fas fa-columns mr-1"></i>210 <span id="toggle-text">View Preview</span>211 </button>212 213 <div class="main-content flex-grow">214 <div id="editor-container" class="editor-container">215 <div class="bg-gray-800 px-4 py-2 text-sm border-b border-gray-700 flex justify-between items-center">216 <div><i class="fab fa-python mr-1"></i>Python Editor</div>217 <div class="text-xs text-gray-400">Flask App (app.py)</div>218 </div>219 <div id="editor" class="flex-grow"></div>220 <div id="output" class="output-container hidden">221 <div class="text-xs text-gray-400 mb-1">Console Output:</div>222 <div id="output-content"></div>223 </div>224 </div>225 226 <div id="preview-container" class="preview-container">227 <div class="bg-gray-800 px-4 py-2 text-sm border-b border-gray-700 flex justify-between items-center">228 <div><i class="fas fa-globe mr-1"></i>Web Preview</div>229 <div class="text-xs text-gray-400">https://Localhost:5000</div>230 </div>231 <iframe id="preview-frame"></iframe>232 </div>233 </div>234 235 <div class="ai-container">236 <i class="fas fa-robot text-gray-400 mr-3"></i>237 <input id="ai-input" type="text" class="flex-grow bg-transparent border-none text-white outline-none placeholder-gray-500" placeholder="Ask for Flask code suggestions...">238 <div id="ai-loader" class="loader mr-3"></div>239 <button id="ai-send" class="bg-blue-600 hover:bg-blue-500 text-white rounded-full w-8 h-8 flex items-center justify-center">240 <i class="fas fa-paper-plane"></i>241 </button>242 </div>243 244 <!-- CodeMirror JavaScript -->245 <script src="https://cdn.jsdelivr.net/npm/codemirror@5.65.5/lib/codemirror.min.js"></script>246 <script src="https://cdn.jsdelivr.net/npm/codemirror@5.65.5/mode/python/python.min.js"></script>247 <script src="https://cdn.jsdelivr.net/npm/codemirror@5.65.5/mode/htmlmixed/htmlmixed.min.js"></script>248 <script src="https://cdn.jsdelivr.net/npm/codemirror@5.65.5/mode/xml/xml.min.js"></script>249 <script src="https://cdn.jsdelivr.net/npm/codemirror@5.65.5/mode/javascript/javascript.min.js"></script>250 <script src="https://cdn.jsdelivr.net/npm/codemirror@5.65.5/mode/css/css.min.js"></script>251 252 <!-- CodeMirror Add-ons -->253 <script src="https://cdn.jsdelivr.net/npm/codemirror@5.65.5/addon/edit/matchbrackets.min.js"></script>254 <script src="https://cdn.jsdelivr.net/npm/codemirror@5.65.5/addon/edit/closebrackets.min.js"></script>255 256 <script>257 // API Configuration258 const API_CONFIG = {259 OPENAI_API_BASE: "https://openrouter.ai/api/v1",260 OPENAI_API_KEY: "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",261 MODEL_NAME: "google/gemini-2.0-flash-thinking-exp:free"262 };263 264 // Default Python Flask content265 const DEFAULT_PYTHON = `from flask import Flask, render_template266 267app = Flask(__name__)268 269@app.route('/')270def home():271 return render_template('index.html', title='Flask App', 272 message='Welcome to my Flask application!')273 274@app.route('/about')275def about():276 return render_template('about.html', title='About',277 content='This is a simple Flask application.')278 279if __name__ == '__main__':280 app.run(debug=True)`;281 282 // Initialize variables283 let editor;284 let currentView = 'both';285 let isAiWorking = false;286 let previousPrompt = '';287 let conversionTimeout = null;288 let lastCode = '';289 290 // DOM Elements291 const aiInput = document.getElementById('ai-input');292 const aiSendButton = document.getElementById('ai-send');293 const aiLoader = document.getElementById('ai-loader');294 const previewFrame = document.getElementById('preview-frame');295 const viewToggle = document.getElementById('view-toggle');296 const toggleText = document.getElementById('toggle-text');297 const editorContainer = document.getElementById('editor-container');298 const previewContainer = document.getElementById('preview-container');299 const newButton = document.getElementById('new-btn');300 const outputContainer = document.getElementById('output');301 const outputContent = document.getElementById('output-content');302 const conversionStatus = document.getElementById('conversion-status');303 304 // Initialize CodeMirror editor305 document.addEventListener('DOMContentLoaded', function() {306 editor = CodeMirror(document.getElementById('editor'), {307 value: DEFAULT_PYTHON,308 mode: "python",309 theme: "dracula",310 lineNumbers: true,311 autoCloseBrackets: true,312 matchBrackets: true,313 indentUnit: 4,314 tabSize: 4,315 indentWithTabs: false,316 lineWrapping: true317 });318 319 // Set initial preview320 updatePreviewWithMessage("Type Python Flask code to see the web preview");321 322 // Set up auto-conversion on change with debounce323 editor.on('change', function() {324 // Clear any existing timeout325 if (conversionTimeout) {326 clearTimeout(conversionTimeout);327 }328 329 // Set a new timeout330 conversionTimeout = setTimeout(function() {331 const currentCode = editor.getValue().trim();332 333 // Only convert if code has actually changed334 if (currentCode !== lastCode && currentCode) {335 lastCode = currentCode;336 convertPythonToWeb();337 }338 }, 1500); // 1.5 seconds delay339 });340 341 // Initial conversion342 setTimeout(function() {343 lastCode = editor.getValue().trim();344 convertPythonToWeb();345 }, 1000);346 });347 348 // Update preview with HTML content349 function updatePreview(html) {350 // Create a blob with the HTML content351 const blob = new Blob([html], { type: 'text/html' });352 const url = URL.createObjectURL(blob);353 354 // Set iframe src to the blob URL355 previewFrame.src = url;356 357 // Clean up the old URL after the iframe loads358 previewFrame.onload = () => {359 URL.revokeObjectURL(url);360 };361 }362 363 // Update preview with a message364 function updatePreviewWithMessage(message) {365 const html = `366 <!DOCTYPE html>367 <html>368 <head>369 <style>370 body {371 font-family: Arial, sans-serif;372 display: flex;373 justify-content: center;374 align-items: center;375 height: 100vh;376 margin: 0;377 background-color: #f0f4f8;378 color: #333;379 }380 .message-container {381 text-align: center;382 padding: 2rem;383 border-radius: 0.5rem;384 background-color: white;385 box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);386 max-width: 80%;387 }388 .icon {389 font-size: 3rem;390 margin-bottom: 1rem;391 color: #3b82f6;392 }393 </style>394 </head>395 <body>396 <div class="message-container">397 <div class="icon">โน๏ธ</div>398 <p>${message}</p>399 </div>400 </body>401 </html>`;402 updatePreview(html);403 }404 405 // Show output with message406 function showOutput(message, isError = false) {407 outputContainer.classList.remove('hidden');408 outputContent.innerHTML += `<div class="${isError ? 'text-red-400' : 'text-green-400'}">${message}</div>`;409 // Auto-scroll to bottom410 outputContent.scrollTop = outputContent.scrollHeight;411 }412 413 // Clear output414 function clearOutput() {415 outputContent.innerHTML = '';416 outputContainer.classList.add('hidden');417 }418 419 // Toggle view on mobile420 viewToggle.addEventListener('click', () => {421 if (currentView === 'both' || currentView === 'editor') {422 // Show preview only423 editorContainer.classList.add('editor-hidden');424 previewContainer.classList.add('preview-full');425 toggleText.textContent = 'View Editor';426 currentView = 'preview';427 } else {428 // Show editor only or both429 editorContainer.classList.remove('editor-hidden');430 previewContainer.classList.remove('preview-full');431 toggleText.textContent = 'View Preview';432 currentView = 'editor';433 }434 });435 436 // Convert Python to Web function437 async function convertPythonToWeb() {438 if (isAiWorking) return;439 440 const pythonCode = editor.getValue().trim();441 if (!pythonCode) {442 showOutput("Error: No Python code to convert", true);443 return;444 }445 446 isAiWorking = true;447 clearOutput();448 showOutput("Preview Python Flask code...");449 conversionStatus.style.display = 'inline-flex';450 451 try {452 // Update preview with loading state453 updatePreviewWithMessage("Preview your Python Flask code...");454 455 // Construct messages for the AI456 const messages = [457 {"role": "system", "content": "You are a Flask to Web converter. Convert Python Flask code to equivalent HTML, CSS, and JavaScript files that would simulate what the Flask app would render. Create professional, advanced and beautiful CSS styling. Include all necessary JavaScript to simulate Flask routes and functionality."},458 {"role": "user", "content": `Convert this Python Flask code to equivalent HTML, CSS, and JavaScript:\n\n${pythonCode}\n\nProvide a complete standalone web implementation that simulates this Flask app's functionality. Include all HTML pages, CSS styling, and JavaScript for routing. Return ONLY the HTML code for the main page (no explanations, just the code).`}459 ];460 461 // Make API request462 const response = await fetch(`${API_CONFIG.OPENAI_API_BASE}/chat/completions`, {463 method: "POST",464 headers: {465 "Content-Type": "application/json",466 "Authorization": `Bearer ${API_CONFIG.OPENAI_API_KEY}`,467 "HTTP-Referer": window.location.href468 },469 body: JSON.stringify({470 model: API_CONFIG.MODEL_NAME,471 messages: messages,472 stream: true473 })474 });475 476 if (!response.ok) {477 throw new Error(`API error: ${response.status}`);478 }479 480 const reader = response.body.getReader();481 let result = '';482 483 while (true) {484 const { done, value } = await reader.read();485 486 if (done) break;487 488 const text = new TextDecoder().decode(value);489 const lines = text.split('\n');490 491 for (const line of lines) {492 if (line.startsWith('data: ')) {493 const data = line.substring(6);494 if (data === '[DONE]') continue;495 496 try {497 const json = JSON.parse(data);498 if (json.choices && json.choices[0].delta && json.choices[0].delta.content) {499 result += json.choices[0].delta.content;500 }501 } catch (e) {502 console.error('Error parsing JSON:', e);503 }504 }505 }506 }507 508 // Extract HTML code509 const htmlCode = extractHTML(result);510 511 if (htmlCode) {512 // Update the preview with the converted HTML513 updatePreview(htmlCode);514 showOutput("โ
Conversion successful. The web implementation of your Flask app is displayed in the preview.");515 } else {516 updatePreviewWithMessage("Error: Could not extract valid HTML from the conversion result.");517 showOutput("Error: Could not extract valid HTML from the conversion result.", true);518 }519 520 } catch (error) {521 console.error('Error converting code:', error);522 updatePreviewWithMessage("Error: " + error.message);523 showOutput("Error: " + error.message, true);524 } finally {525 isAiWorking = false;526 conversionStatus.style.display = 'none';527 }528 }529 530 // Extract HTML from text531 function extractHTML(text) {532 // Try to find complete HTML document533 const docTypeMatch = text.match(/<!DOCTYPE html>[\s\S]*<\/html>/i);534 if (docTypeMatch) return docTypeMatch[0];535 536 // Try to find HTML tag content537 const htmlTagMatch = text.match(/<html[\s\S]*<\/html>/i);538 if (htmlTagMatch) return "<!DOCTYPE html>" + htmlTagMatch[0];539 540 // Try to extract HTML code from code blocks541 const codeBlockMatch = text.match(/```html\s*([\s\S]*?)```/);542 if (codeBlockMatch && codeBlockMatch[1]) return codeBlockMatch[1].trim();543 544 // If there's <body> tag but no complete document545 const bodyMatch = text.match(/<body[\s\S]*<\/body>/i);546 if (bodyMatch) return `<!DOCTYPE html>\n<html>\n<head>\n<title>Flask App</title>\n</head>\n${bodyMatch[0]}\n</html>`;547 548 return null;549 }550 551 // Ask AI for code suggestions552 async function askAI() {553 if (isAiWorking || !aiInput.value.trim()) return;554 555 const prompt = aiInput.value.trim();556 const pythonCode = editor.getValue();557 558 isAiWorking = true;559 aiLoader.style.display = 'block';560 aiSendButton.style.display = 'none';561 clearOutput();562 563 try {564 // Construct messages for the AI565 const messages = [566 {"role": "system", "content": "You are a helpful Python Flask coding assistant. Provide Python code that is complete, well-structured, and follows best practices."}567 ];568 569 if (pythonCode && pythonCode !== DEFAULT_PYTHON) {570 messages.push({"role": "user", "content": `Here is my current Flask app:\n\`\`\`python\n${pythonCode}\n\`\`\``});571 messages.push({"role": "user", "content": `User request: ${prompt}\n\nPlease provide a complete updated Python Flask application that addresses the request.`});572 } else {573 messages.push({"role": "user", "content": `Create a Flask application based on this request: ${prompt}\n\nPlease make sure it is a complete, well-structured Flask application.`});574 }575 576 // Make API request577 const response = await fetch(`${API_CONFIG.OPENAI_API_BASE}/chat/completions`, {578 method: "POST",579 headers: {580 "Content-Type": "application/json",581 "Authorization": `Bearer ${API_CONFIG.OPENAI_API_KEY}`,582 "HTTP-Referer": window.location.href583 },584 body: JSON.stringify({585 model: API_CONFIG.MODEL_NAME,586 messages: messages,587 stream: true588 })589 });590 591 if (!response.ok) {592 throw new Error(`API error: ${response.status}`);593 }594 595 const reader = response.body.getReader();596 let result = '';597 598 while (true) {599 const { done, value } = await reader.read();600 601 if (done) break;602 603 const text = new TextDecoder().decode(value);604 const lines = text.split('\n');605 606 for (const line of lines) {607 if (line.startsWith('data: ')) {608 const data = line.substring(6);609 if (data === '[DONE]') continue;610 611 try {612 const json = JSON.parse(data);613 if (json.choices && json.choices[0].delta && json.choices[0].delta.content) {614 result += json.choices[0].delta.content;615 }616 } catch (e) {617 console.error('Error parsing JSON:', e);618 }619 }620 }621 }622 623 // Extract Python code624 const pythonCodeMatch = result.match(/```python\s*([\s\S]*?)```/);625 if (pythonCodeMatch && pythonCodeMatch[1]) {626 editor.setValue(pythonCodeMatch[1].trim());627 showOutput("โ
Updated Flask code based on your request");628 } else {629 editor.setValue(result);630 showOutput("โ
Updated Flask code (code block format not detected)");631 }632 633 aiInput.value = '';634 previousPrompt = prompt;635 636 // Trigger conversion after a small delay to allow editor to update637 setTimeout(() => {638 lastCode = editor.getValue().trim();639 convertPythonToWeb();640 }, 500);641 642 } catch (error) {643 console.error('Error calling AI:', error);644 showOutput("Error getting AI response: " + error.message, true);645 } finally {646 isAiWorking = false;647 aiLoader.style.display = 'none';648 aiSendButton.style.display = 'block';649 }650 }651 652 // Event Listeners653 aiSendButton.addEventListener('click', askAI);654 655 // Listen for Enter key in AI input656 aiInput.addEventListener('keydown', (e) => {657 if (e.key === 'Enter') {658 askAI();659 }660 });661 662 // New button event663 newButton.addEventListener('click', () => {664 if (confirm('Clear the current code and start fresh?')) {665 editor.setValue(DEFAULT_PYTHON);666 updatePreviewWithMessage("The web preview will update automatically as you type...");667 clearOutput();668 setTimeout(() => {669 lastCode = editor.getValue().trim();670 convertPythonToWeb();671 }, 500);672 }673 });674 675 // Handle window resize676 window.addEventListener('resize', () => {677 if (window.innerWidth >= 768) {678 editorContainer.classList.remove('editor-hidden');679 previewContainer.classList.remove('preview-full');680 currentView = 'both';681 }682 });683 </script>684</body>685</html>