I made this for a friend who wanted to recreate some receipts that he had misplaced.
A Pen by Jeffrey Carpenter on CodePen.
I made this for a friend who wanted to recreate some receipts that he had misplaced.
A Pen by Jeffrey Carpenter on CodePen.
<!--svg class="is-hidden" aria-hidden="true" width="0" height="0"> | |
<symbol id="heart" viewBox="0 0 20 20"> | |
<path d="M17.19,4.155c-1.672-1.534-4.383-1.534-6.055,0L10,5.197L8.864,4.155c-1.672-1.534-4.382-1.534-6.054,0 c-1.881,1.727-1.881,4.52,0,6.246L10,17l7.19-6.599C19.07,8.675,19.07,5.881,17.19,4.155z"></path> | |
</symbol> | |
</svg> | |
<div> | |
<h2>I <svg class="made-with-love" viewBox="0 0 20 20"> | |
<use xlink:href="#heart"></use> | |
</svg>Kami</h2> | |
</div--> | |
<div class='centered'> | |
<h2>Gas Receipt Generator</h2> | |
<form> | |
<div id='station-details' class='column'> | |
<label for='station'>Station Name</label> | |
<input type='text' name='station' id='station' placeholder='Quick Stop' /> | |
<label for='address'>Street Address</label> | |
<input type='text' name='address' id='address' placeholder='58 Leonard Ave.' /> | |
<label for='city'>City</label> | |
<input type='text' name='city' id='city' placeholder='Leonardo' /> | |
<label for='state'>State</label> | |
<input type='text' name='state' id='state' placeholder='NJ' /> | |
<label for='city'>Zipcode</label> | |
<input type='zipcode' name='zipcode' id='zipcode' placeholder='07737' /> | |
<label for='city'>Phone Number</label> | |
<input type='tel' name='phone' id='phone' placeholder='7322919635' /> | |
</div> | |
<div id='purchase-details' class='column'> | |
<label for='type'>Product Type</label> | |
<input type='text' name='type' id='type' placeholder='Regular' /> | |
<label for='quantity'>Quantity</label> | |
<input type='text' name='quantity' id='quantity' placeholder='21.000' /> | |
<label for='ppg'>Price Per Galon</label> | |
<input type='text' name='ppg' id='ppg' placeholder='2.540' /> | |
<label for='paid'>Cash Paid</label> | |
<input type='text' name='paid' id='paid' placeholder='60.00' /> | |
<label for='date'>Date</label> | |
<input type='date' name='date' id='date' /> | |
<label for='time'>Time</label> | |
<input type='time' name='time' id='time' /> | |
<div class='controls'> | |
<input type='button' id='update' value='update' /> | |
</div> | |
</div> | |
<div id='generated-details' class='column'> | |
<label for='pump'>Pump Number</label> | |
<input type='text' name='pump' id='pump' /> | |
<label for='tx'>ST-TX</label> | |
<input type='text' name='tx' id='tx' /> | |
<label for='uuid'>UUID</label> | |
<input type='text' name='uuid' id='uuid' /> | |
<label for='terminal'>Terminal</label> | |
<input type='text' name='terminal' id='terminal' /> | |
<label for='operator'>Operator</label> | |
<input type='text' name='operator' id='operator' /> | |
<div class='controls'> | |
<input type='button' id='generate' value='regenerate' /> | |
</div> | |
</div> | |
<div id='preview' class='column'> | |
<div id='receipt' class='receipt'> | |
<div class='paper'> | |
<h1 id='receipt-station'>Quick Stop</h1> | |
<h1 id='receipt-address'>58 Leonard Ave.</h1> | |
<h1 id='receipt-city'>Leonardo</h1> | |
<h1> | |
<span id='receipt-state'>NJ</span> | |
<span id='receipt-zipcode'>07737</span></h1> | |
<section class='info'> | |
<div> | |
<span>ST-TX: <span id='receipt-tx'>72938256</span></span> | |
<span id='receipt-phone' class='right'>7322919635</span> | |
</div> | |
<div> | |
<span id='receipt-date'>2018-09-03</span> | |
<span id='receipt-uuid'>EA509659:5816428</span> | |
<span id='receipt-time'>09:22</span> | |
</div> | |
<div> | |
<span>TERMINAL: <span id='receipt-terminal'>755816428</span></span> | |
<span>OPER: <span id='receipt-operator'>A</span></span> | |
<span> </span> | |
</div> | |
</section> | |
<section class='items'> | |
<div class='fuel'>Fuel</div> | |
<div class='quantity'>(G)</div> | |
<div class='ppg'>($/G)</div> | |
<div class='price'>($)</div> | |
<div class='pump'>Pump <span id='receipt-pump'>6</span></div> | |
<div id='receipt-type' class='fuel'>Regular</div> | |
<div id='receipt-quantity' class='quantity'>20.510</div> | |
<div id='receipt-ppg' class='ppg'>2.540</div> | |
<div id='receipt-price' class='price'>52.10*</div> | |
</section> | |
<section class='total'> | |
<div>Total Owed</div> | |
<div id='receipt-total' class='right'>52.10</div> | |
</section> | |
<section class='change'> | |
<div class='label'>Cash Tendered</div> | |
<div id='receipt-paid' class='amount'>60.00</div> | |
<div class='label'>Change Due</div> | |
<div id='receipt-change' class='amount'>7.90</div> | |
</section> | |
<section class='important'> | |
<div>Retain This Copy For Your Records</div> | |
</section> | |
</div> | |
</div> | |
<div class='controls'> | |
<input type='button' id='download' value='download' /> | |
</div> | |
</div> | |
</form> | |
</div> |
const randomIntegerInRange = (min, max) => | |
Math.floor(Math.random() * (max - min + 1)) + min; | |
const randomLetter = (from = 'A', to = 'Z') => | |
String.fromCharCode(randomIntegerInRange(from.charCodeAt(0), to.charCodeAt(0))); | |
const randomUUID = () => | |
`${randomLetter()}${randomLetter()}${randomIntegerInRange(100000, 999999)}:${randomIntegerInRange(100000, 999999)}` | |
const generate = () => { | |
document.getElementById('pump').value = randomIntegerInRange(1, 6); | |
document.getElementById('tx').value = randomIntegerInRange(100000,98765432); | |
document.getElementById('uuid').value = randomUUID(); | |
document.getElementById('terminal').value = randomIntegerInRange(1000000, 987654321); | |
document.getElementById('operator').value = randomLetter('A', 'H'); | |
} | |
const update = () => { | |
const data = {}; | |
data.station = document.getElementById('station').value || 'Quick Stop'; | |
data.address = document.getElementById('address').value || '58 Leonard Ave.'; | |
data.city = document.getElementById('city').value || 'Leonardo'; | |
data.state = document.getElementById('state').value || 'NJ'; | |
data.tx = document.getElementById('tx').value || randomIntegerInRange(100000,98765432); | |
data.zipcode = document.getElementById('zipcode').value || '07737'; | |
data.phone = document.getElementById('phone').value.replace(/\D/g,'') || '7322919635'; | |
data.date = document.getElementById('date').value || moment().format('YYYY-MM-DD'); | |
data.time = document.getElementById('time').value || moment().format('HH:mm:ss'); | |
data.uuid = document.getElementById('uuid').value || randomUUID(); | |
data.terminal = document.getElementById('terminal').value || randomIntegerInRange(1000000, 987654321); | |
data.operator = document.getElementById('operator').value || randomLetter('A', 'H'); | |
data.pump = document.getElementById('pump').value || randomIntegerInRange(1,6); | |
data.type = document.getElementById('type').value || 'Regular'; | |
data.quantity = Number(document.getElementById('quantity').value) || 20.510; | |
data.ppg = Number(document.getElementById('ppg').value) || 2.540; | |
data.price = data.quantity * data.ppg; | |
data.total = data.price; | |
data.paid = Number(document.getElementById('paid').value) || 60.00; | |
data.change = data.paid - data.total; | |
return data; | |
} | |
const populateReceipt = (data) => { | |
document.getElementById('receipt-station').innerHTML = data.station; | |
document.getElementById('receipt-address').innerHTML = data.address; | |
document.getElementById('receipt-city').innerHTML = data.city; | |
document.getElementById('receipt-state').innerHTML = data.state; | |
document.getElementById('receipt-zipcode').innerHTML = data.zipcode; | |
document.getElementById('receipt-tx').innerHTML = data.tx; | |
document.getElementById('receipt-phone').innerHTML = data.phone; | |
document.getElementById('receipt-date').innerHTML = data.date; | |
document.getElementById('receipt-time').innerHTML = data.time.substr(0, data.time.lastIndexOf(':')); | |
document.getElementById('receipt-uuid').innerHTML = data.uuid; | |
document.getElementById('receipt-terminal').innerHTML = data.terminal; | |
document.getElementById('receipt-operator').innerHTML = data.operator; | |
document.getElementById('receipt-pump').innerHTML = data.pump; | |
document.getElementById('receipt-type').innerHTML = data.type; | |
document.getElementById('receipt-quantity').innerHTML = data.quantity.toFixed(3); | |
document.getElementById('receipt-ppg').innerHTML = data.ppg.toFixed(3); | |
document.getElementById('receipt-price').innerHTML = data.price.toFixed(2); | |
document.getElementById('receipt-total').innerHTML = data.total.toFixed(2); | |
document.getElementById('receipt-paid').innerHTML = data.paid.toFixed(2); | |
document.getElementById('receipt-change').innerHTML = data.change.toFixed(2); | |
} | |
const createReceipt = (e) => { | |
e.preventDefault(); | |
const data = update(); | |
populateReceipt(data); | |
}; | |
const download = (e) => { | |
e.preventDefault(); | |
domtoimage.toBlob(document.getElementById('receipt')) | |
.then(function (blob) { | |
saveAs(blob, 'receipt.jpg'); | |
}); | |
} | |
document.getElementById('date').value = moment().format('YYYY-MM-DD'); | |
document.getElementById('time').value = moment().format('HH:mm:ss'); | |
//createReceipt(); | |
document.getElementById('generate').onclick = generate; | |
document.getElementById('download').onclick = download; | |
document.getElementById('update').onclick = createReceipt; | |
generate(); |
<script src="https://cdnjs.cloudflare.com/ajax/libs/dom-to-image/2.6.0/dom-to-image.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.8/FileSaver.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script> |
/* | |
.made-with-love { | |
width: 80px; | |
height: 80px; | |
fill: #fff; | |
transform: scale(.9); | |
animation: love .5s infinite linear alternate-reverse; | |
position: relative; | |
top: 12px; | |
left: -15px; | |
} | |
@keyframes love{ | |
to { | |
transform: scale(1.2) | |
} | |
} | |
*/ | |
h2 { | |
font-size: 72px; | |
color: #fafafa; | |
font-family: VT323; | |
text-align: center; | |
text-shadow: -4px -4px 0 #212121, | |
4px -4px 0 #212121, | |
-4px 4px 0 #212121, | |
4px 4px 0 #212121, | |
4px 8px 0 #212121, | |
-4px 8px 0 #212121, | |
0px 8px 0 #212121, | |
4px 3px 0 #212121; | |
} | |
* { | |
box-sizing: border-box; | |
} | |
.centered { | |
min-width: 50%; | |
} | |
body { | |
display: flex; | |
height: 100vh; | |
margin: 0; | |
align-items: center; | |
color: rgba(0, 0, 0, 0.62); | |
background: #fc3153; | |
flex-direction: column; | |
font-family: 'Helvetica', 'Arial'; | |
} | |
form { | |
display: flex; | |
min-width: 800px; | |
//height: 80%; | |
justify-content: space-evenly; | |
} | |
label { | |
color: #fff; | |
//font-size: 1.2em; | |
margin-top: .5em; | |
} | |
input { | |
line-height: 1.1; | |
color: #212121; | |
} | |
::placeholder { | |
color: #000; | |
opacity: 0.3; | |
} | |
.column { | |
display: flex; | |
flex-direction: column; | |
} | |
.controls { | |
display: flex; | |
flex-direction: column; | |
flex-grow: 1; | |
justify-content: end; | |
padding-top: 26.4px; | |
input[type='button'] { | |
padding: 0.25em .5em; | |
border: 1px solid #212121; | |
box-shadow: 6px 6px #212121; | |
} | |
} | |
.receipt { | |
& { | |
width: 227px; | |
box-shadow: 0 .2em 1em .2em rgba(0, 0, 0, 0.2); | |
border: 1px dotted white; | |
border-width: 1px 0; | |
font: 13px Arial Narrow, monospace; | |
} | |
.paper { | |
padding: 1em 1em 1.5em; | |
background: white; | |
} | |
h1 { | |
font-size: 100%; | |
margin: 0; | |
font-weight: 400; | |
text-transform: uppercase; | |
} | |
h1, | |
.event { | |
text-align: center; | |
line-height: 1; | |
} | |
section { | |
display: flex; | |
flex-wrap: wrap; | |
margin: 1.5em 0 0; | |
justify-content: space-between; | |
line-height: 1; | |
} | |
div | |
{ | |
margin: 0; | |
} | |
.center { | |
text-align: center; | |
} | |
.right { | |
text-align: right; | |
} | |
.info div { | |
width: 100%; | |
display: flex; | |
justify-content: space-between; | |
} | |
.items { | |
justify-content: flex-start; | |
} | |
.fuel { | |
width: 40%; | |
} | |
.quantity, | |
.ppg, | |
.price { | |
width: 20%; | |
text-align: right; | |
} | |
.pump { | |
width: 100%; | |
} | |
.total { | |
margin: 0; | |
margin-top: 1em; | |
} | |
.change { | |
margin: 0; | |
margin-top: 1em; | |
.label { | |
width: 80%; | |
text-align: right; | |
} | |
.amount { | |
width: 20%; | |
text-align: right; | |
} | |
} | |
.important:before { | |
content: '-- IMPORTANT --'; | |
display: block; | |
width: 100%; | |
text-align: center; | |
} | |
.important { | |
justify-content: center; | |
} | |
} |
<link href="https://fonts.googleapis.com/css?family=VT323" rel="stylesheet" /> | |
<link href="https://fonts.googleapis.com/css?family=Pirata+One" rel="stylesheet" /> |