Context
All plan types, except FREE have planDetails that share many fields but differ in economic model and feature requirements.
Rendering conditional fields inline (e.g., if (type === SVOD)) inside sections risks:
- Scattered branching logic
- Reduced readability
- Increased maintenance burden
- Hard-to-track plan-type conditionals
A centralized visibility strategy was required without introducing a dynamic schema engine.
Decision
We introduced a PlanDetails field visibility configuration map:
export const PlanDetailsFieldMap = {
fieldName: [AllowedPlanTypes],
};
This map:
- Defines which fields are visible for which plan types
- Contains no rendering metadata
- Contains no validation logic
- Controls visibility only
A pure helper:
shouldShowField(fieldId, planType);
And a small UI guard component:
<PlanFieldGuard fieldId="..." planType={type}>
{children}
</PlanFieldGuard>
were introduced to centralize field branching.
Sections now declare fields declaratively, and visibility is controlled by the guard.
Consequences
Positive
- Eliminates inline plan-type conditionals
- Centralizes visibility logic
- Improves JSX readability
- Prevents conditional sprawl
- Adding new fields requires updating only:
- The section
- The field map
Negative
- Small additional abstraction layer
- Requires discipline to ensure all type-sensitive fields use the guard
Notes
- This approach intentionally avoids building a dynamic form schema system.
- Monetisation is considered stable, and this solution balances clarity and maintainability without over-engineering.
- The field visibility map must remain strictly limited to:
field → allowed plan types- No additional responsibilities should be added.