@finos/legend-application-marketplace
Version:
Legend Marketplace application core
122 lines • 6.94 kB
JavaScript
/**
* Copyright (c) 2026-present, Goldman Sachs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { MAX_PRODUCT_IMAGE_COUNT } from '../../stores/lakehouse/dataProducts/ProductCardState.js';
// ─── String labels ───────────────────────────────────────────────────────────
export var OrderProfileLabel;
(function (OrderProfileLabel) {
OrderProfileLabel["CHIP_LABEL"] = "Order Profile";
OrderProfileLabel["ALREADY_HAVE_ACCESS"] = "Already have access";
OrderProfileLabel["ADD_TO_CART"] = "Add to cart";
OrderProfileLabel["IN_CART"] = "In Cart";
OrderProfileLabel["ADDING"] = "Adding...";
OrderProfileLabel["SELECT_TERMINAL_TITLE"] = "Select Terminal";
OrderProfileLabel["SELECT_TERMINAL_DESCRIPTION"] = "All Add-Ons will be added automatically after the terminal is confirmed.";
OrderProfileLabel["CANCEL"] = "Cancel";
OrderProfileLabel["CLOSE"] = "Close";
OrderProfileLabel["OWNED_SUFFIX"] = "(Owned)";
OrderProfileLabel["IN_CART_SUFFIX"] = "(In Cart)";
OrderProfileLabel["MODEL_PREFIX"] = "Model: ";
OrderProfileLabel["PRICE_TOTAL_SEPARATOR"] = " \u00B7 Total: ";
OrderProfileLabel["VIEW_DETAILS"] = "View details";
})(OrderProfileLabel || (OrderProfileLabel = {}));
export var OrderProfileTableHeader;
(function (OrderProfileTableHeader) {
OrderProfileTableHeader["PRODUCT_NAME"] = "PRODUCT NAME";
OrderProfileTableHeader["PROVIDER"] = "PROVIDER";
OrderProfileTableHeader["CATEGORY"] = "CATEGORY";
OrderProfileTableHeader["COST_MONTHLY"] = "COST (Monthly)";
})(OrderProfileTableHeader || (OrderProfileTableHeader = {}));
// ─── Image URL ──────────────────────────────────────────────────────────────────
/**
* Returns a stable random product image URL for a given asset base URL.
* Intended to be called once inside a `useState` initialiser so the image
* does not change on re-renders.
*/
export const getRandomImageUrl = (assetUrl) => {
const randomValue = crypto.getRandomValues(new Uint32Array(1))[0] ?? 0;
const randomIndex = (randomValue % MAX_PRODUCT_IMAGE_COUNT) + 1;
return `${assetUrl}/images${randomIndex}.jpg`;
};
// ─── Price formatting ─────────────────────────────────────────────────────────
const USD_FORMATTER = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
minimumFractionDigits: 2,
maximumFractionDigits: 2,
});
/** Formats a price as a plain USD string, e.g. "$1,234.56". Used in detail tables. */
export const formatItemPrice = (price) => USD_FORMATTER.format(price);
/** Formats a price with a "/month" suffix for display on cards. */
export const formatCardPrice = (price) => `${USD_FORMATTER.format(price)}/month`;
// ─── Toast message formatters ────────────────────────────────────────────────
export const formatAddToCartSuccessMessage = (productName) => `Order profile ${productName} has been successfully added to cart.`;
export const formatAddToCartErrorMessage = (productName, errorMessage) => `Failed to add ${productName} to cart: ${errorMessage}`;
// ─── Item summary helpers ─────────────────────────────────────────────────────
export const getItemSummary = (items) => {
const terminalCount = items.filter((item) => item.isTerminal).length;
return { terminalCount, addOnCount: items.length - terminalCount };
};
export const formatProfileSummaryLine = (terminalCount, addOnCount) => {
const terminalLabel = terminalCount === 1 ? '1 Terminal' : `${terminalCount} Terminals`;
const addOnLabel = addOnCount === 1 ? '1 Add-On' : `${addOnCount} Add-Ons`;
return `${terminalLabel} · ${addOnLabel}`;
};
// ─── Multiselect price calculation ──────────────────────────────────────────
/**
* Calculates the total price for a multiselect order profile.
* Finds the highest-priced terminal and sums it with its associated add-ons.
* Returns `undefined` when there are no terminal items.
*/
export const calculateMultiselectTotalPrice = (items) => {
const terminals = items.filter((item) => item.isTerminal && !item.isOwned);
if (terminals.length === 0) {
return undefined;
}
const highestTerminal = terminals.reduce((max, curr) => curr.price > max.price ? curr : max);
const addOns = items.filter((item) => !item.isTerminal && !item.isOwned && item.model === highestTerminal.model);
const addOnsTotal = addOns.reduce((sum, item) => sum + item.price, 0);
return highestTerminal.price + addOnsTotal;
};
// ─── Grouping ─────────────────────────────────────────────────────────────────
/**
* Groups items so that each vendor-profile (terminal) is immediately followed
* by its associated add-ons (matched by item.model). Unmatched add-ons are
* appended at the end.
*/
export const groupOrderProfileItems = (items) => {
const result = [];
const terminals = items.filter((i) => i.isTerminal);
const addOns = items.filter((i) => !i.isTerminal);
const matchedAddonIds = new Set();
for (const terminal of terminals) {
result.push({ item: terminal, isSubItem: false });
if (terminal.model !== undefined && terminal.model !== null) {
for (const addon of addOns) {
if (addon.model === terminal.model && !matchedAddonIds.has(addon.id)) {
result.push({ item: addon, isSubItem: true });
matchedAddonIds.add(addon.id);
}
}
}
}
for (const addon of addOns) {
if (!matchedAddonIds.has(addon.id)) {
result.push({ item: addon, isSubItem: false });
}
}
return result;
};
//# sourceMappingURL=orderProfileUtils.js.map