{"id":2582,"date":"2026-04-15T09:49:49","date_gmt":"2026-04-15T09:49:49","guid":{"rendered":"https:\/\/buy-super.com\/?page_id=2582"},"modified":"2026-04-15T10:12:54","modified_gmt":"2026-04-15T10:12:54","slug":"lead-upload","status":"publish","type":"page","link":"https:\/\/buy-super.com\/index.php\/lead-upload\/","title":{"rendered":"Lead Upload"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"2582\" class=\"elementor elementor-2582\" data-elementor-post-type=\"page\">\n\t\t\t\t<div class=\"elementor-element elementor-element-bd143cf e-flex e-con-boxed e-con e-parent\" data-id=\"bd143cf\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-a55c067 elementor-widget elementor-widget-html\" data-id=\"a55c067\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/xlsx\/0.18.5\/xlsx.full.min.js\"><\/script>\r\n<script src=\"https:\/\/unpkg.com\/vue@3\/dist\/vue.global.prod.js\"><\/script>\r\n\r\n<style>\r\n    #app-final-wrapper { all: initial; display: block; font-family: sans-serif; background: #f4f7f9; padding: 25px; color: #333; }\r\n    #app-final-wrapper * { box-sizing: border-box; }\r\n    .card { background: white; padding: 20px; border-radius: 8px; margin-bottom: 20px; box-shadow: 0 2px 4px rgba(0,0,0,0.08); border: 1px solid #dcdcde; }\r\n    .header { margin: 0 0 20px 0; font-size: 22px; font-weight: bold; color: #1d2327; display: flex; justify-content: space-between; align-items: center; }\r\n    \r\n    .grid-row { display: flex; gap: 15px; margin-bottom: 15px; flex-wrap: wrap; }\r\n    .grid-col { flex: 1; min-width: 200px; }\r\n    label { display: block; font-size: 11px; font-weight: bold; margin-bottom: 5px; color: #666; text-transform: uppercase; }\r\n    \r\n    input, select {\r\n        width: 100% !important; padding: 10px !important; border: 1px solid #ccc !important;\r\n        border-radius: 4px !important; background: white !important; font-size: 14px !important; height: 40px !important;\r\n    }\r\n    .btn {\r\n        display: inline-block; padding: 12px 24px !important; border-radius: 4px !important;\r\n        cursor: pointer !important; font-weight: bold !important; border: none !important; color: white !important; transition: 0.2s;\r\n    }\r\n    .btn-blue { background: #2271b1 !important; }\r\n    .btn-green { background: #00a32a !important; width: 100%; font-size: 16px !important; }\r\n    .btn:disabled { background: #ccc !important; opacity: 0.7; }\r\n\r\n    .mapping-table { width: 100%; border-collapse: collapse; margin-top: 10px; }\r\n    .mapping-table th { text-align: left; font-size: 11px; color: #888; padding: 5px; }\r\n    .mapping-table td { padding: 5px; vertical-align: middle; }\r\n\r\n    .table-container { overflow: auto; background: white; border: 1px solid #ddd; max-height: 400px; margin-top: 15px; border-radius: 4px; }\r\n    table.data-table { width: 100%; border-collapse: collapse; font-size: 12px; }\r\n    table.data-table th { background: #f8f9fa; padding: 12px; border: 1px solid #ddd; position: sticky; top: 0; z-index: 5; }\r\n    table.data-table td { padding: 5px; border: 1px solid #ddd; }\r\n    \r\n    .status-sent { background: #edfaef !important; }\r\n    .status-error { background: #fcf0f1 !important; }\r\n    .badge { padding: 2px 6px; border-radius: 10px; font-size: 10px; background: #eee; }\r\n<\/style>\r\n\r\n<div id=\"app-final-wrapper\">\r\n    <div id=\"vue-app\">\r\n        <div class=\"header\">\r\n            <span>Lead Connector Pro<\/span>\r\n            <span class=\"badge\" v-if=\"leads.length\">{{ leads.length }} Leads caricate<\/span>\r\n        <\/div>\r\n\r\n        <div class=\"card\">\r\n            <div class=\"grid-row\">\r\n                <div class=\"grid-col\" style=\"flex: 1.5;\">\r\n                    <label>\ud83d\udcc2 Seleziona File (CSV o Excel)<\/label>\r\n                    <input type=\"file\" @change=\"handleFile\" accept=\".csv, .xlsx, .xls\">\r\n                <\/div>\r\n                <div class=\"grid-col\">\r\n                    <label>\ud83c\udd94 User ID<\/label>\r\n                    <input v-model=\"config.user_id\" type=\"number\">\r\n                <\/div>\r\n                <div class=\"grid-col\">\r\n                    <label>\ud83c\udf0d Country (es: PL, GR, IT)<\/label>\r\n                    <input v-model=\"config.default_country\" type=\"text\" maxlength=\"2\">\r\n                <\/div>\r\n            <\/div>\r\n        <\/div>\r\n\r\n        <div class=\"card\" v-if=\"headers.length > 0\" style=\"background: #f0f6fb; border-color: #bcd1e0;\">\r\n            <label style=\"color: #2271b1; margin-bottom: 15px;\">\u2699\ufe0f Mapping Campi (Sorgente File \u2192 Destinazione API)<\/label>\r\n            \r\n            <table class=\"mapping-table\">\r\n                <thead>\r\n                    <tr>\r\n                        <th>CAMPO API (Destinazione)<\/th>\r\n                        <th>COLONNA FILE (Sorgente)<\/th>\r\n                    <\/tr>\r\n                <\/thead>\r\n                <tbody>\r\n                    <tr>\r\n                        <td><input v-model=\"mapping.name_key\" placeholder=\"Nome campo API (es: name)\"><\/td>\r\n                        <td>\r\n                            <select v-model=\"mapping.name_src\">\r\n                                <option v-for=\"h in headers\" :value=\"h\">{{h}}<\/option>\r\n                            <\/select>\r\n                        <\/td>\r\n                    <\/tr>\r\n                    <tr>\r\n                        <td><input v-model=\"mapping.phone_key\" placeholder=\"Nome campo API (es: phone)\"><\/td>\r\n                        <td>\r\n                            <select v-model=\"mapping.phone_src\">\r\n                                <option v-for=\"h in headers\" :value=\"h\">{{h}}<\/option>\r\n                            <\/select>\r\n                        <\/td>\r\n                    <\/tr>\r\n                    <tr>\r\n                        <td><input v-model=\"mapping.offer_key\" placeholder=\"Nome campo API (es: offer_id)\"><\/td>\r\n                        <td>\r\n                            <select v-model=\"mapping.offer_src\">\r\n                                <option v-for=\"h in headers\" :value=\"h\">{{h}}<\/option>\r\n                            <\/select>\r\n                        <\/td>\r\n                    <\/tr>\r\n                <\/tbody>\r\n            <\/table>\r\n            <p style=\"font-size: 11px; color: #666; margin-top: 10px;\">\r\n                * Modifica i box a sinistra solo se il network richiede nomi diversi da quelli predefiniti.\r\n            <\/p>\r\n        <\/div>\r\n\r\n        <div class=\"card\" v-if=\"leads.length > 0\">\r\n            <label>\u26a1 Modifica Rapida<\/label>\r\n            <div class=\"grid-row\" style=\"align-items:flex-end; margin-bottom: 0;\">\r\n                <div style=\"flex:2\"><select v-model=\"bulk.field\"><option v-for=\"h in headers\" :value=\"h\">{{h}}<\/option><\/select><\/div>\r\n                <div style=\"flex:2\"><input v-model=\"bulk.value\" type=\"text\" placeholder=\"Nuovo valore per tutti\"><\/div>\r\n                <div style=\"flex:1\"><button @click=\"applyBulkUpdate\" class=\"btn btn-blue\" style=\"width:100%\">Applica<\/button><\/div>\r\n            <\/div>\r\n        <\/div>\r\n\r\n        <div class=\"table-container\" v-if=\"leads.length > 0\">\r\n            <table class=\"data-table\">\r\n                <thead>\r\n                    <tr>\r\n                        <th width=\"60\">Stato<\/th>\r\n                        <th v-for=\"h in headers\">{{h}}<\/th>\r\n                    <\/tr>\r\n                <\/thead>\r\n                <tbody>\r\n                    <tr v-for=\"(lead, idx) in leads\" :key=\"idx\" :class=\"{'status-sent': lead._status === 'sent', 'status-error': lead._status === 'error'}\">\r\n                        <td align=\"center\" style=\"font-size: 18px;\">\r\n                            <span v-if=\"lead._status === 'pending'\">\u23f3<\/span>\r\n                            <span v-if=\"lead._status === 'sent'\">\u2705<\/span>\r\n                            <span v-if=\"lead._status === 'error'\">\u274c<\/span>\r\n                        <\/td>\r\n                        <td v-for=\"h in headers\">\r\n                            <input v-model=\"leads[idx][h]\" style=\"border:none !important; background:transparent !important; width:100%;\">\r\n                        <\/td>\r\n                    <\/tr>\r\n                <\/tbody>\r\n            <\/table>\r\n        <\/div>\r\n\r\n        <div v-if=\"leads.length > 0\" style=\"margin-top:20px;\">\r\n            <button @click=\"startSending\" :disabled=\"isSending\" class=\"btn btn-green\">\r\n                {{ isSending ? '\ud83d\ude80 INVIO IN CORSO...' : '\ud83d\ude80 INVIA ORA AL NETWORK' }}\r\n            <\/button>\r\n        <\/div>\r\n    <\/div>\r\n<\/div>\r\n\r\n<script>\r\n(function() {\r\n    const { createApp, ref, reactive } = Vue;\r\n    createApp({\r\n        setup() {\r\n            const leads = ref([]);\r\n            const headers = ref([]);\r\n            const isSending = ref(false);\r\n            const config = reactive({ user_id: '414', default_country: 'PL', batchSize: 5 });\r\n            const bulk = reactive({ field: '', value: '' });\r\n            \r\n            \/\/ Mapping flessibile: Sorgente (File) e Destinazione (Chiave API)\r\n            const mapping = reactive({ \r\n                name_src: '', name_key: 'name',\r\n                phone_src: '', phone_key: 'phone',\r\n                offer_src: '', offer_key: 'offer_id'\r\n            });\r\n\r\n            const handleFile = (e) => {\r\n                const file = e.target.files[0];\r\n                if (!file) return;\r\n                const reader = new FileReader();\r\n                reader.onload = (evt) => {\r\n                    const wb = XLSX.read(evt.target.result, { type: 'binary' });\r\n                    const ws = wb.Sheets[wb.SheetNames[0]];\r\n                    const data = XLSX.utils.sheet_to_json(ws, { defval: \"\" });\r\n                    if (data.length > 0) {\r\n                        headers.value = Object.keys(data[0]);\r\n                        leads.value = data.map(r => ({ ...r, _status: 'pending' }));\r\n                        \r\n                        \/\/ Auto-Mapping Sorgente (per comodit\u00e0)\r\n                        headers.value.forEach(h => {\r\n                            const low = h.toLowerCase();\r\n                            if (low.includes('imi\u0119') || low.includes('name')) mapping.name_src = h;\r\n                            if (low.includes('telefon') || low.includes('phone') || low.includes('numer')) mapping.phone_src = h;\r\n                            if (low.includes('offer')) mapping.offer_src = h;\r\n                        });\r\n                    }\r\n                };\r\n                reader.readAsBinaryString(file);\r\n            };\r\n\r\n            const applyBulkUpdate = () => {\r\n                if (!bulk.field) return;\r\n                leads.value.forEach(l => l[bulk.field] = bulk.value);\r\n            };\r\n\r\n            const startSending = async () => {\r\n                if (!mapping.name_src || !mapping.phone_src) return alert(\"Assicurati di aver mappato Nome e Telefono!\");\r\n                isSending.value = true;\r\n\r\n                for (let i = 0; i < leads.value.length; i += config.batchSize) {\r\n                    const batch = leads.value.slice(i, i + config.batchSize).filter(l => l._status !== 'sent');\r\n                    \r\n                    await Promise.all(batch.map(async (lead) => {\r\n                        try {\r\n                            \/\/ Costruzione dinamica del pacchetto \"data\" usando le chiavi personalizzate\r\n                            const dynamicData = {};\r\n                            dynamicData[mapping.name_key] = lead[mapping.name_src];\r\n                            dynamicData[mapping.phone_key] = String(lead[mapping.phone_src]);\r\n                            dynamicData[mapping.offer_key] = parseInt(lead[mapping.offer_src] || 0);\r\n                            dynamicData['country'] = config.default_country;\r\n\r\n                            const payload = {\r\n                                user_id: parseInt(config.user_id),\r\n                                data: dynamicData\r\n                            };\r\n\r\n                            const response = await fetch('\/proxy-lead.php', {\r\n                                method: 'POST',\r\n                                headers: { 'Content-Type': 'application\/json' },\r\n                                body: JSON.stringify(payload)\r\n                            });\r\n\r\n                            if (response.ok) lead._status = 'sent';\r\n                            else lead._status = 'error';\r\n                        } catch (e) { lead._status = 'error'; }\r\n                    }));\r\n                    await new Promise(r => setTimeout(r, 1000));\r\n                }\r\n                isSending.value = false;\r\n                alert(\"Processo completato!\");\r\n            };\r\n\r\n            return { leads, headers, config, handleFile, bulk, applyBulkUpdate, startSending, isSending, mapping };\r\n        }\r\n    }).mount('#vue-app');\r\n})();\r\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>Lead Connector Pro {{ leads.length }} Leads caricate \ud83d\udcc2 Seleziona File (CSV o Excel) \ud83c\udd94 User ID \ud83c\udf0d Country (es: PL, GR, IT) 0&#8243; style=&#8221;background: #f0f6fb; border-color: #bcd1e0;&#8221;> \u2699\ufe0f Mapping Campi (Sorgente File \u2192 Destinazione API) CAMPO API (Destinazione) COLONNA FILE (Sorgente) {{h}} {{h}} {{h}} * Modifica i box a sinistra solo se il network [&hellip;]<\/p>\n","protected":false},"author":3,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-2582","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/buy-super.com\/index.php\/wp-json\/wp\/v2\/pages\/2582","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/buy-super.com\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/buy-super.com\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/buy-super.com\/index.php\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/buy-super.com\/index.php\/wp-json\/wp\/v2\/comments?post=2582"}],"version-history":[{"count":13,"href":"https:\/\/buy-super.com\/index.php\/wp-json\/wp\/v2\/pages\/2582\/revisions"}],"predecessor-version":[{"id":2595,"href":"https:\/\/buy-super.com\/index.php\/wp-json\/wp\/v2\/pages\/2582\/revisions\/2595"}],"wp:attachment":[{"href":"https:\/\/buy-super.com\/index.php\/wp-json\/wp\/v2\/media?parent=2582"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}