222 lines
11 KiB
HTML
222 lines
11 KiB
HTML
<!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>
|