sn351621/claude-s-code-canvas-clone
0
1 2// AI Configuration3let aiConfig = JSON.parse(localStorage.getItem('aiConfig')) || {4 endpoint: 'https://api.openai.com/v1/chat/completions',5 apiKey: '',6 model: 'gpt-3.5-turbo'7};8 9// Save AI config to localStorage10function saveAIConfig() {11 localStorage.setItem('aiConfig', JSON.stringify(aiConfig));12}13 14// AI Setup Dialog15function showAISetup() {16 const endpoint = prompt('AI Endpoint:', aiConfig.endpoint);17 if (endpoint === null) return;18 19 const apiKey = prompt('API Key:', aiConfig.apiKey);20 if (apiKey === null) return;21 22 const model = prompt('Model:', aiConfig.model);23 if (model === null) return;24 25 aiConfig = { endpoint, apiKey, model };26 saveAIConfig();27 alert('AI configuration saved!');28}29 30// Function to call AI31async function callAIAssistant(prompt) {32 if (!aiConfig.apiKey) {33 alert('Please configure AI first');34 showAISetup();35 return null;36 }37 38 try {39 const response = await fetch(aiConfig.endpoint, {40 method: 'POST',41 headers: {42 'Content-Type': 'application/json',43 'Authorization': `Bearer ${aiConfig.apiKey}`44 },45 body: JSON.stringify({46 model: aiConfig.model,47 messages: [{48 role: 'user',49 content: `As a coding assistant, help with this request: ${prompt}\nCurrent code:\n${editor.getValue()}`50 }],51 temperature: 0.752 })53 });54 55 if (!response.ok) {56 throw new Error(`AI request failed: ${response.status}`);57 }58 59 const data = await response.json();60 return data.choices?.[0]?.message?.content || null;61 } catch (error) {62 console.error('AI Error:', error);63 return null;64 }65}66document.addEventListener('DOMContentLoaded', function() {67 // View toggle setup68 const viewButtons = document.querySelectorAll('.view-btn');69 const previewContainer = document.getElementById('preview-container');70 71 viewButtons.forEach(btn => {72 btn.addEventListener('click', () => {73 viewButtons.forEach(b => b.classList.remove('active', 'bg-blue-600'));74 btn.classList.add('active', 'bg-blue-600');75 76 if (btn.dataset.view === 'preview') {77 previewContainer.classList.remove('hidden');78 previewContainer.innerHTML = editor.getValue();79 } else {80 previewContainer.classList.add('hidden');81 }82 });83 });84 85 // AI setup button86 document.getElementById('ai-setup-btn').addEventListener('click', showAISetup);87 88 // Initialize CodeMirror editor89const editor = CodeMirror(document.getElementById('editor-container'), {90 mode: 'htmlmixed',91 theme: 'dracula',92 lineNumbers: true,93 indentUnit: 2,94 tabSize: 2,95 value: `<!DOCTYPE html>96<html>97<head>98 <title>Age Calculator</title>99 <style>100 body {101 font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;102 display: flex;103 justify-content: center;104 align-items: center;105 min-height: 100vh;106 background: linear-gradient(135deg, #667eea, #764ba2);107 margin: 0;108 padding: 20px;109 }110 .calculator {111 background: white;112 border-radius: 10px;113 box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);114 padding: 30px;115 width: 100%;116 max-width: 400px;117 }118 h1 {119 color: #333;120 text-align: center;121 margin-bottom: 30px;122 }123 .form-group {124 margin-bottom: 20px;125 }126 label {127 display: block;128 margin-bottom: 8px;129 color: #555;130 }131 input {132 width: 100%;133 padding: 12px;134 border: 1px solid #ddd;135 border-radius: 5px;136 font-size: 16px;137 }138 button {139 width: 100%;140 padding: 12px;141 background: #667eea;142 color: white;143 border: none;144 border-radius: 5px;145 font-size: 16px;146 cursor: pointer;147 transition: background 0.3s;148 }149 button:hover {150 background: #5a6dc7;151 }152 #result {153 margin-top: 20px;154 padding: 15px;155 background: #f8f9fa;156 border-radius: 5px;157 text-align: center;158 font-size: 18px;159 display: none;160 }161 </style>162</head>163<body>164 <div class="calculator">165 <h1>Age Calculator</h1>166 <div class="form-group">167 <label for="birthdate">Enter your birthdate:</label>168 <input type="date" id="birthdate">169 </div>170 <button onclick="calculateAge()">Calculate Age</button>171 <div id="result"></div>172 </div>173 174 <script>175 function calculateAge() {176 const birthdate = new Date(document.getElementById('birthdate').value);177 const today = new Date();178 179 if (isNaN(birthdate.getTime())) {180 alert('Please enter a valid date');181 return;182 }183 184 let age = today.getFullYear() - birthdate.getFullYear();185 const monthDiff = today.getMonth() - birthdate.getMonth();186 187 if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthdate.getDate())) {188 age--;189 }190 191 const resultDiv = document.getElementById('result');192 resultDiv.style.display = 'block';193 resultDiv.innerHTML = \`Your age is: <strong>\${age}</strong> years old\`;194 }195 </script>196</body>197</html>`,198autoCloseTags: true,199 lineWrapping: true,200 extraKeys: {201 'Ctrl-Enter': runCode,202 'Cmd-Enter': runCode203 }204 });205 206 const previewFrame = document.getElementById('preview-frame');207 const runBtn = document.getElementById('run-btn');208 const tabButtons = document.querySelectorAll('.tab-btn');209 210 // Set up tab switching211 tabButtons.forEach(btn => {212 btn.addEventListener('click', () => {213 tabButtons.forEach(b => b.classList.remove('active', 'bg-blue-600'));214 btn.classList.add('active', 'bg-blue-600');215 216 const lang = btn.dataset.lang;217 if (lang === 'html') {218 editor.setOption('mode', 'htmlmixed');219 } else if (lang === 'css') {220 editor.setOption('mode', 'css');221 } else if (lang === 'js') {222 editor.setOption('mode', 'javascript');223 }224 });225 });226 // AI button click handler227 document.getElementById('ai-btn').addEventListener('click', async () => {228 const prompt = window.prompt('What would you like the AI to do? (e.g. "Create a counter component", "Fix the layout", etc.)');229 if (prompt) {230 const aiResponse = await callAIAssistant(prompt);231 if (aiResponse) {232 editor.setValue(aiResponse);233 runCode();234 } else {235 alert('Failed to get response from AI');236 }237 }238 });239 240 // Run button click handler241 runBtn.addEventListener('click', runCode);242// Initial run243 runCode();244 function runCode() {245 const code = editor.getValue();246 const previewContainer = document.getElementById('preview-container');247 previewContainer.innerHTML = '';248 249 // Create iframe to isolate the age calculator250 const iframe = document.createElement('iframe');251 iframe.style.width = '100%';252 iframe.style.height = '100%';253 iframe.style.border = 'none';254 255 previewContainer.appendChild(iframe);256 257 const previewDoc = iframe.contentDocument || iframe.contentWindow.document;258 previewDoc.open();259 previewDoc.write(code);260 previewDoc.close();261 262 // Add event listener for the calculate button in the preview263 iframe.contentWindow.calculateAge = function() {264 const birthdate = new Date(iframe.contentDocument.getElementById('birthdate').value);265 const today = new Date();266 267 if (isNaN(birthdate.getTime())) {268 iframe.contentWindow.alert('Please enter a valid date');269 return;270 }271 272 let age = today.getFullYear() - birthdate.getFullYear();273 const monthDiff = today.getMonth() - birthdate.getMonth();274 275 if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthdate.getDate())) {276 age--;277 }278 279 const resultDiv = iframe.contentDocument.getElementById('result');280 resultDiv.style.display = 'block';281 resultDiv.innerHTML = `Your age is: <strong>${age}</strong> years old`;282 };283 }284// Auto-run on code change with debounce285 let debounceTimer;286 editor.on('change', () => {287 clearTimeout(debounceTimer);288 debounceTimer = setTimeout(runCode, 1000);289 });290});291 