import React, { type FunctionComponent, Suspense, useEffect, useMemo, useState, } from 'react' import type { IProductComparison } from '.' import { useFadeEffect, useProductComparison } from '../../hooks' import SlideOver, { SlideOverHeader, type SlideOverProps } from '../SlideOver' import { Table, TableBody, TableCell, TableHead, TableRow, } from '../../molecules/Table' import ToggleField from '../../molecules/ToggleField' import Badge from '../../atoms/Badge' import Button from '../../atoms/Button' import Icon from '../../atoms/Icon' import Price, { type PriceFormatter } from '../../atoms/Price' import Select from '../../atoms/Select' import Dropdown, { DropdownButton, DropdownItem, DropdownMenu, } from '../../molecules/Dropdown' import ProductCard, { ProductCardContent, ProductCardImage, } from '../../molecules/ProductCard' const SPECIFICATION = 'SPECIFICATION' export interface SortOptions { label: string value: string onChange: (productComparison: IProductComparison[]) => IProductComparison[] } export type ImageComponentType = FunctionComponent<{ src: string alt: string width?: number height?: number }> export interface ProductComparisonSidebarProps extends Omit { /** * Defines the title of the SlideOver. */ title: string /** * Defines the sort-related labels. */ sortLabels: { label?: string options?: { productByName?: string productByPrice?: string } } /** * Defines the filter label. */ filterLabel: string /** * Defines the toggle field label. */ toggleFieldLabel: string /** * Defines the preference label. */ preferencesLabel: string /** * Defines the label from add to cart button. */ cartButtonLabel: string /** * Defines the label for the price including taxes. */ priceWithTaxLabel: string /** * Formatter function that transforms the raw price value and render the result. */ priceFormatter: PriceFormatter /** * Custom labels to introducing about products. */ technicalInformation?: { title: string description: string } /** * Custom function to sort the products. */ sortOptions?: SortOptions[] /** * Function to select the product that will be added to the cart. */ handleProductToBuy: (productId: string) => void /** * Event to handle the click on the add to cart button. */ setPendingEvent: (event: React.MouseEvent) => void } const ImageComponent: ImageComponentType = ({ src, alt, ...otherProps }) => ( {alt} ) function useProductSpecifications( products: IProductComparison[], productSorted: IProductComparison[], showOnlyDifferences: boolean ) { return useMemo(() => { const firstProduct = products[0] const allSpecs = getAllSpecifications(firstProduct) const diffSpecs = getDifferences(firstProduct, productSorted) return { specsToShow: showOnlyDifferences ? diffSpecs : allSpecs, allSpecs, diffSpecs, } }, [products, productSorted, showOnlyDifferences]) } function ProductComparisonSidebar({ title, sortLabels: { label: sortLabel = '', options: sortOptionsLabels = {} } = {}, filterLabel, preferencesLabel, toggleFieldLabel, cartButtonLabel, priceWithTaxLabel, technicalInformation, size = 'partial', direction = 'rightSide', priceFormatter, overlayProps, sortOptions, handleProductToBuy, setPendingEvent, ...otherProps }: ProductComparisonSidebarProps) { const { fade } = useFadeEffect() const { isOpen, setIsOpen, products } = useProductComparison() const [showTechnicalInfo, setShowTechnicalInfo] = useState(true) const [selectedFilter, setSelectedFilter] = useState('productByName') const [showOnlyDifferences, setShowOnlyDifferences] = useState(false) const handleClickAddCart = ( event: React.MouseEvent, product: IProductComparison ) => { event.preventDefault() handleProductToBuy(product.id) setPendingEvent(event) } const productSorted = useMemo( () => sortOptions ?.find((option) => option.value === selectedFilter) ?.onChange(products) ?? products, [selectedFilter, products] ) const { specsToShow } = useProductSpecifications( products, productSorted, showOnlyDifferences ) useEffect(() => { if (isOpen) { // Prevent scrolling when the drawer is open document.body.style.overflow = 'hidden' return } // Restore scrolling when the drawer is closed document.body.style.overflow = '' }, [isOpen]) const options = useMemo( () => sortOptions?.reduce( (acc: Record, option) => { acc[option.value] = option.label return acc }, {} as Record ) || {}, [sortOptions] ) function toggleInfo() { setShowTechnicalInfo(!showTechnicalInfo) } return ( setIsOpen(false)}>

{title}

{products.length}

{sortLabel}