/** * 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 { type JSX, useState } from 'react'; import { Box, Button, Card, CardActionArea, CardActions, CardContent, CardMedia, Chip, CircularProgress, IconButton, Typography, } from '@mui/material'; import { CheckCircleIcon, InfoCircleIcon, ShoppingCartIcon, } from '@finos/legend-art'; import type { TraderProfile, TraderProfileItem, } from '@finos/legend-server-marketplace'; import { useLegendMarketplaceBaseStore } from '../../application/providers/LegendMarketplaceFrameworkProvider.js'; import { observer } from 'mobx-react-lite'; import { flowResult } from 'mobx'; import { toastManager } from '../Toast/CartToast.js'; import { assertErrorThrown } from '@finos/legend-shared'; import { OrderProfileDetailModal } from './OrderProfileDetailModal.js'; import { OrderProfileMultiselectModal } from './OrderProfileMultiselectModal.js'; import { calculateMultiselectTotalPrice, formatAddToCartErrorMessage, formatAddToCartSuccessMessage, formatCardPrice, formatProfileSummaryLine, getItemSummary, getRandomImageUrl, OrderProfileLabel, } from './orderProfileUtils.js'; import { LegendMarketplaceTelemetryHelper } from '../../__lib__/LegendMarketplaceTelemetryHelper.js'; export const LegendMarketplaceOrderProfileCard = observer( (props: { traderProfile: TraderProfile }): JSX.Element => { const { traderProfile } = props; const [isAddingToCart, setIsAddingToCart] = useState(false); const [showDetailModal, setShowDetailModal] = useState(false); const [showMultiselectModal, setShowMultiselectModal] = useState(false); const legendMarketplaceBaseStore = useLegendMarketplaceBaseStore(); const { cartStore, applicationStore } = legendMarketplaceBaseStore; const assetUrl = applicationStore.config.assetsBaseUrl; const isTargetUser = cartStore.cartUser !== applicationStore.identityService.currentUser; const [imageUrl] = useState(() => getRandomImageUrl(assetUrl)); const items = traderProfile.items; const { terminalCount, addOnCount } = getItemSummary(items); const multiselectTotalPrice = traderProfile.multiselect ? calculateMultiselectTotalPrice(items) : undefined; const displayPrice = traderProfile.multiselect ? (multiselectTotalPrice ?? traderProfile.price) : traderProfile.price; const isInCart = cartStore.isOrderProfileInCart(traderProfile); const executeCartAction = async ( action: () => Promise, ): Promise => { setIsAddingToCart(true); try { await action(); toastManager.success( formatAddToCartSuccessMessage(traderProfile.productName), ); } catch (error) { assertErrorThrown(error); toastManager.error( formatAddToCartErrorMessage(traderProfile.productName, error.message), ); } finally { setIsAddingToCart(false); } }; const handleAddToCart = (): void => { if (traderProfile.isOwned) { return; } if (traderProfile.multiselect) { setShowMultiselectModal(true); return; } executeCartAction(async () => { await flowResult(cartStore.addOrderProfileItemsToCart(items, true)); LegendMarketplaceTelemetryHelper.logEvent_AddOrderProfileToCart( applicationStore.telemetryService, traderProfile.productName, false, isTargetUser, ); }).catch(applicationStore.alertUnhandledError); }; const getCartButtonContent = (): JSX.Element => { if (isAddingToCart) { return ( <> {OrderProfileLabel.ADDING}   ); } if (isInCart) { return ( <> {OrderProfileLabel.IN_CART}   ); } return ( <> {OrderProfileLabel.ADD_TO_CART}   ); }; const handleMultiselectConfirm = ( selectedTerminals: TraderProfileItem[], ): void => { setShowMultiselectModal(false); const selectedModel = selectedTerminals[0]?.model ?? null; const addOnItems = items.filter( (item) => !item.isTerminal && !item.isOwned && (selectedModel === null || item.model === selectedModel), ); executeCartAction(async () => { await flowResult( cartStore.addOrderProfileItemsToCart( [...selectedTerminals, ...addOnItems], true, ), ); LegendMarketplaceTelemetryHelper.logEvent_AddOrderProfileToCart( applicationStore.telemetryService, traderProfile.productName, true, isTargetUser, ); }).catch(applicationStore.alertUnhandledError); }; return ( <> {formatProfileSummaryLine(terminalCount, addOnCount)} {traderProfile.productName.toUpperCase()} { e.stopPropagation(); setShowDetailModal(true); LegendMarketplaceTelemetryHelper.logEvent_ViewOrderProfileDetails( applicationStore.telemetryService, traderProfile.productName, ); }} className="legend-marketplace-order-profile-card__info-button" aria-label="View profile details" > {traderProfile.isOwned ? ( {OrderProfileLabel.ALREADY_HAVE_ACCESS}   ) : ( <> )} setShowDetailModal(false)} {...(multiselectTotalPrice === undefined ? {} : { multiselectTotalPrice })} /> setShowMultiselectModal(false)} onConfirm={handleMultiselectConfirm} /> ); }, );