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>
|
<span class="nav-text" x-text="lang === 'ar' ? 'لوحة المشرف العام' : 'Super Admin'"></span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button class="nav-item" :class="{ 'active': activeDashboardTab === 'whatsapp' }" @click="activeDashboardTab = 'whatsapp'" id="nav-whatsapp-btn">
|
<button class="nav-item" :class="{ 'active': activeDashboardTab === 'whatsapp' }" @click="activeDashboardTab = 'whatsapp'; fetchMetaSessions()" id="nav-whatsapp-btn">
|
||||||
<span>📱</span> <span x-text="lang === 'ar' ? 'اتصال الواتساب' : 'WhatsApp Connection'"></span>
|
<span>📱</span> <span x-text="lang === 'ar' ? 'قنوات الاتصال' : 'Communication Channels'"></span>
|
||||||
</button>
|
</button>
|
||||||
<button class="nav-item" :class="{ 'active': activeDashboardTab === 'billing' }" @click="activeDashboardTab = 'billing'; fetchPlans()" id="nav-billing-btn">
|
<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>
|
<span>💳</span> <span x-text="lang === 'ar' ? 'الباقات والاشتراكات' : 'Billing & Plans'"></span>
|
||||||
@@ -897,7 +897,15 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="panel" x-show="activeDashboardTab === 'whatsapp'" id="panel-whatsapp">
|
<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' : ''">
|
<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>
|
<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;">
|
<div style="display: flex; gap: 0.5rem; align-items: center;">
|
||||||
@@ -1058,6 +1066,112 @@
|
|||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</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>
|
</div>
|
||||||
|
|
||||||
<!-- Panel: Billing & Plans -->
|
<!-- Panel: Billing & Plans -->
|
||||||
@@ -1821,6 +1935,14 @@
|
|||||||
whatsappSessions: [],
|
whatsappSessions: [],
|
||||||
whatsappMaxSessions: 1,
|
whatsappMaxSessions: 1,
|
||||||
newSessionName: '',
|
newSessionName: '',
|
||||||
|
metaSessions: [],
|
||||||
|
newMetaSession: {
|
||||||
|
channel_type: 'messenger',
|
||||||
|
page_id: '',
|
||||||
|
page_name: '',
|
||||||
|
page_access_token: ''
|
||||||
|
},
|
||||||
|
showMetaConnectModal: false,
|
||||||
staff: [],
|
staff: [],
|
||||||
showAddStaffModal: false,
|
showAddStaffModal: false,
|
||||||
staffForm: {
|
staffForm: {
|
||||||
@@ -2032,6 +2154,7 @@
|
|||||||
initializeDashboard() {
|
initializeDashboard() {
|
||||||
this.fetchWhatsappSessions();
|
this.fetchWhatsappSessions();
|
||||||
this.fetchWhatsappStatus();
|
this.fetchWhatsappStatus();
|
||||||
|
this.fetchMetaSessions();
|
||||||
this.fetchSallaStatus();
|
this.fetchSallaStatus();
|
||||||
this.fetchWooCommerceStatus();
|
this.fetchWooCommerceStatus();
|
||||||
// Set up persistent background status check
|
// Set up persistent background status check
|
||||||
@@ -2195,6 +2318,77 @@
|
|||||||
this.actionLoading = false;
|
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() {
|
async fetchWhatsappSessions() {
|
||||||
if (!this.token) return;
|
if (!this.token) return;
|
||||||
try {
|
try {
|
||||||
|
|||||||
Reference in New Issue
Block a user