Files
ludikevent_crm/assets/admin.js
Serreau Jovann 1896f83107 ```
 feat(reservation/flow): Améliore le flux de réservation et ajoute des options.

Cette commit améliore le flux de réservation, ajoute une estimation des
frais de livraison et gère les options de produit et les paiements.
```
2026-02-05 08:18:29 +01:00

160 lines
6.0 KiB
JavaScript

import './admin.scss';
import * as Sentry from "@sentry/browser";
import * as Turbo from "@hotwired/turbo";
import { RepeatLine } from "./libs/RepeatLine.js";
import { DevisManager } from "./libs/DevisManager.js";
import { CrmEditor } from "./libs/CrmEditor.js";
import { initTomSelect } from "./libs/initTomSelect.js";
import { SearchProduct, SearchOptions } from "./libs/SearchProduct.js";
import { SearchProductDevis, SearchOptionsDevis } from "./libs/SearchProductDevis.js";
import { SearchOptionsProduct } from "./libs/SearchProductProduct.js";
import { SearchProductFormule, SearchOptionsFormule } from "./libs/SearchProductFormule.js";
import PlaningLogestics from "./libs/PlaningLogestics.js";
import {SortableReorder} from "./libs/SortableReorder.js";
import { StripeCommissionCalculator } from "./libs/StripeCommissionCalculator.js";
import { ProductAddOption } from "./libs/ProductAddOption.js";
import { LeafletMap } from "./tools/LeafletMap.js";
// --- CONFIGURATION SENTRY ---
Sentry.init({
dsn: "https://803814be6540031b1c37bf92ba9c0f79@sentry.esy-web.dev/24",
tunnel: "/sentry-tunnel",
integrations: [Sentry.browserTracingIntegration(), Sentry.replayIntegration()],
tracesSampleRate: 1.0,
replaysSessionSampleRate: 0.1,
replaysOnErrorSampleRate: 1.0
});
/**
* Enregistre les Custom Elements de manière groupée
*/
const registerCustomElements = () => {
const elements = [
{ name: 'repeat-line', class: RepeatLine, extends: 'div' },
{ name: 'sortable-reorder', class: SortableReorder, extends: 'table' },
{ name: 'devis-manager', class: DevisManager, extends: 'div' },
{ name: 'search-product', class: SearchProduct, extends: 'button' },
{ name: 'search-productformule', class: SearchProductFormule, extends: 'button' },
{ name: 'search-optionsformule', class: SearchOptionsFormule, extends: 'button' },
{ name: 'search-optionsproduct', class: SearchOptionsProduct, extends: 'button' },
{ name: 'planing-logestics', class: PlaningLogestics },
{ name: 'search-options', class: SearchOptions, extends: 'button' },
{ name: 'search-productdevis', class: SearchProductDevis, extends: 'button' },
{ name: 'search-optionsdevis', class: SearchOptionsDevis, extends: 'button' },
{ name: 'crm-editor', class: CrmEditor, extends: 'textarea' },
{ name: 'stripe-commission-calculator', class: StripeCommissionCalculator, extends: 'div' },
{ name: 'product-add-option', class: ProductAddOption, extends: 'button' },
{ name: 'leaflet-map', class: LeafletMap }
];
elements.forEach(el => {
if (!customElements.get(el.name)) {
if(el.extends != undefined) {
customElements.define(el.name, el.class, { extends: el.extends });
} else {
customElements.define(el.name, el.class);
}
}
});
};
/**
* Preview d'image optimisée
*/
function initImagePreview() {
const input = document.getElementById('product_image_input');
const preview = document.getElementById('product-image-preview');
const placeholder = document.getElementById('product-image-placeholder');
input?.addEventListener('change', ({ target }) => {
const file = target.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = (e) => {
if (preview) {
preview.src = e.target.result;
preview.classList.remove('hidden');
}
placeholder?.classList.add('hidden');
};
reader.readAsDataURL(file);
});
}
/**
* Filtrage dynamique (Contrats, Devis, etc.)
*/
function initDynamicSearch() {
const searchInput = document.getElementById('searchContrat');
const listContainer = document.getElementById('contratsList');
searchInput?.addEventListener('input', (e) => {
const filter = e.target.value.toLowerCase();
const cards = listContainer?.querySelectorAll('.contrat-card');
cards?.forEach(card => {
const isVisible = card.textContent.toLowerCase().includes(filter);
card.classList.toggle('hidden', !isVisible);
card.style.opacity = isVisible ? "1" : "0";
card.style.transform = isVisible ? "scale(1)" : "scale(0.95)";
});
});
}
/**
* Gestion UI : Sidebar, Submenus et Flash messages
*/
function initUI() {
// Sidebar
const elements = {
sidebar: document.getElementById('sidebar'),
overlay: document.getElementById('sidebar-overlay'),
toggleBtn: document.getElementById('sidebar-toggle'),
settingsToggle: document.getElementById('settings-toggle'),
settingsSubmenu: document.getElementById('settings-submenu')
};
const toggleSidebar = () => {
elements.sidebar?.classList.toggle('-translate-x-full');
elements.overlay?.classList.toggle('hidden');
};
elements.toggleBtn?.addEventListener('click', toggleSidebar);
elements.overlay?.addEventListener('click', toggleSidebar);
// Settings Submenu
elements.settingsToggle?.addEventListener('click', (e) => {
e.preventDefault();
const isHidden = elements.settingsSubmenu?.classList.toggle('hidden');
localStorage.setItem('admin_settings_open', !isHidden);
});
// Flash Messages (Délégation pour performance)
document.querySelectorAll('.flash-message').forEach(flash => {
setTimeout(() => {
flash.classList.add('opacity-0', 'translate-x-10');
setTimeout(() => flash.remove(), 500);
}, 5000);
});
}
// --- INITIALISATION ---
document.addEventListener('turbo:load', () => {
registerCustomElements();
initDynamicSearch();
initImagePreview();
initUI();
initTomSelect();
});
// Confirmation de suppression Turbo
document.addEventListener("turbo:click", (event) => {
const attr = event.target.closest("[data-turbo-confirm]")?.getAttribute("data-turbo-confirm");
if (attr && !confirm(attr)) {
event.preventDefault();
}
});