Files
ASPIC/mission_test.html

218 lines
8.9 KiB
HTML

<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ASPIC — Test Missions / Compétences</title>
<style>
/* mission_test.html — 11 septembre 2026
Outil de mise au point interne (PAS un écran utilisateur), même esprit
que contact_ia_test.html : look "terminal", pas de polish. Sert à tester
mission_agent.php (dialogue + outils réels) et sites_web.php
(publication) avant toute intégration dans ecran_fond.html — le classeur
"Missions" du bureau n'a encore aucun écran réel (voir journal, section
19), inutile de construire l'écran final avant que le mécanisme lui-même
soit validé en conditions réelles. */
*{box-sizing:border-box;}
html,body{margin:0;padding:0;background:#111;color:#ddd;
font-family:"Segoe UI",Arial,sans-serif;}
#page{max-width:820px;margin:0 auto;padding:20px 16px 60px;}
h1{font-size:16px;color:#888;font-weight:normal;margin:0 0 4px;}
.sous-titre{font-size:12px;color:#666;margin:0 0 20px;}
section{background:#1a1a1a;border:1px solid #333;border-radius:6px;
padding:14px 16px;margin-bottom:16px;}
section h2{font-size:12px;color:#888;text-transform:uppercase;
letter-spacing:.05em;font-weight:normal;margin:0 0 10px;}
label{display:block;font-size:11px;color:#999;margin:8px 0 3px;}
input,textarea,select{width:100%;font:inherit;font-size:13px;
background:#0d0d0d;color:#eee;border:1px solid #444;border-radius:4px;
padding:6px 8px;}
textarea{min-height:60px;resize:vertical;font-family:inherit;}
button{font:inherit;font-size:13px;background:#2a4d2a;color:#bdf7bd;
border:1px solid #3a6d3a;border-radius:5px;padding:7px 16px;
cursor:pointer;margin-top:8px;}
button:disabled{opacity:.4;cursor:default;}
button.secondaire{background:#1a1a1a;color:#ccc;border-color:#444;}
.liste-missions .ligne, .liste-sites .ligne{padding:8px;border-bottom:1px solid #262626;
font-size:13px;cursor:pointer;display:flex;justify-content:space-between;gap:10px;}
.liste-missions .ligne:hover, .liste-sites .ligne:hover{background:#222;}
.liste-missions .ligne.actif{background:#233;}
.badge{font-size:11px;padding:2px 7px;border-radius:10px;background:#333;color:#aaa;}
.badge.ouverte{background:#2a4d2a;color:#bdf7bd;}
.badge.close{background:#4d2a2a;color:#f7bdbd;}
.badge.brouillon{background:#4d3a2a;color:#f7d7bd;}
.badge.publie{background:#2a3d4d;color:#bde0f7;}
#chat{min-height:200px;max-height:400px;overflow-y:auto;background:#000;
border:1px solid #333;border-radius:6px;padding:10px;margin-bottom:8px;}
.bulle{max-width:80%;padding:8px 12px;border-radius:8px;margin:6px 0;
font-size:13px;line-height:1.5;white-space:pre-wrap;}
.bulle.moi{background:#264d73;color:#fff;margin-left:auto;}
.bulle.collab{background:#333;color:#eee;}
.bulle.systeme{background:transparent;color:#7a7;font-size:11px;font-style:italic;}
.fichiers-site{font-size:12px;color:#999;margin-top:4px;}
#zone-saisie{display:flex;gap:8px;}
#zone-saisie textarea{flex:1;}
</style>
</head>
<body>
<div id="page">
<h1>ASPIC — Test Missions / Compétences</h1>
<p class="sous-titre">Outil interne — pas un écran utilisateur final.</p>
<section>
<h2>Nouvelle mission — Sophia / Créer et gérer un site web vitrine</h2>
<label>Titre</label>
<input id="nvTitre" placeholder="ex. Site vitrine Mevelia Solutions">
<label>Objectif (brief donné à Sophia)</label>
<textarea id="nvObjectif" placeholder="Décris ce que le site doit contenir, le ton, les pages attendues..."></textarea>
<button id="btnCreerMission">Ouvrir la mission</button>
<span id="msgCreation" style="margin-left:10px;font-size:12px;"></span>
</section>
<section>
<h2>Missions</h2>
<div id="listeMissions" class="liste-missions"></div>
</section>
<section id="blocChat" style="display:none;">
<h2 id="titreMissionActive"></h2>
<div id="chat"></div>
<div id="zone-saisie">
<textarea id="saisieMessage" placeholder="Écris à Sophia..."></textarea>
<button id="btnEnvoyer">Envoyer</button>
</div>
</section>
<section>
<h2>Sites</h2>
<div id="listeSites" class="liste-sites"></div>
</section>
</div>
<script>
const AGENT_SOPHIA = 13;
const COMPETENCE_SITE_WEB = 'SITE_WEB';
let missionActive = null;
function badge(texte, classe) {
return `<span class="badge ${classe}">${texte}</span>`;
}
async function chargerMissions() {
const r = await fetch('missions.php');
const data = await r.json();
const conteneur = document.getElementById('listeMissions');
conteneur.innerHTML = '';
(data.missions || []).forEach(m => {
const div = document.createElement('div');
div.className = 'ligne' + (missionActive === m.MIS_Incr ? ' actif' : '');
div.innerHTML = `<span>#${m.MIS_Incr} — ${m.MIS_Titre} (${m.AGN_Prenom})</span>${badge(m.MIS_Statut, m.MIS_Statut)}`;
div.addEventListener('click', () => ouvrirMission(m.MIS_Incr, m.MIS_Titre));
conteneur.appendChild(div);
});
}
async function chargerSites() {
const r = await fetch('sites_web.php');
const data = await r.json();
const conteneur = document.getElementById('listeSites');
conteneur.innerHTML = '';
(data.sites || []).forEach(s => {
const div = document.createElement('div');
div.className = 'ligne';
const fichiers = (s.fichiers || []).map(f => f.SWF_CheminRelatif).join(', ') || '(aucun fichier)';
div.innerHTML = `<div>
<div>#${s.SIT_Incr} — ${s.SIT_Nom} ${badge(s.SIT_Statut, s.SIT_Statut)}</div>
<div class="fichiers-site">${fichiers}</div>
</div>`;
if (s.SIT_Statut === 'brouillon' && (s.fichiers || []).length) {
const btn = document.createElement('button');
btn.className = 'secondaire';
btn.textContent = 'Publier';
btn.addEventListener('click', async (e) => {
e.stopPropagation();
btn.disabled = true;
const rp = await fetch('sites_web.php', {
method: 'POST', headers: {'Content-Type':'application/json'},
body: JSON.stringify({action:'publier', SIT_Incr: s.SIT_Incr})
});
const dp = await rp.json();
alert(rp.ok ? 'Publié : ' + dp.chemin_publie : (dp.error || 'Erreur'));
chargerSites();
});
div.appendChild(btn);
}
conteneur.appendChild(div);
});
}
function ajouterBulle(role, texte) {
const bulle = document.createElement('div');
bulle.className = 'bulle ' + role;
bulle.textContent = texte;
document.getElementById('chat').appendChild(bulle);
document.getElementById('chat').scrollTop = 999999;
}
function ouvrirMission(misIncr, titre) {
missionActive = misIncr;
document.getElementById('blocChat').style.display = 'block';
document.getElementById('titreMissionActive').textContent = `Mission #${misIncr} — ${titre}`;
document.getElementById('chat').innerHTML = '';
ajouterBulle('systeme', 'Mission ouverte — écris ton premier message.');
chargerMissions();
}
document.getElementById('btnCreerMission').addEventListener('click', async () => {
const titre = document.getElementById('nvTitre').value.trim();
const objectif = document.getElementById('nvObjectif').value.trim();
const msg = document.getElementById('msgCreation');
if (!titre || !objectif) { msg.textContent = 'Titre et objectif obligatoires.'; return; }
const r = await fetch('missions.php', {
method: 'POST', headers: {'Content-Type':'application/json'},
body: JSON.stringify({MIS_AgentIncr: AGENT_SOPHIA, MIS_CompetenceCode: COMPETENCE_SITE_WEB, MIS_Titre: titre, MIS_Objectif: objectif})
});
const data = await r.json();
if (!r.ok) { msg.textContent = data.error || 'Erreur'; return; }
msg.textContent = 'Mission créée.';
document.getElementById('nvTitre').value = '';
document.getElementById('nvObjectif').value = '';
await chargerMissions();
ouvrirMission(data.MIS_Incr, titre);
});
document.getElementById('btnEnvoyer').addEventListener('click', async () => {
const zone = document.getElementById('saisieMessage');
const texte = zone.value.trim();
if (!texte || !missionActive) return;
zone.value = '';
ajouterBulle('moi', texte);
const attente = document.createElement('div');
attente.className = 'bulle systeme';
attente.textContent = 'Sophia réfléchit...';
document.getElementById('chat').appendChild(attente);
try {
const r = await fetch('mission_agent.php', {
method: 'POST', headers: {'Content-Type':'application/json'},
body: JSON.stringify({MIS_Incr: missionActive, message: texte})
});
const data = await r.json();
attente.remove();
if (!r.ok) { ajouterBulle('systeme', 'Erreur : ' + (data.error || r.status)); return; }
(data.outils || []).forEach(o => {
ajouterBulle('systeme', `[outil] ${o.nom} → ${o.erreur ? 'échec' : 'ok'} : ${o.resultat}`);
});
ajouterBulle('collab', data.reponse);
chargerSites();
} catch (e) {
attente.remove();
ajouterBulle('systeme', 'Erreur réseau');
}
});
chargerMissions();
chargerSites();
</script>
</body>
</html>