137 lines
13 KiB
HTML
Executable File
137 lines
13 KiB
HTML
Executable File
<?php include_once("/opt/wevads-arsenal/public/api/wevads-metrics.php"); ?>
|
||
<!DOCTYPE html>
|
||
<html lang="fr">
|
||
<head>
|
||
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>WEVADS - Ads Commander — WEVADS</title>
|
||
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
|
||
<style>
|
||
:root{--bg:#080b12;--surface:#0f1420;--surface2:#161d2e;--border:rgba(255,255,255,.06);--border-h:rgba(255,255,255,.12);--text:#c8d0e0;--text-dim:#6b7a94;--text-bright:#edf0f7;--red:#ff4d6a;--green:#00e68a;--blue:#3d8bfd;--amber:#ffb547;--purple:#a78bfa;--cyan:#22d3ee;--accent:#3d8bfd;--accent-dark:#0a1a3a}
|
||
*{margin:0;padding:0;box-sizing:border-box}body{font-family:'DM Sans',sans-serif;background:#060a14;color:var(--text);min-height:100vh}
|
||
.header{background:linear-gradient(135deg,var(--accent-dark),var(--bg) 60%);border-bottom:1px solid var(--border);padding:14px 28px;display:flex;align-items:center;gap:18px;position:sticky;top:0;z-index:100;backdrop-filter:blur(20px)}
|
||
.header .logo{font-size:28px}.header h1{font-size:22px;font-weight:700;color:var(--text-bright)}.header h1 span{color:var(--accent)}
|
||
.header .badge{background:rgba(61,139,253,.15);color:var(--accent);padding:4px 12px;border-radius:20px;font-size:11px;font-weight:600}
|
||
.header .back{color:var(--text-dim);text-decoration:none;font-size:13px;margin-left:auto}.header .back:hover{color:var(--accent)}
|
||
.tabs{display:flex;gap:2px;padding:0 28px;background:var(--surface);border-bottom:1px solid var(--border)}
|
||
.tab{padding:12px 22px;font-size:13px;font-weight:500;color:var(--text-dim);cursor:pointer;border-bottom:2px solid transparent;transition:all .2s;user-select:none}
|
||
.tab:hover{color:var(--text)}.tab.active{color:var(--accent);border-bottom-color:var(--accent);font-weight:600}
|
||
.panel{display:none;padding:24px 28px}.panel.active{display:block}
|
||
.kpi-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:14px;margin-bottom:24px}
|
||
.kpi{background:var(--surface);border:1px solid var(--border);border-radius:12px;padding:18px 20px;transition:all .2s}
|
||
.kpi:hover{border-color:var(--border-h);transform:translateY(-2px)}.kpi .label{font-size:11px;font-weight:500;color:var(--text-dim);text-transform:uppercase;letter-spacing:.8px;margin-bottom:8px}
|
||
.kpi .value{font-size:28px;font-weight:700;font-family:'JetBrains Mono',monospace;color:var(--text-bright)}.kpi .sub{font-size:11px;color:var(--text-dim);margin-top:4px}
|
||
.kpi.green .value{color:var(--green)}.kpi.red .value{color:var(--red)}.kpi.blue .value{color:var(--accent)}.kpi.amber .value{color:var(--amber)}
|
||
.ds{background:var(--surface);border:1px solid var(--border);border-radius:12px;overflow:hidden;margin-bottom:20px}
|
||
.dh{padding:14px 20px;display:flex;align-items:center;gap:12px;border-bottom:1px solid var(--border);background:rgba(255,255,255,.01)}
|
||
.dh h3{font-size:14px;font-weight:600;color:var(--text-bright);flex:1}.dh .ct{font-size:12px;color:var(--text-dim);font-family:'JetBrains Mono',monospace}
|
||
table{width:100%;border-collapse:collapse;font-size:13px}th{text-align:left;padding:10px 16px;font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.6px;color:var(--text-dim);background:rgba(0,0,0,.2);border-bottom:1px solid var(--border)}
|
||
td{padding:10px 16px;border-bottom:1px solid var(--border);color:var(--text)}tr:hover td{background:rgba(255,255,255,.02)}tr:last-child td{border-bottom:none}
|
||
.bs{display:inline-block;padding:3px 10px;border-radius:20px;font-size:11px;font-weight:600}
|
||
.bs.active,.bs.active_boosted{background:rgba(0,230,138,.12);color:var(--green)}.bs.paused{background:rgba(255,181,71,.12);color:var(--amber)}.bs.draft{background:rgba(107,122,148,.2);color:var(--text-dim)}.bs.killed{background:rgba(255,77,106,.12);color:var(--red)}.bs.boost{background:rgba(0,230,138,.12);color:var(--green)}.bs.kill{background:rgba(255,77,106,.12);color:var(--red)}.bs.pause{background:rgba(255,181,71,.12);color:var(--amber)}
|
||
.controls{display:flex;gap:10px;flex-wrap:wrap;margin-bottom:18px;align-items:center}
|
||
.btn{padding:8px 18px;border-radius:8px;font-size:13px;font-weight:600;border:none;cursor:pointer;font-family:inherit;transition:all .15s;display:inline-flex;align-items:center;gap:6px}
|
||
.btn-primary{background:var(--accent);color:#fff}.btn-primary:hover{filter:brightness(1.15)}
|
||
.btn-secondary{background:var(--surface2);color:var(--text);border:1px solid var(--border)}.btn-secondary:hover{border-color:var(--border-h)}
|
||
select.ctrl,input.ctrl{padding:8px 14px;border-radius:8px;font-size:13px;font-family:inherit;background:var(--surface2);color:var(--text);border:1px solid var(--border);outline:none}
|
||
.toast{position:fixed;top:20px;right:20px;padding:12px 20px;border-radius:10px;font-size:13px;font-weight:500;z-index:999;animation:si .3s;max-width:400px}
|
||
.toast.info{background:rgba(61,139,253,.9);color:#fff}.toast.success{background:rgba(0,230,138,.9);color:#e2e8f0}.toast.error{background:rgba(255,77,106,.9);color:#fff}
|
||
@keyframes si{from{transform:translateX(100px);opacity:0}to{transform:translateX(0);opacity:1}}
|
||
.empty{text-align:center;padding:60px 20px;color:var(--text-dim)}.empty .icon{font-size:48px;margin-bottom:12px;opacity:.5}
|
||
.fg{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:20px}.fi{display:flex;flex-direction:column;gap:6px}.fi label{font-size:12px;color:var(--text-dim);font-weight:500}
|
||
.wv-status{position:fixed;top:12px;right:140px;z-index:9998;background:rgba(52,211,153,.15);border:1px solid #34d399;border-radius:12px;padding:3px 10px;color:#34d399;font-size:10px;font-weight:700;font-family:'JetBrains Mono',monospace}
|
||
|
||
.sc,.card,[class*="stat-card"]{transition:all .25s ease;position:relative;overflow:hidden}
|
||
.sc:hover,.card:hover,[class*="stat-card"]:hover{transform:translateY(-2px);box-shadow:0 8px 24px rgba(0,0,0,.25)}
|
||
.sc::after,.card::after{content:'';position:absolute;bottom:0;left:0;right:0;height:2px;background:var(--cy,#22d3ee);opacity:0;transition:opacity .25s}
|
||
.sc:hover::after,.card:hover::after{opacity:.7}
|
||
.btn,.button,[class*="btn-"]{transition:all .2s ease}
|
||
.btn:hover,.button:hover{transform:translateY(-1px)}
|
||
@keyframes fadeIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}
|
||
.sc,.card{animation:fadeIn .4s ease both}
|
||
.sc:nth-child(2),.card:nth-child(2){animation-delay:.05s}
|
||
.sc:nth-child(3),.card:nth-child(3){animation-delay:.1s}
|
||
.sc:nth-child(4),.card:nth-child(4){animation-delay:.15s}
|
||
.sc:nth-child(5),.card:nth-child(5){animation-delay:.2s}
|
||
.sc:nth-child(6),.card:nth-child(6){animation-delay:.25s}
|
||
</style>
|
||
<link rel="stylesheet" href="wevads-global.css?v1770777318">
|
||
</head>
|
||
<body>
|
||
|
||
<div class="header"><div class="logo">🎯</div><h1>Ads <span>Commander</span></h1>
|
||
<p style="font-size:12px;color:#64748b;margin:6px 0 16px;max-width:600px;line-height:1.6">Centre de commande publicitaire — pilotage multi-plateforme, budgets, enchères.</p>
|
||
<div class="badge">CROSS-CHANNEL ADS</div><a href="menu.html" class="back">← Menu</a></div>
|
||
<div class="tabs">
|
||
<div class="tab active" data-tab="dashboard">📊 Dashboard</div>
|
||
<div class="tab" data-tab="campaigns">🚀 Campaigns</div>
|
||
<div class="tab" data-tab="create">➕ Create</div>
|
||
<div class="tab" data-tab="arbitrage">⚡ Arbitrage</div>
|
||
<div class="tab" data-tab="accounts">🔑 Accounts</div>
|
||
</div>
|
||
|
||
<div class="panel active" id="panel-dashboard">
|
||
<div class="kpi-grid" id="dK"></div>
|
||
<div class="ds"><div class="dh"><h3>⚡ Recent Decisions</h3><span class="ct" id="dC"></span></div><div id="dD"></div></div>
|
||
<div class="ds"><div class="dh"><h3>🚀 Active Campaigns</h3></div><div id="dA"></div></div>
|
||
</div>
|
||
<div class="panel" id="panel-campaigns">
|
||
<div class="controls"><select class="ctrl" id="cF" onchange="lC()"><option value="">All</option><option value="active">Active</option><option value="paused">Paused</option><option value="draft">Draft</option></select><button class="btn btn-secondary" onclick="lC()">🔄</button></div>
|
||
<div class="ds"><div class="dh"><h3>📊 All Campaigns</h3><span class="ct" id="cC"></span></div><div id="cT"></div></div>
|
||
</div>
|
||
<div class="panel" id="panel-create">
|
||
<div class="ds" style="padding:24px">
|
||
<h3 style="color:var(--text-bright);margin-bottom:20px">➕ Create New Campaign</h3>
|
||
<div class="fg">
|
||
<div class="fi"><label>Campaign Name</label><input class="ctrl" id="fN" placeholder="DE Winter Sale"></div>
|
||
<div class="fi"><label>Platform</label><select class="ctrl" id="fP"><option value="meta">📘 Meta</option><option value="tiktok">🎵 TikTok</option><option value="linkedin">💼 LinkedIn</option><option value="all">🌐 All</option></select></div>
|
||
<div class="fi"><label>Objective</label><select class="ctrl" id="fO"><option value="conversions">🎯 Conversions</option><option value="traffic">🔗 Traffic</option><option value="leads">📋 Leads</option></select></div>
|
||
<div class="fi"><label>Offer Link</label><input class="ctrl" id="fL" placeholder="https://..."></div>
|
||
<div class="fi"><label>Daily Budget (€)</label><input class="ctrl" type="number" id="fB" value="50"></div>
|
||
<div class="fi"><label>ROAS Target</label><input class="ctrl" type="number" id="fR" value="2.0" step="0.1"></div>
|
||
</div>
|
||
<button class="btn btn-primary" onclick="cC2()">🚀 Launch Campaign</button>
|
||
</div>
|
||
</div>
|
||
<div class="panel" id="panel-arbitrage">
|
||
<div class="controls"><button class="btn btn-primary" onclick="rA()">⚡ Run Arbitrage Now</button><button class="btn btn-secondary" onclick="lD()">🔄</button></div>
|
||
<div class="kpi-grid" id="aK"></div>
|
||
<div class="ds"><div class="dh"><h3>📋 Arbitrage History</h3><span class="ct" id="aC"></span></div><div id="aT"></div></div>
|
||
</div>
|
||
<div class="panel" id="panel-accounts">
|
||
<div class="ds"><div class="dh"><h3>🔑 Ad Accounts</h3></div><div id="acT"></div></div>
|
||
</div>
|
||
<script>
|
||
async function loadCommander(){
|
||
try{
|
||
const r=await fetch('/api/ads-platform.php?action=dashboard');
|
||
const d=await r.json();
|
||
if(d.status!=='success')return;
|
||
var t=d.totals||{};
|
||
// Update any stat elements
|
||
var sts=document.querySelectorAll('.stat-value,.kpi-value,.st .n,[class*="stat"]');
|
||
// Build platform table if container exists
|
||
var container=document.querySelector('.platforms-table,table tbody,.card-body,#platforms');
|
||
if(!container) container=document.querySelector('.card:first-child .card-b,table:first-of-type tbody');
|
||
if(container){
|
||
var colors={youtube:'#ff0000',meta:'#1877f2',google:'#060a14',tiktok:'#ff0050',linkedin:'#0a66c2',twitter:'#1da1f2',snapchat:'#fffc00',pinterest:'#e60023',native:'#f97316'};
|
||
var icons={youtube:'\u{1f3ac}',meta:'\u{1f4d8}',google:'\u{1f50d}',tiktok:'\u{1f3b5}',linkedin:'\u{1f4bc}',twitter:'\u{1f426}',snapchat:'\u{1f47b}',pinterest:'\u{1f4cc}',native:'\u{1f4f0}'};
|
||
container.innerHTML='<div style="display:grid;gap:8px">'+(d.platforms||[]).map(p=>{
|
||
var roi=parseFloat(p.spend)>0?((parseFloat(p.revenue)-parseFloat(p.spend))/parseFloat(p.spend)*100).toFixed(0):0;
|
||
return '<div style="display:flex;align-items:center;gap:12px;padding:10px;background:rgba(15,23,42,.6);border-radius:8px;border-left:3px solid '+(colors[p.platform]||'#666')+'"><span style="font-size:20px">'+(icons[p.platform]||'\u{1f4ca}')+'</span><div style="flex:1"><b>'+p.platform.toUpperCase()+'</b><br><span style="font-size:11px;color:#64748b">'+p.active+' actives / '+p.total+' total</span></div><div style="text-align:right"><div style="color:#22c55e;font-weight:700">\u20ac'+parseFloat(p.revenue).toLocaleString()+'</div><div style="font-size:11px;color:#64748b">Spend: \u20ac'+parseFloat(p.spend).toLocaleString()+' | ROI: '+roi+'%</div></div></div>'
|
||
}).join('')+'<div style="padding:12px;text-align:center;background:rgba(139,92,246,.1);border-radius:8px;margin-top:8px"><b style="color:#a78bfa">TOTAL: \u20ac'+t.revenue.toLocaleString()+' revenue | \u20ac'+t.spend.toLocaleString()+' spend | ROI: '+t.roi+'%</b></div></div>';
|
||
}
|
||
}catch(e){console.error(e)}
|
||
}
|
||
loadCommander();
|
||
setInterval(loadCommander,30000);
|
||
function lC(){loadDashboard?loadDashboard():location.reload()}
|
||
function rA(){fetch('/api/ads-platform.php?action=arbitrage').then(r=>r.json()).then(d=>{alert('Arbitrage: '+(d.status||'done'))}).catch(()=>{})}
|
||
function lD(){location.reload()}
|
||
function cC2(){var n=prompt('Campaign name?');if(n)fetch('/api/ads-platform.php?action=create_campaign',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({name:n})}).then(r=>r.json()).then(d=>{alert('Created: '+(d.campaign_id||d.status));location.reload()}).catch(()=>alert('Queued'))}
|
||
</script>
|
||
<script src="arsenal-common.js?v1770778169">
|
||
<?php include("/opt/wevads-arsenal/public/universal-drill.html"); ?>
|
||
</body></html></script>
|