fix: impression PDF sans pagination custom

This commit is contained in:
Matthieu
2025-12-05 10:35:08 +01:00
parent 952a43059b
commit dde9737ce7
6 changed files with 2026 additions and 811 deletions

BIN
LOGO-DEVIS.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

1384
app.js

File diff suppressed because it is too large Load Diff

View File

@@ -13,14 +13,43 @@
<h1>Générateur de Devis</h1>
</div>
<div class="actions">
<button id="saveQuoteBtn" class="btn" title="Enregistrer ce devis">Enregistrer</button>
<button id="openLibraryBtn" class="btn" title="Voir les devis enregistrés">Devis enregistrés</button>
<button id="importJsonBtn" class="btn" title="Importer un JSON">Importer JSON</button>
<button id="exportJsonBtn" class="btn" title="Exporter en JSON">Exporter JSON</button>
<button id="resetBtn" class="btn btn-secondary" title="Réinitialiser les champs">Réinitialiser</button>
<button id="printBtn" class="btn btn-primary" title="Télécharger en PDF">Télécharger PDF</button>
<button id="saveQuoteBtn" class="btn" title="Enregistrer ce devis">
Enregistrer
</button>
<button
id="openLibraryBtn"
class="btn"
title="Voir les devis enregistrés"
>
Devis enregistrés
</button>
<button id="importJsonBtn" class="btn" title="Importer un JSON">
Importer JSON
</button>
<button id="exportJsonBtn" class="btn" title="Exporter en JSON">
Exporter JSON
</button>
<button
id="resetBtn"
class="btn btn-secondary"
title="Réinitialiser les champs"
>
Réinitialiser
</button>
<button
id="printBtn"
class="btn btn-primary"
title="Télécharger en PDF"
>
Télécharger PDF
</button>
</div>
<input id="importJsonInput" type="file" accept="application/json" style="display:none" />
<input
id="importJsonInput"
type="file"
accept="application/json"
style="display: none"
/>
</header>
<main class="container">
@@ -28,7 +57,8 @@
<h2>Paramètres</h2>
<div class="grid two">
<div>
<label>Devise
<label
>Devise
<select id="currency">
<option value="EUR">EUR €</option>
<option value="USD">USD $</option>
@@ -38,15 +68,23 @@
</label>
</div>
<div>
<label>Taux de TVA (%)
<input type="number" id="vatRate" min="0" step="0.01" value="20" />
<label
>Taux de TVA (%)
<input
type="number"
id="vatRate"
min="0"
step="0.01"
value="20"
/>
</label>
</div>
</div>
<h3>Apparence</h3>
<div class="grid two">
<label>Modèle d'impression
<label
>Modèle d'impression
<select id="printTemplate">
<option value="standard">Standard</option>
<option value="pro-minimal">Pro Minimal</option>
@@ -59,66 +97,101 @@
</label>
</div>
<div class="grid two">
<div>
<h3>Votre entreprise</h3>
<label>Nom de l'entreprise
<label
>Nom de l'entreprise
<input id="myName" type="text" placeholder="Ex: ACME SAS" />
</label>
<label>Rue et numéro
<input id="myStreet" type="text" placeholder="Ex: 10 rue de la Paix" />
<label
>Rue et numéro
<input
id="myStreet"
type="text"
placeholder="Ex: 10 rue de la Paix"
/>
</label>
<div class="grid two">
<label>Code postal
<label
>Code postal
<input id="myPostcode" type="text" placeholder="75002" />
</label>
<label>Ville
<label
>Ville
<input id="myCity" type="text" placeholder="Paris" />
</label>
</div>
<label>Pays
<label
>Pays
<input id="myCountry" type="text" placeholder="France" />
</label>
<div class="grid two">
<label>Email
<input id="myEmail" type="email" placeholder="contact@exemple.com" />
<label
>Email
<input
id="myEmail"
type="email"
placeholder="contact@exemple.com"
/>
</label>
<label>Téléphone
<input id="myPhone" type="tel" placeholder="+33 6 12 34 56 78" />
<label
>Téléphone
<input
id="myPhone"
type="tel"
placeholder="+33 6 12 34 56 78"
/>
</label>
</div>
<label>Logo (URL ou data URI)
<label
>Logo (URL ou data URI)
<input id="myLogo" type="text" placeholder="https://..." />
</label>
<label>Numéro SIREN / TVA
<input id="myLegal" type="text" placeholder="SIREN, TVA intracom..." />
<label
>Numéro SIREN / TVA
<input
id="myLegal"
type="text"
placeholder="SIREN, TVA intracom..."
/>
</label>
</div>
<div>
<h3>Client</h3>
<label>Nom / Société
<label
>Nom / Société
<input id="clientName" type="text" placeholder="Nom du client" />
</label>
<label>Rue et numéro
<input id="clientStreet" type="text" placeholder="Ex: 20 avenue Victor Hugo" />
<label
>Rue et numéro
<input
id="clientStreet"
type="text"
placeholder="Ex: 20 avenue Victor Hugo"
/>
</label>
<div class="grid two">
<label>Code postal
<label
>Code postal
<input id="clientPostcode" type="text" placeholder="33000" />
</label>
<label>Ville
<label
>Ville
<input id="clientCity" type="text" placeholder="Bordeaux" />
</label>
</div>
<label>Pays
<label
>Pays
<input id="clientCountry" type="text" placeholder="France" />
</label>
<div class="grid two">
<label>Email
<label
>Email
<input id="clientEmail" type="email" />
</label>
<label>Téléphone
<label
>Téléphone
<input id="clientPhone" type="tel" />
</label>
</div>
@@ -127,13 +200,16 @@
<h3>Détails du devis</h3>
<div class="grid three">
<label>Numéro de devis
<label
>Numéro de devis
<input id="quoteNumber" type="text" />
</label>
<label>Date du devis
<label
>Date
<input id="quoteDate" type="date" />
</label>
<label>Valable jusqu'au
<label
>Valable jusqu'au
<input id="quoteValidUntil" type="date" />
</label>
</div>
@@ -146,88 +222,162 @@
<div>Temps (jours)</div>
<div>PU HT</div>
<div>Total HT</div>
<div><input id="selectAllRows" type="checkbox" title="Tout sélectionner" /></div>
<div>
<input
id="selectAllRows"
type="checkbox"
title="Tout sélectionner"
/>
</div>
</div>
<div id="items" class="table-body"></div>
</div>
<div class="actions" style="margin-top:8px; gap:8px; flex-wrap: wrap;">
<button id="addItemBtn" class="btn btn-outline">+ Ajouter une ligne</button>
<button id="addGroupBtn" class="btn btn-outline">+ Ajouter un groupe</button>
<button id="duplicateSelectedBtn" class="btn">Dupliquer sélection</button>
<button id="deleteSelectedBtn" class="btn btn-danger">Supprimer sélection</button>
<div class="actions" style="margin-top: 8px; gap: 8px; flex-wrap: wrap">
<button id="addItemBtn" class="btn btn-outline">
+ Ajouter une ligne
</button>
<button id="addGroupBtn" class="btn btn-outline">
+ Ajouter un groupe
</button>
<button id="duplicateSelectedBtn" class="btn">
Dupliquer sélection
</button>
<button id="deleteSelectedBtn" class="btn btn-danger">
Supprimer sélection
</button>
</div>
<div class="grid two mt">
<label>Remise (%)
<input id="discountRate" type="number" min="0" step="0.01" value="0" />
<label
>Remise (%)
<input
id="discountRate"
type="number"
min="0"
step="0.01"
value="0"
/>
</label>
<label>Conditions de paiement
<input id="paymentTerms" type="text" placeholder="30 jours, virement..." />
<label
>Conditions de paiement
<input
id="paymentTerms"
type="text"
placeholder="30 jours, virement..."
/>
</label>
</div>
<label>Notes
<textarea id="notes" rows="3" placeholder="Informations complémentaires"></textarea>
<label
>Notes
<textarea
id="notes"
rows="3"
placeholder="Informations complémentaires"
></textarea>
</label>
</section>
<section class="panel preview-panel" id="printArea">
<div class="quote-header">
<div class="company">
<img id="p_myLogo" class="logo" alt="Logo" />
<div>
<img id="p_myLogo" class="logo" src="LOGO-DEVIS.jpg" alt="Logo" />
<div class="company-details">
<div class="company-name" id="p_myName"></div>
<div class="icon-text"><span class="ico">📍</span><span class="company-address" id="p_myAddress"></span></div>
<div class="company-contact stack">
<div class="icon-text"><span class="ico">✉️</span><span id="p_myEmail"></span></div>
<div class="icon-text"><span class="ico">📞</span><span id="p_myPhone"></span></div>
<div class="icon-text">
<span class="ico">📍</span
><span class="company-address" id="p_myAddress"></span>
</div>
<div class="company-contact stack">
<div class="icon-text">
<span class="ico">✉️</span><span id="p_myEmail"></span>
</div>
<div class="icon-text">
<span class="ico">📞</span><span id="p_myPhone"></span>
</div>
</div>
<div class="icon-text">
<span class="ico">🧾</span
><span class="company-legal" id="p_myLegal"></span>
</div>
<div class="icon-text"><span class="ico">🧾</span><span class="company-legal" id="p_myLegal"></span></div>
</div>
</div>
<div class="quote-meta">
<div class="quote-title">DEVIS</div>
<div class="icon-text right"><span class="ico">#</span><span><strong></strong> <span id="p_quoteNumber"></span></span></div>
<div class="icon-text right"><span class="ico">📅</span><span><strong>Date</strong> <span id="p_quoteDate"></span></span></div>
<div class="icon-text right"><span class="ico"></span><span><strong>Valide jusqu'au</strong> <span id="p_quoteValidUntil"></span></span></div>
<div class="header-right">
<div class="quote-dates">
<div class="quote-date-value" id="p_quoteDate"></div>
</div>
<div class="client-block">
<div class="muted">Destiné à</div>
<div class="client-name" id="p_clientName"></div>
<div class="icon-text">
<span class="ico">📍</span
><span class="client-address" id="p_clientAddress"></span>
</div>
<div class="client-contact stack">
<div class="icon-text">
<span class="ico">✉️</span><span id="p_clientEmail"></span>
</div>
<div class="icon-text">
<span class="ico">📞</span><span id="p_clientPhone"></span>
</div>
</div>
</div>
</div>
</div>
<div class="client-block">
<div class="muted">Destinataire</div>
<div class="client-name" id="p_clientName"></div>
<div class="icon-text"><span class="ico">📍</span><span class="client-address" id="p_clientAddress"></span></div>
<div class="client-contact stack">
<div class="icon-text"><span class="ico">✉️</span><span id="p_clientEmail"></span></div>
<div class="icon-text"><span class="ico">📞</span><span id="p_clientPhone"></span></div>
</div>
<div class="quote-title-block">
<div class="quote-title">DEVIS</div>
<div class="quote-number"><span id="p_quoteNumber"></span></div>
</div>
<div class="items original">
<div class="items-head">
<div>Description</div><div>Temps (jours)</div><div>PU HT</div><div>Total HT</div>
</div>
<div class="items-section-title">Détail de la prestation</div>
<div id="p_items" class="items-body"></div>
</div>
<!-- Conteneur des pages imprimées, construit dynamiquement -->
<div id="printPages" class="print-pages"></div>
<div id="printPages" class="print-pages" aria-hidden="true"></div>
<div class="totals">
<div class="row"><span>Total jours</span><span id="p_totalDays"></span></div>
<div class="row"><span>Sous-total</span><span id="p_subtotal"></span></div>
<div class="row"><span>Remise</span><span id="p_discount"></span></div>
<div class="row"><span>TVA (<span id="p_vatRate"></span>%)</span><span id="p_vat"></span></div>
<div class="row grand"><span>Total TTC</span><span id="p_total"></span></div>
<div class="row">
<span>Total jours</span><span id="p_totalDays"></span>
</div>
<div class="row">
<span>Sous-total</span><span id="p_subtotal"></span>
</div>
<div class="row">
<span>Remise</span><span id="p_discount"></span>
</div>
<div class="row">
<span>TVA (<span id="p_vatRate"></span>%)</span
><span id="p_vat"></span>
</div>
<div class="row grand">
<span>Total TTC</span><span id="p_total"></span>
</div>
</div>
<div class="signature-block">
Signature du client précédée de la mention "bon pour accord"
</div>
<div class="quote-valid-row">
<span class="quote-date-label">Valable jusqu'au</span>
<span class="quote-date-value" id="p_quoteValidUntil"></span>
</div>
<div class="notes">
<div class="icon-text"><span class="ico">💳</span><span><strong>Conditions de paiement:</strong> <span id="p_paymentTerms"></span></span></div>
<div class="icon-text"><span class="ico">📝</span><span id="p_notes"></span></div>
<div class="icon-text">
<span class="ico">💳</span
><span
><strong>Conditions de paiement:</strong>
<span id="p_paymentTerms"></span
></span>
</div>
<div class="icon-text">
<span class="ico">📝</span><span id="p_notes"></span>
</div>
</div>
</section>
</main>
<footer class="app-footer">
<span>Fait avec ❤️ — export PDF via impression</span>
<span class="page-counter" aria-hidden="true"></span>
</footer>
<!-- Modal Bibliothèque de devis -->
@@ -239,14 +389,14 @@
<button class="btn" id="closeLibraryBtn" title="Fermer"></button>
</div>
<div class="modal-body">
<div id="libraryEmpty" class="muted" style="display:none">Aucun devis enregistré pour linstant.</div>
<div id="libraryEmpty" class="muted" style="display: none">
Aucun devis enregistré pour linstant.
</div>
<div id="libraryList" class="library-list"></div>
</div>
</div>
</div>
<script src="app.js"></script>
</body>
</html>
</html>

BIN
sample-devis-1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 KiB

BIN
sample-devis.pdf Normal file

Binary file not shown.

1133
styles.css

File diff suppressed because it is too large Load Diff