Team Ai
Apppublic

Brahtim47/Idea_Into_a_Website_Python

sourceHugging Facemitupdated 1y agoView on Hugging Face
1likes
index.html685 linesDownload Raw Back to root
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>