{"id":118,"date":"2026-03-28T13:19:13","date_gmt":"2026-03-28T13:19:13","guid":{"rendered":"https:\/\/utiles.fagales360.com\/?page_id=118"},"modified":"2026-03-28T13:19:13","modified_gmt":"2026-03-28T13:19:13","slug":"repartidores","status":"publish","type":"page","link":"https:\/\/utiles.fagales360.com\/?page_id=118","title":{"rendered":"Repartidores"},"content":{"rendered":"\n<!DOCTYPE html>\n<html lang=\"es\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <title>App Repartidores &#8211; Pro<\/title>\n    <script src=\"https:\/\/cdn.tailwindcss.com\"><\/script>\n    <link rel=\"stylesheet\" href=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/font-awesome\/6.4.0\/css\/all.min.css\">\n    <style>\n        input, button, textarea { font-size: 16px !important; }\n        .hide-arrows::-webkit-outer-spin-button, .hide-arrows::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }\n        .hide-arrows { -moz-appearance: textfield; }\n        body { -webkit-tap-highlight-color: transparent; }\n    <\/style>\n<\/head>\n<body class=\"bg-gray-100 text-gray-800 antialiased pb-24\">\n\n    <!-- VISTA 1: PEDIDOS -->\n    <div id=\"view-pedidos\" class=\"view-section max-w-md mx-auto p-2 md:p-4 space-y-4\">\n        \n        <!-- Pre-cargar Pedido -->\n        <div class=\"bg-white rounded-xl shadow p-4\">\n            <h2 class=\"text-lg font-bold mb-3 border-b pb-2\"><i class=\"fa-solid fa-cart-plus text-blue-600 mr-2\"><\/i>Nuevo Pedido<\/h2>\n            <div class=\"space-y-3\">\n                <input type=\"text\" id=\"clientName\" class=\"w-full border rounded-lg p-2 focus:ring-2 focus:ring-blue-500 outline-none\" placeholder=\"\ud83d\udc64 Nombre del Cliente\">\n                <input type=\"text\" id=\"productName\" class=\"w-full border rounded-lg p-2 focus:ring-2 focus:ring-blue-500 outline-none\" placeholder=\"\ud83d\udce6 Producto (Ej. Pollo)\">\n                <div class=\"grid grid-cols-2 gap-3\">\n                    <input type=\"number\" id=\"qty\" class=\"w-full border rounded-lg p-2 focus:ring-2 focus:ring-blue-500 outline-none hide-arrows\" placeholder=\"Cant.\" value=\"1\">\n                    <input type=\"number\" id=\"usdCost\" class=\"w-full border rounded-lg p-2 focus:ring-2 focus:ring-blue-500 outline-none hide-arrows\" placeholder=\"Costo Total USD\">\n                <\/div>\n                <button id=\"addTaskBtn\" class=\"w-full bg-blue-100 text-blue-700 font-bold py-2 rounded-lg shadow-sm border border-blue-200 hover:bg-blue-200 transition\">A\u00f1adir a la Hoja<\/button>\n            <\/div>\n        <\/div>\n\n        <!-- Lista Agrupada por Clientes -->\n        <div class=\"flex justify-between items-center px-1\">\n            <h2 class=\"text-lg font-bold text-gray-700\">Ruta de Entregas<\/h2>\n            <span id=\"progressBadge\" class=\"bg-blue-100 text-blue-800 text-xs font-bold px-2 py-1 rounded\">0\/0 Listos<\/span>\n        <\/div>\n        \n        <div id=\"clientsList\" class=\"space-y-4\">\n            <!-- Inyecci\u00f3n JS -->\n        <\/div>\n        <p id=\"emptyTasks\" class=\"text-gray-400 text-center text-sm py-4 hidden\">No hay pedidos registrados.<\/p>\n    <\/div>\n\n    <!-- VISTA 2: LUGARES -->\n    <div id=\"view-lugares\" class=\"view-section max-w-md mx-auto p-2 md:p-4 space-y-4 hidden\">\n        <div class=\"bg-white rounded-xl shadow p-4 border-l-4 border-purple-500\">\n            <h2 class=\"text-lg font-bold mb-3 border-b pb-2\"><i class=\"fa-solid fa-map-location-dot mr-2 text-purple-600\"><\/i>Lugares Visitados<\/h2>\n            <p class=\"text-xs text-gray-500 mb-3\">Registra d\u00f3nde compraste para el cobro del recorrido.<\/p>\n            <div class=\"flex space-x-2\">\n                <input type=\"text\" id=\"placeName\" class=\"w-full border rounded-lg p-2 focus:ring-2 focus:ring-purple-500 outline-none\" placeholder=\"Ej. Tienda 3ra y 70...\">\n                <button id=\"addPlaceBtn\" class=\"bg-purple-600 text-white px-4 rounded-lg font-bold hover:bg-purple-700\"><i class=\"fa-solid fa-plus\"><\/i><\/button>\n            <\/div>\n            <ul id=\"placesList\" class=\"mt-4 space-y-2 text-sm\"><\/ul>\n        <\/div>\n    <\/div>\n\n    <!-- VISTA 3: RESUMEN Y SYNC -->\n    <div id=\"view-opciones\" class=\"view-section max-w-md mx-auto p-2 md:p-4 space-y-4 hidden\">\n        \n        <div class=\"bg-white rounded-xl shadow p-4 border-l-4 border-blue-500\">\n            <label class=\"block text-sm font-semibold text-gray-700 mb-1\">Tasa del D\u00eda (CUP\/USD)<\/label>\n            <input type=\"number\" id=\"globalRate\" class=\"w-full border-gray-300 rounded-lg p-3 bg-gray-50 border focus:ring-2 focus:ring-blue-500 outline-none hide-arrows font-bold\" value=\"505\">\n        <\/div>\n\n        <!-- Sincronizaci\u00f3n Offline -->\n        <div class=\"bg-gray-900 text-white rounded-xl shadow p-4 space-y-3 border border-gray-700\">\n            <h2 class=\"font-bold text-sm text-blue-400 uppercase\"><i class=\"fa-solid fa-wifi mr-2\"><\/i>Exportar a Notas<\/h2>\n            <p class=\"text-xs text-gray-400\">Pega la lista aqu\u00ed despu\u00e9s de llenarla en tus notas y presiona Cargar.<\/p>\n            <textarea id=\"syncText\" class=\"w-full h-32 bg-black border border-gray-600 rounded p-2 text-sm font-mono text-green-400 outline-none focus:border-blue-500\" placeholder=\"Pega el texto aqu\u00ed...\"><\/textarea>\n            <div class=\"flex space-x-2\">\n                <button id=\"copyToNotesBtn\" class=\"flex-1 bg-gray-700 py-3 rounded font-bold hover:bg-gray-600 text-sm\"><i class=\"fa-solid fa-copy mr-1\"><\/i> Copiar<\/button>\n                <button id=\"loadFromNotesBtn\" class=\"flex-1 bg-blue-600 py-3 rounded font-bold hover:bg-blue-500 text-sm\"><i class=\"fa-solid fa-upload mr-1\"><\/i> Cargar<\/button>\n            <\/div>\n        <\/div>\n\n        <!-- Resumen Financiero -->\n        <div class=\"bg-white rounded-xl shadow p-4 border-t-4 border-green-500\">\n            <h2 class=\"font-bold text-gray-700 mb-3 border-b pb-2\"><i class=\"fa-solid fa-chart-pie mr-2\"><\/i>Balance Global<\/h2>\n            <div class=\"flex justify-between items-center mb-4\">\n                <div class=\"text-sm\">\n                    <p class=\"text-gray-500\">Gasto Total: <strong id=\"totalSpentText\" class=\"text-black text-lg\">0 CUP<\/strong><\/p>\n                    <p class=\"text-gray-500\">Margen Global: <strong id=\"globalMarginText\" class=\"text-black text-lg\">0%<\/strong><\/p>\n                <\/div>\n                <button id=\"clearDataBtn\" class=\"bg-red-100 text-red-600 px-4 py-2 rounded-xl shadow-sm border border-red-200 hover:bg-red-200 transition text-sm font-bold\">\n                    <i class=\"fa-solid fa-trash-can mr-1\"><\/i> Limpiar BD\n                <\/button>\n            <\/div>\n            <button id=\"sendReportBtn\" class=\"w-full bg-green-600 text-white font-bold py-3 px-4 rounded-xl shadow-lg flex items-center justify-center hover:bg-green-700 transition\">\n                <i class=\"fa-brands fa-whatsapp text-xl mr-2\"><\/i> Compartir Reporte\n            <\/button>\n        <\/div>\n    <\/div>\n\n    <!-- STICKY BOTTOM MENU -->\n    <nav class=\"fixed bottom-0 left-0 w-full bg-white border-t border-gray-200 shadow-[0_-4px_10px_-1px_rgba(0,0,0,0.05)] z-40 pb-safe\">\n        <div class=\"max-w-md mx-auto flex justify-around\">\n            <button onclick=\"switchTab('pedidos')\" id=\"tab-pedidos\" class=\"tab-btn flex-1 py-3 text-blue-600 flex flex-col items-center transition\">\n                <i class=\"fa-solid fa-box text-xl mb-1\"><\/i>\n                <span class=\"text-[10px] font-bold uppercase\">Pedidos<\/span>\n            <\/button>\n            <button onclick=\"switchTab('lugares')\" id=\"tab-lugares\" class=\"tab-btn flex-1 py-3 text-gray-400 hover:text-blue-500 flex flex-col items-center transition\">\n                <i class=\"fa-solid fa-map-location-dot text-xl mb-1\"><\/i>\n                <span class=\"text-[10px] font-bold uppercase\">Lugares<\/span>\n            <\/button>\n            <button onclick=\"switchTab('opciones')\" id=\"tab-opciones\" class=\"tab-btn flex-1 py-3 text-gray-400 hover:text-blue-500 flex flex-col items-center transition\">\n                <i class=\"fa-solid fa-gear text-xl mb-1\"><\/i>\n                <span class=\"text-[10px] font-bold uppercase\">Ajustes<\/span>\n            <\/button>\n        <\/div>\n    <\/nav>\n\n    <!-- Modal Calculadora de Desglose -->\n    <div id=\"calcModal\" class=\"fixed inset-0 bg-black bg-opacity-60 z-50 flex items-center justify-center p-4 hidden\">\n        <div class=\"bg-white rounded-xl shadow-2xl w-full max-w-sm overflow-hidden flex flex-col max-h-[90vh]\">\n            <div class=\"bg-blue-600 p-3 text-white flex justify-between items-center\">\n                <h3 class=\"font-bold\"><i class=\"fa-solid fa-calculator mr-2\"><\/i>Desglose de Compra<\/h3>\n                <button onclick=\"closeCalculator()\" class=\"text-blue-200 hover:text-white\"><i class=\"fa-solid fa-xmark text-xl\"><\/i><\/button>\n            <\/div>\n            <div class=\"p-4 overflow-y-auto flex-1\">\n                <p class=\"text-xs text-gray-500 mb-3\">A\u00f1ade filas si compraste en varios lugares a distintos precios.<\/p>\n                <div id=\"calcRows\" class=\"space-y-2 mb-4\"><\/div>\n                <button onclick=\"addCalcRow()\" class=\"w-full border-2 border-dashed border-gray-300 text-gray-500 font-bold py-2 rounded-lg hover:bg-gray-50 mb-4 text-sm\">\n                    <i class=\"fa-solid fa-plus mr-1\"><\/i> A\u00f1adir precio distinto\n                <\/button>\n                <div class=\"bg-gray-100 p-3 rounded-lg flex justify-between items-center border\">\n                    <span class=\"font-bold text-gray-600\">Total Calculado:<\/span>\n                    <span id=\"calcGrandTotal\" class=\"font-black text-lg text-blue-700\">0 CUP<\/span>\n                <\/div>\n            <\/div>\n            <div class=\"p-4 border-t bg-gray-50\">\n                <button onclick=\"applyCalculator()\" class=\"w-full bg-blue-600 text-white font-bold py-3 rounded-lg shadow hover:bg-blue-700\">\n                    Aplicar Total\n                <\/button>\n            <\/div>\n        <\/div>\n    <\/div>\n\n    <script>\n        \/\/ TAB ROUTER\n        window.switchTab = (tabId) => {\n            document.querySelectorAll('.view-section').forEach(el => el.classList.add('hidden'));\n            document.getElementById('view-' + tabId).classList.remove('hidden');\n            \n            document.querySelectorAll('.tab-btn').forEach(btn => {\n                btn.classList.remove('text-blue-600');\n                btn.classList.add('text-gray-400');\n            });\n            document.getElementById('tab-' + tabId).classList.remove('text-gray-400');\n            document.getElementById('tab-' + tabId).classList.add('text-blue-600');\n        };\n\n        document.addEventListener('DOMContentLoaded', () => {\n            let tasks = JSON.parse(localStorage.getItem('rep_tasks')) || [];\n            let places = JSON.parse(localStorage.getItem('rep_places')) || [];\n            const rateInput = document.getElementById('globalRate');\n            if(localStorage.getItem('rep_rate')) rateInput.value = localStorage.getItem('rep_rate');\n\n            rateInput.addEventListener('input', () => {\n                localStorage.setItem('rep_rate', rateInput.value);\n                renderApp();\n            });\n\n            \/\/ GESTI\u00d3N DE TAREAS Y CLIENTES\n            document.getElementById('addTaskBtn').addEventListener('click', () => {\n                const client = document.getElementById('clientName').value.trim();\n                const product = document.getElementById('productName').value.trim();\n                const qty = parseFloat(document.getElementById('qty').value) || 1;\n                const usd = parseFloat(document.getElementById('usdCost').value);\n\n                if(!client || !product || isNaN(usd)) return alert('Falta Cliente, Producto o Costo USD.');\n\n                tasks.push({\n                    id: Date.now(), client, product, qty, usd, cup: '', breakdown: [], status: 'PENDIENTE', delivered: false\n                });\n\n                saveAndRender();\n                document.getElementById('productName').value = '';\n                document.getElementById('usdCost').value = '';\n                document.getElementById('productName').focus();\n            });\n\n            window.renderApp = () => {\n                const list = document.getElementById('clientsList');\n                const empty = document.getElementById('emptyTasks');\n                const rate = parseFloat(rateInput.value) || 0;\n                list.innerHTML = '';\n                \n                if (tasks.length === 0) {\n                    empty.classList.remove('hidden');\n                    updateFooter(0, 0);\n                    renderPlaces();\n                    return;\n                }\n                empty.classList.add('hidden');\n\n                \/\/ Agrupar por clientes\n                const grouped = tasks.reduce((acc, obj) => {\n                    if(!acc[obj.client]) acc[obj.client] = { items: [], isDelivered: true };\n                    acc[obj.client].items.push(obj);\n                    if(!obj.delivered) acc[obj.client].isDelivered = false;\n                    return acc;\n                }, {});\n\n                let completedCount = 0, globalBudget = 0, globalSpent = 0;\n\n                for (const [clientName, data] of Object.entries(grouped)) {\n                    let clientHTML = '';\n                    let allPriced = true;\n\n                    data.items.forEach(t => {\n                        const hasPrice = t.cup !== '' && parseFloat(t.cup) > 0;\n                        if(hasPrice) completedCount++;\n                        else allPriced = false;\n\n                        const itemBudget = t.usd * rate;\n                        const itemSpent = hasPrice ? parseFloat(t.cup) : 0; \n                        globalBudget += itemBudget;\n                        globalSpent += itemSpent;\n\n                        let marginPercent = 0, bgColor = 'bg-red-50 border-red-300';\n                        let statusLabel = '<span class=\"text-red-600 text-[10px] font-bold\">FALTA PRECIO<\/span>';\n\n                        if (hasPrice) {\n                            marginPercent = ((itemBudget - itemSpent) \/ itemBudget) * 100;\n                            if (marginPercent >= 10) {\n                                bgColor = 'bg-green-50 border-green-400';\n                                statusLabel = `<span class=\"text-green-700 text-[10px] font-bold\">OK (${marginPercent.toFixed(1)}%)<\/span>`;\n                                t.status = 'OK';\n                            } else if (marginPercent >= 5) {\n                                bgColor = 'bg-yellow-50 border-yellow-400';\n                                statusLabel = `<span class=\"text-yellow-700 text-[10px] font-bold\">L\u00cdMITE (${marginPercent.toFixed(1)}%)<\/span>`;\n                                t.status = 'L\u00cdMITE';\n                            } else {\n                                bgColor = 'bg-red-100 border-red-500';\n                                statusLabel = `<span class=\"text-red-700 text-[10px] font-bold\">P\u00c9RDIDA<\/span>`;\n                                t.status = 'CONSULTA';\n                            }\n                        } else t.status = 'PENDIENTE';\n\n                        const hasBreakdown = t.breakdown && t.breakdown.length > 0;\n                        const calcBtnClass = hasBreakdown ? 'bg-blue-600 text-white' : 'bg-gray-200 text-gray-600 hover:bg-gray-300';\n\n                        clientHTML += `\n                            <div class=\"p-2 rounded border relative transition-colors ${bgColor} mb-2\">\n                                <button onclick=\"deleteTask(${t.id})\" class=\"absolute top-1 right-2 text-gray-400 hover:text-red-600\"><i class=\"fa-solid fa-xmark\"><\/i><\/button>\n                                <p class=\"text-xs text-gray-800 font-bold pr-6\">\ud83d\udce6 ${t.product} (x${t.qty}) | \ud83d\udcb5 Ext: $${t.usd} USD<\/p>\n                                <div class=\"flex items-center space-x-2 mt-2\">\n                                    <div class=\"flex flex-1 shadow-sm rounded\">\n                                        <input type=\"number\" value=\"${t.cup}\" onchange=\"updatePrice(${t.id}, this.value)\" ${data.isDelivered ? 'disabled' : ''} placeholder=\"Total CUP\" class=\"w-full border border-gray-300 p-1.5 rounded-l text-sm focus:ring-2 focus:ring-blue-500 outline-none hide-arrows font-bold\" \/>\n                                        <button onclick=\"openCalculator(${t.id})\" ${data.isDelivered ? 'disabled' : ''} class=\"px-2 rounded-r border border-l-0 border-gray-300 transition ${calcBtnClass}\">\n                                            <i class=\"fa-solid fa-calculator text-sm\"><\/i>\n                                        <\/button>\n                                    <\/div>\n                                    <div class=\"w-20 text-right leading-none\">${statusLabel}<\/div>\n                                <\/div>\n                            <\/div>\n                        `;\n                    });\n\n                    const clientOkBadge = allPriced ? `<span class=\"bg-green-100 text-green-700 text-xs font-bold px-2 py-0.5 rounded border border-green-300\"><i class=\"fa-solid fa-check mr-1\"><\/i>COMPRAS OK<\/span>` : '';\n                    const opacityClass = data.isDelivered ? 'opacity-60 grayscale' : 'shadow-md';\n                    const btnEntregadoClass = data.isDelivered ? 'bg-gray-300 text-gray-600' : 'bg-green-600 text-white hover:bg-green-700';\n                    const btnEntregadoText = data.isDelivered ? '<i class=\"fa-solid fa-rotate-left mr-1\"><\/i> Deshacer' : '<i class=\"fa-solid fa-box-open mr-1\"><\/i> Entregado';\n\n                    list.innerHTML += `\n                        <div class=\"bg-white rounded-xl overflow-hidden border ${opacityClass} transition-all duration-300\">\n                            <div class=\"bg-gray-800 text-white p-3 flex justify-between items-center relative\">\n                                <h3 class=\"font-bold\">\ud83d\udc64 ${clientName}<\/h3>\n                                ${clientOkBadge}\n                                ${data.isDelivered ? '<div class=\"absolute inset-0 flex items-center justify-center pointer-events-none\"><span class=\"border-4 border-red-500 text-red-500 font-black text-2xl uppercase transform -rotate-12 bg-white px-2 rounded-lg opacity-80\">Entregado<\/span><\/div>' : ''}\n                            <\/div>\n                            <div class=\"p-2\">\n                                ${clientHTML}\n                                <button onclick=\"toggleDelivered('${clientName}')\" class=\"w-full mt-1 ${btnEntregadoClass} font-bold py-2 rounded shadow-sm text-sm transition\">\n                                    ${btnEntregadoText}\n                                <\/button>\n                            <\/div>\n                        <\/div>\n                    `;\n                }\n\n                document.getElementById('progressBadge').textContent = `${completedCount}\/${tasks.length} Listos`;\n                updateFooter(globalBudget, globalSpent);\n                renderPlaces();\n            };\n\n            function updateFooter(budget, spent) {\n                document.getElementById('totalSpentText').textContent = spent > 0 ? spent.toLocaleString() + ' CUP' : '0 CUP';\n                let margin = (budget > 0 && spent > 0) ? ((budget - spent) \/ budget) * 100 : 0;\n                const mEl = document.getElementById('globalMarginText');\n                mEl.textContent = margin.toFixed(1) + '%';\n                mEl.className = margin >= 10 ? 'text-green-600 font-bold text-lg' : (margin >= 5 ? 'text-yellow-600 font-bold text-lg' : 'text-red-600 font-bold text-lg');\n            }\n\n            window.updatePrice = (id, val) => {\n                const task = tasks.find(t => t.id === id);\n                if(task) { task.cup = val; task.breakdown = []; saveAndRender(); }\n            };\n\n            window.deleteTask = (id) => { tasks = tasks.filter(t => t.id !== id); saveAndRender(); };\n\n            window.toggleDelivered = (clientName) => {\n                const clientTasks = tasks.filter(t => t.client === clientName);\n                const isCurrentlyDelivered = clientTasks[0].delivered;\n                clientTasks.forEach(t => t.delivered = !isCurrentlyDelivered);\n                saveAndRender();\n            };\n\n            \/\/ GESTI\u00d3N DE LUGARES\n            document.getElementById('addPlaceBtn').addEventListener('click', () => {\n                const pName = document.getElementById('placeName').value.trim();\n                if(!pName) return;\n                places.push({ id: Date.now(), name: pName });\n                localStorage.setItem('rep_places', JSON.stringify(places));\n                document.getElementById('placeName').value = '';\n                renderPlaces();\n            });\n\n            window.deletePlace = (id) => {\n                places = places.filter(p => p.id !== id);\n                localStorage.setItem('rep_places', JSON.stringify(places));\n                renderPlaces();\n            };\n\n            function renderPlaces() {\n                const list = document.getElementById('placesList');\n                list.innerHTML = '';\n                if(places.length === 0) {\n                    list.innerHTML = '<li class=\"text-gray-400 text-xs italic\">Ning\u00fan lugar registrado.<\/li>';\n                    return;\n                }\n                places.forEach(p => {\n                    list.innerHTML += `\n                        <li class=\"flex justify-between items-center bg-gray-50 p-2 rounded border border-gray-200\">\n                            <span><i class=\"fa-solid fa-location-dot text-purple-400 mr-2\"><\/i>${p.name}<\/span>\n                            <button onclick=\"deletePlace(${p.id})\" class=\"text-red-400 p-1\"><i class=\"fa-solid fa-trash\"><\/i><\/button>\n                        <\/li>\n                    `;\n                });\n            }\n\n            function saveAndRender() { localStorage.setItem('rep_tasks', JSON.stringify(tasks)); renderApp(); }\n\n            \/\/ --- L\u00d3GICA CALCULADORA ---\n            let currentCalcTaskId = null;\n            let currentCalcRows = [];\n\n            window.openCalculator = (id) => {\n                currentCalcTaskId = id;\n                const task = tasks.find(t => t.id === id);\n                currentCalcRows = (task.breakdown && task.breakdown.length > 0) ? JSON.parse(JSON.stringify(task.breakdown)) : [{ q: '', p: '' }];\n                document.getElementById('calcModal').classList.remove('hidden');\n                renderCalcRows();\n            };\n\n            window.closeCalculator = () => { document.getElementById('calcModal').classList.add('hidden'); };\n            window.addCalcRow = () => { currentCalcRows.push({ q: '', p: '' }); renderCalcRows(); };\n            window.removeCalcRow = (idx) => { currentCalcRows.splice(idx, 1); renderCalcRows(); updateCalcTotal(); };\n            window.updateCalcInput = (idx, field, val) => { currentCalcRows[idx][field] = val; updateCalcTotal(); };\n\n            function renderCalcRows() {\n                const container = document.getElementById('calcRows');\n                container.innerHTML = '';\n                currentCalcRows.forEach((row, idx) => {\n                    container.innerHTML += `\n                        <div class=\"flex space-x-2 items-center\">\n                            <input type=\"number\" value=\"${row.q}\" oninput=\"updateCalcInput(${idx}, 'q', this.value)\" placeholder=\"Cant.\" class=\"w-1\/3 border rounded p-2 text-sm text-center hide-arrows\">\n                            <span class=\"text-gray-400 text-sm\">x<\/span>\n                            <input type=\"number\" value=\"${row.p}\" oninput=\"updateCalcInput(${idx}, 'p', this.value)\" placeholder=\"Precio Unit.\" class=\"flex-1 border rounded p-2 text-sm hide-arrows\">\n                            <button onclick=\"removeCalcRow(${idx})\" class=\"text-red-400 p-2\"><i class=\"fa-solid fa-trash\"><\/i><\/button>\n                        <\/div>\n                    `;\n                });\n                updateCalcTotal();\n            }\n\n            function updateCalcTotal() {\n                let total = 0;\n                currentCalcRows.forEach(r => total += ((parseFloat(r.q) || 0) * (parseFloat(r.p) || 0)));\n                document.getElementById('calcGrandTotal').textContent = total > 0 ? total.toLocaleString() + ' CUP' : '0 CUP';\n                return total;\n            }\n\n            window.applyCalculator = () => {\n                const total = updateCalcTotal();\n                if(total === 0) return alert('El total no puede ser 0');\n                const task = tasks.find(t => t.id === currentCalcTaskId);\n                if(task) {\n                    task.cup = total;\n                    task.breakdown = currentCalcRows.filter(r => r.q !== '' && r.p !== '');\n                    saveAndRender();\n                    closeCalculator();\n                }\n            };\n\n            \/\/ --- SISTEMA OFFLINE TEXTO ---\n            document.getElementById('copyToNotesBtn').addEventListener('click', () => {\n                if(tasks.length === 0) return alert('Vac\u00edo.');\n                let text = \"=== LISTA DE COMPRAS ===\\n(Edita solo el numero de CUP)\\n\\n\";\n                \n                const grouped = tasks.reduce((a, o) => { (a[o.client] = a[o.client] || []).push(o); return a; }, {});\n                \n                for(const client in grouped) {\n                    text += `\ud83d\udc64 Cliente: ${client}\\n`;\n                    grouped[client].forEach(t => {\n                        \/\/ FIX: Se a\u00f1adi\u00f3 la cantidad (x${t.qty}) al formato de exportaci\u00f3n\n                        text += `  [ID:${t.id}] \ud83d\udce6 ${t.product} (x${t.qty}) | CUP: ${t.cup || ''}\\n`;\n                    });\n                    text += '\\n';\n                }\n\n                document.getElementById('syncText').value = text;\n                navigator.clipboard.writeText(text).then(() => alert('Formato copiado. P\u00e9galo en Notas.'));\n            });\n\n            document.getElementById('loadFromNotesBtn').addEventListener('click', () => {\n                const lines = document.getElementById('syncText').value.split('\\n');\n                let c = 0;\n                lines.forEach(l => {\n                    const m = l.match(\/\\[ID:(\\d+)\\].*CUP:\\s*(\\d+)\/i);\n                    if(m) {\n                        const t = tasks.find(x => x.id === parseInt(m[1]));\n                        if(t && !isNaN(parseFloat(m[2]))) { t.cup = parseFloat(m[2]); t.breakdown = []; c++; }\n                    }\n                });\n                if(c > 0) { saveAndRender(); document.getElementById('syncText').value=''; alert(`Actualizados ${c} precios.`); switchTab('pedidos'); }\n                else alert('No se encontraron precios nuevos en el formato correcto.');\n            });\n\n            document.getElementById('clearDataBtn').addEventListener('click', () => {\n                if(confirm('\u00bfBorrar TODO (Pedidos y Lugares)?')) { \n                    tasks = []; places = []; \n                    localStorage.removeItem('rep_places');\n                    saveAndRender(); \n                }\n            });\n\n            \/\/ ENVIAR REPORTE WHATSAPP\n            document.getElementById('sendReportBtn').addEventListener('click', () => {\n                if(tasks.length === 0 && places.length === 0) return alert('No hay datos.');\n                let text = `\ud83c\udfcd\ufe0f *REPORTE DE RUTA*\\n*Tasa:* ${rateInput.value} CUP\/USD\\n\\n`;\n                let tCup = 0, tUsd = 0;\n\n                const grouped = tasks.reduce((a, o) => { (a[o.client] = a[o.client] || []).push(o); return a; }, {});\n\n                if(tasks.length > 0) text += `\ud83d\uded2 *PEDIDOS*\\n`;\n\n                for(const client in grouped) {\n                    const isDelivered = grouped[client][0].delivered;\n                    text += `\ud83d\udc64 *${client}* ${isDelivered ? '(\u2705 Entregado)' : ''}\\n`;\n                    grouped[client].forEach(p => {\n                        const spent = parseFloat(p.cup || 0);\n                        tCup += spent; tUsd += p.usd;\n                        text += `  \ud83d\udce6 ${p.product} (x${p.qty}) - Ext: $${p.usd}\\n`;\n                        if(p.breakdown && p.breakdown.length > 0) {\n                            text += `      \u21b3 Desglose: ${p.breakdown.map(b => `${b.q}x${b.p}`).join(' + ')}\\n`;\n                        }\n                        text += `  \ud83d\udcb0 Compra: ${spent > 0 ? spent + ' CUP' : 'NO COMPRADO'} [${p.status}]\\n`;\n                    }); text += `\\n`;\n                }\n                \n                if(places.length > 0) {\n                    text += `\ud83d\udccd *LUGARES VISITADOS*\\n`;\n                    places.forEach((p, idx) => text += `${idx+1}. ${p.name}\\n`);\n                    text += `\\n`;\n                }\n\n                text += `\ud83d\udcc8 *RESUMEN*\\nTotal USD: $${tUsd}\\nTotal CUP: ${tCup.toLocaleString()} CUP`;\n\n                try { window.open(`https:\/\/wa.me\/?text=${encodeURIComponent(text)}`, '_blank'); } \n                catch (e) { navigator.clipboard.writeText(text); alert(\"Copiado al portapapeles.\"); }\n            });\n\n            renderApp();\n        });\n    <\/script>\n<\/body>\n<\/html>\n","protected":false},"excerpt":{"rendered":"<p>App Repartidores &#8211; Pro Nuevo Pedido A\u00f1adir a la Hoja Ruta de Entregas 0\/0 Listos No hay pedidos registrados. Lugares [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"class_list":["post-118","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/utiles.fagales360.com\/index.php?rest_route=\/wp\/v2\/pages\/118","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/utiles.fagales360.com\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/utiles.fagales360.com\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/utiles.fagales360.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/utiles.fagales360.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=118"}],"version-history":[{"count":1,"href":"https:\/\/utiles.fagales360.com\/index.php?rest_route=\/wp\/v2\/pages\/118\/revisions"}],"predecessor-version":[{"id":120,"href":"https:\/\/utiles.fagales360.com\/index.php?rest_route=\/wp\/v2\/pages\/118\/revisions\/120"}],"wp:attachment":[{"href":"https:\/\/utiles.fagales360.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=118"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}