| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>Code Assistant AI</title> |
| <script src="https://cdn.tailwindcss.com"></script> |
| <script src="https://unpkg.com/lucide@latest"></script> |
| <script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script> |
| <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script> |
| <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script> |
| <style> |
| .code-editor { |
| min-height: 300px; |
| font-family: 'Courier New', monospace; |
| tab-size: 4; |
| } |
| .dark .code-editor { |
| background-color: #1e293b; |
| color: #f8fafc; |
| } |
| .dark .output-panel { |
| background-color: #1e293b; |
| color: #f8fafc; |
| } |
| .dark .sidebar { |
| background-color: #0f172a; |
| } |
| .dark .tab-active { |
| border-bottom-color: #3b82f6; |
| color: #3b82f6; |
| } |
| .dark .tab-inactive { |
| border-bottom-color: transparent; |
| color: #94a3b8; |
| } |
| .dark .file-upload-label { |
| background-color: #1e293b; |
| border-color: #334155; |
| } |
| .dark .file-upload-label:hover { |
| background-color: #334155; |
| } |
| .transition-all { |
| transition-property: all; |
| transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); |
| transition-duration: 150ms; |
| } |
| </style> |
| </head> |
| <body class="bg-gray-100 dark:bg-gray-900 transition-all duration-300"> |
| <div id="root"></div> |
|
|
| <script type="text/babel"> |
| const { useState, useEffect, useRef } = React; |
| |
| const CodeAssistant = () => { |
| |
| const [darkMode, setDarkMode] = useState(false); |
| const [inputCode, setInputCode] = useState(''); |
| const [outputCode, setOutputCode] = useState(''); |
| const [analysis, setAnalysis] = useState(''); |
| const [htmlPreview, setHtmlPreview] = useState(''); |
| const [activeTab, setActiveTab] = useState('output'); |
| const [sourceLanguage, setSourceLanguage] = useState('auto'); |
| const [targetLanguage, setTargetLanguage] = useState('javascript'); |
| const [processingMode, setProcessingMode] = useState('improve'); |
| const [isLoading, setIsLoading] = useState(false); |
| const [error, setError] = useState(null); |
| const [success, setSuccess] = useState(null); |
| const [detectedLanguage, setDetectedLanguage] = useState(null); |
| const [fileName, setFileName] = useState(''); |
| |
| |
| const fileInputRef = useRef(null); |
| const textareaRef = useRef(null); |
| |
| |
| const languages = [ |
| { value: 'auto', label: 'Auto-detect' }, |
| { value: 'python', label: 'Python' }, |
| { value: 'javascript', label: 'JavaScript' }, |
| { value: 'java', label: 'Java' }, |
| { value: 'c++', label: 'C++' }, |
| { value: 'html', label: 'HTML' }, |
| { value: 'css', label: 'CSS' }, |
| { value: 'jsx', label: 'React JSX' } |
| ]; |
| |
| |
| const modes = [ |
| { value: 'improve', label: 'Improve Code' }, |
| { value: 'convert', label: 'Convert Code' }, |
| { value: 'analyze', label: 'Analyze Code' } |
| ]; |
| |
| |
| const toggleDarkMode = () => { |
| setDarkMode(!darkMode); |
| document.documentElement.classList.toggle('dark'); |
| }; |
| |
| |
| const detectLanguage = (code) => { |
| if (!code.trim()) return null; |
| |
| |
| if (code.includes('<html') || code.includes('<!DOCTYPE html')) return 'html'; |
| if (code.includes('</style>') || code.includes('{') && code.includes('}') && code.includes(':')) return 'css'; |
| if (code.includes('import React') || code.includes('</>')) return 'jsx'; |
| if (code.includes('def ') || code.includes('lambda ') || code.includes('import ')) return 'python'; |
| if (code.includes('function ') || code.includes('=>') || code.includes('const ') || code.includes('let ')) return 'javascript'; |
| if (code.includes('public class') || code.includes('System.out.println')) return 'java'; |
| if (code.includes('#include') || code.includes('std::')) return 'c++'; |
| |
| return null; |
| }; |
| |
| |
| const handleFileUpload = (e) => { |
| const file = e.target.files[0]; |
| if (!file) return; |
| |
| setFileName(file.name); |
| const reader = new FileReader(); |
| reader.onload = (event) => { |
| setInputCode(event.target.result); |
| const detected = detectLanguage(event.target.result); |
| if (detected) setSourceLanguage(detected); |
| }; |
| reader.readAsText(file); |
| }; |
| |
| |
| const loadExample = (lang) => { |
| const examples = { |
| python: 'def greet(name):\n print(f"Hello, {name}!")\n\ngreet("World")', |
| javascript: 'function greet(name) {\n console.log(`Hello, ${name}!`);\n}\n\ngreet("World");', |
| java: 'public class Main {\n public static void greet(String name) {\n System.out.println("Hello, " + name + "!");\n }\n\n public static void main(String[] args) {\n greet("World");\n }\n}', |
| 'c++': '#include <iostream>\n\nvoid greet(std::string name) {\n std::cout << "Hello, " << name << "!" << std::endl;\n}\n\nint main() {\n greet("World");\n return 0;\n}', |
| html: '<!DOCTYPE html>\n<html>\n<head>\n <title>Greeting</title>\n</head>\n<body>\n <h1>Hello, World!</h1>\n</body>\n</html>', |
| css: 'body {\n font-family: Arial, sans-serif;\n background-color: #f0f0f0;\n}\n\nh1 {\n color: #333;\n text-align: center;\n}', |
| jsx: 'import React from "react";\n\nfunction Greeting({ name }) {\n return (\n <div>\n <h1>Hello, {name}!</h1>\n </div>\n );\n}\n\nexport default Greeting;' |
| }; |
| |
| setInputCode(examples[lang] || ''); |
| setSourceLanguage(lang); |
| }; |
| |
| |
| const processCode = async () => { |
| if (!inputCode.trim()) { |
| setError('Please enter some code to process'); |
| return; |
| } |
| |
| setIsLoading(true); |
| setError(null); |
| setSuccess(null); |
| |
| try { |
| |
| |
| |
| const detectedLang = sourceLanguage === 'auto' ? detectLanguage(inputCode) || 'unknown' : sourceLanguage; |
| setDetectedLanguage(detectedLang); |
| |
| |
| await new Promise(resolve => setTimeout(resolve, 1500)); |
| |
| |
| if (processingMode === 'improve') { |
| setOutputCode(`// Improved ${detectedLang} code\n${inputCode}\n// Code has been optimized for better readability and performance`); |
| setAnalysis(`Analysis of ${detectedLang} code:\n\n- Code structure is good\n- Could benefit from more comments\n- Consider using more modern language features`); |
| } else if (processingMode === 'convert') { |
| const targetLangName = languages.find(l => l.value === targetLanguage)?.label || targetLanguage; |
| setOutputCode(`// Converted from ${detectedLang} to ${targetLangName}\n// This is a mock conversion\n${inputCode}`); |
| setAnalysis(`Conversion analysis:\n\n- Some language-specific features may not translate directly\n- Manual review recommended for edge cases`); |
| } else if (processingMode === 'analyze') { |
| setOutputCode(inputCode); |
| setAnalysis(`Detailed analysis of ${detectedLang} code:\n\n1. Syntax: No errors detected\n2. Performance: Good overall\n3. Security: No obvious vulnerabilities\n4. Best Practices: Follows most conventions\n\nRecommendations:\n- Add error handling\n- Consider edge cases`); |
| } |
| |
| if (detectedLang === 'html') { |
| setHtmlPreview(inputCode); |
| } else { |
| setHtmlPreview(''); |
| } |
| |
| setActiveTab('output'); |
| setSuccess('Code processed successfully!'); |
| } catch (err) { |
| setError('Failed to process code. Please try again.'); |
| console.error(err); |
| } finally { |
| setIsLoading(false); |
| } |
| }; |
| |
| |
| const copyToClipboard = (text) => { |
| if (!text) return; |
| |
| navigator.clipboard.writeText(text) |
| .then(() => setSuccess('Copied to clipboard!')) |
| .catch(() => setError('Failed to copy to clipboard')); |
| }; |
| |
| |
| const downloadCode = (content, name) => { |
| if (!content) return; |
| |
| const blob = new Blob([content], { type: 'text/plain' }); |
| const url = URL.createObjectURL(blob); |
| const a = document.createElement('a'); |
| a.href = url; |
| a.download = name || 'code.txt'; |
| document.body.appendChild(a); |
| a.click(); |
| document.body.removeChild(a); |
| URL.revokeObjectURL(url); |
| |
| setSuccess('Download started!'); |
| }; |
| |
| |
| const clearAll = () => { |
| setInputCode(''); |
| setOutputCode(''); |
| setAnalysis(''); |
| setHtmlPreview(''); |
| setFileName(''); |
| setError(null); |
| setSuccess(null); |
| setDetectedLanguage(null); |
| if (fileInputRef.current) fileInputRef.current.value = ''; |
| }; |
| |
| |
| useEffect(() => { |
| if (textareaRef.current) { |
| textareaRef.current.style.height = 'auto'; |
| textareaRef.current.style.height = `${textareaRef.current.scrollHeight}px`; |
| } |
| }, [inputCode]); |
| |
| |
| useEffect(() => { |
| const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; |
| setDarkMode(prefersDark); |
| if (prefersDark) { |
| document.documentElement.classList.add('dark'); |
| } |
| }, []); |
| |
| |
| useEffect(() => { |
| lucide.createIcons(); |
| }, []); |
| |
| return ( |
| <div className={`min-h-screen flex flex-col ${darkMode ? 'dark' : ''}`}> |
| {/* Header */} |
| <header className="bg-blue-600 text-white p-4 shadow-md"> |
| <div className="container mx-auto flex justify-between items-center"> |
| <h1 className="text-2xl font-bold flex items-center"> |
| <i data-lucide="code" className="mr-2"></i> |
| Code Assistant AI |
| </h1> |
| <div className="flex items-center space-x-4"> |
| <button |
| onClick={toggleDarkMode} |
| className="p-2 rounded-full hover:bg-blue-700 transition-colors" |
| aria-label="Toggle dark mode" |
| > |
| {darkMode ? ( |
| <i data-lucide="sun"></i> |
| ) : ( |
| <i data-lucide="moon"></i> |
| )} |
| </button> |
| </div> |
| </div> |
| </header> |
| |
| {/* Main content */} |
| <main className="flex-grow container mx-auto p-4 flex flex-col lg:flex-row gap-6"> |
| {/* Input panel */} |
| <div className="w-full lg:w-1/2 flex flex-col gap-4"> |
| <div className="bg-white dark:bg-gray-800 rounded-lg shadow-md p-4"> |
| <div className="flex justify-between items-center mb-4"> |
| <h2 className="text-xl font-semibold">Input Code</h2> |
| <div className="flex gap-2"> |
| <select |
| value={sourceLanguage} |
| onChange={(e) => setSourceLanguage(e.target.value)} |
| className="bg-gray-100 dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded px-2 py-1 text-sm" |
| > |
| {languages.map((lang) => ( |
| <option key={lang.value} value={lang.value}> |
| {lang.label} |
| </option> |
| ))} |
| </select> |
| <button |
| onClick={() => loadExample(sourceLanguage === 'auto' ? 'javascript' : sourceLanguage)} |
| className="bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600 px-3 py-1 rounded text-sm flex items-center gap-1" |
| > |
| <i data-lucide="file-text" className="w-4 h-4"></i> |
| Example |
| </button> |
| </div> |
| </div> |
| |
| <textarea |
| ref={textareaRef} |
| value={inputCode} |
| onChange={(e) => setInputCode(e.target.value)} |
| className="w-full code-editor p-3 border border-gray-300 dark:border-gray-600 rounded bg-white dark:bg-gray-900 text-gray-800 dark:text-gray-200 resize-none" |
| placeholder="Paste your code here or upload a file..." |
| spellCheck="false" |
| ></textarea> |
| |
| <div className="mt-3 flex flex-wrap gap-2 justify-between"> |
| <div> |
| <label className="file-upload-label inline-block bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600 px-3 py-1 rounded cursor-pointer text-sm"> |
| <i data-lucide="upload" className="inline mr-1 w-4 h-4"></i> |
| Upload File |
| <input |
| type="file" |
| ref={fileInputRef} |
| onChange={handleFileUpload} |
| className="hidden" |
| accept=".txt,.js,.py,.java,.cpp,.html,.css,.jsx" |
| /> |
| </label> |
| {fileName && ( |
| <span className="ml-2 text-sm text-gray-600 dark:text-gray-400"> |
| {fileName} |
| </span> |
| )} |
| </div> |
| |
| <button |
| onClick={clearAll} |
| className="bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600 px-3 py-1 rounded text-sm flex items-center gap-1" |
| > |
| <i data-lucide="trash-2" className="w-4 h-4"></i> |
| Clear |
| </button> |
| </div> |
| </div> |
| |
| <div className="bg-white dark:bg-gray-800 rounded-lg shadow-md p-4"> |
| <h2 className="text-xl font-semibold mb-4">Processing Options</h2> |
| |
| <div className="grid grid-cols-3 gap-2 mb-4"> |
| {modes.map((mode) => ( |
| <button |
| key={mode.value} |
| onClick={() => setProcessingMode(mode.value)} |
| className={`py-2 px-3 rounded text-sm font-medium ${processingMode === mode.value ? 'bg-blue-600 text-white' : 'bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600'}`} |
| > |
| {mode.label} |
| </button> |
| ))} |
| </div> |
| |
| {processingMode === 'convert' && ( |
| <div className="mb-4"> |
| <label className="block text-sm font-medium mb-1">Convert to:</label> |
| <select |
| value={targetLanguage} |
| onChange={(e) => setTargetLanguage(e.target.value)} |
| className="w-full bg-gray-100 dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded px-3 py-2" |
| > |
| {languages.filter(l => l.value !== 'auto').map((lang) => ( |
| <option key={lang.value} value={lang.value}> |
| {lang.label} |
| </option> |
| ))} |
| </select> |
| </div> |
| )} |
| |
| <button |
| onClick={processCode} |
| disabled={isLoading || !inputCode.trim()} |
| className={`w-full py-2 px-4 rounded font-medium flex items-center justify-center gap-2 ${isLoading || !inputCode.trim() ? 'bg-blue-400 dark:bg-blue-500 cursor-not-allowed' : 'bg-blue-600 hover:bg-blue-700 dark:hover:bg-blue-800 text-white'}`} |
| > |
| {isLoading ? ( |
| <> |
| <i data-lucide="loader" className="animate-spin w-5 h-5"></i> |
| Processing... |
| </> |
| ) : ( |
| <> |
| <i data-lucide="zap" className="w-5 h-5"></i> |
| Process Code |
| </> |
| )} |
| </button> |
| </div> |
| </div> |
| |
| {} |
| <div className="w-full lg:w-1/2 flex flex-col gap-4"> |
| <div className="bg-white dark:bg-gray-800 rounded-lg shadow-md overflow-hidden"> |
| <div className="flex border-b border-gray-200 dark:border-gray-700"> |
| <button |
| onClick={() => setActiveTab('output')} |
| className={`px-4 py-3 font-medium ${activeTab === 'output' ? 'tab-active border-b-2' : 'tab-inactive'}`} |
| > |
| Output |
| </button> |
| <button |
| onClick={() => setActiveTab('analysis')} |
| className={`px-4 py-3 font-medium ${activeTab === 'analysis' ? 'tab-active border-b-2' : 'tab-inactive'}`} |
| > |
| Analysis |
| </button> |
| {htmlPreview && ( |
| <button |
| onClick={() => setActiveTab('preview')} |
| className={`px-4 py-3 font-medium ${activeTab === 'preview' ? 'tab-active border-b-2' : 'tab-inactive'}`} |
| > |
| HTML Preview |
| </button> |
| )} |
| </div> |
| |
| <div className="p-4"> |
| {activeTab === 'output' && ( |
| <div className="relative"> |
| {outputCode ? ( |
| <> |
| <pre className="code-editor p-3 bg-gray-50 dark:bg-gray-900 rounded overflow-x-auto">{outputCode}</pre> |
| <div className="absolute top-2 right-2 flex gap-2"> |
| <button |
| onClick={() => copyToClipboard(outputCode)} |
| className="bg-gray-200 dark:bg-gray-700 hover:bg-gray-300 dark:hover:bg-gray-600 p-1 rounded" |
| title="Copy to clipboard" |
| > |
| <i data-lucide="copy" className="w-4 h-4"></i> |
| </button> |
| <button |
| onClick={() => downloadCode(outputCode, 'output.txt')} |
| className="bg-gray-200 dark:bg-gray-700 hover:bg-gray-300 dark:hover:bg-gray-600 p-1 rounded" |
| title="Download" |
| > |
| <i data-lucide="download" className="w-4 h-4"></i> |
| </button> |
| </div> |
| </> |
| ) : ( |
| <div className="text-center py-8 text-gray-500 dark:text-gray-400"> |
| <i data-lucide="code" className="w-8 h-8 mx-auto mb-2"></i> |
| <p>Process code to see the output</p> |
| </div> |
| )} |
| </div> |
| )} |
| |
| {activeTab === 'analysis' && ( |
| <div className="relative"> |
| {analysis ? ( |
| <> |
| <div className="code-editor p-3 bg-gray-50 dark:bg-gray-900 rounded whitespace-pre-wrap">{analysis}</div> |
| <div className="absolute top-2 right-2"> |
| <button |
| onClick={() => copyToClipboard(analysis)} |
| className="bg-gray-200 dark:bg-gray-700 hover:bg-gray-300 dark:hover:bg-gray-600 p-1 rounded" |
| title="Copy to clipboard" |
| > |
| <i data-lucide="copy" className="w-4 h-4"></i> |
| </button> |
| </div> |
| </> |
| ) : ( |
| <div className="text-center py-8 text-gray-500 dark:text-gray-400"> |
| <i data-lucide="search" className="w-8 h-8 mx-auto mb-2"></i> |
| <p>Process code to see the analysis</p> |
| </div> |
| )} |
| </div> |
| )} |
| |
| {activeTab === 'preview' && ( |
| <div className="relative h-full"> |
| <iframe |
| srcDoc={htmlPreview} |
| className="w-full h-96 border border-gray-300 dark:border-gray-600 rounded bg-white" |
| title="HTML Preview" |
| ></iframe> |
| </div> |
| )} |
| </div> |
| </div> |
| |
| {} |
| {(error || success) && ( |
| <div className={`p-3 rounded ${error ? 'bg-red-100 dark:bg-red-900 text-red-800 dark:text-red-200' : 'bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200'}`}> |
| <div className="flex items-center gap-2"> |
| <i data-lucide={error ? 'alert-circle' : 'check-circle'} className="w-5 h-5"></i> |
| <span>{error || success}</span> |
| </div> |
| </div> |
| )} |
| |
| {} |
| {detectedLanguage && ( |
| <div className="bg-white dark:bg-gray-800 rounded-lg shadow-md p-4"> |
| <h3 className="font-medium mb-2">Language Information</h3> |
| <div className="flex items-center gap-2"> |
| <span className="px-2 py-1 bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-200 rounded text-sm"> |
| {languages.find(l => l.value === detectedLanguage)?.label || detectedLanguage} |
| </span> |
| <span className="text-sm text-gray-600 dark:text-gray-400"> |
| {sourceLanguage === 'auto' ? '(Auto-detected)' : '(User-selected)'} |
| </span> |
| </div> |
| </div> |
| )} |
| </div> |
| </main> |
| |
| {} |
| <footer className="bg-gray-100 dark:bg-gray-800 py-4 text-center text-sm text-gray-600 dark:text-gray-400"> |
| <p>Code Assistant AI © {new Date().getFullYear()}</p> |
| </footer> |
| </div> |
| ); |
| }; |
| |
| const root = ReactDOM.createRoot(document.getElementById('root')); |
| root.render(<CodeAssistant />); |
| </script> |
| </body> |
| </html> |
|
|
|
|
| This implementation includes all the requested features: |
|
|
| 1. **Dark/Light Mode Toggle**: With smooth transitions using Tailwind CSS |
| 2. **Responsive Layout**: Two-column on large screens, stacked on mobile |
| 3. **Code Processing**: Three modes (improve, convert, analyze) |
| 4. **Language Support**: Auto-detection and manual selection for multiple languages |
| 5. **File Upload**: With filename display |
| 6. **Example Loading**: For each supported language |
| 7. **Output Tabs**: Switch between output, analysis, and HTML preview |
| 8. **Action Buttons**: Copy, download, clear functionality |
| 9. **Status Messages**: Error and success notifications |
| 10. **Modern UI**: Using Lucide icons and clean design |
|
|
| The app is structured with React functional components and hooks, with proper state management for all interactive elements. The UI is fully responsive and accessible. |