fix(web): handle null maxListings/maxSavedSearches on ENTERPRISE plan
Some checks failed
CI / Lint → Typecheck → Test → Build (22) (push) Failing after 6s
CI / E2E Tests (push) Has been skipped
CodeQL Analysis / CodeQL (javascript-typescript) (push) Failing after 35s
Deploy / Build AI Services Image (push) Failing after 6s
CI / AI Services (Python) — Smoke (push) Failing after 5s
Deploy / Build API Image (push) Failing after 5s
Deploy / Build Web Image (push) Failing after 5s
E2E Tests / Playwright E2E (push) Failing after 18s
Security Scanning / Dependency Audit (pnpm) (push) Failing after 4s
Security Scanning / Trivy Scan — API Image (push) Failing after 43s
Security Scanning / Trivy Scan — Web Image (push) Failing after 38s
Security Scanning / Trivy Scan — AI Services Image (push) Failing after 44s
Security Scanning / Trivy Filesystem Scan (push) Failing after 36s
Deploy / Deploy to Staging (push) Has been skipped
Deploy / Deploy to Production (push) Has been skipped
Deploy / Smoke Test Production (push) Has been skipped
Security Scanning / Security Gate (push) Failing after 1s
Deploy / Rollback Staging (push) Has been skipped
Deploy / Smoke Test Staging (push) Has been skipped
Deploy / Rollback Production (push) Has been skipped
Some checks failed
CI / Lint → Typecheck → Test → Build (22) (push) Failing after 6s
CI / E2E Tests (push) Has been skipped
CodeQL Analysis / CodeQL (javascript-typescript) (push) Failing after 35s
Deploy / Build AI Services Image (push) Failing after 6s
CI / AI Services (Python) — Smoke (push) Failing after 5s
Deploy / Build API Image (push) Failing after 5s
Deploy / Build Web Image (push) Failing after 5s
E2E Tests / Playwright E2E (push) Failing after 18s
Security Scanning / Dependency Audit (pnpm) (push) Failing after 4s
Security Scanning / Trivy Scan — API Image (push) Failing after 43s
Security Scanning / Trivy Scan — Web Image (push) Failing after 38s
Security Scanning / Trivy Scan — AI Services Image (push) Failing after 44s
Security Scanning / Trivy Filesystem Scan (push) Failing after 36s
Deploy / Deploy to Staging (push) Has been skipped
Deploy / Deploy to Production (push) Has been skipped
Deploy / Smoke Test Production (push) Has been skipped
Security Scanning / Security Gate (push) Failing after 1s
Deploy / Rollback Staging (push) Has been skipped
Deploy / Smoke Test Staging (push) Has been skipped
Deploy / Rollback Production (push) Has been skipped
Seed stores null (not -1) for unlimited quotas on the ENTERPRISE tier. PlanDto now types these as `number | null`. PricingPage treats null the same as -1 — both render 'Không giới hạn' instead of 'null tin đăng'. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -87,10 +87,13 @@ function getFeatureValue(
|
||||
key: string,
|
||||
): boolean | number | string {
|
||||
if (key === 'maxListings') {
|
||||
return plan.maxListings === -1 ? 'Không giới hạn' : plan.maxListings;
|
||||
// null and -1 both signal "unlimited" (seed uses null, business logic uses -1)
|
||||
return plan.maxListings == null || plan.maxListings === -1
|
||||
? 'Không giới hạn'
|
||||
: plan.maxListings;
|
||||
}
|
||||
if (key === 'maxSavedSearches') {
|
||||
return plan.maxSavedSearches === -1
|
||||
return plan.maxSavedSearches == null || plan.maxSavedSearches === -1
|
||||
? 'Không giới hạn'
|
||||
: plan.maxSavedSearches;
|
||||
}
|
||||
@@ -300,17 +303,19 @@ export default function PricingPage() {
|
||||
<li className="flex items-center gap-2">
|
||||
<Check className="h-4 w-4 shrink-0 text-green-600" />
|
||||
<span>
|
||||
{plan.maxListings === -1
|
||||
{plan.maxListings == null || plan.maxListings === -1
|
||||
? t('unlimited')
|
||||
: `${plan.maxListings} ${t('listingsCount')}`}
|
||||
: `${plan.maxListings}`}{' '}
|
||||
{t('listingsCount')}
|
||||
</span>
|
||||
</li>
|
||||
<li className="flex items-center gap-2">
|
||||
<Check className="h-4 w-4 shrink-0 text-green-600" />
|
||||
<span>
|
||||
{plan.maxSavedSearches === -1
|
||||
{plan.maxSavedSearches == null || plan.maxSavedSearches === -1
|
||||
? t('unlimited')
|
||||
: `${plan.maxSavedSearches} ${t('savedSearchesCount')}`}
|
||||
: `${plan.maxSavedSearches}`}{' '}
|
||||
{t('savedSearchesCount')}
|
||||
</span>
|
||||
</li>
|
||||
<li className="flex items-center gap-2">
|
||||
|
||||
@@ -6,8 +6,8 @@ export interface PlanDto {
|
||||
name: string;
|
||||
priceMonthlyVND: string;
|
||||
priceYearlyVND: string;
|
||||
maxListings: number;
|
||||
maxSavedSearches: number;
|
||||
maxListings: number | null; // null = unlimited (ENTERPRISE tier)
|
||||
maxSavedSearches: number | null;
|
||||
features: Record<string, boolean | number | string>;
|
||||
isActive: boolean;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user