Deploy: 2026-05-25 00:33:34
This commit is contained in:
@@ -765,8 +765,8 @@
|
||||
<span class="nav-text" x-text="lang === 'ar' ? 'لوحة المشرف العام' : 'Super Admin'"></span>
|
||||
</button>
|
||||
|
||||
<button class="nav-item" :class="{ 'active': activeDashboardTab === 'whatsapp' }" @click="activeDashboardTab = 'whatsapp'" id="nav-whatsapp-btn">
|
||||
<span>📱</span> <span x-text="lang === 'ar' ? 'اتصال الواتساب' : 'WhatsApp Connection'"></span>
|
||||
<button class="nav-item" :class="{ 'active': activeDashboardTab === 'whatsapp' }" @click="activeDashboardTab = 'whatsapp'; fetchMetaSessions()" id="nav-whatsapp-btn">
|
||||
<span>📱</span> <span x-text="lang === 'ar' ? 'قنوات الاتصال' : 'Communication Channels'"></span>
|
||||
</button>
|
||||
<button class="nav-item" :class="{ 'active': activeDashboardTab === 'billing' }" @click="activeDashboardTab = 'billing'; fetchPlans()" id="nav-billing-btn">
|
||||
<span>💳</span> <span x-text="lang === 'ar' ? 'الباقات والاشتراكات' : 'Billing & Plans'"></span>
|
||||
@@ -897,8 +897,16 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel" x-show="activeDashboardTab === 'whatsapp'" id="panel-whatsapp">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 1.5rem;" :style="lang === 'ar' ? 'flex-direction: row-reverse' : ''">
|
||||
<div class="panel" x-show="activeDashboardTab === 'whatsapp'" id="panel-whatsapp" x-data="{ channelTab: 'whatsapp' }">
|
||||
<!-- Sub-tabs for Channels -->
|
||||
<div style="display: flex; gap: 1rem; border-bottom: 1px solid var(--card-border); margin-bottom: 1.5rem;" :style="lang === 'ar' ? 'flex-direction: row-reverse' : ''">
|
||||
<button class="tab-btn" :class="{ 'active': channelTab === 'whatsapp' }" @click="channelTab = 'whatsapp'" x-text="lang === 'ar' ? 'واتساب' : 'WhatsApp'"></button>
|
||||
<button class="tab-btn" :class="{ 'active': channelTab === 'messenger' }" @click="channelTab = 'messenger'; fetchMetaSessions()" x-text="lang === 'ar' ? 'فيسبوك ماسنجر' : 'Facebook Messenger'"></button>
|
||||
<button class="tab-btn" :class="{ 'active': channelTab === 'instagram' }" @click="channelTab = 'instagram'; fetchMetaSessions()" x-text="lang === 'ar' ? 'إنستغرام' : 'Instagram'"></button>
|
||||
</div>
|
||||
|
||||
<div x-show="channelTab === 'whatsapp'">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 1.5rem;" :style="lang === 'ar' ? 'flex-direction: row-reverse' : ''">
|
||||
<h2 style="font-size: 1.4rem; margin: 0;" x-text="lang === 'ar' ? 'إدارة قنوات اتصال واتساب' : 'WhatsApp Session Management'"></h2>
|
||||
<div style="display: flex; gap: 0.5rem; align-items: center;">
|
||||
<span class="badge badge-warning" x-show="whatsappSessions.length >= whatsappMaxSessions" x-text="lang === 'ar' ? 'تم الوصول للحد الأقصى (' + whatsappSessions.length + '/' + whatsappMaxSessions + ')' : 'Limit Reached (' + whatsappSessions.length + '/' + whatsappMaxSessions + ')'"></span>
|
||||
@@ -1058,6 +1066,112 @@
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- End of WhatsApp Sub-tab -->
|
||||
|
||||
<!-- Facebook Messenger Sub-tab -->
|
||||
<div x-show="channelTab === 'messenger'">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 1.5rem;" :style="lang === 'ar' ? 'flex-direction: row-reverse' : ''">
|
||||
<h2 style="font-size: 1.4rem; margin: 0;" x-text="lang === 'ar' ? 'ربط فيسبوك ماسنجر' : 'Facebook Messenger Integration'"></h2>
|
||||
<button @click="openMetaConnectModal('messenger')" class="btn btn-primary" style="padding: 0.5rem 1rem; font-size: 0.85rem;">
|
||||
<span x-text="lang === 'ar' ? '+ ربط صفحة جديدة' : '+ Connect New Page'"></span>
|
||||
</button>
|
||||
</div>
|
||||
<p class="text-muted" style="margin-bottom: 1.5rem; font-size: 0.9rem;" x-text="lang === 'ar' ? 'قم بربط صفحات فيسبوك الخاصة بك لتفعيل الردود التلقائية وروبوت المحادثة بالذكاء الاصطناعي لرسائل العملاء.' : 'Connect your Facebook Pages to enable AI automated replies for customer messages.'"></p>
|
||||
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 1.5rem; margin-bottom: 2rem;">
|
||||
<template x-for="session in metaSessions.filter(s => s.channel_type === 'messenger')" :key="session.id">
|
||||
<div class="status-box" style="margin: 0; padding: 1.5rem; display: flex; flex-direction: column; justify-content: space-between; height: 100%; border: 1px solid var(--card-border); background: var(--card-bg); border-radius: 16px;">
|
||||
<div>
|
||||
<div style="display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 1rem;" :style="lang === 'ar' ? 'flex-direction: row-reverse' : ''">
|
||||
<div>
|
||||
<h3 style="font-size: 1.1rem; font-weight: 700;" x-text="session.page_name"></h3>
|
||||
<span style="font-family: monospace; font-size: 0.8rem; color: var(--text-muted);" x-text="'ID: ' + session.page_id"></span>
|
||||
</div>
|
||||
<div class="status-badge badge-connected" style="margin: 0; font-size: 0.75rem; padding: 0.2rem 0.5rem; background: rgba(16, 185, 129, 0.12); color: #34d399; border: 1px solid rgba(16, 185, 129, 0.25);">
|
||||
<span x-text="session.status"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex; justify-content: flex-end;">
|
||||
<button @click="deleteMetaSession(session.id)" class="btn btn-danger" style="padding: 0.4rem 0.8rem; font-size: 0.8rem;" :disabled="actionLoading">
|
||||
<span x-text="lang === 'ar' ? 'حذف / قطع الاتصال' : 'Disconnect / Delete'"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template x-if="metaSessions.filter(s => s.channel_type === 'messenger').length === 0">
|
||||
<div style="grid-column: 1 / -1; text-align: center; padding: 3rem; color: var(--text-muted);" x-text="lang === 'ar' ? 'لا توجد صفحات فيسبوك مرتبطة حالياً. اضغط على الزر أعلاه للربط.' : 'No Facebook pages connected. Click the button above to link one.'"></div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Instagram Business Sub-tab -->
|
||||
<div x-show="channelTab === 'instagram'">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 1.5rem;" :style="lang === 'ar' ? 'flex-direction: row-reverse' : ''">
|
||||
<h2 style="font-size: 1.4rem; margin: 0;" x-text="lang === 'ar' ? 'ربط حساب إنستغرام للأعمال' : 'Instagram Business Integration'"></h2>
|
||||
<button @click="openMetaConnectModal('instagram')" class="btn btn-primary" style="padding: 0.5rem 1rem; font-size: 0.85rem;">
|
||||
<span x-text="lang === 'ar' ? '+ ربط حساب جديد' : '+ Connect New Profile'"></span>
|
||||
</button>
|
||||
</div>
|
||||
<p class="text-muted" style="margin-bottom: 1.5rem; font-size: 0.9rem;" x-text="lang === 'ar' ? 'قم بربط حسابات إنستغرام للأعمال الخاصة بك لتفعيل روبوت المحادثة المخصص لرسائل المتابعين والعملاء.' : 'Connect your Instagram Business accounts to enable automated chatbot replies for customer direct messages.'"></p>
|
||||
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 1.5rem; margin-bottom: 2rem;">
|
||||
<template x-for="session in metaSessions.filter(s => s.channel_type === 'instagram')" :key="session.id">
|
||||
<div class="status-box" style="margin: 0; padding: 1.5rem; display: flex; flex-direction: column; justify-content: space-between; height: 100%; border: 1px solid var(--card-border); background: var(--card-bg); border-radius: 16px;">
|
||||
<div>
|
||||
<div style="display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 1rem;" :style="lang === 'ar' ? 'flex-direction: row-reverse' : ''">
|
||||
<div>
|
||||
<h3 style="font-size: 1.1rem; font-weight: 700;" x-text="session.page_name"></h3>
|
||||
<span style="font-family: monospace; font-size: 0.8rem; color: var(--text-muted);" x-text="'ID: ' + session.page_id"></span>
|
||||
</div>
|
||||
<div class="status-badge badge-connected" style="margin: 0; font-size: 0.75rem; padding: 0.2rem 0.5rem; background: rgba(16, 185, 129, 0.12); color: #34d399; border: 1px solid rgba(16, 185, 129, 0.25);">
|
||||
<span x-text="session.status"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex; justify-content: flex-end;">
|
||||
<button @click="deleteMetaSession(session.id)" class="btn btn-danger" style="padding: 0.4rem 0.8rem; font-size: 0.8rem;" :disabled="actionLoading">
|
||||
<span x-text="lang === 'ar' ? 'حذف / قطع الاتصال' : 'Disconnect / Delete'"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template x-if="metaSessions.filter(s => s.channel_type === 'instagram').length === 0">
|
||||
<div style="grid-column: 1 / -1; text-align: center; padding: 3rem; color: var(--text-muted);" x-text="lang === 'ar' ? 'لا توجد حسابات إنستغرام مرتبطة حالياً. اضغط على الزر أعلاه للربط.' : 'No Instagram profiles connected. Click the button above to link one.'"></div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Meta Connection Modal -->
|
||||
<div class="modal-overlay" x-show="showMetaConnectModal" style="display: none; z-index: 2000;">
|
||||
<div class="modal-card">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title" x-text="newMetaSession.channel_type === 'messenger' ? (lang === 'ar' ? 'ربط صفحة فيسبوك' : 'Link Facebook Page') : (lang === 'ar' ? 'ربط حساب إنستغرام' : 'Link Instagram Profile')"></h3>
|
||||
<button class="modal-close" @click="showMetaConnectModal = false">×</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label class="form-label" x-text="lang === 'ar' ? 'الاسم' : 'Name'"></label>
|
||||
<input type="text" x-model="newMetaSession.page_name" class="form-input" :placeholder="lang === 'ar' ? 'اسم الصفحة أو الحساب' : 'Page or Profile Name'">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label" x-text="lang === 'ar' ? 'المعرّف (ID)' : 'ID'"></label>
|
||||
<input type="text" x-model="newMetaSession.page_id" class="form-input" :placeholder="lang === 'ar' ? 'معرّف الصفحة أو الحساب' : 'Page or Account ID'">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label" x-text="lang === 'ar' ? 'رمز الوصول (Access Token)' : 'Access Token'"></label>
|
||||
<input type="text" x-model="newMetaSession.page_access_token" class="form-input" :placeholder="lang === 'ar' ? 'رمز الوصول للصفحة' : 'Page Access Token'">
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer" style="display: flex; justify-content: flex-end; gap: 1rem;">
|
||||
<button class="btn btn-secondary" style="width: auto;" @click="showMetaConnectModal = false" x-text="lang === 'ar' ? 'إلغاء' : 'Cancel'"></button>
|
||||
<button class="btn btn-primary" style="width: auto;" @click="connectMetaSession()" :disabled="actionLoading">
|
||||
<span x-show="!actionLoading" x-text="lang === 'ar' ? 'ربط وتفعيل' : 'Connect & Enable'"></span>
|
||||
<span x-show="actionLoading" class="spinner"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Panel: Billing & Plans -->
|
||||
@@ -1821,6 +1935,14 @@
|
||||
whatsappSessions: [],
|
||||
whatsappMaxSessions: 1,
|
||||
newSessionName: '',
|
||||
metaSessions: [],
|
||||
newMetaSession: {
|
||||
channel_type: 'messenger',
|
||||
page_id: '',
|
||||
page_name: '',
|
||||
page_access_token: ''
|
||||
},
|
||||
showMetaConnectModal: false,
|
||||
staff: [],
|
||||
showAddStaffModal: false,
|
||||
staffForm: {
|
||||
@@ -2032,6 +2154,7 @@
|
||||
initializeDashboard() {
|
||||
this.fetchWhatsappSessions();
|
||||
this.fetchWhatsappStatus();
|
||||
this.fetchMetaSessions();
|
||||
this.fetchSallaStatus();
|
||||
this.fetchWooCommerceStatus();
|
||||
// Set up persistent background status check
|
||||
@@ -2195,6 +2318,77 @@
|
||||
this.actionLoading = false;
|
||||
}
|
||||
},
|
||||
async fetchMetaSessions() {
|
||||
if (!this.token) return;
|
||||
try {
|
||||
const response = await fetch('/api/meta/sessions', {
|
||||
headers: { 'Authorization': `Bearer ${this.token}` }
|
||||
});
|
||||
const data = await response.json();
|
||||
if (response.ok && data.status === 'success') {
|
||||
this.metaSessions = data.data || [];
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Failed to fetch meta sessions', err);
|
||||
}
|
||||
},
|
||||
openMetaConnectModal(type) {
|
||||
this.newMetaSession = {
|
||||
channel_type: type,
|
||||
page_id: '',
|
||||
page_name: '',
|
||||
page_access_token: ''
|
||||
};
|
||||
this.showMetaConnectModal = true;
|
||||
},
|
||||
async connectMetaSession() {
|
||||
this.actionLoading = true;
|
||||
try {
|
||||
const response = await fetch('/api/meta/sessions/connect', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${this.token}`
|
||||
},
|
||||
body: JSON.stringify(this.newMetaSession)
|
||||
});
|
||||
const data = await response.json();
|
||||
if (response.ok && data.status === 'success') {
|
||||
this.showMetaConnectModal = false;
|
||||
this.fetchMetaSessions();
|
||||
} else {
|
||||
alert(data.message || 'Connection failed');
|
||||
}
|
||||
} catch (err) {
|
||||
alert('Network error connecting Meta session');
|
||||
} finally {
|
||||
this.actionLoading = false;
|
||||
}
|
||||
},
|
||||
async deleteMetaSession(id) {
|
||||
if (!confirm(this.lang === 'ar' ? 'هل أنت متأكد من حذف هذه القناة؟' : 'Are you sure you want to disconnect this channel?')) {
|
||||
return;
|
||||
}
|
||||
this.actionLoading = true;
|
||||
try {
|
||||
const response = await fetch('/api/meta/sessions', {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${this.token}`
|
||||
},
|
||||
body: JSON.stringify({ session_id: id })
|
||||
});
|
||||
const data = await response.json();
|
||||
if (response.ok && data.status === 'success') {
|
||||
this.fetchMetaSessions();
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Failed to delete meta session', err);
|
||||
} finally {
|
||||
this.actionLoading = false;
|
||||
}
|
||||
},
|
||||
async fetchWhatsappSessions() {
|
||||
if (!this.token) return;
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user