{"repo": "abawe444/carsspacebot", "files": {"public/js/setup.js": {"c9702418341d3f44467d62c6cfbb641187770d98": {"t": 1786067877.6377082, "n": 11598, "h": "213ee605d882fdbb", "c": "let currentStep = 1;\nconst maxStep = 5;\n\nfunction showToast(message, type = 'info') {\n const toast = document.getElementById('toast');\n if (!toast) return;\n toast.textContent = message;\n toast.classList.remove('hidden');\n toast.style.background = type === 'error' ? '#b72626' : type === 'warning' ? '#a8670b' : '#1f6feb';\n setTimeout(() => toast.classList.add('hidden'), 2600);\n}\n\nasync function api(url, options = {}) {\n const response = await fetch(url, {\n headers: { 'Content-Type': 'application/json' },\n ...options\n });\n const data = await response.json().catch(() => ({}));\n if (!response.ok || data.success === false) {\n const error = new Error(data.message || data.error || 'فشل الطلب');\n error.status = response.status;\n error.statusText = response.statusText;\n error.data = data;\n error.details = data?.data || null;\n throw error;\n }\n return data;\n}\n\nfunction formatProviderErrorForUi(error) {\n const details = error?.details || {};\n const status = details.responseStatus || error?.status || '';\n const statusText = details.responseStatusText || error?.statusText || '';\n const rawError = details.error || error?.message || 'تعذر الاتصال بمزود الذكاء';\n const responseData = details.responseData ? JSON.stringify(details.responseData, null, 2) : 'null';\n const friendly = details.error_ar || error?.message || 'تعذر الاتصال بمزود الذكاء';\n\n return {\n friendly,\n full: `السبب: ${friendly}\nHTTP: ${status || '-'} ${statusText || ''}\nBackend: ${rawError}\nResponse: ${responseData}`\n };\n}\n\nfunction setStep(step) {\n currentStep = Math.min(maxStep, Math.max(1, step));\n\n for (let i = 1; i <= maxStep; i += 1) {\n const panel = document.getElementById(`step${i}`);\n panel?.classList.toggle('hidden-step', i !== currentStep);\n }\n\n document.querySelectorAll('.wiz-step').forEach((btn) => {\n btn.classList.toggle('active', Number(btn.getAttribute('data-step')) === currentStep);\n });\n\n document.getElementById('prevStepBtn').disabled = currentStep === 1;\n document.getElementById('nextStepBtn').textContent = currentStep === maxStep ? 'الانتقال للوحة' : 'التالي';\n}\n\nfunction setWhatsappStatus(status) {\n const badge = document.getElementById('setupWhatsappStatus');\n const text = document.getElementById('setupQrStatusText');\n const qrArea = document.getElementById('setupQrArea');\n\n const map = {\n connected: { label: 'متصل وجاهز للرد', cls: 'success' },\n qr: { label: 'بانتظار مسح QR', cls: 'warning' },\n reconnecting: { label: 'إعادة الاتصال', cls: 'warning' },\n disconnected: { label: 'غير متصل بواتساب', cls: 'danger' }\n };\n\n const item = map[status?.status] || map.disconnected;\n if (badge) {\n badge.textContent = item.label;\n badge.className = `status-pill ${item.cls}`;\n }\n if (text) text.textContent = item.label;\n\n if (!qrArea) return;\n if (status?.qr) {\n qrArea.innerHTML = `\"QR\"`;\n } else if (status?.status === 'connected') {\n qrArea.innerHTML = '
تم الربط بنجاح ✅
';\n } else {\n qrArea.innerHTML = '
بانتظار مسح QR
';\n }\n}\n\nfunction setProviderStatus(ok) {\n const badge = document.getElementById('setupProviderStatus');\n if (!badge) return;\n if (ok) {\n badge.textContent = 'تم الاتصال بمزود الذكاء بنجاح';\n badge.className = 'status-pill success';\n } else {\n badge.textContent = 'تعذر الاتصال بمزود الذكاء';\n badge.className = 'status-pill danger';\n }\n}\n\nfunction fillForm(formId, values = {}) {\n const form = document.getElementById(formId);\n if (!form) return;\n Object.entries(values).forEach(([key, value]) => {\n const el = form.querySelector(`[name=\"${key}\"]`);\n if (el && value !== undefined && value !== null) {\n el.value = value;\n }\n });\n}\n\nfunction serializeForm(formId) {\n const form = document.getElementById(formId);\n const payload = {};\n form.querySelectorAll('[name]').forEach((el) => {\n payload[el.name] = el.value;\n });\n return payload;\n}\n\nconst providerDefaults = {\n rules_only: { baseUrl: '', model: '' },\n openai: { baseUrl: 'https://api.openai.com/v1', model: 'gpt-4.1-mini' },\n openrouter: { baseUrl: 'https://openrouter.ai/api/v1', model: 'openai/gpt-4o-mini' },\n deepseek: { baseUrl: 'https://api.deepseek.com/v1', model: 'deepseek-chat' },\n grok: { baseUrl: 'https://api.x.ai/v1', model: 'grok-3-mini' },\n google: { baseUrl: 'https://generativelanguage.googleapis.com/v1beta/openai', model: 'gemini-2.5-flash' },\n custom_openai_compatible: { baseUrl: '', model: '' }\n};\n\nfunction onProviderChange() {\n const provider = document.getElementById('providerSelect').value;\n const defaults = providerDefaults[provider] || providerDefaults.rules_only;\n const baseEl = document.getElementById('providerBaseUrl');\n const modelEl = document.getElementById('providerModel');\n\n if (!baseEl.value) baseEl.value = defaults.baseUrl;\n if (!modelEl.value) modelEl.value = defaults.model;\n}\n\nasync function loadSetupData() {\n const { data } = await api('/api/setup/data');\n\n fillForm('setupCompanyForm', {\n company_name: data.company?.company_name || data.settings?.company_name,\n contact_number: data.company?.contact_number || data.settings?.company_contact_number,\n business_description: data.company?.business_description || data.settings?.company_field,\n general_manager: data.company?.general_manager || data.settings?.management_general_manager,\n company_responsible: data.company?.company_responsible || data.settings?.management_company_manager,\n center_manager: data.company?.center_manager || data.settings?.management_center_manager\n });\n\n fillForm('setupLocationsForm', {\n company_location_title: data.company?.company_location_title || data.settings?.location_company_name,\n company_location_url: data.company?.company_location_url || data.settings?.location_company_map_url,\n center_location_title: data.company?.center_location_title || data.settings?.location_center_name,\n center_location_url: data.company?.center_location_url || data.settings?.location_center_map_url\n });\n\n fillForm('setupProviderForm', {\n provider: data.provider?.provider || 'rules_only',\n baseUrl: data.provider?.base_url || '',\n model: data.provider?.model || '',\n temperature: data.provider?.temperature || 0.3,\n maxOutputTokens: data.provider?.max_output_tokens || 250,\n aiMode: data.provider?.ai_mode || 'rules_first',\n enabled: data.provider?.enabled ? 'true' : 'false'\n });\n\n fillForm('setupAssistantForm', {\n assistant_name: data.settings?.assistant_name,\n assistant_tone: data.settings?.assistant_tone,\n assistant_prompt: data.settings?.assistant_prompt\n });\n\n setWhatsappStatus(data.whatsapp || { status: 'disconnected' });\n}\n\nasync function saveCompany(e) {\n e.preventDefault();\n const payload = serializeForm('setupCompanyForm');\n await api('/api/setup/company', { method: 'POST', body: JSON.stringify(payload) });\n showToast('تم حفظ بيانات الشركة');\n}\n\nasync function saveLocations(e) {\n e.preventDefault();\n const payload = serializeForm('setupLocationsForm');\n await api('/api/setup/locations', { method: 'POST', body: JSON.stringify(payload) });\n showToast('تم حفظ بيانات المواقع');\n}\n\nasync function saveProvider(e) {\n e.preventDefault();\n const payload = serializeForm('setupProviderForm');\n payload.enabled = payload.enabled === 'true';\n await api('/api/setup/provider', { method: 'POST', body: JSON.stringify(payload) });\n showToast('تم حفظ إعدادات مزود الذكاء');\n}\n\nasync function testProvider() {\n const payload = serializeForm('setupProviderForm');\n const apiKeyInput = document.querySelector('#setupProviderForm [name=\"apiKey\"]');\n const rawApiKey = String(apiKeyInput?.value || '').trim();\n const isMasked = /\\*{3,}/.test(rawApiKey);\n const apiKey = isMasked ? '' : rawApiKey;\n const useSavedKey = !apiKey || isMasked;\n const requestPayload = {\n provider: payload.provider,\n baseUrl: payload.baseUrl,\n model: payload.model,\n apiKey,\n useSavedKey,\n temperature: payload.temperature,\n maxOutputTokens: payload.maxOutputTokens,\n aiMode: payload.aiMode\n };\n console.debug('Provider test payload:', {\n provider: requestPayload.provider,\n baseUrl: requestPayload.baseUrl,\n model: requestPayload.model,\n hasApiKey: !!requestPayload.apiKey,\n useSavedKey: requestPayload.useSavedKey,\n temperature: requestPayload.temperature,\n maxOutputTokens: requestPayload.maxOutputTokens\n });\n const output = document.getElementById('providerTestResult');\n output.textContent = 'جارٍ اختبار الاتصال...';\n\n try {\n const result = await api('/api/provider/test', {\n method: 'POST',\n body: JSON.stringify(requestPayload)\n });\n output.innerHTML = `${result.message}
الرد: ${(result.data?.text || '').replace(/\\n/g, '
')}`;\n setProviderStatus(true);\n showToast('تم الاتصال بمزود الذكاء بنجاح');\n } catch (error) {\n const formatted = formatProviderErrorForUi(error);\n output.innerHTML = `فشل اختبار مزود الذكاء
${formatted.full}
`;\n setProviderStatus(false);\n showToast(formatted.friendly, 'error');\n }\n}\n\nasync function saveAssistant(e) {\n e.preventDefault();\n const payload = serializeForm('setupAssistantForm');\n await api('/api/setup/assistant', { method: 'POST', body: JSON.stringify(payload) });\n showToast('تم حفظ شخصية المساعد');\n}\n\nasync function finishSetup() {\n await api('/api/setup/complete', { method: 'POST' });\n showToast('تم إنهاء الإعداد بنجاح');\n setTimeout(() => {\n window.location.href = '/';\n }, 600);\n}\n\nfunction bindEvents() {\n document.querySelectorAll('.wiz-step').forEach((btn) => {\n btn.addEventListener('click', () => setStep(Number(btn.getAttribute('data-step'))));\n });\n\n document.getElementById('prevStepBtn')?.addEventListener('click', () => setStep(currentStep - 1));\n document.getElementById('nextStepBtn')?.addEventListener('click', () => {\n if (currentStep === maxStep) {\n window.location.href = '/';\n return;\n }\n setStep(currentStep + 1);\n });\n\n document.getElementById('providerSelect')?.addEventListener('change', onProviderChange);\n document.getElementById('setupCompanyForm')?.addEventListener('submit', saveCompany);\n document.getElementById('setupLocationsForm')?.addEventListener('submit', saveLocations);\n document.getElementById('setupProviderForm')?.addEventListener('submit', saveProvider);\n document.getElementById('setupAssistantForm')?.addEventListener('submit', saveAssistant);\n document.getElementById('testProviderBtn')?.addEventListener('click', testProvider);\n document.getElementById('finishSetupBtn')?.addEventListener('click', finishSetup);\n\n document.getElementById('setupReconnectBtn')?.addEventListener('click', async () => {\n await api('/api/connection/restart', { method: 'POST' });\n showToast('جارٍ إعادة الاتصال بواتساب');\n });\n\n document.getElementById('setupResetSessionBtn')?.addEventListener('click', async () => {\n if (!confirm('هل تريد حذف الجلسة الحالية؟')) return;\n await api('/api/session/reset', { method: 'POST' });\n showToast('تم حذف الجلسة');\n });\n}\n\nfunction initSocket() {\n const socket = io();\n socket.on('whatsapp:status', (status) => {\n setWhatsappStatus(status);\n });\n}\n\ndocument.addEventListener('DOMContentLoaded', async () => {\n bindEvents();\n setStep(1);\n initSocket();\n try {\n await loadSetupData();\n } catch (error) {\n showToast(error.message, 'error');\n }\n});\n"}}}}