Component Name: subscriptions¶
Last Updated: 2025-09-29 Source Code: https://bitbucket.org/i2cinc/i2c.salesforce.metadata/src/STAGING/force-app/main/default/lwc/subscriptions
API Name: c-subscriptions Type: Form/Display Component Target: Not exposed (embedded in parent components)
Business Purpose¶
This component displays and manages a user's active subscriptions, allowing them to view renewal dates, amounts, and cancel future auto-renewals. It enforces a 90-day restriction preventing cancellation of newly-purchased subscriptions. Used within account management interfaces to give members control over their recurring purchases.
User Interface¶
Visual Description¶
- Layout: Modal dialog with subscription list
- Key UI Elements: "View My Subscriptions" link, modal with subscription table, checkboxes, cancel button
- Responsive: Modal adapts to screen size
Component Structure¶
Files¶
subscriptions.html- Template (83 lines)subscriptions.js- Controller (160 lines)subscriptions.js-meta.xml- Metadata (not exposed)
HTML Template Structure¶
<template>
<div class="row">
<a onclick={openModal} data-item="subscriptions">View My Subscriptions</a>
</div>
<div class="modal" data-id="subscriptions">
<div class="modal-dialog">
<div class="modal-header">
<h5>My Subscriptions</h5>
<button onclick={closeModal}>Close</button>
</div>
<div class="modal-body">
<template lwc:if={isLoading}>
<lightning-spinner />
</template>
<template lwc:elseif={showSubscriptions}>
<template if:true={subscriptions.length}>
<div for:each={subscriptions}>
<input type="checkbox" onchange={handleSubscriptionSelection}
disabled={subscription.preventCancel} />
<strong>Product:</strong> {subscription.ProductName}
<strong>Renewal Date:</strong> {subscription.EndtDate}
</div>
<button onclick={handleCancelSubscription}>
Cancel Future Auto-Renewal(s)
</button>
<div if:true={showErrorMessage} class={messageClass}>
{messageText}
</div>
</template>
<template if:false={subscriptions.length}>
<p>You don't have any subscriptions.</p>
</template>
</template>
</div>
</div>
</div>
</template>
Key Template Features: - Modal dialog pattern with backdrop - Lightning spinner during loading/operations - Checkboxes with preventCancel logic (90-day restriction) - Alert messages for user feedback - Conditional rendering for empty state
JavaScript Controller¶
Properties (API)¶
@api accountId¶
- Type:
String - Required: Yes
- Description: Account ID to load subscriptions for
@api refreshData()¶
- Type:
Function - Returns: Promise
- Description: Public method to refresh subscription data
Tracked Properties¶
@track selectedSubscriptions¶
- Type:
Set - Purpose: Tracks which subscriptions user has selected for cancellation
@track showErrorMessage, messageClass, messageText¶
- Type:
Boolean,String,String - Purpose: Controls display and styling of user feedback messages
isLoading¶
- Type:
Boolean - Purpose: Shows/hides loading spinner
Wire Adapters¶
@wire(getActiveSubscriptions, {accountId: '$accountId'})¶
@wire(getActiveSubscriptions, {accountId: '$accountId'})
wiredSubscriptions(response) {
this.subscriptionsResponse = response;
if(response.data) {
this.subscriptions = response.data.map((subscription) => ({
Id, ProductName, StartDate, EndtDate, formattedAmount,
preventCancel: this.computePreventCancel(subscription.Start_Date__c)
}));
}
}
Purpose: Loads active subscriptions for account Fields Retrieved: Subscription with Product, dates, Order Product price Error Handling: Logs to console
Event Handlers¶
handleSubscriptionSelection(event)¶
Triggered By: Checkbox change Action: Adds/removes subscription from selectedSubscriptions Set
handleCancelSubscription()¶
Triggered By: Click "Cancel Future Auto-Renewal(s)" button Action: Validates selection, calls cancelSubscriptions Apex, refreshes data
openModal(event) / closeModal(event)¶
Triggered By: Click link/button Action: Shows/hides modal and backdrop
Private Methods¶
computePreventCancel(startRaw)¶
Purpose: Calculates if subscription is within 90-day restriction Returns: Boolean (true if within 90 days) Logic: Compares subscription.Start_Date__c to today
formatDate(dateString)¶
Purpose: Formats date as "DD Mon YYYY" (e.g., "15 Jan 2025") Returns: Formatted string
getCurrencySymbol(currencyIsoCode)¶
Purpose: Maps currency codes to symbols Returns: Currency symbol (e.g., "$", "€")
showMessage(type, message)¶
Purpose: Displays alert message for 8 seconds Parameters: type ("alert-warning"), message (String)
toggleModalVisibility(modal, isVisible)¶
Purpose: Shows/hides modal and backdrop
Events¶
None dispatched to parent
Styling (CSS)¶
Custom CSS Classes¶
.cancel-subscription-btn-bg: Cancel button styling.order-row: Subscription row styling.alert,.alert-warning: Alert message styling.spinner-section: Loading spinner positioning.my-sybscriptions-link: Link styling
SLDS Classes¶
slds-backdrop,slds-backdrop_open: Modal backdrop
Dependencies¶
Lightning Web Components (Base)¶
lightning-spinner
Custom LWC Components¶
None
Apex Classes¶
SubscriptionController.getActiveSubscriptions(): Returns active subscriptionsSubscriptionController.cancelSubscriptions(): Cancels selected subscriptions
Salesforce Objects & Fields¶
Subscription__c: Product__c, Start_Date__c, Renew_On__c, Order_Product__r.TotalPrice, etc.Chargent_Order__c: ChargentOrders__Next_Scheduled_Payment__c
Configuration¶
Not exposed - embedded component
User Interactions¶
Actions Available to Users¶
- View Subscriptions:
- Trigger: Click "View My Subscriptions" link
-
Result: Opens modal with subscription list
-
Select Subscriptions to Cancel:
- Trigger: Check checkboxes (if not within 90-day restriction)
-
Result: Adds to selection
-
Cancel Future Auto-Renewals:
- Trigger: Click "Cancel Future Auto-Renewal(s)" button
- Result: Cancels selected subscriptions, refreshes list, shows confirmation
Validation & Error Handling¶
Client-Side Validation: - Prevents cancellation within 90 days of purchase (preventCancel flag) - Requires at least one subscription selected
Error Messages: - "Please select at least one subscription." (if none selected) - Apex errors logged to console, may show blank on failure
Loading States: - Spinner during initial load - Spinner during cancellation operation - Disabled backdrop prevents interaction during loading
Data Flow¶
Input Data Flow¶
accountId from parent
↓
@wire getActiveSubscriptions
↓
Map to subscription objects with preventCancel
↓
Display in modal
Output Data Flow¶
User selects subscriptions
↓
handleCancelSubscription
↓
cancelSubscriptions Apex
↓
refreshApex(subscriptionsResponse)
↓
List updates automatically
Performance Considerations¶
- Uses @wire for automatic caching
- refreshApex reuses wire cache (efficient)
- Set data structure for O(1) selection lookups
Accessibility (a11y)¶
ARIA Labels: - Modal needs aria-modal, aria-labelledby attributes - Checkboxes need labels (currently only visual)
Keyboard Navigation: - Modal trap focus needs implementation - Checkboxes keyboard accessible
Screen Reader Support: - Modal title announced - Checkbox labels needed - Alert messages announced (auto-dismisses may be too fast)
Color Contrast: - Depends on custom CSS classes
Testing¶
Jest Tests¶
None
Manual Testing Checklist¶
- [ ] Subscriptions load correctly
- [ ] 90-day restriction prevents cancellation
- [ ] Multiple selections work
- [ ] Cancellation succeeds
- [ ] Empty state displays
- [ ] Loading states show
- [ ] Error messages display
- [ ] Auto-dismissal timing
- [ ] Modal open/close
- [ ] Refresh after cancellation
Usage Examples¶
In Parent Component¶
Programmatic Refresh¶
// In parent component
const subsComponent = this.template.querySelector('c-subscriptions');
await subsComponent.refreshData();
Changes & History¶
- 2025-09-29: Latest version
⚠️ Pre-Go-Live Concerns¶
CRITICAL - Fix Before Go-Live¶
- 90-day calculation uses local time: computePreventCancel (lines 76-88) uses Date() which varies by timezone - should use UTC
- No confirmation dialog: Users can accidentally cancel subscriptions with one click
- No undo: Once cancelled, no way to undo (before closing modal)
HIGH - Address Soon After Go-Live¶
- No unit tests: Zero coverage for business-critical cancellation logic
- Checkbox labels missing: Accessibility violation - checkboxes have no associated labels
- Modal not accessible: Missing aria-modal, aria-labelledby, focus trap
- Error handling weak: Apex errors don't show user-friendly messages
- Alert auto-dismisses: 8-second timeout may be too fast for users to read (line 126-128)
MEDIUM - Future Enhancement¶
- Add cancellation reason: Collect feedback on why cancelling
- Add pause option: Allow pausing instead of cancelling
- Show cancellation effective date: Clarify when renewal stops
- Add reactivation: Allow un-cancelling within grace period
- Bulk actions: Select all/deselect all checkboxes
LOW - Monitor¶
- Currency symbol hardcoded: getCurrencySymbol supports limited currencies
- Date format hardcoded: "en-GB" format may not suit all locales
- Console.log statements: Lines 112, 124 log to console
- Commented-out code: Lines 45, 54-57 have commented JSX
Maintenance Notes¶
Complexity: Medium Recommended Review Schedule: Quarterly
Key Maintainer Notes: - CRITICAL: 90-day restriction calculation must account for timezones - Component manages auto-renewal cancellations - very sensitive user action - No confirmation dialog - users can accidentally cancel with one click - Cancellation is permanent within this UI (no undo) - preventCancel logic prevents cancellation within 90 days of Start_Date__c - Refresh uses refreshApex which is efficient (reuses wire cache) - Modal visibility managed via CSS classes and backdrop div - selectedSubscriptions uses Set for efficient lookups - Alert messages auto-dismiss after 8 seconds - Component embedded in parent (not standalone page) - Consider adding analytics to track cancellation rates
Browser Compatibility: - Chrome: Latest - Firefox: Latest - Safari: Latest - Mobile: iOS 12+, Android 8+