feat: Enhance billing display with currency formatting, improve dynamic form field management by clearing cached controllers and using unique keys, and add mailto URL scheme support.
This commit is contained in:
@@ -173,7 +173,7 @@ class _BillingTabState extends ConsumerState<BillingTab> {
|
||||
text: TextSpan(
|
||||
children: [
|
||||
TextSpan(
|
||||
text: '\$${plan!['amount']}',
|
||||
text: '\$${_formatAmount(plan!['amount'])}',
|
||||
style: const TextStyle(
|
||||
fontFamily: 'Fractul',
|
||||
fontSize: 35,
|
||||
@@ -340,25 +340,24 @@ class _BillingTabState extends ConsumerState<BillingTab> {
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 155,
|
||||
height: 43,
|
||||
child: ElevatedButton(
|
||||
onPressed: _startCheckout,
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: AppColors.accentOrange,
|
||||
side: const BorderSide(color: AppColors.accentOrange),
|
||||
padding: EdgeInsets.zero,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(15)),
|
||||
),
|
||||
child: const Text('Get Premium Access',
|
||||
style: TextStyle(
|
||||
fontFamily: 'Fractul',
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: Colors.white)),
|
||||
ElevatedButton(
|
||||
onPressed: _startCheckout,
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: AppColors.accentOrange,
|
||||
side: const BorderSide(color: AppColors.accentOrange),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 20, vertical: 12),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(15)),
|
||||
),
|
||||
child: const Text('Get Premium Access',
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontFamily: 'Fractul',
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: Colors.white)),
|
||||
),
|
||||
const Spacer(),
|
||||
ClipRRect(
|
||||
@@ -556,7 +555,7 @@ class _BillingTabState extends ConsumerState<BillingTab> {
|
||||
final repo = ref.read(profileRepositoryProvider);
|
||||
final url = await repo.createPortalSession();
|
||||
if (!mounted) return;
|
||||
await Navigator.of(context).push<Map<String, dynamic>?>(
|
||||
await Navigator.of(context, rootNavigator: true).push<Map<String, dynamic>?>(
|
||||
MaterialPageRoute(
|
||||
builder: (_) => StripeCheckoutScreen(
|
||||
url: url,
|
||||
@@ -583,7 +582,7 @@ class _BillingTabState extends ConsumerState<BillingTab> {
|
||||
final planId = plans.first['id'] as String;
|
||||
final url = await repo.createCheckoutSession(planId);
|
||||
if (!mounted) return;
|
||||
final result = await Navigator.of(context).push<Map<String, dynamic>?>(
|
||||
final result = await Navigator.of(context, rootNavigator: true).push<Map<String, dynamic>?>(
|
||||
MaterialPageRoute(
|
||||
builder: (_) => StripeCheckoutScreen(
|
||||
url: url,
|
||||
@@ -643,6 +642,16 @@ class _BillingTabState extends ConsumerState<BillingTab> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Stripe amounts are in cents — convert to dollars.
|
||||
String _formatAmount(dynamic amount) {
|
||||
final cents = amount is num ? amount : num.tryParse('$amount') ?? 0;
|
||||
final dollars = cents / 100;
|
||||
// Show whole dollars if no cents, otherwise 2 decimal places
|
||||
return dollars == dollars.roundToDouble()
|
||||
? dollars.toInt().toString()
|
||||
: dollars.toStringAsFixed(2);
|
||||
}
|
||||
|
||||
String _formatDate(String dateStr) {
|
||||
try {
|
||||
final date = DateTime.parse(dateStr);
|
||||
|
||||
Reference in New Issue
Block a user