Le problème était que l'update du champ contract_pdf_s3_key utilisait le client Supabase normal (avec RLS) au lieu du client admin (service role). Cela empêchait potentiellement la mise à jour du contrat ou l'accès côté client. Changements: - Import de createClient depuis @supabase/supabase-js - Création d'un adminClient avec SUPABASE_SERVICE_ROLE_KEY - Utilisation de adminClient pour l'update au lieu de sb - Ajout de logs pour le debug
4.9 KiB
Fix : Rafraîchissement des documents après upload manuel du contrat signé
Problème identifié
Lorsqu'un contrat de travail était uploadé manuellement depuis la page staff (staff/contrats/[id]), il n'apparaissait pas immédiatement sur la page client (contrats/[id]).
Cause racine
Le composant DocumentsCard utilisé par la page client effectuait des appels fetch directs dans des useEffect avec uniquement contractId comme dépendance. Ces appels n'étaient donc déclenchés qu'au montage du composant, et pas lors d'un upload manuel effectué depuis une autre page.
Côté staff, le système fonctionnait correctement car il utilisait React Query avec invalidation de cache.
Solution implémentée
1. Ajout d'un mécanisme de refresh dans DocumentsCard
Fichier : components/contrats/DocumentsCard.tsx
- Ajout d'une prop
refreshTrigger?: number - Ajout de
refreshTriggercomme dépendance dans tous lesuseEffectqui récupèrent les données - Ajout de
setLoadingSignedPdf(true)au début defetchSignedPdfpour afficher un loader lors du rechargement
interface DocumentsCardProps {
contractId: string;
contractNumber?: string;
contractData?: { ... };
showPayslips?: boolean;
refreshTrigger?: number; // ← Nouvelle prop
}
useEffect(() => {
const fetchSignedPdf = async () => {
setLoadingSignedPdf(true); // ← Ajouté
// ... code de récupération
};
fetchSignedPdf();
}, [contractId, refreshTrigger]); // ← refreshTrigger ajouté
2. Système d'événements personnalisés
Fichier : components/staff/contracts/ManualSignedContractUpload.tsx
Après un upload réussi, émission d'un événement personnalisé :
// Émettre un événement personnalisé pour rafraîchir les documents côté client
if (typeof window !== 'undefined') {
window.dispatchEvent(new CustomEvent('refreshContractDocuments'));
}
3. Écoute de l'événement dans la page client
Fichier : app/(app)/contrats/[id]/page.tsx
- Ajout d'un state
documentsRefreshTrigger - Ajout d'un listener pour l'événement
refreshContractDocuments - Passage de
refreshTriggerau composantDocumentsCard
const [documentsRefreshTrigger, setDocumentsRefreshTrigger] = useState<number>(0);
useEffect(() => {
const handleRefreshDocuments = () => {
console.log('🔄 Rafraîchissement des documents demandé');
setDocumentsRefreshTrigger(prev => prev + 1);
};
window.addEventListener('refreshContractDocuments', handleRefreshDocuments);
return () => {
window.removeEventListener('refreshContractDocuments', handleRefreshDocuments);
};
}, []);
// Dans le JSX
<DocumentsCard
contractId={id}
contractNumber={data.numero}
contractData={{ ... }}
refreshTrigger={documentsRefreshTrigger}
/>
Flux de données
- Upload manuel : L'utilisateur staff upload un contrat signé via
ManualSignedContractUpload - Upload S3 : Le fichier est uploadé sur S3 et
contract_pdf_s3_keyest mis à jour dans la base de données - Invalidation React Query : La query
["signed-contract-pdf", contract.id]est invalidée côté staff - Événement custom : Un événement
refreshContractDocumentsest émis globalement - Réception côté client : La page client écoute cet événement et incrémente
documentsRefreshTrigger - Rechargement :
DocumentsCarddétecte le changement derefreshTriggeret re-déclenche sesuseEffect - Affichage : Le contrat signé apparaît dans la liste des documents
Avantages de cette approche
- Compatibilité : Fonctionne même si la page client n'est pas en React Query
- Découplage : Les composants ne sont pas fortement couplés
- Extensible : D'autres composants peuvent écouter le même événement si nécessaire
- Performance : Pas de polling inutile, rechargement uniquement quand nécessaire
Tests à effectuer
- Upload manuel d'un contrat depuis la page staff
- Vérifier que le contrat apparaît sur la page client (après F5 ou event)
- Vérifier que l'upload fonctionne toujours côté staff (avec React Query)
- Vérifier les logs console pour confirmer le déclenchement de l'événement
Commit
fix: Rafraîchir les documents côté client après upload manuel du contrat signé
- Ajout d'une prop refreshTrigger à DocumentsCard pour forcer le rechargement
- Ajout d'un listener d'événement custom 'refreshContractDocuments' dans la page client
- Émission de l'événement après l'upload réussi dans ManualSignedContractUpload
- Fix: Le contrat signé apparaît maintenant sur la page client après upload manuel depuis staff
Notes
- Cette solution est temporaire en attendant une migration complète vers React Query dans
DocumentsCard - À terme, il serait préférable de centraliser toutes les requêtes de documents dans React Query
- L'événement
refreshContractDocumentspourrait être typé avec TypeScript pour plus de sécurité