• דף הבית
    • אינדקס קישורים
    • פוסטים אחרונים
    • משתמשים
    • חיפוש בהגדרות המתקדמות
    • חיפוש גוגל בפורום
    • ניהול המערכת
    • ניהול המערכת - שרת private
    • הרשמה
    • התחברות

    למה אין נתונים לקווים? 🤔

    מתוזמן נעוץ נעול הועבר בקשות לפיתוח
    142 פוסטים 11 כותבים 331 צפיות 5 עוקבים
    טוען פוסטים נוספים
    • מהישן לחדש
    • מהחדש לישן
    • הכי הרבה הצבעות
    תגובה
    • תגובה כנושא
    התחברו כדי לפרסם תגובה
    נושא זה נמחק. רק משתמשים עם הרשאות מתאימות יוכלו לצפות בו.
    • 5 מנותק
      565906 @אA
      נערך לאחרונה על ידי

      @אA
      החישובים בטוח לא נכונים עדיין....


      c02db0bf-0e0d-4d41-9f2f-4293fa875a67-image.png
      ccc8994b-2c8d-4f61-b14c-23f5b19a09a7-image.png

      א תגובה 1 תגובה אחרונה תגובה ציטוט 0
      • א מנותק
        אA @565906
        נערך לאחרונה על ידי

        @565906
        עדיין מטפל בזה.

        5 2 תגובות תגובה אחרונה תגובה ציטוט 1
        • 5 מנותק
          565906 @אA
          נערך לאחרונה על ידי 565906

          @אA אגב:
          גם בדאשבורד בגרף אני חושב שכדאי שיהיה גרף של שעות....


          זה בהצגה של נתונים רק מהיום...
          ab7b9c55-888b-4b1d-a7ac-7be1ca1d7ecd-image.png

          א תגובה 1 תגובה אחרונה תגובה ציטוט 0
          • י מנותק
            יוסף חיים 5
            נערך לאחרונה על ידי

            @אa אם אני עושה יום אחד בחודש הוא מראה את כל החודש, וכן אם אני בוחר כמה חודשים הוא נותן רק את הראשון

            תגובה 1 תגובה אחרונה תגובה ציטוט 0
            • 5 מנותק
              565906 @אA
              נערך לאחרונה על ידי 565906

              @אA
              בהשמעות אני חושב שכדאי להוסיף גם מיון לפי מספר קובץ מלבד אחוז השמעה / נטישה (שאגב: לא מספיק ברור מה זה - איך זה עובד) ופופולאריות

              תגובה 1 תגובה אחרונה תגובה ציטוט 1
              • א מנותק
                אA @565906
                נערך לאחרונה על ידי

                @565906
                חשבתי ע"ז.
                בעז"ה נוסיף.

                תגובה 1 תגובה אחרונה תגובה ציטוט 1
                • ק מנותק
                  קו המוסיקה @אA
                  נערך לאחרונה על ידי

                  @אA כתב בלמה אין נתונים לקווים? 🤔:

                  כלומר שהרוב האזינו ל17% מהקובץ.

                  נראה לי שיותר נכון לומר שממוצא ההאזנה הוא 17%, לא?

                  ק תגובה 1 תגובה אחרונה תגובה ציטוט 1
                  • ק מנותק
                    קו המוסיקה @קו המוסיקה
                    נערך לאחרונה על ידי

                    @אa וגם איך אפשר באמת לדעת על איזה קובץ מדובר שכתוב קובץ 000 יש לי מאות כאלה בקו,
                    צריך שיהיה אופציה לראות איזה שלוחה

                    א תגובה 1 תגובה אחרונה תגובה ציטוט 0
                    • א מנותק
                      אA @קו המוסיקה
                      נערך לאחרונה על ידי

                      @קו-המוסיקה
                      ראית את הגירסא האחרונה?
                      שם זה נוסף.
                      אני גם עובד על הנתונים שיהיו מדוייקים.

                      ק תגובה 1 תגובה אחרונה תגובה ציטוט 1
                      • ק מנותק
                        קו המוסיקה @אA
                        נערך לאחרונה על ידי

                        @אA ראיתי לא הבנתי מה באמת השתנה שם

                        א תגובה 1 תגובה אחרונה תגובה ציטוט 0
                        • א מנותק
                          אA @קו המוסיקה
                          נערך לאחרונה על ידי

                          @קו-המוסיקה
                          למשל, שמציג גם את השלוחה בה נמצא הקובץ.
                          אני רוצה לעשות סינון לקבצים, השאלה היא איך להציג את הקבצים בצורה ברורה?!

                          ק תגובה 1 תגובה אחרונה תגובה ציטוט 0
                          • ק מנותק
                            קו המוסיקה @אA
                            נערך לאחרונה על ידי

                            @אA אני לא רואה את זה...

                            א תגובה 1 תגובה אחרונה תגובה ציטוט 0
                            • א מנותק
                              אA @קו המוסיקה
                              נערך לאחרונה על ידי

                              @קו-המוסיקה
                              סליחה, אתה צודק.
                              זה בגירסא שאצלי, עדיין לא העלתי אותה.

                              תגובה 1 תגובה אחרונה תגובה ציטוט 1
                              • א מנותק
                                אA
                                נערך לאחרונה על ידי

                                אני מעלה קוד שאמור לתקן את הבעיה של הנתונים השגויים.
                                אשמח אם תוכלו לבדוק אותו.

                                הקוד

                                <!DOCTYPE html>
                                <html lang="he" dir="rtl">
                                <head>
                                    <meta charset="UTF-8">
                                    <title>ניתוח נתוני מערכות | v26.5</title>
                                    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
                                    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
                                    <style>
                                        :root { --bg: #0f172a; --card: #1e293b; --primary: #38bdf8; --accent: #22c55e; --text: #f1f5f9; --border: #334155; --danger: #ef4444; --warning: #f59e0b; }
                                        body { font-family: 'Segoe UI', sans-serif; background: var(--bg); color: var(--text); margin: 0; display: flex; flex-direction: column; height: 100vh; }
                                        header { background: #1e293b; padding: 1rem 2rem; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid var(--border); box-shadow: 0 4px 6px -1px rgba(0,0,0,0.1); }
                                        .logo-box { display: flex; align-items: center; gap: 12px; }
                                        .logo-icon { background: linear-gradient(135deg, var(--primary), #0ea5e9); color: #0f172a; width: 40px; height: 40px; border-radius: 10px; display: flex; align-items: center; justify-content: center; font-size: 1.2rem; }
                                        .logo-text { font-size: 1.4rem; font-weight: 800; color: var(--text); }
                                        .config-box { display: flex; gap: 12px; align-items: center; }
                                        input, select { background: #0f172a; border: 1px solid var(--border); color: white; padding: 10px; border-radius: 8px; outline: none; }
                                        input[type="date"]::-webkit-calendar-picker-indicator { filter: invert(1); cursor: pointer; }
                                        .btn-run { background: var(--primary); color: #0f172a; border: none; padding: 10px 25px; border-radius: 8px; font-weight: bold; cursor: pointer; transition: 0.3s; }
                                        .nav-tabs { background: #1e293b; display: flex; padding: 0 20px; border-bottom: 1px solid var(--border); }
                                        .tab { padding: 15px 25px; cursor: pointer; color: #94a3b8; border-bottom: 3px solid transparent; transition: 0.3s; }
                                        .tab.active { color: var(--primary); border-bottom-color: var(--primary); background: rgba(56, 189, 248, 0.07); }
                                        .main-content { flex: 1; padding: 25px; overflow-y: auto; background: #0f172a; }
                                        .card { background: var(--card); padding: 25px; border-radius: 16px; border: 1px solid var(--border); margin-bottom: 25px; }
                                        .stat-num { font-size: 2.5rem; font-weight: 800; color: var(--primary); }
                                        .control-bar { display: flex; gap: 20px; align-items: center; background: #334155; padding: 15px 25px; border-radius: 12px 12px 0 0; }
                                        .search-input { background: #0f172a; border: 1px solid var(--border); color: white; padding: 8px 15px; border-radius: 8px; width: 250px; }
                                        table { width: 100%; border-collapse: collapse; background: var(--card); border-radius: 0 0 12px 12px; overflow: hidden; }
                                        th { text-align: right; padding: 15px; background: #475569; color: white; font-size: 0.85rem; }
                                        td { padding: 15px; border-bottom: 1px solid var(--border); font-size: 0.95rem; }
                                        tr.clickable { cursor: pointer; }
                                        tr.clickable:hover { background: rgba(56, 189, 248, 0.1); }
                                        .bar-container { width: 100px; background: #0f172a; height: 10px; border-radius: 10px; display: inline-block; overflow: hidden; vertical-align: middle; margin-left: 8px; }
                                        .bar-fill { height: 100%; background: var(--accent); }
                                        .modal-overlay { position: fixed; top:0; left:0; width:100%; height:100%; background: rgba(0,0,0,0.85); display: none; justify-content: center; align-items: center; z-index: 1000; }
                                        .modal-content { background: var(--card); width: 85%; max-height: 85%; border-radius: 20px; border: 1px solid var(--primary); overflow-y: auto; padding: 30px; position: relative; }
                                        .close-modal { position: absolute; top: 20px; left: 20px; color: white; font-size: 2rem; cursor: pointer; }
                                        .progress-container { width: 100%; background: #1e293b; height: 20px; display: none; position: relative; text-align: center; }
                                        #progress-fill { height: 100%; background: var(--primary); width: 0%; transition: 0.4s; position: absolute; top:0; right:0; }
                                        #progress-text { position: relative; z-index: 2; font-size: 0.8rem; font-weight: bold; color: white; line-height: 20px; }
                                        .hidden { display: none; }
                                        .live-status { display: flex; align-items: center; gap: 6px; font-size: 0.75rem; padding: 4px 10px; border-radius: 20px; background: #334155; }
                                        .dot { width: 8px; height: 8px; border-radius: 50%; background: #666; }
                                        .dot.active { background: var(--accent); animation: pulse 2s infinite; }
                                        @keyframes pulse { 0% { opacity: 1; } 50% { opacity: 0.4; } 100% { opacity: 1; } }
                                    </style>
                                </head>
                                <body>
                                
                                <header>
                                    <div class="logo-box">
                                        <div class="logo-icon"><i class="fas fa-chart-pie"></i></div>
                                        <div class="logo-text">ניתוח נתוני מערכות</div>
                                        <div class="live-status"><div id="live-dot" class="dot"></div> <span id="live-text">OFFLINE</span></div>
                                    </div>
                                    <div class="config-box">
                                        <input type="password" id="apiToken" placeholder="טוקן API">
                                        <input type="date" id="startDate">
                                        <input type="date" id="endDate">
                                        <button class="btn-run" onclick="manualStart()">הפעל ניתוח</button>
                                    </div>
                                </header>
                                
                                <div class="progress-container" id="progBar">
                                    <div id="progress-fill"></div>
                                    <span id="progress-text">0%</span>
                                </div>
                                
                                <div class="nav-tabs">
                                    <div class="tab active" onclick="switchTab(event, 'dash-tab')">דאשבורד</div>
                                    <div class="tab" onclick="switchTab(event, 'ext-tab')">שלוחות</div>
                                    <div class="tab" onclick="switchTab(event, 'play-tab')">השמעות</div>
                                    <div class="tab" onclick="switchTab(event, 'users-tab')">מאזינים</div>
                                    <div class="tab" style="color: var(--warning)" onclick="switchTab(event, 'debug-tab')">לוג</div>
                                </div>
                                
                                <div class="main-content">
                                    <div id="dash-tab" class="tab-content">
                                        <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 25px; margin-bottom: 25px;">
                                            <div class="card"><span style="color: #94a3b8">מאזינים ייחודיים</span><br><span id="stat-users" class="stat-num">0</span></div>
                                            <div class="card"><span style="color: #94a3b8">סה"כ דקות שיחה (מערכת)</span><br><span id="stat-min" class="stat-num">0</span></div>
                                            <div class="card"><span style="color: #94a3b8">קבצים שהושמעו במלואם</span><br><span id="stat-comp" class="stat-num">0</span></div>
                                        </div>
                                        <div class="card"><h3>גרף פעילות יומי</h3><canvas id="dailyChart" height="100"></canvas></div>
                                    </div>
                                
                                    <div id="ext-tab" class="tab-content hidden">
                                        <div class="control-bar">
                                            <select id="extSort" onchange="renderExts()"><option value="count">כמות כניסות</option><option value="sec">זמן שהייה</option></select>
                                            <input type="text" id="extSearch" class="search-input" placeholder="חפש שלוחה..." onkeyup="renderExts()">
                                        </div>
                                        <table id="extTable"><thead><tr><th>שם השלוחה</th><th>תיאור שלוחה</th><th>כניסות</th><th>דקות שהייה</th><th>ממוצע</th></tr></thead><tbody></tbody></table>
                                    </div>
                                
                                    <div id="play-tab" class="tab-content hidden">
                                        <div class="control-bar">
                                            <select id="playSort" onchange="renderPlays()"><option value="count">פופולריות</option><option value="pct">אחוז השלמה</option></select>
                                            <input type="text" id="playSearch" class="search-input" placeholder="חפש קובץ..." onkeyup="renderPlays()">
                                        </div>
                                        <table id="playTable"><thead><tr><th>שם קובץ</th><th>שלוחה</th><th>השמעות</th><th>סה"כ דקות</th><th>אחוז השלמה</th><th>נטישה</th></tr></thead><tbody></tbody></table>
                                    </div>
                                
                                    <div id="users-tab" class="tab-content hidden">
                                        <div class="control-bar">
                                            <select id="userSort" onchange="renderUsers()"><option value="sec">זמן האזנה כולל</option><option value="calls">מספר שיחות</option></select>
                                            <input type="text" id="userSearch" class="search-input" placeholder="חפש טלפון או שם..." onkeyup="renderUsers()">
                                        </div>
                                        <table id="usersTable"><thead><tr><th>מספר טלפון</th><th>שם מאזין</th><th>דקות האזנה</th><th>מספר שיחות</th><th>סטטוס</th></tr></thead><tbody></tbody></table>
                                    </div>
                                
                                    <div id="debug-tab" class="tab-content hidden"><div class="card"><div id="debug-console" style="background:#000; color:#22c55e; padding:20px; height:400px; overflow-y:auto; font-family:monospace;"></div></div></div>
                                </div>
                                
                                <div id="userModal" class="modal-overlay" onclick="closeModal()">
                                    <div class="modal-content" onclick="event.stopPropagation()">
                                        <span class="close-modal" onclick="closeModal()">&times;</span>
                                        <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
                                            <h2 id="modalTitle" style="color: var(--primary); margin:0;"></h2>
                                            <select id="modalFilter" onchange="filterModalContent()" style="background: var(--bg); border: 1px solid var(--primary); padding: 5px 15px;">
                                                <option value="all">הכל</option>
                                                <option value="שלוחה">שלוחות בלבד</option>
                                                <option value="השמעה">השמעות בלבד</option>
                                            </select>
                                        </div>
                                        <table id="modalTable">
                                            <thead>
                                                <tr>
                                                    <th>סוג פעילות</th>
                                                    <th>שלוחה/קובץ</th>
                                                    <th>זמן שהייה</th>
                                                    <th>תאריך</th>
                                                </tr>
                                            </thead>
                                            <tbody></tbody>
                                        </table>
                                    </div>
                                </div>
                                
                                <script>
                                    const API = "https://www.call2all.co.il/ym/api/";
                                    let dataStore = { exts: {}, plays: {}, users: {}, daily: {}, rawActivity: [], totalSec: 0, completed: 0, names: {} };
                                    let callMap = {}; 
                                    let currentModalPhone = "";
                                    let dailyChart = null;
                                    let autoRefreshTimer = null;
                                
                                    function addLog(msg, color = '#22c55e') {
                                        const console = document.getElementById('debug-console');
                                        if(!console) return;
                                        const div = document.createElement('div');
                                        div.style.color = color;
                                        div.innerText = `[${new Date().toLocaleTimeString()}] ${msg}`;
                                        console.appendChild(div);
                                    }
                                
                                    async function fetchNames(token) {
                                        try {
                                            // שינוי הנתיב לשלוחה הראשית: ivr2:/EnterIDValName.ini
                                            const res = await fetch(`${API}DownloadFile?token=${token}&path=ivr2:/EnterIDValName.ini`);
                                            const text = await res.text();
                                            if(!text || text.includes("NOT_FOUND")) {
                                                addLog("קובץ שמות לא נמצא בשלוחה הראשית", "orange");
                                                return;
                                            }
                                            text.split(/\r?\n/).forEach(line => {
                                                if (line.includes('=')) {
                                                    const parts = line.split('=');
                                                    const phone = parts[0].replace(/[^\d]/g, "").trim(); 
                                                    const name = parts[1].trim();
                                                    if (phone && name) dataStore.names[phone] = name;
                                                }
                                            });
                                            addLog(`נטענו ${Object.keys(dataStore.names).length} שמות מהמערכת`);
                                        } catch(e) { addLog("שגיאה בטעינת שמות: " + e.message, "red"); }
                                    }
                                
                                    function cleanExt(val) {
                                        if (!val) return "ראשית";
                                        let s = val.toString().trim().replace(/^\ufeff/, "");
                                        if (s === "" || s === "/" || s === "." || s.toLowerCase() === "root" || s.toLowerCase() === "main") return "ראשית";
                                        return s;
                                    }
                                
                                    function parseSec(t) {
                                        if (!t) return 0;
                                        if (t.toString().includes(':')) {
                                            const p = t.split(':').map(Number);
                                            return p.length === 3 ? (p[0]*3600)+(p[1]*60)+p[2] : (p[0]*60)+p[1];
                                        }
                                        return parseInt(t) || 0;
                                    }
                                
                                    async function manualStart() {
                                        if(autoRefreshTimer) clearInterval(autoRefreshTimer);
                                        await startFullAnalysis();
                                        document.getElementById('live-dot').classList.add('active');
                                        document.getElementById('live-text').innerText = "LIVE (עדכון אוטומטי)";
                                        autoRefreshTimer = setInterval(startFullAnalysis, 60000); 
                                    }
                                
                                    async function startFullAnalysis() {
                                        const token = document.getElementById('apiToken').value;
                                        const start = document.getElementById('startDate').value;
                                        const end = document.getElementById('endDate').value;
                                        if (!token) return alert("נא להזין טוקן API");
                                
                                        addLog("מתחיל ניתוח נתונים...");
                                        dataStore = { exts: {}, plays: {}, users: {}, daily: {}, rawActivity: [], totalSec: 0, completed: 0, names: {} };
                                        callMap = {}; 
                                        
                                        document.getElementById('progBar').style.display = 'block';
                                        await fetchNames(token);
                                
                                        const monthStr = start.substring(0, 7); 
                                        try {
                                            const res = await fetch(`${API}RenderYMGRFile?token=${token}&wath=ivr2:/Log/LogFolderEnterExit-${monthStr}.ymgr&convertType=json`);
                                            const json = await res.json();
                                            if (json.data) {
                                                json.data.forEach(row => {
                                                    const extName = cleanExt(row["שלוחה"]);
                                                    const phone = row["טלפון"] || "חסוי";
                                                    const sec = parseInt(row["סה\"כ שניות"]) || 0;
                                                    const callId = row["מזהה שיחה"];
                                                    const date = row["תאריך"];
                                
                                                    if (!dataStore.exts[extName]) dataStore.exts[extName] = { count: 0, sec: 0, title: row["כותרת שלוחה"] || "-" };
                                                    dataStore.exts[extName].count++;
                                                    dataStore.exts[extName].sec += sec;
                                
                                                    if (callId) {
                                                        if (!callMap[callId]) {
                                                            callMap[callId] = { phone, maxSec: 0, date };
                                                        }
                                                        if (sec > callMap[callId].maxSec) {
                                                            callMap[callId].maxSec = sec;
                                                        }
                                                    }
                                
                                                    if (!dataStore.users[phone]) dataStore.users[phone] = { sec: 0, callIds: new Set() };
                                                    if (callId) dataStore.users[phone].callIds.add(callId);
                                
                                                    dataStore.rawActivity.push({ phone, type: 'שלוחה', name: extName, sec: sec + " ש'", date: (row["תאריך"] || "") + " " + (row["התחלה שעה"] || "") });
                                                });
                                            }
                                        } catch(e) { addLog("שגיאה בלוג כניסות", "red"); }
                                
                                        Object.values(callMap).forEach(call => {
                                            dataStore.totalSec += call.maxSec;
                                            if (dataStore.users[call.phone]) {
                                                dataStore.users[call.phone].sec += call.maxSec;
                                            }
                                        });
                                
                                        let dates = [];
                                        for(let d=new Date(start); d<=new Date(end); d.setDate(d.getDate()+1)) dates.push(new Date(d).toISOString().split('T')[0]);
                                
                                        for (let day of dates) {
                                            updateProgress(dates.indexOf(day)+1, dates.length);
                                            try {
                                                const res = await fetch(`${API}RenderYMGRFile?token=${token}&wath=ivr2:/Log/LogPlaybackPlayStop/LogPlaybackPlayStop.${day}.ymgr&convertType=json`);
                                                const json = await res.json();
                                                if (json.data) {
                                                    if (!dataStore.daily[day]) dataStore.daily[day] = 0;
                                                    json.data.forEach(row => {
                                                        const file = row["השמעה"] || "לא ידוע";
                                                        const phone = row["טלפון"] || "חסוי";
                                                        const sec = parseInt(row["סה\"כ שניות"]) || 0;
                                                        const len = parseSec(row["אורך הקובץ"]);
                                                        const isEnd = row["נקודת יציאה"] === "סוף";
                                                        
                                                        dataStore.daily[day]++; 
                                                        if (isEnd) dataStore.completed++;
                                
                                                        if (!dataStore.plays[file]) dataStore.plays[file] = { count: 0, sec: 0, drops: 0, pcts: [], folder: row["שלוחה"] || "-" };
                                                        dataStore.plays[file].count++;
                                                        dataStore.plays[file].sec += sec;
                                                        dataStore.plays[file].pcts.push(len > 0 ? Math.min(100, Math.round((sec/len)*100)) : 0);
                                                        if (!isEnd) dataStore.plays[file].drops++;
                                
                                                        dataStore.rawActivity.push({ phone, type: 'השמעה', name: file, sec: sec + " ש'", date: day + " " + (row["שעה"] || "") });
                                                    });
                                                }
                                            } catch(e) {}
                                        }
                                        renderUI();
                                    }
                                
                                    function updateProgress(c, t) { 
                                        const pct = Math.round(c/t*100);
                                        document.getElementById('progress-fill').style.width = pct + '%'; 
                                        document.getElementById('progress-text').innerText = pct + '% (' + c + '/' + t + ')';
                                    }
                                
                                    function renderUI() {
                                        document.getElementById('progBar').style.display = 'none';
                                        document.getElementById('stat-users').innerText = Object.keys(dataStore.users).length.toLocaleString();
                                        document.getElementById('stat-min').innerText = Math.floor(dataStore.totalSec / 60).toLocaleString();
                                        document.getElementById('stat-comp').innerText = dataStore.completed.toLocaleString();
                                        renderExts(); renderPlays(); renderUsers(); updateChart();
                                        addLog("הנתונים מעודכנים.");
                                    }
                                
                                    function renderExts() {
                                        const sort = document.getElementById('extSort').value;
                                        const q = document.getElementById('extSearch').value.toLowerCase();
                                        let items = Object.entries(dataStore.exts).map(([name, d]) => ({name, ...d})).filter(i => i.name.toLowerCase().includes(q));
                                        items.sort((a,b) => b[sort] - a[sort]);
                                        document.querySelector('#extTable tbody').innerHTML = items.map(i => `
                                            <tr><td style="color:var(--primary); font-weight:600">${i.name}</td><td>${i.title}</td><td>${i.count}</td><td>${(i.sec/60).toFixed(1)}</td><td>${i.count ? Math.round(i.sec/i.count) : 0} ש'</td></tr>
                                        `).join('');
                                    }
                                
                                    function renderPlays() {
                                        const sort = document.getElementById('playSort').value;
                                        const q = document.getElementById('playSearch').value.toLowerCase();
                                        let items = Object.entries(dataStore.plays).map(([name, d]) => {
                                            const avg = d.pcts.length ? Math.round(d.pcts.reduce((a,b)=>a+b,0)/d.pcts.length) : 0;
                                            const drop = Math.round((d.drops/d.count)*100);
                                            return {name, avg, drop, ...d};
                                        }).filter(i => i.name.toLowerCase().includes(q));
                                        items.sort((a,b) => sort === 'count' ? b.count - a.count : b.avg - a.avg);
                                        document.querySelector('#playTable tbody').innerHTML = items.map(i => `
                                            <tr><td>${i.name}</td><td>${i.folder}</td><td>${i.count}</td><td>${(i.sec/60).toFixed(1)}</td>
                                            <td><div class="bar-container"><div class="bar-fill" style="width:${i.avg}%"></div></div> ${i.avg}%</td>
                                            <td style="color:${i.drop > 50 ? 'var(--danger)' : 'var(--accent)'}">${i.drop}%</td></tr>
                                        `).join('');
                                    }
                                
                                    function renderUsers() {
                                        const sortKey = document.getElementById('userSort').value;
                                        const q = document.getElementById('userSearch').value;
                                        let items = Object.entries(dataStore.users).map(([phone, d]) => ({
                                            phone, name: dataStore.names[phone] || "לא ידוע", sec: d.sec, calls: d.callIds ? d.callIds.size : 0
                                        })).filter(i => i.phone.includes(q) || i.name.includes(q));
                                        items.sort((a,b) => b[sortKey] - a[sortKey]);
                                        document.querySelector('#usersTable tbody').innerHTML = items.map((i, idx) => `
                                            <tr class="clickable" onclick="openUserDetail('${i.phone}')">
                                                <td style="font-weight:bold">${i.phone}</td><td style="color:var(--warning)">${i.name}</td>
                                                <td style="color:var(--primary); font-weight:bold">${(i.sec/60).toFixed(1)}</td><td>${i.calls}</td>
                                                <td>${idx < 3 ? '🏆 מוביל' : 'מאזין'}</td>
                                            </tr>
                                        `).join('');
                                    }
                                
                                    function openUserDetail(phone) {
                                        currentModalPhone = phone;
                                        document.getElementById('modalTitle').innerText = `פירוט מאזין: ${phone} (${dataStore.names[phone] || "לא ידוע"})`;
                                        filterModalContent();
                                        document.getElementById('userModal').style.display = 'flex';
                                    }
                                
                                    function filterModalContent() {
                                        const filter = document.getElementById('modalFilter').value;
                                        const activity = dataStore.rawActivity.filter(a => a.phone === currentModalPhone);
                                        const filtered = filter === 'all' ? activity : activity.filter(a => a.type === filter);
                                        document.querySelector('#modalTable tbody').innerHTML = filtered.map(a => `
                                            <tr><td style="color:${a.type==='השמעה'?'var(--primary)':'var(--accent)'}; font-weight:bold">${a.type}</td>
                                            <td>${a.name}</td><td>${a.sec}</td><td>${a.date}</td></tr>
                                        `).join('');
                                    }
                                
                                    function closeModal() { document.getElementById('userModal').style.display = 'none'; }
                                    function switchTab(e, id) {
                                        document.querySelectorAll('.tab-content').forEach(c => c.classList.add('hidden'));
                                        document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
                                        document.getElementById(id).classList.remove('hidden');
                                        e.currentTarget.classList.add('active');
                                    }
                                    function updateChart() {
                                        if (dailyChart) dailyChart.destroy();
                                        const ctx = document.getElementById('dailyChart').getContext('2d');
                                        dailyChart = new Chart(ctx, {
                                            type: 'line',
                                            data: { labels: Object.keys(dataStore.daily), datasets: [{ label: 'פעולות', data: Object.values(dataStore.daily), borderColor: '#38bdf8', tension: 0.4, fill: true, backgroundColor: 'rgba(56, 189, 248, 0.1)' }] },
                                            options: { plugins: { legend: { display: false } } }
                                        });
                                    }
                                    document.getElementById('startDate').value = document.getElementById('endDate').value = new Date().toISOString().split('T')[0];
                                </script>
                                </body>
                                </html>
                                

                                ב תגובה 1 תגובה אחרונה תגובה ציטוט 0
                                • ב מנותק
                                  בוס @אA
                                  נערך לאחרונה על ידי

                                  @אA 75704768-9715-4e39-a908-e7aae4b9a2d3-image.png

                                  א תגובה 1 תגובה אחרונה תגובה ציטוט 0
                                  • א מנותק
                                    אA @בוס
                                    נערך לאחרונה על ידי

                                    @בוס
                                    ממש מוזר.
                                    עשית טווח או משהו?!
                                    כי אצלי זה היה בסדר.

                                    ק א 2 תגובות תגובה אחרונה תגובה ציטוט 0
                                    • ק מנותק
                                      קו המוסיקה @אA
                                      נערך לאחרונה על ידי

                                      @אA אצלי גם לא עובד,
                                      וסמתי נתונים רק להיום

                                      תגובה 1 תגובה אחרונה תגובה ציטוט 0
                                      • א מנותק
                                        אA @אA
                                        נערך לאחרונה על ידי

                                        תנסה את זה

                                        <!DOCTYPE html>
                                        <html lang="he" dir="rtl">
                                        <head>
                                            <meta charset="UTF-8">
                                            <title>ניתוח נתוני מערכות | v26.6</title>
                                            <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
                                            <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
                                            <style>
                                                :root { --bg: #0f172a; --card: #1e293b; --primary: #38bdf8; --accent: #22c55e; --text: #f1f5f9; --border: #334155; --danger: #ef4444; --warning: #f59e0b; }
                                                body { font-family: 'Segoe UI', sans-serif; background: var(--bg); color: var(--text); margin: 0; display: flex; flex-direction: column; height: 100vh; }
                                                header { background: #1e293b; padding: 1rem 2rem; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid var(--border); box-shadow: 0 4px 6px -1px rgba(0,0,0,0.1); }
                                                .logo-box { display: flex; align-items: center; gap: 12px; }
                                                .logo-icon { background: linear-gradient(135deg, var(--primary), #0ea5e9); color: #0f172a; width: 40px; height: 40px; border-radius: 10px; display: flex; align-items: center; justify-content: center; font-size: 1.2rem; }
                                                .logo-text { font-size: 1.4rem; font-weight: 800; color: var(--text); }
                                                .config-box { display: flex; gap: 12px; align-items: center; }
                                                input, select { background: #0f172a; border: 1px solid var(--border); color: white; padding: 10px; border-radius: 8px; outline: none; }
                                                .btn-run { background: var(--primary); color: #0f172a; border: none; padding: 10px 25px; border-radius: 8px; font-weight: bold; cursor: pointer; transition: 0.3s; }
                                                .nav-tabs { background: #1e293b; display: flex; padding: 0 20px; border-bottom: 1px solid var(--border); }
                                                .tab { padding: 15px 25px; cursor: pointer; color: #94a3b8; border-bottom: 3px solid transparent; transition: 0.3s; }
                                                .tab.active { color: var(--primary); border-bottom-color: var(--primary); background: rgba(56, 189, 248, 0.07); }
                                                .main-content { flex: 1; padding: 25px; overflow-y: auto; background: #0f172a; }
                                                .card { background: var(--card); padding: 25px; border-radius: 16px; border: 1px solid var(--border); margin-bottom: 25px; }
                                                .stat-num { font-size: 2.5rem; font-weight: 800; color: var(--primary); }
                                                .control-bar { display: flex; gap: 20px; align-items: center; background: #334155; padding: 15px 25px; border-radius: 12px 12px 0 0; }
                                                .search-input { background: #0f172a; border: 1px solid var(--border); color: white; padding: 8px 15px; border-radius: 8px; width: 250px; }
                                                table { width: 100%; border-collapse: collapse; background: var(--card); border-radius: 0 0 12px 12px; overflow: hidden; }
                                                th { text-align: right; padding: 15px; background: #475569; color: white; font-size: 0.85rem; }
                                                td { padding: 15px; border-bottom: 1px solid var(--border); font-size: 0.95rem; }
                                                tr.clickable { cursor: pointer; }
                                                tr.clickable:hover { background: rgba(56, 189, 248, 0.1); }
                                                .bar-container { width: 100px; background: #0f172a; height: 10px; border-radius: 10px; display: inline-block; overflow: hidden; vertical-align: middle; margin-left: 8px; }
                                                .bar-fill { height: 100%; background: var(--accent); }
                                                .modal-overlay { position: fixed; top:0; left:0; width:100%; height:100%; background: rgba(0,0,0,0.85); display: none; justify-content: center; align-items: center; z-index: 1000; }
                                                .modal-content { background: var(--card); width: 85%; max-height: 85%; border-radius: 20px; border: 1px solid var(--primary); overflow-y: auto; padding: 30px; position: relative; }
                                                .close-modal { position: absolute; top: 20px; left: 20px; color: white; font-size: 2rem; cursor: pointer; }
                                                .progress-container { width: 100%; background: #1e293b; height: 20px; display: none; position: relative; text-align: center; }
                                                #progress-fill { height: 100%; background: var(--primary); width: 0%; transition: 0.4s; position: absolute; top:0; right:0; }
                                                #progress-text { position: relative; z-index: 2; font-size: 0.8rem; font-weight: bold; color: white; line-height: 20px; }
                                                .hidden { display: none; }
                                                .live-status { display: flex; align-items: center; gap: 6px; font-size: 0.75rem; padding: 4px 10px; border-radius: 20px; background: #334155; }
                                                .dot { width: 8px; height: 8px; border-radius: 50%; background: #666; }
                                                .dot.active { background: var(--accent); animation: pulse 2s infinite; }
                                                @keyframes pulse { 0% { opacity: 1; } 50% { opacity: 0.4; } 100% { opacity: 1; } }
                                            </style>
                                        </head>
                                        <body>
                                        
                                        <header>
                                            <div class="logo-box">
                                                <div class="logo-icon"><i class="fas fa-chart-pie"></i></div>
                                                <div class="logo-text">ניתוח נתוני מערכות</div>
                                                <div class="live-status"><div id="live-dot" class="dot"></div> <span id="live-text">OFFLINE</span></div>
                                            </div>
                                            <div class="config-box">
                                                <input type="password" id="apiToken" placeholder="טוקן API">
                                                <input type="date" id="startDate">
                                                <input type="date" id="endDate">
                                                <button class="btn-run" onclick="manualStart()">הפעל ניתוח</button>
                                            </div>
                                        </header>
                                        
                                        <div class="progress-container" id="progBar">
                                            <div id="progress-fill"></div>
                                            <span id="progress-text">0%</span>
                                        </div>
                                        
                                        <div class="nav-tabs">
                                            <div class="tab active" onclick="switchTab(event, 'dash-tab')">דאשבורד</div>
                                            <div class="tab" onclick="switchTab(event, 'ext-tab')">שלוחות</div>
                                            <div class="tab" onclick="switchTab(event, 'play-tab')">השמעות</div>
                                            <div class="tab" onclick="switchTab(event, 'users-tab')">מאזינים</div>
                                            <div class="tab" style="color: var(--warning)" onclick="switchTab(event, 'debug-tab')">לוג</div>
                                        </div>
                                        
                                        <div class="main-content">
                                            <div id="dash-tab" class="tab-content">
                                                <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 25px; margin-bottom: 25px;">
                                                    <div class="card"><span style="color: #94a3b8">מאזינים ייחודיים</span><br><span id="stat-users" class="stat-num">0</span></div>
                                                    <div class="card"><span style="color: #94a3b8">סה"כ דקות שיחה (מערכת)</span><br><span id="stat-min" class="stat-num">0</span></div>
                                                    <div class="card"><span style="color: #94a3b8">קבצים שהושמעו במלואם</span><br><span id="stat-comp" class="stat-num">0</span></div>
                                                </div>
                                                <div class="card"><h3>גרף פעילות יומי</h3><canvas id="dailyChart" height="100"></canvas></div>
                                            </div>
                                        
                                            <div id="ext-tab" class="tab-content hidden">
                                                <div class="control-bar">
                                                    <select id="extSort" onchange="renderExts()"><option value="count">כמות כניסות</option><option value="sec">זמן שהייה</option></select>
                                                    <input type="text" id="extSearch" class="search-input" placeholder="חפש שלוחה..." onkeyup="renderExts()">
                                                </div>
                                                <table id="extTable"><thead><tr><th>שם השלוחה</th><th>תיאור שלוחה</th><th>כניסות</th><th>דקות שהייה</th><th>ממוצע</th></tr></thead><tbody></tbody></table>
                                            </div>
                                        
                                            <div id="play-tab" class="tab-content hidden">
                                                <div class="control-bar">
                                                    <select id="playSort" onchange="renderPlays()"><option value="count">פופולריות</option><option value="pct">אחוז השלמה</option></select>
                                                    <input type="text" id="playSearch" class="search-input" placeholder="חפש קובץ..." onkeyup="renderPlays()">
                                                </div>
                                                <table id="playTable"><thead><tr><th>שם קובץ</th><th>שלוחה</th><th>השמעות</th><th>סה"כ דקות</th><th>אחוז השלמה</th><th>נטישה</th></tr></thead><tbody></tbody></table>
                                            </div>
                                        
                                            <div id="users-tab" class="tab-content hidden">
                                                <div class="control-bar">
                                                    <select id="userSort" onchange="renderUsers()"><option value="sec">זמן האזנה כולל</option><option value="calls">מספר שיחות</option></select>
                                                    <input type="text" id="userSearch" class="search-input" placeholder="חפש טלפון או שם..." onkeyup="renderUsers()">
                                                </div>
                                                <table id="usersTable"><thead><tr><th>מספר טלפון</th><th>שם מאזין</th><th>דקות האזנה</th><th>מספר שיחות</th><th>סטטוס</th></tr></thead><tbody></tbody></table>
                                            </div>
                                        
                                            <div id="debug-tab" class="tab-content hidden"><div class="card"><div id="debug-console" style="background:#000; color:#22c55e; padding:20px; height:400px; overflow-y:auto; font-family:monospace;"></div></div></div>
                                        </div>
                                        
                                        <div id="userModal" class="modal-overlay" onclick="closeModal()">
                                            <div class="modal-content" onclick="event.stopPropagation()">
                                                <span class="close-modal" onclick="closeModal()">&times;</span>
                                                <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
                                                    <h2 id="modalTitle" style="color: var(--primary); margin:0;"></h2>
                                                    <select id="modalFilter" onchange="filterModalContent()" style="background: var(--bg); border: 1px solid var(--primary); padding: 5px 15px;">
                                                        <option value="all">הכל</option>
                                                        <option value="שלוחה">שלוחות בלבד</option>
                                                        <option value="השמעה">השמעות בלבד</option>
                                                    </select>
                                                </div>
                                                <table id="modalTable"><thead><tr><th>סוג פעילות</th><th>שלוחה/קובץ</th><th>זמן שהייה</th><th>תאריך</th></tr></thead><tbody></tbody></table>
                                            </div>
                                        </div>
                                        
                                        <script>
                                            const API = "https://www.call2all.co.il/ym/api/";
                                            let dataStore = { exts: {}, plays: {}, users: {}, daily: {}, rawActivity: [], totalSec: 0, completed: 0, names: {} };
                                            let currentModalPhone = "";
                                            let dailyChart = null;
                                            let autoRefreshTimer = null;
                                        
                                            function addLog(msg, color = '#22c55e') {
                                                const console = document.getElementById('debug-console');
                                                if(!console) return;
                                                const div = document.createElement('div');
                                                div.style.color = color;
                                                div.innerText = `[${new Date().toLocaleTimeString()}] ${msg}`;
                                                console.appendChild(div);
                                            }
                                        
                                            async function fetchNames(token) {
                                                try {
                                                    const res = await fetch(`${API}DownloadFile?token=${token}&path=ivr2:/EnterIDValName.ini`);
                                                    const text = await res.text();
                                                    if(!text || text.includes("NOT_FOUND")) {
                                                        addLog("קובץ שמות לא נמצא בשלוחה הראשית", "orange");
                                                        return;
                                                    }
                                                    text.split(/\r?\n/).forEach(line => {
                                                        if (line.includes('=')) {
                                                            const parts = line.split('=');
                                                            const phone = parts[0].replace(/[^\d]/g, "").trim(); 
                                                            const name = parts[1].trim();
                                                            if (phone && name) dataStore.names[phone] = name;
                                                        }
                                                    });
                                                    addLog(`נטענו ${Object.keys(dataStore.names).length} שמות`);
                                                } catch(e) { addLog("שגיאה בטעינת שמות: " + e.message, "red"); }
                                            }
                                        
                                            function cleanExt(val) {
                                                if (!val) return "ראשית";
                                                let s = val.toString().trim().replace(/^\ufeff/, "");
                                                if (s === "" || s === "/" || s === "." || s.toLowerCase() === "root" || s.toLowerCase() === "main") return "ראשית";
                                                return s;
                                            }
                                        
                                            async function manualStart() {
                                                if(autoRefreshTimer) clearInterval(autoRefreshTimer);
                                                await startFullAnalysis();
                                                document.getElementById('live-dot').classList.add('active');
                                                document.getElementById('live-text').innerText = "LIVE (עדכון אוטומטי)";
                                                autoRefreshTimer = setInterval(startFullAnalysis, 60000); 
                                            }
                                        
                                            async function startFullAnalysis() {
                                                const token = document.getElementById('apiToken').value;
                                                const start = document.getElementById('startDate').value;
                                                const end = document.getElementById('endDate').value;
                                                if (!token) return alert("נא להזין טוקן API");
                                        
                                                addLog("מנקה נתונים ומתחיל ניתוח חדש...");
                                                dataStore = { exts: {}, plays: {}, users: {}, daily: {}, rawActivity: [], totalSec: 0, completed: 0, names: dataStore.names };
                                                let callIDTracker = {}; // אובייקט עזר למניעת כפל דקות
                                        
                                                document.getElementById('progBar').style.display = 'block';
                                                if (Object.keys(dataStore.names).length === 0) await fetchNames(token);
                                        
                                                const monthStr = start.substring(0, 7); 
                                                try {
                                                    const res = await fetch(`${API}RenderYMGRFile?token=${token}&wath=ivr2:/Log/LogFolderEnterExit-${monthStr}.ymgr&convertType=json`);
                                                    const json = await res.json();
                                                    if (json.data) {
                                                        json.data.forEach(row => {
                                                            const phone = row["טלפון"] || "חסוי";
                                                            const callId = row["מזהה שיחה"];
                                                            const sec = parseInt(row["סה\"כ שניות"]) || 0;
                                                            const extName = cleanExt(row["שלוחה"]);
                                        
                                                            // חישוב דקות לכל מאזין לפי מזהה שיחה ייחודי
                                                            if (callId) {
                                                                if (!callIDTracker[callId]) {
                                                                    callIDTracker[callId] = { phone: phone, maxSec: 0 };
                                                                }
                                                                if (sec > callIDTracker[callId].maxSec) {
                                                                    callIDTracker[callId].maxSec = sec;
                                                                }
                                                            }
                                        
                                                            // סטטיסטיקת שלוחות
                                                            if (!dataStore.exts[extName]) dataStore.exts[extName] = { count: 0, sec: 0, title: row["כותרת שלוחה"] || "-" };
                                                            dataStore.exts[extName].count++;
                                                            dataStore.exts[extName].sec += sec;
                                        
                                                            // תיעוד לפעילות מאזין
                                                            dataStore.rawActivity.push({ phone, type: 'שלוחה', name: extName, sec: sec + " ש'", date: (row["תאריך"] || "") + " " + (row["התחלה שעה"] || "") });
                                                        });
                                                    }
                                                } catch(e) { addLog("שגיאה בלוג כניסות", "red"); }
                                        
                                                // סיכום דקות לכל מאזין ולמערכת (ללא כפילויות של CallID)
                                                Object.values(callIDTracker).forEach(call => {
                                                    if (!dataStore.users[call.phone]) dataStore.users[call.phone] = { sec: 0, calls: 0 };
                                                    dataStore.users[call.phone].sec += call.maxSec;
                                                    dataStore.users[call.phone].calls++;
                                                    dataStore.totalSec += call.maxSec;
                                                });
                                        
                                                // לוג השמעות
                                                let dates = [];
                                                for(let d=new Date(start); d<=new Date(end); d.setDate(d.getDate()+1)) dates.push(new Date(d).toISOString().split('T')[0]);
                                        
                                                for (let day of dates) {
                                                    updateProgress(dates.indexOf(day)+1, dates.length);
                                                    try {
                                                        const res = await fetch(`${API}RenderYMGRFile?token=${token}&wath=ivr2:/Log/LogPlaybackPlayStop/LogPlaybackPlayStop.${day}.ymgr&convertType=json`);
                                                        const json = await res.json();
                                                        if (json.data) {
                                                            if (!dataStore.daily[day]) dataStore.daily[day] = 0;
                                                            json.data.forEach(row => {
                                                                const file = row["השמעה"] || "לא ידוע";
                                                                const phone = row["טלפון"] || "חסוי";
                                                                const sec = parseInt(row["סה\"כ שניות"]) || 0;
                                                                const isEnd = row["נקודת יציאה"] === "סוף";
                                                                
                                                                dataStore.daily[day]++; 
                                                                if (isEnd) dataStore.completed++;
                                        
                                                                if (!dataStore.plays[file]) dataStore.plays[file] = { count: 0, sec: 0, drops: 0, folder: row["שלוחה"] || "-" };
                                                                dataStore.plays[file].count++;
                                                                dataStore.plays[file].sec += sec;
                                                                if (!isEnd) dataStore.plays[file].drops++;
                                        
                                                                dataStore.rawActivity.push({ phone, type: 'השמעה', name: file, sec: sec + " ש'", date: day + " " + (row["שעה"] || "") });
                                                            });
                                                        }
                                                    } catch(e) {}
                                                }
                                                renderUI();
                                            }
                                        
                                            function updateProgress(c, t) { 
                                                const pct = Math.round(c/t*100);
                                                document.getElementById('progress-fill').style.width = pct + '%'; 
                                                document.getElementById('progress-text').innerText = pct + '% (' + c + '/' + t + ')';
                                            }
                                        
                                            function renderUI() {
                                                document.getElementById('progBar').style.display = 'none';
                                                document.getElementById('stat-users').innerText = Object.keys(dataStore.users).length.toLocaleString();
                                                document.getElementById('stat-min').innerText = Math.floor(dataStore.totalSec / 60).toLocaleString();
                                                document.getElementById('stat-comp').innerText = dataStore.completed.toLocaleString();
                                                renderExts(); renderPlays(); renderUsers(); updateChart();
                                                addLog("הנתונים מעודכנים ותוקנו.");
                                            }
                                        
                                            function renderExts() {
                                                const sort = document.getElementById('extSort').value;
                                                const q = document.getElementById('extSearch').value.toLowerCase();
                                                let items = Object.entries(dataStore.exts).map(([name, d]) => ({name, ...d})).filter(i => i.name.toLowerCase().includes(q));
                                                items.sort((a,b) => b[sort] - a[sort]);
                                                document.querySelector('#extTable tbody').innerHTML = items.map(i => `
                                                    <tr><td style="color:var(--primary); font-weight:600">${i.name}</td><td>${i.title}</td><td>${i.count}</td><td>${(i.sec/60).toFixed(1)}</td><td>${i.count ? Math.round(i.sec/i.count) : 0} ש'</td></tr>
                                                `).join('');
                                            }
                                        
                                            function renderPlays() {
                                                const q = document.getElementById('playSearch').value.toLowerCase();
                                                let items = Object.entries(dataStore.plays).map(([name, d]) => ({name, ...d})).filter(i => i.name.toLowerCase().includes(q));
                                                items.sort((a,b) => b.count - a.count);
                                                document.querySelector('#playTable tbody').innerHTML = items.map(i => `
                                                    <tr><td>${i.name}</td><td>${i.folder}</td><td>${i.count}</td><td>${(i.sec/60).toFixed(1)}</td>
                                                    <td>-</td><td>${Math.round((i.drops/i.count)*100)}%</td></tr>
                                                `).join('');
                                            }
                                        
                                            function renderUsers() {
                                                const sortKey = document.getElementById('userSort').value;
                                                const q = document.getElementById('userSearch').value;
                                                let items = Object.entries(dataStore.users).map(([phone, d]) => ({
                                                    phone, name: dataStore.names[phone] || "לא ידוע", sec: d.sec, calls: d.calls
                                                })).filter(i => i.phone.includes(q) || i.name.includes(q));
                                                items.sort((a,b) => b[sortKey] - a[sortKey]);
                                                document.querySelector('#usersTable tbody').innerHTML = items.map((i, idx) => `
                                                    <tr class="clickable" onclick="openUserDetail('${i.phone}')">
                                                        <td style="font-weight:bold">${i.phone}</td><td style="color:var(--warning)">${i.name}</td>
                                                        <td style="color:var(--primary); font-weight:bold">${(i.sec/60).toFixed(1)}</td><td>${i.calls}</td>
                                                        <td>${idx < 3 ? '🏆 מוביל' : 'מאזין'}</td>
                                                    </tr>
                                                `).join('');
                                            }
                                        
                                            function openUserDetail(phone) {
                                                currentModalPhone = phone;
                                                document.getElementById('modalTitle').innerText = `פירוט: ${phone}`;
                                                filterModalContent();
                                                document.getElementById('userModal').style.display = 'flex';
                                            }
                                        
                                            function filterModalContent() {
                                                const filter = document.getElementById('modalFilter').value;
                                                const activity = dataStore.rawActivity.filter(a => a.phone === currentModalPhone);
                                                const filtered = filter === 'all' ? activity : activity.filter(a => a.type === filter);
                                                document.querySelector('#modalTable tbody').innerHTML = filtered.map(a => `
                                                    <tr><td style="color:${a.type==='השמעה'?'var(--primary)':'var(--accent)'}; font-weight:bold">${a.type}</td>
                                                    <td>${a.name}</td><td>${a.sec}</td><td>${a.date}</td></tr>
                                                `).join('');
                                            }
                                        
                                            function closeModal() { document.getElementById('userModal').style.display = 'none'; }
                                            function switchTab(e, id) {
                                                document.querySelectorAll('.tab-content').forEach(c => c.classList.add('hidden'));
                                                document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
                                                document.getElementById(id).classList.remove('hidden');
                                                e.currentTarget.classList.add('active');
                                            }
                                            function updateChart() {
                                                if (dailyChart) dailyChart.destroy();
                                                const ctx = document.getElementById('dailyChart').getContext('2d');
                                                dailyChart = new Chart(ctx, {
                                                    type: 'line',
                                                    data: { labels: Object.keys(dataStore.daily), datasets: [{ label: 'פעולות', data: Object.values(dataStore.daily), borderColor: '#38bdf8', tension: 0.4, fill: true, backgroundColor: 'rgba(56, 189, 248, 0.1)' }] },
                                                    options: { plugins: { legend: { display: false } } }
                                                });
                                            }
                                            document.getElementById('startDate').value = document.getElementById('endDate').value = new Date().toISOString().split('T')[0];
                                        </script>
                                        </body>
                                        </html>
                                        

                                        תגובה 1 תגובה אחרונה תגובה ציטוט 0
                                        • י מנותק
                                          יוסף חיים 5
                                          נערך לאחרונה על ידי יוסף חיים 5

                                          @אa
                                          סליחה טעות שלי פשוט נלחץ לי כמה פעמים על האנטר אז הוא הכפיל הכול

                                          א 2 תגובות תגובה אחרונה תגובה ציטוט 0
                                          • א מנותק
                                            אA @יוסף חיים 5
                                            נערך לאחרונה על ידי

                                            @יוסף-חיים-5
                                            הקוד האחרון בספויילר או אחד לפניו?

                                            ק תגובה 1 תגובה אחרונה תגובה ציטוט 0
                                            • פוסט ראשון
                                              פוסט אחרון