5180 fichiers 38.5 Mo 0 téléchargements 270 vues mis à jour il y a 5 heures ui
nitro-v36-with-renderer-v36 / src / components / collectibles / CollectiblesShopTabView.tsx
CollectiblesShopTabView.tsx 8.3 Ko Télécharger le fichier
import { CollectibleShopOfferData } from '@octane/renderer';
import { FC, useMemo, useState } from 'react';
import { localizeWithFallback } from '../../api';
import { BaseButton } from '../../common/BaseButton';
import { ToggleButton } from '../../common/ToggleButton';
import { groupShopOffers, PRODUCT_TYPE_FALLBACKS, productTypeKey, SHOP_CATEGORY_FALLBACKS } from '../../hooks/collectibles/collectibles.helpers';
import { getCollectibleProductName, useCollectibles } from '../../hooks/collectibles/useCollectibles';
import { useNotification } from '../../hooks/notification';
import emeraldIcon from '../../assets/images/collectibles/pursearea_tiny_emerald_icon.png';
import { CollectibleProductImageView } from './CollectibleProductImageView';
import { CollectiblesLoadingView } from './CollectiblesLoadingView';
import { NativeTextTree } from '../../common/native-text/NativeTextTree';

/** `ShopTab`: the shop's categories, the offers of the picked one, and the picked offer's preview and price. */
export const CollectiblesShopTabView: FC = () => {
    const { shopOffers = null, emeralds = 0, purchase = null, purchasePending = false } = useCollectibles();
    const { simpleAlert = null, showConfirm = null } = useNotification();
    const [categoryKey, setCategoryKey] = useState<string>(null);
    const [selectedCode, setSelectedCode] = useState<string>(null);
    const groups = useMemo(() => groupShopOffers(shopOffers ?? []), [shopOffers]);
    const group = groups.find((entry) => entry.categoryKey === categoryKey) ?? groups[0] ?? null;
    const offer: CollectibleShopOfferData = group?.offers.find((entry) => entry.productCode === selectedCode) ?? group?.offers[0] ?? null;

    if (shopOffers === null) return <CollectiblesLoadingView />;

    if (!groups.length) {
        return <div className="octane-collectibles-empty">{localizeWithFallback('collectibles.shop.empty', 'There is nothing for sale right now.')}</div>;
    }

    /** `ShopTab.onClickBuy`: too few emeralds is an alert, otherwise the purchase is confirmed first. */
    const buy = () => {
        if (!offer) return;

        if (emeralds < offer.emeraldPrice) {
            simpleAlert?.(
                localizeWithFallback('catalog.alert.notenough.activitypoints.description.1001', 'You do not have enough emeralds.'),
                null,
                null,
                null,
                localizeWithFallback('catalog.alert.notenough.activitypoints.title.1001', 'Not enough emeralds')
            );
            return;
        }

        const name = getCollectibleProductName(offer.product);

        showConfirm?.(
            localizeWithFallback('collectibles.shop.confirm', `Buy ${name} for ${offer.emeraldPrice} emeralds?`, ['name', 'price'], [name, String(offer.emeraldPrice)]),
            () => purchase?.(offer),
            null,
            localizeWithFallback('generic.buy', 'Buy'),
            null,
            localizeWithFallback('catalog.purchase_confirmation.title', 'Confirm purchase')
        );
    };

    return (
        <NativeTextTree>
            <div className="octane-collectibles-split" data-testid="collectibles-shop">
                <div className="octane-collectibles-side">
                    <div className="octane-collectibles-navigation is-tall">
                        {groups.map((entry) => (
                            <ToggleButton
                                key={entry.categoryKey}
                                className={`octane-collectibles-navigation-item${group?.categoryKey === entry.categoryKey ? ' is-active' : ''}`}
                                pressed={group?.categoryKey === entry.categoryKey}
                                onClick={() => {
                                    setCategoryKey(entry.categoryKey);
                                    setSelectedCode(null);
                                }}
                            >
                                <span className="octane-collectibles-navigation-title">
                                    {localizeWithFallback(entry.categoryKey, SHOP_CATEGORY_FALLBACKS[entry.categoryKey] ?? entry.categoryKey)}
                                </span>
                            </ToggleButton>
                        ))}
                    </div>
                </div>
                <div className="octane-collectibles-collection">
                    <div className="octane-collectibles-preview is-shop">
                        <div className="octane-collectibles-preview-star" />
                        <div className="octane-collectibles-preview-image">{offer && <CollectibleProductImageView product={offer.product} />}</div>
                        {offer && (
                            <>
                                <div className="octane-collectibles-preview-name" data-testid="collectibles-shop-name">
                                    {getCollectibleProductName(offer.product)}
                                </div>
                                <div className="octane-collectibles-preview-info is-shop">
                                    <div>
                                        <span>{localizeWithFallback('collectibles.item.type', 'Type')}</span>
                                        <span>
                                            {localizeWithFallback(
                                                productTypeKey(offer.product.productTypeId),
                                                PRODUCT_TYPE_FALLBACKS[productTypeKey(offer.product.productTypeId)] ?? ''
                                            )}
                                        </span>
                                    </div>
                                    <div>
                                        <span>{localizeWithFallback('collectibles.item.rarity', 'Rarity')}</span>
                                        <span>{offer.product.rarity}</span>
                                    </div>
                                    <div>
                                        <span>{localizeWithFallback('collectibles.item.xp', 'XP')}</span>
                                        <span>{offer.product.score}</span>
                                    </div>
                                </div>
                                <div className="octane-collectibles-buy-bar">
                                    {offer.mintLimit > 0 && (
                                        <span className="octane-collectibles-mint-limit" data-testid="collectibles-mint-limit">
                                            {`${offer.mintedCount}/${offer.mintLimit}`}
                                        </span>
                                    )}
                                    <span className="octane-collectibles-price">
                                        {offer.emeraldPrice}
                                        <img alt="" draggable={false} src={emeraldIcon} />
                                    </span>
                                    <BaseButton className="octane-collectibles-button is-green" disabled={!(offer.mintLimit === -1 || offer.mintedCount < offer.mintLimit) || purchasePending} onClick={buy}>
                                        {localizeWithFallback('generic.buy', 'Buy')}
                                    </BaseButton>
                                </div>
                            </>
                        )}
                    </div>
                    <div className="octane-collectibles-item-grid">
                        {group?.offers.map((entry) => (
                            <ToggleButton
                                key={entry.productCode}
                                aria-label={getCollectibleProductName(entry.product)}
                                className={`octane-collectibles-item${offer?.productCode === entry.productCode ? ' is-selected' : ''}`}
                                pressed={offer?.productCode === entry.productCode}
                                onClick={() => setSelectedCode(entry.productCode)}
                            >
                                <CollectibleProductImageView icon product={entry.product} />
                                <span className="octane-collectibles-item-amount">{entry.emeraldPrice}</span>
                            </ToggleButton>
                        ))}
                    </div>
                </div>
            </div>
        </NativeTextTree>
    );
};
15Sujets
1Dépôts
20Membres
2En 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