277 lines
9.4 KiB
Plaintext
Raw Normal View History

2026-02-13 14:59:30 -07:00
<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>