humanvprojectceo commited on
Commit
5f216b2
·
verified ·
1 Parent(s): bd6fc8b

Create cafe.html

Browse files
Files changed (1) hide show
  1. cafe.html +570 -0
cafe.html ADDED
@@ -0,0 +1,570 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
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
+ <!-- لود واژه‌نامه و فوت فارسی زیبا -->
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 برای استایل‌دهی مدرن -->
12
+ <script src="https://cdn.tailwindcss.com"></script>
13
+ <script>
14
+ tailwind.config = {
15
+ theme: {
16
+ extend: {
17
+ fontFamily: {
18
+ sans: ['Vazirmatn', 'sans-serif'],
19
+ },
20
+ colors: {
21
+ cafeDark: '#09090b', /* مشکی بسیار تیره */
22
+ cafeCard: '#18181b', /* خاکستری تیره برای کارت‌ها */
23
+ cafeBorder: '#27272a', /* رنگ حاشیه‌ها */
24
+ cafeGold: '#d4af37', /* رنگ طلایی شاخص */
25
+ cafeGoldHover: '#f3cd5c', /* طلایی روشن‌تر */
26
+ cafeAccent: '#f59e0b' /* کهربایی */
27
+ }
28
+ }
29
+ }
30
+ }
31
+ </script>
32
+ <style>
33
+ body {
34
+ background-color: #09090b;
35
+ color: #f4f4f5;
36
+ }
37
+ /* کاستومایز کردن اسکرول‌بار برای هماهنگی با تم تاریک */
38
+ ::-webkit-scrollbar {
39
+ width: 6px;
40
+ }
41
+ ::-webkit-scrollbar-track {
42
+ background: #18181b;
43
+ }
44
+ ::-webkit-scrollbar-thumb {
45
+ background: #3f3f46;
46
+ border-radius: 3px;
47
+ }
48
+ ::-webkit-scrollbar-thumb:hover {
49
+ background: #52525b;
50
+ }
51
+ </style>
52
+ </head>
53
+ <body class="min-h-screen flex flex-col font-sans selection:bg-amber-500 selection:text-black">
54
+
55
+ <!-- هدر اصلی پنل مدیریت -->
56
+ <header class="border-b border-cafeBorder bg-cafeCard/80 backdrop-blur sticky top-0 z-50 px-4 py-3 md:px-8">
57
+ <div class="max-w-7xl mx-auto flex items-center justify-between">
58
+ <div class="flex items-center gap-3">
59
+ <!-- لوگوی اختصاصی فنجان قهوه هوشمند (SVG) -->
60
+ <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">
61
+ <path d="M17 8h1a4 4 0 1 1 0 8h-1" />
62
+ <path d="M3 8h14v9a4 4 0 0 1-4 4H7a4 4 0 0 1-4-4Z" />
63
+ <line x1="6" y1="2" x2="6" y2="4" />
64
+ <line x1="10" y1="2" x2="10" y2="4" />
65
+ <line x1="14" y1="2" x2="14" y2="4" />
66
+ </svg>
67
+ <div>
68
+ <h1 class="text-lg font-bold tracking-wide text-white flex items-center gap-2">
69
+ پنل مدیریت <span class="text-cafeGold">Cafe AI</span>
70
+ </h1>
71
+ <p class="text-[10px] text-zinc-400">سیستم نظارت بر سفارشات و هوش مصنوعی نیلا</p>
72
+ </div>
73
+ </div>
74
+
75
+ <div class="flex items-center gap-4">
76
+ <span class="inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs font-medium bg-emerald-500/10 text-emerald-400 border border-emerald-500/20">
77
+ <span class="w-1.5 h-1.5 rounded-full bg-emerald-400 animate-pulse"></span>
78
+ سیستم فعال است
79
+ </span>
80
+ </div>
81
+ </div>
82
+ </header>
83
+
84
+ <!-- بدنه اصلی چیدمان دو ستونه -->
85
+ <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">
86
+
87
+ <!-- ستون سمت راست: مدیریت سفارشات فعال و بارگذاری منو (عرض: ۷ از ۱۲) -->
88
+ <section class="lg:col-span-7 flex flex-col gap-6">
89
+
90
+ <!-- بخش سفارش‌های زنده -->
91
+ <div class="bg-cafeCard border border-cafeBorder rounded-xl p-5 shadow-2xl">
92
+ <div class="flex items-center justify-between mb-4 border-b border-cafeBorder pb-3">
93
+ <h2 class="text-base font-bold text-white flex items-center gap-2">
94
+ <svg class="w-5 h-5 text-cafeGold" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
95
+ <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" />
96
+ </svg>
97
+ سفارشات جاری آشپزخانه
98
+ </h2>
99
+ <button onclick="fetchActiveOrders()" class="text-xs text-zinc-400 hover:text-cafeGold flex items-center gap-1 transition-all">
100
+ <svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
101
+ <path stroke-linecap="round" stroke-linejoin="round" d="M4 4v5h.582m15.356 2A8.001 8.001 0 1121.21 15H15" />
102
+ </svg>
103
+ بروزرسانی دستی
104
+ </button>
105
+ </div>
106
+
107
+ <!-- لیست سفارشات -->
108
+ <div id="ordersContainer" class="space-y-4 max-h-[400px] overflow-y-auto pr-1">
109
+ <!-- حالت بارگذاری اولیه یا خالی بودن -->
110
+ <div class="text-center py-12 text-zinc-500">
111
+ در حال بارگذاری سفارشات جاری...
112
+ </div>
113
+ </div>
114
+ </div>
115
+
116
+ <!-- بخش بارگذاری و استخراج منو -->
117
+ <div class="bg-cafeCard border border-cafeBorder rounded-xl p-5 shadow-2xl">
118
+ <h2 class="text-base font-bold text-white mb-4 flex items-center gap-2 border-b border-cafeBorder pb-3">
119
+ <svg class="w-5 h-5 text-cafeGold" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
120
+ <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" />
121
+ </svg>
122
+ بارگذاری و به‌روزرسانی هوشمند منو
123
+ </h2>
124
+
125
+ <p class="text-xs text-zinc-400 mb-4 leading-relaxed">
126
+ تصویر منو یا فایل لیست قیمت‌ها را آپلود کنید. دستیار هوشمند نیلا، آیتم‌ها، قیمت‌ها و توضیحات را استخراج کرده و جهت تایید نهایی به شما نمایش می‌دهد.
127
+ </p>
128
+
129
+ <!-- باکس آپلود فایل -->
130
+ <div class="border-2 border-dashed border-cafeBorder hover:border-cafeGold/50 rounded-lg p-6 text-center cursor-pointer transition-all bg-cafeDark/30" onclick="document.getElementById('menuFileInput').click()">
131
+ <input type="file" id="menuFileInput" class="hidden" accept="image/*,application/pdf" onchange="uploadMenuFile(event)">
132
+ <div class="flex flex-col items-center gap-2">
133
+ <svg class="w-8 h-8 text-zinc-500" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5">
134
+ <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" />
135
+ </svg>
136
+ <span class="text-sm text-zinc-300">انتخاب تصویر منو یا فایل متنی</span>
137
+ <span class="text-[10px] text-zinc-500">فرمت‌های مجاز: تصاویر (PNG, JPG) یا PDF</span>
138
+ </div>
139
+ </div>
140
+
141
+ <!-- اسپینر در حال بارگذاری تحلیل مدل -->
142
+ <div id="uploadLoader" class="hidden mt-4 text-center py-6 bg-cafeDark/50 rounded-lg border border-cafeBorder">
143
+ <div class="inline-block animate-spin rounded-full h-8 w-8 border-t-2 border-b-2 border-cafeGold mb-2"></div>
144
+ <p class="text-xs text-cafeGold">نیلا در حال پردازش سند و استخراج ساختار منو است. لطفاً شکیبا باشید...</p>
145
+ </div>
146
+
147
+ <!-- ویرایشگر منوی استخراج شده -->
148
+ <div id="menuEditorContainer" class="hidden mt-6 space-y-4 border-t border-cafeBorder pt-4">
149
+ <h3 class="text-sm font-bold text-white flex items-center gap-2 text-amber-400">
150
+ <svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
151
+ <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" />
152
+ </svg>
153
+ بازبینی و ویرایش منوی پیشنهادی هوش مصنوعی
154
+ </h3>
155
+
156
+ <div class="overflow-x-auto max-h-[300px] border border-cafeBorder rounded-lg">
157
+ <table class="min-w-full divide-y divide-cafeBorder bg-cafeDark/40 text-xs">
158
+ <thead class="bg-cafeCard">
159
+ <tr>
160
+ <th class="px-3 py-2 text-right font-medium text-zinc-400">ن��م آیتم</th>
161
+ <th class="px-3 py-2 text-right font-medium text-zinc-400">توضیحات/ترکیبات</th>
162
+ <th class="px-3 py-2 text-right font-medium text-zinc-400 w-24">قیمت (تومان)</th>
163
+ <th class="px-3 py-2 text-center font-medium text-zinc-400 w-16">عملیات</th>
164
+ </tr>
165
+ </thead>
166
+ <tbody id="menuEditorTableBody" class="divide-y divide-cafeBorder">
167
+ <!-- سطرها داینامیک اضافه میشن -->
168
+ </tbody>
169
+ </table>
170
+ </div>
171
+
172
+ <div class="flex justify-end gap-2">
173
+ <button onclick="addEmptyMenuRow()" class="px-3 py-1.5 border border-cafeBorder hover:border-zinc-500 rounded text-xs text-zinc-300 transition-all">
174
+ افزودن سطر جدید
175
+ </button>
176
+ <button onclick="saveAndPublishMenu()" class="px-4 py-1.5 bg-emerald-600 hover:bg-emerald-500 rounded text-xs font-bold text-white transition-all flex items-center gap-1.5">
177
+ <svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
178
+ <path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7" />
179
+ </svg>
180
+ تایید نهایی و به‌روزرسانی زنده منو
181
+ </button>
182
+ </div>
183
+ </div>
184
+
185
+ </div>
186
+ </section>
187
+
188
+ <!-- ستون سمت چپ: چت همکار (ادمین) با نیلا (عرض: ۵ از ۱۲) -->
189
+ <section class="lg:col-span-5 flex flex-col bg-cafeCard border border-cafeBorder rounded-xl shadow-2xl h-[650px] overflow-hidden">
190
+
191
+ <!-- سربرگ چت -->
192
+ <div class="px-5 py-4 border-b border-cafeBorder flex items-center justify-between bg-cafeDark/30">
193
+ <div class="flex items-center gap-3">
194
+ <!-- آواتار هوش مصنوعی نیلا مخصوص ادمین -->
195
+ <div class="w-9 h-9 rounded-full bg-cafeGold/10 border border-cafeGold/30 flex items-center justify-center">
196
+ <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">
197
+ <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"/>
198
+ <path d="M12 8v4l3 3"/>
199
+ </svg>
200
+ </div>
201
+ <div>
202
+ <h3 class="text-sm font-bold text-white">دستیار هوشمند کافه (Nila)</h3>
203
+ <p class="text-[9px] text-emerald-400">اتصال پایدار با مدل gemini-3.1-flash-lite</p>
204
+ </div>
205
+ </div>
206
+ </div>
207
+
208
+ <!-- بدنه پیام‌های چت -->
209
+ <div id="chatMessages" class="flex-1 overflow-y-auto p-4 space-y-4">
210
+ <!-- پیام خوش آمدگویی پیش‌فرض -->
211
+ <div class="flex gap-2.5 max-w-[85%]">
212
+ <div class="w-7 h-7 rounded-full bg-cafeGold/10 border border-cafeGold/30 flex items-center justify-center flex-shrink-0">
213
+ <svg class="w-4 h-4 text-cafeGold" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
214
+ <circle cx="12" cy="12" r="10"/>
215
+ <path d="M12 8v4l3 3"/>
216
+ </svg>
217
+ </div>
218
+ <div class="bg-cafeDark/60 border border-cafeBorder text-zinc-200 text-xs rounded-2xl rounded-tr-none px-3.5 py-2.5 leading-relaxed">
219
+ سلام همکار گرامی! من نیلا هستم، دستیار هوشمند شما. می‌توانید از همین‌جا با من گفتگو کنید و مواردی مثل ناموجود کردن آیتم‌ها (مثلا: "کیک شکلاتی تموم شد") یا فعال‌سازی مجدد آن‌ها را اعلام کنید تا بلافاصله روی سیستم و منوی مشتریان اعمال کنم.
220
+ </div>
221
+ </div>
222
+ </div>
223
+
224
+ <!-- لودر تایپ هوش مصنوعی -->
225
+ <div id="chatLoader" class="hidden px-4 py-2 flex items-center gap-2 bg-cafeDark/30 text-xs text-zinc-400 border-t border-cafeBorder/50">
226
+ <div class="flex space-x-1 space-x-reverse">
227
+ <span class="w-1.5 h-1.5 bg-cafeGold rounded-full animate-bounce" style="animation-delay: 0.1s"></span>
228
+ <span class="w-1.5 h-1.5 bg-cafeGold rounded-full animate-bounce" style="animation-delay: 0.2s"></span>
229
+ <span class="w-1.5 h-1.5 bg-cafeGold rounded-full animate-bounce" style="animation-delay: 0.3s"></span>
230
+ </div>
231
+ <span>نیلا در حال تفکر...</span>
232
+ </div>
233
+
234
+ <!-- بخش ورودی پیام چت -->
235
+ <form id="chatForm" onsubmit="sendAdminMessage(event)" class="p-3 border-t border-cafeBorder bg-cafeDark/50 flex gap-2">
236
+ <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 py-2.5 focus:outline-none focus:border-cafeGold/60 transition-all">
237
+ <button type="submit" class="bg-cafeGold hover:bg-cafeGoldHover text-zinc-950 font-bold px-4 py-2 rounded-lg text-xs transition-all flex items-center justify-center flex-shrink-0">
238
+ <svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.5">
239
+ <path stroke-linecap="round" stroke-linejoin="round" d="M14 5l7 7m0 0l-7 7m7-7H3" />
240
+ </svg>
241
+ </button>
242
+ </form>
243
+
244
+ </section>
245
+
246
+ </main>
247
+
248
+ <!-- فوتر پایین پنل -->
249
+ <footer class="border-t border-cafeBorder py-4 text-center text-[10px] text-zinc-600 bg-cafeDark">
250
+ طراحی و توسعه توسط الگوریتم داده نسترن | کلیه حقوق محفوظ است © ۲۰۲۶
251
+ </footer>
252
+
253
+ <!-- منطق جاوا اسکریپت و پردازش‌های API -->
254
+ <script>
255
+ // آرشیو پیام‌های چت جاری با نیلا
256
+ let chatHistory = [
257
+ { role: 'model', content: 'سلام همکار گرامی! من نیلا هستم، دستیار هوشمند شما در مدیریت کافه AI. چطور می‌تونم کمکتون کنم؟' }
258
+ ];
259
+
260
+ // پس از لود شدن کامل صفحه کارهای اولیه را انجام می‌دهیم
261
+ window.addEventListener('DOMContentLoaded', () => {
262
+ fetchActiveOrders();
263
+ // بروزرسانی خودکار سفارشات هر ۱۰ ثانیه
264
+ setInterval(fetchActiveOrders, 10000);
265
+ });
266
+
267
+ // --- مدیریت سفارشات جاری ---
268
+
269
+ async function fetchActiveOrders() {
270
+ const container = document.getElementById('ordersContainer');
271
+ try {
272
+ const response = await fetch('/api/admin/orders');
273
+ const orders = await response.json();
274
+
275
+ if (response.ok) {
276
+ if (orders.length === 0) {
277
+ container.innerHTML = `
278
+ <div class="text-center py-16 text-zinc-500 border border-dashed border-cafeBorder rounded-xl bg-cafeDark/20">
279
+ <svg class="w-10 h-10 text-zinc-600 mx-auto mb-2" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5">
280
+ <path stroke-linecap="round" stroke-linejoin="round" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
281
+ </svg>
282
+ در حال حاضر هیچ سفارش معلق و فعالی ثبت نشده است.
283
+ </div>
284
+ `;
285
+ return;
286
+ }
287
+
288
+ container.innerHTML = '';
289
+ orders.forEach(order => {
290
+ // تولید آیتم‌های لیست سفارش
291
+ let itemsHtml = '';
292
+ order.items.forEach(item => {
293
+ itemsHtml += `
294
+ <div class="flex items-center justify-between text-xs bg-cafeDark/50 px-3 py-2 rounded border border-cafeBorder/40">
295
+ <span class="text-zinc-200 font-bold">${item.name}</span>
296
+ <span class="text-cafeGold bg-cafeGold/10 px-2 py-0.5 rounded-full font-bold">تعداد: ${item.quantity}</span>
297
+ </div>
298
+ `;
299
+ });
300
+
301
+ // تبدیل زمان ثبت شده یونیکس به ساعت محلی ساده
302
+ const orderTime = new Date(order.timestamp * 1000).toLocaleTimeString('fa-IR', { hour: '2-digit', minute: '2-digit' });
303
+
304
+ const cardHtml = `
305
+ <div class="border border-cafeBorder hover:border-amber-500/30 rounded-xl p-4 bg-cafeDark/40 transition-all flex flex-col md:flex-row justify-between items-start md:items-center gap-4">
306
+ <div class="flex-1 space-y-2">
307
+ <div class="flex items-center gap-3">
308
+ <span class="text-sm font-bold text-white bg-cafeGold/10 border border-cafeGold/30 px-3 py-1 rounded-lg">میز ${order.table}</span>
309
+ <span class="text-[10px] text-zinc-500">ساعت ثبت سفارش: ${orderTime}</span>
310
+ </div>
311
+ <div class="grid grid-cols-1 sm:grid-cols-2 gap-2 mt-2">
312
+ ${itemsHtml}
313
+ </div>
314
+ </div>
315
+ <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-xs font-bold transition-all flex items-center justify-center gap-2 border border-zinc-700 hover:border-emerald-600 flex-shrink-0 group">
316
+ <svg class="w-4 h-4 text-zinc-400 group-hover:text-white transition-colors" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.5">
317
+ <path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7" />
318
+ </svg>
319
+ آماده و تحویل داده شد
320
+ </button>
321
+ </div>
322
+ `;
323
+ container.insertAdjacentHTML('beforeend', cardHtml);
324
+ });
325
+ } else {
326
+ container.innerHTML = `<div class="text-center py-6 text-rose-500 text-xs">بروز خطا در بازیابی اطلاعات سفارشات از سرور.</div>`;
327
+ }
328
+ } catch (err) {
329
+ container.innerHTML = `<div class="text-center py-6 text-rose-500 text-xs">خطای اتصال به سرور: ${err.message}</div>`;
330
+ }
331
+ }
332
+
333
+ async function completeOrder(orderId) {
334
+ try {
335
+ const response = await fetch('/api/admin/complete_order', {
336
+ method: 'POST',
337
+ headers: { 'Content-Type': 'application/json' },
338
+ body: JSON.stringify({ order_id: orderId })
339
+ });
340
+
341
+ const result = await response.json();
342
+ if (response.ok && result.success) {
343
+ // بروزرسانی آنی لیست پس از ثبت اتمام سفارش
344
+ fetchActiveOrders();
345
+ } else {
346
+ alert(result.error || "خطایی در تغییر وضعیت سفارش رخ داد.");
347
+ }
348
+ } catch (err) {
349
+ alert("خطای شبکه: " + err.message);
350
+ }
351
+ }
352
+
353
+
354
+ // --- چت ادمین با هوش مصنوعی نیلا ---
355
+
356
+ async function sendAdminMessage(e) {
357
+ e.preventDefault();
358
+ const input = document.getElementById('chatInput');
359
+ const messageText = input.value.trim();
360
+ if (!messageText) return;
361
+
362
+ // نمایش پیام ادمین در صفحه چت
363
+ appendChatMessage('user', messageText);
364
+ input.value = '';
365
+
366
+ // افزودن به سوابق گفتگو جهت ارسال به مدل
367
+ chatHistory.push({ role: 'user', content: messageText });
368
+
369
+ // نمایش افکت در حال تفکر نیلا
370
+ const loader = document.getElementById('chatLoader');
371
+ loader.classList.remove('hidden');
372
+
373
+ try {
374
+ const response = await fetch('/api/admin/chat', {
375
+ method: 'POST',
376
+ headers: { 'Content-Type': 'application/json' },
377
+ body: JSON.stringify({ messages: chatHistory })
378
+ });
379
+
380
+ const data = await response.json();
381
+ loader.classList.add('hidden');
382
+
383
+ if (response.ok && data.success) {
384
+ appendChatMessage('model', data.response);
385
+ chatHistory.push({ role: 'model', content: data.response });
386
+ } else {
387
+ appendChatMessage('model', data.error || 'خطایی در تولید پاسخ پیش آمد. لطفاً اتصال سرور و کلید API را ارزیابی نمایید.');
388
+ }
389
+ } catch (err) {
390
+ loader.classList.add('hidden');
391
+ appendChatMessage('model', 'خطا در ارتباط با سرور رخ داده است: ' + err.message);
392
+ }
393
+ }
394
+
395
+ function appendChatMessage(role, content) {
396
+ const container = document.getElementById('chatMessages');
397
+
398
+ let messageHtml = '';
399
+ if (role === 'user') {
400
+ messageHtml = `
401
+ <div class="flex justify-end gap-2.5 max-w-[85%] mr-auto">
402
+ <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">
403
+ ${content}
404
+ </div>
405
+ </div>
406
+ `;
407
+ } else {
408
+ messageHtml = `
409
+ <div class="flex gap-2.5 max-w-[85%]">
410
+ <div class="w-7 h-7 rounded-full bg-cafeGold/10 border border-cafeGold/30 flex items-center justify-center flex-shrink-0">
411
+ <svg class="w-4 h-4 text-cafeGold" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
412
+ <circle cx="12" cy="12" r="10"/>
413
+ <path d="M12 8v4l3 3"/>
414
+ </svg>
415
+ </div>
416
+ <div class="bg-cafeDark/60 border border-cafeBorder text-zinc-200 text-xs rounded-2xl rounded-tr-none px-3.5 py-2.5 leading-relaxed">
417
+ ${content}
418
+ </div>
419
+ </div>
420
+ `;
421
+ }
422
+
423
+ container.insertAdjacentHTML('beforeend', messageHtml);
424
+ // اسکرول اتوماتیک به انتهای چت باکس
425
+ container.scrollTop = container.scrollHeight;
426
+ }
427
+
428
+
429
+ // --- بارگذاری تصویر منو و ویرایش هوشمند منو ---
430
+
431
+ async function uploadMenuFile(e) {
432
+ const file = e.target.files[0];
433
+ if (!file) return;
434
+
435
+ const loader = document.getElementById('uploadLoader');
436
+ const editorContainer = document.getElementById('menuEditorContainer');
437
+
438
+ loader.classList.remove('hidden');
439
+ editorContainer.classList.add('hidden');
440
+
441
+ const formData = new FormData();
442
+ formData.append('file', file);
443
+
444
+ try {
445
+ const response = await fetch('/api/admin/extract_menu', {
446
+ method: 'POST',
447
+ body: formData
448
+ });
449
+
450
+ const data = await response.json();
451
+ loader.classList.add('hidden');
452
+
453
+ if (response.ok && data.success) {
454
+ renderMenuEditor(data.extracted_menu);
455
+ editorContainer.classList.remove('hidden');
456
+ } else {
457
+ alert(data.error || 'استخراج منو ناموفق بود.');
458
+ }
459
+ } catch (err) {
460
+ loader.classList.add('hidden');
461
+ alert('خطا در بارگذاری فایل: ' + err.message);
462
+ }
463
+ }
464
+
465
+ function renderMenuEditor(menuItems) {
466
+ const tbody = document.getElementById('menuEditorTableBody');
467
+ tbody.innerHTML = '';
468
+
469
+ menuItems.forEach((item, index) => {
470
+ const row = `
471
+ <tr data-index="${index}" class="hover:bg-cafeCard/40">
472
+ <td class="px-2 py-2">
473
+ <input type="text" class="menu-name w-full bg-cafeCard border border-cafeBorder rounded px-2 py-1 text-zinc-200 focus:border-cafeGold/40 focus:outline-none" value="${item.name || ''}">
474
+ </td>
475
+ <td class="px-2 py-2">
476
+ <input type="text" class="menu-desc w-full bg-cafeCard border border-cafeBorder rounded px-2 py-1 text-zinc-200 focus:border-cafeGold/40 focus:outline-none" value="${item.description || ''}">
477
+ </td>
478
+ <td class="px-2 py-2">
479
+ <input type="text" class="menu-price w-full bg-cafeCard border border-cafeBorder rounded px-2 py-1 text-zinc-200 focus:border-cafeGold/40 focus:outline-none" value="${item.price || ''}">
480
+ </td>
481
+ <td class="px-2 py-2 text-center">
482
+ <button onclick="removeMenuRow(this)" class="p-1 hover:text-rose-500 text-zinc-500 transition-colors">
483
+ <svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
484
+ <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" />
485
+ </svg>
486
+ </button>
487
+ </td>
488
+ </tr>
489
+ `;
490
+ tbody.insertAdjacentHTML('beforeend', row);
491
+ });
492
+ }
493
+
494
+ function addEmptyMenuRow() {
495
+ const tbody = document.getElementById('menuEditorTableBody');
496
+ const row = `
497
+ <tr class="hover:bg-cafeCard/40">
498
+ <td class="px-2 py-2">
499
+ <input type="text" class="menu-name w-full bg-cafeCard border border-cafeBorder rounded px-2 py-1 text-zinc-200 focus:border-cafeGold/40 focus:outline-none" placeholder="مثال: لاته">
500
+ </td>
501
+ <td class="px-2 py-2">
502
+ <input type="text" class="menu-desc w-full bg-cafeCard border border-cafeBorder rounded px-2 py-1 text-zinc-200 focus:border-cafeGold/40 focus:outline-none" placeholder="شیر داغ، قهوه...">
503
+ </td>
504
+ <td class="px-2 py-2">
505
+ <input type="text" class="menu-price w-full bg-cafeCard border border-cafeBorder rounded px-2 py-1 text-zinc-200 focus:border-cafeGold/40 focus:outline-none" placeholder="۷۰,۰۰۰">
506
+ </td>
507
+ <td class="px-2 py-2 text-center">
508
+ <button onclick="removeMenuRow(this)" class="p-1 hover:text-rose-500 text-zinc-500 transition-colors">
509
+ <svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
510
+ <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" />
511
+ </svg>
512
+ </button>
513
+ </td>
514
+ </tr>
515
+ `;
516
+ tbody.insertAdjacentHTML('beforeend', row);
517
+ }
518
+
519
+ function removeMenuRow(btn) {
520
+ btn.closest('tr').remove();
521
+ }
522
+
523
+ async function saveAndPublishMenu() {
524
+ const tbody = document.getElementById('menuEditorTableBody');
525
+ const rows = tbody.querySelectorAll('tr');
526
+ const updatedMenu = [];
527
+
528
+ rows.forEach(row => {
529
+ const name = row.querySelector('.menu-name').value.trim();
530
+ const description = row.querySelector('.menu-desc').value.trim();
531
+ const price = row.querySelector('.menu-price').value.trim();
532
+
533
+ if (name) {
534
+ updatedMenu.push({
535
+ name: name,
536
+ description: description,
537
+ price: price,
538
+ available: true // به طور پیش‌فرض آیتم‌های جدید را موجود ثبت می‌کنیم
539
+ });
540
+ }
541
+ });
542
+
543
+ if (updatedMenu.length === 0) {
544
+ alert("امکان انتشار منوی خالی وجود ندارد. حداقل یک سطر با نام معتبر ثبت کنید.");
545
+ return;
546
+ }
547
+
548
+ try {
549
+ const response = await fetch('/api/admin/save_menu', {
550
+ method: 'POST',
551
+ headers: { 'Content-Type': 'application/json' },
552
+ body: JSON.stringify({ menu: updatedMenu })
553
+ });
554
+
555
+ const data = await response.json();
556
+ if (response.ok && data.success) {
557
+ alert("منوی جدید ثبت و در لحظه برای تمامی مشتریان و دستیار نیلا فعال شد!");
558
+ document.getElementById('menuEditorContainer').classList.add('hidden');
559
+ // به نیلا در گفتگو اطلاع می‌دهیم منو تغییر کرده است
560
+ appendChatMessage('model', 'منوی جدید سیستم با موفقیت به سیستم مرکزی فرستاده و اعمال شد. از این پس منوی مشتریان را از روی پایگاه‌داده جدید پردازش خواهم کرد.');
561
+ } else {
562
+ alert(data.error || 'خطا در ثبت منو.');
563
+ }
564
+ } catch (err) {
565
+ alert('خطای ارتباط با سرور: ' + err.message);
566
+ }
567
+ }
568
+ </script>
569
+ </body>
570
+ </html>