Compare commits
No commits in common. "Lm" and "main" have entirely different histories.
|
|
@ -1,5 +0,0 @@
|
|||
DB_URL=http://127.0.0.1:8091/
|
||||
DB_ADMIN=admin@axa.fr
|
||||
DB_PASSWORD=DTadmin123TT
|
||||
NODE_ENV=developpement
|
||||
PORT=8082
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
# Dependencies
|
||||
node_modules/
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Classique
|
||||
package-lock.json
|
||||
|
||||
# Logs
|
||||
logs/
|
||||
*.log
|
||||
|
||||
# Environment variables
|
||||
.env
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
# OS files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# IDE
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
|
||||
# Build outputs
|
||||
dist/
|
||||
build/
|
||||
|
||||
|
|
@ -1,279 +0,0 @@
|
|||
// Module IIFE pour éviter la pollution de l'espace global
|
||||
(function () {
|
||||
// Variables globales du module
|
||||
let parcours, contrat, client, matricule;
|
||||
|
||||
// Initialisation du formulaire et des données
|
||||
function init() {
|
||||
const token = localStorage.getItem('jwtToken');
|
||||
|
||||
if (token) {
|
||||
const decoded = jwt_decode(token);
|
||||
matricule = decoded.userMatricule;
|
||||
}
|
||||
|
||||
// Accéder aux informations stockées du parcours
|
||||
parcours = JSON.parse(sessionStorage.getItem('parcours'));
|
||||
contrat = JSON.parse(sessionStorage.getItem('contrat'));
|
||||
client = contrat?.["@expand"]?.client || null;
|
||||
|
||||
console.log("Matricule user actuel:", matricule);
|
||||
console.log("Initialisation pour formulaire client :", contrat);
|
||||
|
||||
// Materialize init Modal
|
||||
var modals = document.querySelectorAll('.modal');
|
||||
M.Modal.init(modals);
|
||||
|
||||
// Appel des différentes fonctions d'initialisation
|
||||
setupEventListeners();
|
||||
populateFormData();
|
||||
updateSubmitButtonState('clientForm');
|
||||
}
|
||||
|
||||
// Configuration des écouteurs d'événements
|
||||
function setupEventListeners() {
|
||||
document.getElementById('clientFormBtn').addEventListener('click', handleSubmitForm);
|
||||
document.getElementById('creditsafe').addEventListener('click', (event) => handleOpenLink(event, 'creditsafeURL'));
|
||||
document.getElementById('easyQP').addEventListener('click', (event) => handleOpenLink(event, 'easyQPURL'));
|
||||
document.getElementById('refNoteFi').addEventListener('click', (event) => handleOpenLink(event, 'refNoteFiURL'));
|
||||
document.getElementById('cl063-client').addEventListener('click', (event) => handleExtractClient(event));
|
||||
document.getElementById('modalExtraireClient').addEventListener('click', (event) => handleModalExtract(event));
|
||||
|
||||
// Controle de saisie et format sur les champs du formulaire
|
||||
document.getElementById('noteFinanciereClient').addEventListener('input', function () {
|
||||
validateField('noteFinanciereClient', true);
|
||||
updateSubmitButtonState('clientForm');
|
||||
});
|
||||
|
||||
document.getElementById('numClient').addEventListener('input', function () {
|
||||
validateField('numClient', true);
|
||||
updateSubmitButtonState('clientForm');
|
||||
});
|
||||
|
||||
document.getElementById('nomClient').addEventListener('input', function () {
|
||||
validateField('nomClient', true);
|
||||
updateSubmitButtonState('clientForm');
|
||||
});
|
||||
|
||||
document.getElementById('emailClient').addEventListener('input', function () {
|
||||
validateField('emailClient', true);
|
||||
updateSubmitButtonState('clientForm');
|
||||
});
|
||||
|
||||
document.getElementById('adresseClient').addEventListener('input', function () {
|
||||
validateField('adresseClient', true);
|
||||
updateSubmitButtonState('clientForm');
|
||||
});
|
||||
|
||||
document.getElementById('codePostalClient').addEventListener('input', function () {
|
||||
validateField('codePostalClient', true);
|
||||
updateSubmitButtonState('clientForm');
|
||||
});
|
||||
|
||||
document.getElementById('villeClient').addEventListener('input', function () {
|
||||
validateField('villeClient', true);
|
||||
updateSubmitButtonState('clientForm');
|
||||
});
|
||||
|
||||
document.getElementById('modalNumClient').addEventListener('input', function () {
|
||||
validateField('modalNumClient', true);
|
||||
updateSubmitButtonState('modalExtraireClient');
|
||||
});
|
||||
}
|
||||
|
||||
// Peupler le formulaire avec les données
|
||||
function populateFormData() {
|
||||
const clientStorage = JSON.parse(sessionStorage.getItem('tmp'));
|
||||
|
||||
if (client) {
|
||||
document.getElementById('nomClient').value = client.nom || '';
|
||||
document.getElementById('numClient').value = client.numClient || '';
|
||||
document.getElementById('adresseClient').value = client.adresse || '';
|
||||
document.getElementById('emailClient').value = client.mail || '';
|
||||
document.getElementById('codePostalClient').value = client.codePostal || '';
|
||||
document.getElementById('villeClient').value = client.ville || '';
|
||||
document.getElementById('noteFinanciereClient').value = client.noteFinanciere || '';
|
||||
}
|
||||
|
||||
if (clientStorage) {
|
||||
document.getElementById('nomClient').value = clientStorage.nomClient || '';
|
||||
document.getElementById('numClient').value = clientStorage.numClient || '';
|
||||
document.getElementById('adresseClient').value = clientStorage.adresseClient || '';
|
||||
document.getElementById('codePostalClient').value = clientStorage.postalClient || '';
|
||||
document.getElementById('villeClient').value = clientStorage.villeClient || '';
|
||||
}
|
||||
}
|
||||
|
||||
// Gérer l'ouverture de liens externes
|
||||
function handleOpenLink(event, urlType) {
|
||||
event.preventDefault();
|
||||
let url = '';
|
||||
|
||||
switch (urlType) {
|
||||
case 'creditsafeURL':
|
||||
url = 'https://www.creditsafe.fr/csfr?UserName=735265dorothee&Password=UH04EuLocXZMxIRqY19w6A%3d%3d&BackOfficeCountry=FR&origincountry=FR&linkages=Y';
|
||||
break;
|
||||
case 'easyQPURL':
|
||||
if (document.getElementById('numClient').value != "") {
|
||||
url = `https://qualite-portefeuille-iard-ent.axa-fr.intraxa/client/${document.getElementById('numClient').value}`;
|
||||
} else {
|
||||
url = `https://qualite-portefeuille-iard-ent.axa-fr.intraxa/`;
|
||||
}
|
||||
break;
|
||||
case 'refNoteFiURL':
|
||||
url = 'https://app.powerbi.com/groups/me/apps/7b48f9a2-bd97-4178-bc1a-a5f7ef6e985f/reports/d29a9f83-cafe-4a0f-bc38-0929921e8cd3/ReportSection?ctid=396b38cc-aa65-492b-bb0e-3d94ed25a97b';
|
||||
break;
|
||||
}
|
||||
|
||||
window.open(url, '_blank');
|
||||
}
|
||||
|
||||
// Gérer l'extraction axaPAC
|
||||
async function handleExtractClient(event) {
|
||||
event.preventDefault();
|
||||
|
||||
// Affiche le modal
|
||||
const elem = document.getElementById('modalExtractAxAPAC');
|
||||
const instance = M.Modal.getInstance(elem);
|
||||
instance.open();
|
||||
}
|
||||
|
||||
async function handleModalExtract() {
|
||||
document.getElementById('modalExtraireClient').disabled = true;
|
||||
|
||||
const response = await fetch(`/client/extract`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
"matricule": matricule,
|
||||
"numClient": document.getElementById("modalNumClient").value
|
||||
}),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
const res = await response.json();
|
||||
|
||||
if (res.valid) {
|
||||
document.getElementById("error-extract").style.display = "none";
|
||||
document.getElementById('modalExtraireClient').disabled = false;
|
||||
console.log(res);
|
||||
|
||||
// Save sessionStorage for Intermediaire
|
||||
sessionStorage.setItem('tmp', JSON.stringify(res.data));
|
||||
|
||||
// Populate data
|
||||
document.getElementById("numClient").value = (res.data.numClient) ? res.data.numClient : null;
|
||||
document.getElementById("nomClient").value = (res.data.nomClient) ? res.data.nomClient : null;
|
||||
document.getElementById("adresseClient").value = (res.data.adresseClient) ? res.data.adresseClient : null;
|
||||
document.getElementById("codePostalClient").value = (res.data.postalClient) ? res.data.postalClient : null;
|
||||
document.getElementById("villeClient").value = (res.data.villeClient) ? res.data.villeClient : null;
|
||||
|
||||
validateField('numClient', true);
|
||||
validateField('nomClient', true);
|
||||
validateField('adresseClient', true);
|
||||
validateField('codePostalClient', true);
|
||||
validateField('villeClient', true);
|
||||
updateSubmitButtonState('clientForm');
|
||||
|
||||
// close le modal
|
||||
const elem = document.getElementById('modalExtractAxAPAC');
|
||||
const instance = M.Modal.getInstance(elem);
|
||||
instance.close();
|
||||
} else {
|
||||
document.getElementById("error-extract").style.display = "block";
|
||||
document.getElementById('modalExtraireClient').disabled = false;
|
||||
console.log("Problème rencontré lors de l'extraction cl063 AxA PAC :", res.error);
|
||||
}
|
||||
}
|
||||
|
||||
// Gérer la soumission du formulaire
|
||||
async function handleSubmitForm(event) {
|
||||
event.preventDefault();
|
||||
|
||||
let idClient = client?.id;
|
||||
const numClient = document.getElementById('numClient').value;
|
||||
|
||||
let responseClient;
|
||||
|
||||
if (numClient) {
|
||||
responseClient = await fetch(`/client/read/${numClient}`, {
|
||||
method: 'GET',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
});
|
||||
}
|
||||
const dataClient = await responseClient.json();
|
||||
|
||||
if (dataClient.valid) {
|
||||
idClient = dataClient.idClient;
|
||||
} else {
|
||||
// Créez le client ici si non trouvé
|
||||
const responseCreateClient = await fetch(`/client/create`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
});
|
||||
const dataCreateClient = await responseCreateClient.json();
|
||||
|
||||
if (dataCreateClient.valid) {
|
||||
idClient = dataCreateClient.client.id;
|
||||
}
|
||||
}
|
||||
|
||||
// Mettre à jour le contrat avec l'ID du client
|
||||
if (idClient) {
|
||||
const response = await fetch(`/client/update/${idClient}`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
"nom": document.getElementById('nomClient').value.toUpperCase(),
|
||||
"numClient": document.getElementById('numClient').value,
|
||||
"adresse": document.getElementById('adresseClient').value.toUpperCase(),
|
||||
"mail": document.getElementById('emailClient').value,
|
||||
"codePostal": document.getElementById('codePostalClient').value,
|
||||
"ville": document.getElementById('villeClient').value.toUpperCase(),
|
||||
"noteFinanciere": document.getElementById('noteFinanciereClient').value
|
||||
}),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
const data = await response.json();
|
||||
|
||||
if (data.valid) {
|
||||
const idContrat = contrat?.id;
|
||||
|
||||
fetch(`/contrat/update/client/${idContrat}/${idClient}`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.valid) {
|
||||
// Update Session storage
|
||||
const clientStorage = JSON.parse(sessionStorage.getItem('tmp'));
|
||||
|
||||
if (clientStorage) {
|
||||
clientStorage.nomClient = document.getElementById('nomClient').value.toUpperCase();
|
||||
clientStorage.numClient = document.getElementById('numClient').value;
|
||||
clientStorage.adresseClient = document.getElementById('adresseClient').value.toUpperCase();
|
||||
clientStorage.postalClient = document.getElementById('codePostalClient').value;
|
||||
clientStorage.villeClient = document.getElementById('villeClient').value.toUpperCase();
|
||||
|
||||
sessionStorage.setItem('tmp', JSON.stringify(clientStorage))
|
||||
}
|
||||
|
||||
// Redirect vers intermédiaire
|
||||
window.location.href = `/navParcours?numParcours=${getNumParcoursFromURL()}&submenu=intermediaire`;
|
||||
} else {
|
||||
console.log('Echec lors de la mise à jour de la relation id contrat - id client :', data);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Exposer init globalement pour y accéder depuis l'extérieur
|
||||
window.initSubmenuForm = init;
|
||||
})();
|
||||
|
|
@ -1,129 +0,0 @@
|
|||
document.addEventListener("DOMContentLoaded", () => {
|
||||
let activateTimeout = null;
|
||||
let timeoutWarning = null;
|
||||
let currentPageLoad = null;
|
||||
let safetyTimeout = null; // Timeout de sécurité pour éviter que le loader reste bloqué
|
||||
|
||||
/**
|
||||
* Active le loader et le rend visible
|
||||
* Affiche un message d'annulation après 8 secondes
|
||||
*/
|
||||
window.showLoader = function() {
|
||||
const loader = document.getElementById("loader-overlay");
|
||||
if (!loader) return; // Protection : si l'élément n'existe pas, on ne fait rien
|
||||
|
||||
const timeoutMessage = document.getElementById("timeout-message");
|
||||
const errorMessage = document.getElementById("error-message");
|
||||
|
||||
// Nettoyer les timeouts précédents
|
||||
clearTimeout(activateTimeout);
|
||||
clearTimeout(timeoutWarning);
|
||||
|
||||
// Réinitialiser l'affichage
|
||||
if (errorMessage) errorMessage.style.display = "none";
|
||||
if (timeoutMessage) timeoutMessage.style.display = "none";
|
||||
loader.classList.remove("hidden");
|
||||
|
||||
// Afficher le loader après 500ms (évite le flash sur les chargements rapides)
|
||||
activateTimeout = setTimeout(() => {
|
||||
if (loader && !loader.classList.contains("hidden")) {
|
||||
loader.classList.add("active");
|
||||
}
|
||||
}, 500);
|
||||
|
||||
// Afficher le message de timeout après 8 secondes
|
||||
timeoutWarning = setTimeout(() => {
|
||||
if (loader && loader.classList.contains("active") && !loader.classList.contains("hidden")) {
|
||||
if (timeoutMessage) {
|
||||
timeoutMessage.style.display = "block";
|
||||
}
|
||||
}
|
||||
}, 8000);
|
||||
|
||||
// Protection : cacher automatiquement le loader après 30 secondes maximum
|
||||
// Au cas où hideLoader ne serait jamais appelé (page qui ne charge pas, erreur, etc.)
|
||||
if (safetyTimeout) clearTimeout(safetyTimeout);
|
||||
safetyTimeout = setTimeout(() => {
|
||||
if (loader && !loader.classList.contains("hidden")) {
|
||||
hideLoader();
|
||||
}
|
||||
}, 30000); // 30 secondes max
|
||||
};
|
||||
|
||||
/**
|
||||
* Désactive et cache le loader
|
||||
*/
|
||||
window.hideLoader = function() {
|
||||
const loader = document.getElementById("loader-overlay");
|
||||
if (!loader) return; // Protection : si l'élément n'existe pas, on ne fait rien
|
||||
|
||||
const timeoutMessage = document.getElementById("timeout-message");
|
||||
|
||||
clearTimeout(activateTimeout);
|
||||
clearTimeout(timeoutWarning);
|
||||
if (safetyTimeout) {
|
||||
clearTimeout(safetyTimeout);
|
||||
safetyTimeout = null;
|
||||
}
|
||||
|
||||
loader.classList.remove("active");
|
||||
if (timeoutMessage) timeoutMessage.style.display = "none";
|
||||
|
||||
setTimeout(() => {
|
||||
if (loader) {
|
||||
loader.classList.add("hidden");
|
||||
}
|
||||
}, 500);
|
||||
};
|
||||
|
||||
/**
|
||||
* Affiche un message d'erreur dans le loader
|
||||
* @param {string} msg - Message d'erreur à afficher
|
||||
*/
|
||||
window.showError = function(msg) {
|
||||
const errorMessage = document.getElementById("error-message");
|
||||
const timeoutMessage = document.getElementById("timeout-message");
|
||||
|
||||
if (!errorMessage) return; // Protection : si l'élément n'existe pas, on ne fait rien
|
||||
|
||||
clearTimeout(activateTimeout);
|
||||
clearTimeout(timeoutWarning);
|
||||
|
||||
if (timeoutMessage) timeoutMessage.style.display = "none";
|
||||
|
||||
errorMessage.textContent = msg;
|
||||
errorMessage.style.display = "block";
|
||||
};
|
||||
|
||||
/**
|
||||
* Annule le chargement en cours et cache le loader
|
||||
*/
|
||||
const cancelLoadingLink = document.getElementById("cancel-loading-link");
|
||||
if (cancelLoadingLink) {
|
||||
cancelLoadingLink.addEventListener("click", () => {
|
||||
// Annuler le chargement de la page en cours si possible
|
||||
if (currentPageLoad && currentPageLoad.abort) {
|
||||
currentPageLoad.abort();
|
||||
}
|
||||
|
||||
hideLoader();
|
||||
|
||||
// Afficher une notification discrète
|
||||
if (typeof M !== 'undefined' && M.toast) {
|
||||
M.toast({
|
||||
html: 'Chargement annulé',
|
||||
classes: 'rounded grey darken-3',
|
||||
displayLength: 2500
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Permet de stocker l'abort controller du chargement en cours
|
||||
* @param {AbortController} controller - Controller de la requête fetch
|
||||
*/
|
||||
window.setCurrentPageLoad = function(controller) {
|
||||
currentPageLoad = controller;
|
||||
};
|
||||
});
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
/**
|
||||
* Affiche le loader lors des navigations entre pages (localhost)
|
||||
* Comme on est en localhost, on peut se permettre d'afficher le loader
|
||||
* au clic sur un lien, il disparaîtra automatiquement au chargement de la nouvelle page
|
||||
*/
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
|
||||
// Intercepter les clics sur les liens internes pour afficher le loader
|
||||
document.body.addEventListener("click", (e) => {
|
||||
const link = e.target.closest("a");
|
||||
|
||||
// Si c'est un lien interne (commence par /) et pas un lien spécial
|
||||
if (link &&
|
||||
link.getAttribute("href") &&
|
||||
link.getAttribute("href").startsWith("/") &&
|
||||
!link.classList.contains("modal-close") &&
|
||||
!link.getAttribute("href").startsWith("/#")) {
|
||||
|
||||
// Afficher le loader avant la navigation
|
||||
if (typeof showLoader === 'function') {
|
||||
showLoader();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Afficher le loader lors du rechargement (F5, Cmd+R)
|
||||
window.addEventListener("beforeunload", () => {
|
||||
if (typeof showLoader === 'function') {
|
||||
showLoader();
|
||||
}
|
||||
});
|
||||
|
||||
// Cacher le loader quand la page est complètement chargée
|
||||
window.addEventListener("load", () => {
|
||||
if (typeof hideLoader === 'function') {
|
||||
// Petit délai pour éviter le flash
|
||||
setTimeout(hideLoader, 100);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
Pocketbase_0.7.5.exe serve --http="127.0.0.1:8091"
|
||||
pause
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,13 @@
|
|||
# Ignore files type
|
||||
*.log
|
||||
*.env
|
||||
*.exe
|
||||
*.wbk
|
||||
*.cmd
|
||||
*~*
|
||||
|
||||
# Ignore directory
|
||||
**/vbs/
|
||||
**/node_modules/
|
||||
**/logs/
|
||||
**/.vscode/
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
Description
|
||||
EasyTransport est une application en cours de transition technologique, destinée à la plateforme AxA IARD Transport. Le backend est écrit en Node.js avec une base de données embarquée PocketBase, et le frontend utilise EJS et Materialize CSS. L'application propose divers modules tels que la tarification, la génération de contrats à partir de formulaires, l'authentification via JWT, et la génération d'attestations.
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -9,7 +9,9 @@
|
|||
"test": "jest"
|
||||
},
|
||||
"pkg": {
|
||||
"assets": ["public/**"]
|
||||
"assets": [
|
||||
"public/**"
|
||||
]
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "cyril.ducaffy@axa.fr",
|
||||
|
|
@ -512,49 +512,3 @@ a.grille-garanties:hover{
|
|||
@keyframes l13 {
|
||||
100% { transform: rotate(1turn); }
|
||||
}
|
||||
|
||||
/* Message d'erreur du loader */
|
||||
#error-message {
|
||||
display: none;
|
||||
color: #ff4444;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
margin-top: 20px;
|
||||
white-space: pre-line;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
/* Message de timeout du loader */
|
||||
#timeout-message {
|
||||
display: none;
|
||||
margin-top: 30px;
|
||||
text-align: center;
|
||||
color: #d0d0d0;
|
||||
font-size: 14px;
|
||||
max-width: 420px;
|
||||
line-height: 1.6;
|
||||
padding: 0 20px;
|
||||
animation: fadeIn 0.5s ease;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from { opacity: 0; transform: translateY(10px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
|
||||
/* Lien cliquable pour annuler le chargement */
|
||||
#cancel-loading-link {
|
||||
color: #66B2FF;
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 3px;
|
||||
text-decoration-thickness: 1px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
#cancel-loading-link:hover {
|
||||
color: #90CAF9;
|
||||
text-decoration-thickness: 2px;
|
||||
text-shadow: 0 0 10px rgba(102, 178, 255, 0.6);
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
/* Overlay loader (css pris du site https://css-loaders.com/)*/
|
||||
#loader-overlay {
|
||||
position: fixed;
|
||||
top: 0; left: 0;
|
||||
width: 100%; height: 100%;
|
||||
background: linear-gradient(
|
||||
rgba(10, 20, 60, 0.2),
|
||||
rgba(0, 0, 0, 0.4)
|
||||
);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 9999;
|
||||
font-family: 'Roboto', sans-serif;
|
||||
opacity: 0;
|
||||
backdrop-filter: blur(0px);
|
||||
pointer-events: none;
|
||||
transition: opacity 0.5s ease, backdrop-filter 0.5s ease;
|
||||
}
|
||||
#loader-overlay.active {
|
||||
opacity: 1;
|
||||
backdrop-filter: blur(3px);
|
||||
pointer-events: all;
|
||||
}
|
||||
#loader-overlay.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Spinner wrapper (fade/slide) */
|
||||
.loader-spin-wrap {
|
||||
opacity: 0;
|
||||
transform: translateY(10px);
|
||||
transition: opacity 0.5s ease, transform 0.5s ease;
|
||||
transition-delay: 0.5s; /* apparaît après 0.5s */
|
||||
}
|
||||
#loader-overlay.active .loader-spin-wrap {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
/* Spinner circulaire */
|
||||
.loader-spin {
|
||||
width: 50px;
|
||||
aspect-ratio: 1;
|
||||
border-radius: 50%;
|
||||
mask:1;
|
||||
background:
|
||||
radial-gradient(farthest-side,darkblue 94%,transparent) top/8px 8px no-repeat,
|
||||
conic-gradient(transparent 30%,darkblue);
|
||||
-webkit-mask: radial-gradient(farthest-side,transparent calc(100% - 8px),#000 0);
|
||||
animation: l13 1s infinite linear;
|
||||
}
|
||||
@keyframes l13 {
|
||||
100% { transform: rotate(1turn); }
|
||||
}
|
||||
|
||||
/* Erreur */
|
||||
#error-message {
|
||||
display: none;
|
||||
color: red;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
margin-top: 20px;
|
||||
white-space: pre-line;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue