feat: Ajout saisie heures répétitions et correction PDF avenants
- Ajout champs heures totales et minutes pour répétitions dans AmendmentDureeForm - Intégration DatesQuantityModal pour saisie heures par jour de répétition - Ajout type 'heures_repetitions' dans dateFormatter et DatesQuantityModal - Correction envoi precisions_salaire à PDFMonkey pour les avenants - Ajout champs séparés dates_representations_detail et dates_repetitions_detail - Correction logique dates_repetitions_heures pour éviter doublons dans PDF
This commit is contained in:
parent
3653dd6e77
commit
44fc21c817
5 changed files with 102 additions and 6 deletions
|
|
@ -215,7 +215,11 @@ export async function POST(request: NextRequest) {
|
|||
if (dureeData.dates_representations) {
|
||||
datesTravaillees += dureeData.dates_representations;
|
||||
}
|
||||
if (dureeData.dates_repetitions) {
|
||||
// Pour les répétitions, utiliser dates_repetitions_heures si disponible, sinon dates_repetitions
|
||||
if (dureeData.dates_repetitions_heures) {
|
||||
if (datesTravaillees) datesTravaillees += " ; ";
|
||||
datesTravaillees += dureeData.dates_repetitions_heures;
|
||||
} else if (dureeData.dates_repetitions) {
|
||||
if (datesTravaillees) datesTravaillees += " ; ";
|
||||
datesTravaillees += dureeData.dates_repetitions;
|
||||
}
|
||||
|
|
@ -284,6 +288,7 @@ export async function POST(request: NextRequest) {
|
|||
maximumFractionDigits: 2
|
||||
})
|
||||
: "",
|
||||
precisions_salaire: remunerationData.precisions_salaire || contract.precisions_salaire || "",
|
||||
signature_contrat: formatDate(contract.date_signature),
|
||||
CCN: ccn,
|
||||
effet_avenant: formatDate(amendmentData.date_effet),
|
||||
|
|
@ -297,6 +302,8 @@ export async function POST(request: NextRequest) {
|
|||
heures: heures,
|
||||
heuresparjour: heuresParJour
|
||||
},
|
||||
dates_representations_detail: dureeData.dates_representations || contract.jours_representations || "",
|
||||
dates_repetitions_detail: dureeData.dates_repetitions_heures || dureeData.dates_repetitions || contract.jours_repetitions || "",
|
||||
imageUrl: orgDetails.logo || ""
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ interface DatesQuantityModalProps {
|
|||
pdfFormatted: string;
|
||||
}) => void;
|
||||
selectedDates: string[]; // format input "12/10, 13/10, ..."
|
||||
dateType: "representations" | "repetitions" | "jours_travail"; // Type de dates pour déterminer le libellé
|
||||
dateType: "representations" | "repetitions" | "jours_travail" | "heures_repetitions"; // Type de dates pour déterminer le libellé
|
||||
minDate?: string;
|
||||
maxDate?: string;
|
||||
}
|
||||
|
|
@ -78,6 +78,8 @@ export default function DatesQuantityModal({
|
|||
return "service(s) de répétition";
|
||||
case "jours_travail":
|
||||
return isRange ? "heure(s) par jour" : "heure(s)";
|
||||
case "heures_repetitions":
|
||||
return isRange ? "heure(s) par jour" : "heure(s)";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
|
|
@ -91,6 +93,8 @@ export default function DatesQuantityModal({
|
|||
return "service(s) de répétition";
|
||||
case "jours_travail":
|
||||
return isRange ? "heure(s) par jour" : "heure(s)";
|
||||
case "heures_repetitions":
|
||||
return isRange ? "heure(s) par jour" : "heure(s)";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,12 +24,13 @@ export default function AmendmentDureeForm({
|
|||
// États pour les calendriers (dates de représentations/répétitions/jours de travail uniquement)
|
||||
const [showDatesRep, setShowDatesRep] = useState(false);
|
||||
const [showDatesServ, setShowDatesServ] = useState(false);
|
||||
const [showHeuresRepetitions, setShowHeuresRepetitions] = useState(false);
|
||||
const [showJoursTravail, setShowJoursTravail] = useState(false);
|
||||
|
||||
// Modal de quantités
|
||||
const [quantityModalOpen, setQuantityModalOpen] = useState(false);
|
||||
const [quantityModalType, setQuantityModalType] = useState<
|
||||
"representations" | "repetitions" | "jours_travail"
|
||||
"representations" | "repetitions" | "jours_travail" | "heures_repetitions"
|
||||
>("representations");
|
||||
const [pendingDates, setPendingDates] = useState<string[]>([]);
|
||||
|
||||
|
|
@ -68,6 +69,17 @@ export default function AmendmentDureeForm({
|
|||
setQuantityModalOpen(true);
|
||||
};
|
||||
|
||||
const handleHeuresRepetitionsApply = (result: {
|
||||
selectedDates: string[];
|
||||
hasMultiMonth: boolean;
|
||||
pdfFormatted: string;
|
||||
}) => {
|
||||
// Pour les heures de répétitions, on passe directement à la modale de quantités
|
||||
setPendingDates(result.selectedDates);
|
||||
setQuantityModalType("heures_repetitions");
|
||||
setQuantityModalOpen(true);
|
||||
};
|
||||
|
||||
const handleJoursTravailApply = (result: {
|
||||
selectedDates: string[];
|
||||
hasMultiMonth: boolean;
|
||||
|
|
@ -105,6 +117,12 @@ export default function AmendmentDureeForm({
|
|||
nb_repetitions: nbDates,
|
||||
});
|
||||
break;
|
||||
case "heures_repetitions":
|
||||
onChange({
|
||||
...data,
|
||||
dates_repetitions_heures: result.pdfFormatted,
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
setQuantityModalOpen(false);
|
||||
|
|
@ -237,6 +255,68 @@ export default function AmendmentDureeForm({
|
|||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-xs font-medium text-slate-700 mb-2">
|
||||
Nombre d'heures de répétition (total)
|
||||
</label>
|
||||
<div className="text-xs text-slate-500 mb-2">
|
||||
Actuellement : {originalData.nb_heures || "-"}
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<input
|
||||
type="number"
|
||||
min="0"
|
||||
value={data.heures_repetitions || ""}
|
||||
onChange={(e) =>
|
||||
onChange({
|
||||
...data,
|
||||
heures_repetitions: e.target.value ? Number(e.target.value) : "",
|
||||
})
|
||||
}
|
||||
placeholder="ex: 3"
|
||||
className="flex-1 px-3 py-2 border rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-indigo-500"
|
||||
/>
|
||||
<select
|
||||
value={data.minutes_repetitions || "0"}
|
||||
onChange={(e) =>
|
||||
onChange({
|
||||
...data,
|
||||
minutes_repetitions: e.target.value,
|
||||
})
|
||||
}
|
||||
className="px-3 py-2 border rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-indigo-500"
|
||||
aria-label="Minutes"
|
||||
>
|
||||
<option value="0">+ 00 min</option>
|
||||
<option value="30">+ 30 min</option>
|
||||
</select>
|
||||
<button
|
||||
onClick={() => setShowHeuresRepetitions(!showHeuresRepetitions)}
|
||||
className="px-3 py-2 border rounded-lg text-sm hover:bg-slate-50 flex items-center gap-2 whitespace-nowrap"
|
||||
>
|
||||
<Calendar className="h-4 w-4" />
|
||||
Heures/jour
|
||||
</button>
|
||||
</div>
|
||||
<p className="text-xs text-slate-500 mt-1">
|
||||
Nombre d'heures total sur toutes les répétitions
|
||||
</p>
|
||||
{showHeuresRepetitions && (
|
||||
<DatePickerCalendar
|
||||
isOpen={showHeuresRepetitions}
|
||||
onClose={() => setShowHeuresRepetitions(false)}
|
||||
onApply={handleHeuresRepetitionsApply}
|
||||
initialDates={[]}
|
||||
title="Sélectionner les dates de répétition avec heures"
|
||||
/>
|
||||
)}
|
||||
{data.dates_repetitions_heures && (
|
||||
<div className="mt-2 p-2 bg-white rounded text-xs text-slate-600 border">
|
||||
{data.dates_repetitions_heures}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ export { generateDateRange };
|
|||
export function formatQuantifiedDates(
|
||||
isos: string[],
|
||||
quantities: Record<string, number | string>,
|
||||
dateType: "representations" | "repetitions" | "jours_travail"
|
||||
dateType: "representations" | "repetitions" | "jours_travail" | "heures_repetitions"
|
||||
): string {
|
||||
if (!isos || isos.length === 0) return "";
|
||||
|
||||
|
|
@ -121,7 +121,7 @@ export function formatQuantifiedDates(
|
|||
let base = '';
|
||||
if (dateType === 'representations') base = qtyNum > 1 ? 'représentations' : 'représentation';
|
||||
else if (dateType === 'repetitions') base = qtyNum > 1 ? 'services de répétition' : 'service de répétition';
|
||||
else if (dateType === 'jours_travail') base = qtyNum > 1 ? 'heures' : 'heure';
|
||||
else if (dateType === 'jours_travail' || dateType === 'heures_repetitions') base = qtyNum > 1 ? 'heures' : 'heure';
|
||||
|
||||
if (g.startIso === g.endIso) {
|
||||
// date isolée
|
||||
|
|
@ -129,7 +129,7 @@ export function formatQuantifiedDates(
|
|||
}
|
||||
|
||||
// plage: utiliser "par jour" pour indiquer par-journée
|
||||
if (dateType === 'jours_travail') {
|
||||
if (dateType === 'jours_travail' || dateType === 'heures_repetitions') {
|
||||
return `${qty} ${base} par jour du ${formatDateFr(g.startIso)} au ${formatDateFr(g.endIso!)}`;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,8 +29,11 @@ export interface AmendmentDureeData {
|
|||
nb_representations?: number;
|
||||
nb_repetitions?: number;
|
||||
nb_heures?: number; // Pour techniciens
|
||||
heures_repetitions?: number; // Heures totales pour répétitions (artistes)
|
||||
minutes_repetitions?: string; // Minutes pour répétitions: "0" ou "30"
|
||||
dates_representations?: string;
|
||||
dates_repetitions?: string;
|
||||
dates_repetitions_heures?: string; // Heures de répétition par jour (format texte)
|
||||
jours_travail?: string;
|
||||
}
|
||||
|
||||
|
|
@ -104,6 +107,8 @@ export interface OriginalContractData {
|
|||
nb_representations?: number;
|
||||
nb_repetitions?: number;
|
||||
nb_heures?: number;
|
||||
heures_repetitions?: number; // Heures totales pour répétitions (artistes)
|
||||
minutes_repetitions?: string; // Minutes pour répétitions: "0" ou "30"
|
||||
dates_representations?: string;
|
||||
dates_repetitions?: string;
|
||||
jours_travail?: string;
|
||||
|
|
|
|||
Loading…
Reference in a new issue