5180 fichiers 38.5 Mo 0 téléchargements 560 vues mis à jour il y a 8 heures ui
nitro-v36-with-renderer-v36 / src / components / catalog / views / page / layout / CatalogLayoutRecolorableFurnitureView.tsx
CatalogLayoutRecolorableFurnitureView.tsx 6.1 Ko Télécharger le fichier
import { CSSProperties, FC, useEffect, useMemo } from 'react';
import {
    formatRecolor,
    IPurchasableOffer,
    isRecolorableClass,
    localizeWithFallback,
    NO_RECOLOR,
    recolorablePalette,
    recolorHex,
    recolorPageColors
} from '../../../../../api';
import { AutoGrid, Column, Text } from '../../../../../common';
import { BaseButton } from '../../../../../common/BaseButton';
import { NativeTextTree } from '../../../../../common/native-text/NativeTextTree';
import {
    pickRecolorableColor,
    recolorableObjectData,
    useCatalogData,
    useCatalogUiState,
    useInventoryFurni,
    useRecolorableColorStore
} from '../../../../../hooks';
import { CatalogGridOfferView } from '../common/CatalogGridOfferView';
import { CatalogPreviewControls } from '../widgets/CatalogPreviewControls';
import { CatalogPurchaseWidgetView } from '../widgets/CatalogPurchaseWidgetView';
import { CatalogViewProductWidgetView } from '../widgets/CatalogViewProductWidgetView';
import { CatalogLayoutProps } from './CatalogLayout.types';

/**
 * AIR's layout_recolorable_furniture (Builders Club): the preview (150 px), the furni grid, then the palette of the
 * picked furni inline under it (`catalog.recolorable.palette`, 27 x 22 swatches) and the builder widget. A colour goes
 * to every furni on the page; the preview and the furni on the cursor take it and the placement sends it as "R,G,B".
 */
export const CatalogLayoutRecolorableFurnitureView: FC<CatalogLayoutProps> = (props) => {
    const { page = null } = props;
    const { currentOffer = null, roomPreviewer = null } = useCatalogData();
    const { setCurrentOffer = null, setPurchaseOptions = null } = useCatalogUiState();
    const { isVisible: inventoryVisible = false } = useInventoryFurni();
    const colors = useRecolorableColorStore((state) => state.colors);
    const setColor = useRecolorableColorStore((state) => state.setColor);

    const offers = page?.offers ?? [];
    const onPage = !!currentOffer && offers.includes(currentOffer);
    const className = currentOffer?.product?.furnitureData?.className ?? null;
    const recolorable = isRecolorableClass(className);
    const palette = useMemo(() => (recolorable ? recolorablePalette(className) : []), [recolorable, className]);
    const color = recolorable ? pickRecolorableColor(colors, className, palette) : NO_RECOLOR;

    const selectOffer = (offer: IPurchasableOffer) => {
        if (!offer || !setCurrentOffer) return;

        offer.activate();
        setCurrentOffer(offer);
    };

    const pickColor = (rgb: number) => {
        const classNames = offers.map((offer: IPurchasableOffer) => offer?.product?.furnitureData?.className).filter(Boolean);

        for (const [offerClass, offerColor] of recolorPageColors(classNames, rgb)) setColor(offerClass, offerColor);
    };

    // The first furni is shown when the page opens, as in Habbo.
    useEffect(() => {
        if (onPage || !offers.length || !setCurrentOffer) return;

        offers[0].activate();
        setCurrentOffer(offers[0]);
    }, [offers, onPage, setCurrentOffer]);

    useEffect(() => {
        if (!currentOffer || !setPurchaseOptions || color === NO_RECOLOR) return;

        setPurchaseOptions((previous) => ({ ...previous, extraData: formatRecolor(color), previewStuffData: recolorableObjectData(color) }));
    }, [currentOffer, color, setPurchaseOptions]);

    return (
        <NativeTextTree>
            <Column className="octane-catalog-builders-blocks octane-catalog-recolorable" gap={1} overflow="hidden">
                <div className="octane-catalog-builders-blocks-preview relative flex items-center justify-center overflow-hidden">
                    {currentOffer && (
                        <>
                            <CatalogPreviewControls productType={currentOffer.product.productType} roomPreviewer={roomPreviewer} />
                            <CatalogViewProductWidgetView height={150} />
                            <Text bold className="octane-catalog-builders-blocks-name" truncate>
                                {currentOffer.localizationName}
                            </Text>
                        </>
                    )}
                </div>
                <div className="octane-catalog-builders-blocks-shapes">
                    <AutoGrid columnCount={7} columnMinHeight={50} columnMinWidth={45}>
                        {offers.map((offer) => (
                            <CatalogGridOfferView
                                key={offer.offerId}
                                itemActive={offer === currentOffer}
                                offer={offer}
                                selectOffer={() => selectOffer(offer)}
                                inventoryVisible={inventoryVisible}
                            />
                        ))}
                    </AutoGrid>
                </div>
                <div className="octane-catalog-recolorable-palette">
                    <span className="octane-catalog-recolorable-palette-caption">{localizeWithFallback('catalog.recolorable.palette', 'Palette')}</span>
                    <div
                        aria-label={localizeWithFallback('catalog.recolorable.palette', 'Palette')}
                        className="octane-catalog-recolorable-palette-box"
                        role="radiogroup"
                    >
                        {palette.map((swatch) => (
                            <BaseButton
                                key={swatch}
                                aria-checked={swatch === color}
                                aria-label={recolorHex(swatch)}
                                className={`octane-catalog-recolorable-swatch${swatch === color ? ' is-chosen' : ''}`}
                                role="radio"
                                style={{ '--swatch-color': recolorHex(swatch) } as CSSProperties}
                                onClick={() => pickColor(swatch)}
                            />
                        ))}
                    </div>
                </div>
                <div className="octane-catalog-builders-blocks-actions">{currentOffer && <CatalogPurchaseWidgetView />}</div>
            </Column>
        </NativeTextTree>
    );
};
15Sujets
1Dépôts
20Membres
4En ligne
Profile
Inscrit
Dernière visite
Messages
0
Votes positifs
0
Votes négatifs
0

Nous utilisons des cookies pour assurer le bon fonctionnement du site et améliorer votre expérience. en savoir plus

Autoriser