{"id":9905,"date":"2025-11-04T13:09:15","date_gmt":"2025-11-04T13:09:15","guid":{"rendered":"https:\/\/www.animcloud.fr\/?page_id=9905"},"modified":"2025-11-04T13:17:28","modified_gmt":"2025-11-04T13:17:28","slug":"matrice-eisonhower","status":"publish","type":"page","link":"https:\/\/www.animcloud.fr\/en\/matrice-eisonhower\/","title":{"rendered":"MATRICE EISONHOWER"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<!DOCTYPE html>\n<html lang=\"fr\">\n<head>\n  <meta charset=\"utf-8\" \/>\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" \/>\n  <title>Matrice d&rsquo;Eisenhower \u2013 AnimCloud<\/title>\n  <style>\n  \/* ===== Design refresh AnimCloud \u2013 Matrice d'Eisenhower ===== *\/\n  :root{\n    \/* Palette neutre + accents accessibles *\/\n    --bg: #0b0f14;           \/* page *\/\n    --panel: #0f1520;        \/* panneaux *\/\n    --panel-2: #0c111a;      \/* cartes *\/\n    --border: #1b2432;       \/* traits *\/\n    --elev: rgba(255,255,255,.04);\n    --text: #e8eef7;         \/* texte principal *\/\n    --muted: #9fb1c7;        \/* texte secondaire *\/\n    --accent: #7dd3fc;       \/* bleu clair *\/\n    --accent-strong:#38bdf8;\n    --ok: #34d399;\n    --warn: #fbbf24;\n    --danger:#f87171;\n    --shadow: 0 6px 24px rgba(0,0,0,.25), inset 0 1px 0 rgba(255,255,255,.02);\n    --radius: 16px;\n  }\n  html,body{margin:0;background:var(--bg);color:var(--text);font-family: ui-sans-serif, -apple-system, Segoe UI, Roboto, Inter, Helvetica, Arial, \"Apple Color Emoji\",\"Segoe UI Emoji\";}\n  *{box-sizing:border-box}\n\n  .wrap{max-width: 1180px; margin:0 auto; padding:28px 20px 48px;}\n\n  \/* Header collant avec blur *\/\n  header.global{position: sticky; top:0; z-index: 30; display:flex; gap:14px; align-items:center; justify-content:space-between; padding:14px 16px; margin:-28px -20px 18px; background: linear-gradient(180deg, rgba(11,15,20,.9), rgba(11,15,20,.45)); backdrop-filter: blur(8px); border-bottom:1px solid var(--border);}  \n  h1{margin:0; font-size: clamp(22px,3.4vw,30px); letter-spacing:.2px}\n  .sub{color:var(--muted); font-size:14px; margin-top:4px}\n\n  .controls{display:flex; flex-wrap:wrap; gap:8px; align-items:center}\n  input, select, button, textarea{background:var(--panel); color:var(--text); border:1px solid var(--border); border-radius:12px; padding:10px 12px; font-size:14px; outline:none; transition:.2s ease;}\n  input:focus, select:focus, textarea:focus{border-color:var(--accent-strong); box-shadow:0 0 0 3px rgba(56,189,248,.25)}\n  button{cursor:pointer; font-weight:600}\n  button.primary{background:var(--accent); color:#07223a; border-color:transparent}\n  button.primary:hover{filter:saturate(115%)}\n  button.ghost{background:transparent}\n  button.warn{background:var(--warn); color:#1b1300; border-color:transparent}\n  button.danger{background:var(--danger); color:#2a0a0a; border-color:transparent}\n\n  \/* Barre d'ajout *\/\n  .new{display:grid; grid-template-columns: 1.7fr 1fr .9fr auto; gap:10px; margin: 8px 0 16px}\n  @media (max-width: 860px){ .new{grid-template-columns: 1fr; } }\n\n  \/* Grille principale *\/\n  .grid{display:grid; grid-template-columns: 1fr 1fr; gap:14px}\n  @media (max-width: 980px){ .grid{grid-template-columns:1fr} }\n  .col{background: var(--panel); border:1px solid var(--border); border-radius: var(--radius); overflow:hidden; box-shadow: var(--shadow)}\n\n  .col header{display:flex; align-items:center; gap:10px; justify-content:flex-start; padding:12px 14px; background:linear-gradient(180deg, var(--elev), rgba(255,255,255,0)); border-bottom:1px solid var(--border)}\n  .col h2{margin:0; font-size:16px; letter-spacing:.3px}\n  .tag{font-size:11px; padding:4px 8px; border-radius:999px; border:1px solid var(--border); color:var(--muted); background:#0b111b}\n\n  \/* Zone de drop *\/\n  .drop{display:flex; flex-direction:column; gap:10px; padding:14px; min-height:200px}\n  .drop:empty::before{content:\"Aucune t\u00e2che ici\u2026\"; color:var(--muted); font-size:13px; padding:10px; border:1px dashed var(--border); border-radius:12px}\n\n  \/* Cartes *\/\n  .card{background: var(--panel-2); border:1px solid var(--border); border-radius:12px; padding:12px 12px; display:grid; grid-template-columns: 1fr auto; gap:8px; align-items:start; box-shadow: var(--shadow)}\n  .card:hover{transform: translateY(-1px);}\n  .card[draggable=\"true\"]{cursor: grab}\n  .card.dragging{opacity:.55; box-shadow:none}\n  .title{font-weight:700; line-height:1.3}\n  .meta{font-size:12px; color:var(--muted); display:flex; gap:8px; flex-wrap:wrap}\n  .pill{font-size:11px; padding:3px 8px; border-radius:999px; border:1px solid var(--border); background:#0b111b}\n  .pill.ok{background: rgba(52,211,153,.12); border-color: rgba(52,211,153,.35)}\n  .pill.warn{background: rgba(251,191,36,.1); border-color: rgba(251,191,36,.45)}\n  .pill.danger{background: rgba(248,113,113,.1); border-color: rgba(248,113,113,.45)}\n  .actions{display:flex; gap:6px}\n  .iconbtn{background:transparent; border:1px solid var(--border); border-radius:10px; padding:6px 8px}\n  .iconbtn:hover{border-color:var(--accent-strong)}\n  .handle{cursor:grab; font-size:16px; opacity:.6; user-select:none; margin-right:6px}\n\n  .footer{display:flex; gap:10px; align-items:center; justify-content:space-between; flex-wrap:wrap; margin-top:16px}\n  .small{font-size:12px; color:var(--muted)}\n  .kbd{font-family: ui-monospace, Menlo, Consolas, monospace; font-size:12px; padding:1px 6px; border:1px solid var(--border); border-radius:6px; background:#0b111b; color:#cbd5e1}\n  .hr{height:1px; background:var(--border); margin:14px 0}\n<\/style>\n<\/head>\n<body>\n  <div class=\"wrap\">\n    <header class=\"global\">\n  <div>\n    <h1>Matrice d&rsquo;Eisenhower \u2013 tableau interactif<\/h1>\n    <div class=\"sub\">Ajoute, d\u00e9place (drag &#038; drop) et garde une trace. Donn\u00e9es stock\u00e9es localement. Option : envoyer chaque modification vers un webhook WordPress.<\/div>\n  <\/div>\n  <div class=\"controls\">\n    <button id=\"btnExport\" class=\"ghost\">Exporter JSON<\/button>\n    <label class=\"small\" for=\"fileImport\" style=\"cursor:pointer;border:1px solid var(--border);border-radius:10px;padding:8px 12px;\">Importer JSON <input id=\"fileImport\" type=\"file\" accept=\"application\/json\" style=\"display:none\"><\/label>\n    <button id=\"btnReset\" class=\"danger\">R\u00e9initialiser<\/button>\n  <\/div>\n<\/header> \n\n    <section class=\"new\">\n      <input id=\"taskTitle\" placeholder=\"Intitul\u00e9 de la t\u00e2che\u2026\" \/>\n      <select id=\"taskQuadrant\">\n        <option value=\"Q1\">\u00c0 faire maintenant (Urgent + Important)<\/option>\n        <option value=\"Q2\">Planifier (Non urgent + Important)<\/option>\n        <option value=\"Q3\">D\u00e9l\u00e9guer (Urgent + Non important)<\/option>\n        <option value=\"Q4\">\u00c9liminer (Non urgent + Non important)<\/option>\n      <\/select>\n      <input id=\"taskDue\" type=\"date\" \/>\n      <button id=\"btnAdd\" class=\"primary\" type=\"button\" aria-label=\"Ajouter la t\u00e2che\">Ajouter<\/button>\n    <\/section>\n\n    <div class=\"grid\">\n      <div class=\"col\" data-q=\"Q1\">\n        <header>\n          <span class=\"tag\">URGENT<\/span>\n          <span class=\"tag\">IMPORTANT<\/span>\n          <h2>\u00c0 FAIRE MAINTENANT<\/h2>\n        <\/header>\n        <div class=\"drop\" id=\"Q1\" aria-label=\"Zone Q1\"><\/div>\n      <\/div>\n      <div class=\"col\" data-q=\"Q2\">\n        <header>\n          <span class=\"tag\">NON URGENT<\/span>\n          <span class=\"tag\">IMPORTANT<\/span>\n          <h2>PLANIFIER<\/h2>\n        <\/header>\n        <div class=\"drop\" id=\"Q2\" aria-label=\"Zone Q2\"><\/div>\n      <\/div>\n      <div class=\"col\" data-q=\"Q3\">\n        <header>\n          <span class=\"tag\">URGENT<\/span>\n          <span class=\"tag\">NON IMPORTANT<\/span>\n          <h2>D\u00c9L\u00c9GUER<\/h2>\n        <\/header>\n        <div class=\"drop\" id=\"Q3\" aria-label=\"Zone Q3\"><\/div>\n      <\/div>\n      <div class=\"col\" data-q=\"Q4\">\n        <header>\n          <span class=\"tag\">NON URGENT<\/span>\n          <span class=\"tag\">NON IMPORTANT<\/span>\n          <h2>\u00c9LIMINER<\/h2>\n        <\/header>\n        <div class=\"drop\" id=\"Q4\" aria-label=\"Zone Q4\"><\/div>\n      <\/div>\n    <\/div>\n\n    <div class=\"footer\">\n      <div class=\"small\">Astuce\u00a0: glisse-d\u00e9pose les cartes entre les quadrants. Double\u2011clique sur un titre pour l\u2019\u00e9diter. <span class=\"kbd\">Ctrl\/Cmd + S<\/span> pour sauvegarder localement.<\/div>\n      <div style=\"display:flex;gap:8px;align-items:center;flex-wrap:wrap;\">\n        <input id=\"webhook\" placeholder=\"URL webhook (optionnel) \u2013 ex: WP Webhooks\" style=\"min-width: 320px;\"\/>\n        <button id=\"btnPing\" class=\"warn\">Tester l&rsquo;envoi<\/button>\n      <\/div>\n    <\/div>\n\n    <div class=\"hr\"><\/div>\n    <div class=\"small\">Donn\u00e9es locales: <span id=\"saveState\">(non sauvegard\u00e9)<\/span><\/div>\n  <\/div>\n\n  <script>\n    \/\/ --------- Mod\u00e8le de donn\u00e9es ---------\n    const STORAGE_KEY = 'animcloud_eisenhower_v1';\n    const state = {\n      items: [], \/\/ {id, title, due, q}\n      webhook: ''\n    };\n\n    \/\/ Pr\u00e9\u2011remplissage depuis le document fourni\n    const seed = [\n      { title: \"Arriver avec une direction de soir\u00e9e\", q: 'Q1' },\n      { title: \"Reunion tp adventure night\", q: 'Q2' },\n      { title: \"Reflechir pour les affectations\", q: 'Q2' },\n      { title: \"Se mettre d\u2019accord sur le theme et la direction de la soir\u00e9e\", q: 'Q3' },\n    ];\n\n    \/\/ --------- Helpers ---------\n    const uid = () => Math.random().toString(36).slice(2,9);\n    const $ = s => document.querySelector(s);\n    const $$ = s => Array.from(document.querySelectorAll(s));\n\n    function save() {\n      const payload = { items: state.items, webhook: $('#webhook').value };\n      localStorage.setItem(STORAGE_KEY, JSON.stringify(payload));\n      markSaved();\n      debounceSync();\n    }\n\n    function load() {\n      const raw = localStorage.getItem(STORAGE_KEY);\n      if (!raw) {\n        state.items = seed.map(s => ({ id: uid(), title: s.title, due: '', q: s.q }));\n        return;\n      }\n      try {\n        const parsed = JSON.parse(raw);\n        state.items = Array.isArray(parsed.items) ? parsed.items : [];\n        state.webhook = parsed.webhook || '';\n        $('#webhook').value = state.webhook;\n      } catch(e){ console.warn('Load error', e); }\n    }\n\n    function render() {\n      ['Q1','Q2','Q3','Q4'].forEach(q => {\n        const host = document.getElementById(q);\n        host.innerHTML = '';\n        state.items.filter(i=>i.q===q).forEach(i => host.appendChild(card(i)));\n      });\n    }\n\n    function card(item){\n      const el = document.createElement('div');\nel.className = 'card';\nel.setAttribute('draggable','true');\nel.dataset.id = item.id;\n\nconst titleWrap = document.createElement('div');\nconst title = document.createElement('div');\ntitle.className = 'title';\ntitle.textContent = item.title;\ntitle.title = 'Double\u2011clic pour \u00e9diter';\ntitle.ondblclick = () => {\n  const nv = prompt('Modifier le titre :', item.title);\n  if (nv !== null) { item.title = nv.trim(); save(); render(); }\n};\n\nconst meta = document.createElement('div');\nmeta.className = 'meta';\n\/\/ mise en \u00e9vidence de l'\u00e9ch\u00e9ance si proche \/ d\u00e9pass\u00e9e\nlet dueClass = '';\nif (item.due){\n  const today = new Date(); today.setHours(0,0,0,0);\n  const d = new Date(item.due);\n  if (d < today) dueClass = 'danger';\n  else if ((d - today) \/ 86400000 <= 3) dueClass = 'warn';\n  else dueClass = 'ok';\n}\nmeta.innerHTML = item.due ? `<span class=\"pill ${dueClass}\">\u00c9ch\u00e9ance\u00a0: ${item.due}<\/span>` : '<span class=\"pill\">Sans \u00e9ch\u00e9ance<\/span>';\n\ntitleWrap.append(title, meta);\n\nconst right = document.createElement('div');\nright.className = 'actions';\n\nconst handle = document.createElement('div');\nhandle.className = 'handle';\nhandle.textContent = '\u22ee\u22ee';\n\nconst editBtn = document.createElement('button');\neditBtn.className = 'iconbtn';\neditBtn.textContent = '\u270f\ufe0f';\neditBtn.title = 'Renommer';\neditBtn.onclick = () => title.ondblclick();\n\nconst delBtn = document.createElement('button');\ndelBtn.className = 'iconbtn';\ndelBtn.textContent = '\ud83d\uddd1\ufe0f';\ndelBtn.title = 'Supprimer';\ndelBtn.onclick = () => { if(confirm('Supprimer cette carte ?')){ state.items = state.items.filter(x=>x.id!==item.id); save(); render(); } };\n\nright.append(handle, editBtn, delBtn);\n\nel.append(titleWrap, right);\n\n\/\/ Drag & drop\nel.addEventListener('dragstart', (e)=>{ el.classList.add('dragging'); e.dataTransfer.setData('text\/plain', item.id); });\nel.addEventListener('dragend', ()=> el.classList.remove('dragging'));\n\nreturn el;\n    }\n\n    \/\/ Drop zones\n    $$('.drop').forEach(zone => {\n      zone.addEventListener('dragover', (e)=>{ e.preventDefault(); });\n      zone.addEventListener('drop', (e)=>{\n        e.preventDefault();\n        const id = e.dataTransfer.getData('text\/plain');\n        const it = state.items.find(x=>x.id===id);\n        if (it) { it.q = zone.id; save(); render(); }\n      });\n    });\n\n    \/\/ Add new item \u2013 en \u00e9coute robuste (WordPress peut perturber les handlers inline)\nfunction addItem(){\n  const t = $('#taskTitle').value.trim();\n  if(!t) return alert('Ajoute un intitul\u00e9.');\n  const q = $('#taskQuadrant').value || 'Q2';\n  const d = $('#taskDue').value || '';\n  if(!Array.isArray(state.items)) state.items = [];\n  state.items.push({ id: uid(), title: t, due: d, q });\n  $('#taskTitle').value = ''; $('#taskDue').value='';\n  save(); render();\n}\n\n$('#btnAdd')?.addEventListener('click', addItem);\n\/\/ s\u00e9curit\u00e9 : d\u00e9l\u00e9gation si l\u2019\u00e9l\u00e9ment est recharg\u00e9 par WP\ndocument.addEventListener('click', (e)=>{\n  const el = e.target;\n  if(el && el.id === 'btnAdd') addItem();\n});\n\n    \/\/ Export \/ Import\n    $('#btnExport').onclick = () => {\n      const blob = new Blob([JSON.stringify({ items: state.items }, null, 2)], {type: 'application\/json'});\n      const url = URL.createObjectURL(blob);\n      const a = document.createElement('a');\n      a.href = url; a.download = 'eisenhower_animcloud.json'; a.click();\n      URL.revokeObjectURL(url);\n    };\n    $('#fileImport').onchange = (e) => {\n      const file = e.target.files[0]; if(!file) return;\n      const reader = new FileReader();\n      reader.onload = () => {\n        try{\n          const data = JSON.parse(reader.result);\n          if(Array.isArray(data.items)){\n            state.items = data.items.map(x=>({ id: x.id||uid(), title: x.title||'', due: x.due||'', q: x.q||'Q2' }));\n            save(); render();\n          } else { alert('Fichier invalide.'); }\n        } catch(err){ alert('Import impossible\u00a0: JSON invalide'); }\n      };\n      reader.readAsText(file);\n      e.target.value = '';\n    };\n\n    \/\/ Reset\n    $('#btnReset').onclick = () => {\n      if(confirm('R\u00e9initialiser le tableau ?')){\n        localStorage.removeItem(STORAGE_KEY);\n        state.items = seed.map(s => ({ id: uid(), title: s.title, due: '', q: s.q }));\n        $('#webhook').value = '';\n        save(); render();\n      }\n    };\n\n    \/\/ Webhook test\n    $('#btnPing').onclick = async () => {\n      const url = $('#webhook').value.trim();\n      if(!url) return alert('Renseigne l\\'URL du webhook (ex: WP Webhooks > Receive Data).');\n      try{\n        await fetch(url, { method:'POST', headers:{'Content-Type':'application\/json'}, body: JSON.stringify(payload()) });\n        alert('Envoi effectu\u00e9 au webhook.');\n      }catch(e){ alert('Erreur d\\'envoi au webhook. Regarde la console.'); console.error(e); }\n    };\n\n    \/\/ Sauvegarde au clavier\n    window.addEventListener('keydown', (e)=>{\n      if((e.ctrlKey||e.metaKey) && e.key.toLowerCase()==='s'){\n        e.preventDefault(); save();\n      }\n    });\n\n    \/\/ Indicateur d'\u00e9tat\n    let saveTimer;\n    function markDirty(){ clearTimeout(saveTimer); $('#saveState').textContent = 'modifications non enregistr\u00e9es'; }\n    function markSaved(){ $('#saveState').textContent = 'enregistr\u00e9 localement'; clearTimeout(saveTimer); saveTimer = setTimeout(()=>$('#saveState').textContent='\u2014', 2500); }\n\n    \/\/ Sync vers webhook (optionnel) \u2013 anti-spam avec debounce\n    let syncTimer;\n    function debounceSync(){\n      clearTimeout(syncTimer);\n      syncTimer = setTimeout(()=>{ autoSync(); }, 1200);\n    }\n    function payload(){\n      return {\n        source: 'animcloud_eisenhower',\n        when: new Date().toISOString(),\n        url: location.href,\n        data: state.items\n      };\n    }\n    async function autoSync(){\n      const url = $('#webhook').value.trim();\n      if(!url) return; \/\/ webhook optionnel\n      try{\n        await fetch(url, { method:'POST', headers:{'Content-Type':'application\/json'}, body: JSON.stringify(payload()) });\n      } catch(e) { console.warn('Webhook error', e); }\n    }\n\n    \/\/ Observers basiques pour marquer dirty quand on tape dans les champs\n    ['taskTitle','taskDue','taskQuadrant','webhook'].forEach(id => {\n      const el = document.getElementById(id);\n      el && el.addEventListener('input', markDirty);\n      el && el.addEventListener('change', markDirty);\n    });\n\n    \/\/ Init\n    load();\n    render();\n    markSaved();\n  <\/script>\n<\/body>\n<\/html>\n\n","protected":false},"excerpt":{"rendered":"<p>Matrice d&rsquo;Eisenhower \u2013 AnimCloud Matrice d&rsquo;Eisenhower \u2013 tableau interactif Ajoute, d\u00e9place (drag &#038; drop) et garde une trace. Donn\u00e9es stock\u00e9es localement. Option : envoyer chaque modification vers un webhook WordPress. Exporter JSON Importer JSON R\u00e9initialiser \u00c0 faire maintenant (Urgent + Important)Planifier (Non urgent + Important)D\u00e9l\u00e9guer (Urgent + Non important)\u00c9liminer (Non urgent + Non important) Ajouter [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-9905","page","type-page","status-publish","hentry"],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.animcloud.fr\/en\/wp-json\/wp\/v2\/pages\/9905","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.animcloud.fr\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.animcloud.fr\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.animcloud.fr\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.animcloud.fr\/en\/wp-json\/wp\/v2\/comments?post=9905"}],"version-history":[{"count":4,"href":"https:\/\/www.animcloud.fr\/en\/wp-json\/wp\/v2\/pages\/9905\/revisions"}],"predecessor-version":[{"id":9909,"href":"https:\/\/www.animcloud.fr\/en\/wp-json\/wp\/v2\/pages\/9905\/revisions\/9909"}],"wp:attachment":[{"href":"https:\/\/www.animcloud.fr\/en\/wp-json\/wp\/v2\/media?parent=9905"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}