/** * Copyright (c) 2025-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, useCallback, useState } from 'react'; import { Box, Button, Card, CardActionArea, CardActions, CardContent, CardMedia, Chip, CircularProgress, Typography, } from '@mui/material'; import type { TerminalResult } from '@finos/legend-server-marketplace'; import { CheckCircleIcon, ShoppingCartIcon } from '@finos/legend-art'; import { useLegendMarketplaceBaseStore } from '../../application/providers/LegendMarketplaceFrameworkProvider.js'; import { observer } from 'mobx-react-lite'; import { flowResult } from 'mobx'; import { toastManager } from '../Toast/CartToast.js'; import { RecommendedAddOnsModal } from '../AddToCart/RecommendedAddOnsModal.js'; import { assertErrorThrown } from '@finos/legend-shared'; import { MAX_PRODUCT_IMAGE_COUNT } from '../../stores/lakehouse/dataProducts/ProductCardState.js'; import { LegendMarketplaceTelemetryHelper, TERMINAL_SEARCH_LOCATION, } from '../../__lib__/LegendMarketplaceTelemetryHelper.js'; export const LegendMarketplaceTerminalCard = observer( (props: { terminalResult: TerminalResult }): JSX.Element => { const { terminalResult } = props; const [isAddingToCart, setIsAddingToCart] = useState(false); const [showRecommendationsModal, setShowRecommendationsModal] = useState(false); const [recommendedItems, setRecommendedItems] = useState( [], ); const [modalMessage, setModalMessage] = useState(''); const [modalTotalCount, setModalTotalCount] = useState< number | null | undefined >(undefined); const legendMarketplaceBaseStore = useLegendMarketplaceBaseStore(); const applicationStore = legendMarketplaceBaseStore.applicationStore; const assetUrl = applicationStore.config.assetsBaseUrl; const telemetryService = applicationStore.telemetryService; const [imageUrl] = useState(() => { const randomIndex = Math.floor(Math.random() * MAX_PRODUCT_IMAGE_COUNT) + 1; return `${assetUrl}/images${randomIndex}.jpg`; }); const handleAddToCart = async () => { setIsAddingToCart(true); try { const result = await flowResult( legendMarketplaceBaseStore.cartStore.addToCartWithAPI( legendMarketplaceBaseStore.cartStore.providerToCartRequest( terminalResult, ), ), ); if (result.success) { LegendMarketplaceTelemetryHelper.logEvent_AddTerminalAddonToCart( telemetryService, terminalResult.id, terminalResult.productName, terminalResult.providerName, terminalResult.terminalItemType, TERMINAL_SEARCH_LOCATION.MAIN_CATALOG, legendMarketplaceBaseStore.cartStore.cartUser !== applicationStore.identityService.currentUser, ); } if (result.recommendations && result.recommendations.length > 0) { setRecommendedItems(result.recommendations); setModalMessage(result.message); setModalTotalCount(result.totalCount); setShowRecommendationsModal(true); LegendMarketplaceTelemetryHelper.logEvent_OpenAddonsPopup( telemetryService, terminalResult.productName, terminalResult.providerName, result.totalCount ?? null, ); } } catch (error) { assertErrorThrown(error); toastManager.error( `Failed to add ${terminalResult.productName} to cart: ${error.message}`, ); } finally { setIsAddingToCart(false); } }; const isInCart = legendMarketplaceBaseStore.cartStore.isItemInCart( terminalResult.id, ); const handleViewCart = () => { legendMarketplaceBaseStore.cartStore.setOpen(true); }; const handleTerminalSelected = useCallback( ( _selectedTerminal: TerminalResult, recommendations: TerminalResult[], responseMessage: string, totalCount?: number | null, ) => { setRecommendedItems(recommendations); setModalMessage(responseMessage); setModalTotalCount(totalCount); setShowRecommendationsModal(true); LegendMarketplaceTelemetryHelper.logEvent_OpenAddonsPopup( telemetryService, _selectedTerminal.productName, _selectedTerminal.providerName, totalCount ?? null, ); }, [telemetryService], ); const handleCardClick = useCallback(() => { LegendMarketplaceTelemetryHelper.logEvent_ClickTerminalAddonCard( telemetryService, terminalResult.id, terminalResult.productName, terminalResult.providerName, terminalResult.terminalItemType, TERMINAL_SEARCH_LOCATION.MAIN_CATALOG, ); }, [telemetryService, terminalResult]); return ( {terminalResult.category && ( )} {terminalResult.providerName} {terminalResult.productName} {terminalResult.isOwned ? ( Already have access   ) : ( <> {typeof terminalResult.price === 'number' && ( )} )} ); }, );