diff --git a/public/index.html b/public/index.html index 8ed6966..cdb8ba5 100644 --- a/public/index.html +++ b/public/index.html @@ -30,13 +30,13 @@
-

Règles des cartes

+

Règles du jeu

Les cartes ajoutent des effets spéciaux au-dessus des règles d'échecs classiques. Voici l'essentiel pour jouer :

Remarque : ces règles couvrent uniquement les mécaniques des cartes — pour le jeu d'échecs standard, les mouvements habituels s'appliquent (pions, tours, cavaliers, fous, dames, rois).

diff --git a/public/waiting.html b/public/waiting.html index c84f9c1..f2083a0 100644 --- a/public/waiting.html +++ b/public/waiting.html @@ -4,6 +4,12 @@ ChessNut - Salle d'attente +
@@ -35,6 +41,25 @@
+
+ +
+ + + +
@@ -63,6 +88,14 @@ const autoDrawToggleEl = document.getElementById('autoDrawToggle'); const noRemiseLabelEl = document.getElementById('no-remise'); const noRemiseToggleEl = document.getElementById('no-remiseToggle'); + const customDrawLabelEl = document.getElementById('customDrawLabel'); + const customDrawToggleEl = document.getElementById('customDrawToggle'); + + // Selection state for custom draw (persisted per room) + let selectedCards = new Set(); + function storageKey(){ return `customDrawSelection:${roomId}`; } + function saveSelection(){ try{ localStorage.setItem(storageKey(), JSON.stringify(Array.from(selectedCards))); }catch(_){} } + function loadSelection(){ try{ const v = localStorage.getItem(storageKey()); if(v){ const arr = JSON.parse(v); selectedCards = new Set(arr || []); } }catch(_){} } function log(...args){ console.log(...args); } @@ -137,6 +170,18 @@ } } }catch(_){ } + // show custom draw checkbox to host (UI-only for now) + try{ + if(customDrawLabelEl && customDrawToggleEl){ + if(myPlayerId && roomHostId && myPlayerId === roomHostId){ + customDrawLabelEl.style.display = 'inline-flex'; + // do not override the user's local choice; leave checked as-is + customDrawToggleEl.disabled = false; + } else { + customDrawLabelEl.style.display = 'none'; + } + } + }catch(_){ } }); // register game started handler early so we don't miss the broadcast @@ -195,6 +240,18 @@ } } }catch(_){ } + // show custom draw checkbox to host on initial fetch as well + try{ + if(customDrawLabelEl && customDrawToggleEl){ + if(myPlayerId && roomHostId && myPlayerId === roomHostId){ + customDrawLabelEl.style.display = 'inline-flex'; + // preserve local UI state for this control; do not force-assign checked + customDrawToggleEl.disabled = false; + } else { + customDrawLabelEl.style.display = 'none'; + } + } + }catch(_){ } }catch(_){ } if(roomInfo && roomInfo.status === 'playing'){ // server already marked room as playing; redirect immediately @@ -243,6 +300,113 @@ }); } + // Custom draw toggle (minimal behavior) + // When checked, show a new section and fetch /cards to display a simple list. + if(customDrawToggleEl){ + const customCardsSection = document.getElementById('customCardsSection'); + const customCardsContainer = document.getElementById('customCardsContainer'); + const customSelectAllBtn = document.getElementById('customSelectAll'); + const customDeselectAllBtn = document.getElementById('customDeselectAll'); + customDrawToggleEl.addEventListener('change', async (ev)=>{ + const checked = !!customDrawToggleEl.checked; + log('custom-draw toggled (minimal)', { checked }); + if(customCardsSection) customCardsSection.style.display = checked ? 'block' : 'none'; + if(checked){ + // fetch card list and render simple names + if(customCardsContainer){ + customCardsContainer.textContent = 'Chargement...'; + try{ + const r = await fetch('/cards'); + const data = await r.json(); + const cards = Array.isArray(data) ? data : (data && Array.isArray(data.cards) ? data.cards : []); + if(cards.length === 0){ customCardsContainer.textContent = 'Aucune carte trouvée.'; return; } + // restore previous selection for this room + try{ loadSelection(); }catch(_){} + const grid = document.createElement('div'); + grid.style.display = 'grid'; + grid.style.gridTemplateColumns = 'repeat(auto-fill,minmax(220px,1fr))'; + grid.style.gap = '10px'; + + cards.forEach(c => { + // create the same visual structure as in game.renderHands -> .pokemon-card + const cardEl = document.createElement('div'); + cardEl.className = 'pokemon-card'; + const cardId = (c.id || c.cardId || c.name || c.title || JSON.stringify(c)).toString(); + cardEl.dataset.cardId = cardId; + + const top = document.createElement('div'); top.className = 'pokemon-card-top'; + const art = document.createElement('div'); art.className = 'pokemon-card-art'; art.textContent = ''; + try{ + const cid = (c.cardId || c.id || '').toString().toLowerCase(); + const titleRaw = (c.title || '').toString().toLowerCase(); + let imgSrc = null; + if(cid === 'adoubement' || titleRaw.indexOf('adoub') !== -1) imgSrc = '/assets/img/cards/adoubement.png'; + if(cid === 'folie' || titleRaw.indexOf('folie') !== -1 || titleRaw.indexOf('fou') !== -1) imgSrc = '/assets/img/cards/folie.png'; + if(cid === 'fortification' || titleRaw.indexOf('fortification') !== -1 || titleRaw.indexOf('fortif') !== -1) imgSrc = '/assets/img/cards/fortification.png'; + if(imgSrc){ const img = document.createElement('img'); img.src = imgSrc; img.alt = c.title || cid || 'card'; img.className = 'card-art-img'; img.style.width='100%'; img.style.height='100%'; img.style.objectFit='cover'; art.appendChild(img); } + }catch(e){} + top.appendChild(art); + + const mid = document.createElement('div'); mid.className = 'pokemon-card-mid'; + const h = document.createElement('div'); h.className = 'pokemon-card-title'; h.textContent = c.name || c.title || c.cardId || c.id || 'Carte'; + const p = document.createElement('div'); p.className = 'pokemon-card-desc'; p.textContent = c.short || c.description || ''; + mid.appendChild(h); mid.appendChild(p); + + const footer = document.createElement('div'); footer.className = 'pokemon-card-footer'; + + // add a small select mark (hidden unless selected) + const selectMark = document.createElement('div'); selectMark.className = 'select-mark'; selectMark.textContent = '✓'; selectMark.style.display = 'none'; + cardEl.appendChild(selectMark); + + cardEl.appendChild(top); cardEl.appendChild(mid); cardEl.appendChild(footer); + + // apply selection state if previously selected + if(selectedCards.has(cardId)){ + cardEl.classList.add('selected'); + selectMark.style.display = 'flex'; + } + + // click toggles selection (no other action in waiting room) + cardEl.addEventListener('click', (ev)=>{ + ev.stopPropagation(); + if(selectedCards.has(cardId)){ + selectedCards.delete(cardId); + cardEl.classList.remove('selected'); + selectMark.style.display = 'none'; + } else { + selectedCards.add(cardId); + cardEl.classList.add('selected'); + selectMark.style.display = 'flex'; + } + saveSelection(); + }); + + grid.appendChild(cardEl); + }); + customCardsContainer.innerHTML = ''; + customCardsContainer.appendChild(grid); + }catch(e){ customCardsContainer.textContent = 'Erreur lors du chargement des cartes.'; } + } + } + }); + // wire up select all / deselect all + function setAllVisible(yes){ + // find card elements in the container grid + const els = customCardsContainer ? customCardsContainer.querySelectorAll('.pokemon-card') : []; + els.forEach(el => { + const id = el.dataset.cardId; + const mark = el.querySelector('.select-mark'); + if(yes){ selectedCards.add(id); el.classList.add('selected'); if(mark) mark.style.display = 'flex'; } + else { selectedCards.delete(id); el.classList.remove('selected'); if(mark) mark.style.display = 'none'; } + }); + saveSelection(); + } + if(customSelectAllBtn) customSelectAllBtn.addEventListener('click', (e)=>{ e.preventDefault(); setAllVisible(true); }); + if(customDeselectAllBtn) customDeselectAllBtn.addEventListener('click', (e)=>{ e.preventDefault(); setAllVisible(false); }); + // ensure initial state: hide unless checkbox is already checked + if(customDrawToggleEl.checked && customCardsSection){ customCardsSection.style.display = 'block'; customDrawToggleEl.dispatchEvent(new Event('change')); } + } + // Copy invite link (hidden link, no display) document.getElementById('copyInviteBtn').addEventListener('click', async ()=>{ const link = `${window.location.origin}/waiting.html?roomId=${encodeURIComponent(roomId)}`;