Highlight upgrades in package shop
This commit is contained in:
@@ -13,6 +13,7 @@ import { useAdminTheme } from './theme';
|
||||
import { getPackages, createTenantPaddleCheckout, Package, getTenantPackagesOverview, TenantPackageSummary } from '../api';
|
||||
import { getApiErrorMessage } from '../lib/apiError';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { classifyPackageTier, selectRecommendedPackageId } from './lib/packageShop';
|
||||
|
||||
export default function MobilePackageShopPage() {
|
||||
const { t } = useTranslation('management');
|
||||
@@ -57,16 +58,18 @@ export default function MobilePackageShopPage() {
|
||||
);
|
||||
}
|
||||
|
||||
const activePackageId = inventory?.activePackage?.package_id ?? null;
|
||||
const activeCatalogPackage = (catalog ?? []).find((pkg) => pkg.id === activePackageId) ?? null;
|
||||
const activePrice = activeCatalogPackage?.price ?? null;
|
||||
const recommendedPackageId = selectRecommendedPackageId(catalog ?? [], recommendedFeature, activePrice);
|
||||
|
||||
// Merge and sort packages
|
||||
const sortedPackages = [...(catalog || [])].sort((a, b) => {
|
||||
// 1. Recommended feature first
|
||||
const aHasFeature = recommendedFeature && a.features?.[recommendedFeature];
|
||||
const bHasFeature = recommendedFeature && b.features?.[recommendedFeature];
|
||||
if (aHasFeature && !bHasFeature) return -1;
|
||||
if (!aHasFeature && bHasFeature) return 1;
|
||||
if (recommendedPackageId) {
|
||||
if (a.id === recommendedPackageId && b.id !== recommendedPackageId) return -1;
|
||||
if (b.id === recommendedPackageId && a.id !== recommendedPackageId) return 1;
|
||||
}
|
||||
|
||||
// 2. Inventory status (Owned packages later if they are fully used, but usually we want to show active stuff)
|
||||
// Actually, let's keep price sorting as secondary
|
||||
return a.price - b.price;
|
||||
});
|
||||
|
||||
@@ -97,7 +100,8 @@ export default function MobilePackageShopPage() {
|
||||
{sortedPackages.map((pkg) => {
|
||||
const owned = inventory?.packages?.find(p => p.package_id === pkg.id);
|
||||
const isActive = inventory?.activePackage?.package_id === pkg.id;
|
||||
const isRecommended = recommendedFeature && pkg.features?.[recommendedFeature];
|
||||
const isRecommended = recommendedPackageId ? pkg.id === recommendedPackageId : false;
|
||||
const { isUpgrade, isDowngrade } = classifyPackageTier(pkg.price, activePrice);
|
||||
|
||||
return (
|
||||
<PackageShopCard
|
||||
@@ -106,6 +110,8 @@ export default function MobilePackageShopPage() {
|
||||
owned={owned}
|
||||
isActive={isActive}
|
||||
isRecommended={isRecommended}
|
||||
isUpgrade={isUpgrade}
|
||||
isDowngrade={isDowngrade}
|
||||
onSelect={() => setSelectedPackage(pkg)}
|
||||
/>
|
||||
);
|
||||
@@ -121,12 +127,16 @@ function PackageShopCard({
|
||||
owned,
|
||||
isActive,
|
||||
isRecommended,
|
||||
isUpgrade,
|
||||
isDowngrade,
|
||||
onSelect
|
||||
}: {
|
||||
pkg: Package;
|
||||
owned?: TenantPackageSummary;
|
||||
isActive?: boolean;
|
||||
isRecommended?: any;
|
||||
isUpgrade?: boolean;
|
||||
isDowngrade?: boolean;
|
||||
onSelect: () => void
|
||||
}) {
|
||||
const { textStrong, muted, border, primary, accentSoft } = useAdminTheme();
|
||||
@@ -140,6 +150,7 @@ function PackageShopCard({
|
||||
? t('shop.status.remaining', '{{count}} Events left', { count: owned.remaining_events })
|
||||
: t('shop.status.owned', 'Purchased'))
|
||||
: null;
|
||||
const isSubdued = Boolean(isDowngrade && !isActive);
|
||||
|
||||
return (
|
||||
<MobileCard
|
||||
@@ -149,6 +160,7 @@ function PackageShopCard({
|
||||
space="$3"
|
||||
pressStyle={{ backgroundColor: accentSoft }}
|
||||
backgroundColor={isActive ? '$green1' : undefined}
|
||||
style={{ opacity: isSubdued ? 0.6 : 1 }}
|
||||
>
|
||||
<XStack justifyContent="space-between" alignItems="flex-start">
|
||||
<YStack space="$1">
|
||||
@@ -157,6 +169,8 @@ function PackageShopCard({
|
||||
{pkg.name}
|
||||
</Text>
|
||||
{isRecommended && <PillBadge tone="warning">{t('shop.badges.recommended', 'Recommended')}</PillBadge>}
|
||||
{isUpgrade && !isActive ? <PillBadge tone="success">{t('shop.badges.upgrade', 'Upgrade')}</PillBadge> : null}
|
||||
{isDowngrade && !isActive ? <PillBadge tone="muted">{t('shop.badges.downgrade', 'Downgrade')}</PillBadge> : null}
|
||||
{isActive && <PillBadge tone="success">{t('shop.badges.active', 'Active')}</PillBadge>}
|
||||
</XStack>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user