403 lines
12 KiB
HTML
403 lines
12 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="fr">
|
||
<head>
|
||
<meta charset="UTF-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||
<title>Générateur de Devis</title>
|
||
<link rel="stylesheet" href="styles.css" />
|
||
</head>
|
||
<body>
|
||
<header class="app-header">
|
||
<div class="brand">
|
||
<span class="logo-circle">€</span>
|
||
<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>
|
||
</div>
|
||
<input
|
||
id="importJsonInput"
|
||
type="file"
|
||
accept="application/json"
|
||
style="display: none"
|
||
/>
|
||
</header>
|
||
|
||
<main class="container">
|
||
<section class="panel form-panel">
|
||
<h2>Paramètres</h2>
|
||
<div class="grid two">
|
||
<div>
|
||
<label
|
||
>Devise
|
||
<select id="currency">
|
||
<option value="EUR">EUR €</option>
|
||
<option value="USD">USD $</option>
|
||
<option value="GBP">GBP £</option>
|
||
<option value="CHF">CHF Fr.</option>
|
||
</select>
|
||
</label>
|
||
</div>
|
||
<div>
|
||
<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
|
||
<select id="printTemplate">
|
||
<option value="standard">Standard</option>
|
||
<option value="pro-minimal">Pro Minimal</option>
|
||
<option value="pro-striped">Pro Bandes</option>
|
||
<option value="compact">Compact</option>
|
||
<option value="pro-borders">Pro Bordures</option>
|
||
<option value="sidebar-accent">Bandeau Latéral</option>
|
||
<option value="centered-minimal">Minimal Centré</option>
|
||
</select>
|
||
</label>
|
||
</div>
|
||
|
||
<div class="grid two">
|
||
<div>
|
||
<h3>Votre entreprise</h3>
|
||
<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>
|
||
<div class="grid two">
|
||
<label
|
||
>Code postal
|
||
<input id="myPostcode" type="text" placeholder="75002" />
|
||
</label>
|
||
<label
|
||
>Ville
|
||
<input id="myCity" type="text" placeholder="Paris" />
|
||
</label>
|
||
</div>
|
||
<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>
|
||
<label
|
||
>Téléphone
|
||
<input
|
||
id="myPhone"
|
||
type="tel"
|
||
placeholder="+33 6 12 34 56 78"
|
||
/>
|
||
</label>
|
||
</div>
|
||
<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>
|
||
</div>
|
||
<div>
|
||
<h3>Client</h3>
|
||
<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>
|
||
<div class="grid two">
|
||
<label
|
||
>Code postal
|
||
<input id="clientPostcode" type="text" placeholder="33000" />
|
||
</label>
|
||
<label
|
||
>Ville
|
||
<input id="clientCity" type="text" placeholder="Bordeaux" />
|
||
</label>
|
||
</div>
|
||
<label
|
||
>Pays
|
||
<input id="clientCountry" type="text" placeholder="France" />
|
||
</label>
|
||
<div class="grid two">
|
||
<label
|
||
>Email
|
||
<input id="clientEmail" type="email" />
|
||
</label>
|
||
<label
|
||
>Téléphone
|
||
<input id="clientPhone" type="tel" />
|
||
</label>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<h3>Détails du devis</h3>
|
||
<div class="grid three">
|
||
<label
|
||
>Numéro de devis
|
||
<input id="quoteNumber" type="text" />
|
||
</label>
|
||
<label
|
||
>Date
|
||
<input id="quoteDate" type="date" />
|
||
</label>
|
||
<label
|
||
>Valable jusqu'au
|
||
<input id="quoteValidUntil" type="date" />
|
||
</label>
|
||
</div>
|
||
|
||
<h3>Lignes</h3>
|
||
<div class="table">
|
||
<div class="table-head">
|
||
<div></div>
|
||
<div>Description</div>
|
||
<div>Temps (jours)</div>
|
||
<div>PU HT</div>
|
||
<div>Total HT</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>
|
||
|
||
<div class="grid two mt">
|
||
<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>
|
||
</div>
|
||
<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" 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>
|
||
<div class="icon-text">
|
||
<span class="ico">🧾</span
|
||
><span class="company-legal" id="p_myLegal"></span>
|
||
</div>
|
||
</div>
|
||
</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="quote-title-block">
|
||
<div class="quote-title">DEVIS</div>
|
||
<div class="quote-number">N° <span id="p_quoteNumber"></span></div>
|
||
</div>
|
||
|
||
<div class="items original">
|
||
<div class="items-section-title">Détail de la prestation</div>
|
||
<div id="p_items" class="items-body"></div>
|
||
</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>
|
||
<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>
|
||
</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 -->
|
||
<div id="libraryModal" class="modal" aria-hidden="true">
|
||
<div class="modal-backdrop" data-close="1"></div>
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h3>Devis enregistrés</h3>
|
||
<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 l’instant.
|
||
</div>
|
||
<div id="libraryList" class="library-list"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script src="app.js"></script>
|
||
</body>
|
||
</html>
|