Description
- adding price quote calculator
- view demo – password: abc
- buy me a coffee

#1. Install Code
If you need to tweak code, send all code to AI (ChatGPT, Claude or this AI chat bot for Squarespace). You can also use this free calculator tool to create a calculator with more layout/styles.
#1.1. You can edit Page where you want to place Calculator > Add a Code Block

#1.2. Add this code into Code Block
<!-- 09.26c14v1(v3) Price Quote Calculator -->
<div class="tp-calc" data-tp-quotecalc></div>
<script>
window.PriceQuoteCalcConfig = {
text: {
title: "",
productsLabel: "Number of Products",
productsHint: "Slide to select the number of products you're interested in.",
priceLabel: "Product Price",
priceHint: "Enter the price for each product.",
serviceLabel: "Service Type",
serviceHint: "Select the type of service you need.",
durationLabel: "Service Duration (hours)",
durationHint: "Slide to select the duration of the service in hours.",
totalHeading: "Total Quote",
totalHint: "Your estimated total.",
servicePriceLabel: "Service Price",
servicePriceHint: "Cost of services.",
productPriceLabel: "Product Price",
productPriceHint: "Cost of products.",
ctaHeading: "Ready to Get Started?",
ctaHint: "Get your project moving today with our competitive pricing. Reach out for a detailed consultation.",
ctaButton: "Request a Quote",
ctaHref: "/contact-us"
},
tags: {
title: "h2",
productsLabel: "h3",
priceLabel: "h3",
serviceLabel: "h3",
durationLabel: "h3",
totalHeading: "h3",
servicePriceLabel: "h4",
productPriceLabel: "h4",
ctaHeading: "h2"
},
colors: {
title: "",
label: "",
smallText: "",
cardBg: "#4a9de8",
cardHeading: "#ffffff",
cardValue: "#ffffff",
cardMuted: "rgba(255,255,255,0.72)"
},
slider: {
trackFill: "#4a9de8",
trackEmpty: "rgba(17,17,17,0.05)",
thumbBg: "#ffffff",
thumbBorder: "rgba(17,17,17,0.1)",
trackHeight: "6px",
thumbSize: "24px"
},
checkbox: {
border: "rgba(17,17,17,0.25)",
checkedBg: "#e74c3c",
size: "26px",
radius: "6px"
},
layout: {
inputBorder: "1px solid rgba(17,17,17,0.2)"
},
button: {
text: "#ffffff",
bg: "#111111",
border: "#111111",
hoverText: "#ffffff",
hoverBg: "#000000",
hoverBorder: "#000000"
},
ranges: {
products: { min: 1, max: 100, step: 1, value: 9 },
duration: { min: 1, max: 24, step: 1, value: 2 }
},
// Price per product, entered by the visitor
productPrice: { value: 100 },
// rate = hourly rate used for the service cost (duration x rate)
services: [
{ label: "Standard Service", rate: 200 },
{ label: "Premium Service", rate: 300 },
{ label: "Deluxe Service", rate: 400 }
],
formula: {
currencySymbol: "$",
moneyDecimals: 0,
// totalFn(productsCost, serviceCost, formula) -> total quote
totalFn: null
}
};
</script>
<script>
(function () {
var CFG = window.PriceQuoteCalcConfig;
var CSS =
".tp-calc,.tp-calc *{box-sizing:border-box}" +
".tp-calc{--tp-card-bg:#4a9de8;--tp-track-fill:#4a9de8;--tp-track-empty:rgba(17,17,17,0.05);--tp-thumb-bg:#fff;--tp-thumb-border:rgba(17,17,17,0.1);--tp-track-h:6px;--tp-thumb-size:24px;--tp-input-border:1px solid rgba(17,17,17,0.2);--tp-card-radius:22px;color:inherit}" +
".tp-calc__wrap{max-width:1180px;margin:40px auto;padding:0 24px;display:grid;grid-template-columns:1.1fr 0.9fr;gap:48px;align-items:start}" +
".tp-calc__h{margin:0}" +
".tp-calc__title{margin:0 0 32px}" +
".tp-calc__field{padding:14px 0}" +
".tp-calc__labelRow{display:flex;align-items:center;justify-content:space-between;gap:16px;margin-bottom:18px}" +
".tp-calc__sm{margin:14px 0 0}" +
".tp-calc__pill{min-width:var(--tp-pill-min-width,64px);background:#fff;border:var(--tp-input-border);border-radius:12px;padding:12px 16px;display:inline-flex;align-items:center;justify-content:center;font-size:17px;color:#111}" +
".tp-calc__num{width:auto;min-width:1ch;border:0;background:transparent;padding:0;margin:0;color:inherit;text-align:center}" +
".tp-calc__unit{margin-left:6px}" +
".tp-calc__unit--tight{margin-left:2px}" +
".tp-calc__range{width:100%;-webkit-appearance:none;appearance:none;height:var(--tp-track-h);border-radius:999px;margin:4px 0 0;cursor:pointer;background:linear-gradient(90deg,var(--tp-track-fill) 0%,var(--tp-track-fill) var(--tp-fill,0%),var(--tp-track-empty) var(--tp-fill,0%),var(--tp-track-empty) 100%)}" +
".tp-calc__range::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:var(--tp-thumb-size);height:var(--tp-thumb-size);border-radius:50%;background:var(--tp-thumb-bg);border:1px solid var(--tp-thumb-border);box-shadow:0 2px 6px rgba(0,0,0,.15);cursor:pointer}" +
".tp-calc__range::-moz-range-thumb{width:var(--tp-thumb-size);height:var(--tp-thumb-size);border-radius:50%;background:var(--tp-thumb-bg);border:1px solid var(--tp-thumb-border);box-shadow:0 2px 6px rgba(0,0,0,.15);cursor:pointer}" +
".tp-calc__minmax{display:flex;justify-content:space-between;margin-top:12px}" +
".tp-calc__money{display:flex;align-items:center;gap:2px;width:100%;border:var(--tp-input-border);border-radius:12px;padding:16px 18px;font-size:18px;line-height:1.2;background:#fff;color:#111;margin-top:4px}" +
".tp-calc__moneyPrefix{flex:0 0 auto}" +
".tp-calc__moneyInput{flex:1 1 auto;min-width:0;width:100%;border:0;background:transparent;padding:0;margin:0;font:inherit;color:inherit}" +
".tp-calc__moneyInput:focus{outline:none}" +
".tp-calc__select{position:relative;margin-top:4px}" +
".tp-calc__selectTrigger{display:flex;align-items:center;justify-content:space-between;gap:12px;width:100%;border:var(--tp-input-border);border-radius:12px;padding:16px 18px;font-size:18px;line-height:1.2;background:#fff;color:#111;cursor:pointer}" +
".tp-calc__selectValue{flex:1 1 auto}" +
".tp-calc__chevron{flex:0 0 auto;width:0;height:0;border-left:6px solid transparent;border-right:6px solid transparent;border-top:7px solid rgba(17,17,17,0.55);pointer-events:none;transition:transform .15s}" +
".tp-calc__select[data-open='true'] .tp-calc__chevron{transform:rotate(180deg)}" +
".tp-calc__options{list-style:none;margin:6px 0 0;padding:6px;position:absolute;left:0;right:0;top:100%;z-index:20;background:#fff;border:var(--tp-input-border);border-radius:12px;box-shadow:0 10px 30px rgba(0,0,0,.12);display:none}" +
".tp-calc__select[data-open='true'] .tp-calc__options{display:block}" +
".tp-calc__option{padding:12px 14px;border-radius:8px;font-size:17px;line-height:1.2;cursor:pointer}" +
".tp-calc__option:hover{background:rgba(17,17,17,0.05)}" +
".tp-calc__option[aria-selected='true']{background:rgba(17,17,17,0.06)}" +
".tp-calc__card{width:100%;background:var(--tp-card-bg);border-radius:var(--tp-card-radius);padding:44px}" +
".tp-calc__card .tp-calc__h{margin:0 0 4px}" +
".tp-calc__total{font-size:60px;line-height:1;margin:10px 0 6px}" +
".tp-calc__etaRow{display:flex;justify-content:space-between;align-items:flex-start;gap:16px}" +
".tp-calc__etaVal{font-size:22px;white-space:nowrap}" +
".tp-calc__spacer{height:26px}" +
".tp-calc__spacer--lg{height:40px}" +
".tp-calc a.tp-calc__btn{display:block !important;width:100% !important;text-align:center !important;border-radius:10px !important;margin-top:20px}" +
"@media (max-width:980px){.tp-calc__wrap{grid-template-columns:1fr;gap:28px}.tp-calc__card{padding:34px}}" +
"@media (max-width:520px){.tp-calc__card{padding:28px}.tp-calc__total{font-size:52px}}";
function decl(prop, val) { return val ? prop + ":" + val + " !important;" : ""; }
function buttonCSS() {
var B = CFG.button;
var base = decl("color", B.text) + decl("background-color", B.bg) + decl("border-color", B.border);
var hover = decl("color", B.hoverText) + decl("background-color", B.hoverBg) + decl("border-color", B.hoverBorder);
var out = "";
if (base) out += ".tp-calc a.tp-calc__btn{" + base + "}";
if (hover) out += ".tp-calc a.tp-calc__btn:hover{" + hover + "}";
return out;
}
function injectCSS() {
if (window.__quoteCalcStyled) return;
window.__quoteCalcStyled = true;
var st = document.createElement("style");
st.type = "text/css";
st.textContent = CSS + buttonCSS();
document.head.appendChild(st);
}
function el(tag, cls, txt) {
var e = document.createElement(tag);
if (cls) e.className = cls;
if (txt != null) e.textContent = txt;
return e;
}
function heading(tag, txt, color) {
var e = el(tag, "tp-calc__h", txt);
if (color) e.style.color = color;
return e;
}
function smallP(txt, color) {
var e = el("p", "sqsrte-small tp-calc__sm", txt);
if (color) e.style.color = color;
return e;
}
function stepDecimals(step) {
var s = String(step);
var i = s.indexOf(".");
return i < 0 ? 0 : (s.length - i - 1);
}
function fmtNumber(v, decimals) {
return (+v).toLocaleString("en-US", { minimumFractionDigits: 0, maximumFractionDigits: decimals });
}
function formatMoney(n) {
var F = CFG.formula;
var d = Math.max(0, F.moneyDecimals | 0);
return F.currencySymbol + (+n).toLocaleString("en-US", { minimumFractionDigits: d, maximumFractionDigits: d });
}
function clampNum(v, min, max, decimals) {
v = +v;
if (!isFinite(v)) v = min;
v = Math.min(max, Math.max(min, v));
var f = Math.pow(10, decimals || 0);
return Math.round(v * f) / f;
}
var measureSpan;
function autosize(input) {
if (!measureSpan) {
measureSpan = document.createElement("span");
measureSpan.style.cssText = "position:absolute;visibility:hidden;white-space:pre;left:-9999px;top:0";
document.body.appendChild(measureSpan);
}
var cs = window.getComputedStyle(input);
measureSpan.style.fontFamily = cs.fontFamily;
measureSpan.style.fontSize = cs.fontSize;
measureSpan.style.fontWeight = cs.fontWeight;
measureSpan.style.fontStyle = cs.fontStyle;
measureSpan.style.letterSpacing = cs.letterSpacing;
measureSpan.textContent = input.value || "0";
input.style.width = (measureSpan.offsetWidth + 2) + "px";
}
function numField(o) {
var decimals = stepDecimals(o.r.step);
var node = el("div", "tp-calc__field");
var row = el("div", "tp-calc__labelRow");
row.appendChild(heading(o.tag, o.label, CFG.colors.label));
var pill = el("div", "tp-calc__pill");
var input = el("input", "tp-calc__num");
input.type = "text";
input.setAttribute("inputmode", decimals ? "decimal" : "numeric");
input.setAttribute("aria-label", o.label);
pill.appendChild(input);
if (o.suffix) {
pill.appendChild(el("span", "tp-calc__unit" + (o.suffixTight ? " tp-calc__unit--tight" : ""), o.suffix));
}
row.appendChild(pill);
node.appendChild(row);
var range = el("input", "tp-calc__range");
range.type = "range";
range.min = o.r.min; range.max = o.r.max; range.step = o.r.step; range.value = o.r.value;
range.setAttribute("aria-label", o.label);
node.appendChild(range);
var mm = el("div", "tp-calc__minmax");
var s1 = el("span", "sqsrte-small", labelText(o.r.min));
var s2 = el("span", "sqsrte-small", labelText(o.r.max));
if (CFG.colors.smallText) { s1.style.color = CFG.colors.smallText; s2.style.color = CFG.colors.smallText; }
mm.appendChild(s1); mm.appendChild(s2);
node.appendChild(mm);
if (o.hint) node.appendChild(smallP(o.hint, CFG.colors.smallText));
function labelText(v) {
var s = (o.prefix || "") + fmtNumber(v, decimals);
if (o.suffix) s += (o.suffixTight ? "" : " ") + o.suffix;
return s;
}
function disp(v) { return (o.prefix || "") + fmtNumber(v, decimals); }
function get() {
var cleaned = (input.value || "").replace(/[^0-9.]/g, "");
var v = cleaned === "" ? o.r.min : parseFloat(cleaned);
return clampNum(v, o.r.min, o.r.max, decimals);
}
function fill() {
var v = +range.value, min = +range.min, max = +range.max;
range.style.setProperty("--tp-fill", ((v - min) / (max - min)) * 100 + "%");
}
function sync(v) { range.value = v; fill(); autosize(input); }
var cb = function () {};
input.addEventListener("input", function () { autosize(input); cb(); });
input.addEventListener("change", function () { input.value = disp(get()); autosize(input); cb(); });
range.addEventListener("input", function () { input.value = disp(+range.value); autosize(input); cb(); });
input.value = disp(o.r.value);
fill();
return { node: node, get: get, sync: sync, onChange: function (f) { cb = f; } };
}
function moneyField(o) {
var node = el("div", "tp-calc__field");
node.appendChild(heading(o.tag, o.label, CFG.colors.label));
var decimals = Math.max(0, CFG.formula.moneyDecimals | 0);
var box = el("div", "tp-calc__money");
box.appendChild(el("span", "tp-calc__moneyPrefix", CFG.formula.currencySymbol));
var input = el("input", "tp-calc__moneyInput");
input.type = "text";
input.setAttribute("inputmode", decimals ? "decimal" : "numeric");
input.setAttribute("aria-label", o.label);
box.appendChild(input);
node.appendChild(box);
if (o.hint) node.appendChild(smallP(o.hint, CFG.colors.smallText));
function fmt(v) { return fmtNumber(v, decimals); }
function get() {
var cleaned = (input.value || "").replace(/[^0-9.]/g, "");
var v = cleaned === "" ? 0 : parseFloat(cleaned);
if (!isFinite(v) || v < 0) v = 0;
return v;
}
var cb = function () {};
input.addEventListener("input", function () { cb(); });
input.addEventListener("change", function () { input.value = fmt(get()); cb(); });
input.value = fmt(o.value);
return { node: node, get: get, onChange: function (f) { cb = f; } };
}
function selectField(o) {
var node = el("div", "tp-calc__field");
node.appendChild(heading(o.tag, o.label, CFG.colors.label));
var sel = el("div", "tp-calc__select");
sel.setAttribute("data-open", "false");
var trigger = el("div", "tp-calc__selectTrigger");
trigger.setAttribute("role", "button");
trigger.setAttribute("tabindex", "0");
trigger.setAttribute("aria-haspopup", "listbox");
trigger.setAttribute("aria-expanded", "false");
trigger.setAttribute("aria-label", o.label);
var valueEl = el("span", "tp-calc__selectValue", o.options[0].label);
trigger.appendChild(valueEl);
trigger.appendChild(el("span", "tp-calc__chevron"));
sel.appendChild(trigger);
var list = el("ul", "tp-calc__options");
list.setAttribute("role", "listbox");
var lis = [];
for (var i = 0; i < o.options.length; i++) {
var li = el("li", "tp-calc__option", o.options[i].label);
li.setAttribute("role", "option");
li.setAttribute("data-i", String(i));
li.setAttribute("aria-selected", i === 0 ? "true" : "false");
list.appendChild(li);
lis.push(li);
}
sel.appendChild(list);
node.appendChild(sel);
if (o.hint) node.appendChild(smallP(o.hint, CFG.colors.smallText));
var idx = 0;
var cb = function () {};
function open() { sel.setAttribute("data-open", "true"); trigger.setAttribute("aria-expanded", "true"); }
function close() { sel.setAttribute("data-open", "false"); trigger.setAttribute("aria-expanded", "false"); }
function toggle() { if (sel.getAttribute("data-open") === "true") close(); else open(); }
function choose(i) {
idx = i;
valueEl.textContent = o.options[i].label;
for (var k = 0; k < lis.length; k++) lis[k].setAttribute("aria-selected", k === i ? "true" : "false");
close();
cb();
}
trigger.addEventListener("click", toggle);
trigger.addEventListener("keydown", function (e) {
var k = e.keyCode || 0;
if (e.key === "Enter" || e.key === " " || k === 13 || k === 32) { e.preventDefault(); toggle(); }
else if (e.key === "Escape" || k === 27) close();
});
for (var j = 0; j < lis.length; j++) {
(function (n) { lis[n].addEventListener("click", function () { choose(n); }); })(j);
}
document.addEventListener("click", function (e) { if (!sel.contains(e.target)) close(); });
return { node: node, get: function () { return o.options[idx]; }, onChange: function (f) { cb = f; } };
}
function summaryRow(tag, label, hint) {
var row = el("div", "tp-calc__etaRow");
var lft = el("div");
lft.appendChild(heading(tag, label, CFG.colors.cardHeading));
if (hint) lft.appendChild(smallP(hint, CFG.colors.cardMuted));
var val = el("div", "tp-calc__etaVal");
if (CFG.colors.cardValue) val.style.color = CFG.colors.cardValue;
row.appendChild(lft); row.appendChild(val);
return { row: row, val: val };
}
function mount(root) {
if (!root || root.dataset.tpDone === "1") return;
root.dataset.tpDone = "1";
var T = CFG.text, G = CFG.tags, K = CFG.colors, S = CFG.slider, R = CFG.ranges, F = CFG.formula;
root.style.setProperty("--tp-card-bg", K.cardBg);
root.style.setProperty("--tp-track-fill", S.trackFill);
root.style.setProperty("--tp-track-empty", S.trackEmpty);
root.style.setProperty("--tp-thumb-bg", S.thumbBg);
root.style.setProperty("--tp-thumb-border", S.thumbBorder);
root.style.setProperty("--tp-track-h", S.trackHeight);
root.style.setProperty("--tp-thumb-size", S.thumbSize);
root.style.setProperty("--tp-input-border", CFG.layout.inputBorder);
var wrap = el("div", "tp-calc__wrap");
var left = el("div", "tp-calc__left");
var right = el("div", "tp-calc__right");
if (T.title) {
var title = heading(G.title, T.title, K.title);
title.classList.add("tp-calc__title");
left.appendChild(title);
}
var productsField = numField({ label: T.productsLabel, tag: G.productsLabel, hint: T.productsHint, r: R.products });
left.appendChild(productsField.node);
var priceField = moneyField({ label: T.priceLabel, tag: G.priceLabel, hint: T.priceHint, value: CFG.productPrice.value });
left.appendChild(priceField.node);
var serviceField = selectField({ label: T.serviceLabel, tag: G.serviceLabel, hint: T.serviceHint, options: CFG.services });
left.appendChild(serviceField.node);
var durationField = numField({ label: T.durationLabel, tag: G.durationLabel, hint: T.durationHint, suffix: "hrs", r: R.duration });
left.appendChild(durationField.node);
var card = el("div", "tp-calc__card");
card.appendChild(heading(G.totalHeading, T.totalHeading, K.cardHeading));
var total = el("div", "tp-calc__total");
if (K.cardValue) total.style.color = K.cardValue;
card.appendChild(total);
card.appendChild(smallP(T.totalHint, K.cardMuted));
card.appendChild(el("div", "tp-calc__spacer tp-calc__spacer--lg"));
var serviceRow = summaryRow(G.servicePriceLabel, T.servicePriceLabel, T.servicePriceHint);
card.appendChild(serviceRow.row);
card.appendChild(el("div", "tp-calc__spacer"));
var productRow = summaryRow(G.productPriceLabel, T.productPriceLabel, T.productPriceHint);
card.appendChild(productRow.row);
card.appendChild(el("div", "tp-calc__spacer tp-calc__spacer--lg"));
card.appendChild(heading(G.ctaHeading, T.ctaHeading, K.cardHeading));
card.appendChild(smallP(T.ctaHint, K.cardMuted));
var btn = el("a", "btn btn--border theme-btn--primary-inverse sqs-button-element--primary tp-calc__btn", T.ctaButton);
btn.setAttribute("href", T.ctaHref);
btn.setAttribute("rel", "noopener");
card.appendChild(btn);
right.appendChild(card);
wrap.appendChild(left); wrap.appendChild(right);
root.appendChild(wrap);
function recalc() {
var products = productsField.get();
productsField.sync(products);
var duration = durationField.get();
durationField.sync(duration);
var productPrice = priceField.get();
var service = serviceField.get();
var serviceRate = +service.rate;
var productsCost = products * productPrice;
var serviceCost = duration * serviceRate;
var totalVal = (typeof F.totalFn === "function")
? F.totalFn(productsCost, serviceCost, F)
: productsCost + serviceCost;
total.textContent = formatMoney(totalVal);
serviceRow.val.textContent = formatMoney(serviceCost);
productRow.val.textContent = formatMoney(productsCost);
}
productsField.onChange(recalc);
priceField.onChange(recalc);
serviceField.onChange(recalc);
durationField.onChange(recalc);
recalc();
}
function init() {
var nodes = document.querySelectorAll("[data-tp-quotecalc]");
for (var i = 0; i < nodes.length; i++) mount(nodes[i]);
}
function ready(fn) {
if (document.readyState !== "loading") fn();
else document.addEventListener("DOMContentLoaded", fn);
}
injectCSS();
ready(init);
if (!window.__quoteCalcBound) {
window.__quoteCalcBound = true;
window.addEventListener("mercury:load", init);
}
})();
</script>

#2. Customize
#2.1. To change text + button url, change line 05 – 25
text: {
title: "",
productsLabel: "Number of Products",
productsHint: "Slide to select the number of products you're interested in.",
priceLabel: "Product Price",
priceHint: "Enter the price for each product.",
serviceLabel: "Service Type",
serviceHint: "Select the type of service you need.",
durationLabel: "Service Duration (hours)",
durationHint: "Slide to select the duration of the service in hours.",
totalHeading: "Total Quote",
totalHint: "Your estimated total.",
servicePriceLabel: "Service Price",
servicePriceHint: "Cost of services.",
productPriceLabel: "Product Price",
productPriceHint: "Cost of products.",
ctaHeading: "Ready to Get Started?",
ctaHint: "Get your project moving today with our competitive pricing. Reach out for a detailed consultation.",
ctaButton: "Request a Quote",
ctaHref: "/contact-us"
},
#2.2. To change style of text, button, slider…change line 26 – 70
tags: {
title: "h2",
productsLabel: "h3",
priceLabel: "h3",
serviceLabel: "h3",
durationLabel: "h3",
totalHeading: "h3",
servicePriceLabel: "h4",
productPriceLabel: "h4",
ctaHeading: "h2"
},
colors: {
title: "",
label: "",
smallText: "",
cardBg: "#4a9de8",
cardHeading: "#ffffff",
cardValue: "#ffffff",
cardMuted: "rgba(255,255,255,0.72)"
},
slider: {
trackFill: "#4a9de8",
trackEmpty: "rgba(17,17,17,0.05)",
thumbBg: "#ffffff",
thumbBorder: "rgba(17,17,17,0.1)",
trackHeight: "6px",
thumbSize: "24px"
},
checkbox: {
border: "rgba(17,17,17,0.25)",
checkedBg: "#e74c3c",
size: "26px",
radius: "6px"
},
layout: {
inputBorder: "1px solid rgba(17,17,17,0.2)"
},
button: {
text: "#ffffff",
bg: "#111111",
border: "#111111",
hoverText: "#ffffff",
hoverBg: "#000000",
hoverBorder: "#000000"
},
#2.3. To change value of Number of Products & Services Duration, change line 71 – 74
ranges: {
products: { min: 1, max: 100, step: 1, value: 9 },
duration: { min: 1, max: 24, step: 1, value: 2 }
},
#2.4. To change value of Services Type, change line 78 – 82
services: [
{ label: "Standard Service", rate: 200 },
{ label: "Premium Service", rate: 300 },
{ label: "Deluxe Service", rate: 400 }
],
#2.5. To change formula, change line 83 – 88
formula: {
currencySymbol: "$",
moneyDecimals: 0,
// totalFn(productsCost, serviceCost, formula) -> total quote
totalFn: null
}
an example
formula: {
currencySymbol: "$",
moneyDecimals: 0,
// totalFn(productsCost, serviceCost, formula) -> total quote
totalFn: function (productsCost, serviceCost, formula) {
return productsCost + serviceCost + 50;
}
}
You can ask AI write custom formula for you