253 lines
10 KiB
HTML
253 lines
10 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 du devis
|
||
<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" alt="Logo" />
|
||
<div>
|
||
<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="quote-meta">
|
||
<div class="quote-title">DEVIS</div>
|
||
<div class="icon-text right"><span class="ico">#</span><span><strong>N°</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>
|
||
</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>
|
||
|
||
<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 id="p_items" class="items-body"></div>
|
||
</div>
|
||
<!-- Conteneur des pages imprimées, construit dynamiquement -->
|
||
<div id="printPages" class="print-pages"></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="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>
|
||
</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>
|