<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>thermoprint — Receipt Builder</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="app">
<aside class="sidebar">
<div class="sidebar-header">
<div class="logo-row">
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="3" y="7" width="16" height="10" rx="2" fill="#1e293b"/>
<rect x="3" y="7" width="16" height="4" rx="2" fill="#e94560"/>
<rect x="6" y="12" width="10" height="1.2" rx="0.6" fill="#334155"/>
<rect x="7" y="14" width="8" height="5" rx="1" fill="#f1f5f9"/>
<rect x="8.5" y="15.5" width="1" height="2.5" fill="#334155"/>
<rect x="10" y="15.5" width="1.5" height="2.5" fill="#334155"/>
<rect x="12" y="15.5" width="1" height="2.5" fill="#334155"/>
<circle cx="17" cy="9" r="1" fill="#4ecca3"/>
</svg>
<span class="logo-text">thermo<span class="accent">print</span></span>
</div>
<p class="subtitle">ESC/POS Receipt Builder</p>
</div>
<form id="receipt-form" autocomplete="off">
<section class="form-section">
<h3 class="section-title">Shop Info</h3>
<div class="field">
<label>Shop Name</label>
<div class="input-with-align">
<input title="shop-name" type="text" id="shop-name" value="MA BOUTIQUE" />
<div class="align-btns" data-target="header-align">
<button type="button" class="align-btn active" data-align="center" title="Center">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="10" x2="6" y2="10"/><line x1="21" y1="6" x2="3" y2="6"/><line x1="21" y1="14" x2="3" y2="14"/><line x1="18" y1="18" x2="6" y2="18"/></svg>
</button>
<button type="button" class="align-btn" data-align="left" title="Left">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="17" y1="10" x2="3" y2="10"/><line x1="21" y1="6" x2="3" y2="6"/><line x1="21" y1="14" x2="3" y2="14"/><line x1="17" y1="18" x2="3" y2="18"/></svg>
</button>
<button type="button" class="align-btn" data-align="right" title="Right">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="21" y1="10" x2="7" y2="10"/><line x1="21" y1="6" x2="3" y2="6"/><line x1="21" y1="14" x2="3" y2="14"/><line x1="21" y1="18" x2="7" y2="18"/></svg>
</button>
</div>
</div>
</div>
<div class="field">
<label>Phone</label>
<input title="shop-phone" type="text" id="shop-phone" value="+221 77 000 00 00" />
</div>
<div class="field">
<label>Address</label>
<input title="shop-address" type="text" id="shop-address" value="Dakar, Senegal" />
</div>
<div class="field-row">
<div class="field">
<label>Currency</label>
<input title="currency" type="text" id="currency" value="FCFA" maxlength="8" />
</div>
<div class="field">
<label>Paper Width</label>
<select title="paper-width" id="paper-width">
<option value="58mm">58 mm</option>
<option value="80mm" selected>80 mm</option>
<option value="a4">A4</option>
</select>
</div>
</div>
<div class="field">
<label>Language</label>
<select title="language" id="language">
<option value="fr" selected>Francais</option>
<option value="en">English</option>
<option value="es">Espanol</option>
<option value="pt">Portugues</option>
<option value="ar">Arabic (Latin)</option>
<option value="wo">Wolof</option>
</select>
</div>
</section>
<section class="form-section">
<h3 class="section-title">
Items
<button type="button" class="btn-add" id="add-item">+ Add Item</button>
</h3>
<div id="items-list"></div>
</section>
<section class="form-section">
<h3 class="section-title">
Taxes
<button type="button" class="btn-add" id="add-tax">+ Add Tax</button>
</h3>
<p class="section-hint">Tax amounts are <strong>auto-calculated</strong> from subtotal.</p>
<div id="taxes-list"></div>
</section>
<section class="form-section">
<h3 class="section-title">
Custom Lines
<button type="button" class="btn-add" id="add-custom-line">+ Add</button>
</h3>
<p class="section-hint">Extra text lines inserted before totals.</p>
<div id="custom-lines-list"></div>
</section>
<section class="form-section">
<h3 class="section-title">Payment</h3>
<div class="field-row">
<div class="field">
<label>Received</label>
<input title="received" type="number" id="received" value="100000" min="0" />
</div>
<div class="field">
<label>Order Ref</label>
<input title="order-ref" type="text" id="order-ref" value="ORD-2024-001" />
</div>
</div>
<div class="field">
<label>Served by</label>
<input title="served-by" type="text" id="served-by" value="Mamadou" />
</div>
</section>
<section class="form-section">
<h3 class="section-title">Logo</h3>
<p class="section-hint">Upload an image — it will be dithered for thermal printing.</p>
<div class="logo-upload-area" id="logo-upload-area">
<input type="file" id="logo-file" accept="image/*" hidden />
<canvas id="logo-canvas" hidden></canvas>
<div class="logo-preview" id="logo-preview">
<button type="button" class="btn-upload" id="btn-upload-logo">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>
Upload Logo
</button>
<button type="button" class="btn-remove-logo" id="btn-remove-logo" style="display:none" title="Remove logo">×</button>
<img id="logo-img-preview" style="display:none;max-width:100%;max-height:80px;margin-top:6px;border-radius:4px" />
</div>
</div>
</section>
<section class="form-section">
<h3 class="section-title">Options</h3>
<div class="checkboxes">
<label class="checkbox-label">
<input type="checkbox" id="opt-date" checked /> Print date & time
</label>
<label class="checkbox-label">
<input type="checkbox" id="opt-receipt-no" checked /> Receipt number
</label>
<label class="checkbox-label">
<input type="checkbox" id="opt-barcode" checked /> Barcode (Code128)
</label>
<label class="checkbox-label">
<input type="checkbox" id="opt-qr" /> QR Code
</label>
<label class="checkbox-label">
<input type="checkbox" id="opt-thankyou" checked /> Thank-you footer
</label>
<label class="checkbox-label">
<input type="checkbox" id="opt-cut" checked /> Paper cut
</label>
</div>
<div class="field" id="qr-data-field" style="display:none;margin-top:8px">
<label>QR Data</label>
<input title="qr-data" type="text" id="qr-data" value="https://thermoprint.dev" placeholder="URL or text" />
</div>
<div class="field" style="margin-top:8px">
<label>Footer Alignment</label>
<div class="align-btns" data-target="footer-align">
<button type="button" class="align-btn active" data-align="center" title="Center">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="10" x2="6" y2="10"/><line x1="21" y1="6" x2="3" y2="6"/><line x1="21" y1="14" x2="3" y2="14"/><line x1="18" y1="18" x2="6" y2="18"/></svg>
</button>
<button type="button" class="align-btn" data-align="left" title="Left">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="17" y1="10" x2="3" y2="10"/><line x1="21" y1="6" x2="3" y2="6"/><line x1="21" y1="14" x2="3" y2="14"/><line x1="17" y1="18" x2="3" y2="18"/></svg>
</button>
<button type="button" class="align-btn" data-align="right" title="Right">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="21" y1="10" x2="7" y2="10"/><line x1="21" y1="6" x2="3" y2="6"/><line x1="21" y1="14" x2="3" y2="14"/><line x1="21" y1="18" x2="7" y2="18"/></svg>
</button>
</div>
</div>
</section>
<button type="submit" class="btn-build" id="build-btn">
<span id="build-label">Build Receipt</span>
</button>
</form>
</aside>
<main class="preview-pane">
<div class="preview-toolbar">
<span class="preview-title">Receipt Preview</span>
<div class="toolbar-actions">
<button class="btn-icon btn-print" id="print-btn" disabled title="Print via WebSerial/WebUSB">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="6 9 6 2 18 2 18 9"/><path d="M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2"/><rect x="6" y="14" width="12" height="8"/>
</svg>
Print
</button>
<button class="btn-icon" id="export-png-btn" disabled title="Export as PNG">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="3" y="3" width="18" height="18" rx="2" ry="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21 15 16 10 5 21"/>
</svg>
PNG
</button>
<button class="btn-icon" id="export-pdf-btn" disabled title="Export as PDF">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/>
</svg>
PDF
</button>
<button class="btn-icon" id="copy-code-btn" disabled title="Copy JS code">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/>
</svg>
Copy JS
</button>
<button class="btn-icon" id="download-btn" disabled title="Download .bin">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
<polyline points="7 10 12 15 17 10"/>
<line x1="12" y1="15" x2="12" y2="3"/>
</svg>
.bin
</button>
<button class="btn-icon" id="copy-hex-btn" disabled title="Copy hex bytes">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"/>
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/>
</svg>
Hex
</button>
</div>
</div>
<div class="output-tabs">
<button class="tab-btn active" data-tab="preview">Preview</button>
<button class="tab-btn" data-tab="code">JS Code</button>
<button class="tab-btn" data-tab="json">JSON Template</button>
<button class="tab-btn" data-tab="hex">Hex Dump</button>
</div>
<div class="tab-content active" id="tab-preview">
<div class="receipt-wrapper">
<div class="receipt-paper" id="receipt-paper">
<div class="empty-state" id="empty-state">
<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="8" y="14" width="32" height="24" rx="4" fill="#1e293b"/>
<rect x="8" y="14" width="32" height="8" rx="4" fill="#e94560" opacity="0.7"/>
<rect x="14" y="25" width="20" height="2" rx="1" fill="#334155"/>
<rect x="16" y="29" width="16" height="12" rx="2" fill="#f1f5f9" opacity="0.9"/>
</svg>
<p>Fill in the form and click<br/><strong>Build Receipt</strong></p>
</div>
<div class="receipt-content" id="receipt-content" style="display:none"></div>
</div>
</div>
</div>
<div class="tab-content" id="tab-code">
<div class="code-wrapper">
<pre class="code-output" id="code-output">// Build your receipt to see the JS code here</pre>
</div>
</div>
<div class="tab-content" id="tab-json">
<div class="code-wrapper">
<div class="json-toolbar">
<button class="btn-icon" id="copy-json-btn" disabled title="Copy JSON template">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"/>
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/>
</svg>
Copy JSON
</button>
<span class="json-hint">Use <code>render_template(json)</code> to render this template</span>
</div>
<pre class="code-output json-output" id="json-output">// Build your receipt to see the JSON template here</pre>
</div>
</div>
<div class="tab-content" id="tab-hex">
<div class="hex-wrapper">
<pre class="hex-dump" id="hex-dump"></pre>
</div>
</div>
<div class="stats-bar" id="stats-bar" style="display:none">
<span id="stat-bytes">0 bytes</span>
<span class="stat-sep">|</span>
<span id="stat-items">0 items</span>
<span class="stat-sep">|</span>
<span id="stat-taxes">0 taxes</span>
<span class="stat-sep">|</span>
<span id="stat-total">Total: 0 FCFA</span>
</div>
</main>
</div>
<div class="toast" id="toast"></div>
<script type="module" src="app.js"></script>
</body>
</html>