277 lines
9.4 KiB
Plaintext
277 lines
9.4 KiB
Plaintext
|
|
<template>
|
||
|
|
<div class="page">
|
||
|
|
<div class="navbar">
|
||
|
|
<div class="navbar-bg"></div>
|
||
|
|
<div class="navbar-inner sliding">
|
||
|
|
<div class="left">
|
||
|
|
<a href="#" class="link back">
|
||
|
|
<i class="icon icon-back"></i>
|
||
|
|
<span class="if-not-md">Back</span>
|
||
|
|
</a>
|
||
|
|
</div>
|
||
|
|
<div class="title">Print and Fax</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
<div class="page-content">
|
||
|
|
<div class="margin">
|
||
|
|
<p class="segmented segmented-strong">
|
||
|
|
${modes.map((m) => $h`
|
||
|
|
<button class="button ${fnMode===m.m ? 'button-active' : '' }" @click=${()=>setMode(m.m)}>${m.s}</button>
|
||
|
|
`)}
|
||
|
|
<span class="segmented-highlight"></span>
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
<div class="grid grid-cols-2">
|
||
|
|
|
||
|
|
<div class="margin">
|
||
|
|
<div id="copiesFormContainer">
|
||
|
|
<input type="text" class="padding margin-bottom" maxlength="4" placeholder="# of pages" name="copies" id="copiesInput" @input="${updateTotal}" />
|
||
|
|
<osk-numberpad target="copiesInput" />
|
||
|
|
<div class="list">
|
||
|
|
<ul>
|
||
|
|
<li-input type="text" placeholder="Job ID, Fax #, etc." name="notes" id="notesInput" />
|
||
|
|
</ul>
|
||
|
|
</div>
|
||
|
|
<div class="button button-large button-fill margin-top" @click="${addToSale}">
|
||
|
|
Add to Sale
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div>
|
||
|
|
<input type="text" class="padding margin-bottom" value="${global.apis.i18n.moneyString(currentTotal)}" placeholder="${global.apis.i18n.moneyString(0.0)}" id="totalPriceInput" readonly='readonly' />
|
||
|
|
<div class="block-title">Pricing</div>
|
||
|
|
<div class="list list-outline inset list-dividers simple-list no-margin-top">
|
||
|
|
<ul>
|
||
|
|
${pricingToDisplayPriceChart().map((p) => $h`
|
||
|
|
<li>
|
||
|
|
<div>${p.num}</div>
|
||
|
|
<div>${p.each}</div></li>
|
||
|
|
`)}
|
||
|
|
</ul>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</template>
|
||
|
|
<style>
|
||
|
|
#copiesFormContainer {
|
||
|
|
width: 100%;
|
||
|
|
max-width: 30em;
|
||
|
|
margin: 0 auto;
|
||
|
|
text-align: center;
|
||
|
|
}
|
||
|
|
|
||
|
|
#copiesInput, #totalPriceInput {
|
||
|
|
width: 100%;
|
||
|
|
font-size: 25px;
|
||
|
|
text-align: center;
|
||
|
|
border-radius: 5px;
|
||
|
|
margin-right: auto;
|
||
|
|
margin-left: auto;
|
||
|
|
}
|
||
|
|
|
||
|
|
#copiesInput {
|
||
|
|
background: var(--f7-input-item-bg-color);
|
||
|
|
}
|
||
|
|
|
||
|
|
</style>
|
||
|
|
<script>
|
||
|
|
export default (props, { $f7, $on, $update }) => {
|
||
|
|
const plugin = require(global.apis.getPluginFolder("app.postalpoint.printscan") + "/plugin.js");
|
||
|
|
var modes = [
|
||
|
|
{
|
||
|
|
m: "print_bw", // ID
|
||
|
|
s: "Print (Black)", // human name
|
||
|
|
t: "print", // tax type
|
||
|
|
r: "Printing, BW", // receipt item title
|
||
|
|
p: [] // price chart
|
||
|
|
},
|
||
|
|
{
|
||
|
|
m: "print_color",
|
||
|
|
s: "Print (Color)",
|
||
|
|
t: "print",
|
||
|
|
r: "Printing, Color",
|
||
|
|
p: []
|
||
|
|
},
|
||
|
|
{
|
||
|
|
m: "copy_bw", // ID
|
||
|
|
s: "Copy (Black)", // human name
|
||
|
|
t: "print", // tax type
|
||
|
|
r: "Copies, BW", // receipt item title
|
||
|
|
p: [] // price chart
|
||
|
|
},
|
||
|
|
{
|
||
|
|
m: "copy_color",
|
||
|
|
s: "Copy (Color)",
|
||
|
|
t: "print",
|
||
|
|
r: "Copies, Color",
|
||
|
|
p: []
|
||
|
|
},
|
||
|
|
{
|
||
|
|
m: "scan",
|
||
|
|
s: "Scan",
|
||
|
|
t: "scanfax",
|
||
|
|
r: "Scanning",
|
||
|
|
p: []
|
||
|
|
},
|
||
|
|
{
|
||
|
|
m: "fax",
|
||
|
|
s: "Fax",
|
||
|
|
t: "scanfax",
|
||
|
|
r: "Faxing",
|
||
|
|
p: []
|
||
|
|
}
|
||
|
|
];
|
||
|
|
var fnMode = modes[0].m;
|
||
|
|
var priceChart = modes[0].p;
|
||
|
|
var currentTotal = 0;
|
||
|
|
|
||
|
|
async function loadPricing() {
|
||
|
|
for (var i = 0; i < modes.length; i++) {
|
||
|
|
modes[i].p = plugin.parsePricingString(await plugin.getPricing(modes[i].m));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function getPricingForMode(mode) {
|
||
|
|
return getMode(mode).p;
|
||
|
|
}
|
||
|
|
|
||
|
|
function getMode(mode = fnMode) {
|
||
|
|
for (var i = 0; i < modes.length; i++) {
|
||
|
|
if (modes[i].m == mode) {
|
||
|
|
return modes[i];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
;
|
||
|
|
}
|
||
|
|
|
||
|
|
function pricingToDisplayPriceChart() {
|
||
|
|
var out = [];
|
||
|
|
var len = priceChart.length;
|
||
|
|
for (var i = 0; i < len; i++) {
|
||
|
|
const th = priceChart[i];
|
||
|
|
var r;
|
||
|
|
if (th.num == "MIN") {
|
||
|
|
r = {
|
||
|
|
num: `First ${th.min > 1 ? th.min + ' pages' : 'page'}`,
|
||
|
|
each: global.apis.i18n.moneyString(th.each)
|
||
|
|
};
|
||
|
|
} else {
|
||
|
|
r = {
|
||
|
|
num: th.num,
|
||
|
|
each: global.apis.i18n.moneyString(th.each) + " per page"
|
||
|
|
};
|
||
|
|
if (i < len - 1) {
|
||
|
|
r.num = `${th.num} to ${priceChart[i + 1].num}`;
|
||
|
|
} else {
|
||
|
|
r.num = `${th.num} and up`;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
out.push(r);
|
||
|
|
}
|
||
|
|
return out;
|
||
|
|
}
|
||
|
|
|
||
|
|
async function setMode(m) {
|
||
|
|
fnMode = m;
|
||
|
|
priceChart = getPricingForMode(m);
|
||
|
|
updateTotal();
|
||
|
|
$update();
|
||
|
|
}
|
||
|
|
|
||
|
|
function getPriceTotal(count, chart = priceChart) {
|
||
|
|
if (!count) {
|
||
|
|
return 0.0;
|
||
|
|
}
|
||
|
|
var total = 0.0;
|
||
|
|
if (chart[0].num == "MIN") {
|
||
|
|
if (count <= chart[0].min) {
|
||
|
|
return chart[0].each;
|
||
|
|
} else {
|
||
|
|
total += chart[0].each;
|
||
|
|
var priceEach = 0.0;
|
||
|
|
for (var i = 1; i < chart.length; i++) {
|
||
|
|
if (count >= chart[i].num) {
|
||
|
|
priceEach = chart[i].each;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
total += priceEach * (count - chart[0].min);
|
||
|
|
return total;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
var priceEach = chart[0].each;
|
||
|
|
for (var i = 0; i < chart.length; i++) {
|
||
|
|
if (count >= chart[i].num) {
|
||
|
|
priceEach = chart[i].each;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return priceEach * count;
|
||
|
|
}
|
||
|
|
|
||
|
|
function updateTotal() {
|
||
|
|
var copies = Math.floor((document.getElementById("copiesInput").value * 1) ?? 0);
|
||
|
|
if (copies > 9999) {
|
||
|
|
copies = 9999;
|
||
|
|
document.getElementById("copiesInput").value = "9999";
|
||
|
|
}
|
||
|
|
currentTotal = getPriceTotal(copies);
|
||
|
|
$update();
|
||
|
|
}
|
||
|
|
|
||
|
|
async function addToSale() {
|
||
|
|
var copies = document.getElementById("copiesInput").value;
|
||
|
|
if (!copies || copies.replace(/\D/g, '') == "") {
|
||
|
|
global.apis.alert("Enter a number of pages for the job.", "Whoops!");
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
copies = Math.floor(copies * 1);
|
||
|
|
|
||
|
|
var mode = getMode();
|
||
|
|
var taxRate = await global.apis.storage.getDB(`${plugin.id}.${mode.t}_taxrate`, 0) * 1.0;
|
||
|
|
var merchCategory = await global.apis.storage.getDB(`${plugin.id}.merchcategory`, "Print/Scan/Fax");
|
||
|
|
|
||
|
|
var pt = getPriceTotal(copies);
|
||
|
|
var jobInfo = document.getElementById("notesInput").value ?? null;
|
||
|
|
var receiptItem = new global.apis.pos.ReceiptItem(
|
||
|
|
`printscan_${mode.m}_${global.apis.util.uuid.short()}`, // SKU/ID
|
||
|
|
mode.r, // label
|
||
|
|
jobInfo ?? null,
|
||
|
|
global.apis.i18n.moneyToFixed(pt / (copies * 1)) * 1.0,
|
||
|
|
copies * 1,
|
||
|
|
0,
|
||
|
|
taxRate / 100.0
|
||
|
|
);
|
||
|
|
receiptItem.merch = true;
|
||
|
|
if (merchCategory && merchCategory != "") {
|
||
|
|
receiptItem.category = merchCategory;
|
||
|
|
}
|
||
|
|
global.apis.pos.addReceiptItem(receiptItem);
|
||
|
|
|
||
|
|
global.apis.f7.notification.create({
|
||
|
|
icon: '<i class="icon fa-solid fa-check"></i>',
|
||
|
|
title: 'Job Added to Transaction',
|
||
|
|
titleRightText: '',
|
||
|
|
closeTimeout: 3000
|
||
|
|
}).open();
|
||
|
|
document.getElementById("copiesInput").value = "";
|
||
|
|
updateTotal();
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
$on('pageInit', () => {
|
||
|
|
// do something on page init
|
||
|
|
loadPricing().then(() => {
|
||
|
|
setMode(fnMode);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
$on('pageAfterOut', () => {
|
||
|
|
// page has left the view
|
||
|
|
});
|
||
|
|
|
||
|
|
// component function must return render function
|
||
|
|
return $render;
|
||
|
|
}
|
||
|
|
</script>
|