f / index.html
fahad509's picture
تحقق من طريقة عمل api ولا تنسى ان تضيف ايضا تحسينات وتطويرات - Initial Deployment
86480f2 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Professional AI Chat Interface</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
.message-fade {
animation: fadeIn 0.3s ease-in-out;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
.typing-indicator::after {
content: "...";
animation: typing 1.5s infinite;
}
@keyframes typing {
0% { content: "."; }
33% { content: ".."; }
66% { content: "..."; }
}
.code-block {
position: relative;
}
.code-toolbar {
position: absolute;
top: 8px;
right: 8px;
opacity: 0;
transition: opacity 0.2s;
}
.code-block:hover .code-toolbar {
opacity: 1;
}
.tooltip {
position: relative;
}
.tooltip:hover::after {
content: attr(data-tooltip);
position: absolute;
bottom: 100%;
left: 50%;
transform: translateX(-50%);
background: #333;
color: white;
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
white-space: nowrap;
z-index: 10;
}
.quick-command {
transition: all 0.2s;
}
.quick-command:hover {
transform: translateY(-1px);
}
</style>
</head>
<body class="bg-gray-100 font-sans">
<div class="flex flex-col h-screen">
<!-- Header -->
<header class="bg-indigo-700 text-white p-4 shadow-md">
<div class="container mx-auto flex justify-between items-center">
<div class="flex items-center space-x-4">
<h1 class="text-2xl font-bold">AI Chat Professional</h1>
<select id="api-provider" class="text-sm border border-gray-300 rounded px-2 py-1 bg-white">
<option value="openai">OpenAI</option>
<option value="anthropic">Anthropic</option>
<option value="aliyun">Aliyun</option>
</select>
<select id="chat-mode" class="text-sm border border-gray-300 rounded px-2 py-1 bg-white">
<option value="general">General</option>
<option value="technical">Technical</option>
<option value="creative">Creative</option>
<option value="academic">Academic</option>
<option value="business">Business</option>
</select>
</div>
<div class="flex items-center space-x-4">
<button id="settings-btn" class="p-2 rounded-full hover:bg-indigo-600 transition">
<i class="fas fa-cog"></i>
</button>
<button id="history-btn" class="p-2 rounded-full hover:bg-indigo-600 transition">
<i class="fas fa-history"></i>
</button>
</div>
</div>
</header>
<!-- Main Content -->
<main class="flex-1 flex flex-col md:flex-row container mx-auto p-4 gap-4 overflow-hidden">
<!-- Sidebar (Settings) -->
<div id="settings-sidebar" class="hidden md:block w-full md:w-80 bg-white rounded-lg shadow-md p-4 overflow-y-auto">
<h2 class="text-xl font-semibold mb-4 text-gray-800">Model Configuration</h2>
<div class="mb-6">
<label class="block text-gray-700 mb-2">API Key</label>
<input type="password" id="api-key" value="sk-5c6d9121897544829cd0213db3d6749c"
class="w-full p-2 border border-gray-300 rounded focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500">
</div>
<div class="mb-6">
<label class="block text-gray-700 mb-2">Model Behavior</label>
<textarea id="system-prompt" rows="4"
class="w-full p-2 border border-gray-300 rounded focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500"
placeholder="You are a helpful AI assistant...">You are an expert AI assistant specialized in programming and technical topics. Provide clear, concise answers with code examples when appropriate. Format code blocks properly and explain complex concepts in simple terms.</textarea>
</div>
<div class="mb-6">
<label class="block text-gray-700 mb-2">Temperature</label>
<input type="range" id="temperature" min="0" max="1" step="0.1" value="0.7"
class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer">
<div class="flex justify-between text-xs text-gray-500 mt-1">
<span>Precise</span>
<span>Balanced</span>
<span>Creative</span>
</div>
</div>
<div class="mb-6">
<label class="block text-gray-700 mb-2">Max Tokens</label>
<input type="number" id="max-tokens" min="100" max="4000" value="2000"
class="w-full p-2 border border-gray-300 rounded focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500">
</div>
<div class="mb-6">
<label class="block text-gray-700 mb-2">Response Style</label>
<select id="response-style" class="w-full p-2 border border-gray-300 rounded focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500">
<option value="professional">Professional</option>
<option value="friendly">Friendly</option>
<option value="concise">Concise</option>
<option value="detailed">Detailed</option>
<option value="creative">Creative</option>
</select>
</div>
<div class="mb-6">
<label class="flex items-center space-x-2 cursor-pointer">
<input type="checkbox" id="auto-continue" class="rounded text-indigo-600 focus:ring-indigo-500">
<span class="text-gray-700">Auto-continue long responses</span>
</label>
</div>
<div class="mb-6">
<label class="flex items-center space-x-2 cursor-pointer">
<input type="checkbox" id="web-search" class="rounded text-indigo-600 focus:ring-indigo-500">
<span class="text-gray-700">Enable web search for answers</span>
</label>
</div>
<div class="mb-6">
<h3 class="text-lg font-semibold mb-2 text-gray-800">Quick Commands</h3>
<div class="grid grid-cols-2 gap-2">
<button class="quick-command bg-gray-200 hover:bg-gray-300 text-gray-800 py-1 px-2 rounded text-sm" data-command="/summarize">
Summarize
</button>
<button class="quick-command bg-gray-200 hover:bg-gray-300 text-gray-800 py-1 px-2 rounded text-sm" data-command="/translate">
Translate
</button>
<button class="quick-command bg-gray-200 hover:bg-gray-300 text-gray-800 py-1 px-2 rounded text-sm" data-command="/explain">
Explain
</button>
<button class="quick-command bg-gray-200 hover:bg-gray-300 text-gray-800 py-1 px-2 rounded text-sm" data-command="/code">
Generate Code
</button>
</div>
</div>
<button id="save-settings" class="w-full bg-indigo-600 text-white py-2 px-4 rounded hover:bg-indigo-700 transition">
Save Configuration
</button>
</div>
<!-- Chat Area -->
<div class="flex-1 flex flex-col bg-white rounded-lg shadow-md overflow-hidden">
<!-- Messages Container -->
<div id="messages-container" class="flex-1 overflow-y-auto p-4 space-y-4">
<div class="text-center text-gray-500 py-8">
<i class="fas fa-robot text-4xl mb-2 text-indigo-500"></i>
<p>How can I help you today?</p>
</div>
</div>
<!-- Input Area -->
<div class="border-t border-gray-200 p-4 bg-gray-50">
<div class="flex items-end space-x-2 mb-2">
<div class="flex space-x-1">
<button id="bold-btn" class="p-2 text-gray-500 hover:text-indigo-600 tooltip" data-tooltip="Bold">
<i class="fas fa-bold"></i>
</button>
<button id="italic-btn" class="p-2 text-gray-500 hover:text-indigo-600 tooltip" data-tooltip="Italic">
<i class="fas fa-italic"></i>
</button>
<button id="list-btn" class="p-2 text-gray-500 hover:text-indigo-600 tooltip" data-tooltip="List">
<i class="fas fa-list-ul"></i>
</button>
<button id="code-btn" class="p-2 text-gray-500 hover:text-indigo-600 tooltip" data-tooltip="Code Block">
<i class="fas fa-code"></i>
</button>
<button id="attach-btn" class="p-2 text-gray-500 hover:text-indigo-600 tooltip" data-tooltip="Attach File">
<i class="fas fa-paperclip"></i>
</button>
<button id="image-btn" class="p-2 text-gray-500 hover:text-indigo-600 tooltip" data-tooltip="Insert Image">
<i class="fas fa-image"></i>
</button>
</div>
</div>
<div class="flex space-x-2">
<textarea id="message-input" rows="2"
class="flex-1 p-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 resize-none"
placeholder="Type your message here..."></textarea>
<button id="send-btn" class="bg-indigo-600 text-white p-3 rounded-lg hover:bg-indigo-700 transition self-end">
<i class="fas fa-paper-plane"></i>
</button>
</div>
<div class="flex justify-between items-center mt-2 text-xs text-gray-500">
<div id="typing-indicator" class="typing-indicator hidden">AI is typing</div>
<div>
<span id="char-count">0</span>/1000
</div>
</div>
</div>
</div>
</main>
</div>
<!-- Modals -->
<!-- History Modal -->
<div id="history-modal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden">
<div class="bg-white rounded-lg shadow-xl w-full max-w-2xl max-h-[80vh] overflow-hidden">
<div class="flex justify-between items-center p-4 border-b">
<h3 class="text-lg font-semibold">Chat History</h3>
<button id="close-history" class="text-gray-500 hover:text-gray-700">
<i class="fas fa-times"></i>
</button>
</div>
<div id="history-list" class="overflow-y-auto p-4 space-y-2">
<!-- History items will be added here -->
</div>
<div class="p-4 border-t flex justify-end">
<button id="clear-history" class="text-red-500 hover:text-red-700">
<i class="fas fa-trash mr-1"></i> Clear History
</button>
</div>
</div>
</div>
<!-- Code Save Modal -->
<div id="code-save-modal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden">
<div class="bg-white rounded-lg shadow-xl w-full max-w-md p-6">
<div class="flex justify-between items-center mb-4">
<h3 class="text-lg font-semibold">Save Code Snippet</h3>
<button id="close-code-save" class="text-gray-500 hover:text-gray-700">
<i class="fas fa-times"></i>
</button>
</div>
<div class="mb-4">
<label class="block text-gray-700 mb-2">Title</label>
<input type="text" id="code-title" class="w-full p-2 border border-gray-300 rounded">
</div>
<div class="mb-4">
<label class="block text-gray-700 mb-2">Language</label>
<select id="code-language" class="w-full p-2 border border-gray-300 rounded">
<option value="javascript">JavaScript</option>
<option value="html">HTML</option>
<option value="css">CSS</option>
<option value="python">Python</option>
<option value="java">Java</option>
<option value="php">PHP</option>
<option value="csharp">C#</option>
<option value="cpp">C++</option>
</select>
</div>
<div class="flex justify-end space-x-2">
<button id="cancel-code-save" class="px-4 py-2 border border-gray-300 rounded hover:bg-gray-100">
Cancel
</button>
<button id="confirm-code-save" class="px-4 py-2 bg-indigo-600 text-white rounded hover:bg-indigo-700">
Save
</button>
</div>
</div>
</div>
<!-- Saved Codes Modal -->
<div id="saved-codes-modal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden">
<div class="bg-white rounded-lg shadow-xl w-full max-w-4xl max-h-[80vh] overflow-hidden">
<div class="flex justify-between items-center p-4 border-b">
<h3 class="text-lg font-semibold">Saved Code Snippets</h3>
<button id="close-saved-codes" class="text-gray-500 hover:text-gray-700">
<i class="fas fa-times"></i>
</button>
</div>
<div id="saved-codes-list" class="overflow-y-auto p-4 grid grid-cols-1 md:grid-cols-2 gap-4">
<!-- Saved codes will be added here -->
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
// DOM Elements
const messagesContainer = document.getElementById('messages-container');
const messageInput = document.getElementById('message-input');
const sendBtn = document.getElementById('send-btn');
const apiKeyInput = document.getElementById('api-key');
const systemPrompt = document.getElementById('system-prompt');
const temperature = document.getElementById('temperature');
const maxTokens = document.getElementById('max-tokens');
const saveSettingsBtn = document.getElementById('save-settings');
const settingsSidebar = document.getElementById('settings-sidebar');
const settingsBtn = document.getElementById('settings-btn');
const historyBtn = document.getElementById('history-btn');
const historyModal = document.getElementById('history-modal');
const closeHistory = document.getElementById('close-history');
const historyList = document.getElementById('history-list');
const clearHistory = document.getElementById('clear-history');
const typingIndicator = document.getElementById('typing-indicator');
const charCount = document.getElementById('char-count');
const codeBtn = document.getElementById('code-btn');
const codeSaveModal = document.getElementById('code-save-modal');
const closeCodeSave = document.getElementById('close-code-save');
const cancelCodeSave = document.getElementById('cancel-code-save');
const confirmCodeSave = document.getElementById('confirm-code-save');
const savedCodesModal = document.getElementById('saved-codes-modal');
const closeSavedCodes = document.getElementById('close-saved-codes');
const savedCodesList = document.getElementById('saved-codes-list');
// State
let chatHistory = JSON.parse(localStorage.getItem('chatHistory')) || [];
let savedCodes = JSON.parse(localStorage.getItem('savedCodes')) || [];
let currentCodeToSave = null;
let isWaitingForResponse = false;
// Initialize
updateCharCount();
renderSavedCodes();
// Event Listeners
messageInput.addEventListener('input', updateCharCount);
messageInput.addEventListener('keydown', function(e) {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
sendMessage();
}
});
sendBtn.addEventListener('click', sendMessage);
saveSettingsBtn.addEventListener('click', saveSettings);
settingsBtn.addEventListener('click', toggleSettings);
historyBtn.addEventListener('click', showHistoryModal);
closeHistory.addEventListener('click', hideHistoryModal);
clearHistory.addEventListener('click', clearChatHistory);
codeBtn.addEventListener('click', showSavedCodesModal);
closeCodeSave.addEventListener('click', hideCodeSaveModal);
cancelCodeSave.addEventListener('click', hideCodeSaveModal);
confirmCodeSave.addEventListener('click', saveCurrentCode);
closeSavedCodes.addEventListener('click', hideSavedCodesModal);
// Functions
function updateCharCount() {
const count = messageInput.value.length;
charCount.textContent = count;
if (count > 1000) {
charCount.classList.add('text-red-500');
} else {
charCount.classList.remove('text-red-500');
}
}
function toggleSettings() {
settingsSidebar.classList.toggle('hidden');
}
function saveSettings() {
localStorage.setItem('apiKey', apiKeyInput.value);
localStorage.setItem('systemPrompt', systemPrompt.value);
localStorage.setItem('temperature', temperature.value);
localStorage.setItem('maxTokens', maxTokens.value);
// Show confirmation
const confirmation = document.createElement('div');
confirmation.className = 'fixed bottom-4 right-4 bg-green-500 text-white px-4 py-2 rounded shadow-lg';
confirmation.textContent = 'Settings saved successfully!';
document.body.appendChild(confirmation);
setTimeout(() => {
confirmation.remove();
}, 3000);
}
async function getApiEndpoint(modelType) {
const modelMap = {
'general': 'gpt-3.5-turbo',
'technical': 'gpt-4',
'creative': 'gpt-4-turbo',
'academic': 'claude-3',
'business': 'gpt-4',
'vision': 'gpt-4-vision'
};
const baseUrls = {
'openai': 'https://api.openai.com/v1/chat/completions',
'anthropic': 'https://api.anthropic.com/v1/messages',
'aliyun': 'https://dashscope-intl.aliyuncs.com/compatible-mode/v1/chat/completions'
};
const model = modelMap[modelType] || 'gpt-3.5-turbo';
if (model.includes('gpt')) return { url: baseUrls.openai, model };
if (model.includes('claude')) return { url: baseUrls.anthropic, model };
return { url: baseUrls.aliyun, model };
}
async function sendMessage() {
const message = messageInput.value.trim();
if (!message || isWaitingForResponse) return;
// Add user message to chat
addMessage('user', message);
messageInput.value = '';
updateCharCount();
// Show typing indicator
isWaitingForResponse = true;
typingIndicator.classList.remove('hidden');
try {
const chatMode = document.getElementById('chat-mode').value;
const { url, model } = await getApiEndpoint(chatMode);
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${apiKeyInput.value || 'sk-5c6d9121897544829cd0213db3d6749c'}`
},
body: JSON.stringify({
model: model,
messages: [
{
role: "system",
content: systemPrompt.value || "You are a helpful AI assistant."
},
...chatHistory.slice(-6).map(msg => ({ // Keep last 6 messages for context
role: msg.role,
content: msg.content
})),
{
role: "user",
content: message
}
],
temperature: parseFloat(temperature.value) || 0.7,
max_tokens: parseInt(maxTokens.value) || 2000,
stream: true // Enable streaming for better UX
}),
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${apiKeyInput.value || 'sk-5c6d9121897544829cd0213db3d6749c'}`,
'Accept': 'application/json'
}
});
if (!response.ok) {
throw new Error(`API request failed with status ${response.status}`);
}
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.error?.message || `API request failed with status ${response.status}`);
}
// Handle streaming response
const reader = response.body.getReader();
const decoder = new TextDecoder();
let aiMessage = '';
let messageDiv = document.createElement('div');
messageDiv.className = 'message-fade flex justify-start';
let bubble = document.createElement('div');
bubble.className = 'max-w-[80%] rounded-lg p-4 bg-gray-200 text-gray-800';
messageDiv.appendChild(bubble);
messagesContainer.appendChild(messageDiv);
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
const lines = chunk.split('\n').filter(line => line.trim() !== '');
for (const line of lines) {
if (line.startsWith('data:') && !line.includes('[DONE]')) {
try {
const data = JSON.parse(line.substring(5));
const content = data.choices[0]?.delta?.content || '';
aiMessage += content;
bubble.innerHTML = formatMessageContent(aiMessage);
messagesContainer.scrollTop = messagesContainer.scrollHeight;
} catch (e) {
console.error('Error parsing stream chunk:', e);
}
}
}
}
// Update chat history
chatHistory.push(
{ role: 'user', content: message },
{ role: 'assistant', content: aiMessage }
);
// Save to localStorage
localStorage.setItem('chatHistory', JSON.stringify(chatHistory));
} catch (error) {
console.error('Error:', error);
addMessage('assistant', `Sorry, I encountered an error: ${error.message}`);
} finally {
// Hide typing indicator
typingIndicator.classList.add('hidden');
isWaitingForResponse = false;
}
}
function formatMessageContent(content) {
// Format code blocks
let formattedContent = content.replace(/```(\w*)\n([\s\S]*?)\n```/g,
(match, lang, code) => {
return `<div class="code-block bg-gray-800 text-gray-100 p-4 rounded my-2 overflow-x-auto relative">
<pre><code class="language-${lang || 'text'}">${code.trim()}</code></pre>
<div class="code-toolbar flex space-x-2">
<button class="copy-code bg-gray-700 hover:bg-gray-600 text-white p-1 rounded" title="Copy">
<i class="fas fa-copy text-xs"></i>
</button>
<button class="save-code bg-gray-700 hover:bg-gray-600 text-white p-1 rounded" title="Save">
<i class="fas fa-save text-xs"></i>
</button>
</div>
</div>`;
});
// Format inline code
formattedContent = formattedContent.replace(/`([^`]+)`/g, '<code class="bg-gray-200 text-gray-800 px-1 rounded">$1</code>');
// Format links
formattedContent = formattedContent.replace(/(https?:\/\/[^\s]+)/g, '<a href="$1" target="_blank" class="text-indigo-600 hover:underline">$1</a>');
return formattedContent;
}
function addMessage(role, content) {
const messageDiv = document.createElement('div');
messageDiv.className = `message-fade flex ${role === 'user' ? 'justify-end' : 'justify-start'}`;
const bubble = document.createElement('div');
bubble.className = `max-w-[80%] rounded-lg p-4 ${role === 'user' ? 'bg-indigo-600 text-white' : 'bg-gray-200 text-gray-800'}`;
// Format content with markdown-like code blocks
let formattedContent = content;
// Replace code blocks with proper formatting
formattedContent = formattedContent.replace(/```(\w*)\n([\s\S]*?)\n```/g,
(match, lang, code) => {
return `<div class="code-block bg-gray-800 text-gray-100 p-4 rounded my-2 overflow-x-auto relative">
<pre><code class="language-${lang || 'text'}">${code.trim()}</code></pre>
<div class="code-toolbar flex space-x-2">
<button class="copy-code bg-gray-700 hover:bg-gray-600 text-white p-1 rounded" title="Copy">
<i class="fas fa-copy text-xs"></i>
</button>
<button class="save-code bg-gray-700 hover:bg-gray-600 text-white p-1 rounded" title="Save">
<i class="fas fa-save text-xs"></i>
</button>
</div>
</div>`;
});
// Replace inline code
formattedContent = formattedContent.replace(/`([^`]+)`/g, '<code class="bg-gray-200 text-gray-800 px-1 rounded">$1</code>');
bubble.innerHTML = formattedContent;
messageDiv.appendChild(bubble);
// Add to messages container
messagesContainer.appendChild(messageDiv);
// Scroll to bottom
messagesContainer.scrollTop = messagesContainer.scrollHeight;
// Add event listeners for code block buttons
setTimeout(() => {
document.querySelectorAll('.copy-code').forEach(btn => {
btn.addEventListener('click', function() {
const codeBlock = this.closest('.code-block').querySelector('code');
navigator.clipboard.writeText(codeBlock.textContent);
// Show copied notification
const notification = document.createElement('div');
notification.className = 'absolute top-2 right-2 bg-green-500 text-white px-2 py-1 rounded text-xs';
notification.textContent = 'Copied!';
this.parentNode.appendChild(notification);
setTimeout(() => {
notification.remove();
}, 2000);
});
});
document.querySelectorAll('.save-code').forEach(btn => {
btn.addEventListener('click', function() {
const codeBlock = this.closest('.code-block');
const code = codeBlock.querySelector('code').textContent;
const lang = codeBlock.querySelector('code').className.replace('language-', '') || 'text';
currentCodeToSave = { code, lang };
showCodeSaveModal();
});
});
}, 100);
}
function showHistoryModal() {
historyList.innerHTML = '';
if (chatHistory.length === 0) {
historyList.innerHTML = '<p class="text-gray-500 text-center py-4">No chat history available</p>';
} else {
chatHistory.forEach((msg, index) => {
if (msg.role === 'user') {
const historyItem = document.createElement('div');
historyItem.className = 'p-3 bg-gray-100 rounded mb-2 cursor-pointer hover:bg-gray-200';
historyItem.textContent = msg.content;
historyItem.addEventListener('click', () => {
// Clear current chat and load this conversation
// (Implementation would depend on how you want to handle this)
});
historyList.appendChild(historyItem);
}
});
}
historyModal.classList.remove('hidden');
}
function hideHistoryModal() {
historyModal.classList.add('hidden');
}
function clearChatHistory() {
chatHistory = [];
localStorage.removeItem('chatHistory');
hideHistoryModal();
// Clear messages container except for the welcome message
messagesContainer.innerHTML = `
<div class="text-center text-gray-500 py-8">
<i class="fas fa-robot text-4xl mb-2 text-indigo-500"></i>
<p>How can I help you today?</p>
</div>
`;
}
function showCodeSaveModal() {
if (!currentCodeToSave) return;
codeSaveModal.classList.remove('hidden');
}
function hideCodeSaveModal() {
codeSaveModal.classList.add('hidden');
}
function saveCurrentCode() {
if (!currentCodeToSave) return;
const title = document.getElementById('code-title').value.trim() || 'Untitled Code';
const language = document.getElementById('code-language').value;
savedCodes.push({
title,
language,
code: currentCodeToSave.code,
timestamp: new Date().toISOString()
});
localStorage.setItem('savedCodes', JSON.stringify(savedCodes));
renderSavedCodes();
// Reset form
document.getElementById('code-title').value = '';
document.getElementById('code-language').value = 'javascript';
currentCodeToSave = null;
hideCodeSaveModal();
// Show confirmation
const confirmation = document.createElement('div');
confirmation.className = 'fixed bottom-4 right-4 bg-green-500 text-white px-4 py-2 rounded shadow-lg';
confirmation.textContent = 'Code saved successfully!';
document.body.appendChild(confirmation);
setTimeout(() => {
confirmation.remove();
}, 3000);
}
function showSavedCodesModal() {
renderSavedCodes();
savedCodesModal.classList.remove('hidden');
}
function hideSavedCodesModal() {
savedCodesModal.classList.add('hidden');
}
function renderSavedCodes() {
savedCodesList.innerHTML = '';
if (savedCodes.length === 0) {
savedCodesList.innerHTML = '<p class="text-gray-500 text-center col-span-2 py-8">No saved code snippets</p>';
} else {
savedCodes.forEach((snippet, index) => {
const snippetDiv = document.createElement('div');
snippetDiv.className = 'bg-gray-100 rounded-lg p-4 border border-gray-200';
snippetDiv.innerHTML = `
<div class="flex justify-between items-start mb-2">
<h4 class="font-medium text-gray-800">${snippet.title}</h4>
<span class="text-xs bg-indigo-100 text-indigo-800 px-2 py-1 rounded">${snippet.language}</span>
</div>
<pre class="bg-gray-800 text-gray-100 text-xs p-3 rounded overflow-x-auto max-h-40">${snippet.code}</pre>
<div class="flex justify-between items-center mt-2 text-xs text-gray-500">
<span>${new Date(snippet.timestamp).toLocaleString()}</span>
<div class="space-x-2">
<button class="copy-snippet text-gray-500 hover:text-indigo-600" data-index="${index}">
<i class="fas fa-copy"></i>
</button>
<button class="delete-snippet text-gray-500 hover:text-red-600" data-index="${index}">
<i class="fas fa-trash"></i>
</button>
</div>
</div>
`;
savedCodesList.appendChild(snippetDiv);
});
// Add event listeners for the buttons
document.querySelectorAll('.copy-snippet').forEach(btn => {
btn.addEventListener('click', function() {
const index = parseInt(this.getAttribute('data-index'));
navigator.clipboard.writeText(savedCodes[index].code);
// Show copied notification
const notification = document.createElement('div');
notification.className = 'fixed bottom-4 right-4 bg-green-500 text-white px-4 py-2 rounded shadow-lg';
notification.textContent = 'Code copied to clipboard!';
document.body.appendChild(notification);
setTimeout(() => {
notification.remove();
}, 3000);
});
});
document.querySelectorAll('.delete-snippet').forEach(btn => {
btn.addEventListener('click', function() {
const index = parseInt(this.getAttribute('data-index'));
if (confirm('Are you sure you want to delete this code snippet?')) {
savedCodes.splice(index, 1);
localStorage.setItem('savedCodes', JSON.stringify(savedCodes));
renderSavedCodes();
}
});
});
}
}
});
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=fahad509/f" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>