Files
ludikevent_crm/assets/libs/SortableReorder.js
Serreau Jovann c5a0e41803 ```
 feat(ReserverController): Ordonne les formules par position
🎨 style(formule/show.twig): Simplifie le texte de tarification
♻️ refactor(FormulesController): Permet de réordonner les formules
🐛 fix(SortableReorder.js): Corrige l'attribut URL de tbody
 feat(formules/view.twig): Ajoute un sélecteur de type de formule
🐛 fix(formules.twig): Correction de l'ordre d'affichage
🐛 fix(revervation.twig): Correction de la description SEO
```
2026-01-30 10:35:02 +01:00

85 lines
2.5 KiB
JavaScript

import Sortable from 'sortablejs';
/**
* Composant <sortable-reorder url="/api/update-order">
* Encapsule un tableau pour rendre ses lignes triables.
*/
export class SortableReorder extends HTMLTableElement {
constructor() {
super();
this.sortable = null;
}
connectedCallback() {
// On attend que le DOM enfant soit parsé
setTimeout(() => this.init(), 0);
}
init() {
const tbody = this.querySelector('tbody');
const url = tbody.getAttribute('url');
if (!tbody || !url) {
console.warn('SortableReorder: <tbody> ou attribut "url" manquant.');
return;
}
this.sortable = new Sortable(tbody, {
animation: 150,
handle: '.cursor-move', // On attrape par l'icône uniquement
ghostClass: 'sortable-ghost', // Classe ajoutée à l'élément en mouvement (fond bleu)
onEnd: () => this.saveOrder(tbody, url)
});
}
async saveOrder(tbody, url) {
// Récupération des IDs dans le nouvel ordre
const items = Array.from(tbody.querySelectorAll('tr[data-id]'))
.map(tr => tr.dataset.id);
try {
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest'
},
body: JSON.stringify({ items })
});
if (!response.ok) {
throw new Error('Erreur réseau lors de la sauvegarde.');
}
// Petit feedback visuel (optionnel)
this.showFeedback('success');
} catch (error) {
console.error('SortableReorder:', error);
this.showFeedback('error');
}
}
showFeedback(type) {
// Simple flash visuel sur le conteneur
const color = type === 'success' ? 'rgba(16, 185, 129, 0.2)' : 'rgba(239, 68, 68, 0.2)';
const originalTransition = this.style.transition;
this.style.transition = 'background-color 0.3s';
this.style.backgroundColor = color;
setTimeout(() => {
this.style.backgroundColor = 'transparent';
setTimeout(() => {
this.style.transition = originalTransition;
}, 300);
}, 500);
}
disconnectedCallback() {
if (this.sortable) {
this.sortable.destroy();
}
}
}