humanvprojectceo commited on
Commit
d87a207
·
verified ·
1 Parent(s): 6acba78

Update cafe.html

Browse files
Files changed (1) hide show
  1. cafe.html +155 -147
cafe.html CHANGED
@@ -2,13 +2,11 @@
2
  <html lang="fa" dir="rtl">
3
  <head>
4
  <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Cafe AI - پنل مدیریت</title>
7
- <!-- بارگذاری قلم فارسی Vazirmatn -->
8
  <link rel="preconnect" href="https://fonts.googleapis.com">
9
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
10
- <link href="https://fonts.googleapis.com/css2?family=Vazirmatn:wght@300;400;700&display=swap" rel="stylesheet">
11
- <!-- بارگذاری Tailwind CSS از طریق CDN -->
12
  <script src="https://cdn.tailwindcss.com"></script>
13
  <script>
14
  tailwind.config = {
@@ -18,11 +16,16 @@
18
  sans: ['Vazirmatn', 'sans-serif'],
19
  },
20
  colors: {
21
- cafeDark: '#09090b', /* پس‌زمینه تیره تیره */
22
- cafeCard: '#18181b', /* خاکستری تیره برای کارت‌ها */
23
- cafeBorder: '#27272a', /* خطوط راهنما */
24
- cafeGold: '#d4af37', /* طلایی سنتی کافه */
25
- cafeGoldHover: '#f3cd5c', /* طلایی روشن */
 
 
 
 
 
26
  }
27
  }
28
  }
@@ -32,67 +35,75 @@
32
  body {
33
  background-color: #09090b;
34
  color: #f4f4f5;
 
35
  }
36
- /* تنظیمات اسکرول‌بار اختصاصی و باریک */
37
  ::-webkit-scrollbar {
38
  width: 4px;
39
  }
40
  ::-webkit-scrollbar-track {
41
- background: #18181b;
42
  }
43
  ::-webkit-scrollbar-thumb {
44
- background: #3f3f46;
45
  border-radius: 2px;
46
  }
47
  </style>
48
  </head>
49
- <body class="min-h-screen flex flex-col font-sans selection:bg-amber-500 selection:text-black overflow-x-hidden">
 
 
 
 
 
 
50
 
51
- <!-- بخش سربرگ (Header) -->
52
- <header class="border-b border-cafeBorder bg-cafeCard/70 backdrop-blur sticky top-0 z-50 px-4 py-3 md:px-8">
53
  <div class="max-w-7xl mx-auto flex items-center justify-between">
54
  <div class="flex items-center gap-3">
55
- <!-- لوگوی وکتور فنجان قهوه هوشمند -->
56
- <svg class="w-8 h-8 text-cafeGold" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
57
- <path d="M17 8h1a4 4 0 1 1 0 8h-1" />
58
- <path d="M3 8h14v9a4 4 0 0 1-4 4H7a4 4 0 0 1-4-4Z" />
59
- <line x1="6" y1="2" x2="6" y2="4" />
60
- <line x1="10" y1="2" x2="10" y2="4" />
61
- <line x1="14" y1="2" x2="14" y2="4" />
62
- </svg>
 
63
  <div>
64
- <h1 class="text-base font-bold text-white flex items-center gap-2">
65
- پنل پیشرفته <span class="text-cafeGold">Cafe AI</span>
66
  </h1>
67
- <p class="text-[9px] text-zinc-500">نظارت بر سفارشات و مدیریت خودکار منوی فعال</p>
68
  </div>
69
  </div>
70
 
71
  <div class="flex items-center gap-3">
72
- <span class="inline-flex items-center gap-1.5 px-2.5 py-1 rounded-lg text-[10px] font-medium bg-emerald-500/10 text-emerald-400 border border-emerald-500/20">
73
  <span class="w-1.5 h-1.5 rounded-full bg-emerald-400 animate-pulse"></span>
74
- اتصال فعال با سرور
75
  </span>
76
  </div>
77
  </div>
78
  </header>
79
 
80
- <!-- چیدمان اصلی پنل مدیریت -->
81
- <main class="flex-1 max-w-7xl w-full mx-auto p-4 md:p-6 lg:p-8 grid grid-cols-1 lg:grid-cols-12 gap-6">
82
 
83
- <!-- ستون سمت راست: بخش سفارشات جاری و بارگذاری منوی فیزیکی (۷ از ۱۲) -->
84
  <section class="lg:col-span-7 flex flex-col gap-6">
85
 
86
- <!-- بخش سفارشات جاری ثبت‌شده توسط مشتریان -->
87
- <div class="bg-cafeCard border border-cafeBorder rounded-2xl p-5 shadow-xl">
88
- <div class="flex items-center justify-between mb-4 border-b border-cafeBorder pb-3">
89
- <h2 class="text-sm font-bold text-white flex items-center gap-2">
90
- <svg class="w-5 h-5 text-cafeGold" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
91
- <path stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-3 7h3m-3 4h3m-6-4h.01M9 16h.01" />
92
  </svg>
93
- سفارشات جدید و فعال آشپزخانه
94
  </h2>
95
- <button onclick="fetchActiveOrders()" class="text-[10px] text-zinc-400 hover:text-cafeGold flex items-center gap-1 transition-all">
96
  <svg class="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
97
  <path stroke-linecap="round" stroke-linejoin="round" d="M4 4v5h.582m15.356 2A8.001 8.001 0 1121.21 15H15" />
98
  </svg>
@@ -100,7 +111,7 @@
100
  </button>
101
  </div>
102
 
103
- <!-- کانتینر سفارشات فعال -->
104
  <div id="ordersContainer" class="space-y-4 max-h-[350px] overflow-y-auto pr-1">
105
  <div class="text-center py-12 text-xs text-zinc-500">
106
  در حال بارگذاری لیست سفارشات جاری...
@@ -108,71 +119,68 @@
108
  </div>
109
  </div>
110
 
111
- <!-- بخش آپلود و استخراج خودکار منو -->
112
- <div class="bg-cafeCard border border-cafeBorder rounded-2xl p-5 shadow-xl space-y-4">
113
- <h2 class="text-sm font-bold text-white flex items-center gap-2 border-b border-cafeBorder pb-3">
114
- <svg class="w-5 h-5 text-cafeGold" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
115
  <path stroke-linecap="round" stroke-linejoin="round" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m4-4v12" />
116
  </svg>
117
- بارگذاری تصویر و استخراج منو
118
  </h2>
119
 
120
- <p class="text-[11px] text-zinc-400 leading-relaxed">
121
- فایل یا عکس منوی کافه خود را آپلود کنید. هوش مصنوعی نیلا اطلاعات آن را استخراج می‌کند و پس از تایید یا ویرایش شما، به عنوان منوی فعال کافه ذخیره شده و برای سفارش مشتریان اعمال می‌شود.
122
  </p>
123
 
124
- <!-- باکس رها کردن فایل یا کلیک جهت آپلود -->
125
- <div class="border-2 border-dashed border-cafeBorder hover:border-cafeGold/40 rounded-xl p-6 text-center cursor-pointer transition-all bg-cafeDark/20" onclick="document.getElementById('menuFileInput').click()">
126
  <input type="file" id="menuFileInput" class="hidden" accept="image/*,application/pdf" onchange="uploadMenuFile(event)">
127
  <div class="flex flex-col items-center gap-2.5">
128
- <svg class="w-8 h-8 text-zinc-600" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5">
129
  <path stroke-linecap="round" stroke-linejoin="round" d="M9 13h6m-3-3v6m-9 1V7a2 2 0 012-2h6l2 2h6a2 2 0 012 2v8a2 2 0 01-2 2H5a2 2 0 01-2-2z" />
130
  </svg>
131
- <span class="text-xs text-zinc-300">عکس یا سند منو را جهت استخراج انتخاب کنید</span>
132
- <span class="text-[9px] text-zinc-500">پشتیبانی از فرمت‌های تصویری و PDF متنی</span>
133
  </div>
134
  </div>
135
 
136
- <!-- افکت لودینگ حین تحلیل تصویر با مدل -->
137
- <div id="uploadLoader" class="hidden text-center py-6 bg-cafeDark/40 rounded-xl border border-cafeBorder">
138
- <div class="inline-block animate-spin rounded-full h-7 w-7 border-t-2 border-b-2 border-cafeGold mb-2"></div>
139
- <p class="text-[11px] text-cafeGold">نیلا در حال استخراج و ساختاردهی به منو است. لطفاً چند لحظه شکیبا باشید...</p>
140
  </div>
141
 
142
  <!-- جدول ویرایش اقلام استخراج شده -->
143
- <div id="menuEditorContainer" class="hidden space-y-4 border-t border-cafeBorder pt-4 transition-all">
144
- <h3 class="text-xs font-bold text-amber-400 flex items-center gap-1.5">
145
- <svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
146
  <path stroke-linecap="round" stroke-linejoin="round" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z" />
147
  </svg>
148
- بازبینی و ویرایش اطلاعات منو پیش از انتشار نهایی
149
  </h3>
150
 
151
- <div class="overflow-x-auto max-h-[250px] border border-cafeBorder rounded-xl">
152
- <table class="min-w-full divide-y divide-cafeBorder bg-cafeDark/30 text-[11px]">
153
- <thead class="bg-cafeCard">
154
  <tr>
155
- <th class="px-3 py-2 text-right font-medium text-zinc-400">نام محصول</th>
156
- <th class="px-3 py-2 text-right font-medium text-zinc-400">توضیحات و ترکیبات</th>
157
- <th class="px-3 py-2 text-right font-medium text-zinc-400 w-24">قیمت (تومان)</th>
158
- <th class="px-3 py-2 text-center font-medium text-zinc-400 w-16">حذف</th>
159
  </tr>
160
  </thead>
161
- <tbody id="menuEditorTableBody" class="divide-y divide-cafeBorder">
162
- <!-- اقلام استخراج شده به صورت سطرهای این جدول رندر می‌شوند -->
163
  </tbody>
164
  </table>
165
  </div>
166
 
167
  <div class="flex justify-end gap-2">
168
- <button onclick="addEmptyMenuRow()" class="px-3 py-1.5 border border-cafeBorder hover:border-zinc-500 rounded-lg text-[10px] text-zinc-300 transition-all">
169
  افزودن محصول جدید
170
  </button>
171
- <button onclick="saveAndPublishMenu()" class="px-4 py-1.5 bg-emerald-600 hover:bg-emerald-500 rounded-lg text-[11px] font-bold text-white transition-all flex items-center gap-1.5">
172
- <svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
173
- <path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7" />
174
- </svg>
175
- تایید نهایی و انتشار منوی زنده
176
  </button>
177
  </div>
178
  </div>
@@ -180,59 +188,59 @@
180
  </div>
181
  </section>
182
 
183
- <!-- ستون سمت چپ: سیستم چت هوشمند ادمین با نیلا جهت مدیریت موجودی (۵ از ۱۲) -->
184
- <section class="lg:col-span-5 flex flex-col bg-cafeCard border border-cafeBorder rounded-2xl shadow-xl h-[630px] overflow-hidden">
185
 
186
- <!-- سربرگ بخش چت -->
187
- <div class="px-5 py-4 border-b border-cafeBorder flex items-center justify-between bg-cafeDark/20">
188
  <div class="flex items-center gap-3">
189
- <div class="w-9 h-9 rounded-full bg-cafeGold/10 border border-cafeGold/30 flex items-center justify-center">
190
- <svg class="w-5 h-5 text-cafeGold" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
191
  <path d="M12 2a10 10 0 0 1 10 10c0 5.523-4.477 10-10 10S2 17.523 2 12A10 10 0 0 1 12 2z"/>
192
  <path d="M12 8v4l3 3"/>
193
  </svg>
194
  </div>
195
  <div>
196
- <h3 class="text-xs font-bold text-white">دستیار هوشمند ادمین (Nila)</h3>
197
- <p class="text-[9px] text-zinc-500">مدیریت لحظه‌ای موجودی و فرآیندهای منو</p>
198
  </div>
199
  </div>
200
  </div>
201
 
202
- <!-- بدنه نمایش تاریخچه چت ادمین -->
203
  <div id="chatMessages" class="flex-1 overflow-y-auto p-4 space-y-4">
204
  <div class="flex gap-2.5 max-w-[85%]">
205
- <div class="w-7 h-7 rounded-full bg-cafeGold/10 border border-cafeGold/30 flex items-center justify-center flex-shrink-0">
206
- <svg class="w-4 h-4 text-cafeGold" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
207
  <circle cx="12" cy="12" r="10"/>
208
  <path d="M12 8v4l3 3"/>
209
  </svg>
210
  </div>
211
- <div class="bg-cafeDark/50 border border-cafeBorder text-zinc-200 text-xs rounded-2xl rounded-tr-none px-3.5 py-2.5 leading-relaxed">
212
- سلام ادمین محترم! من نیلا هستم، دستیار مدیریت منو. شما می‌توانید از طریق مکالمه زنده، آیتم‌های منو را ناموجود یا موجود کنید؛ به طور مثال بنویسید: "لاته به اتمام رسید" یا "کروسان را موجود کن" تا تغییرات سریعاً در پایگاه داده مشتریان اعمال شود.
213
  </div>
214
  </div>
215
  </div>
216
 
217
- <!-- لودر وضعیت و دکمه توقف پردازش پاسخ مدل -->
218
- <div id="chatLoader" class="hidden px-4 py-2 flex items-center justify-between bg-cafeDark/30 text-[10px] text-zinc-400 border-t border-cafeBorder/50">
219
  <div class="flex items-center gap-2">
220
  <div class="flex space-x-1 space-x-reverse">
221
- <span class="w-1.5 h-1.5 bg-cafeGold rounded-full animate-bounce" style="animation-delay: 0.1s"></span>
222
- <span class="w-1.5 h-1.5 bg-cafeGold rounded-full animate-bounce" style="animation-delay: 0.2s"></span>
223
- <span class="w-1.5 h-1.5 bg-cafeGold rounded-full animate-bounce" style="animation-delay: 0.3s"></span>
224
  </div>
225
- <span>نیلا در حال پردازش دستور شما...</span>
226
  </div>
227
- <button onclick="stopAdminChat()" class="px-2.5 py-1 bg-rose-950/40 border border-rose-800/40 hover:bg-rose-900/60 rounded text-[9px] text-rose-400 font-bold transition-all">
228
- توقف فرآیند
229
  </button>
230
  </div>
231
 
232
- <!-- فیلد ارسال پیام و دستور جدید به نیلا -->
233
- <form id="chatForm" onsubmit="sendAdminMessage(event)" class="p-3 border-t border-cafeBorder bg-cafeDark/40 flex gap-2">
234
- <input type="text" id="chatInput" placeholder="دستور مورد نظر خود را بنویسید..." autocomplete="off" class="flex-1 bg-cafeCard border border-cafeBorder text-xs text-zinc-200 placeholder-zinc-500 rounded-lg px-3.5 py-2.5 focus:outline-none focus:border-cafeGold/50 transition-all">
235
- <button type="submit" id="sendBtn" class="bg-cafeGold hover:bg-cafeGoldHover text-zinc-950 font-bold px-4 py-2.5 rounded-lg text-xs transition-all flex items-center justify-center flex-shrink-0">
236
  <svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.5">
237
  <path stroke-linecap="round" stroke-linejoin="round" d="M14 5l7 7m0 0l-7 7m7-7H3" />
238
  </svg>
@@ -243,26 +251,26 @@
243
 
244
  </main>
245
 
246
- <!-- فوتر پنل مدیریت -->
247
- <footer class="border-t border-cafeBorder py-4 text-center text-[10px] text-zinc-600 bg-cafeDark/80">
248
  طراحی و توسعه توسط الگوریتم داده نسترن | کلیه حقوق محفوظ است © ۲۰۲۶
249
  </footer>
250
 
251
- <!-- بخش جاوا اسکریپت و پردازش کلاینت -->
252
  <script>
253
  let chatHistory = [
254
- { role: 'model', content: 'سلام ادمین محترم! من نیلا هستم، دستیار مدیریت منو. شما می‌توانید از طریق مکالمه زنده، آیتم‌های منو را ناموجود یا موجود کنید؛ به طور مثال بنویسید: "لاته به اتمام رسید" یا "کروسان را موجود کن" تا تغییرات سریعاً در پایگاه داده مشتریان اعمال شود.' }
255
  ];
256
  let abortController = null;
257
  let isGenerating = false;
258
 
259
  window.addEventListener('DOMContentLoaded', () => {
260
  fetchActiveOrders();
261
- // بروزرسانی خودکار لیست سفارشات هر ۱۰ ثانیه یکبار
262
  setInterval(fetchActiveOrders, 10000);
263
  });
264
 
265
- // --- مانیتورینگ سفارشات فعال آشپزخانه ---
266
 
267
  async function fetchActiveOrders() {
268
  const container = document.getElementById('ordersContainer');
@@ -273,11 +281,11 @@
273
  if (response.ok) {
274
  if (orders.length === 0) {
275
  container.innerHTML = `
276
- <div class="text-center py-16 text-zinc-500 border border-dashed border-cafeBorder rounded-xl bg-cafeDark/10">
277
  <svg class="w-9 h-9 text-zinc-600 mx-auto mb-2" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5">
278
  <path stroke-linecap="round" stroke-linejoin="round" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
279
  </svg>
280
- هیچ سفارش فعالی در آشپزخانه ثبت نشده است.
281
  </div>
282
  `;
283
  return;
@@ -288,9 +296,9 @@
288
  let itemsHtml = '';
289
  order.items.forEach(item => {
290
  itemsHtml += `
291
- <div class="flex items-center justify-between text-[11px] bg-cafeDark/50 px-2.5 py-1.5 rounded border border-cafeBorder/40">
292
  <span class="text-zinc-300 font-bold">${item.name}</span>
293
- <span class="text-cafeGold bg-cafeGold/10 px-2 py-0.5 rounded font-bold">تعداد: ${item.quantity}</span>
294
  </div>
295
  `;
296
  });
@@ -298,31 +306,31 @@
298
  const timeString = new Date(order.timestamp * 1000).toLocaleTimeString('fa-IR', { hour: '2-digit', minute: '2-digit' });
299
 
300
  const cardHtml = `
301
- <div class="border border-cafeBorder hover:border-amber-500/20 rounded-xl p-4 bg-cafeDark/30 transition-all flex flex-col md:flex-row justify-between items-start md:items-center gap-3">
302
  <div class="flex-1 space-y-2 w-full">
303
  <div class="flex items-center justify-between md:justify-start gap-3 w-full">
304
- <span class="text-xs font-bold text-white bg-cafeGold/10 border border-cafeGold/20 px-2.5 py-1 rounded-lg">میز شماره ${order.table}</span>
305
- <span class="text-[9px] text-zinc-500">زمان ثبت سفارش: ${timeString}</span>
306
  </div>
307
  <div class="grid grid-cols-1 sm:grid-cols-2 gap-1.5 mt-2">
308
  ${itemsHtml}
309
  </div>
310
  </div>
311
- <button onclick="completeOrder(${order.id})" class="w-full md:w-auto px-3.5 py-2 bg-zinc-800 hover:bg-emerald-700 text-zinc-200 hover:text-white rounded-lg text-[10px] font-bold transition-all flex items-center justify-center gap-1.5 border border-zinc-700 hover:border-emerald-600 flex-shrink-0 group">
312
  <svg class="w-3.5 h-3.5 text-zinc-400 group-hover:text-white transition-colors" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.5">
313
  <path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7" />
314
  </svg>
315
- آماده و تحویل داده شد
316
  </button>
317
  </div>
318
  `;
319
  container.insertAdjacentHTML('beforeend', cardHtml);
320
  });
321
  } else {
322
- container.innerHTML = `<div class="text-center py-6 text-rose-500 text-xs">خطا در دریافت اطلاعات سفارشات فعال.</div>`;
323
  }
324
  } catch (err) {
325
- container.innerHTML = `<div class="text-center py-6 text-rose-500 text-xs">خطای اتصال با سرور مرکزی: ${err.message}</div>`;
326
  }
327
  }
328
 
@@ -338,15 +346,15 @@
338
  if (response.ok && result.success) {
339
  fetchActiveOrders();
340
  } else {
341
- alert(result.error || "خطایی در عملیات تغییر وضعیت پیش آمد.");
342
  }
343
  } catch (err) {
344
- alert("بروز خطای غیر منتظره در شبکه: " + err.message);
345
  }
346
  }
347
 
348
 
349
- // --- گفتگو و مدیریت موجودی با نیلا ---
350
 
351
  async function sendAdminMessage(e) {
352
  e.preventDefault();
@@ -379,7 +387,7 @@
379
  isGenerating = false;
380
 
381
  if (response.ok && data.success) {
382
- // شبیه‌سازی انیمیشن تایپ حروف
383
  const botBubbleId = appendChatMessage('model', '');
384
  const botBubble = document.getElementById(botBubbleId);
385
  let i = 0;
@@ -387,10 +395,10 @@
387
 
388
  function typeText() {
389
  if (i < textResponse.length && !abortController.signal.aborted) {
390
- botBubble.innerText += textResponse.charAt(i);
391
  i++;
392
  document.getElementById('chatMessages').scrollTop = document.getElementById('chatMessages').scrollHeight;
393
- setTimeout(typeText, 8);
394
  } else {
395
  chatHistory.push({ role: 'model', content: textResponse });
396
  }
@@ -398,13 +406,13 @@
398
  typeText();
399
 
400
  } else {
401
- appendChatMessage('model', data.error || 'پاسخی از سرور دریافت نشد.');
402
  }
403
  } catch (err) {
404
  toggleChatLoading(false);
405
  isGenerating = false;
406
  if (err.name !== 'AbortError') {
407
- appendChatMessage('model', 'اختلال در ارتباط شبکه: ' + err.message);
408
  }
409
  }
410
  }
@@ -441,7 +449,7 @@
441
  if (role === 'user') {
442
  html = `
443
  <div class="flex justify-end gap-2.5 max-w-[85%] mr-auto">
444
- <div class="bg-amber-500/10 border border-amber-500/20 text-zinc-100 text-xs rounded-2xl rounded-tl-none px-3.5 py-2.5 leading-relaxed">
445
  ${content}
446
  </div>
447
  </div>
@@ -449,13 +457,13 @@
449
  } else {
450
  html = `
451
  <div class="flex gap-2.5 max-w-[85%]">
452
- <div class="w-7 h-7 rounded-full bg-cafeGold/10 border border-cafeGold/30 flex items-center justify-center flex-shrink-0">
453
- <svg class="w-4 h-4 text-cafeGold" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
454
  <circle cx="12" cy="12" r="10"/>
455
  <path d="M12 8v4l3 3"/>
456
  </svg>
457
  </div>
458
- <div id="${bubbleId}" class="bg-cafeDark/50 border border-cafeBorder text-zinc-200 text-xs rounded-2xl rounded-tr-none px-3.5 py-2.5 leading-relaxed font-sans">
459
  ${content}
460
  </div>
461
  </div>
@@ -468,7 +476,7 @@
468
  }
469
 
470
 
471
- // --- استخراج و ویرایش هوشمند منوی آپلود شده ---
472
 
473
  async function uploadMenuFile(e) {
474
  const file = e.target.files[0];
@@ -496,11 +504,11 @@
496
  renderMenuEditor(data.extracted_menu);
497
  editor.classList.remove('hidden');
498
  } else {
499
- alert(data.error || 'هوش مصنوعی قادر به استخراج اقلام تصویر ارسالی نبود.');
500
  }
501
  } catch (err) {
502
  loader.classList.add('hidden');
503
- alert('خطا در بارگذاری سند منو: ' + err.message);
504
  }
505
  }
506
 
@@ -510,18 +518,18 @@
510
 
511
  menuItems.forEach((item, index) => {
512
  const row = `
513
- <tr class="hover:bg-cafeCard/30 transition-colors">
514
  <td class="px-2 py-2">
515
- <input type="text" class="menu-name w-full bg-cafeCard border border-cafeBorder rounded px-2.5 py-1 text-zinc-200 focus:border-cafeGold/50 focus:outline-none" value="${item.name || ''}">
516
  </td>
517
  <td class="px-2 py-2">
518
- <input type="text" class="menu-desc w-full bg-cafeCard border border-cafeBorder rounded px-2.5 py-1 text-zinc-200 focus:border-cafeGold/50 focus:outline-none" value="${item.description || ''}">
519
  </td>
520
  <td class="px-2 py-2">
521
- <input type="text" class="menu-price w-full bg-cafeCard border border-cafeBorder rounded px-2.5 py-1 text-zinc-200 focus:border-cafeGold/50 focus:outline-none" value="${item.price || ''}">
522
  </td>
523
  <td class="px-2 py-2 text-center">
524
- <button onclick="removeMenuRow(this)" class="p-1 text-zinc-500 hover:text-rose-500 transition-colors">
525
  <svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
526
  <path stroke-linecap="round" stroke-linejoin="round" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
527
  </svg>
@@ -536,18 +544,18 @@
536
  function addEmptyMenuRow() {
537
  const tbody = document.getElementById('menuEditorTableBody');
538
  const row = `
539
- <tr class="hover:bg-cafeCard/30 transition-colors">
540
  <td class="px-2 py-2">
541
- <input type="text" class="menu-name w-full bg-cafeCard border border-cafeBorder rounded px-2.5 py-1 text-zinc-200 focus:border-cafeGold/50 focus:outline-none" placeholder="مثلاً: اسپرسو دبل">
542
  </td>
543
  <td class="px-2 py-2">
544
- <input type="text" class="menu-desc w-full bg-cafeCard border border-cafeBorder rounded px-2.5 py-1 text-zinc-200 focus:border-cafeGold/50 focus:outline-none" placeholder="قهوه ۱۰۰٪ عربیکا">
545
  </td>
546
  <td class="px-2 py-2">
547
- <input type="text" class="menu-price w-full bg-cafeCard border border-cafeBorder rounded px-2.5 py-1 text-zinc-200 focus:border-cafeGold/50 focus:outline-none" placeholder="۵۵,۰۰۰">
548
  </td>
549
  <td class="px-2 py-2 text-center">
550
- <button onclick="removeMenuRow(this)" class="p-1 text-zinc-500 hover:text-rose-500 transition-colors">
551
  <svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
552
  <path stroke-linecap="round" stroke-linejoin="round" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
553
  </svg>
@@ -583,7 +591,7 @@
583
  });
584
 
585
  if (menuData.length === 0) {
586
- alert("منوی ثبت شده نمیتواند فاقد هرگونه محصول باشد.");
587
  return;
588
  }
589
 
@@ -596,14 +604,14 @@
596
 
597
  const data = await response.json();
598
  if (response.ok && data.success) {
599
- alert("منوی نهایی با موفقیت ثبت شد و در لحظه برای مشتریان و هوش مصنوعی فعال گردید!");
600
  document.getElementById('menuEditorContainer').classList.add('hidden');
601
  appendChatMessage('model', 'منوی ارسال شده با موفقیت تایید و روی وب‌سایت همگام‌سازی شد. از این پس برای میزهای مشتریان منوی جدید را مبنای کار قرار خواهم داد.');
602
  } else {
603
- alert(data.error || 'خطا در فرآیند ذخیره اطلاعات منو.');
604
  }
605
  } catch (err) {
606
- alert('خطا در دسترسی به سرور جهت همگام‌سازی منو: ' + err.message);
607
  }
608
  }
609
  </script>
 
2
  <html lang="fa" dir="rtl">
3
  <head>
4
  <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
6
+ <title>Cafe AI - پنل مدیریت کافه</title>
 
7
  <link rel="preconnect" href="https://fonts.googleapis.com">
8
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
9
+ <link href="https://fonts.googleapis.com/css2?family=Vazirmatn:wght@300;400;500;700;800&display=swap" rel="stylesheet">
 
10
  <script src="https://cdn.tailwindcss.com"></script>
11
  <script>
12
  tailwind.config = {
 
16
  sans: ['Vazirmatn', 'sans-serif'],
17
  },
18
  colors: {
19
+ obsidian: '#09090b', /* مشکی تیره خالص */
20
+ coal: '#121215', /* خاکستری ذغالی */
21
+ clay: '#1c1c22', /* خاکستری روشن‌تر */
22
+ brass: '#c5a880', /* برنز گرم */
23
+ brassHover: '#dcc6a8', /* برنز روشن */
24
+ emeraldMuted: '#10b981', /* سبز تایید نهایی */
25
+ },
26
+ boxShadow: {
27
+ glow: '0 0 20px rgba(197, 168, 128, 0.12)',
28
+ greenGlow: '0 0 25px rgba(16, 185, 129, 0.2)',
29
  }
30
  }
31
  }
 
35
  body {
36
  background-color: #09090b;
37
  color: #f4f4f5;
38
+ -webkit-tap-highlight-color: transparent;
39
  }
40
+ /* تنظیمات اسکرول‌بار اختصاصی باریک */
41
  ::-webkit-scrollbar {
42
  width: 4px;
43
  }
44
  ::-webkit-scrollbar-track {
45
+ background: #121215;
46
  }
47
  ::-webkit-scrollbar-thumb {
48
+ background: #2c2c35;
49
  border-radius: 2px;
50
  }
51
  </style>
52
  </head>
53
+ <body class="min-h-screen flex flex-col font-sans selection:bg-amber-500 selection:text-black overflow-x-hidden bg-gradient-to-tr from-obsidian via-[#0d0e12] to-[#120f0a] antialiased">
54
+
55
+ <!-- تصویر زمینه هاله‌های نوری در دسکتاپ -->
56
+ <div class="hidden lg:block absolute inset-0 overflow-hidden pointer-events-none z-0">
57
+ <div class="absolute -top-[10%] -left-[5%] w-[600px] h-[600px] rounded-full bg-brass/3 blur-[140px]"></div>
58
+ <div class="absolute -bottom-[10%] -right-[5%] w-[600px] h-[600px] rounded-full bg-brass/2 blur-[140px]"></div>
59
+ </div>
60
 
61
+ <!-- هدر پنل مدیریت -->
62
+ <header class="border-b border-[#2c2c35]/40 bg-coal/50 backdrop-blur-md sticky top-0 z-50 px-4 py-4 md:px-8">
63
  <div class="max-w-7xl mx-auto flex items-center justify-between">
64
  <div class="flex items-center gap-3">
65
+ <div class="w-10 h-10 rounded-xl bg-brass/10 border border-brass/20 flex items-center justify-center">
66
+ <svg class="w-6 h-6 text-brass" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
67
+ <path d="M17 8h1a4 4 0 1 1 0 8h-1" />
68
+ <path d="M3 8h14v9a4 4 0 0 1-4 4H7a4 4 0 0 1-4-4Z" />
69
+ <line x1="6" y1="2" x2="6" y2="4" />
70
+ <line x1="10" y1="2" x2="10" y2="4" />
71
+ <line x1="14" y1="2" x2="14" y2="4" />
72
+ </svg>
73
+ </div>
74
  <div>
75
+ <h1 class="text-sm font-extrabold text-white flex items-center gap-2">
76
+ پنل مدیریت ادمین <span class="text-brass">Cafe AI</span>
77
  </h1>
78
+ <p class="text-[10px] text-zinc-500 font-medium">پایش لحظه‌ای سفارشات آشپزخانه و منوی فعال هوش مصنوعی</p>
79
  </div>
80
  </div>
81
 
82
  <div class="flex items-center gap-3">
83
+ <span class="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-full text-[10px] font-bold bg-emeraldMuted/10 text-emerald-400 border border-emeraldMuted/20">
84
  <span class="w-1.5 h-1.5 rounded-full bg-emerald-400 animate-pulse"></span>
85
+ نظارت زنده فعال
86
  </span>
87
  </div>
88
  </div>
89
  </header>
90
 
91
+ <!-- بدنه چیدمان اصلی پنل ادمین -->
92
+ <main class="flex-1 max-w-7xl w-full mx-auto p-4 md:p-6 lg:p-8 grid grid-cols-1 lg:grid-cols-12 gap-6 z-10 relative">
93
 
94
+ <!-- ستون سمت راست: پایش سفارشات فعال و آپلود فاکتور منو (۷ از ۱۲) -->
95
  <section class="lg:col-span-7 flex flex-col gap-6">
96
 
97
+ <!-- باکس مانیتورینگ سفارشات آشپزخانه -->
98
+ <div class="bg-coal/60 border border-[#2c2c35]/40 rounded-2xl p-5 shadow-xl backdrop-blur-md">
99
+ <div class="flex items-center justify-between mb-4 border-b border-[#2c2c35]/30 pb-3">
100
+ <h2 class="text-xs font-extrabold text-white flex items-center gap-2">
101
+ <svg class="w-4 h-4 text-brass" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
102
+ <path stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" />
103
  </svg>
104
+ سفارشات جدید آشپزخانه
105
  </h2>
106
+ <button onclick="fetchActiveOrders()" class="text-[10px] text-zinc-500 hover:text-brass flex items-center gap-1 transition-all duration-300">
107
  <svg class="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
108
  <path stroke-linecap="round" stroke-linejoin="round" d="M4 4v5h.582m15.356 2A8.001 8.001 0 1121.21 15H15" />
109
  </svg>
 
111
  </button>
112
  </div>
113
 
114
+ <!-- ظرف دربرگیرنده لیست سفارشات -->
115
  <div id="ordersContainer" class="space-y-4 max-h-[350px] overflow-y-auto pr-1">
116
  <div class="text-center py-12 text-xs text-zinc-500">
117
  در حال بارگذاری لیست سفارشات جاری...
 
119
  </div>
120
  </div>
121
 
122
+ <!-- بخش آپلود و استخراج خودکار عکس منو -->
123
+ <div class="bg-coal/60 border border-[#2c2c35]/40 rounded-2xl p-5 shadow-xl backdrop-blur-md space-y-4">
124
+ <h2 class="text-xs font-extrabold text-white flex items-center gap-2 border-b border-[#2c2c35]/30 pb-3">
125
+ <svg class="w-4 h-4 text-brass" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
126
  <path stroke-linecap="round" stroke-linejoin="round" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m4-4v12" />
127
  </svg>
128
+ استخراج منوی جدید با تصویر
129
  </h2>
130
 
131
+ <p class="text-[11px] text-zinc-500 leading-relaxed">
132
+ با کشیدن و رها کردن یا انتخاب عکس منوی جدید، هوش مصنوعی نیلا ساختار قیمت‌ها و محصولات را فوراً استخراج می‌کند تا پس از ویرایش برای مشتریان منتشر کنید.
133
  </p>
134
 
135
+ <!-- زون آپلود فایل -->
136
+ <div class="border-2 border-dashed border-[#2c2c35] hover:border-brass/30 rounded-xl p-6 text-center cursor-pointer transition-all bg-obsidian/30" onclick="document.getElementById('menuFileInput').click()">
137
  <input type="file" id="menuFileInput" class="hidden" accept="image/*,application/pdf" onchange="uploadMenuFile(event)">
138
  <div class="flex flex-col items-center gap-2.5">
139
+ <svg class="w-7 h-7 text-zinc-600" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5">
140
  <path stroke-linecap="round" stroke-linejoin="round" d="M9 13h6m-3-3v6m-9 1V7a2 2 0 012-2h6l2 2h6a2 2 0 012 2v8a2 2 0 01-2 2H5a2 2 0 01-2-2z" />
141
  </svg>
142
+ <span class="text-xs text-zinc-300 font-medium">عکس منوی جدید را جهت بارگذاری انتخاب کنید</span>
143
+ <span class="text-[9px] text-zinc-500 uppercase tracking-wider">فرمت‌های تصویری یا فایل PDF</span>
144
  </div>
145
  </div>
146
 
147
+ <!-- افکت لودینگ تحلیل هوش مصنوعی -->
148
+ <div id="uploadLoader" class="hidden text-center py-6 bg-obsidian/40 rounded-xl border border-[#2c2c35]/40 animate-pulse">
149
+ <div class="inline-block animate-spin rounded-full h-7 w-7 border-t-2 border-b-2 border-brass mb-2"></div>
150
+ <p class="text-[10px] text-brass font-bold">نیلا در حال پردازش متون و فاکتور منوی جدید است. لطفاً چند لحظه شکیبا باشید...</p>
151
  </div>
152
 
153
  <!-- جدول ویرایش اقلام استخراج شده -->
154
+ <div id="menuEditorContainer" class="hidden space-y-4 border-t border-[#2c2c35]/30 pt-4">
155
+ <h3 class="text-xs font-bold text-brass flex items-center gap-1.5">
156
+ <svg class="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
157
  <path stroke-linecap="round" stroke-linejoin="round" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z" />
158
  </svg>
159
+ بازبینی و بازسازی منوی جاری پیش از انتشار
160
  </h3>
161
 
162
+ <div class="overflow-x-auto max-h-[250px] border border-[#2c2c35]/40 rounded-xl bg-obsidian/20">
163
+ <table class="min-w-full divide-y divide-[#2c2c35]/40 text-[11px]">
164
+ <thead class="bg-coal">
165
  <tr>
166
+ <th class="px-3 py-2.5 text-right font-medium text-zinc-400">عنوان محصول</th>
167
+ <th class="px-3 py-2.5 text-right font-medium text-zinc-400">توضیحات کوتاه</th>
168
+ <th class="px-3 py-2.5 text-right font-medium text-zinc-400 w-24">قیمت (تومان)</th>
169
+ <th class="px-3 py-2.5 text-center font-medium text-zinc-400 w-16">عملیات</th>
170
  </tr>
171
  </thead>
172
+ <tbody id="menuEditorTableBody" class="divide-y divide-[#2c2c35]/40">
173
+ <!-- سطرها -->
174
  </tbody>
175
  </table>
176
  </div>
177
 
178
  <div class="flex justify-end gap-2">
179
+ <button onclick="addEmptyMenuRow()" class="px-3 py-1.5 border border-[#2c2c35] hover:border-zinc-500 rounded-lg text-[10px] text-zinc-300 transition-all duration-300">
180
  افزودن محصول جدید
181
  </button>
182
+ <button onclick="saveAndPublishMenu()" class="px-4 py-1.5 bg-emerald-600 hover:bg-emerald-500 rounded-lg text-[11px] font-extrabold text-white transition-all duration-300 flex items-center gap-1.5 shadow-greenGlow">
183
+ تایید و فعالسازی منوی زنده مشتریان
 
 
 
184
  </button>
185
  </div>
186
  </div>
 
188
  </div>
189
  </section>
190
 
191
+ <!-- ستون سمت چپ: چت مدیریت با هوش مصنوعی نیلا جهت تغییر موجودی (۵ از ۱۲) -->
192
+ <section class="lg:col-span-5 flex flex-col bg-coal/60 border border-[#2c2c35]/40 rounded-2xl shadow-xl h-[630px] overflow-hidden backdrop-blur-md">
193
 
194
+ <!-- سربرگ چت ادمین -->
195
+ <div class="px-5 py-4 border-b border-[#2c2c35]/40 flex items-center justify-between bg-obsidian/20">
196
  <div class="flex items-center gap-3">
197
+ <div class="w-10 h-10 rounded-xl bg-brass/10 border border-brass/20 flex items-center justify-center">
198
+ <svg class="w-5 h-5 text-brass" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
199
  <path d="M12 2a10 10 0 0 1 10 10c0 5.523-4.477 10-10 10S2 17.523 2 12A10 10 0 0 1 12 2z"/>
200
  <path d="M12 8v4l3 3"/>
201
  </svg>
202
  </div>
203
  <div>
204
+ <h3 class="text-xs font-extrabold text-white">دستیار مدیریت منو (Nila)</h3>
205
+ <p class="text-[9px] text-zinc-500 font-medium">تغییر زنده وضعیت موجودی محصولات با مکالمه</p>
206
  </div>
207
  </div>
208
  </div>
209
 
210
+ <!-- بدنه چت باکس ادمین -->
211
  <div id="chatMessages" class="flex-1 overflow-y-auto p-4 space-y-4">
212
  <div class="flex gap-2.5 max-w-[85%]">
213
+ <div class="w-7 h-7 rounded-lg bg-brass/10 border border-brass/20 flex items-center justify-center flex-shrink-0">
214
+ <svg class="w-4 h-4 text-brass" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
215
  <circle cx="12" cy="12" r="10"/>
216
  <path d="M12 8v4l3 3"/>
217
  </svg>
218
  </div>
219
+ <div class="bg-obsidian/50 border border-[#2c2c35]/40 text-zinc-300 text-xs rounded-2xl rounded-tr-none px-3.5 py-2.5 leading-relaxed font-sans">
220
+ سلام ادمین گرامی! من نیلا هستم، دستیار مدیریت منوی Cafe AI. شما می‌توانید از همین‌جا اقلام منو را با گفتگوی ساده کنترل کنید؛ برای مثال بنویسید: "کروسان ساده تمام شد" یا "چای ماسالا را موجود کن" تا سریعاً تغییرات روی سیستم مشتریان نیز اعمال گردد.
221
  </div>
222
  </div>
223
  </div>
224
 
225
+ <!-- لودر تایپ ادمین چت -->
226
+ <div id="chatLoader" class="hidden px-4 py-2 flex items-center justify-between bg-obsidian/30 text-[9px] text-zinc-500 font-bold border-t border-[#2c2c35]/40">
227
  <div class="flex items-center gap-2">
228
  <div class="flex space-x-1 space-x-reverse">
229
+ <span class="w-1.5 h-1.5 bg-brass rounded-full animate-bounce" style="animation-delay: 0.1s"></span>
230
+ <span class="w-1.5 h-1.5 bg-brass rounded-full animate-bounce" style="animation-delay: 0.2s"></span>
231
+ <span class="w-1.5 h-1.5 bg-brass rounded-full animate-bounce" style="animation-delay: 0.3s"></span>
232
  </div>
233
+ <span>نیلا در حال پردازش دستور مدیریت...</span>
234
  </div>
235
+ <button onclick="stopAdminChat()" class="px-2.5 py-1 bg-rose-950/20 border border-rose-800/30 hover:bg-rose-900/40 rounded-lg text-[9px] text-rose-400 font-bold transition-all">
236
+ توقف پاسخ
237
  </button>
238
  </div>
239
 
240
+ <!-- فرم ارسال پیام در چت ادمین -->
241
+ <form id="chatForm" onsubmit="sendAdminMessage(event)" class="p-3 border-t border-[#2c2c35]/40 bg-obsidian/30 flex gap-2">
242
+ <input type="text" id="chatInput" placeholder="دستور جدید را به صورت متنی بنویسید..." autocomplete="off" class="flex-1 bg-coal border border-[#2c2c35]/40 text-xs text-zinc-200 placeholder-zinc-600 rounded-lg px-3.5 py-2.5 focus:outline-none focus:border-brass/30 transition-all duration-300">
243
+ <button type="submit" id="sendBtn" class="bg-brass hover:bg-brassHover text-obsidian font-extrabold px-4 py-2.5 rounded-lg text-xs transition-all duration-300 flex items-center justify-center flex-shrink-0 shadow-glow">
244
  <svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.5">
245
  <path stroke-linecap="round" stroke-linejoin="round" d="M14 5l7 7m0 0l-7 7m7-7H3" />
246
  </svg>
 
251
 
252
  </main>
253
 
254
+ <!-- فوتر پایین پنل -->
255
+ <footer class="border-t border-[#2c2c35]/30 py-4 text-center text-[10px] text-zinc-600 bg-obsidian/90">
256
  طراحی و توسعه توسط الگوریتم داده نسترن | کلیه حقوق محفوظ است © ۲۰۲۶
257
  </footer>
258
 
259
+ <!-- منطق جاوا اسکریپت پنل مدیریت ادمین -->
260
  <script>
261
  let chatHistory = [
262
+ { role: 'model', content: 'سلام ادمین گرامی! من نیلا هستم، دستیار مدیریت منوی Cafe AI. شما می‌توانید از همین‌جا اقلام منو را با گفتگوی ساده کنترل کنید؛ برای مثال بنویسید: "کروسان ساده تمام شد" یا "چای ماسالا را موجود کن" تا سریعاً تغییرات روی سیستم مشتریان نیز اعمال گردد.' }
263
  ];
264
  let abortController = null;
265
  let isGenerating = false;
266
 
267
  window.addEventListener('DOMContentLoaded', () => {
268
  fetchActiveOrders();
269
+ // بروزرسانی خودکار سفارشات هر ۱۰ ثانیه
270
  setInterval(fetchActiveOrders, 10000);
271
  });
272
 
273
+ // --- مدیریت پایش سفارشات زنده ---
274
 
275
  async function fetchActiveOrders() {
276
  const container = document.getElementById('ordersContainer');
 
281
  if (response.ok) {
282
  if (orders.length === 0) {
283
  container.innerHTML = `
284
+ <div class="text-center py-16 text-zinc-500 border border-dashed border-[#2c2c35]/40 rounded-2xl bg-obsidian/10">
285
  <svg class="w-9 h-9 text-zinc-600 mx-auto mb-2" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5">
286
  <path stroke-linecap="round" stroke-linejoin="round" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
287
  </svg>
288
+ هیچ سفارش معلق و فعالی در صف آشپزخانه نیست.
289
  </div>
290
  `;
291
  return;
 
296
  let itemsHtml = '';
297
  order.items.forEach(item => {
298
  itemsHtml += `
299
+ <div class="flex items-center justify-between text-[11px] bg-obsidian/60 px-3 py-2 rounded-lg border border-[#2c2c35]/40">
300
  <span class="text-zinc-300 font-bold">${item.name}</span>
301
+ <span class="text-brass bg-brass/10 px-2 py-0.5 rounded-md font-extrabold">تعداد: ${item.quantity}</span>
302
  </div>
303
  `;
304
  });
 
306
  const timeString = new Date(order.timestamp * 1000).toLocaleTimeString('fa-IR', { hour: '2-digit', minute: '2-digit' });
307
 
308
  const cardHtml = `
309
+ <div class="border border-[#2c2c35]/40 hover:border-brass/20 rounded-xl p-4 bg-obsidian/30 transition-all duration-300 flex flex-col md:flex-row justify-between items-start md:items-center gap-3">
310
  <div class="flex-1 space-y-2 w-full">
311
  <div class="flex items-center justify-between md:justify-start gap-3 w-full">
312
+ <span class="text-xs font-bold text-white bg-brass/10 border border-brass/20 px-2.5 py-1 rounded-lg">میز شماره ${order.table}</span>
313
+ <span class="text-[9px] text-zinc-500 font-medium">زمان ثبت: ${timeString}</span>
314
  </div>
315
  <div class="grid grid-cols-1 sm:grid-cols-2 gap-1.5 mt-2">
316
  ${itemsHtml}
317
  </div>
318
  </div>
319
+ <button onclick="completeOrder(${order.id})" class="w-full md:w-auto px-4 py-2.5 bg-zinc-800 hover:bg-emerald-700 text-zinc-200 hover:text-white rounded-lg text-[10px] font-bold transition-all flex items-center justify-center gap-1.5 border border-zinc-700 hover:border-emerald-600 flex-shrink-0 group">
320
  <svg class="w-3.5 h-3.5 text-zinc-400 group-hover:text-white transition-colors" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.5">
321
  <path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7" />
322
  </svg>
323
+ آماده و تحویل شد
324
  </button>
325
  </div>
326
  `;
327
  container.insertAdjacentHTML('beforeend', cardHtml);
328
  });
329
  } else {
330
+ container.innerHTML = `<div class="text-center py-6 text-rose-500 text-xs">خطا در دریافت سفارشات از پایگاه داده مرکزی.</div>`;
331
  }
332
  } catch (err) {
333
+ container.innerHTML = `<div class="text-center py-6 text-rose-500 text-xs">عدم اتصال پایدار با سرور اصلی کافه: ${err.message}</div>`;
334
  }
335
  }
336
 
 
346
  if (response.ok && result.success) {
347
  fetchActiveOrders();
348
  } else {
349
+ alert(result.error || "خطایی در فرآیند تغییر وضعیت رخ داد.");
350
  }
351
  } catch (err) {
352
+ alert("بروز خطای نامشخص شبکه: " + err.message);
353
  }
354
  }
355
 
356
 
357
+ // --- سیستم مکالمه مدیریت جهت تغییر موجودی منو ---
358
 
359
  async function sendAdminMessage(e) {
360
  e.preventDefault();
 
387
  isGenerating = false;
388
 
389
  if (response.ok && data.success) {
390
+ // شبیه‌سازی انیمیشن نگارش کلمات جهت پایداری ظاهر بصری
391
  const botBubbleId = appendChatMessage('model', '');
392
  const botBubble = document.getElementById(botBubbleId);
393
  let i = 0;
 
395
 
396
  function typeText() {
397
  if (i < textResponse.length && !abortController.signal.aborted) {
398
+ botBubble.textContent += textResponse.charAt(i);
399
  i++;
400
  document.getElementById('chatMessages').scrollTop = document.getElementById('chatMessages').scrollHeight;
401
+ setTimeout(typeText, 6);
402
  } else {
403
  chatHistory.push({ role: 'model', content: textResponse });
404
  }
 
406
  typeText();
407
 
408
  } else {
409
+ appendChatMessage('model', data.error || 'پاسخی از سمت دستیار هوشمند دریافت نشد.');
410
  }
411
  } catch (err) {
412
  toggleChatLoading(false);
413
  isGenerating = false;
414
  if (err.name !== 'AbortError') {
415
+ appendChatMessage('model', 'خطا در ارتباط زنده با دستیار ادمین: ' + err.message);
416
  }
417
  }
418
  }
 
449
  if (role === 'user') {
450
  html = `
451
  <div class="flex justify-end gap-2.5 max-w-[85%] mr-auto">
452
+ <div class="bg-brass/10 border border-brass/20 text-zinc-100 text-xs rounded-2xl rounded-tl-none px-3.5 py-2.5 leading-relaxed">
453
  ${content}
454
  </div>
455
  </div>
 
457
  } else {
458
  html = `
459
  <div class="flex gap-2.5 max-w-[85%]">
460
+ <div class="w-7 h-7 rounded-lg bg-brass/10 border border-brass/20 flex items-center justify-center flex-shrink-0">
461
+ <svg class="w-4 h-4 text-brass" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
462
  <circle cx="12" cy="12" r="10"/>
463
  <path d="M12 8v4l3 3"/>
464
  </svg>
465
  </div>
466
+ <div id="${bubbleId}" class="bg-obsidian/50 border border-[#2c2c35]/40 text-zinc-200 text-xs rounded-2xl rounded-tr-none px-3.5 py-2.5 leading-relaxed font-sans">
467
  ${content}
468
  </div>
469
  </div>
 
476
  }
477
 
478
 
479
+ // --- سیستم بارگذاری، استخراج و ویرایش منوی جدید ---
480
 
481
  async function uploadMenuFile(e) {
482
  const file = e.target.files[0];
 
504
  renderMenuEditor(data.extracted_menu);
505
  editor.classList.remove('hidden');
506
  } else {
507
+ alert(data.error || 'هوش مصنوعی موفق به پردازش تصویر ارسالی نشد.');
508
  }
509
  } catch (err) {
510
  loader.classList.add('hidden');
511
+ alert('خطا در فرستادن اطلاعات تصویر منو: ' + err.message);
512
  }
513
  }
514
 
 
518
 
519
  menuItems.forEach((item, index) => {
520
  const row = `
521
+ <tr class="hover:bg-coal/40 transition-colors duration-200">
522
  <td class="px-2 py-2">
523
+ <input type="text" class="menu-name w-full bg-coal border border-[#2c2c35]/50 rounded-lg px-2.5 py-1.5 text-zinc-200 focus:border-brass/30 focus:outline-none" value="${item.name || ''}">
524
  </td>
525
  <td class="px-2 py-2">
526
+ <input type="text" class="menu-desc w-full bg-coal border border-[#2c2c35]/50 rounded-lg px-2.5 py-1.5 text-zinc-200 focus:border-brass/30 focus:outline-none" value="${item.description || ''}">
527
  </td>
528
  <td class="px-2 py-2">
529
+ <input type="text" class="menu-price w-full bg-coal border border-[#2c2c35]/50 rounded-lg px-2.5 py-1.5 text-zinc-200 focus:border-brass/30 focus:outline-none" value="${item.price || ''}">
530
  </td>
531
  <td class="px-2 py-2 text-center">
532
+ <button onclick="removeMenuRow(this)" class="p-1 text-zinc-600 hover:text-rose-500 transition-colors">
533
  <svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
534
  <path stroke-linecap="round" stroke-linejoin="round" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
535
  </svg>
 
544
  function addEmptyMenuRow() {
545
  const tbody = document.getElementById('menuEditorTableBody');
546
  const row = `
547
+ <tr class="hover:bg-coal/40 transition-colors duration-200">
548
  <td class="px-2 py-2">
549
+ <input type="text" class="menu-name w-full bg-coal border border-[#2c2c35]/50 rounded-lg px-2.5 py-1.5 text-zinc-200 focus:border-brass/30 focus:outline-none" placeholder="مثال: لاته ماکیاتو">
550
  </td>
551
  <td class="px-2 py-2">
552
+ <input type="text" class="menu-desc w-full bg-coal border border-[#2c2c35]/50 rounded-lg px-2.5 py-1.5 text-zinc-200 focus:border-brass/30 focus:outline-none" placeholder="ترکیب لاته آرت با سس اسپرسو">
553
  </td>
554
  <td class="px-2 py-2">
555
+ <input type="text" class="menu-price w-full bg-coal border border-[#2c2c35]/50 rounded-lg px-2.5 py-1.5 text-zinc-200 focus:border-brass/30 focus:outline-none" placeholder="۷۵,۰۰۰">
556
  </td>
557
  <td class="px-2 py-2 text-center">
558
+ <button onclick="removeMenuRow(this)" class="p-1 text-zinc-600 hover:text-rose-500 transition-colors">
559
  <svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
560
  <path stroke-linecap="round" stroke-linejoin="round" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
561
  </svg>
 
591
  });
592
 
593
  if (menuData.length === 0) {
594
+ alert("امکان انتشار یک لیست خالی وجود ندارد.");
595
  return;
596
  }
597
 
 
604
 
605
  const data = await response.json();
606
  if (response.ok && data.success) {
607
+ alert("منوی جدید با موفقیت ثبت و روی وب‌سایت همگام‌سازی شد!");
608
  document.getElementById('menuEditorContainer').classList.add('hidden');
609
  appendChatMessage('model', 'منوی ارسال شده با موفقیت تایید و روی وب‌سایت همگام‌سازی شد. از این پس برای میزهای مشتریان منوی جدید را مبنای کار قرار خواهم داد.');
610
  } else {
611
+ alert(data.error || 'بروز خطا در همگام‌سازی داده‌های جدید.');
612
  }
613
  } catch (err) {
614
+ alert('خطا در دسترسی به پایگاه داده مرکزی منوها: ' + err.message);
615
  }
616
  }
617
  </script>