diff --git a/lib/navigation/backoffice_navigator.dart b/lib/navigation/backoffice_navigator.dart index b3b727f..f2b41e1 100644 --- a/lib/navigation/backoffice_navigator.dart +++ b/lib/navigation/backoffice_navigator.dart @@ -9,6 +9,7 @@ import 'package:client_backoffice/views/settings/external_clients_page.dart'; import 'package:client_backoffice/views/settings/git_integration_page.dart'; import 'package:client_backoffice/views/settings/manage_access_page.dart'; import 'package:client_backoffice/views/settings_page.dart'; +import 'package:client_backoffice/views/subscription_page.dart'; import 'package:client_backoffice/views/welcome_dev_page.dart'; import 'package:client_common/navigator/common_navigator.dart'; import 'package:client_common/navigator/guard.dart'; @@ -147,7 +148,19 @@ class BackofficeNavigator extends CommonNavigator { ), ); }, - routes: [settings], + routes: [settings, subscription], + ); + + static GoRoute subscription = GoRoute( + name: "subscription", + path: "subscription", + pageBuilder: (context, state) { + return NoTransitionPage( + child: SubscriptionPage( + appId: int.parse(state.params["appId"]!), + ), + ); + }, ); static GoRoute selectProject = GoRoute( diff --git a/lib/views/backoffice_drawer.dart b/lib/views/backoffice_drawer.dart index 9e1a43f..94dd13b 100644 --- a/lib/views/backoffice_drawer.dart +++ b/lib/views/backoffice_drawer.dart @@ -203,6 +203,16 @@ class _ProjectMenuState extends State<_ProjectMenu> { selected: false, onPressed: navigateTo(context, null), ), + BackofficeSideMenuRoute( + "Subscription", + icon: Icons.money, + selected: CommonNavigator.isCurrent(context, BackofficeNavigator.subscription), + onPressed: navigateTo( + context, + BackofficeNavigator.subscription, + params: {"appId": selectedApp.id.toString()}, + ), + ), BackofficeSideMenuRoute( "Settings", icon: Icons.settings_outlined, diff --git a/lib/views/subscription_page.dart b/lib/views/subscription_page.dart new file mode 100644 index 0000000..37a4390 --- /dev/null +++ b/lib/views/subscription_page.dart @@ -0,0 +1,165 @@ +import 'package:client_backoffice/views/backoffice_page.dart'; +import 'package:client_common/api/request_models/create_stripe_checkout_request.dart'; +import 'package:client_common/api/request_models/create_stripe_customer_request.dart'; +import 'package:client_common/api/response_models/get_stripe_subscriptions_response.dart'; +import 'package:client_common/api/stripe_api.dart'; +import 'package:flutter/material.dart'; +import 'package:lenra_components/lenra_components.dart'; +import 'package:url_launcher/url_launcher.dart'; + +class SubscriptionPage extends StatefulWidget { + final int appId; + + SubscriptionPage({required this.appId}); + + @override + State createState() => _SubscriptionPageState(); +} + +class _SubscriptionPageState extends State { + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return BackofficePage( + title: 'Subscription', + child: FutureBuilder( + future: StripeApi.createCustomer( + CreateStripeCustomerRequest(email: "jonas@lenra.io"), + ).then((customer) async { + return [customer, await StripeApi.getSubscriptions(widget.appId)]; + }), + builder: (context, snapshot) { + if (!snapshot.hasData) { + return CircularProgressIndicator(); + } + + String customer = snapshot.data?[0] as String? ?? ''; + String? currentPlan = (snapshot.data?[1] as GetStripeSubscriptionsResponse?)?.plan; + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + subcriptionBox( + SubscriptionPlan.month, + customer, + currentPlan, + ), + SizedBox( + width: 32, + ), + subcriptionBox( + SubscriptionPlan.year, + customer, + currentPlan, + ), + ], + ); + }, + ), + ); + } + + Widget subcriptionBox(SubscriptionPlan plan, String customer, String? currentPlan) { + var theme = LenraTheme.of(context); + String title; + String price; + String realPrice; + String per; + + if (plan == SubscriptionPlan.month) { + title = "Monthly"; + price = "4 €"; + realPrice = "8 €"; + per = "month"; + } else { + title = "Yearly"; + price = "40 €"; + realPrice = "80 €"; + per = "year"; + } + + bool isCurrentPlan = (currentPlan != null && currentPlan == plan.name); + bool isNotCurrentPlan = (currentPlan != null && currentPlan != plan.name); + + String buttonText = "Subscribe"; + if (isCurrentPlan) { + buttonText = "Manage"; + } + + return Container( + width: 250, + padding: EdgeInsets.all(16), + decoration: BoxDecoration( + border: Border.all(width: 2, color: Color(0x22000000)), + borderRadius: BorderRadius.circular(8), + ), + child: LenraFlex( + direction: Axis.vertical, + crossAxisAlignment: CrossAxisAlignment.center, + spacing: 8, + children: [ + Text( + title, + style: theme.lenraTextThemeData.headline2, + ), + SizedBox(), + Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.baseline, + textBaseline: TextBaseline.alphabetic, + children: [ + Text( + price, + style: theme.lenraTextThemeData.headline1, + ), + Text( + " / $per", + style: theme.lenraTextThemeData.bodyText, + ), + ], + ), + Text(realPrice, + style: theme.lenraTextThemeData.disabledBodyText.copyWith(decoration: TextDecoration.lineThrough)), + ], + ), + Container( + constraints: BoxConstraints( + maxHeight: 100, + minWidth: double.infinity, + ), + child: LenraButton( + disabled: isNotCurrentPlan, + onPressed: () async { + String? redirectUrl; + if (isCurrentPlan) { + redirectUrl = await StripeApi.getCustomerPortalUrl(); + } else { + redirectUrl = await StripeApi.createCheckout( + CreateStripeCheckoutRequest( + appId: widget.appId, + plan: plan.name, + customer: customer, + successUrl: 'http://localhost:10000/stripe', + cancelUrl: 'http://localhost:10000/stripe', + ), + ); + } + + launchUrl(Uri.parse(redirectUrl)); + }, + text: buttonText, + ), + ), + ], + ), + ); + } +} + +enum SubscriptionPlan { month, year } diff --git a/pubspec.lock b/pubspec.lock index 51ab147..dd07e09 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -94,8 +94,8 @@ packages: dependency: "direct main" description: path: "." - ref: "v1.0.0-beta.45" - resolved-ref: "0b7891871299c854445b30c0dac78553ca6a3005" + ref: "v1.0.0-beta.48" + resolved-ref: "6959b0a98ae0995f6295b751cc5c4594430aee46" url: "https://github.com/lenra-io/client-common.git" source: git version: "1.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index 1568156..59eec09 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -28,7 +28,7 @@ dependencies: client_common: git: url: https://github.com/lenra-io/client-common.git - ref: v1.0.0-beta.45 + ref: v1.0.0-beta.48 url_launcher: ^6.1.2 logging: ^1.0.2 provider: ^6.0.1