Nessun oggetto della modifica
Nessun oggetto della modifica
 
(40 versioni intermedie di uno stesso utente non sono mostrate)
Riga 1: Riga 1:
<html>
<html>
<h2>🔧 Dashboard Operativa – Masticationpedia</h2>
  <h2>🔧 Dashboard Operativa – Masticationpedia</h2>
<p><em>Centro di comando per progetti, API, file e backup</em></p>
  <p><em>Centro di comando per progetti, API, file e backup</em></p>


<a href="/dashboard/api/log_view.php" target="_blank">🧾 Apri Log Dashboard</a>
  <a href="/dashboard/api/log_view.php" target="_blank">🧾 Apri Log Dashboard</a>
  <button onclick="clearServerLog()">🧹 Svuota Log</button>


  <div style="margin: 2rem 0; display: flex; flex-wrap: wrap; gap: 1rem;">
    <button class="dashboard-toggle" onclick="toggleDashboardBox('api-settings')">⚙️ Connessione API</button>


<!-- 🔘 Pulsanti di navigazione -->
    <button class="dashboard-toggle"
<div style="margin: 2rem 0; display: flex; flex-wrap: wrap; gap: 1rem;">
      onclick="(window.showMpAI ? showMpAI() : (function(){var el=document.getElementById('mpAI'); if(el){ el.style.display='block'; el.scrollIntoView({behavior:'smooth'});} else { alert('#mpAI non trovato'); } })())">
  <button class="dashboard-toggle" onclick="toggleDashboardBox('api-settings')">⚙️ Connessione API</button>
       🤖 Masticationpedia AI
  <button class="dashboard-toggle" onclick="toggleDashboardBox('project-status')">📊 Stato Progetti</button>
     </button>
  <button class="dashboard-toggle" onclick="toggleDashboardBox('chatgpt-plus')">🤖 ChatGPT plus</button>
  <button class="dashboard-toggle" onclick="toggleDashboardBox('test-tools')">🧪 Strumenti di Test</button>
  <button class="dashboard-toggle" onclick="toggleDashboardBox('activity-log')">📘 Registro Attività</button>
  <button class="dashboard-toggle" onclick="uploadToOpenAI()">📄 Carica in OpenAI</button>
</div>
 
<!-- 📦 Connessione API (via server, nessuna key lato client) -->
<div id="api-settings" style="display:none; padding:1rem; border:1px solid #ccc; border-radius:8px; background:#f9f9f9;">
  <strong>Connessione API (protetta dal server)</strong><br><br>
 
  <label>Modello</label>
  <select id="model-select" style="width:100%; margin-bottom:0.5rem;">
    <option value="gpt-4o-2024-05-13" selected>gpt-4o-2024-05-13</option>
    <option value="gpt-4o-mini">gpt-4o-mini</option>
    <option value="gpt-4-turbo-2024-04-09">gpt-4-turbo-2024-04-09</option>
  </select>
 
  <label>Prompt di test</label>
  <textarea id="test-prompt" rows="3" style="width:100%; margin-bottom:0.5rem;">Dimmi una curiosità sulla mandibola</textarea><br>
 
  <button onclick="testAPIConnection()">▶️ Esegui</button>
  <pre id="api-result" style="background:#f0f0f0; padding:1rem; border:1px solid #ccc; margin-top:1rem; white-space:pre-wrap;"></pre>
</div>
 
<!-- 📊 Stato Progetti -->
<div id="project-status" style="display:none; padding:1rem; border:1px solid #ccc; border-radius:8px; background:#f9f9f9;">
  <strong>Stato Progetti:</strong><br><br>
 
 
  <!-- 🧠 Risposta GPT – Analisi progetto (stile ChatGPT) -->
<div style="margin-top: 1rem;">
  <label><strong>🧠 Risposta GPT – Analisi progetto:</strong></label>
  <div id="gptResponse" class="gpt-card" style="
       margin-top:8px; background:#fff; border:1px solid #e6e6e6; border-radius:10px;
      padding:16px; font: 16px/1.6 system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif;
      color:#1f2328; box-shadow: 0 1px 2px rgba(0,0,0,.04);">
     <em style="opacity:.7">Qui apparirà la risposta generata da GPT sull’analisi del progetto…</em>
   </div>
   </div>


   <!-- parametri sintetici per dare contesto a GPT -->
   <!-- ============== MASTICATIONPEDIA AI ============== -->
   <div id="gptParams" style="margin-top:14px;padding:10px;border:1px dashed #ccc;border-radius:8px;background:#fcfcfc;">
   <div id="mpAI" class="mpai-root" style="display:none">
     <div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;">
     <div class="mpai-header">
       <input id="p_goal"       placeholder="🎯 Obiettivo (es. mini-corso AI)" />
       <div class="mpai-title">🤖 Masticationpedia <b>AI</b></div>
      <input id="p_audience"   placeholder="👥 Pubblico (es. medici, studenti)" />
      <div class="mpai-actions">
      <input id="p_deliverable" placeholder="📦 Output atteso (es. 6 capitoli + quiz)" />
        <button id="mpai-new-chat" class="mpai-btn ghost">Nuova chat</button>
      <input id="p_constraints" placeholder="⏱️ Vincoli (tempo, budget, tool)" />
        <button id="mpai-clear" class="mpai-btn danger">Pulisci conversazione</button>
        <button id="mpai-save-as-project" class="mpai-btn">💾 Salva come progetto</button>
      </div>
     </div>
     </div>
    <div style="margin-top:10px;">
      <button id="btnAnalyze" style="background:#0a7cff;color:#fff;border:none;padding:.5rem .9rem;border-radius:8px;font-weight:600;">
        Analizza con GPT
      </button>
    </div>
  </div>
</div>


    <div class="mpai-grid">
      <aside class="mpai-col mpai-left">
        <h4>📂 Progetti</h4>
        <div id="mpai-project-list" class="mpai-projects">
          <em class="muted">Carico progetti…</em>
        </div>
        <div class="mpai-new-project">
          <input id="mpai-project-name" type="text" placeholder="Nuovo progetto (A-Z 0-9 _ -)" />
          <button id="mpai-project-create" class="mpai-btn">Crea</button>
        </div>
        <div class="mpai-help muted">
          Ogni progetto mantiene la sua cronologia locale (browser).
        </div>
      </aside>


  <!-- 📁 Gestione Progetti (nuova sezione stabile) -->
      <main class="mpai-col mpai-center">
  <div class="projects-controls" style="margin-top:1.5rem; padding:1rem; border:1px solid #ddd; border-radius:6px; background:#fff;">
        <div id="mpai-uploads" class="mpai-uploads" data-state="idle">
    <h4>📂 Gestione Progetti</h4>
          <div class="mpai-dropzone" id="mpai-dropzone">
    <input id="newProjectName" type="text" placeholder="Nome progetto (A-Z 0-9 _ -)" style="margin-right:6px; padding:4px;">
            <div>
    <button id="btnCreateProject" style="background:#28a745; color:white; border:none; padding:0.3rem 0.8rem; border-radius:4px;">Crea progetto</button>
              <div class="muted" style="margin-bottom:6px;">Trascina qui file <b>sanificati</b> oppure</div>
   
              <label class="mpai-file-label">
    <ul id="projectsList" class="projects-list" style="margin-top:1rem; list-style:none; padding:0;"></ul>
                <input id="mpai-file-input" type="file" multiple style="display:none;">
  </div>
                <span class="mpai-btn">📂 Aggiungi file</span>
              </label>
            </div>
          </div>
          <div id="mpai-file-list" class="mpai-filelist"></div>
        </div>


        <div id="mpai-chat" class="mpai-chat">
          <div class="mpai-msg mpai-hint">
            Benvenuto. Seleziona un progetto a sinistra, oppure scrivi subito: se non c’è un progetto creo una conversazione locale. Le risposte appariranno qui sotto in ordine, come in ChatGPT.
          </div>
        </div>


        <div class="mpai-composer">
          <textarea id="mpai-input" rows="3" placeholder="Scrivi qui la tua domanda..."></textarea>


</div>
          <div class="mpai-composer-right">
            <label class="mpai-check" style="margin:0 0 6px 0;">
              <input id="mpai-drop-urls" type="checkbox">
              Ignora/Cancella URL e allegati per questo invio
            </label>
            <button id="mpai-send" class="mpai-btn primary">Invia</button>
          </div>
        </div>
      </main>


<!-- 🤖 ChatGPT plus (unico contenitore) -->
      <aside class="mpai-col mpai-right">
<div id="chatgpt-plus" style="display:none; padding:1rem; border:1px solid #ccc; border-radius:8px; background:#fcfcfc;">
        <h4>⚙️ Impostazioni</h4>
  <strong>ChatGPT plus – Generazione capitoli</strong><br><br>
        <label class="mpai-field">Modello
 
          <select id="mpai-model">
  <!-- Barra superiore -->
            <option value="gpt-4o-2024-05-13" selected>gpt-4o-2024-05-13</option>
  <div style="display:flex; gap:12px; flex-wrap:wrap; margin-bottom:10px;">
            <option value="gpt-4-turbo-2024-04-09">gpt-4-turbo-2024-04-09</option>
    <label>📁 Progetto:
          </select>
      <select id="mpChatProject">
        </label>
        <option value="Generazione_capitoli" selected>Generazione capitoli</option>
        <label class="mpai-field">Temperatura
      </select>
          <input id="mpai-temp" type="number" min="0" max="1" step="0.1" value="0.7">
    </label>
        </label>
    <label>⚙️ Modalità:
         <label class="mpai-check">
      <select id="mpChatMode">
          <input id="mpai-sanitized-only" type="checkbox" checked>
        <option value="analysis">Analisi</option>
          Usa solo file <b>sanificati</b> come contesto
         <option value="rewrite">Riscrittura</option>
        </label>
        <option value="generate">Genera capitolo</option>
        <div class="mpai-help muted">
        <option value="biblio">Bibliografia</option>
          Le API key restano lato server (file sicuro). Il browser non vede mai le chiavi.
      </select>
        </div>
    </label>
      </aside>
  </div>
     </div>
 
  <!-- Allegati -->
  <div style="display:flex; gap:8px; align-items:center; flex-wrap:wrap; margin-bottom:8px;">
    <input id="mpChatFile" type="file" multiple />
    <span id="mpChatDrop" style="border:1px dashed #bbb; padding:6px 10px; border-radius:8px; cursor:pointer; user-select:none;">
      Trascina qui file (solo elenco, non inviati)
     </span>
   </div>
   </div>
  <div id="mpChatFiles" style="display:flex; gap:8px; flex-wrap:wrap; margin-bottom:8px;"></div>


   <!-- Input domanda -->
   <!-- ============ STILI (CSS) ============ -->
   <label><b>Domanda</b> (breve, come in ChatGPT):</label>
   <style>
  <div style="display:flex; gap:8px; align-items:flex-start; margin-bottom:8px;">
    .mpai-root{--bg:#f7f8fa;--card:#fff;--muted:#6b7280;--line:#e5e7eb;--text:#111827;--primary:#0a7cff;--danger:#e74c3c;--accent:#eef2ff;font-family:system-ui,-apple-system,Segoe UI,Roboto,Arial,sans-serif;color:var(--text)}
     <textarea id="mpChatPrompt" rows="3" style="flex:1 1 auto; width:100%;"></textarea>
    .mpai-header{display:flex;align-items:center;justify-content:space-between;margin:8px 0 12px}
     <button id="mpChatSend">Invia</button>
    .mpai-title{font-size:20px;font-weight:700}
  </div>
    .mpai-actions{display:flex;gap:8px}
    .mpai-btn{border:1px solid var(--line);background:#fff;padding:.45rem .8rem;border-radius:8px;cursor:pointer}
    .mpai-btn:hover{background:#f3f4f6}
    .mpai-btn.primary{background:var(--primary);border-color:var(--primary);color:#fff}
    .mpai-btn.danger{background:var(--danger);border-color:var(--danger);color:#fff}
    .mpai-btn.ghost{background:transparent}
    .muted{color:var(--muted)}
    .mpai-grid{display:grid;grid-template-columns:260px minmax(0,1fr) 260px;gap:12px}
    .mpai-col{background:#fff;border:1px solid var(--line);border-radius:12px;padding:12px}
    .mpai-left,.mpai-right{max-height:75vh;overflow:auto}
    .mpai-projects{display:flex;flex-direction:column;gap:6px;margin:8px 0}
    .mpai-projects .row{display:flex;align-items:center;gap:6px;justify-content:space-between;border:1px solid var(--line);border-radius:8px;padding:6px 8px}
    .mpai-projects .row .title{font-family:monospace;font-size:12px}
    .mpai-new-project{display:flex;gap:6px;margin-top:8px}
    .mpai-new-project input{flex:1 1 auto;padding:.45rem .6rem;border:1px solid var(--line);border-radius:8px}
    .mpai-field{display:flex;flex-direction:column;gap:4px;margin:8px 0}
    .mpai-field input,.mpai-field select{padding:.45rem .6rem;border:1px solid var(--line);border-radius:8px}
    .mpai-check{display:flex;align-items:center;gap:8px;margin:8px 0}
    .mpai-center{display:flex;flex-direction:column;gap:10px}
    .mpai-uploads{border:1px dashed var(--line);border-radius:12px;padding:10px;background:#fafafa}
    .mpai-dropzone{display:flex;align-items:center;justify-content:center;border-radius:10px;padding:12px;background:var(--accent);text-align:center}
    .mpai-filelist{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px}
    .mpai-filepill{display:flex;align-items:center;gap:6px;border:1px solid var(--line);border-radius:999px;padding:4px 8px;background:#fff;font-size:12px}
    .mpai-filepill button{border:none;background:transparent;cursor:pointer;color:#c00}
    .mpai-chat{display:flex;flex-direction:column;gap:10px;max-height:50vh;overflow:auto;border:1px solid var(--line);border-radius:12px;padding:10px;background:#fff}
    .mpai-msg{border:1px solid var(--line);border-radius:12px;padding:10px;background:#fff}
    .mpai-msg.user{border-color:#bee3f8;background:#eff6ff}
    .mpai-msg.assistant{border-color:#d1fae5;background:#f0fdf4}
    .mpai-msg.error{border-color:#fecaca;background:#fff1f2}
    .mpai-msg .role{font-weight:600;margin-bottom:4px}
    .mpai-hint{border-style:dashed;color:var(--muted)}
    .mpai-composer{display:flex;gap:8px;align-items:flex-end}
     .mpai-composer textarea{flex:1 1 auto;min-height:90px;border:1px solid var(--line);border-radius:12px;padding:10px}
     .mpai-composer-right{display:flex;flex-direction:column;gap:6px}


  <!-- Output risposta -->
    /* --- Blocchi codice nelle risposte + copia --- */
  <label><b>Risposta</b> (box grande):</label>
    .mp-code{border:1px solid #e5e7eb;border-radius:10px;overflow:hidden;margin:.5rem 0;background:#fff}
  <div id="mpChatAnswer" style="min-height:220px; border:1px solid #ddd; background:#fff; border-radius:8px; padding:10px; white-space:pre-wrap;"></div>
    .mp-code__hdr{display:flex;justify-content:space-between;align-items:center;padding:.5rem .75rem;border-bottom:1px solid #e5e7eb;background:#f8fafc}
    .mp-code__lang{font-family:ui-monospace, Menlo, Consolas, monospace;color:#334155}
    .mp-copy{border:1px solid #e5e7eb;background:#fff;border-radius:8px;padding:.25rem .5rem;cursor:pointer}
    .mp-copy:hover{background:#f1f5f9}
    .mp-code pre{margin:0;padding:.75rem 1rem;overflow:auto;font-family:ui-monospace, Menlo, Consolas, monospace;font-size:13px}
    @media (max-width:1100px){.mpai-grid{grid-template-columns:1fr}.mpai-left,.mpai-right{max-height:none}}
  </style>


   <!-- Explorer semplice dei file salvati -->
   <!-- ========= SEZIONI LEGACY (nascoste) ========= -->
  <div style="margin-top:10px; border-top:1px dashed #ddd; padding-top:10px;">
  <div id="api-settings" style="display:none; padding:1rem; border:1px solid #ccc; border-radius:8px; background:#f9f9f9;">
    <div style="display:flex; align-items:center; gap:8px; margin-bottom:6px;">
    <strong>Connessione API (protetta dal server)</strong><br><br>
      <strong>🗂️ File salvati (output/)</strong>
      <button id="mpChatRefresh"
        title="Aggiorna elenco"
        onclick="window.__forceRefreshList && window.__forceRefreshList()">Aggiorna</button>
    </div>
    <div id="mpSavedList" style="max-height:180px; overflow:auto; border:1px solid #eee; background:#fff; border-radius:8px; padding:6px; font-family:monospace; font-size:12px;">
      <em style="color:#777;">Nessun file elencato. Clicca “Aggiorna”.</em>
    </div>
  </div>


  <!-- Azioni -->
    <label>Modello</label>
  <div style="margin-top:8px; display:flex; gap:8px; justify-content:flex-end;">
    <select id="model-select" style="width:100%; margin-bottom:0.5rem;">
    <button id="mpChatClear">Pulisci</button>
      <option value="gpt-4o-2024-05-13" selected>gpt-4o-2024-05-13</option>
    <button id="mpChatCopy">Copia risposta</button>
      <option value="gpt-4-turbo-2024-04-09">gpt-4-turbo-2024-04-09</option>
     <button id="mpChatSave">📥 Salva risposta</button>
     </select>
  </div>
</div>


<!-- 📁 Importa file dal server (semplificata) -->
     <label>Prompt di test</label>
<div id="serverFileSimpleImportContainer">
     <textarea id="test_prompt" rows="3" style="width:100%; margin-bottom:0.5rem;">Dimmi una curiosità sulla mandibola</textarea>
  <div class="dashboard-box" style="margin-top:1rem;">
    <h4>📁 Importa file dal server (semplificata)</h4>
     <label for="sourcePathInput"><b>📂 Percorso Assoluto del file sorgente:</b></label><br>
     <input type="text" id="sourcePathInput" placeholder="/percorso/assoluto/file.php" style="width:100%; margin-bottom:0.5rem;"><br>
    <label for="projectNameInput"><b>📁 Cartella di destinazione nel progetto:</b></label><br>
    <input type="text" id="projectNameInput" placeholder="nome_progetto/">
  </div>
</div>


<!-- 📁 Caricamento File GPT -->
    <label style="display:inline-flex; gap:.4rem; align-items:center; margin:.25rem 0 .75rem;">
<div style="margin-top:2rem;">
      <input id="test_drop_urls" type="checkbox">
  <h3>📁 Carica File GPT</h3>
      Ignora/Cancella URL e allegati per questo invio
  <label>📁 Project: <input type="text" id="gpt-load-project" value="SSO_LinkedIn" /></label>
    </label><br>
  <label>📂 Subfolder: <input type="text" id="gpt-load-subfolder" value="php" /></label>
  <label>📄 Filename: <input type="text" id="gpt-load-filename" placeholder="es: testGPT.php" /></label>
  <button onclick="caricaFileGPT()">📁 Carica file</button>
</div>


<!-- 🧪 Console JS -->
    <button id="test_run">Esegui</button>
<div id="test-tools" style="display:none; padding:1rem; border:1px solid #ccc; border-radius:8px; background:#f9f9f9;">
  <strong>Console JS:</strong><br>
  <textarea id="codeArea" placeholder="Scrivi codice JS da testare..." style="width:100%; height:100px;"></textarea><br>
<button onclick="checkCodeAI()">🔍 Controlla con AI</button>
  <pre id="consoleOutput" style="background:#000; color:#0f0; padding:1rem; border-radius:8px; font-family:monospace;"></pre>
</div>


<!-- 📘 Registro Attività -->
    <pre id="api-result" style="background:#f0f0f0; padding:1rem; border:1px solid #ccc; margin-top:1rem; white-space:pre-wrap;"></pre>
<div id="activity-log" style="display:none; padding:1rem; border:1px solid #ccc; border-radius:8px; background:#fdfdfd;">
  <strong>📘 Registro attività:</strong>
  <button onclick="clearActivityLog()" style="float:right; background:#e74c3c; color:white; border:none; padding:0.4rem 1rem; border-radius:6px; font-weight:bold;">🧹 Svuota</button>
  <div id="activityLogContent" style="margin-top:1rem; max-height:250px; overflow-y:auto; background:#f0f0f0; padding:1rem; border:1px solid #ccc; border-radius:6px; font-family:monospace; font-size:0.85rem;">
    <em><span style="color:#888;">Registro avviato...</span></em>
   </div>
   </div>
</div>
<!-- ✅ Carica JS esterno (se lo usi) -->
<script src="/dashboard/api/dashboard.js?v=20250907d"></script>
<!-- ✅ Mini-script che POPOLA l’elenco e gestisce “Apri” -->
<script>
document.addEventListener('DOMContentLoaded', () => {
  const refreshBtn = document.getElementById('mpChatRefresh');
  const listBox    = document.getElementById('mpSavedList');
  const answerBox  = document.getElementById('mpChatAnswer');
  const projectSel = document.getElementById('mpChatProject');
  function currentProject(){
    return (projectSel?.value || 'Generazione_capitoli').trim();
  }
  async function refreshList(){
    if (!listBox) return;
    listBox.innerHTML = '<em style="color:#777;">Aggiorno…</em>';
    const prj = currentProject();
    try {
      const r = await fetch('/dashboard/api/list_saved_output.php?project=' + encodeURIComponent(prj) + '&sub=output', { cache:'no-store' });
      const txt = await r.text();
      let j;
      try { j = JSON.parse(txt); }
      catch(e){
        listBox.innerHTML = '<span style="color:#c00;">Risposta non-JSON</span><pre style="white-space:pre-wrap">'+txt.substring(0,400)+'</pre>';
        console.error('list_saved_output NON JSON:', txt);
        return;
      }
      if (!j.ok) { listBox.textContent = 'Errore: ' + (j.error || ''); return; }
      if (!j.files || !j.files.length) { listBox.innerHTML = '<em style="color:#777;">Nessun file salvato.</em>'; return; }
      listBox.innerHTML = j.files.map(f => `
        <div style="display:flex;justify-content:space-between;gap:8px;border-bottom:1px dashed #eee;padding:4px 0;">
          <span>${f.name} <span style="color:#888;">(${f.size} B)</span></span>
          <button class="mpOpen" data-name="${f.name}">Apri</button>
        </div>
      `).join('');
      listBox.querySelectorAll('.mpOpen').forEach(btn => {
        btn.addEventListener('click', async () => {
          const name = btn.getAttribute('data-name');
          try {
            const rr = await fetch('/dashboard/api/read_saved_output.php', {
              method:'POST',
              headers:{'Content-Type':'application/json'},
              body: JSON.stringify({ project: prj, file: name })
            });
            const jj = await rr.json();
            if (!jj.ok) { alert('Errore lettura: ' + (jj.error||'')); return; }
            if (answerBox) answerBox.textContent = jj.content || '';
          } catch (e) {
            alert('Errore apertura file: ' + e.message);
          }
        });
      });
    } catch (e) {
      listBox.textContent = 'Errore JS: ' + e.message;
      console.error(e);
    }
  }
  refreshBtn && refreshBtn.addEventListener('click', refreshList);
  // carica subito l'elenco alla prima apertura
  refreshList();
});
</script>
<script>
<script>
// ✅ Correttore AI – funzione GLOBALE chiamata dal bottone "🔍 Controlla con AI"
// JS minimo temporaneo per sbloccare la pagina
window.checkCodeAI = async function () {
// (serve solo a NON avere errori di sintassi)
  const codeEl = document.getElementById('codeArea');
  const outEl  = document.getElementById('consoleOutput');
  if (!codeEl || !outEl) { alert('Manca #codeArea o #consoleOutput'); return; }
 
  const code = codeEl.value;
  const language = 'php'; // 🔁 cambia a "js", "python", "html", ecc. quando serve
 
  if (!code.trim()) { alert('Incolla del codice da analizzare.'); return; }
 
  outEl.textContent = '⏳ Invio al correttore AI…';
 
  try {
    const r = await fetch('/dashboard/api/ai_check.php', {
      method: 'POST',
      headers: { 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' },
      body: new URLSearchParams({ language, code })
    });
    const j = await r.json();
 
    if (j.ok) {
      let txt = '';
      if (j.lint && j.lint.trim()) {
        txt += '=== LINT ' + language.toUpperCase() + " ===\n" + j.lint + "\n\n";
      }
      txt += (j.analysis || 'Nessun output.');
      outEl.textContent = txt;
    } else {
      outEl.textContent = '❌ Errore: ' + (j.error || 'sconosciuto');
      if (j.raw) outEl.textContent += '\n\nRAW:\n' + j.raw;
    }
  } catch (e) {
    outEl.textContent = '❌ Errore rete: ' + e.message;
  }
};
</script>
 
<script>
/* === Renderer stile ChatGPT: trasforma testo in HTML arioso === */
function renderGpt(text) {
  const box = document.getElementById('gptResponse');
  if (!box) return;
  if (!text) { box.innerHTML = '<em style="opacity:.7">Nessuna risposta</em>'; return; }
 
  // headings ###, ##, #
  let html = (text || '').replace(/\r\n/g, '\n')
    .replace(/^\s*#{3}\s?(.*)$/gm, '<h3 style="font-size:18px;margin:14px 0 6px;">$1</h3>')
    .replace(/^\s*#{2}\s?(.*)$/gm, '<h2 style="font-size:20px;margin:16px 0 8px;">$1</h2>')
    .replace(/^\s*#\s?(.*)$/gm,  '<h1 style="font-size:22px;margin:18px 0 10px;">$1</h1>')
    .replace(/^\s*-\s+(.*)$/gm,  '<li>$1</li>');
 
  // racchiudi sequenze di <li> in <ul>
  html = html.replace(/(?:<li>.*<\/li>\n?)+/gs, m => `<ul style="margin:8px 0 14px 22px;">${m}</ul>`);
 
  // paragrafi (evita di wrappare headings/list)
  html = html.split('\n').map(line => {
    if (/^<h\d|^<ul|^<li|^<\/ul>/.test(line)) return line;
    if (line.trim()==='') return '';
    return `<p style="margin:8px 0;">${line}</p>`;
  }).join('');
 
  box.innerHTML = html;
}
 
/* === Costruzione contesto per GPT dai campi pagina === */
function buildProjectContext() {
  const title = (document.getElementById('newProjectTitle')?.value || '').trim();
  const notes = (document.getElementById('newProjectNotes')?.value || '').trim();
  const goal        = (document.getElementById('p_goal')?.value || '').trim();
  const audience    = (document.getElementById('p_audience')?.value || '').trim();
  const deliverable = (document.getElementById('p_deliverable')?.value || '').trim();
  const constraints = (document.getElementById('p_constraints')?.value || '').trim();
  return { title, notes, goal, audience, deliverable, constraints };
}
 
function buildPromptForGPT() {
  const c = buildProjectContext();
  const out = [];
  out.push(`You are a senior editor and project designer. Provide a clear, actionable plan.`);
  if (c.title)      out.push(`\n# Title\n${c.title}`);
  if (c.notes)      out.push(`\n# Notes\n${c.notes}`);
  if (c.goal)        out.push(`\n# Goal\n${c.goal}`);
  if (c.audience)    out.push(`\n# Audience\n${c.audience}`);
  if (c.deliverable) out.push(`\n# Deliverables\n${c.deliverable}`);
  if (c.constraints) out.push(`\n# Constraints\n${c.constraints}`);
  out.push(`\n# Output format
- Executive Summary
- Strengths & Risks
- Step-by-step Plan (milestones)
- Resources & Budget hints
- Metrics of success`);
  return out.join('\n');
}
 
/* === Azione: Analizza con GPT (usa la tua API già protetta) ===
* Se NON hai ancora un endpoint dedicato, per test immediato simuliamo la risposta.
* Quando vorrai la chiamata reale, sostituisci la parte "FAKE RESPONSE" con una fetch al tuo endpoint server (/dashboard/api/ai_project_analyze.php).
*/
async function runProjectAnalysis() {
  const btn = document.getElementById('btnAnalyze');
  if (!btn) return;
  btn.disabled = true; btn.textContent = 'Analizzo…';
 
  try {
    const prompt = buildPromptForGPT();
 
    // === FAKE RESPONSE PER TEST VISIVO (subito) ===
    const fake = `# Executive Summary
Progetto focalizzato su ${ (document.getElementById('newProjectTitle')?.value || 'il tema indicato') }.
Obiettivo: ${ document.getElementById('p_goal')?.value || 'non specificato' }.
Pubblico: ${ document.getElementById('p_audience')?.value || 'non specificato' }.
 
## Strengths & Risks
- Strength: contenuti specialistici.
- Risk: mancano vincoli chiari (${ document.getElementById('p_constraints')?.value || '—' }).
 
## Step-by-step Plan (milestones)
- M1: Definizione indice capitoli.
- M2: Sviluppo contenuti.
- M3: Revisione clinica e bibliografia.
- M4: Pubblicazione.
 
## Resources & Budget hints
- Autori, revisori, tool AI, hosting video.
 
## Metrics of success
- Capitoli completati, feedback medici, engagement studenti.`;
 
    renderGpt(fake);
 
    // === VERSIONE REALE (quando pronta):
    // const r = await fetch('/dashboard/api/ai_project_analyze.php', {
    //  method: 'POST',
    //  headers: {'Content-Type':'application/x-www-form-urlencoded'},
    //  body: new URLSearchParams({ prompt })
    // });
    // const j = await r.json();
    // if (!j.ok) throw new Error(j.error || 'AI error');
    // renderGpt(j.text);
 
  } catch (e) {
    renderGpt('❌ Errore: ' + e.message);
  } finally {
    btn.disabled = false; btn.textContent = 'Analizza con GPT';
  }
}
 
/* bind del bottone */
document.addEventListener('DOMContentLoaded', () => {
  const b = document.getElementById('btnAnalyze');
  if (b) b.addEventListener('click', runProjectAnalysis);
});
</script>
</script>


</html>
</html>

Versione attuale delle 15:48, 19 ott 2025

🔧 Dashboard Operativa – Masticationpedia

Centro di comando per progetti, API, file e backup

🧾 Apri Log Dashboard