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:
pradeepkumar
2026-03-15 00:57:14 +05:30
parent d5a92e0b94
commit 84e9cd9680
5 changed files with 99 additions and 70 deletions

View File

@@ -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);