From 969f6daf7846a9ea725b0009fa75d2ff04c40a8c Mon Sep 17 00:00:00 2001 From: Shni Date: Wed, 15 Oct 2025 10:25:13 -0500 Subject: [PATCH] =?UTF-8?q?feat:=20Agregar=20modal=20de=20selecci=C3=B3n?= =?UTF-8?q?=20de=20roles=20en=20los=20ajustes=20del=20servidor=20para=20me?= =?UTF-8?q?jorar=20la=20experiencia=20del=20usuario?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../partials/dashboard/dashboard_settings.ejs | 153 ++++++++++++------ 1 file changed, 106 insertions(+), 47 deletions(-) diff --git a/src/server/views/partials/dashboard/dashboard_settings.ejs b/src/server/views/partials/dashboard/dashboard_settings.ejs index e003d95..20b3e9b 100644 --- a/src/server/views/partials/dashboard/dashboard_settings.ejs +++ b/src/server/views/partials/dashboard/dashboard_settings.ejs @@ -2,7 +2,6 @@

Ajustes del servidor

- ← Volver al overview
@@ -19,13 +18,31 @@ <% const selectedStaff = (guildConfig && Array.isArray(guildConfig.staff) ? guildConfig.staff.map(String) : (guildConfig && guildConfig.staff ? String(guildConfig.staff).split(',') : [])) || []; %> <% if (typeof guildRoles !== 'undefined' && guildRoles && guildRoles.length) { %>
-
-
- +
+
+ + +
+
Pulsa + para seleccionar roles del servidor.
+ + + - - -
Selecciona roles del servidor. Escribe para filtrar, pulsa Enter para elegir.
<% } else { %> @@ -99,10 +116,25 @@ const staffHidden = document.getElementById('staffHidden'); // Prepare role options (id, name, color) from server-side `guildRoles` - <% const ROLE_JSON = JSON.stringify((guildRoles||[]).map(r=>{ var c; if (typeof r.color !== 'undefined' && r.color !== null) { if (typeof r.color === 'number') { c = '#'+('000000'+r.color.toString(16)).slice(-6); } else { c = (''+r.color).replace(/^#?/, '#'); } } else { c = (r.colorHex||r.hex||'#8b95a0'); } return { id: String(r.id), name: r.name, color: c }; })); %> - const ROLE_OPTIONS = <%- ROLE_JSON %>; + <% + // Build a simple roles array with normalized color (hex string) + const _roles = (guildRoles||[]).map(r=>{ + let c = '#8b95a0'; + if (r && (typeof r.color !== 'undefined') && r.color !== null) { + if (typeof r.color === 'number') { + c = '#'+('000000'+(r.color).toString(16)).slice(-6); + } else { + c = String(r.color).replace(/^#?/, '#'); + } + } else if (r && (r.colorHex || r.hex)) { + c = String(r.colorHex || r.hex).replace(/^#?/, '#'); + } + return { id: String(r.id), name: String(r.name || r.id), color: c }; + }); + %> + const ROLE_OPTIONS = <%- JSON.stringify(_roles) %>; // Initial selected staff IDs (strings) - const INITIAL_STAFF = <%- JSON.stringify(selectedStaff || []) %>; + const INITIAL_STAFF = <%- JSON.stringify(selectedStaff || []) %>; let selectedIds = Array.isArray(INITIAL_STAFF) ? INITIAL_STAFF.slice() : []; @@ -144,48 +176,75 @@ renderChips(); } - if(staffTagInput){ - // initial render - renderChips(); + // initial render of chips + renderChips(); - staffTagInput.addEventListener('input', (e)=>{ - showSuggestions(e.target.value); - }); + // Role picker modal logic + const openRolePicker = document.getElementById('openRolePicker'); + const rolePickerModal = document.getElementById('rolePickerModal'); + const rolePickerBackdrop = document.getElementById('rolePickerBackdrop'); + const rolePickerList = document.getElementById('rolePickerList'); + const rolePickerSearch = document.getElementById('rolePickerSearch'); + const closeRolePicker = document.getElementById('closeRolePicker'); + const rolePickerDone = document.getElementById('rolePickerDone'); - staffTagInput.addEventListener('keydown', (e)=>{ - if(e.key === 'Enter'){ - e.preventDefault(); - // pick first suggestion if any, otherwise ignore - const first = staffSuggestions.querySelector('li'); - if(first){ addId(first.dataset.id); staffTagInput.value=''; staffSuggestions.classList.add('hidden'); } - } else if (e.key === 'Backspace' && !staffTagInput.value){ - // remove last - selectedIds.pop(); renderChips(); - } - }); + function populateRolePicker(filter){ + if(!rolePickerList) return; + const q = (filter||'').trim().toLowerCase(); + const items = ROLE_OPTIONS.filter(r=> !selectedIds.includes(String(r.id)) && (!q || r.name.toLowerCase().includes(q)) ).slice(0,200); + rolePickerList.innerHTML = items.map(r=>`
${r.name}
`).join(''); + } - document.addEventListener('click', (ev)=>{ - if(!staffSuggestions) return; - if(ev.target.closest && ev.target.closest('#staffSuggestions')) return; - if(ev.target === staffTagInput) return; - staffSuggestions.classList.add('hidden'); - }); + function openPicker(){ + if(!rolePickerModal) return; + rolePickerModal.classList.remove('hidden'); + populateRolePicker(''); + setTimeout(()=>{ if(rolePickerSearch) rolePickerSearch.focus(); },50); + } + function closePicker(){ + if(!rolePickerModal) return; + rolePickerModal.classList.add('hidden'); + if(rolePickerSearch) rolePickerSearch.value = ''; + if(rolePickerList) rolePickerList.innerHTML = ''; + } - staffSuggestions.addEventListener('click', (ev)=>{ - const li = ev.target.closest('li'); - if(!li) return; - addId(li.dataset.id); - staffTagInput.value=''; - staffSuggestions.classList.add('hidden'); - staffTagInput.focus(); - }); + if(openRolePicker){ + openRolePicker.addEventListener('click', (e)=>{ e.preventDefault(); openPicker(); }); + } + if(rolePickerBackdrop){ rolePickerBackdrop.addEventListener('click', closePicker); } + if(closeRolePicker){ closeRolePicker.addEventListener('click', closePicker); } - staffChips.addEventListener('click', (ev)=>{ - const btn = ev.target.closest('.remove-chip'); - if(!btn) return; - removeId(btn.dataset.id); - }); - } + if(rolePickerSearch){ + rolePickerSearch.addEventListener('input', ()=> populateRolePicker(rolePickerSearch.value)); + rolePickerSearch.addEventListener('keydown', (e)=>{ + if(e.key === 'Enter'){ + e.preventDefault(); + // pick first item + const first = rolePickerList && rolePickerList.querySelector('.role-item'); + if(first){ addId(first.dataset.id); closePicker(); } + } else if(e.key === 'Escape'){ + closePicker(); + } + }); + } + + if(rolePickerList){ + rolePickerList.addEventListener('click', (ev)=>{ + const it = ev.target.closest && ev.target.closest('.role-item'); + if(!it) return; + addId(it.dataset.id); + // remove the clicked item from list + it.remove(); + }); + } + + if(rolePickerDone){ rolePickerDone.addEventListener('click', (e)=>{ e.preventDefault(); closePicker(); }); } + + staffChips.addEventListener('click', (ev)=>{ + const btn = ev.target.closest('.remove-chip'); + if(!btn) return; + removeId(btn.dataset.id); + }); form.addEventListener('submit', async (e)=>{ e.preventDefault();