Skip to content

Commit

Permalink
Paid Apps handling and creation on the mobile side (#1513)
Browse files Browse the repository at this point in the history
- [x] Add the paid/free and $ per month configuration to the app creator
page and backend update
- [x] Display $ per month instead of "Install App"
- [x] Show $ per month in the app list
- [x] Navigate to the Stripe payment link to make a payment.
Automatically check the payment status every 3-5 seconds, only when the
user clicks the Stripe link ($/month)

Part of #1404 



https://github.com/user-attachments/assets/451832e9-35ca-48be-b836-39f31d1571a9
  • Loading branch information
beastoin authored Dec 10, 2024
2 parents fa0ed6c + 00dd772 commit 1075891
Show file tree
Hide file tree
Showing 12 changed files with 1,467 additions and 892 deletions.
18 changes: 18 additions & 0 deletions app/lib/backend/http/api/apps.dart
Original file line number Diff line number Diff line change
Expand Up @@ -340,3 +340,21 @@ Future<Map<String, dynamic>?> getAppDetailsServer(String appId) async {
return null;
}
}

Future<List<PaymentPlan>> getPaymentPlansServer() async {
var response = await makeApiCall(
url: '${Env.apiBaseUrl}v1/app/payment-plans',
headers: {},
body: '',
method: 'GET',
);
try {
if (response == null || response.statusCode != 200) return [];
log('getPaymentPlansServer: ${response.body}');
return PaymentPlan.fromJsonList(jsonDecode(response.body));
} catch (e, stackTrace) {
debugPrint(e.toString());
CrashReporting.reportHandledCrash(e, stackTrace);
return [];
}
}
59 changes: 59 additions & 0 deletions app/lib/backend/schema/app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,11 @@ class App {
bool deleted;
int? usageCount;
double? moneyMade;
bool isPaid;
String? paymentPlan;
double? price;
bool isUserPaid;
String? paymentLink;

App({
required this.id,
Expand Down Expand Up @@ -211,6 +216,11 @@ class App {
this.proactiveNotification,
this.usageCount,
this.moneyMade,
required this.isPaid,
this.paymentPlan,
this.price,
required this.isUserPaid,
this.paymentLink,
});

String? getRatingAvg() => ratingAvg?.toStringAsFixed(1);
Expand Down Expand Up @@ -253,9 +263,25 @@ class App {
: null,
usageCount: json['usage_count'] ?? 0,
moneyMade: json['money_made'] ?? 0.0,
isPaid: json['is_paid'] ?? false,
paymentPlan: json['payment_plan'],
price: json['price'] ?? 0.0,
isUserPaid: json['is_user_paid'] ?? false,
paymentLink: json['payment_link'],
);
}

String getFormattedPrice() {
if (price == null) {
return 'Free';
}
if (paymentPlan == 'monthly_recurring') {
return '\$${price!} per month';
} else {
return '\$${price!}';
}
}

String getImageUrl() {
if (image.startsWith('http')) {
return image;
Expand Down Expand Up @@ -319,6 +345,11 @@ class App {
'proactive_notification': proactiveNotification?.toJson(),
'usage_count': usageCount,
'money_made': moneyMade,
'is_paid': isPaid,
'payment_plan': paymentPlan,
'price': price,
'is_user_paid': isUserPaid,
'payment_link': paymentLink,
};
}

Expand Down Expand Up @@ -470,3 +501,31 @@ class ProactiveNotification {
};
}
}

class PaymentPlan {
final String title;
final String id;

PaymentPlan({
required this.title,
required this.id,
});

factory PaymentPlan.fromJson(Map<String, dynamic> json) {
return PaymentPlan(
title: json['title'],
id: json['id'],
);
}

toJson() {
return {
'title': title,
'id': id,
};
}

static List<PaymentPlan> fromJsonList(List<dynamic> jsonList) {
return jsonList.map((e) => PaymentPlan.fromJson(e)).toList();
}
}
386 changes: 200 additions & 186 deletions app/lib/pages/apps/add_app.dart

Large diffs are not rendered by default.

Loading

0 comments on commit 1075891

Please sign in to comment.