Spaces:
Running
Running

Same ### التكامل الكامل لواجهة الدردشة مع استخدام الأيقونات بشكل أساسي والرسوم التعبيرية كخيار #### 1. تعديل كود HTML (أضف بعد عناصر الواجهة العائمة) ```html <!-- ===== CHAT PANEL ===== --> <div x-show="openChat" x-transition.opacity @keydown.escape.window="openChat=false" class="fixed inset-0 bg-black/50 backdrop-blur-sm z-50 flex items-end sm:items-center justify-center"> <div class="glass w-full sm:max-w-xl h-[60vh] sm:h-[70vh] rounded-t-2xl sm:rounded-xl flex flex-col overflow-hidden shadow-2xl"> <!-- Header with Icons --> <header class="flex items-center justify-between px-4 py-3 bg-gray-900 border-b border-accent/30"> <div class="flex items-center gap-2"> <i class="fas fa-robot text-accent text-lg"></i> <h3 class="font-bold text-white">مساعد المتجر الذكي</h3> </div> <button @click="openChat=false" aria-label="إغلاق الدردشة" class="text-gray-400 hover:text-white transition"> <i class="fas fa-times text-xl"></i> </button> </header> <!-- Messages Container --> <section id="chatScroll" class="flex-1 px-4 py-3 overflow-y-auto space-y-4 bg-gradient-to-b from-gray-900 to-gray-800"> <template x-for="m in messages" :key="m.id"> <div :class="m.role === 'user' ? 'justify-end' : 'justify-start'" class="flex"> <div class="flex items-start gap-2 max-w-[90%]"> <!-- Icons for Different Roles --> <template x-if="m.role === 'assistant'"> <i class="fas fa-robot mt-1.5 text-accent flex-shrink-0"></i> </template> <div :class="m.role === 'user' ? 'bg-accent/10 border border-accent/20 text-accent' : 'bg-gray-800 border border-gray-700 text-white'" class="px-4 py-3 rounded-2xl shadow-sm"> <p x-text="m.content" class="whitespace-pre-line"></p> <!-- Emoji Option (Hidden by Default) --> <div x-show="emojiMode" class="mt-2 flex gap-1"> <template x-for="emoji in m.emojis || []"> <span x-text="emoji" class="text-xl"></span> </template> </div> </div> <template x-if="m.role === 'user'"> <i class="fas fa-user mt-1.5 text-gray-400 flex-shrink-0"></i> </template> </div> </div> </template> </section> <!-- Input Area --> <form
@submit
.prevent="sendMessage()" class="p-3 border-t border-white/10 bg-gray-900 flex gap-2"> <div class="relative flex-1"> <input x-model="draft" placeholder="اكتب رسالتك هنا..." class="w-full bg-gray-800 border border-gray-700 rounded-xl px-4 py-3 text-white placeholder-gray-500 focus:outline-none focus:ring-1 focus:ring-accent"> <!-- Emoji Toggle Button --> <button type="button" @click="emojiMode = !emojiMode" class="absolute left-3 top-1/2 -translate-y-1/2 text-gray-500 hover:text-accent"> <i :class="emojiMode ? 'fas fa-icons text-accent' : 'far fa-face-smile'"></i> </button> </div> <button :disabled="loading || !draft.trim()" class="px-4 py-3 rounded-xl bg-accent hover:bg-accent/90 transition text-white font-bold disabled:opacity-40 flex items-center gap-2"> <i class="fas fa-paper-plane"></i> <span>إرسال</span> </button> </form> </div> </div> ``` #### 2. تحديث حالة Alpine.js (أضف لـ storeAi()) ```javascript Alpine.data('storeAi', () => ({ // ... existing state ... /* Chat System */ openChat: false, draft: '', messages: JSON.parse(localStorage.getItem('chat') || '[]'), loading: false, emojiMode: false, // Emojis as optional feature async sendMessage() { const text = this.draft.trim(); if (!text) return; // Add user message this.messages.push({ id: Date.now(), role: 'user', content: text }); this.draft = ''; this.loading = true; this.persistChat(); this.scrollDown(); try { // Stream assistant reply const res = await fetch('/api/chat', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ messages: this.messages, emoji_mode: this.emojiMode // Send emoji preference }) }); const reader = res.body.getReader(); let assistantMsg = { id: Date.now() + 1, role: 'assistant', content: '', emojis: this.emojiMode ? [] : null // Initialize emojis array if enabled }; this.messages.push(assistantMsg); let buffer = ''; while (true) { const { value, done } = await reader.read(); if (done) break; buffer += new TextDecoder().decode(value); const parts = buffer.split('\n\n'); buffer = parts.pop() || ''; for (const part of parts) { try { const data = JSON.parse(part); assistantMsg.content += data.content || ''; // Add emojis if enabled if (this.emojiMode && data.emojis) { assistantMsg.emojis = [...(assistantMsg.emojis || []), ...data.emojis]; } } catch (e) { console.error('Parsing error:', e); } } this.persistChat(); this.$nextTick(() => this.scrollDown()); } } catch (error) { console.error('Chat error:', error); assistantMsg.content = '⚠️ حدث خطأ في الاتصال بالمساعد. يرجى المحاولة لاحقًا.'; } this.loading = false; this.persistChat(); }, scrollDown() { this.$nextTick(() => { const el = document.getElementById('chatScroll'); if (el) el.scrollTop = el.scrollHeight + 100; }); }, persistChat() { localStorage.setItem('chat', JSON.stringify(this.messages)); } })); ``` #### 3. تحديث زر الدردشة العائم ```html <button id="aiBubble" @click="openChat = true; $nextTick(() => scrollDown())" class="fixed bottom-6 right-6 w-14 h-14 rounded-full bg-accent shadow-lg flex items-center justify-center hover:scale-110 transition-transform"> <i class="fas fa-robot text-white text-2xl"></i> </button> ``` #### 4. نموذج محدث لخادم API (/api/chat) ```javascript import { OpenAI } from 'openai'; import emojiRegex from 'emoji-regex'; export const config = { runtime: 'edge' }; export default async (req) => { const { messages, emoji_mode } = await req.json(); // 1. Moderation Check (Important!) const lastMessage = messages[messages.length - 1]?.content; if (lastMessage) { const moderation = await openai.moderations.create({ input: lastMessage }); if (moderation.results[0]?.flagged) { return new Response(JSON.stringify({ content: "⛔ لا يمكنني الرد على هذا الاستفسار. يرجى طرح سؤال آخر.", emojis: ["⚠️"] }), { status: 200 }); } } // 2. Prepare messages history const history = messages.map(m => ({ role: m.role, content: m.content })); // 3. Create stream const openai = new OpenAI({ apiKey: process.env.OPENAI_KEY }); const stream = await openai.chat.completions.create({ model: 'gpt-4', stream: true, messages: history, max_tokens: 1000 }); // 4. Custom stream processing const encoder = new TextEncoder(); const streamProcessor = new TransformStream({ async transform(chunk, controller) { const text = chunk.choices[0]?.delta?.content || ''; // Extract emojis if enabled let emojis = []; if (emoji_mode) { const matches = text.match(emojiRegex()); if (matches) emojis = [...new Set(matches)]; } controller.enqueue(encoder.encode( JSON.stringify({ content: text, emojis }) + '\n\n' )); } }); return new Response(stream.pipeThrough(streamProcessor), { headers: { 'Content-Type': 'application/ndjson' } }); }; ``` ### ملاحظات الأمان والتكلفة: 1. **التحكم في التكلفة**: ```javascript // أضف في backend قبل openai.chat.completions.create const MAX_DAILY_COST = 5; // دولار if (await checkDailyCostExceeded(userId, MAX_DAILY_COST)) { return new Response(JSON.stringify({ content: "🛑 وصلت لحد الاستخدام اليومي. يرجى المحاولة غدًا." }), { status: 200 }); } ``` 2. **إشعار الخصوصية** (أضف في واجهة الدردشة): ```html <div class="px-4 py-2 text-xs text-gray-400 bg-gray-900 border-t border-gray-800"> <i class="fas fa-shield-alt mr-1"></i> المحادثات تُخزن محلياً فقط. قد تُرسل الاستفسارات لشركة OpenAI لمعالجتها. </div> ``` 3. **أيقونات إضافية جديدة** (مثال من deepsite): ```html <!-- أضف في الهيدر --> <i class="fas fa-magic text-purple-400"></i> <!-- للإبداعات --> <i class="fas fa-cloud-upload-alt text-blue-400"></i> <!-- للرفع --> <i class="fas fa-microphone text-green-400"></i> <!-- للصوت --> ``` ### ميزات إضافية مقترحة: 1. **التحويل الصوتي**: ```javascript // أضف في الواجهة <button @click="startVoiceInput" class="p-2 text-gray-500 hover:text-accent"> <i class="fas fa-microphone"></i> </button> // أضف في حالة Alpine.js startVoiceInput() { const recognition = new webkitSpeechRecognition(); recognition.lang = 'ar-SA'; recognition.onresult = (e) => { this.draft = e.results[0][0].transcript; }; recognition.start(); } ``` 2. **تحميل الملفات**: ```html <!-- أضف بجانب حقل الإدخال --> <label class="cursor-pointer p-2 text-gray-500 hover:text-accent"> <i class="fas fa-paperclip"></i> <input type="file" class="hidden"
@change
="handleFileUpload"> </label> ``` الرسوم التعبيرية ظاهرة فقط عند تفعيل الخيار (زر الوجه 😊)، بينما الأيقونات هي الأساس لكل عنصر ووظيفة. اجعل الاساسي ايقونات و يكون هناك جميع ما يخدم المتاجر و انشئ برومت يتضمن هذه التحسينات التي اجريت ل https://huggingface.co/spaces/enzostvs/deepsite - Initial Deployment
818ff47
verified
<html lang="en" x-data="dashboardState()" x-bind:class="{ 'dark': darkMode }"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Store AI Hub – Control Center</title> | |
<script src="https://cdn.tailwindcss.com"></script> | |
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/cdn.min.js" defer></script> | |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
<style> | |
.glass { background: rgba(255,255,255,.08); backdrop-filter: blur(20px) saturate(180%); -webkit-backdrop-filter: blur(20px) saturate(180%); border: 1px solid rgba(255,255,255,.12); } | |
.glass-dark { background: rgba(17,24,39,.65); backdrop-filter: blur(20px) saturate(180%); -webkit-backdrop-filter: blur(20px) saturate(180%); border: 1px solid rgba(255,255,255,.1); } | |
.glow { box-shadow: 0 0 20px rgba(0,255,255,.4), 0 0 6px rgba(0,255,255,.6); } | |
.ring-glow { box-shadow: 0 0 0 3px rgba(0,255,255,.4); } | |
[x-cloak] { display: none ; } | |
::-webkit-scrollbar { width: 6px; height: 6px; } | |
::-webkit-scrollbar-thumb { background-color: rgba(156,163,175,.4); border-radius: 3px; } | |
::-webkit-scrollbar-track { background-color: transparent; } | |
@media (max-width: 768px) { | |
.sidebar { transform: translateX(-100%); transition: transform .3s ease; } | |
.sidebar.open { transform: translateX(0); } | |
} | |
</style> | |
</head> | |
<body class="min-h-screen bg-gray-100 dark:bg-gray-900 text-gray-800 dark:text-gray-200 flex"> | |
<!-- Mobile Menu Button --> | |
<button @click="mobileMenuOpen = !mobileMenuOpen" class="md:hidden fixed top-4 left-4 z-50 p-2 rounded-full bg-white dark:bg-gray-800 shadow-lg"> | |
<i class="fas fa-bars"></i> | |
</button> | |
<!-- Sidebar --> | |
<aside class="sidebar w-20 xl:w-56 glass-dark text-gray-200 flex flex-col fixed h-full z-40"> | |
<div> | |
<div class="flex items-center justify-center xl:justify-start p-4 border-b border-gray-700/50"> | |
<i class="fa-solid fa-robot text-cyan-400 text-2xl xl:mr-3"></i> | |
<span class="hidden xl:block text-lg font-bold bg-clip-text text-transparent bg-gradient-to-r from-cyan-400 to-purple-400">AI Commerce</span> | |
</div> | |
<nav class="flex-1 px-2 space-y-2"> | |
<template x-for="item in navItems" :key="item.key"> | |
<button @click="currentTab=item.key; mobileMenuOpen=false" | |
:title="item.label" | |
class="relative w-full flex items-center justify-center xl:justify-start px-2 py-3 rounded-lg hover:bg-gray-700/50 transition-colors" | |
:class="currentTab===item.key ? 'bg-cyan-500/20 text-cyan-300 ring-glow' : 'text-gray-300 hover:text-white'"> | |
<i :class="item.icon" class="text-xl xl:mr-3"></i> | |
<span class="hidden xl:block text-sm font-medium" x-text="item.label"></span> | |
<span class="absolute left-full ml-2 px-2 py-1 bg-gray-800 text-xs rounded opacity-0 group-hover:opacity-100 xl:hidden whitespace-nowrap" x-text="item.label"></span> | |
</button> | |
</template> | |
</nav> | |
</div> | |
<div class="p-4 border-t border-gray-200 dark:border-gray-700"> | |
<div class="flex items-center space-x-3"> | |
<img src="https://randomuser.me/api/portraits/women/44.jpg" alt="User" class="w-8 h-8 rounded-full"> | |
<div class="flex-1 min-w-0"> | |
<p class="text-sm font-medium">Sarah Johnson</p> | |
<p class="text-xs text-gray-500">Admin</p> | |
</div> | |
</div> | |
<div class="flex items-center justify-between mt-3"> | |
<span class="text-sm">Dark</span> | |
<button @click="toggleDark()" class="relative inline-flex h-5 w-9 items-center rounded-full transition-colors" | |
:class="darkMode ? 'bg-cyan-500' : 'bg-gray-400'"> | |
<span class="inline-block h-3.5 w-3.5 transform rounded-full bg-white transition-transform" :class="darkMode ? 'translate-x-5' : 'translate-x-1'"></span> | |
</button> | |
</div> | |
</div> | |
</aside> | |
<!-- Main --> | |
<main class="flex-1 ml-0 md:ml-20 xl:ml-56 transition-all duration-300"> | |
<!-- Top Bar --> | |
<header class="bg-white/20 dark:bg-gray-800/20 glass sticky top-0 z-10"> | |
<div class="px-4 py-3 flex items-center justify-between"> | |
<div class="flex items-center space-x-3"> | |
<h1 class="text-xl font-bold" x-text="getCurrentTabTitle()"></h1> | |
<div class="hidden md:flex items-center space-x-1 text-xs text-gray-500"> | |
<span>Dashboard</span><i class="fas fa-chevron-right text-xs"></i><span x-text="getCurrentTabTitle()" class="text-cyan-400"></span> | |
</div> | |
</div> | |
<div class="flex items-center space-x-3"> | |
<div class="relative hidden md:block"> | |
<input type="text" placeholder="Search..." class="pl-9 pr-3 py-1.5 border border-gray-300 dark:border-gray-600 rounded-lg bg-gray-50 dark:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-cyan-500 w-52"> | |
<i class="fas fa-search absolute left-3 top-2 text-gray-400"></i> | |
</div> | |
<button class="relative p-1.5 rounded-full hover:bg-gray-200 dark:hover:bg-gray-700"> | |
<i class="fas fa-bell text-gray-600 dark:text-gray-300"></i> | |
<span class="absolute -top-0.5 -right-0.5 h-2 w-2 rounded-full bg-red-500"></span> | |
</button> | |
<button class="p-1.5 rounded-full hover:bg-gray-200 dark:hover:bg-gray-700"> | |
<i class="fas fa-plus text-gray-600 dark:text-gray-300"></i> | |
</button> | |
</div> | |
</div> | |
</header> | |
<!-- Content --> | |
<div class="p-4 md:p-6"> | |
<!-- Dashboard (empty) --> | |
<section x-show="currentTab==='dashboard'" x-cloak> | |
<div class="glass rounded-2xl p-6 mb-6 flex flex-col md:flex-row items-center justify-between"> | |
<div> | |
<h2 class="text-2xl font-bold mb-1">Welcome back, Sarah 👋</h2> | |
<p class="text-gray-400 mb-4">Here’s what’s happening with your store today.</p> | |
<button class="px-4 py-2 bg-cyan-500 text-gray-900 rounded-lg font-semibold hover:bg-cyan-400 transition"> | |
<i class="fas fa-rocket mr-2"></i>Start New Task | |
</button> | |
</div> | |
<div class="hidden md:block"> | |
<div class="w-24 h-24 relative"> | |
<svg class="w-full h-full spin-slow" viewBox="0 0 36 36"> | |
<path stroke="#059669" stroke-width="3" fill="none" stroke-dasharray="75,100" d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831"></path> | |
<path stroke="#4b5563" stroke-width="3" fill="none" stroke-dasharray="25,100" d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831"></path> | |
</svg> | |
<div class="absolute inset-0 flex items-center justify-center text-sm font-bold">95%</div> | |
</div> | |
<p class="text-center text-xs text-gray-400 mt-1">AI Health</p> | |
</div> | |
</div> | |
<!-- KPIs --> | |
<div class="grid grid-cols-2 md:grid-cols-4 gap-4 mb-6"> | |
<template x-for="stat in quickStats" :key="stat.label"> | |
<div class="glass rounded-xl p-4 flex items-center space-x-3"> | |
<div :class="stat.color" class="w-10 h-10 rounded-lg flex items-center justify-center text-lg"> | |
<i :class="stat.icon"></i> | |
</div> | |
<div> | |
<p class="text-xs text-gray-400" x-text="stat.label"></p> | |
<p class="text-lg font-bold" x-text="stat.value"></p> | |
<p :class="stat.trend > 0 ? 'text-green-400' : 'text-red-400'" class="text-xs flex items-center"> | |
<i :class="stat.trend > 0 ? 'fas fa-arrow-up' : 'fas fa-arrow-down'" class="mr-1"></i> | |
<span x-text="Math.abs(stat.trend)+'%'"></span> | |
</p> | |
</div> | |
</div> | |
</template> | |
</div> | |
<!-- Widgets Row --> | |
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6"> | |
<div class="glass rounded-xl p-4 lg:col-span-2"> | |
<h3 class="font-semibold mb-3">Revenue</h3> | |
<div class="bg-gray-700/30 rounded-lg h-48 flex items-center justify-center"> | |
<i class="fas fa-chart-line text-4xl text-cyan-400"></i> | |
</div> | |
</div> | |
<div class="glass rounded-xl p-4"> | |
<h3 class="font-semibold mb-3">Top Products</h3> | |
<ul class="space-y-3"> | |
<li class="flex items-center"> | |
<div class="w-8 h-8 bg-gray-700 rounded mr-2"></div> | |
<div> | |
<p class="text-sm">Wireless Headphones</p> | |
<p class="text-xs text-gray-400">$1,245 / 45 sold</p> | |
</div> | |
</li> | |
<li class="flex items-center"> | |
<div class="w-8 h-8 bg-gray-700 rounded mr-2"></div> | |
<div> | |
<p class="text-sm">Smart Watch</p> | |
<p class="text-xs text-gray-400">$980 / 32 sold</p> | |
</div> | |
</li> | |
</ul> | |
</div> | |
</div> | |
<!-- Empty helper --> | |
<div x-show="showEmptyHelper" x-transition class="fixed bottom-6 right-6 glass-dark rounded-xl p-4 max-w-xs"> | |
<p class="text-sm">New here? <button class="text-cyan-400 underline">Upload your first file</button> to get AI insights in seconds.</p> | |
</div> | |
</section> | |
<!-- Orders --> | |
<section x-show="currentTab==='orders'" x-cloak> | |
<div class="glass rounded-xl overflow-hidden"> | |
<div class="p-4 border-b border-gray-700/50 flex items-center justify-between"> | |
<h3 class="font-semibold">Orders</h3> | |
<button class="px-3 py-1 bg-cyan-500 text-gray-900 rounded text-sm font-semibold"><i class="fas fa-plus mr-1"></i>New</button> | |
</div> | |
<div class="overflow-x-auto"> | |
<table class="w-full text-sm"> | |
<thead class="bg-gray-800/50"> | |
<tr> | |
<th class="px-4 py-2 text-left">ID</th> | |
<th class="px-4 py-2 text-left">Customer</th> | |
<th class="px-4 py-2 text-left">Date</th> | |
<th class="px-4 py-2 text-left">Amount</th> | |
<th class="px-4 py-2 text-left">Status</th> | |
<th class="px-4 py-2 text-left"></th> | |
</tr> | |
</thead> | |
<tbody> | |
<tr class="border-t border-gray-700/50"> | |
<td class="px-4 py-2">#1001</td> | |
<td class="px-4 py-2">John Smith</td> | |
<td class="px-4 py-2">05 Jun 2024</td> | |
<td class="px-4 py-2">$245.00</td> | |
<td class="px-4 py-2"><span class="px-2 py-0.5 rounded-full text-xs bg-green-500/20 text-green-300">Completed</span></td> | |
<td class="px-4 py-2"><button class="text-cyan-400 text-xs">View</button></td> | |
</tr> | |
<tr class="border-t border-gray-700/50"> | |
<td class="px-4 py-2">#1002</td> | |
<td class="px-4 py-2">Sarah Johnson</td> | |
<td class="px-4 py-2">05 Jun 2024</td> | |
<td class="px-4 py-2">$189.50</td> | |
<td class="px-4 py-2"><span class="px-2 py-0.5 rounded-full text-xs bg-yellow-500/20 text-yellow-300">Processing</span></td> | |
<td class="px-4 py-2"><button class="text-cyan-400 text-xs">View</button></td> | |
</tr> | |
</tbody> | |
</table> | |
</div> | |
</div> | |
</section> | |
<!-- Products --> | |
<section x-show="currentTab==='products'" x-cloak> | |
<div class="glass rounded-xl overflow-hidden"> | |
<div class="p-4 border-b border-gray-700/50 flex items-center justify-between"> | |
<h3 class="font-semibold">Products</h3> | |
<button class="px-3 py-1 bg-cyan-500 text-gray-900 rounded text-sm font-semibold"><i class="fas fa-plus mr-1"></i>Add</button> | |
</div> | |
<div class="overflow-x-auto"> | |
<table class="w-full text-sm"> | |
<thead class="bg-gray-800/50"> | |
<tr> | |
<th class="px-4 py-2 text-left">Product</th> | |
<th class="px-4 py-2 text-left">SKU</th> | |
<th class="px-4 py-2 text-left">Stock</th> | |
<th class="px-4 py-2 text-left">Price</th> | |
<th class="px-4 py-2 text-left">Status</th> | |
<th class="px-4 py-2 text-left"></th> | |
</tr> | |
</thead> | |
<tbody> | |
<tr class="border-t border-gray-700/50"> | |
<td class="px-4 py-2 flex items-center"><img src="https://via.placeholder.com/32" class="rounded mr-2"><span>Wireless Headphones</span></td> | |
<td class="px-4 py-2">SKU-001</td> | |
<td class="px-4 py-2">45</td> | |
<td class="px-4 py-2">$89.99</td> | |
<td class="px-4 py-2"><span class="px-2 py-0.5 rounded-full text-xs bg-green-500/20 text-green-300">Active</span></td> | |
<td class="px-4 py-2"><button class="text-cyan-400 text-xs">Edit</button></td> | |
</tr> | |
<tr class="border-t border-gray-700/50"> | |
<td class="px-4 py-2 flex items-center"><img src="https://via.placeholder.com/32" class="rounded mr-2"><span>Smart Watch</span></td> | |
<td class="px-4 py-2">SKU-002</td> | |
<td class="px-4 py-2">12</td> | |
<td class="px-4 py-2">$199.99</td> | |
<td class="px-4 py-2"><span class="px-2 py-0.5 rounded-full text-xs bg-green-500/20 text-green-300">Active</span></td> | |
<td class="px-4 py-2"><button class="text-cyan-400 text-xs">Edit</button></td> | |
</tr> | |
</tbody> | |
</table> | |
</div> | |
</div> | |
</section> | |
<!-- Customers --> | |
<section x-show="currentTab==='customers'" x-cloak> | |
<div class="glass rounded-xl overflow-hidden"> | |
<div class="p-4 border-b border-gray-700/50 flex items-center justify-between"> | |
<h3 class="font-semibold">Customers</h3> | |
<button class="px-3 py-1 bg-cyan-500 text-gray-900 rounded text-sm font-semibold"><i class="fas fa-plus mr-1"></i>Add</button> | |
</div> | |
<div class="overflow-x-auto"> | |
<table class="w-full text-sm"> | |
<thead class="bg-gray-800/50"> | |
<tr> | |
<th class="px-4 py-2 text-left">Customer</th> | |
<th class="px-4 py-2 text-left">Email</th> | |
<th class="px-4 py-2 text-left">Orders</th> | |
<th class="px-4 py-2 text-left">Spent</th> | |
<th class="px-4 py-2 text-left"></th> | |
</tr> | |
</thead> | |
<tbody> | |
<tr class="border-t border-gray-700/50"> | |
<td class="px-4 py-2 flex items-center"><img src="https://randomuser.me/api/portraits/men/32.jpg" class="w-8 h-8 rounded-full mr-2"><span>John Smith</span></td> | |
<td class="px-4 py-2">[email protected]</td> | |
<td class="px-4 py-2">5</td> | |
<td class="px-4 py-2">$1,245</td> | |
<td class="px-4 py-2"><button class="text-cyan-400 text-xs">View</button></td> | |
</tr> | |
<tr class="border-t border-gray-700/50"> | |
<td class="px-4 py-2 flex items-center"><img src="https://randomuser.me/api/portraits/women/44.jpg" class="w-8 h-8 rounded-full mr-2"><span>Sarah Johnson</span></td> | |
<td class="px-4 py-2">[email protected]</td> | |
<td class="px-4 py-2">3</td> | |
<td class="px-4 py-2">$756</td> | |
<td class="px-4 py-2"><button class="text-cyan-400 text-xs">View</button></td> | |
</tr> | |
</tbody> | |
</table> | |
</div> | |
</div> | |
</section> | |
<!-- Shipping --> | |
<section x-show="currentTab==='shipping'" x-cloak> | |
<div class="glass rounded-xl p-6 text-center"> | |
<i class="fas fa-truck text-4xl text-cyan-400 mb-3"></i> | |
<h3 class="text-lg font-semibold mb-2">Shipping</h3> | |
<p class="text-gray-400 mb-4">Connect carriers, print labels & track packages in one click.</p> | |
<button class="px-4 py-2 bg-cyan-500 text-gray-900 rounded-lg font-semibold">Get Started</button> | |
</div> | |
</section> | |
<!-- AI Center --> | |
<section x-show="currentTab==='ai'" x-cloak> | |
<div class="glass rounded-xl p-6 text-center"> | |
<i class="fas fa-robot text-4xl text-cyan-400 mb-3"></i> | |
<h3 class="text-lg font-semibold mb-2">AI Center</h3> | |
<p class="text-gray-400 mb-4">Chat with AI, auto-generate descriptions, and get smart recommendations.</p> | |
<button class="px-4 py-2 bg-cyan-500 text-gray-900 rounded-lg font-semibold">Open Chat</button> | |
</div> | |
</section> | |
<!-- Analytics --> | |
<section x-show="currentTab==='analytics'" x-cloak> | |
<div class="glass rounded-xl p-6 text-center"> | |
<i class="fas fa-chart-line text-4xl text-cyan-400 mb-3"></i> | |
<h3 class="text-lg font-semibold mb-2">Analytics</h3> | |
<p class="text-gray-400 mb-4">Deep insights on sales, products, and customer behavior.</p> | |
<button class="px-4 py-2 bg-cyan-500 text-gray-900 rounded-lg font-semibold">View Reports</button> | |
</div> | |
</section> | |
<!-- Social --> | |
<section x-show="currentTab==='social'" x-cloak> | |
<div class="glass rounded-xl p-6 text-center"> | |
<i class="fas fa-share-alt text-4xl text-cyan-400 mb-3"></i> | |
<h3 class="text-lg font-semibold mb-2">Social</h3> | |
<p class="text-gray-400 mb-4">Schedule posts, manage ads, and track performance across platforms.</p> | |
<button class="px-4 py-2 bg-cyan-500 text-gray-900 rounded-lg font-semibold">Connect Account</button> | |
</div> | |
</section> | |
</div> | |
</main> | |
<!-- Floating Action Button --> | |
<button class="fixed bottom-6 right-20 md:right-6 w-14 h-14 bg-cyan-500 rounded-full shadow-lg flex items-center justify-center text-gray-900 text-2xl font-bold hover:bg-cyan-400 transition z-50"> | |
+ | |
</button> | |
<!-- Upgrade CTA Popup --> | |
<div x-show="showUpgrade" x-transition class="fixed inset-0 bg-black/50 flex items-center justify-center z-50"> | |
<div class="glass-dark rounded-2xl p-6 max-w-sm text-center"> | |
<i class="fas fa-rocket text-3xl text-cyan-400 mb-3"></i> | |
<h3 class="font-bold text-lg mb-2">Level-up your store</h3> | |
<p class="text-sm text-gray-300 mb-4">Unlock AI insights, automation rules & 24/7 live support.</p> | |
<button class="w-full px-4 py-2 bg-cyan-500 text-gray-900 rounded-lg font-semibold hover:bg-cyan-400">Upgrade Now</button> | |
<button @click="showUpgrade=false" class="mt-2 text-xs text-gray-400 hover:text-white">Maybe later</button> | |
</div> | |
</div> | |
<!-- AI Assistant Bubble --> | |
<button id="aiBubble" | |
@click="openChat = true; $nextTick(() => scrollDown())" | |
class="fixed bottom-6 right-6 w-14 h-14 rounded-full bg-accent shadow-lg | |
flex items-center justify-center hover:scale-110 transition-transform"> | |
<i class="fas fa-robot text-white text-2xl"></i> | |
</button> | |
<!-- Chat Widget --> | |
<div x-show="showChat" x-transition class="fixed bottom-20 right-6 w-80 glass-dark rounded-xl shadow-2xl z-50"> | |
<div class="flex items-center justify-between p-3 border-b border-gray-700/50"> | |
<span class="font-semibold">Live Support</span> | |
<button @click="showChat=false"><i class="fas fa-times text-sm"></i></button> | |
</div> | |
<div class="p-3 space-y-2 text-sm"> | |
<div class="bg-gray-700/50 rounded-lg p-2">Hi! Need help? Ask me anything.</div> | |
<div class="bg-cyan-500/20 rounded-lg p-2 ml-8">Thanks, I’m good for now.</div> | |
</div> | |
<div class="p-3 border-t border-gray-700/50"> | |
<input type="text" placeholder="Type a message..." class="w-full bg-gray-800/50 rounded px-2 py-1 text-sm"> | |
</div> | |
</div> | |
<script> | |
function dashboardState() { | |
return { | |
darkMode: false, | |
currentTab: 'dashboard', | |
mobileMenuOpen: false, | |
showEmptyHelper: true, | |
showUpgrade: false, | |
showChat: false, | |
quickStats: [ | |
{ label: 'Sales', value: '$0', trend: 0, icon: 'fas fa-dollar-sign', color: 'bg-green-500/20 text-green-400' }, | |
{ label: 'Orders', value: '0', trend: 0, icon: 'fas fa-shopping-cart', color: 'bg-blue-500/20 text-blue-400' }, | |
{ label: 'Conversion', value: '0%', trend: 0, icon: 'fas fa-percent', color: 'bg-yellow-500/20 text-yellow-400' }, | |
{ label: 'Health', value: '100', trend: 0, icon: 'fas fa-heartbeat', color: 'bg-red-500/20 text-red-400' } | |
], | |
navItems: [ | |
{ key: 'dashboard', label: 'Home', icon: 'fas fa-home' }, | |
{ key: 'products', label: 'Products', icon: 'fas fa-boxes-stacked' }, | |
{ key: 'orders', label: 'Orders', icon: 'fas fa-shopping-cart' }, | |
{ key: 'integrations', label: 'Integrations', icon: 'fas fa-plug' }, | |
{ key: 'social', label: 'Social', icon: 'fas fa-share-alt' }, | |
{ key: 'assistant', label: 'AI Assistant', icon: 'fas fa-robot' }, | |
{ key: 'automations', label: 'Automations', icon: 'fas fa-cogs' }, | |
{ key: 'shipping', label: 'Shipping', icon: 'fas fa-truck' }, | |
{ key: 'payments', label: 'Payments', icon: 'fas fa-credit-card' }, | |
{ key: 'trends', label: 'Trends', icon: 'fas fa-chart-line' }, | |
{ key: 'settings', label: 'Settings', icon: 'fas fa-cog' }, | |
{ key: 'feedback', label: 'Feedback', icon: 'fas fa-comment-dots' } | |
], | |
getCurrentTabTitle() { | |
const found = this.navItems.find(i => i.key === this.currentTab); | |
return found ? found.label : 'Dashboard'; | |
}, | |
toggleDark() { | |
this.darkMode = !this.darkMode; | |
}, | |
/* Chat System */ | |
openChat: false, | |
draft: '', | |
messages: JSON.parse(localStorage.getItem('chat') || '[]'), | |
loading: false, | |
emojiMode: false, | |
async sendMessage() { | |
const text = this.draft.trim(); | |
if (!text) return; | |
// Add user message | |
this.messages.push({ | |
id: Date.now(), | |
role: 'user', | |
content: text | |
}); | |
this.draft = ''; | |
this.loading = true; | |
this.persistChat(); | |
this.scrollDown(); | |
try { | |
const res = await fetch('/api/chat', { | |
method: 'POST', | |
headers: { 'Content-Type': 'application/json' }, | |
body: JSON.stringify({ | |
messages: this.messages, | |
emoji_mode: this.emojiMode | |
}) | |
}); | |
const reader = res.body.getReader(); | |
let assistantMsg = { | |
id: Date.now() + 1, | |
role: 'assistant', | |
content: '', | |
emojis: this.emojiMode ? [] : null | |
}; | |
this.messages.push(assistantMsg); | |
let buffer = ''; | |
while (true) { | |
const { value, done } = await reader.read(); | |
if (done) break; | |
buffer += new TextDecoder().decode(value); | |
const parts = buffer.split('\n\n'); | |
buffer = parts.pop() || ''; | |
for (const part of parts) { | |
try { | |
const data = JSON.parse(part); | |
assistantMsg.content += data.content || ''; | |
if (this.emojiMode && data.emojis) { | |
assistantMsg.emojis = [...(assistantMsg.emojis || []), ...data.emojis]; | |
} | |
} catch (e) { /* ignore parse errors */ } | |
} | |
this.persistChat(); | |
this.$nextTick(() => this.scrollDown()); | |
} | |
} catch (error) { | |
console.error('Chat error:', error); | |
assistantMsg.content = '⚠️ حدث خطأ في الاتصال بالمساعد. يرجى المحاولة لاحقًا.'; | |
} | |
this.loading = false; | |
this.persistChat(); | |
}, | |
scrollDown() { | |
this.$nextTick(() => { | |
const el = document.getElementById('chatScroll'); | |
if (el) el.scrollTop = el.scrollHeight + 100; | |
}); | |
}, | |
persistChat() { | |
localStorage.setItem('chat', JSON.stringify(this.messages)); | |
}, | |
init() { | |
setTimeout(() => this.showUpgrade = true, 30000); | |
} | |
}; | |
} | |
</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=fsalmansour/secont" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
</html> |