MotorSignal-App/lib/features/settings/widgets/current_plan_card.dart

241 lines
8.9 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:url_launcher/url_launcher.dart';
import '../../../services/billing/product_catalog.dart';
import '../../../services/entitlements/entitlement_providers.dart';
import '../../../services/entitlements/entitlement_state.dart';
import '../../entitlements/widgets/pro_lock_badge.dart';
/// Reusable card displaying the current plan and subscription management options.
/// Used in both Classic Settings and Evolution Settings.
class CurrentPlanCard extends ConsumerWidget {
final bool isEvolution;
const CurrentPlanCard({super.key, this.isEvolution = false});
Future<void> _openGooglePlaySubscriptions() async {
// Official Google Play subscription management deep link
final uri = Uri.parse(
'https://play.google.com/store/account/subscriptions?package=app.motorsignal.motorcycle&sku=${ProductCatalog.proMonthly}',
);
try {
if (await canLaunchUrl(uri)) {
await launchUrl(uri, mode: LaunchMode.externalApplication);
}
} catch (_) {}
}
@override
Widget build(BuildContext context, WidgetRef ref) {
final entitlement = ref.watch(entitlementProvider);
final isPro = entitlement.isPro;
final plan = entitlement.plan;
final status = entitlement.status;
String planTitle = 'MotorSignal Free';
String statusSubtitle = 'Basic telemetry & local recording active';
Color badgeColor = Colors.white54;
String badgeText = 'FREE';
if (plan == MotorSignalPlan.proLifetime && isPro) {
planTitle = 'MotorSignal Pro';
statusSubtitle = 'Lifetime access • Permanent ownership';
badgeColor = const Color(0xFF00E5FF);
badgeText = 'LIFETIME';
} else if (plan == MotorSignalPlan.proMonthly) {
planTitle = 'MotorSignal Pro';
badgeColor = const Color(0xFF00E5FF);
badgeText = 'MONTHLY';
switch (status) {
case MotorSignalEntitlementStatus.proMonthlyActive:
statusSubtitle = entitlement.expiresAt != null
? 'Active • Renews ${entitlement.expiresAt!.toLocal().toString().split(' ')[0]}'
: 'Active subscription';
break;
case MotorSignalEntitlementStatus.proMonthlyGrace:
statusSubtitle =
'Payment grace period • Action needed in Google Play';
badgeColor = Colors.amberAccent;
badgeText = 'GRACE PERIOD';
break;
case MotorSignalEntitlementStatus.proMonthlyAccountHold:
statusSubtitle =
'Account on hold • Please update billing in Google Play';
badgeColor = Colors.redAccent;
badgeText = 'ON HOLD';
break;
case MotorSignalEntitlementStatus.proMonthlyPaused:
statusSubtitle = 'Subscription paused by rider in Google Play';
badgeColor = Colors.amberAccent;
badgeText = 'PAUSED';
break;
case MotorSignalEntitlementStatus.proMonthlyExpired:
statusSubtitle = 'Subscription expired';
badgeColor = Colors.white38;
badgeText = 'EXPIRED';
break;
case MotorSignalEntitlementStatus.syncPending:
statusSubtitle = 'Verification pending with Google Play...';
badgeColor = Colors.amberAccent;
badgeText = 'VERIFYING';
break;
default:
statusSubtitle = 'Status: ${status.name}';
break;
}
} else if (status == MotorSignalEntitlementStatus.syncPending) {
statusSubtitle = 'Checking purchases with Google Play...';
badgeColor = Colors.amberAccent;
badgeText = 'PENDING';
}
final isMonthlySub = plan == MotorSignalPlan.proMonthly;
return Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: isEvolution ? const Color(0xFF0D0D0D) : null,
borderRadius: BorderRadius.circular(isEvolution ? 16 : 12),
border: Border.all(
color: isPro
? const Color(0xFF00E5FF).withValues(alpha: 0.6)
: (isEvolution ? const Color(0xFF1F1F1F) : Colors.white12),
width: 1.2,
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
Icon(
isPro ? Icons.verified : Icons.shield_outlined,
color: isPro ? const Color(0xFF00E5FF) : Colors.white70,
size: 20,
),
const SizedBox(width: 10),
Text(
planTitle.toUpperCase(),
style: TextStyle(
fontFamily: isEvolution ? 'Sora' : null,
fontSize: 13,
fontWeight: FontWeight.w800,
color: isPro ? const Color(0xFF00E5FF) : Colors.white,
letterSpacing: 0.5,
),
),
if (isPro) ...[const SizedBox(width: 8), const ProBadge()],
],
),
Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3),
decoration: BoxDecoration(
color: badgeColor.withValues(alpha: 0.15),
borderRadius: BorderRadius.circular(6),
border: Border.all(
color: badgeColor.withValues(alpha: 0.5),
width: 0.8,
),
),
child: Text(
badgeText,
style: TextStyle(
fontFamily: 'Inter',
fontSize: 9,
fontWeight: FontWeight.w900,
color: badgeColor,
letterSpacing: 0.5,
),
),
),
],
),
const SizedBox(height: 8),
Text(
statusSubtitle,
style: const TextStyle(
fontSize: 12,
color: Colors.white70,
height: 1.3,
),
),
const SizedBox(height: 16),
Row(
children: [
if (!isPro) ...[
Expanded(
child: ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF00E5FF),
foregroundColor: Colors.black,
padding: const EdgeInsets.symmetric(vertical: 10),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
),
onPressed: () => context.push('/settings/pro'),
child: const Text(
'UPGRADE TO PRO',
style: TextStyle(
fontSize: 11,
fontWeight: FontWeight.w800,
),
),
),
),
const SizedBox(width: 10),
],
if (isMonthlySub) ...[
Expanded(
child: OutlinedButton(
style: OutlinedButton.styleFrom(
foregroundColor: Colors.white70,
side: const BorderSide(color: Colors.white24),
padding: const EdgeInsets.symmetric(vertical: 10),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
),
onPressed: _openGooglePlaySubscriptions,
child: const Text(
'MANAGE SUBSCRIPTION',
style: TextStyle(
fontSize: 11,
fontWeight: FontWeight.bold,
),
),
),
),
const SizedBox(width: 10),
],
OutlinedButton(
style: OutlinedButton.styleFrom(
foregroundColor: Colors.white70,
side: const BorderSide(color: Colors.white24),
padding: const EdgeInsets.symmetric(
vertical: 10,
horizontal: 12,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
),
onPressed: () => context.push('/settings/pro'),
child: Text(
isPro ? 'VIEW PLANS' : 'DETAILS',
style: const TextStyle(fontSize: 11),
),
),
],
),
],
),
);
}
}