docs: update subscription feature documentation - M7 (refs #55)
Some checks failed
Deploy to Staging / Build Images (pull_request) Successful in 6m58s
Deploy to Staging / Deploy to Staging (pull_request) Successful in 28s
Deploy to Staging / Verify Staging (pull_request) Failing after 17s
Deploy to Staging / Notify Staging Ready (pull_request) Has been skipped
Deploy to Staging / Notify Staging Failure (pull_request) Successful in 6s
Some checks failed
Deploy to Staging / Build Images (pull_request) Successful in 6m58s
Deploy to Staging / Deploy to Staging (pull_request) Successful in 28s
Deploy to Staging / Verify Staging (pull_request) Failing after 17s
Deploy to Staging / Notify Staging Ready (pull_request) Has been skipped
Deploy to Staging / Notify Staging Failure (pull_request) Successful in 6s
This commit is contained in:
55
backend/src/features/subscriptions/CLAUDE.md
Normal file
55
backend/src/features/subscriptions/CLAUDE.md
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
# backend/src/features/subscriptions/
|
||||||
|
|
||||||
|
Stripe payment integration for subscription tiers and donations.
|
||||||
|
|
||||||
|
## Files
|
||||||
|
|
||||||
|
| File | What | When to read |
|
||||||
|
| ---- | ---- | ------------ |
|
||||||
|
| `README.md` | Feature overview with architecture diagram | Understanding subscription flow |
|
||||||
|
|
||||||
|
## Subdirectories
|
||||||
|
|
||||||
|
| Directory | What | When to read |
|
||||||
|
| --------- | ---- | ------------ |
|
||||||
|
| `api/` | HTTP controllers and routes | API endpoint changes |
|
||||||
|
| `domain/` | Services and type definitions | Business logic changes |
|
||||||
|
| `data/` | Repository for database operations | Database queries |
|
||||||
|
| `external/stripe/` | Stripe API client wrapper | Stripe integration |
|
||||||
|
| `migrations/` | Database schema | Schema changes |
|
||||||
|
| `jobs/` | Scheduled background jobs | Grace period processing |
|
||||||
|
|
||||||
|
## Key Patterns
|
||||||
|
|
||||||
|
- Repository mapRow() converts snake_case to camelCase
|
||||||
|
- Webhook idempotency via stripe_event_id unique constraint
|
||||||
|
- Tier sync to user_profiles.subscription_tier on changes
|
||||||
|
- Grace period: 30 days after payment failure
|
||||||
|
- Vehicle selections for tier downgrades (not deleted, just gated)
|
||||||
|
|
||||||
|
## API Endpoints
|
||||||
|
|
||||||
|
### Subscriptions (Authenticated)
|
||||||
|
- GET /api/subscriptions - Current subscription
|
||||||
|
- POST /api/subscriptions/checkout - Create subscription
|
||||||
|
- POST /api/subscriptions/cancel - Schedule cancellation
|
||||||
|
- POST /api/subscriptions/reactivate - Cancel pending cancellation
|
||||||
|
- POST /api/subscriptions/downgrade - Downgrade with vehicle selection
|
||||||
|
- PUT /api/subscriptions/payment-method - Update payment
|
||||||
|
- GET /api/subscriptions/invoices - Billing history
|
||||||
|
|
||||||
|
### Donations (Authenticated)
|
||||||
|
- POST /api/donations - Create payment intent
|
||||||
|
- GET /api/donations - Donation history
|
||||||
|
|
||||||
|
### Webhooks (Public)
|
||||||
|
- POST /api/webhooks/stripe - Stripe webhook (signature verified)
|
||||||
|
|
||||||
|
## Environment Variables
|
||||||
|
|
||||||
|
- STRIPE_SECRET_KEY
|
||||||
|
- STRIPE_WEBHOOK_SECRET
|
||||||
|
- STRIPE_PRO_MONTHLY_PRICE_ID
|
||||||
|
- STRIPE_PRO_YEARLY_PRICE_ID
|
||||||
|
- STRIPE_ENTERPRISE_MONTHLY_PRICE_ID
|
||||||
|
- STRIPE_ENTERPRISE_YEARLY_PRICE_ID
|
||||||
@@ -2,104 +2,181 @@
|
|||||||
|
|
||||||
Stripe integration for subscription management, donations, and tier-based vehicle limits.
|
Stripe integration for subscription management, donations, and tier-based vehicle limits.
|
||||||
|
|
||||||
## Milestone 1: Core Infrastructure (COMPLETE)
|
## Architecture
|
||||||
|
|
||||||
### Database Schema
|
```
|
||||||
- `subscriptions` - User subscription records with Stripe integration
|
┌─────────────────────────────────────────────────────────────────┐
|
||||||
- `subscription_events` - Webhook event logging for idempotency
|
│ Frontend (React) │
|
||||||
- `donations` - One-time payment tracking
|
│ SubscriptionPage / SubscriptionMobileScreen │
|
||||||
- `tier_vehicle_selections` - User vehicle selections during tier downgrades
|
│ - TierCard, PaymentMethodForm, BillingHistory │
|
||||||
|
│ - VehicleSelectionDialog, DowngradeFlow, DonationSection │
|
||||||
|
└──────────────────────────┬──────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
┌──────────────────────────▼──────────────────────────────────────┐
|
||||||
|
│ Backend API │
|
||||||
|
│ /api/subscriptions/* - Subscription management │
|
||||||
|
│ /api/donations/* - One-time donations │
|
||||||
|
│ /api/webhooks/stripe - Stripe webhook (public) │
|
||||||
|
└──────────────────────────┬──────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
┌─────────────────┼─────────────────┐
|
||||||
|
▼ ▼ ▼
|
||||||
|
┌─────────────────┐ ┌────────────┐ ┌─────────────────┐
|
||||||
|
│ Subscriptions │ │ Stripe │ │ User Profile │
|
||||||
|
│ Service │ │ Client │ │ Repository │
|
||||||
|
│ │ │ │ │ (tier sync) │
|
||||||
|
└────────┬────────┘ └─────┬──────┘ └─────────────────┘
|
||||||
|
│ │
|
||||||
|
▼ ▼
|
||||||
|
┌─────────────────┐ ┌────────────┐
|
||||||
|
│ Subscriptions │ │ Stripe │
|
||||||
|
│ Repository │ │ API │
|
||||||
|
└────────┬────────┘ └────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────────────────────────────┐
|
||||||
|
│ PostgreSQL │
|
||||||
|
│ subscriptions, subscription_events, donations, │
|
||||||
|
│ tier_vehicle_selections │
|
||||||
|
└─────────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
### Type Definitions
|
## Database Schema
|
||||||
- **Domain Types** (`domain/subscriptions.types.ts`): Core business entities and request/response types
|
|
||||||
- **Stripe Types** (`external/stripe/stripe.types.ts`): Simplified Stripe API response types
|
|
||||||
|
|
||||||
### Data Access
|
### subscriptions
|
||||||
- **Repository** (`data/subscriptions.repository.ts`): Database operations with proper snake_case to camelCase mapping
|
Main subscription data linked to user profile.
|
||||||
- Subscription CRUD operations
|
| Column | Type | Description |
|
||||||
- Event logging with idempotency checks
|
|--------|------|-------------|
|
||||||
- Donation tracking
|
| id | UUID | Primary key |
|
||||||
- Vehicle selection management
|
| user_id | VARCHAR(255) | FK to user_profiles.auth0_sub |
|
||||||
|
| stripe_customer_id | VARCHAR(255) | Stripe customer ID |
|
||||||
|
| stripe_subscription_id | VARCHAR(255) | Stripe subscription ID (nullable for free) |
|
||||||
|
| tier | subscription_tier | free, pro, enterprise |
|
||||||
|
| billing_cycle | billing_cycle | monthly, yearly |
|
||||||
|
| status | subscription_status | active, past_due, canceled, unpaid |
|
||||||
|
| current_period_start | TIMESTAMP | Billing period start |
|
||||||
|
| current_period_end | TIMESTAMP | Billing period end |
|
||||||
|
| grace_period_end | TIMESTAMP | Grace period expiry (30 days after payment failure) |
|
||||||
|
| cancel_at_period_end | BOOLEAN | Pending cancellation flag |
|
||||||
|
|
||||||
### External Integration
|
### subscription_events
|
||||||
- **Stripe Client** (`external/stripe/stripe.client.ts`): Stripe API wrapper with error handling
|
Webhook event log for idempotency.
|
||||||
- Customer creation
|
| Column | Type | Description |
|
||||||
- Subscription lifecycle management
|
|--------|------|-------------|
|
||||||
- Payment intent creation for donations
|
| id | UUID | Primary key |
|
||||||
- Webhook event verification
|
| subscription_id | UUID | FK to subscriptions |
|
||||||
- Payment method updates
|
| stripe_event_id | VARCHAR(255) | UNIQUE, prevents duplicate processing |
|
||||||
|
| event_type | VARCHAR(100) | Stripe event type |
|
||||||
|
| payload | JSONB | Full event payload |
|
||||||
|
|
||||||
## Environment Variables
|
### donations
|
||||||
|
One-time payment records.
|
||||||
|
| Column | Type | Description |
|
||||||
|
|--------|------|-------------|
|
||||||
|
| id | UUID | Primary key |
|
||||||
|
| user_id | VARCHAR(255) | FK to user_profiles.auth0_sub |
|
||||||
|
| stripe_payment_intent_id | VARCHAR(255) | UNIQUE |
|
||||||
|
| amount_cents | INTEGER | Amount in cents |
|
||||||
|
| currency | VARCHAR(3) | Currency code (default: usd) |
|
||||||
|
| status | donation_status | pending, succeeded, failed, canceled |
|
||||||
|
|
||||||
Required for Stripe integration:
|
### tier_vehicle_selections
|
||||||
- `STRIPE_SECRET_KEY` - Stripe API secret key
|
Tracks which vehicles user selected to keep during tier downgrade.
|
||||||
- `STRIPE_WEBHOOK_SECRET` - Stripe webhook signing secret
|
| Column | Type | Description |
|
||||||
|
|--------|------|-------------|
|
||||||
|
| id | UUID | Primary key |
|
||||||
|
| user_id | VARCHAR(255) | FK to user_profiles.auth0_sub |
|
||||||
|
| vehicle_id | UUID | FK to vehicles |
|
||||||
|
| selected_at | TIMESTAMP | Selection timestamp |
|
||||||
|
|
||||||
|
## API Endpoints
|
||||||
|
|
||||||
|
### Subscription Management (Authenticated)
|
||||||
|
| Method | Endpoint | Description |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| GET | /api/subscriptions | Get current subscription |
|
||||||
|
| POST | /api/subscriptions/checkout | Create Stripe subscription |
|
||||||
|
| POST | /api/subscriptions/cancel | Schedule cancellation at period end |
|
||||||
|
| POST | /api/subscriptions/reactivate | Cancel pending cancellation |
|
||||||
|
| POST | /api/subscriptions/downgrade | Downgrade with vehicle selection |
|
||||||
|
| PUT | /api/subscriptions/payment-method | Update payment method |
|
||||||
|
| GET | /api/subscriptions/invoices | Get billing history |
|
||||||
|
|
||||||
|
### Donations (Authenticated)
|
||||||
|
| Method | Endpoint | Description |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| POST | /api/donations | Create donation payment intent |
|
||||||
|
| GET | /api/donations | Get donation history |
|
||||||
|
|
||||||
|
### Webhooks (Public)
|
||||||
|
| Method | Endpoint | Description |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| POST | /api/webhooks/stripe | Stripe webhook (signature verified) |
|
||||||
|
|
||||||
|
## Webhook Events Handled
|
||||||
|
|
||||||
|
| Event | Action |
|
||||||
|
|-------|--------|
|
||||||
|
| customer.subscription.created | Update subscription with Stripe subscription ID |
|
||||||
|
| customer.subscription.updated | Sync status, tier, period dates |
|
||||||
|
| customer.subscription.deleted | Mark canceled, downgrade to free tier |
|
||||||
|
| invoice.payment_succeeded | Clear grace period, mark active |
|
||||||
|
| invoice.payment_failed | Set 30-day grace period |
|
||||||
|
| payment_intent.succeeded | Mark donation as succeeded |
|
||||||
|
|
||||||
## Subscription Tiers
|
## Subscription Tiers
|
||||||
|
|
||||||
Defined in `user_profiles.subscription_tier` enum:
|
| Tier | Price | Vehicle Limit | Features |
|
||||||
- `free` - Limited features (default)
|
|------|-------|---------------|----------|
|
||||||
- `pro` - Enhanced features
|
| Free | $0 | 2 | Basic tracking, standard reports |
|
||||||
- `enterprise` - Full features
|
| Pro | $1.99/mo or $19.99/yr | 5 | VIN decoding, OCR, API access |
|
||||||
|
| Enterprise | $4.99/mo or $49.99/yr | Unlimited | All features, priority support |
|
||||||
|
|
||||||
## Billing Cycles
|
## Grace Period
|
||||||
|
|
||||||
- `monthly` - Monthly billing
|
When payment fails:
|
||||||
- `yearly` - Annual billing
|
1. Subscription status set to `past_due`
|
||||||
|
2. Grace period set to 30 days from failure
|
||||||
|
3. Email notifications sent: immediate, day 23, day 29
|
||||||
|
4. Daily job at 2:30 AM checks expired grace periods
|
||||||
|
5. Expired subscriptions downgraded to free tier
|
||||||
|
|
||||||
## Subscription Status
|
## Downgrade Flow
|
||||||
|
|
||||||
- `active` - Subscription is active
|
When user downgrades to a tier with fewer vehicle allowance:
|
||||||
- `past_due` - Payment failed, in grace period
|
1. Check if current vehicle count > target tier limit
|
||||||
- `canceled` - Subscription canceled
|
2. If yes, show VehicleSelectionDialog
|
||||||
- `unpaid` - Payment failed, grace period expired
|
3. User selects which vehicles to keep
|
||||||
|
4. Unselected vehicles become tier-gated (hidden, not deleted)
|
||||||
|
5. Selections saved to tier_vehicle_selections table
|
||||||
|
6. On upgrade, all vehicles become accessible again
|
||||||
|
|
||||||
## Milestone 2: Service Layer + Webhook Endpoint (COMPLETE)
|
## Environment Variables
|
||||||
|
|
||||||
### Service Layer
|
```
|
||||||
- **SubscriptionsService** (`domain/subscriptions.service.ts`): Business logic for subscription management
|
STRIPE_SECRET_KEY=sk_live_...
|
||||||
- Get current subscription for user
|
STRIPE_WEBHOOK_SECRET=whsec_...
|
||||||
- Create new subscription (Stripe customer + free tier record)
|
STRIPE_PRO_MONTHLY_PRICE_ID=price_...
|
||||||
- Upgrade subscription (create Stripe subscription with payment method)
|
STRIPE_PRO_YEARLY_PRICE_ID=price_...
|
||||||
- Cancel subscription (schedule for end of period)
|
STRIPE_ENTERPRISE_MONTHLY_PRICE_ID=price_...
|
||||||
- Reactivate subscription (remove pending cancellation)
|
STRIPE_ENTERPRISE_YEARLY_PRICE_ID=price_...
|
||||||
- Handle Stripe webhook events with idempotency
|
|
||||||
|
|
||||||
### Webhook Processing
|
|
||||||
- **Webhook Events Handled**:
|
|
||||||
- `customer.subscription.created` - Update subscription record with Stripe subscription ID
|
|
||||||
- `customer.subscription.updated` - Update status, tier, period dates
|
|
||||||
- `customer.subscription.deleted` - Mark as canceled, downgrade to free tier
|
|
||||||
- `invoice.payment_succeeded` - Clear grace period, mark active
|
|
||||||
- `invoice.payment_failed` - Set 30-day grace period
|
|
||||||
|
|
||||||
### API Endpoints
|
|
||||||
- **WebhooksController** (`api/webhooks.controller.ts`): Webhook event handler
|
|
||||||
- **Routes** (`api/webhooks.routes.ts`): PUBLIC endpoint with rawBody support
|
|
||||||
- POST /api/webhooks/stripe - Stripe webhook receiver (no JWT auth, signature verified)
|
|
||||||
|
|
||||||
### Integration
|
|
||||||
- Syncs subscription tier changes to `user_profiles.subscription_tier` via UserProfileRepository
|
|
||||||
- Uses environment variables for Stripe price IDs (PRO/ENTERPRISE, MONTHLY/YEARLY)
|
|
||||||
|
|
||||||
## Next Steps (Future Milestones)
|
|
||||||
|
|
||||||
- M3: API endpoints for subscription management (user-facing CRUD)
|
|
||||||
- M4: Frontend integration and subscription UI
|
|
||||||
- M5: Testing and documentation
|
|
||||||
|
|
||||||
## Database Migration
|
|
||||||
|
|
||||||
Run migrations:
|
|
||||||
```bash
|
|
||||||
npm run migrate:feature subscriptions
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Architecture Notes
|
## Files
|
||||||
|
|
||||||
- All database columns use snake_case
|
| File | Purpose |
|
||||||
- All TypeScript properties use camelCase
|
|------|---------|
|
||||||
- Repository `mapRow()` methods handle case conversion
|
| migrations/001_subscriptions_tables.sql | Database schema |
|
||||||
- Prepared statements used for all queries (no string concatenation)
|
| domain/subscriptions.types.ts | TypeScript interfaces |
|
||||||
- Comprehensive error logging with structured logger
|
| domain/subscriptions.service.ts | Business logic |
|
||||||
- Webhook idempotency via `stripe_event_id` unique constraint
|
| domain/donations.service.ts | Donation logic |
|
||||||
|
| data/subscriptions.repository.ts | Database operations |
|
||||||
|
| external/stripe/stripe.client.ts | Stripe API wrapper |
|
||||||
|
| external/stripe/stripe.types.ts | Stripe type definitions |
|
||||||
|
| api/subscriptions.controller.ts | HTTP handlers |
|
||||||
|
| api/subscriptions.routes.ts | Authenticated routes |
|
||||||
|
| api/donations.controller.ts | Donation handlers |
|
||||||
|
| api/donations.routes.ts | Donation routes |
|
||||||
|
| api/webhooks.controller.ts | Webhook handler |
|
||||||
|
| api/webhooks.routes.ts | Public webhook endpoint |
|
||||||
|
| jobs/grace-period.job.ts | Daily grace period expiration job |
|
||||||
|
|||||||
@@ -4,20 +4,21 @@ Frontend UI for subscription management with Stripe integration.
|
|||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
Provides subscription tier management, payment method updates, and billing history viewing.
|
Provides subscription tier management, payment method updates, billing history, donations, and vehicle selection during downgrade flow.
|
||||||
|
|
||||||
## Components
|
## Components
|
||||||
|
|
||||||
### TierCard
|
### TierCard
|
||||||
Displays subscription plan with:
|
Subscription plan display with:
|
||||||
- Plan name and pricing (monthly/yearly)
|
- Plan name and pricing (monthly/yearly toggle)
|
||||||
- Feature list
|
- Feature list
|
||||||
- Current plan indicator
|
- Current plan indicator
|
||||||
- Upgrade/downgrade button
|
- Upgrade/downgrade button
|
||||||
|
|
||||||
### PaymentMethodForm
|
### PaymentMethodForm
|
||||||
Stripe Elements integration for:
|
Stripe Elements integration for:
|
||||||
- Credit card input with validation
|
- Credit card input with CardElement
|
||||||
|
- Real-time validation
|
||||||
- Payment method creation
|
- Payment method creation
|
||||||
- Error handling
|
- Error handling
|
||||||
|
|
||||||
@@ -27,85 +28,130 @@ Invoice list with:
|
|||||||
- PDF download links
|
- PDF download links
|
||||||
- MUI Table component
|
- MUI Table component
|
||||||
|
|
||||||
|
### VehicleSelectionDialog
|
||||||
|
Vehicle selection during downgrade:
|
||||||
|
- Checkbox list for each vehicle
|
||||||
|
- Counter showing selected vs allowed
|
||||||
|
- Warning about tier-gated vehicles
|
||||||
|
- Validation preventing over-selection
|
||||||
|
|
||||||
|
### DowngradeFlow
|
||||||
|
Orchestrates downgrade process:
|
||||||
|
- Checks vehicle count vs target tier limit
|
||||||
|
- Shows VehicleSelectionDialog if needed
|
||||||
|
- Submits vehicle selections to backend
|
||||||
|
|
||||||
|
### DonationSection / DonationSectionMobile
|
||||||
|
One-time donation form:
|
||||||
|
- Free-form amount input (no presets)
|
||||||
|
- $0.50 minimum (Stripe limit)
|
||||||
|
- Stripe CardElement for payment
|
||||||
|
- Donation history table
|
||||||
|
- Success feedback
|
||||||
|
|
||||||
## Pages
|
## Pages
|
||||||
|
|
||||||
### SubscriptionPage (Desktop)
|
### SubscriptionPage (Desktop)
|
||||||
- Current plan card with status
|
MUI-based layout:
|
||||||
- Three-column tier cards layout
|
- Current plan card with status badges
|
||||||
- Payment method section
|
- Three-column tier comparison
|
||||||
|
- Monthly/yearly toggle
|
||||||
|
- Payment method modal
|
||||||
- Billing history table
|
- Billing history table
|
||||||
- Material-UI components
|
- Donation section
|
||||||
|
|
||||||
### SubscriptionMobileScreen (Mobile)
|
### SubscriptionMobileScreen (Mobile)
|
||||||
|
Tailwind-based layout:
|
||||||
|
- GlassCard styling
|
||||||
- Stacked card layout
|
- Stacked card layout
|
||||||
- Touch-friendly buttons (44px min)
|
- Touch-friendly buttons (44px min)
|
||||||
- Tailwind styling
|
- Modal payment forms
|
||||||
- GlassCard components
|
|
||||||
|
|
||||||
## API Integration
|
## API Integration
|
||||||
|
|
||||||
All endpoints are in `/subscriptions`:
|
### Subscriptions
|
||||||
- GET `/subscriptions` - Current subscription
|
| Endpoint | Method | Hook |
|
||||||
- POST `/subscriptions/checkout` - Upgrade subscription
|
|----------|--------|------|
|
||||||
- POST `/subscriptions/cancel` - Cancel subscription
|
| /api/subscriptions | GET | useSubscription() |
|
||||||
- POST `/subscriptions/reactivate` - Reactivate subscription
|
| /api/subscriptions/checkout | POST | useCheckout() |
|
||||||
- PUT `/subscriptions/payment-method` - Update payment method
|
| /api/subscriptions/cancel | POST | useCancelSubscription() |
|
||||||
- GET `/subscriptions/invoices` - Invoice history
|
| /api/subscriptions/reactivate | POST | useReactivateSubscription() |
|
||||||
|
| /api/subscriptions/downgrade | POST | useDowngrade() |
|
||||||
|
| /api/subscriptions/payment-method | PUT | useUpdatePaymentMethod() |
|
||||||
|
| /api/subscriptions/invoices | GET | useInvoices() |
|
||||||
|
|
||||||
|
### Donations
|
||||||
|
| Endpoint | Method | Hook |
|
||||||
|
|----------|--------|------|
|
||||||
|
| /api/donations | POST | useCreateDonation() |
|
||||||
|
| /api/donations | GET | useDonations() |
|
||||||
|
|
||||||
## Hooks
|
## Hooks
|
||||||
|
|
||||||
- `useSubscription()` - Fetch current subscription
|
| Hook | Purpose |
|
||||||
- `useCheckout()` - Upgrade subscription
|
|------|---------|
|
||||||
- `useCancelSubscription()` - Cancel subscription
|
| useSubscription() | Fetch current subscription |
|
||||||
- `useReactivateSubscription()` - Reactivate subscription
|
| useCheckout() | Upgrade subscription |
|
||||||
- `useInvoices()` - Fetch invoice history
|
| useCancelSubscription() | Cancel subscription |
|
||||||
|
| useReactivateSubscription() | Reactivate subscription |
|
||||||
|
| useDowngrade() | Downgrade with vehicle selection |
|
||||||
|
| useInvoices() | Fetch billing history |
|
||||||
|
| useCreateDonation() | Create donation payment |
|
||||||
|
| useDonations() | Fetch donation history |
|
||||||
|
|
||||||
## Environment Setup
|
## Environment Variables
|
||||||
|
|
||||||
Required environment variable:
|
|
||||||
```bash
|
```bash
|
||||||
VITE_STRIPE_PUBLISHABLE_KEY=pk_test_...
|
VITE_STRIPE_PUBLISHABLE_KEY=pk_test_...
|
||||||
```
|
```
|
||||||
|
|
||||||
## Subscription Tiers
|
## Subscription Tiers
|
||||||
|
|
||||||
### Free
|
### Free ($0)
|
||||||
- 2 vehicles
|
- 2 vehicles
|
||||||
- Basic tracking
|
- Basic tracking
|
||||||
- Standard reports
|
- Standard reports
|
||||||
- Price: $0
|
|
||||||
|
|
||||||
### Pro
|
### Pro ($1.99/month or $19.99/year)
|
||||||
- Up to 5 vehicles
|
- Up to 5 vehicles
|
||||||
- VIN decoding
|
- VIN decoding
|
||||||
- OCR functionality
|
- OCR functionality
|
||||||
- API access
|
- API access
|
||||||
- Price: $1.99/month or $19.99/year
|
|
||||||
|
|
||||||
### Enterprise
|
### Enterprise ($4.99/month or $49.99/year)
|
||||||
- Unlimited vehicles
|
- Unlimited vehicles
|
||||||
- All Pro features
|
- All Pro features
|
||||||
- Priority support
|
- Priority support
|
||||||
- Price: $4.99/month or $49.99/year
|
|
||||||
|
|
||||||
## Mobile Navigation
|
## Routing
|
||||||
|
|
||||||
Add subscription screen to settings navigation:
|
- Desktop: `/garage/settings/subscription`
|
||||||
```typescript
|
- Mobile: `navigateToScreen('Subscription')`
|
||||||
navigateToScreen('Subscription')
|
|
||||||
```
|
|
||||||
|
|
||||||
## Desktop Routing
|
## Files
|
||||||
|
|
||||||
Route: `/garage/settings/subscription`
|
| File | Purpose |
|
||||||
|
|------|---------|
|
||||||
|
| types/subscription.types.ts | TypeScript interfaces |
|
||||||
|
| api/subscription.api.ts | API client calls |
|
||||||
|
| hooks/useSubscription.ts | React Query hooks |
|
||||||
|
| constants/plans.ts | Tier configuration |
|
||||||
|
| components/TierCard.tsx | Plan display card |
|
||||||
|
| components/PaymentMethodForm.tsx | Stripe Elements form |
|
||||||
|
| components/BillingHistory.tsx | Invoice table |
|
||||||
|
| components/VehicleSelectionDialog.tsx | Vehicle selection modal |
|
||||||
|
| components/DowngradeFlow.tsx | Downgrade orchestrator |
|
||||||
|
| components/DonationSection.tsx | Desktop donation UI |
|
||||||
|
| components/DonationSectionMobile.tsx | Mobile donation UI |
|
||||||
|
| pages/SubscriptionPage.tsx | Desktop page |
|
||||||
|
| mobile/SubscriptionMobileScreen.tsx | Mobile screen |
|
||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
|
|
||||||
Test subscription flow:
|
|
||||||
1. View current plan
|
1. View current plan
|
||||||
2. Toggle monthly/yearly billing
|
2. Toggle monthly/yearly billing
|
||||||
3. Select upgrade tier
|
3. Upgrade: Select tier, enter payment, complete checkout
|
||||||
4. Enter payment method
|
4. Downgrade: Select vehicles to keep if over limit
|
||||||
5. Complete checkout
|
5. Cancel/reactivate subscription
|
||||||
6. Verify subscription update
|
6. Make a donation
|
||||||
7. View billing history
|
7. View billing and donation history
|
||||||
|
|||||||
Reference in New Issue
Block a user