Creating a custom sticker table with options

I’m having trouble with
I have where you can select custom shape, size, material, qty or enter a qty and a price is displayed on screen then you add all of those options to the cart (With The Displayed Price)

Working in
Dev Mode

What I’m trying to do
I just would love for someone to select all of the options then be able to see a price then all all of that to cart. I still need to add a lot more but this is where i’m stuck.

What I’ve tried so far
I’ve watched youtube videos, tried some AI to help with the problem. I’m not good at all, just looking for some help, before I hire someone.

Extra context
Anything else that might help - edge cases, screenshots, etc.

this is the backend code.

// ALTERNATIVE SOLUTION - Backend Code
// This approach uses a base product with $0 price and adds the custom price properly

import { Permissions, webMethod } from 'wix-web-module';
import wixEcomBackend from 'wix-ecom-backend';

export const addCustomStickerToCart = webMethod(
  Permissions.Anyone,
  async (data) => {
    try {
      const {
        productId,
        price,
        size,
        material,
        shape,
        qty
      } = data;

      // Ensure price is a number
      const customPrice = parseFloat(price);
      
      if (isNaN(customPrice) || customPrice < 0) {
        return { success: false, error: 'Invalid price' };
      }

      // Create line item with custom price
      const lineItem = {
        catalogReference: {
          catalogItemId: productId,
          appId: '1380b703-ce81-ff05-f115-39571d94dfcd',
          options: {
            options: {
              Size: size,
              Material: material,
              Shape: shape
            }
          }
        },
        quantity: qty,
        // This is key: set the price per unit
        price: {
          amount: customPrice.toString(),
          formattedAmount: `$${customPrice.toFixed(2)}`
        }
      };

      // Add to cart
      const result = await wixEcomBackend.currentCart.addToCurrentCart([lineItem]);
      
      return { 
        success: true, 
        cart: result.cart,
        lineItems: result.cart.lineItems 
      };
      
    } catch (error) {
      console.error('Error adding custom sticker to cart:', error);
      return { 
        success: false, 
        error: error.message,
        details: error.toString()
      };
    }
  }

this is the front end.

import { addStickerToCart } from 'backend/cart';
import wixLocation from 'wix-location';

// ================= PRICING MAP =================
const pricingMap = {
  Glossy: {
    "2": { 25: 49, 50: 60.74, 100: 72.69, 250: 118.42, 500: 166.14, 1000: 228.45, 2500: 389 },
    "3": { 25: 59, 50: 74, 100: 89, 250: 149, 500: 209, 1000: 289, 2500: 499 },
    "4": { 25: 69, 50: 89, 100: 109, 250: 189, 500: 269, 1000: 379, 2500: 649 },
    "5": { 25: 89, 50: 115, 100: 139, 250: 239, 500: 339, 1000: 479, 2500: 829 }
  },
  Matte: {
    "2": { 25: 52, 50: 64, 100: 76, 250: 122, 500: 172, 1000: 236, 2500: 399 },
    "3": { 25: 62, 50: 79, 100: 95, 250: 159, 500: 219, 1000: 299, 2500: 519 },
    "4": { 25: 72, 50: 94, 100: 114, 250: 199, 500: 279, 1000: 389, 2500: 669 },
    "5": { 25: 92, 50: 119, 100: 144, 250: 249, 500: 349, 1000: 489, 2500: 849 }
  }
};

// ================= PAGE READY =================
$w.onReady(() => {
  $w("#priceText").text = "$0.00";

  $w("#sizeRadio").onChange(updatePrice);
  $w("#materialRadio").onChange(updatePrice);
  $w("#shapeRadio").onChange(updatePrice);
  $w("#qtyRadio").onChange(updatePrice);
  $w("#qtyInput").onInput(updatePrice);

  $w("#addToCartBtn").onClick(addToCart);
});

// ================= PRICE UPDATE =================
function updatePrice() {
    console.log("updatePrice values:", {
    size: $w("#sizeRadio").value,
    material: $w("#materialRadio").value,
    qtyInput: $w("#qtyInput").value,
    qtyRadio: $w("#qtyRadio").value
     });
  const size = $w("#sizeRadio").value;
  const material = $w("#materialRadio").value;

  const qtyInputVal = $w("#qtyInput").value;
  const qtyRadioVal = $w("#qtyRadio").value;

  const qty = qtyInputVal
    ? parseInt(qtyInputVal, 10)
    : qtyRadioVal
    ? parseInt(qtyRadioVal, 10)
    : null;

  if (!size || !material || qty === null || isNaN(qty)) {
    $w("#priceText").text = "$0.00";
    return;
  }

  const price = calculateInterpolatedPrice(material, size, qty);

  if (price === null || isNaN(price) || price <= 0) {
    $w("#priceText").text = "N/A";
    return;
  }

  $w("#priceText").text = `$${price.toFixed(2)}`;
}

// ================= PRICE CALCULATION =================
function calculateInterpolatedPrice(material, size, qty) {
  const tiers = pricingMap?.[material]?.[size];
  if (!tiers) return null;

  const tierQtys = Object.keys(tiers).map(Number).sort((a, b) => a - b);

  if (tiers[qty]) return tiers[qty];

  if (qty < tierQtys[0]) {
    const minQty = tierQtys[0];
    const unitPrice = tiers[minQty] / minQty;
    return unitPrice * qty;
  }

  for (let i = 0; i < tierQtys.length - 1; i++) {
    const lowerQty = tierQtys[i];
    const upperQty = tierQtys[i + 1];

    if (qty > lowerQty && qty < upperQty) {
      const lowerPrice = tiers[lowerQty];
      const upperPrice = tiers[upperQty];
      const unitSlope = (upperPrice - lowerPrice) / (upperQty - lowerQty);
      return lowerPrice + (qty - lowerQty) * unitSlope;
    }
  }

  return null;
}

// ================= ADD TO CART =================
async function addToCart() {
  const size = $w("#sizeRadio").value;
  const material = $w("#materialRadio").value;
  const shape = $w("#shapeRadio").value;

  const qtyInputVal = $w("#qtyInput").value;
  const qtyRadioVal = $w("#qtyRadio").value;

  const qty = qtyInputVal
    ? parseInt(qtyInputVal, 10)
    : qtyRadioVal
    ? parseInt(qtyRadioVal, 10)
    : null;

  if (!size || !material || !shape || !qty || isNaN(qty)) {
    $w("#priceText").text = "Please complete all selections";
    return;
  }

  const price = calculateInterpolatedPrice(material, size, qty);

 if (price === null || isNaN(price) || price <= 0) {
    $w("#priceText").text = "Price error";
    return;
  }

  try {
    await addStickerToCart({
      productId: "5b2d3cd9-a625-9966-b64a-d126853c2223", // base product
      price,
      size,
      material,
      shape,
      qty
    });

    wixLocation.to("/cart");
  } catch (err) {
    console.error("Add to cart failed:", err);
    $w("#priceText").text = "Cart error";
  }
}

here is what this looks like then here is a picture when i add it to cart.

Check out this great tutorial by @thewixwiz. It is pretty easy to follow along:

1 Like