espace-paie-odentas/public/simulateur-embed-compact.html

222 lines
11 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Simulateur Paie Compact</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/css/bootstrap.min.css" rel="stylesheet" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css" />
<style>
:root { color-scheme: light; }
body { margin: 0; background: #f9fafb; font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif; }
.container-compact { padding: 8px; }
.card-compact { background: #fff; border: 1px solid #e5e7eb; border-radius: 12px; padding: 10px; }
.grid { display: grid; grid-template-columns: repeat(3, minmax(0,1fr)); gap: 6px; align-items: start; }
.grid .rowpair { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.grid .span2 { grid-column: span 2; }
.grid .span3 { grid-column: 1 / -1; }
.align-bottom { align-self: end; }
.results-grid { display: grid; grid-template-columns: repeat(3, minmax(0,1fr)); gap: 8px; }
.result-tile { background: #fff; border: 1px solid #e5e7eb; border-radius: 8px; padding: 8px; }
.result-tile .label { font-size: 11px; color: #64748b; margin-bottom: 2px; }
.result-tile .value { font-weight: 700; color: #0f172a; }
.grid select.form-select { min-width: 0; white-space: nowrap; text-overflow: ellipsis; overflow: hidden; }
label { font-size: 12px; font-weight: 600; margin: 0; }
input.form-control, select.form-select { font-size: 12px; min-height: 32px; }
.options { display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); gap: 8px; }
.options label { display: flex; align-items: center; gap: 8px; padding: 6px 10px; border: 1px solid #e2e8f0; border-radius: 8px; background: #fff; margin: 0; }
.options input[type="radio"] { accent-color: #6366f1; }
.options label.checked { background: #eef2ff; border-color: #6366f1; box-shadow: 0 0 0 2px rgba(99,102,241,0.08); }
#results { font-size: 12px; }
#calcBtn { font-size: 12px; padding: 6px 10px; }
/* Keep 3 columns for modal (~500px). Collapse to 1 only on very small widths. */
@media (max-width: 360px) { .grid { grid-template-columns: 1fr; } .options { grid-template-columns: 1fr !important; } }
</style>
</head>
<body>
<div class="container-compact">
<div class="card-compact">
<div class="grid">
<div class="rowpair">
<label for="conventionSelect">Convention Collective</label>
<select id="conventionSelect" class="form-select form-select-sm">
<option value="1285">1285 Entreprises Artistiques & Culturelles (CCNEAC)</option>
<option value="3090">3090 Spectacle Vivant Privé (CCNSVP)</option>
<option value="1518">1518 ÉCLAT (ex-Animation)</option>
<option value="1922">1922 Radiodiffusion</option>
<option value="2121">2121 Édition phonographique</option>
<option value="2412">2412 Production de films d'animation</option>
<option value="2642">2642 Production audiovisuelle</option>
<option value="3097">3097 Production cinématographique</option>
<option value="3241">3241 Télédiffusion</option>
<option value="3252">3252 Entreprises au service de la création et de l'événement</option>
</select>
</div>
<div class="rowpair">
<label for="categorieSelect">Catégorie</label>
<select id="categorieSelect" class="form-select form-select-sm">
<option value="artiste" selected>Artiste (Annexe 10)</option>
<option value="technicien">Technicien (Annexe 8)</option>
</select>
</div>
<div class="rowpair">
<label for="statutSelect">Statut</label>
<select id="statutSelect" class="form-select form-select-sm">
<option value="non-cadre" selected>Artiste non-cadre</option>
<option value="cadre">Artiste cadre</option>
</select>
</div>
</div>
</div>
<div class="card-compact" id="abattementCard" style="display:none; margin-top:8px;">
<div class="grid">
<div class="rowpair span3">
<label>Abattement pour frais professionnels</label>
<div class="d-flex gap-3">
<label class="d-inline-flex align-items-center gap-2"><input type="radio" name="abattement" value="oui"> Oui</label>
<label class="d-inline-flex align-items-center gap-2"><input type="radio" name="abattement" value="non" checked> Non</label>
</div>
</div>
<div class="rowpair span3" id="professionBlock" style="display:none;">
<label for="professionSelect">Profession du salarié</label>
<select id="professionSelect" class="form-select form-select-sm">
<option value="">-- Sélectionnez une profession --</option>
<option value="drama">Artiste dramatique / lyrique / cinématographique / chorégraphique / de cirque (21%)</option>
<option value="musique">Artiste musicien / choriste / chef d'orchestre (18%)</option>
</select>
</div>
</div>
</div>
<div class="card-compact" style="margin-top:8px;">
<div class="grid">
<div class="rowpair">
<label for="cachetsInput">Nombre de cachets</label>
<input id="cachetsInput" type="number" step="1" placeholder="Ex : 10" class="form-control form-control-sm" />
</div>
<div class="rowpair">
<label for="heuresInput">Nombre d'heures</label>
<input id="heuresInput" type="number" step="0.1" placeholder="Ex : 35" class="form-control form-control-sm" />
</div>
<div class="rowpair">
<label for="datesInput">Dates de travail</label>
<input id="datesInput" type="text" placeholder="Cliquez pour sélectionner des dates" class="form-control form-control-sm" readonly />
</div>
<div class="rowpair span2">
<label for="montantInput">Montant total (€)</label>
<input id="montantInput" type="number" step="0.01" placeholder="Ex: 2000" class="form-control form-control-sm" />
</div>
<div class="rowpair align-bottom">
<button id="openCalculatorBtn" type="button" class="btn btn-light btn-sm w-100">Calculatrice</button>
</div>
</div>
</div>
<div class="card-compact" style="margin-top:8px;">
<div class="grid">
<div class="rowpair span3">
<div class="options" style="display:grid; grid-template-columns: repeat(3, minmax(0,1fr)); gap: 8px;">
<label><input type="radio" name="type" value="brut" checked /> Brut</label>
<label><input type="radio" name="type" value="net" /> Net avt PAS</label>
<label><input type="radio" name="type" value="cost" /> Coût employeur</label>
</div>
</div>
<div class="rowpair span3">
<button id="calcBtn" class="btn btn-primary w-100">Calculer</button>
</div>
</div>
</div>
<div class="card-compact" style="margin-top:8px;">
<div id="results"></div>
</div>
</div>
<!-- Hidden full engine iframe -->
<iframe id="engine" src="/simulateur-embed.html" style="display:none; width:0; height:0; border:0;"></iframe>
<script src="https://cdn.jsdelivr.net/npm/flatpickr"></script>
<script>
// Wire compact form to hidden engine via postMessage API
const engine = document.getElementById('engine');
let fp;
function sendToEngine() {
const payload = {
type: 'simulateur_compact_submit',
data: {
ccn: document.getElementById('conventionSelect').value,
categorie: document.getElementById('categorieSelect').value,
statut: document.getElementById('statutSelect').value,
abattement: (document.querySelector('input[name="abattement"]:checked')||{}).value,
profession: document.getElementById('professionSelect')?.value || '',
cachets: document.getElementById('cachetsInput').value,
heures: document.getElementById('heuresInput').value,
dates: document.getElementById('datesInput').value,
montant: document.getElementById('montantInput').value,
type: (document.querySelector('input[name="type"]:checked')||{}).value || 'brut',
}
};
engine.contentWindow?.postMessage(payload, '*');
}
function renderResults(data){
const fmt = (n)=> Number(n||0).toLocaleString('fr-FR',{minimumFractionDigits:2, maximumFractionDigits:2});
const r = document.getElementById('results');
r.innerHTML = `
<div class="results-grid">
<div class="result-tile">
<div class="label">Brut</div>
<div class="value">€ ${fmt(data.resultat_brut)}</div>
</div>
<div class="result-tile">
<div class="label">Net</div>
<div class="value">€ ${fmt(data.resultat_net)}</div>
</div>
<div class="result-tile">
<div class="label">Coût employeur</div>
<div class="value">€ ${fmt(data.resultat_cost)}</div>
</div>
</div>`;
}
// Listen for calculation results proxied by engine
window.addEventListener('message', (ev) => {
if (ev.data?.type === 'simulateur_calculation') {
renderResults(ev.data.data || {});
}
});
// Compact form behavior
document.getElementById('categorieSelect').addEventListener('change', () => {
const isTech = document.getElementById('categorieSelect').value === 'technicien';
document.getElementById('abattementCard').style.display = isTech ? 'none' : '';
});
document.querySelectorAll('input[name="abattement"]').forEach(r => r.addEventListener('change', () => {
const val = (document.querySelector('input[name="abattement"]:checked')||{}).value;
document.getElementById('professionBlock').style.display = (val === 'oui') ? '' : 'none';
}));
// Flatpickr
fp = flatpickr('#datesInput', { mode: 'multiple', dateFormat: 'Y-m-d' });
// Calculate
document.getElementById('calcBtn').addEventListener('click', () => {
sendToEngine();
});
// Reflect checked styling on radios
document.querySelectorAll('.options input[type="radio"]').forEach(input => {
input.addEventListener('change', () => {
document.querySelectorAll('.options label').forEach(l => l.classList.remove('checked'));
input.closest('label')?.classList.add('checked');
});
});
// Open external calculator through parent
document.getElementById('openCalculatorBtn')?.addEventListener('click', () => {
window.parent?.postMessage({ type: 'openCalculator' }, '*');
});
</script>
</body>
</html>