SDK React - @itzenata/efact-react
Composants React prêts à l'emploi pour afficher le statut d'une facture électronique en temps réel.
Installation
Installation
npm install @itzenata/efact-reactPeer dependencies
(doivent être installées séparément) :
Peer Dependencies
npm install react react-domVersions supportées : React 18+.
Configuration du Provider
Envelopper l'application (ou la partie concernée) avec ItzenataProvider :
app/layout.tsx
// app/layout.tsx (Next.js App Router)
import { ItzenataProvider } from '@itzenata/efact-react'
export default function RootLayout({ children }) {
return (
<html>
<body>
<ItzenataProvider publishableKey={process.env.NEXT_PUBLIC_EFACT_PUBLISHABLE_KEY}>
{children}
</ItzenataProvider>
</body>
</html>
)
}La clé publiable est la seule information sensible nécessaire côté frontend - elle est sûre à exposer dans le navigateur.
Composant <InvoiceStatus />
Le composant principal. Affiche le cycle de vie d'une facture en temps réel via SSE.
Usage minimal
Minimal Usage
import { InvoiceStatus } from '@itzenata/efact-react'
export function InvoicePage({ clientSecret }: { clientSecret: string }) {
return <InvoiceStatus clientSecret={clientSecret} />
}Props
| Prop | Type | Requis | Description |
|---|---|---|---|
clientSecret | string | Oui | client_secret retourné par invoices.create() |
onStatusChange | (status: InvoiceStatus) => void | Non | Callback appelé à chaque changement de statut |
onAccepted | (data: InvoiceAcceptedData) => void | Non | Callback quand la DGI accepte la facture |
onRejected | (data: InvoiceRejectedData) => void | Non | Callback quand la DGI rejette la facture |
locale | 'fr' | 'ar' | Non | Langue d'affichage - défaut : 'fr' |
showDownloadLinks | boolean | Non | Afficher les liens PDF/XML - défaut : true |
showQRCode | boolean | Non | Afficher le QR code DGI - défaut : true |
showRetryButton | boolean | Non | Afficher "Renvoyer" si rejeté - défaut : true |
className | string | Non | Classe CSS personnalisée sur le container |
Exemple avec callbacks
Callbacks Example
import { InvoiceStatus } from '@itzenata/efact-react'
import { useRouter } from 'next/navigation'
export function InvoicePage({ clientSecret, invoiceId }) {
const router = useRouter()
return (
<InvoiceStatus
clientSecret={clientSecret}
onAccepted={({ dgiId, pdfUrl, xmlUrl }) => {
console.log('Facture acceptée par la DGI, ID :', dgiId)
// Rediriger vers la page de confirmation
router.push(`/invoices/${invoiceId}/confirmed`)
}}
onRejected={({ rejectionReason }) => {
console.error('Facture rejetée :', rejectionReason)
}}
onStatusChange={(status) => {
// Tracking analytics
analytics.track('invoice_status_changed', { status })
}}
locale="fr"
/>
)
}Ce qu'affiche <InvoiceStatus />
États et leur rendu
| Statut | Affichage |
|---|---|
pending | Indicateur de chargement + "Traitement en cours..." |
signing | Icône signature + "Signature électronique..." |
transmitted | Icône envoi + "Transmis à la DGI..." |
accepted | Icône succès vert + QR code + liens téléchargement |
rejected | Icône erreur rouge + motif de rejet + bouton "Renvoyer" |
Rendu état accepted
Facture acceptée par la DGI
────────────────────────────────
[QR Code DGI] ID DGI : DGI-2026-0042-XYZABC
Télécharger PDF Télécharger XML signé
────────────────────────────────
[QR Code DGI] ID DGI : DGI-2026-0042-XYZABC
Télécharger PDF Télécharger XML signé
Hook useInvoice
Pour un contrôle total sur le rendu, utiliser le hook bas niveau :
Custom Hook Usage
import { useInvoice } from '@itzenata/efact-react'
export function CustomInvoiceStatus({ clientSecret }) {
const { invoice, isLoading, error } = useInvoice(clientSecret)
if (isLoading) return <Spinner />
if (error) return <ErrorMessage message={error.message} />
return (
<div>
<p>Statut : {invoice.status}</p>
{invoice.status === 'accepted' && (
<div>
<p>ID DGI : {invoice.dgiId}</p>
<a href={invoice.pdfUrl} download>Télécharger PDF</a>
</div>
)}
{invoice.status === 'rejected' && (
<p className="text-red-500">{invoice.rejectionReason}</p>
)}
</div>
)
}Valeur retournée par useInvoice
Hook Interface
interface UseInvoiceResult {
invoice: Invoice | null
isLoading: boolean
error: Error | null
retry: () => Promise<void> // forcer un renvoi si status === 'rejected'
}Personnalisation du style
Via className
Custom ClassName
<InvoiceStatus
clientSecret={clientSecret}
className="my-custom-invoice-status"
/>Custom CSS
.my-custom-invoice-status {
border: 2px solid #e2e8f0;
border-radius: 8px;
padding: 24px;
}Variables CSS
Le composant expose des variables CSS pour la personnalisation des couleurs :
CSS Variables
:root {
--efact-color-pending: #6b7280;
--efact-color-signing: #f59e0b;
--efact-color-transmitted: #3b82f6;
--efact-color-accepted: #10b981;
--efact-color-rejected: #ef4444;
--efact-font-family: inherit;
--efact-border-radius: 8px;
}Intégration complète - Exemple Next.js
app/invoices/[id]/page.tsx
// app/invoices/[id]/page.tsx
import { getInvoiceClientSecret } from '@/lib/invoices'
import { InvoiceStatus } from '@itzenata/efact-react'
export default async function InvoicePage({ params }) {
// Récupérer le clientSecret depuis votre base de données
const { clientSecret } = await getInvoiceClientSecret(params.id)
return (
<main className="max-w-2xl mx-auto p-8">
<h1 className="text-2xl font-bold mb-6">Statut de votre facture</h1>
<InvoiceStatus
clientSecret={clientSecret}
showQRCode={true}
showDownloadLinks={true}
/>
</main>
)
}Compatibilité
| Environnement | Support |
|---|---|
| Next.js 14+ (App Router) | Supporté |
| Next.js 13 (Pages Router) | Supporté |
| Vite + React | Supporté |
| Create React App | Supporté |
| Remix | Supporté |
| Server Components (RSC) | Client component uniquement - utiliser 'use client' |