subos-frontend 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/PACKAGE_REFERENCE.md +822 -0
- package/dist/index.js +2 -31
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2 -31
- package/dist/index.mjs.map +1 -1
- package/dist/style.css +3 -15
- package/dist/types/utils/planUtils.d.ts.map +1 -1
- package/package.json +5 -14
|
@@ -0,0 +1,822 @@
|
|
|
1
|
+
# SubOS Frontend Package Reference
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
SubOS Frontend is a comprehensive React component library for managing subscriptions, pricing, billing, and account logic in SaaS applications. This package provides ready-to-use components, hooks, and API integrations for building subscription management interfaces.
|
|
6
|
+
|
|
7
|
+
**Built with:** React 19, TypeScript, Material-UI, Emotion, React Router DOM, Stripe
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## 📦 Installation & Setup
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install subos-frontend
|
|
15
|
+
# or
|
|
16
|
+
yarn add subos-frontend
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### Required Peer Dependencies
|
|
20
|
+
```bash
|
|
21
|
+
npm install react react-dom react-router-dom @stripe/react-stripe-js @stripe/stripe-js
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Configuration (REQUIRED)
|
|
25
|
+
```javascript
|
|
26
|
+
import { configureSubOS } from 'subos-frontend';
|
|
27
|
+
import 'subos-frontend/style.css';
|
|
28
|
+
|
|
29
|
+
// Configure at app startup
|
|
30
|
+
configureSubOS({
|
|
31
|
+
apiEndpoint: 'https://your-api.com/api/v1',
|
|
32
|
+
projectId: 'your-project-id',
|
|
33
|
+
stripePublishableKey: 'pk_test_your_stripe_key',
|
|
34
|
+
appName: 'Your App Name',
|
|
35
|
+
appEnvironment: 'production' // or 'development'
|
|
36
|
+
});
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## 🎯 Components
|
|
42
|
+
|
|
43
|
+
### Plan Components
|
|
44
|
+
|
|
45
|
+
#### `PlanCard`
|
|
46
|
+
Displays individual subscription plan details with selection functionality.
|
|
47
|
+
|
|
48
|
+
**Props:**
|
|
49
|
+
```typescript
|
|
50
|
+
interface PlanCardProps {
|
|
51
|
+
plan: Plan; // Plan object with pricing and features
|
|
52
|
+
isSelected: boolean; // Whether this plan is currently selected
|
|
53
|
+
billingCycle: 'monthly' | 'yearly'; // Current billing cycle filter
|
|
54
|
+
onSelect: (plan: Plan) => void; // Callback when plan is selected
|
|
55
|
+
isActive?: boolean; // Whether this is user's current plan
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**Usage:**
|
|
60
|
+
```jsx
|
|
61
|
+
<PlanCard
|
|
62
|
+
plan={planData}
|
|
63
|
+
isSelected={selectedPlan?.id === planData.id}
|
|
64
|
+
billingCycle="monthly"
|
|
65
|
+
onSelect={handlePlanSelect}
|
|
66
|
+
isActive={false}
|
|
67
|
+
/>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
#### `PlansGrid`
|
|
71
|
+
Grid layout container for displaying multiple plan cards.
|
|
72
|
+
|
|
73
|
+
**Props:**
|
|
74
|
+
```typescript
|
|
75
|
+
interface PlansGridProps {
|
|
76
|
+
plans: Plan[]; // Array of plans to display
|
|
77
|
+
selectedPlan: Plan | null; // Currently selected plan
|
|
78
|
+
billingCycle: 'monthly' | 'yearly'; // Billing cycle filter
|
|
79
|
+
onPlanSelect: (plan: Plan) => void; // Plan selection handler
|
|
80
|
+
activeSubscription?: Subscription; // User's current subscription
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
#### `PlanSelector`
|
|
85
|
+
Complete plan selection interface with filtering and selection.
|
|
86
|
+
|
|
87
|
+
**Props:**
|
|
88
|
+
```typescript
|
|
89
|
+
interface PlanSelectorProps {
|
|
90
|
+
onPlanSelect: (plan: Plan) => void; // Plan selection callback
|
|
91
|
+
initialBillingCycle?: 'monthly' | 'yearly'; // Default billing cycle
|
|
92
|
+
showBillingToggle?: boolean; // Show billing cycle toggle
|
|
93
|
+
showTierFilter?: boolean; // Show tier filtering dropdown
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
#### `BillingCycleToggle`
|
|
98
|
+
Toggle component for switching between monthly and yearly billing.
|
|
99
|
+
|
|
100
|
+
**Props:**
|
|
101
|
+
```typescript
|
|
102
|
+
interface BillingCycleToggleProps {
|
|
103
|
+
value: 'monthly' | 'yearly'; // Current billing cycle
|
|
104
|
+
onChange: (cycle: 'monthly' | 'yearly') => void; // Change handler
|
|
105
|
+
disabled?: boolean; // Disable the toggle
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
#### `TierFilterDropdown`
|
|
110
|
+
Dropdown for filtering plans by tier/category.
|
|
111
|
+
|
|
112
|
+
**Props:**
|
|
113
|
+
```typescript
|
|
114
|
+
interface TierFilterDropdownProps {
|
|
115
|
+
value: string; // Current filter value
|
|
116
|
+
onChange: (value: string) => void; // Filter change handler
|
|
117
|
+
options: DropdownOption[]; // Available filter options
|
|
118
|
+
disabled?: boolean; // Disable the dropdown
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Payment Components
|
|
123
|
+
|
|
124
|
+
#### `ChangeCardButton`
|
|
125
|
+
Button component for updating payment methods.
|
|
126
|
+
|
|
127
|
+
**Props:**
|
|
128
|
+
```typescript
|
|
129
|
+
interface ChangeCardButtonProps {
|
|
130
|
+
onSuccess?: () => void; // Success callback
|
|
131
|
+
onError?: (error: string) => void; // Error callback
|
|
132
|
+
customerId: string; // Customer ID for payment method update
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
#### `PaymentSuccessView`
|
|
137
|
+
Success page component after successful payment.
|
|
138
|
+
|
|
139
|
+
**Usage:**
|
|
140
|
+
```jsx
|
|
141
|
+
<PaymentSuccessView />
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
#### `PaymentCancelView`
|
|
145
|
+
Cancellation page component when payment is cancelled.
|
|
146
|
+
|
|
147
|
+
**Usage:**
|
|
148
|
+
```jsx
|
|
149
|
+
<PaymentCancelView />
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Subscription Components
|
|
153
|
+
|
|
154
|
+
#### `SubscriptionDetails`
|
|
155
|
+
Displays detailed information about user's subscription.
|
|
156
|
+
|
|
157
|
+
**Props:**
|
|
158
|
+
```typescript
|
|
159
|
+
interface SubscriptionDetailsProps {
|
|
160
|
+
subscription: Subscription; // Subscription data
|
|
161
|
+
onCancel?: () => void; // Cancel subscription callback
|
|
162
|
+
onUpgrade?: () => void; // Upgrade subscription callback
|
|
163
|
+
showActions?: boolean; // Show action buttons
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Transaction Components
|
|
168
|
+
|
|
169
|
+
#### `TransactionList`
|
|
170
|
+
List component for displaying transaction history.
|
|
171
|
+
|
|
172
|
+
**Props:**
|
|
173
|
+
```typescript
|
|
174
|
+
interface TransactionListProps {
|
|
175
|
+
externalId: string; // Customer external ID
|
|
176
|
+
filters?: TransactionFilters; // Optional transaction filters
|
|
177
|
+
onTransactionClick?: (transaction: Transaction) => void; // Transaction click handler
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
#### `TransactionModal`
|
|
182
|
+
Modal component for displaying transaction details.
|
|
183
|
+
|
|
184
|
+
**Props:**
|
|
185
|
+
```typescript
|
|
186
|
+
interface TransactionModalProps {
|
|
187
|
+
transaction: Transaction | null; // Transaction to display
|
|
188
|
+
isOpen: boolean; // Modal open state
|
|
189
|
+
onClose: () => void; // Close modal callback
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Email Components
|
|
194
|
+
|
|
195
|
+
#### `EmailEntry`
|
|
196
|
+
Component for email input and management.
|
|
197
|
+
|
|
198
|
+
**Props:**
|
|
199
|
+
```typescript
|
|
200
|
+
interface EmailEntryProps {
|
|
201
|
+
value: string; // Current email value
|
|
202
|
+
onChange: (email: string) => void; // Email change handler
|
|
203
|
+
onSubmit?: (email: string) => void; // Email submit handler
|
|
204
|
+
placeholder?: string; // Input placeholder
|
|
205
|
+
disabled?: boolean; // Disable input
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Upgrade Components
|
|
210
|
+
|
|
211
|
+
#### `UpgradeSummary`
|
|
212
|
+
Summary component showing upgrade details and pricing.
|
|
213
|
+
|
|
214
|
+
**Props:**
|
|
215
|
+
```typescript
|
|
216
|
+
interface UpgradeSummaryProps {
|
|
217
|
+
currentPlan: Plan; // User's current plan
|
|
218
|
+
newPlan: Plan; // Plan to upgrade to
|
|
219
|
+
onConfirm: () => void; // Upgrade confirmation callback
|
|
220
|
+
onCancel: () => void; // Cancel upgrade callback
|
|
221
|
+
}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Common Components
|
|
225
|
+
|
|
226
|
+
#### `Layout`
|
|
227
|
+
Main layout wrapper component.
|
|
228
|
+
|
|
229
|
+
**Usage:**
|
|
230
|
+
```jsx
|
|
231
|
+
<Layout>
|
|
232
|
+
<YourContent />
|
|
233
|
+
</Layout>
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
#### `LogoInline`
|
|
237
|
+
Inline logo component.
|
|
238
|
+
|
|
239
|
+
**Usage:**
|
|
240
|
+
```jsx
|
|
241
|
+
<LogoInline />
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
#### `Pagination`
|
|
245
|
+
Pagination component for paginated data.
|
|
246
|
+
|
|
247
|
+
**Props:**
|
|
248
|
+
```typescript
|
|
249
|
+
interface PaginationProps {
|
|
250
|
+
currentPage: number; // Current page number
|
|
251
|
+
totalPages: number; // Total number of pages
|
|
252
|
+
onPageChange: (page: number) => void; // Page change handler
|
|
253
|
+
disabled?: boolean; // Disable pagination
|
|
254
|
+
}
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### Icon Components
|
|
258
|
+
|
|
259
|
+
#### `CheckIcon`
|
|
260
|
+
Check mark icon component.
|
|
261
|
+
|
|
262
|
+
**Props:**
|
|
263
|
+
```typescript
|
|
264
|
+
interface CheckIconProps {
|
|
265
|
+
className?: string; // CSS classes
|
|
266
|
+
size?: number; // Icon size
|
|
267
|
+
}
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
## 🪝 Hooks
|
|
273
|
+
|
|
274
|
+
### `usePlans()`
|
|
275
|
+
Hook for managing plan data and filtering.
|
|
276
|
+
|
|
277
|
+
**Returns:**
|
|
278
|
+
```typescript
|
|
279
|
+
interface UsePlansReturn {
|
|
280
|
+
// Data
|
|
281
|
+
plans: Plan[]; // All available plans
|
|
282
|
+
filteredPlans: Plan[]; // Filtered plans based on current filters
|
|
283
|
+
selectedPlan: Plan | null; // Currently selected plan
|
|
284
|
+
|
|
285
|
+
// Filters
|
|
286
|
+
tierFilter: string; // Current tier filter
|
|
287
|
+
billingCycle: 'monthly' | 'yearly'; // Current billing cycle
|
|
288
|
+
|
|
289
|
+
// Loading states
|
|
290
|
+
loading: boolean; // Loading state
|
|
291
|
+
error: string | null; // Error message
|
|
292
|
+
|
|
293
|
+
// Actions
|
|
294
|
+
fetchPlans: () => Promise<void>; // Fetch plans from API
|
|
295
|
+
setSelectedPlan: (plan: Plan | null) => void; // Set selected plan
|
|
296
|
+
setTierFilter: (filter: string) => void; // Set tier filter
|
|
297
|
+
setBillingCycle: (cycle: 'monthly' | 'yearly') => void; // Set billing cycle
|
|
298
|
+
clearPlans: () => void; // Clear all plans
|
|
299
|
+
|
|
300
|
+
// Computed values
|
|
301
|
+
dropdownOptions: DropdownOption[]; // Options for tier dropdown
|
|
302
|
+
currentSelectionText: string; // Current filter description
|
|
303
|
+
|
|
304
|
+
// Plan operations
|
|
305
|
+
handlePlanSelect: (plan: Plan) => void; // Handle plan selection
|
|
306
|
+
handleUpgrade: (email: string) => Promise<void>; // Handle plan upgrade
|
|
307
|
+
}
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
**Usage:**
|
|
311
|
+
```jsx
|
|
312
|
+
const {
|
|
313
|
+
plans,
|
|
314
|
+
filteredPlans,
|
|
315
|
+
selectedPlan,
|
|
316
|
+
loading,
|
|
317
|
+
error,
|
|
318
|
+
fetchPlans,
|
|
319
|
+
setSelectedPlan,
|
|
320
|
+
setBillingCycle
|
|
321
|
+
} = usePlans();
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
### `useSubscription()`
|
|
325
|
+
Hook for managing subscription data.
|
|
326
|
+
|
|
327
|
+
**Returns:**
|
|
328
|
+
```typescript
|
|
329
|
+
interface UseSubscriptionReturn {
|
|
330
|
+
subscription: Subscription | null; // Current subscription
|
|
331
|
+
loading: boolean; // Loading state
|
|
332
|
+
error: string | null; // Error message
|
|
333
|
+
fetchSubscription: (externalId: string) => Promise<void>; // Fetch subscription
|
|
334
|
+
cancelSubscription: (externalId: string, options?: CancelOptions) => Promise<void>; // Cancel subscription
|
|
335
|
+
}
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
### `useTransactions()`
|
|
339
|
+
Hook for managing transaction history.
|
|
340
|
+
|
|
341
|
+
**Props:**
|
|
342
|
+
```typescript
|
|
343
|
+
interface UseTransactionsProps {
|
|
344
|
+
externalId: string; // Customer external ID
|
|
345
|
+
filters?: TransactionFilters; // Transaction filters
|
|
346
|
+
}
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
**Returns:**
|
|
350
|
+
```typescript
|
|
351
|
+
interface UseTransactionsReturn {
|
|
352
|
+
transactions: Transaction[]; // Transaction list
|
|
353
|
+
loading: boolean; // Loading state
|
|
354
|
+
error: string | null; // Error message
|
|
355
|
+
pagination: PaginationMeta; // Pagination information
|
|
356
|
+
fetchTransactions: () => Promise<void>; // Fetch transactions
|
|
357
|
+
downloadInvoice: (transactionId: string) => Promise<void>; // Download invoice
|
|
358
|
+
}
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
### `usePagination()`
|
|
362
|
+
Hook for managing pagination state.
|
|
363
|
+
|
|
364
|
+
**Props:**
|
|
365
|
+
```typescript
|
|
366
|
+
interface UsePaginationProps {
|
|
367
|
+
totalItems: number; // Total number of items
|
|
368
|
+
itemsPerPage: number; // Items per page
|
|
369
|
+
initialPage?: number; // Initial page number
|
|
370
|
+
}
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
**Returns:**
|
|
374
|
+
```typescript
|
|
375
|
+
interface UsePaginationReturn {
|
|
376
|
+
currentPage: number; // Current page
|
|
377
|
+
totalPages: number; // Total pages
|
|
378
|
+
hasNextPage: boolean; // Has next page
|
|
379
|
+
hasPreviousPage: boolean; // Has previous page
|
|
380
|
+
goToPage: (page: number) => void; // Go to specific page
|
|
381
|
+
nextPage: () => void; // Go to next page
|
|
382
|
+
previousPage: () => void; // Go to previous page
|
|
383
|
+
}
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
### `useCancelSubscription()`
|
|
387
|
+
Hook for cancelling subscriptions.
|
|
388
|
+
|
|
389
|
+
**Props:**
|
|
390
|
+
```typescript
|
|
391
|
+
interface UseCancelSubscriptionProps {
|
|
392
|
+
externalId: string; // Customer external ID
|
|
393
|
+
onSuccess?: () => void; // Success callback
|
|
394
|
+
onError?: (error: string) => void; // Error callback
|
|
395
|
+
}
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
**Returns:**
|
|
399
|
+
```typescript
|
|
400
|
+
interface UseCancelSubscriptionReturn {
|
|
401
|
+
cancelSubscription: (options?: CancelOptions) => Promise<void>; // Cancel function
|
|
402
|
+
loading: boolean; // Loading state
|
|
403
|
+
error: string | null; // Error message
|
|
404
|
+
}
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
### `useCustomerPortal()`
|
|
408
|
+
Hook for customer portal functionality.
|
|
409
|
+
|
|
410
|
+
**Props:**
|
|
411
|
+
```typescript
|
|
412
|
+
interface UseCustomerPortalProps {
|
|
413
|
+
externalId: string; // Customer external ID
|
|
414
|
+
}
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
**Returns:**
|
|
418
|
+
```typescript
|
|
419
|
+
interface UseCustomerPortalReturn {
|
|
420
|
+
redirectToPortal: () => Promise<void>; // Redirect to customer portal
|
|
421
|
+
loading: boolean; // Loading state
|
|
422
|
+
error: string | null; // Error message
|
|
423
|
+
}
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
### `useEmailManagement()`
|
|
427
|
+
Hook for email management functionality.
|
|
428
|
+
|
|
429
|
+
**Returns:**
|
|
430
|
+
```typescript
|
|
431
|
+
interface UseEmailManagementReturn {
|
|
432
|
+
email: string; // Current email
|
|
433
|
+
setEmail: (email: string) => void; // Set email
|
|
434
|
+
validateEmail: (email: string) => boolean; // Validate email
|
|
435
|
+
saveEmail: () => Promise<void>; // Save email
|
|
436
|
+
loading: boolean; // Loading state
|
|
437
|
+
error: string | null; // Error message
|
|
438
|
+
}
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
---
|
|
442
|
+
|
|
443
|
+
## 🌐 API Functions
|
|
444
|
+
|
|
445
|
+
### Plans API
|
|
446
|
+
|
|
447
|
+
#### `plansApi.getPlans()`
|
|
448
|
+
Fetch all available plans.
|
|
449
|
+
|
|
450
|
+
**Request:** No payload required
|
|
451
|
+
|
|
452
|
+
**Response:**
|
|
453
|
+
```typescript
|
|
454
|
+
ApiResponse<Plan[]>
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
**Usage:**
|
|
458
|
+
```javascript
|
|
459
|
+
const response = await plansApi.getPlans();
|
|
460
|
+
if (response.success) {
|
|
461
|
+
console.log(response.data); // Plan[]
|
|
462
|
+
}
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
#### `plansApi.getPlanByCode(code, externalId, queryParams?)`
|
|
466
|
+
Fetch specific plan by code.
|
|
467
|
+
|
|
468
|
+
**Parameters:**
|
|
469
|
+
- `code: string` - Plan code
|
|
470
|
+
- `externalId: string` - Customer external ID
|
|
471
|
+
- `queryParams?: { paymentMethodId?: string; couponCode?: string }` - Optional query parameters
|
|
472
|
+
|
|
473
|
+
**Response:**
|
|
474
|
+
```typescript
|
|
475
|
+
ApiResponse<Plan>
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
#### `plansApi.createPaymentSession(planCode, options?)`
|
|
479
|
+
Create payment session for checkout.
|
|
480
|
+
|
|
481
|
+
**Parameters:**
|
|
482
|
+
- `planCode: string` - Plan code to purchase
|
|
483
|
+
- `options?: { amount?: number; currency?: string; customerEmail?: string; couponCode?: string }` - Optional parameters
|
|
484
|
+
|
|
485
|
+
**Payload:**
|
|
486
|
+
```typescript
|
|
487
|
+
{
|
|
488
|
+
planCode: string;
|
|
489
|
+
currency?: string; // Default: 'USD'
|
|
490
|
+
returnUrl: string; // Auto-generated: ${origin}/payment-success
|
|
491
|
+
cancelUrl: string; // Auto-generated: ${origin}/payment-cancel
|
|
492
|
+
customerEmail?: string; // Optional customer email
|
|
493
|
+
couponCode?: string; // Optional coupon code
|
|
494
|
+
amount?: number; // Optional custom amount
|
|
495
|
+
}
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
**Response:**
|
|
499
|
+
```typescript
|
|
500
|
+
ApiResponse<{
|
|
501
|
+
checkoutUrl: string; // Hosted checkout URL
|
|
502
|
+
gateway: string; // Payment gateway used
|
|
503
|
+
sessionId?: string; // Session ID
|
|
504
|
+
paymentId?: string; // Payment ID
|
|
505
|
+
}>
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
### Checkout API
|
|
509
|
+
|
|
510
|
+
#### `checkoutApi.getCheckoutDetails(planCode, queryParams?)`
|
|
511
|
+
Get checkout details including pricing and taxes.
|
|
512
|
+
|
|
513
|
+
**Parameters:**
|
|
514
|
+
- `planCode: string` - Plan code
|
|
515
|
+
- `queryParams?: { externalId?: string; paymentMethodId?: string; couponCode?: string }` - Optional parameters
|
|
516
|
+
|
|
517
|
+
**Response:**
|
|
518
|
+
```typescript
|
|
519
|
+
ApiResponse<CheckoutDetails>
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
### Subscription API
|
|
523
|
+
|
|
524
|
+
#### `subscriptionApi.getActiveSubscription(externalId)`
|
|
525
|
+
Get user's active subscription.
|
|
526
|
+
|
|
527
|
+
**Parameters:**
|
|
528
|
+
- `externalId: string` - Customer external ID
|
|
529
|
+
|
|
530
|
+
**Response:**
|
|
531
|
+
```typescript
|
|
532
|
+
ApiResponse<Subscription>
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
#### `subscriptionApi.cancelSubscription(externalId, options?)`
|
|
536
|
+
Cancel user's subscription.
|
|
537
|
+
|
|
538
|
+
**Parameters:**
|
|
539
|
+
- `externalId: string` - Customer external ID
|
|
540
|
+
- `options?: { cancellationMode?: string; cancellationReason?: string }` - Cancellation options
|
|
541
|
+
|
|
542
|
+
**Response:**
|
|
543
|
+
```typescript
|
|
544
|
+
ApiResponse<any>
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
### Customer API
|
|
548
|
+
|
|
549
|
+
#### `customerApi.getCustomer(externalId)`
|
|
550
|
+
Get customer information.
|
|
551
|
+
|
|
552
|
+
**Parameters:**
|
|
553
|
+
- `externalId: string` - Customer external ID
|
|
554
|
+
|
|
555
|
+
**Response:**
|
|
556
|
+
```typescript
|
|
557
|
+
ApiResponse<Customer>
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
### Transaction API
|
|
561
|
+
|
|
562
|
+
#### `transactionApi.getTransactions(externalId, filters?)`
|
|
563
|
+
Get customer's transaction history.
|
|
564
|
+
|
|
565
|
+
**Parameters:**
|
|
566
|
+
- `externalId: string` - Customer external ID
|
|
567
|
+
- `filters?: TransactionFilters` - Optional filters
|
|
568
|
+
|
|
569
|
+
**Filters:**
|
|
570
|
+
```typescript
|
|
571
|
+
interface TransactionFilters {
|
|
572
|
+
startDate?: string; // ISO date string
|
|
573
|
+
endDate?: string; // ISO date string
|
|
574
|
+
status?: string; // Transaction status
|
|
575
|
+
page?: number; // Page number (1-based)
|
|
576
|
+
limit?: number; // Items per page
|
|
577
|
+
}
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
**Response:**
|
|
581
|
+
```typescript
|
|
582
|
+
ApiResponse<PaginatedResponse<Transaction>>
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
#### `transactionApi.getInvoice(transactionId)`
|
|
586
|
+
Get invoice URL for a transaction.
|
|
587
|
+
|
|
588
|
+
**Parameters:**
|
|
589
|
+
- `transactionId: string` - Transaction ID
|
|
590
|
+
|
|
591
|
+
**Response:**
|
|
592
|
+
```typescript
|
|
593
|
+
ApiResponse<{ invoiceUrl: string }>
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
---
|
|
597
|
+
|
|
598
|
+
## 🛠 Utility Functions
|
|
599
|
+
|
|
600
|
+
### Plan Utilities
|
|
601
|
+
|
|
602
|
+
- `getPlanFeatures(plan: Plan): string[]` - Extract features from plan
|
|
603
|
+
- `getCandidateUnits(plans: Plan[]): string[]` - Get unique plan units
|
|
604
|
+
- `getUniqueCandidateUnits(plans: Plan[]): string[]` - Get unique candidate units
|
|
605
|
+
- `getDropdownOptions(plans: Plan[]): DropdownOption[]` - Generate dropdown options
|
|
606
|
+
- `getCurrentSelectionText(filter: string, options: DropdownOption[]): string` - Get current filter text
|
|
607
|
+
- `filterPlansByBillingCycle(plans: Plan[], cycle: 'monthly' | 'yearly'): Plan[]` - Filter by billing cycle
|
|
608
|
+
- `filterPlansByTier(plans: Plan[], tier: string): Plan[]` - Filter by tier
|
|
609
|
+
- `isPlanPopular(plan: Plan): boolean` - Check if plan is marked as popular
|
|
610
|
+
- `getPlanDescription(plan: Plan): string` - Get plan description
|
|
611
|
+
- `formatDate(date: string): string` - Format date string
|
|
612
|
+
|
|
613
|
+
---
|
|
614
|
+
|
|
615
|
+
## 📝 TypeScript Types
|
|
616
|
+
|
|
617
|
+
### Core Types
|
|
618
|
+
|
|
619
|
+
```typescript
|
|
620
|
+
interface Plan {
|
|
621
|
+
id: string;
|
|
622
|
+
name: string;
|
|
623
|
+
code: string;
|
|
624
|
+
fixedCost: number;
|
|
625
|
+
paymentMode: string;
|
|
626
|
+
interval: string;
|
|
627
|
+
successRedirectUrl: string;
|
|
628
|
+
order: number;
|
|
629
|
+
isDefault: boolean;
|
|
630
|
+
intervalCount: number;
|
|
631
|
+
projectId: string;
|
|
632
|
+
charges: any[];
|
|
633
|
+
description?: string;
|
|
634
|
+
price?: number;
|
|
635
|
+
billingFrequency?: 'monthly' | 'yearly' | 'one-time';
|
|
636
|
+
features?: string[];
|
|
637
|
+
isPopular?: boolean;
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
interface Subscription {
|
|
641
|
+
id: string;
|
|
642
|
+
isActive: boolean;
|
|
643
|
+
membershipDate: string;
|
|
644
|
+
expiryDate: string;
|
|
645
|
+
meta: Record<string, any>;
|
|
646
|
+
isPaymentFailed?: boolean;
|
|
647
|
+
transactionCode?: string;
|
|
648
|
+
usage: Record<string, any>;
|
|
649
|
+
plan: {
|
|
650
|
+
name: string;
|
|
651
|
+
code: string;
|
|
652
|
+
fixedCost: number;
|
|
653
|
+
paymentMode: string;
|
|
654
|
+
interval: string;
|
|
655
|
+
trialDays?: number;
|
|
656
|
+
charges: Array<{
|
|
657
|
+
billableMetric: {
|
|
658
|
+
code: string;
|
|
659
|
+
name: string;
|
|
660
|
+
};
|
|
661
|
+
chargeModel: string;
|
|
662
|
+
properties: Record<string, any>;
|
|
663
|
+
}>;
|
|
664
|
+
charge: number;
|
|
665
|
+
canceledOn: string | null;
|
|
666
|
+
features?: string[];
|
|
667
|
+
};
|
|
668
|
+
tax?: number;
|
|
669
|
+
amount?: number;
|
|
670
|
+
customer?: {
|
|
671
|
+
paymentMethodCurrency: string;
|
|
672
|
+
paymentMethodId?: string;
|
|
673
|
+
};
|
|
674
|
+
gracePeriodEndDate?: string;
|
|
675
|
+
remainingGracePeriodDays?: number;
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
interface Transaction {
|
|
679
|
+
id: string;
|
|
680
|
+
transactionCode?: string;
|
|
681
|
+
customerId?: string;
|
|
682
|
+
membershipId?: string;
|
|
683
|
+
purchaseId?: string;
|
|
684
|
+
amount: string | number;
|
|
685
|
+
tax?: number;
|
|
686
|
+
charge?: string | number;
|
|
687
|
+
membershipDate: string;
|
|
688
|
+
expiryDate: string;
|
|
689
|
+
transactionDate?: string;
|
|
690
|
+
transactionStatus: string;
|
|
691
|
+
paymentGateway?: string;
|
|
692
|
+
planName?: string;
|
|
693
|
+
planInterval?: string;
|
|
694
|
+
currency?: string;
|
|
695
|
+
coupon?: string | null;
|
|
696
|
+
discountAmt?: string | number;
|
|
697
|
+
isPlanActive?: boolean;
|
|
698
|
+
order?: number;
|
|
699
|
+
meta?: Record<string, any>;
|
|
700
|
+
invoiceUrl?: string;
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
interface ApiResponse<T> {
|
|
704
|
+
success: boolean;
|
|
705
|
+
data?: T;
|
|
706
|
+
error?: string;
|
|
707
|
+
}
|
|
708
|
+
```
|
|
709
|
+
|
|
710
|
+
---
|
|
711
|
+
|
|
712
|
+
## 🚀 Complete Usage Example
|
|
713
|
+
|
|
714
|
+
```jsx
|
|
715
|
+
import React from 'react';
|
|
716
|
+
import {
|
|
717
|
+
configureSubOS,
|
|
718
|
+
PlanSelector,
|
|
719
|
+
SubscriptionDetails,
|
|
720
|
+
TransactionList,
|
|
721
|
+
usePlans,
|
|
722
|
+
useSubscription,
|
|
723
|
+
useTransactions
|
|
724
|
+
} from 'subos-frontend';
|
|
725
|
+
import 'subos-frontend/style.css';
|
|
726
|
+
|
|
727
|
+
// Configure SubOS
|
|
728
|
+
configureSubOS({
|
|
729
|
+
apiEndpoint: 'https://api.example.com/v1',
|
|
730
|
+
projectId: 'your-project-id',
|
|
731
|
+
stripePublishableKey: 'pk_test_...',
|
|
732
|
+
appName: 'My SaaS App'
|
|
733
|
+
});
|
|
734
|
+
|
|
735
|
+
function SubscriptionApp() {
|
|
736
|
+
const { selectedPlan, handlePlanSelect } = usePlans();
|
|
737
|
+
const { subscription } = useSubscription();
|
|
738
|
+
const { transactions } = useTransactions({
|
|
739
|
+
externalId: 'customer-123'
|
|
740
|
+
});
|
|
741
|
+
|
|
742
|
+
return (
|
|
743
|
+
<div className="app">
|
|
744
|
+
<h1>Subscription Management</h1>
|
|
745
|
+
|
|
746
|
+
{/* Plan Selection */}
|
|
747
|
+
<section>
|
|
748
|
+
<h2>Choose Your Plan</h2>
|
|
749
|
+
<PlanSelector onPlanSelect={handlePlanSelect} />
|
|
750
|
+
</section>
|
|
751
|
+
|
|
752
|
+
{/* Current Subscription */}
|
|
753
|
+
{subscription && (
|
|
754
|
+
<section>
|
|
755
|
+
<h2>Current Subscription</h2>
|
|
756
|
+
<SubscriptionDetails
|
|
757
|
+
subscription={subscription}
|
|
758
|
+
showActions={true}
|
|
759
|
+
/>
|
|
760
|
+
</section>
|
|
761
|
+
)}
|
|
762
|
+
|
|
763
|
+
{/* Transaction History */}
|
|
764
|
+
<section>
|
|
765
|
+
<h2>Transaction History</h2>
|
|
766
|
+
<TransactionList externalId="customer-123" />
|
|
767
|
+
</section>
|
|
768
|
+
</div>
|
|
769
|
+
);
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
export default SubscriptionApp;
|
|
773
|
+
```
|
|
774
|
+
|
|
775
|
+
---
|
|
776
|
+
|
|
777
|
+
## 🔧 Configuration Options
|
|
778
|
+
|
|
779
|
+
### Environment Variables
|
|
780
|
+
```bash
|
|
781
|
+
VITE_API_ENDPOINT=https://your-api.com/api/v1
|
|
782
|
+
VITE_PROJECT_ID=your-project-id
|
|
783
|
+
VITE_STRIPE_PUBLISHABLE_KEY=pk_test_your_stripe_key
|
|
784
|
+
VITE_APP_NAME=Your App Name
|
|
785
|
+
VITE_APP_ENVIRONMENT=production
|
|
786
|
+
```
|
|
787
|
+
|
|
788
|
+
### Runtime Configuration
|
|
789
|
+
```javascript
|
|
790
|
+
configureSubOS({
|
|
791
|
+
apiEndpoint: string; // Required: API base URL
|
|
792
|
+
projectId: string; // Required: Project identifier
|
|
793
|
+
stripePublishableKey: string; // Required: Stripe publishable key
|
|
794
|
+
appName?: string; // Optional: Application name
|
|
795
|
+
appEnvironment?: string; // Optional: Environment (development/production)
|
|
796
|
+
});
|
|
797
|
+
```
|
|
798
|
+
|
|
799
|
+
---
|
|
800
|
+
|
|
801
|
+
## 📋 Requirements
|
|
802
|
+
|
|
803
|
+
- **React**: >=18
|
|
804
|
+
- **React DOM**: >=18
|
|
805
|
+
- **React Router DOM**: >=6
|
|
806
|
+
- **Stripe**: @stripe/react-stripe-js, @stripe/stripe-js
|
|
807
|
+
|
|
808
|
+
---
|
|
809
|
+
|
|
810
|
+
## 🎨 Styling
|
|
811
|
+
|
|
812
|
+
The package includes pre-built CSS that should be imported:
|
|
813
|
+
|
|
814
|
+
```javascript
|
|
815
|
+
import 'subos-frontend/style.css';
|
|
816
|
+
```
|
|
817
|
+
|
|
818
|
+
Components use Tailwind CSS classes and can be customized by overriding the CSS variables or classes.
|
|
819
|
+
|
|
820
|
+
---
|
|
821
|
+
|
|
822
|
+
This documentation provides a complete reference for integrating and using the SubOS Frontend package in your React applications. Each component and hook is designed to work independently or together to create a complete subscription management experience.
|