402 lines
22 KiB
TypeScript
402 lines
22 KiB
TypeScript
"use client";
|
||
|
||
import React, { useEffect, useState } from 'react';
|
||
|
||
const euro = (n: number) => new Intl.NumberFormat('fr-FR', {
|
||
minimumFractionDigits: Number.isInteger(n) ? 0 : 2,
|
||
maximumFractionDigits: 2
|
||
}).format(n) + '€';
|
||
|
||
// Données Annexe 1
|
||
const theatreData = [
|
||
{ cap: "≤ 200 places", j24: 118, j25_48: 100, j48p: 86, mens: 2000 },
|
||
{ cap: "≤ 300 places", j24: 125, j25_48: 106, j48p: 94, mens: 2184 },
|
||
{ cap: "301–600 places", j24: 140, j25_48: 119, j48p: 105, mens: 2448 },
|
||
{ cap: "> 600 places", j24: 155, j25_48: 132, j48p: 116, mens: 2712 },
|
||
];
|
||
|
||
const musicalData = [
|
||
{ cat: "Comédien·ne 1er rôle / 1er·e chanteur·se soliste", r1_7: 177.89, r8_16: 164.34, cont: 129.59, mens24: 2956.98, mens151: 3110.13 },
|
||
{ cat: "Comédien·ne 2nd rôle", r1_7: 142.55, r8_16: 127.23, cont: 108.38, mens24: 2274.87, mens151: 2601.20 },
|
||
{ cat: "Comédien·ne", r1_7: 129.59, r8_16: 117.81, cont: 97.07, mens24: 2027.47, mens151: 2318.46 },
|
||
{ cat: "Artiste chorégraphique 1er rôle", r1_7: 177.89, r8_16: 160.22, cont: 129.59, mens24: 2886.29, mens151: 3110.13 },
|
||
{ cat: "Artiste chorégraphique 2nd rôle", r1_7: 166.11, r8_16: 146.08, cont: 108.38, mens24: 2575.28, mens151: 2601.20 },
|
||
{ cat: "Artiste chorégraphique d'ensemble", r1_7: 142.55, r8_16: 127.23, cont: 97.07, mens24: 2274.87, mens151: 2318.46 },
|
||
{ cat: "Artiste lyrique 1er emploi", r1_7: 177.89, r8_16: 164.34, cont: 129.59, mens24: 2886.29, mens151: 3110.13 },
|
||
{ cat: "Artiste lyrique 2nd emploi / Chanteur", r1_7: 142.55, r8_16: 127.23, cont: 108.38, mens24: 2274.87, mens151: 2601.20 },
|
||
{ cat: "Choristes de plateau", r1_7: 100.52, r8_16: 89.21, cont: 81.80, mens24: 1777.90, mens151: 1912.76 },
|
||
{ cat: "Doublure", r1_7: 100.52, r8_16: 89.21, cont: 79.70, mens24: 1732.24, mens151: 1912.76 },
|
||
{ cat: "Artiste de music-hall / numéro visuel", r1_7: 177.89, r8_16: 164.34, cont: 117.81, mens24: 2956.98, mens151: 2827.39 },
|
||
{ cat: "1er assistant·e des attractions", r1_7: 100.52, r8_16: 89.21, cont: 81.80, mens24: 1777.90, mens151: 1912.76 },
|
||
{ cat: "Autre assistant·e", r1_7: 87.78, r8_16: 81.44, cont: 79.60, mens24: 1777.90, mens151: 1861.37 },
|
||
];
|
||
|
||
const musoData = [
|
||
{ cat: "Chef d'orchestre", r1_7: 259.18, r8_16: 212.05, r16p: 182.60, mens30: 3652.04, mens151: 3769.85 },
|
||
{ cat: "Musicien·ne", r1_7: 174.36, r8_16: 153.25, r16p: 134.90, mens30: 2968.48, mens151: 3063.00 },
|
||
{ cat: "Musicien·ne d'orchestre < 10 musiciens & chœurs", r1_7: 174.36, r8_16: 153.25, r16p: 134.90, mens30: 2968.48, mens151: 3063.00 },
|
||
{ cat: "Musicien·ne d'orchestre > 10 musiciens & chœurs", r1_7: 129.88, r8_16: 129.88, r16p: 129.88, mens30: 2604.62, mens151: 2709.58 },
|
||
{ cat: "Chœurs d'orchestre", r1_7: 129.88, r8_16: 129.88, r16p: 129.88, mens30: 2604.62, mens151: 2709.58 },
|
||
];
|
||
|
||
const techData = [
|
||
{ cls: "Cadres", h200: 14.73, m200: 2234.10, h500: 18.78, m500: 2848.36, hp: 23.34, mp: 3539.98 },
|
||
{ cls: "Agents de maîtrise", h200: 14.24, m200: 2159.78, h500: 15.44, m500: 2341.78, hp: 18.78, mp: 2848.36 },
|
||
{ cls: "Employés qualifiés", h200: 12.95, m200: 1964.13, h500: 12.95, m500: 1964.13, hp: 14.96, mp: 2268.98 },
|
||
{ cls: "Employés", h200: 12.09, m200: 1833.69, h500: 12.09, m500: 1833.69, hp: 12.66, mp: 1920.14 },
|
||
];
|
||
|
||
const techJobs = [
|
||
// CADRES
|
||
{ cls: "Cadres", name: "Directeur·trice technique", keywords: ["directeur technique", "directrice technique", "direction technique"] },
|
||
{ cls: "Cadres", name: "Régisseur·euse général·e", keywords: ["régisseur général", "régisseuse générale"] },
|
||
{ cls: "Cadres", name: "Décorateur·trice", keywords: ["décorateur", "décoratrice"] },
|
||
{ cls: "Cadres", name: "Scénographe", keywords: ["scénographe"] },
|
||
{ cls: "Cadres", name: "Concepteur·trice du son", keywords: ["concepteur son", "conceptrice son", "sound designer"] },
|
||
{ cls: "Cadres", name: "Ingénieur·e du son", keywords: ["ingénieur du son", "ingénieure du son", "ingé son"] },
|
||
{ cls: "Cadres", name: "Concepteur·trice lumière/éclairagiste", keywords: ["concepteur lumière", "conceptrice lumière", "éclairagiste", "lighting designer"] },
|
||
{ cls: "Cadres", name: "Réalisateur·trice lumière", keywords: ["réalisateur lumière", "réalisatrice lumière"] },
|
||
{ cls: "Cadres", name: "Ingénieur·e du son-vidéo", keywords: ["ingénieur son vidéo", "ingénieure son vidéo", "ingénieur audiovisuel", "ingé av"] },
|
||
{ cls: "Cadres", name: "Chef opérateur·trice", keywords: ["chef opérateur", "cheffe opératrice", "directeur photo", "directrice photo"] },
|
||
{ cls: "Cadres", name: "Réalisateur·trice pour diffusion intégrée au spectacle", keywords: ["réalisateur pour diffusion intégrée au spectacle", "réalisatrice pour diffusion intégrée au spectacle"] },
|
||
|
||
// AGENTS DE MAÎTRISE
|
||
{ cls: "Agents de maîtrise", name: "Régisseur·euse", keywords: ["régisseur", "régisseuse"] },
|
||
{ cls: "Agents de maîtrise", name: "Régisseur·euse d'orchestre", keywords: ["régisseur d'orchestre", "régisseuse d'orchestre"] },
|
||
{ cls: "Agents de maîtrise", name: "Régisseur·euse de production", keywords: ["régisseur de production", "régisseuse de production"] },
|
||
{ cls: "Agents de maîtrise", name: "Conseiller·e technique effets spéciaux", keywords: ["conseiller technique fx", "conseillère technique fx", "effets spéciaux"] },
|
||
{ cls: "Agents de maîtrise", name: "Concepteur·trice artificier·ère", keywords: ["concepteur artificier", "conceptrice artificière", "artificier", "artificière"] },
|
||
{ cls: "Agents de maîtrise", name: "Régisseur·euse plateau", keywords: ["régisseur plateau", "régisseuse plateau"] },
|
||
{ cls: "Agents de maîtrise", name: "Régisseur·euse son", keywords: ["régisseur son", "régisseuse son"] },
|
||
{ cls: "Agents de maîtrise", name: "Régisseur·euse lumière", keywords: ["régisseur lumière", "régisseuse lumière"] },
|
||
{ cls: "Agents de maîtrise", name: "Régisseur·euse de scène", keywords: ["régisseur de scène", "régisseuse de scène"] },
|
||
{ cls: "Agents de maîtrise", name: "Régisseur·euse de chœur", keywords: ["régisseur de chœur", "régisseuse de chœur", "regisseur de choeur"] },
|
||
{ cls: "Agents de maîtrise", name: "Opérateur·trice son", keywords: ["opérateur son", "opératrice son", "operator son"] },
|
||
{ cls: "Agents de maîtrise", name: "Preneur·euse de son", keywords: ["preneur de son", "preneuse de son", "prise de son"] },
|
||
{ cls: "Agents de maîtrise", name: "Technicien·ne console", keywords: ["technicien console", "technicienne console"] },
|
||
{ cls: "Agents de maîtrise", name: "Sonorisateur·trice", keywords: ["sonorisateur", "sonorisatrice", "sono"] },
|
||
{ cls: "Agents de maîtrise", name: "Monteur·euse son", keywords: ["monteur son", "monteuse son", "editing son"] },
|
||
{ cls: "Agents de maîtrise", name: "Pupitreur·euse", keywords: ["pupitreur", "pupitreuse"] },
|
||
{ cls: "Agents de maîtrise", name: "Chef électricien·ne", keywords: ["chef électricien", "cheffe électricienne"] },
|
||
{ cls: "Agents de maîtrise", name: "Technicien·ne CAO-PAO", keywords: ["technicien cao", "technicienne cao", "technicien pao", "dao"] },
|
||
{ cls: "Agents de maîtrise", name: "Opérateur·trice lumière", keywords: ["opérateur lumière", "opératrice lumière"] },
|
||
{ cls: "Agents de maîtrise", name: "Chef machiniste", keywords: ["chef machiniste", "cheffe machiniste"] },
|
||
{ cls: "Agents de maîtrise", name: "Chef monteur·euse de structures", keywords: ["chef monteur structures", "cheffe monteuse structures"] },
|
||
{ cls: "Agents de maîtrise", name: "Ensemblier·ère de spectacle", keywords: ["ensemblier", "ensemblière"] },
|
||
{ cls: "Agents de maîtrise", name: "Cadreur·euse", keywords: ["cadreur", "cadreuse", "camera operator"] },
|
||
{ cls: "Agents de maîtrise", name: "Monteur·euse", keywords: ["monteur", "monteuse", "editor"] },
|
||
{ cls: "Agents de maîtrise", name: "Opérateur·trice image", keywords: ["opérateur image", "opératrice image"] },
|
||
{ cls: "Agents de maîtrise", name: "Opérateur·trice vidéo", keywords: ["opérateur vidéo", "opératrice vidéo"] },
|
||
{ cls: "Agents de maîtrise", name: "Régisseur·euse audiovisuel·le", keywords: ["régisseur audiovisuel", "régisseuse audiovisuelle"] },
|
||
{ cls: "Agents de maîtrise", name: "Chef de la sécurité", keywords: ["chef sécurité", "responsable sécurité"] },
|
||
{ cls: "Agents de maîtrise", name: "Réalisateur·trice son", keywords: ["réalisateur son", "réalisatrice son"] },
|
||
|
||
// EMPLOYÉS QUALIFIÉS
|
||
{ cls: "Employés qualifiés", name: "Régisseur·euse adjoint·e", keywords: ["régisseur adjoint", "régisseuse adjointe"] },
|
||
{ cls: "Employés qualifiés", name: "Technicien·ne pyrotechnie", keywords: ["technicien pyrotechnie", "technicienne pyrotechnie", "pyro"] },
|
||
{ cls: "Employés qualifiés", name: "Technicien·ne effets spéciaux", keywords: ["technicien fx", "technicienne fx", "effets spéciaux"] },
|
||
{ cls: "Employés qualifiés", name: "Artificier·ère", keywords: ["artificier", "artificière"] },
|
||
{ cls: "Employés qualifiés", name: "Technicien·ne son", keywords: ["technicien son", "technicienne son"] },
|
||
{ cls: "Employés qualifiés", name: "Technicien·ne instruments", keywords: ["technicien instruments", "technicienne instruments", "backliner"] },
|
||
{ cls: "Employés qualifiés", name: "Accordeur·euse", keywords: ["accordeur", "accordeuse"] },
|
||
{ cls: "Employés qualifiés", name: "Électricien·ne", keywords: ["électricien", "électricienne"] },
|
||
{ cls: "Employés qualifiés", name: "Technicien·ne lumière", keywords: ["technicien lumière", "technicienne lumière"] },
|
||
{ cls: "Employés qualifiés", name: "Accessoiriste", keywords: ["accessoiriste"] },
|
||
{ cls: "Employés qualifiés", name: "Accessoiriste-constructeur·trice", keywords: ["accessoiriste constructeur", "accessoiriste constructrice"] },
|
||
{ cls: "Employés qualifiés", name: "Accrocheur·euse-rigger", keywords: ["accrocheur", "accrocheuse", "rigger"] },
|
||
{ cls: "Employés qualifiés", name: "Assistant·e décorateur·trice", keywords: ["assistant décorateur", "assistante décoratrice"] },
|
||
{ cls: "Employés qualifiés", name: "Cintrier·ière", keywords: ["cintrier", "cintrière"] },
|
||
{ cls: "Employés qualifiés", name: "Constructeur·trice décors", keywords: ["constructeur décors", "constructrice décors"] },
|
||
{ cls: "Employés qualifiés", name: "Machiniste", keywords: ["machiniste"] },
|
||
{ cls: "Employés qualifiés", name: "Menuisier·ère", keywords: ["menuisier", "menuisière"] },
|
||
{ cls: "Employés qualifiés", name: "Peintre décorateur·trice", keywords: ["peintre décorateur", "peintre décoratrice"] },
|
||
{ cls: "Employés qualifiés", name: "Serrurier·ière", keywords: ["serrurier", "serrurière"] },
|
||
{ cls: "Employés qualifiés", name: "Staffeur·euse", keywords: ["staffeur", "staffeuse"] },
|
||
{ cls: "Employés qualifiés", name: "Tapissier·ière", keywords: ["tapissier", "tapissière"] },
|
||
{ cls: "Employés qualifiés", name: "Technicien·ne de plateau", keywords: ["technicien de plateau", "technicienne de plateau"] },
|
||
{ cls: "Employés qualifiés", name: "Technicien·ne structures", keywords: ["technicien structures", "technicienne structures"] },
|
||
{ cls: "Employés qualifiés", name: "Monteur·euse de spectacle", keywords: ["monteur de spectacle", "monteuse de spectacle"] },
|
||
{ cls: "Employés qualifiés", name: "Technicien·ne hydraulique", keywords: ["technicien hydraulique", "technicienne hydraulique"] },
|
||
{ cls: "Employés qualifiés", name: "Technicien·ne vidéo", keywords: ["technicien vidéo", "technicienne vidéo"] },
|
||
{ cls: "Employés qualifiés", name: "Projectionniste", keywords: ["projectionniste"] },
|
||
{ cls: "Employés qualifiés", name: "Technicien·ne prompteur·euse", keywords: ["technicien prompteur", "technicienne prompteuse", "prompteur", "prompteuse"] },
|
||
|
||
// EMPLOYÉS
|
||
{ cls: "Employés", name: "Technicien·ne groupe électrogène", keywords: ["technicien groupe électrogène", "technicienne groupe électrogène", "groupe électrogène"] },
|
||
{ cls: "Employés", name: "Prompteur·euse", keywords: ["prompteur", "prompteuse"] },
|
||
{ cls: "Employés", name: "Souffleur·euse", keywords: ["souffleur", "souffleuse"] },
|
||
{ cls: "Employés", name: "Poursuiteur·euse", keywords: ["poursuiteur", "poursuiteuse"] },
|
||
{ cls: "Employés", name: "Peintre", keywords: ["peintre"] },
|
||
{ cls: "Employés", name: "Cariste", keywords: ["cariste", "chariot élévateur"] },
|
||
{ cls: "Employés", name: "Agent·e de sécurité", keywords: ["agent de sécurité", "agente de sécurité", "sécurité"] },
|
||
];
|
||
|
||
export default function Annexe1Content() {
|
||
const [searchTerm, setSearchTerm] = useState('');
|
||
const [filteredJobs, setFilteredJobs] = useState<typeof techJobs>([]);
|
||
|
||
const normalize = (s: string) => {
|
||
return s.toLowerCase()
|
||
.normalize("NFD").replace(/[\u0300-\u036f]/g, "")
|
||
.replace(/œ/g, "oe")
|
||
.replace(/[·''`^~\-_/.,:;()]/g, " ")
|
||
.replace(/\s+/g, " ")
|
||
.trim();
|
||
};
|
||
|
||
const matchJob = (job: typeof techJobs[0], query: string) => {
|
||
if (!query) return true;
|
||
const nq = normalize(query);
|
||
if (normalize(job.name).includes(nq)) return true;
|
||
return job.keywords.some(kw => normalize(kw).includes(nq));
|
||
};
|
||
|
||
useEffect(() => {
|
||
setFilteredJobs(techJobs.filter(job => matchJob(job, searchTerm)));
|
||
}, [searchTerm]);
|
||
|
||
const groupedJobs = filteredJobs.reduce((acc, job) => {
|
||
if (!acc[job.cls]) acc[job.cls] = [];
|
||
acc[job.cls].push(job);
|
||
return acc;
|
||
}, {} as Record<string, typeof techJobs>);
|
||
|
||
const highlightRow = (cls: string) => {
|
||
const rows = document.querySelectorAll('#a1-tech-body tr');
|
||
rows.forEach((r: Element) => {
|
||
const td0 = (r as HTMLTableRowElement).cells[0];
|
||
if (td0 && td0.textContent?.trim().indexOf(cls) === 0) {
|
||
r.classList.add('hl');
|
||
r.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||
setTimeout(() => r.classList.remove('hl'), 2000);
|
||
}
|
||
});
|
||
};
|
||
|
||
return (
|
||
<div className="space-y-6">
|
||
<div className="rounded-xl border bg-gradient-to-br from-slate-50 to-slate-100 p-4">
|
||
<h2 className="text-lg font-semibold text-slate-900 mb-1">
|
||
Annexe 1 - Exploitants de lieux, producteurs ou diffuseurs de spectacles dramatiques, lyriques, chorégraphiques et de musique classique
|
||
</h2>
|
||
<p className="text-sm text-slate-600">
|
||
Minima pour les artistes dramatiques, lyriques, chorégraphiques, musiciens et techniciens des théâtres
|
||
</p>
|
||
</div>
|
||
|
||
<div className="ccnsvp-grid">
|
||
{/* ARTISTES THÉÂTRE */}
|
||
<div className="rounded-xl border bg-white p-5">
|
||
<h3 className="text-base font-bold text-slate-900 mb-3">Artistes dramatiques — Théâtre</h3>
|
||
|
||
<div className="ccnsvp-kpi">
|
||
<div className="lbl">Cachet de répétition</div>
|
||
<div className="num">83€ / jour</div>
|
||
<div className="muted">Soit 1 service unique de 4h, soit 2 services d'une durée cumulée de 6h</div>
|
||
</div>
|
||
|
||
<div className="font-semibold text-sm text-slate-700 mb-2">Cachet de représentation</div>
|
||
<p className="text-xs text-slate-500 mb-3">
|
||
Cachets selon capacité de salle et nombre de représentations sur une période de 3 mois ou 90j calendaires.
|
||
Colonne « Mensuel » = 24 rep./mois.
|
||
</p>
|
||
|
||
<table className="ccnsvp-table">
|
||
<thead>
|
||
<tr>
|
||
<th>Capacité de salle</th>
|
||
<th>Jusqu'à 24</th>
|
||
<th>25 à 48</th>
|
||
<th>Plus de 48</th>
|
||
<th>Mensuel</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{theatreData.map((row, i) => (
|
||
<tr key={i}>
|
||
<td dangerouslySetInnerHTML={{ __html: row.cap }}></td>
|
||
<td>{euro(row.j24)}</td>
|
||
<td>{euro(row.j25_48)}</td>
|
||
<td>{euro(row.j48p)}</td>
|
||
<td>{euro(row.mens)}</td>
|
||
</tr>
|
||
))}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
{/* THÉÂTRE MUSICAL */}
|
||
<div className="rounded-xl border bg-white p-5 md:row-span-2">
|
||
<h3 className="text-base font-bold text-slate-900 mb-3">
|
||
Théâtre musical • Comédie musicale • Opérette • Autres spectacles
|
||
</h3>
|
||
|
||
<div className="ccnsvp-kpi">
|
||
<div className="lbl">Service de répétition</div>
|
||
<div className="num">46,60€ / service</div>
|
||
<div className="muted">Pour tous les artistes hors musiciens.</div>
|
||
<div className="muted mb-2">
|
||
1 service = 4h pour les artistes dramatiques et lyriques ; 3h pour les artistes chorégraphiques
|
||
</div>
|
||
<div className="ccnsvp-alert">
|
||
<span className="icon">⚠️</span>
|
||
<span>
|
||
Un service de répétition payé <b>46,60€</b> pour <b>4h</b> est inférieur au
|
||
<b> SMIC</b> (11,65€ brut horaire au lieu de 11,88€). Dans ce cas, il convient d'appliquer au minimum le SMIC, soit 47,52€.
|
||
</span>
|
||
</div>
|
||
</div>
|
||
|
||
<p className="text-xs text-slate-500 mb-3">
|
||
Cachets par représentation et minima mensuels (24 rep. et 151h67).
|
||
</p>
|
||
|
||
<div className="overflow-x-auto">
|
||
<table className="ccnsvp-table text-xs">
|
||
<thead>
|
||
<tr>
|
||
<th>Profession</th>
|
||
<th>1 à 7</th>
|
||
<th>8 à 16</th>
|
||
<th>Exploitation continue</th>
|
||
<th>Mensuel (24 rep.)</th>
|
||
<th>Mensuel (151h67)</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{musicalData.map((row, i) => (
|
||
<tr key={i}>
|
||
<td className="font-medium">{row.cat}</td>
|
||
<td>{euro(row.r1_7)}</td>
|
||
<td>{euro(row.r8_16)}</td>
|
||
<td>{euro(row.cont)}</td>
|
||
<td>{euro(row.mens24)}</td>
|
||
<td>{euro(row.mens151)}</td>
|
||
</tr>
|
||
))}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
|
||
{/* MUSICIENS */}
|
||
<div className="rounded-xl border bg-white p-5">
|
||
<h3 className="text-base font-bold text-slate-900 mb-3">Artistes musiciens & orchestre</h3>
|
||
|
||
<div className="ccnsvp-kpi">
|
||
<div className="lbl">Cachet de répétition</div>
|
||
<div className="num">104,94€/cachet</div>
|
||
<div className="muted">Pour 2 services de 3h chacun sur la journée.</div>
|
||
<div className="num mt-2">72,95€/cachet</div>
|
||
<div className="muted">Pour 1 service isolé de 3h sur la journée.</div>
|
||
</div>
|
||
|
||
<div className="font-semibold text-sm text-slate-700 mb-2">Cachet de représentation</div>
|
||
<p className="text-xs text-slate-500 mb-3">
|
||
Cachets par représentation + minima mensuels (30 rep. et 151h67).
|
||
</p>
|
||
|
||
<table className="ccnsvp-table">
|
||
<thead>
|
||
<tr>
|
||
<th>Catégorie</th>
|
||
<th>1 à 7</th>
|
||
<th>8 à 16</th>
|
||
<th>Plus de 16</th>
|
||
<th>Mensuel (30 rep.)</th>
|
||
<th>Mensuel (151h67)</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{musoData.map((row, i) => (
|
||
<tr key={i}>
|
||
<td className="font-medium" dangerouslySetInnerHTML={{ __html: row.cat }}></td>
|
||
<td>{euro(row.r1_7)}</td>
|
||
<td>{euro(row.r8_16)}</td>
|
||
<td>{euro(row.r16p)}</td>
|
||
<td>{euro(row.mens30)}</td>
|
||
<td>{euro(row.mens151)}</td>
|
||
</tr>
|
||
))}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
|
||
{/* TECHNICIENS */}
|
||
<div className="rounded-xl border bg-white p-5">
|
||
<h3 className="text-base font-bold text-slate-900 mb-2">Techniciens — Théâtres</h3>
|
||
<p className="text-sm text-slate-600 mb-4">
|
||
Minima horaires et mensuels selon jauge. Vous pouvez <b>rechercher</b> une profession ci-dessous et trouver sa classification.
|
||
La liste des professions est exhaustive de ce qui est prévu par l'Annexe 1.
|
||
</p>
|
||
|
||
<div className="ccnsvp-search">
|
||
<input
|
||
type="search"
|
||
placeholder="Rechercher une profession (ex. régisseur plateau, chef machiniste, électricien…)"
|
||
value={searchTerm}
|
||
onChange={(e) => setSearchTerm(e.target.value)}
|
||
className="flex-1"
|
||
/>
|
||
<span className="ccnsvp-badge">
|
||
{filteredJobs.length} résultat{filteredJobs.length > 1 ? 's' : ''}
|
||
</span>
|
||
</div>
|
||
|
||
<div className="overflow-x-auto">
|
||
<table className="ccnsvp-table">
|
||
<thead>
|
||
<tr>
|
||
<th>Classification</th>
|
||
<th>Horaire ≤ 200 pl.</th>
|
||
<th>Mensuel ≤ 200 pl.</th>
|
||
<th>Horaire 201–500</th>
|
||
<th>Mensuel 201–500</th>
|
||
<th>Horaire > 500</th>
|
||
<th>Mensuel > 500</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="a1-tech-body">
|
||
{techData.map((row, i) => (
|
||
<tr key={i}>
|
||
<td><b>{row.cls}</b></td>
|
||
<td>{euro(row.h200)}/h</td>
|
||
<td>{euro(row.m200)}</td>
|
||
<td>{euro(row.h500)}/h</td>
|
||
<td>{euro(row.m500)}</td>
|
||
<td>{euro(row.hp)}/h</td>
|
||
<td>{euro(row.mp)}</td>
|
||
</tr>
|
||
))}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
{/* Accordéons */}
|
||
{Object.keys(groupedJobs).length > 0 && (
|
||
<div className="ccnsvp-acc mt-4">
|
||
{Object.entries(groupedJobs).map(([cls, jobs]) => (
|
||
<details key={cls}>
|
||
<summary>
|
||
{cls} <span className="ccnsvp-badge ml-2">({jobs.length})</span>
|
||
</summary>
|
||
<ul>
|
||
{jobs.sort((a, b) => a.name.localeCompare(b.name, 'fr')).map((job, i) => (
|
||
<li
|
||
key={i}
|
||
onClick={() => highlightRow(cls)}
|
||
title={job.keywords.join(', ')}
|
||
>
|
||
{job.name}
|
||
</li>
|
||
))}
|
||
</ul>
|
||
</details>
|
||
))}
|
||
</div>
|
||
)}
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|