| |
| |
| |
| |
|
|
|
|
| (global => {
|
| 'use strict';
|
|
|
| const state = global.FritreeRotationState;
|
| let currentMetricsPage = 1;
|
| const METRICS_ITEMS_PER_PAGE = 8;
|
|
|
| |
| |
|
|
| const buildPerformanceLayout = () => {
|
| const page = document.getElementById('xpoqh5yufi');
|
| if (!page) return;
|
| if (page.querySelector('#fj8dnuc75c')) return;
|
|
|
| page.innerHTML = `
|
| <div id="fj8dnuc75c" class="zcjbe1otmg" style="display: flex; flex-direction: column; gap: var(--space-md); direction: rtl; text-align: right; width: 100%; box-sizing: border-box;">
|
|
|
| <!-- بطاقات مؤشرات الأداء الرئيسية KPIs -->
|
| <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(clamp(130px, 12vw, 200px), 1fr)); gap: 10px; width: 100%;">
|
| <div class="r6wq5imop6" style="padding: clamp(12px, 1.2vw, 16px); border: 1px solid var(--border); flex-direction: row; justify-content: space-between;">
|
| <div style="text-align: right;">
|
| <div class="h7ren96m5v" style="font-size: 10.5px; margin-bottom: 2px;">
|
| <i class="fa-solid fa-play" style="color: var(--primary);"></i> <span>إجمالي النشر</span>
|
| </div>
|
| <strong id="ylohpr45dl" class="kisn3ao2tz" style="font-size: 20px; font-family: var(--font-code); line-height: 1;">
|
| 0
|
| </strong>
|
| </div>
|
| <div style="width: 36px; height: 36px; border-radius: var(--radius-md); background: var(--primary-light); color: var(--primary); display: flex; align-items: center; justify-content: center; font-size: 15px; flex-shrink: 0;">
|
| <i class="fa-solid fa-play"></i>
|
| </div>
|
| </div>
|
|
|
| <div class="r6wq5imop6" style="padding: clamp(12px, 1.2vw, 16px); border: 1px solid var(--border); flex-direction: row; justify-content: space-between;">
|
| <div style="text-align: right;">
|
| <div class="h7ren96m5v" style="font-size: 10.5px; margin-bottom: 2px;">
|
| <i class="fa-solid fa-circle-check" style="color: var(--success);"></i> <span>منشورات ناجحة</span>
|
| </div>
|
| <strong id="md8oymcc5c" class="kisn3ao2tz" style="font-size: 20px; font-family: var(--font-code); color: var(--success); line-height: 1;">
|
| 0
|
| </strong>
|
| </div>
|
| <div style="width: 36px; height: 36px; border-radius: var(--radius-md); background: var(--success-light); color: var(--success); display: flex; align-items: center; justify-content: center; font-size: 15px; flex-shrink: 0;">
|
| <i class="fa-solid fa-circle-check"></i>
|
| </div>
|
| </div>
|
|
|
| <div class="r6wq5imop6" style="padding: clamp(12px, 1.2vw, 16px); border: 1px solid var(--border); flex-direction: row; justify-content: space-between;">
|
| <div style="text-align: right;">
|
| <div class="h7ren96m5v" style="font-size: 10.5px; margin-bottom: 2px;">
|
| <i class="fa-solid fa-hourglass-half" style="color: var(--warning);"></i> <span>معلقة للمراجعة</span>
|
| </div>
|
| <strong id="qoumr7z4ii" class="kisn3ao2tz" style="font-size: 20px; font-family: var(--font-code); color: var(--warning); line-height: 1;">
|
| 0
|
| </strong>
|
| </div>
|
| <div style="width: 36px; height: 36px; border-radius: var(--radius-md); background: var(--warning-light); color: var(--warning); display: flex; align-items: center; justify-content: center; font-size: 15px; flex-shrink: 0;">
|
| <i class="fa-solid fa-hourglass-half"></i>
|
| </div>
|
| </div>
|
|
|
| <div class="r6wq5imop6" style="padding: clamp(12px, 1.2vw, 16px); border: 1px solid var(--border); flex-direction: row; justify-content: space-between;">
|
| <div style="text-align: right;">
|
| <div class="h7ren96m5v" style="font-size: 10.5px; margin-bottom: 2px;">
|
| <i class="fa-solid fa-triangle-exclamation" style="color: var(--danger);"></i> <span>محاولات فشلت</span>
|
| </div>
|
| <strong id="s8t8cbmfne" class="kisn3ao2tz" style="font-size: 20px; font-family: var(--font-code); color: var(--danger); line-height: 1;">
|
| 0
|
| </strong>
|
| </div>
|
| <div style="width: 36px; height: 36px; border-radius: var(--radius-md); background: var(--danger-light); color: var(--danger); display: flex; align-items: center; justify-content: center; font-size: 15px; flex-shrink: 0;">
|
| <i class="fa-solid fa-triangle-exclamation"></i>
|
| </div>
|
| </div>
|
| </div>
|
|
|
| <!-- جدول تقييم الأداء التفصيلي -->
|
| <div class="d5tp7way8h" style="margin: 0; padding: clamp(12px, 1.4vw, 18px); border: 1px solid var(--border); border-radius: var(--radius-lg); background: var(--bg-card); box-sizing: border-box;">
|
| <div class="cm41ch7urz" style="margin-bottom: 10px; border-bottom: 1px solid var(--border); padding-bottom: 8px; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 6px;">
|
| <span style="font-size: 13.5px; font-weight: 800; display: flex; align-items: center; gap: 6px; color: var(--text-main);">
|
| <i class="fa-solid fa-chart-simple" style="color: var(--primary);"></i>
|
| <span>قياس أداء وكفاءة منشورات التدوير</span>
|
| </span>
|
| <span style="font-size: 10.5px; font-weight: 600; color: var(--text-muted);">
|
| <i class="fa-solid fa-hand-pointer"></i> <span>اضغط على أي منشور لعرض سجل إرساله التفصيلي</span>
|
| </span>
|
| </div>
|
|
|
| <div class="diktqr0h64" style="max-height: 440px;">
|
| <table style="width: 100%; border-collapse: collapse; direction: rtl; text-align: right;">
|
| <thead>
|
| <tr>
|
| <th style="width: 40%; padding: 10px 12px; text-align: right;"><i class="fa-solid fa-file-signature"></i> <span>عنوان المنشور</span></th>
|
| <th style="width: 15%; padding: 10px; text-align: center;"><i class="fa-solid fa-play"></i> <span>مرات التشغيل</span></th>
|
| <th style="width: 15%; padding: 10px; text-align: center;"><i class="fa-solid fa-circle-check"></i> <span>ناجح</span></th>
|
| <th style="width: 15%; padding: 10px; text-align: center;"><i class="fa-solid fa-hourglass-half"></i> <span>معلق</span></th>
|
| <th style="width: 15%; padding: 10px; text-align: center;"><i class="fa-solid fa-triangle-exclamation"></i> <span>فشل</span></th>
|
| </tr>
|
| </thead>
|
| <tbody id="i4jg5y3ylx"></tbody>
|
| </table>
|
| </div>
|
|
|
| <div id="du4l2rjkr6" style="display: flex; justify-content: center; margin-top: 14px; align-items: center; gap: 6px; flex-wrap: wrap;"></div>
|
| </div>
|
| </div>
|
| `;
|
| };
|
|
|
| |
| |
|
|
| const appendTraceModalLayout = () => {
|
| let modal = document.getElementById('sg405ywfqm');
|
| if (modal) return;
|
|
|
| modal = document.createElement('div');
|
| modal.className = 'cpzxome5dd';
|
| modal.id = 'sg405ywfqm';
|
| modal.style.cssText = 'position: fixed; top: 0; left: 0; width: 100%; height: 100%; backdrop-filter: blur(8px); display: none; align-items: center; justify-content: center; z-index: var(--z-modal-backdrop); background-color: rgba(15, 23, 42, 0.65); direction: rtl; text-align: right; box-sizing: border-box;';
|
| modal.innerHTML = `
|
| <div class="s4yvtq9394" style="max-width: min(850px, 94vw); max-height: min(88vh, 850px); border-radius: var(--radius-xl); border: 1px solid var(--border); background: var(--bg-card); box-shadow: var(--shadow-modal);">
|
| <div class="x8pdlyq70a" style="border-bottom: 1px solid var(--border); padding: 14px 20px; display: flex; justify-content: space-between; align-items: center; background: var(--bg-subtle);">
|
| <div class="tooau3ykdi" id="ka8vx2wbd1" style="font-weight: 800; font-size: 14px; display: flex; align-items: center; gap: 8px;">
|
| <i class="fa-solid fa-receipt" style="color: var(--primary);"></i> <span>سجل تتبع الإرسال والنشر للمنشور</span>
|
| </div>
|
| <button class="bcuz086hu4" id="c8r5l8id1i">×</button>
|
| </div>
|
| <div class="zn6t0dl6ke" style="padding: clamp(14px, 1.5vw, 20px);">
|
| <div class="diktqr0h64" style="max-height: 380px;">
|
| <table style="width: 100%; border-collapse: collapse; direction: rtl; text-align: right;">
|
| <thead>
|
| <tr>
|
| <th style="padding: 10px 12px;"><i class="fa-solid fa-bullseye"></i> <span>اسم الحملة</span></th>
|
| <th style="padding: 10px 12px;"><i class="fa-solid fa-users"></i> <span>الوجهة المستهدفة</span></th>
|
| <th style="padding: 10px 12px; text-align: center;"><i class="fa-solid fa-circle-info"></i> <span>الحالة</span></th>
|
| <th style="padding: 10px 12px; text-align: center;"><i class="fa-solid fa-link"></i> <span>الرابط / الخطأ</span></th>
|
| </tr>
|
| </thead>
|
| <tbody id="yx004dvp1r"></tbody>
|
| </table>
|
| </div>
|
| </div>
|
| </div>
|
| `;
|
| document.body.appendChild(modal);
|
|
|
| document.getElementById('c8r5l8id1i').onclick = () => {
|
| modal.style.display = 'none';
|
| };
|
| };
|
|
|
| |
| |
|
|
| const renderEvaluationDashboard = async () => {
|
| const container = document.getElementById('i4jg5y3ylx');
|
| const paginationContainer = document.getElementById('du4l2rjkr6');
|
| if (!container) return;
|
| container.innerHTML = '';
|
|
|
| const campaignHistoryData = await global.FritreeStorage.get('campaignHistoryData', []);
|
| const templateStatsMap = {};
|
|
|
| campaignHistoryData.forEach(camp => {
|
| if (camp.logs && Array.isArray(camp.logs)) {
|
| camp.logs.forEach(log => {
|
| const templateId = log.variantName;
|
| if (templateId) {
|
| if (!templateStatsMap[templateId]) {
|
| templateStatsMap[templateId] = { usage: 0, success: 0, pending: 0, failed: 0 };
|
| }
|
| templateStatsMap[templateId].usage++;
|
| if (log.status === 'success') templateStatsMap[templateId].success++;
|
| else if (log.status === 'pending') templateStatsMap[templateId].pending++;
|
| else templateStatsMap[templateId].failed++;
|
| }
|
| });
|
| }
|
| });
|
|
|
| state.previousPostsData.forEach(p => {
|
| const stats = templateStatsMap[p.id] || { usage: 0, success: 0, pending: 0, failed: 0 };
|
| p.stats = stats;
|
| p.usageCount = stats.usage;
|
| });
|
|
|
| if (global.FritreeRotationStore && typeof global.FritreeRotationStore.recalculateScores === 'function') {
|
| global.FritreeRotationStore.recalculateScores();
|
| }
|
|
|
| const sorted = [...state.previousPostsData].sort((a, b) => (b.score || 0) - (a.score || 0));
|
|
|
| if (state.previousPostsData.length === 0) {
|
| container.innerHTML = '<tr><td colspan="5" style="text-align:center; padding:30px 15px; color:var(--text-muted); font-size:11.5px;"><i class="fa-solid fa-circle-exclamation"></i> <span>لا توجد منشورات مسجلة في مكتبة التدوير حالياً.</span></td></tr>';
|
| if (paginationContainer) paginationContainer.innerHTML = '';
|
| updateEvaluationTotalsRow(sorted);
|
| return;
|
| }
|
|
|
| const startIndex = (currentMetricsPage - 1) * METRICS_ITEMS_PER_PAGE;
|
| const pageItems = sorted.slice(startIndex, startIndex + METRICS_ITEMS_PER_PAGE);
|
|
|
| pageItems.forEach(p => {
|
| const tr = document.createElement('tr');
|
| tr.style.cssText = 'cursor: pointer; transition: background 0.15s; border-bottom: 1px solid var(--border);';
|
| tr.onclick = () => openVariantTraceModal(p.id);
|
|
|
| const tdTitle = document.createElement('td');
|
| tdTitle.style.cssText = 'padding: 10px 12px; font-weight: 700;';
|
| tdTitle.innerHTML = `<i class="fa-solid fa-file-lines" style="color:#0d9488; margin-left:6px;"></i> <span style="color:var(--text-main);">${p.title || (p.text ? p.text.substring(0, 30) + '...' : 'منشور مؤرشف')}</span>`;
|
|
|
| const tdUsage = document.createElement('td');
|
| tdUsage.style.cssText = 'padding: 10px; text-align: center; font-weight: 700; font-family: var(--font-code); color: var(--text-main);';
|
| tdUsage.textContent = (p.stats ? p.stats.usage : p.usageCount || 0).toLocaleString('en-US');
|
|
|
| const tdSuccess = document.createElement('td');
|
| tdSuccess.style.cssText = 'padding: 10px; text-align: center; font-weight: 700; font-family: var(--font-code); color: var(--success);';
|
| tdSuccess.textContent = (p.stats ? p.stats.success : 0).toLocaleString('en-US');
|
|
|
| const tdPending = document.createElement('td');
|
| tdPending.style.cssText = 'padding: 10px; text-align: center; font-weight: 700; font-family: var(--font-code); color: var(--warning);';
|
| tdPending.textContent = (p.stats ? p.stats.pending : 0).toLocaleString('en-US');
|
|
|
| const tdFailed = document.createElement('td');
|
| tdFailed.style.cssText = 'padding: 10px; text-align: center; font-weight: 700; font-family: var(--font-code); color: var(--danger);';
|
| tdFailed.textContent = (p.stats ? p.stats.failed : 0).toLocaleString('en-US');
|
|
|
| tr.appendChild(tdTitle);
|
| tr.appendChild(tdUsage);
|
| tr.appendChild(tdSuccess);
|
| tr.appendChild(tdPending);
|
| tr.appendChild(tdFailed);
|
| container.appendChild(tr);
|
| });
|
|
|
| updateEvaluationTotalsRow(sorted);
|
| renderEvaluationPagination(sorted.length, paginationContainer);
|
| };
|
|
|
| |
| |
|
|
| const updateEvaluationTotalsRow = (items) => {
|
| let publishedSum = 0;
|
| let successfulSum = 0;
|
| let reviewedSum = 0;
|
| let failedSum = 0;
|
|
|
| items.forEach(p => {
|
| if (p.stats) {
|
| publishedSum += (p.stats.usage || 0);
|
| successfulSum += (p.stats.success || 0);
|
| reviewedSum += (p.stats.pending || 0);
|
| failedSum += (p.stats.failed || 0);
|
| }
|
| });
|
|
|
| const totalPubEl = document.getElementById('ylohpr45dl');
|
| const totalSuccEl = document.getElementById('md8oymcc5c');
|
| const totalRevEl = document.getElementById('qoumr7z4ii');
|
| const totalFailEl = document.getElementById('s8t8cbmfne');
|
|
|
| if (totalPubEl) totalPubEl.textContent = publishedSum.toLocaleString('en-US');
|
| if (totalSuccEl) totalSuccEl.textContent = successfulSum.toLocaleString('en-US');
|
| if (totalRevEl) totalRevEl.textContent = reviewedSum.toLocaleString('en-US');
|
| if (totalFailEl) totalFailEl.textContent = failedSum.toLocaleString('en-US');
|
| };
|
|
|
| |
| |
|
|
| const renderEvaluationPagination = (totalItems, container) => {
|
| if (!container) return;
|
| container.innerHTML = '';
|
| const totalPages = Math.ceil(totalItems / METRICS_ITEMS_PER_PAGE);
|
| if (totalPages <= 1) return;
|
|
|
| const prevBtn = document.createElement('button');
|
| prevBtn.className = 'ipxi2jz4g0';
|
| prevBtn.style.cssText = 'padding: 4px 8px; font-size: 10.5px; min-height: 28px;';
|
| prevBtn.innerHTML = '<i class="fa-solid fa-chevron-right"></i> ';
|
| prevBtn.disabled = currentMetricsPage === 1;
|
| prevBtn.onclick = () => {
|
| if (currentMetricsPage > 1) {
|
| currentMetricsPage--;
|
| renderEvaluationDashboard();
|
| }
|
| };
|
|
|
| const pageIndicator = document.createElement('span');
|
| pageIndicator.style.cssText = 'font-weight: 700; font-size: 11px; color: var(--text-muted); font-family: var(--font-code); margin: 0 6px;';
|
| pageIndicator.textContent = `صفحة ${currentMetricsPage.toLocaleString('en-US')} من ${totalPages.toLocaleString('en-US')}`;
|
|
|
| const nextBtn = document.createElement('button');
|
| nextBtn.className = 'ipxi2jz4g0';
|
| nextBtn.style.cssText = 'padding: 4px 8px; font-size: 10.5px; min-height: 28px;';
|
| nextBtn.innerHTML = '<i class="fa-solid fa-chevron-left"></i> ';
|
| nextBtn.disabled = currentMetricsPage === totalPages;
|
| nextBtn.onclick = () => {
|
| if (currentMetricsPage < totalPages) {
|
| currentMetricsPage++;
|
| renderEvaluationDashboard();
|
| }
|
| };
|
|
|
| container.appendChild(prevBtn);
|
| container.appendChild(pageIndicator);
|
| container.appendChild(nextBtn);
|
| };
|
|
|
| |
| |
| |
|
|
| const openVariantTraceModal = async (postId) => {
|
| const tbody = document.getElementById('yx004dvp1r');
|
| const metaInfo = document.getElementById('ka8vx2wbd1');
|
| if (!tbody || !metaInfo) return;
|
| tbody.innerHTML = '';
|
|
|
| const post = state.previousPostsData.find(p => p.id === postId);
|
| if (!post) return;
|
|
|
| appendTraceModalLayout();
|
| metaInfo.innerHTML = `<i class="fa-solid fa-receipt" style="color:var(--primary);"></i> <span>سجل تشغيل: "${post.title}" | الكفاءة: ${(post.score || 0).toLocaleString('en-US')}%</span>`;
|
|
|
| const campaignHistoryData = await global.FritreeStorage.get('campaignHistoryData', []);
|
| let matchCount = 0;
|
|
|
| campaignHistoryData.forEach(camp => {
|
| if (camp.logs && Array.isArray(camp.logs)) {
|
| camp.logs.forEach(log => {
|
| if (log.variantName === postId) {
|
| matchCount++;
|
| const tr = document.createElement('tr');
|
|
|
| const tdCamp = document.createElement('td');
|
| tdCamp.style.padding = '8px 10px';
|
| tdCamp.style.fontWeight = "700";
|
| tdCamp.textContent = camp.name;
|
|
|
| const tdTarget = document.createElement('td');
|
| tdTarget.style.padding = '8px 10px';
|
| tdTarget.textContent = log.groupId || "وجهة غير معروفة";
|
|
|
| const tdStatus = document.createElement('td');
|
| tdStatus.style.padding = '8px 10px';
|
| tdStatus.style.textAlign = 'center';
|
| const badge = document.createElement('span');
|
| badge.className = `go30y9mfgh ${log.status === 'success' ? 'success' : (log.status === 'pending' ? 'pending' : 'failed')}`;
|
| badge.textContent = log.status === 'success' ? 'تم النشر' : (log.status === 'pending' ? 'قيد المراجعة' : 'فشل');
|
| tdStatus.appendChild(badge);
|
|
|
| const tdLink = document.createElement('td');
|
| tdLink.style.padding = '8px 10px';
|
| tdLink.style.textAlign = 'center';
|
| if (log.postUrl) {
|
| const link = document.createElement('a');
|
| link.href = log.postUrl;
|
| link.target = '_blank';
|
| link.style.cssText = 'font-weight: 700; color: var(--primary); text-decoration: none; display: inline-flex; align-items: center; gap: 4px;';
|
| link.innerHTML = '<i class="fa-solid fa-arrow-up-right-from-square"></i> <span>عرض المنشور</span>';
|
| tdLink.appendChild(link);
|
| } else {
|
| tdLink.innerHTML = `<span style="color:var(--danger); font-size:10px;">${log.error || 'غير متوفر'}</span>`;
|
| }
|
|
|
| tr.appendChild(tdCamp);
|
| tr.appendChild(tdTarget);
|
| tr.appendChild(tdStatus);
|
| tr.appendChild(tdLink);
|
| tbody.appendChild(tr);
|
| }
|
| });
|
| }
|
| });
|
|
|
| if (matchCount === 0) {
|
| tbody.innerHTML = '<tr><td colspan="4" style="text-align:center; color:var(--text-muted); padding:20px; font-size:11.5px;"><i class="fa-solid fa-folder-open"></i> <span>لا توجد سجلات إرسال لهذا المنشور حتى الآن.</span></td></tr>';
|
| }
|
|
|
| const modal = document.getElementById('sg405ywfqm');
|
| if (modal) modal.style.display = 'flex';
|
| };
|
|
|
| |
| |
|
|
| const initPerformanceModule = () => {
|
| const page = document.getElementById('xpoqh5yufi');
|
| if (!page) return false;
|
| buildPerformanceLayout();
|
| appendTraceModalLayout();
|
| renderEvaluationDashboard();
|
| return true;
|
| };
|
|
|
| |
| |
|
|
| global.FritreeRotationPerformance = {
|
| init: initPerformanceModule,
|
| renderDashboard: renderEvaluationDashboard,
|
| openTraceModal: openVariantTraceModal
|
| };
|
|
|
| })(typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : this); |