feat: page Mes liens /liens/{slug} avec gestion et réordonnancement

This commit is contained in:
Cedric Abonnel
2026-05-13 00:12:49 +02:00
parent c820bdcc3f
commit a21628e5ad
6 changed files with 337 additions and 2 deletions
+91
View File
@@ -67,6 +67,97 @@
</form>
<!-- Flux RSS -->
<!-- Mes liens -->
<div class="mt-4" id="links">
<div class="d-flex align-items-center gap-3 mb-3">
<h2 class="h6 text-muted mb-0">Mes liens</h2>
<?php if (($profileCurrentSlug ?? '') !== ''): ?>
<a href="/liens/<?= rawurlencode($profileCurrentSlug) ?>" class="small" target="_blank">↗ voir la page publique</a>
<?php endif; ?>
</div>
<div class="row g-3 align-items-start">
<div class="col-md-8">
<?php if (!empty($profileLinks)): ?>
<div class="card mb-3">
<ul class="list-group list-group-flush" id="links-sortable">
<?php foreach ($profileLinks as $_link): ?>
<li class="list-group-item d-flex align-items-center gap-2 py-2" data-id="<?= (int)$_link['id'] ?>">
<span class="drag-handle text-muted me-1" style="cursor:grab">⠿</span>
<div class="flex-grow-1 min-w-0">
<div class="fw-semibold small text-truncate"><?= htmlspecialchars($_link['title'] ?: $_link['url']) ?></div>
<div class="text-muted small text-truncate"><?= htmlspecialchars($_link['url']) ?></div>
</div>
<form method="post" action="/link/delete" class="flex-shrink-0">
<input type="hidden" name="link_id" value="<?= (int)$_link['id'] ?>">
<button class="btn btn-sm btn-outline-danger py-0" data-confirm="Supprimer ce lien ?">✕</button>
</form>
</li>
<?php endforeach; ?>
</ul>
</div>
<form method="post" action="/link/reorder" id="reorder-form" class="d-none">
<?php foreach ($profileLinks as $__i => $_link): ?>
<input type="hidden" name="order[]" value="<?= (int)$_link['id'] ?>">
<?php endforeach; ?>
</form>
<script>
(function() {
const list = document.getElementById('links-sortable');
if (!list) return;
let dragged = null;
list.querySelectorAll('li').forEach(li => {
li.setAttribute('draggable', true);
li.addEventListener('dragstart', () => { dragged = li; li.style.opacity = '.4'; });
li.addEventListener('dragend', () => { dragged = null; li.style.opacity = ''; saveOrder(); });
li.addEventListener('dragover', e => { e.preventDefault(); const after = getDragAfter(list, e.clientY); after ? list.insertBefore(dragged, after) : list.appendChild(dragged); });
});
function getDragAfter(container, y) {
return [...container.querySelectorAll('li:not([style*="opacity"])')].reduce((closest, el) => {
const box = el.getBoundingClientRect();
const offset = y - box.top - box.height / 2;
return offset < 0 && offset > closest.offset ? { offset, element: el } : closest;
}, { offset: Number.NEGATIVE_INFINITY }).element;
}
function saveOrder() {
const form = document.getElementById('reorder-form');
if (!form) return;
form.querySelectorAll('input').forEach(i => i.remove());
list.querySelectorAll('li[data-id]').forEach(li => {
const inp = document.createElement('input');
inp.type = 'hidden'; inp.name = 'order[]'; inp.value = li.dataset.id;
form.appendChild(inp);
});
form.submit();
}
})();
</script>
<?php endif; ?>
</div>
<div class="col-md-4">
<div class="card">
<div class="card-header small fw-semibold">Ajouter un lien</div>
<div class="card-body">
<form method="post" action="/link/add">
<div class="mb-2">
<input type="url" name="link_url" class="form-control form-control-sm"
placeholder="https://…" required>
</div>
<div class="mb-2">
<input type="text" name="link_title" class="form-control form-control-sm"
placeholder="Titre" maxlength="100">
</div>
<div class="mb-3">
<input type="text" name="link_desc" class="form-control form-control-sm"
placeholder="Description courte (optionnel)" maxlength="200">
</div>
<button class="btn btn-primary btn-sm w-100">Ajouter</button>
</form>
</div>
</div>
</div>
</div>
</div>
<div class="mt-4" id="feeds">
<h2 class="h6 text-muted mb-3">Flux RSS</h2>
<div class="row g-3 align-items-start">