@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import ' package:mc_common_app/classes/app_state.dart ' ;
import ' package:mc_common_app/extensions/int_extensions.dart ' ;
import ' package:mc_common_app/extensions/string_extensions.dart ' ;
import ' package:mc_common_app/generated/locale_keys.g.dart ' ;
import ' package:mc_common_app/models/general_models/generic_resp_model.dart ' ;
import ' package:mc_common_app/models/subscriptions_models/branch_user_selection_model.dart ' ;
import ' package:mc_common_app/models/subscriptions_models/subscription_model.dart ' ;
@ -15,6 +16,7 @@ import 'package:mc_common_app/views/payments/payment_methods_view.dart';
import ' package:mc_common_app/widgets/button/show_fill_button.dart ' ;
import ' package:mc_common_app/widgets/extensions/extensions_widget.dart ' ;
import ' package:provider/provider.dart ' ;
import ' package:easy_localization/easy_localization.dart ' ;
class DowngradeDataSheet extends StatefulWidget {
final Subscription subscription ;
@ -32,8 +34,65 @@ class _DowngradeDataSheetState extends State<DowngradeDataSheet> {
context . read < SubscriptionsVM > ( ) . getSPBranchUserGet ( ) ;
}
/ / The provider ' s current active plan (not the plan being downgraded to) holds how many
/ / branches / sub - users they currently have - - confirmed with the user this is where
/ / " current totals " come from , as opposed to widget . subscription which is the target plan .
Subscription ? get _currentSubscription {
final list = AppState ( ) . getproviderSubscription ;
return list . isEmpty ? null : list . first ;
}
/ / subscriptionBranches / subscriptionSubUsers are each plan ' s own allowed quota.
/ / totalBranches / totalSubUsers looked plausible but turned out to be unrelated ( they
/ / read identically on both the current and target plan records in testing ) .
int get _currentBranches = > _currentSubscription ? . subscriptionBranches ? ? 0 ;
int get _currentUsers = > _currentSubscription ? . subscriptionSubUsers ? ? 0 ;
int get _targetBranches = > widget . subscription . subscriptionBranches ? ? 0 ;
int get _targetUsers = > widget . subscription . subscriptionSubUsers ? ? 0 ;
int get _branchesToRemove = > ( _currentBranches - _targetBranches ) . clamp ( 0 , _currentBranches ) ;
int get _usersToRemove = > ( _currentUsers - _targetUsers ) . clamp ( 0 , _currentUsers ) ;
/ / Selecting a whole branch removes every user in it too , so that counts towards the
/ / user quota as well , not just the branch quota .
_SelectedCounts _selectedCounts ( List < BranchSelectionModel > branchSelectionList ) {
int selectedBranches = 0 ;
int selectedUsers = 0 ;
for ( var branch in branchSelectionList ) {
if ( branch . isSelected ) {
selectedBranches + + ;
selectedUsers + = branch . usersList . length ;
} else {
selectedUsers + = branch . usersList . where ( ( u ) = > u . isSelected ) . length ;
}
}
return _SelectedCounts ( selectedBranches , selectedUsers ) ;
}
Widget _buildRequirementCounter ( List < BranchSelectionModel > branchSelectionList ) {
final counts = _selectedCounts ( branchSelectionList ) ;
final remainingBranches = ( _branchesToRemove - counts . branches ) . clamp ( 0 , _branchesToRemove ) ;
final remainingUsers = ( _usersToRemove - counts . users ) . clamp ( 0 , _usersToRemove ) ;
if ( remainingBranches = = 0 & & remainingUsers = = 0 ) {
return " You have selected enough branches/users to downgrade. " . toText ( fontSize: 13 , color: MyColors . primaryColor , isBold: true ) ;
}
final parts = < String > [
if ( remainingBranches > 0 ) " $ remainingBranches more branch ${ remainingBranches = = 1 ? ' ' : ' es ' } " ,
if ( remainingUsers > 0 ) " $ remainingUsers more user ${ remainingUsers = = 1 ? ' ' : ' s ' } " ,
] ;
return " Select ${ parts . join ( ' and ' ) } to downgrade. " . toText ( fontSize: 13 , color: MyColors . textColor , isBold: true ) ;
}
@ override
Widget build ( BuildContext context ) {
final targetBranchesText = " $ _targetBranches branch ${ _targetBranches = = 1 ? ' ' : ' es ' } " ;
final targetUsersText = " $ _targetUsers sub-user ${ _targetUsers = = 1 ? ' ' : ' s ' } " ;
return SizedBox (
width: double . infinity ,
height: MediaQuery . of ( context ) . size . height / 1.2 ,
@ -49,19 +108,44 @@ class _DowngradeDataSheetState extends State<DowngradeDataSheet> {
isBold: true ,
) ,
8. height ,
" To select this subscription you need to deactivate your branches and users as this package only supports 1 branch and 2 users per branch. You can reactivate these branches later after upgrading the package "
. toText (
LocaleKeys . downgradeDeactivateInstruction . tr ( namedArgs: { ' branches ' : targetBranchesText , ' users ' : targetUsersText } ) . toText (
fontSize: 14 ,
color: MyColors . textColor ,
) ,
12. height ,
/ / isStartNow is passed as false for a downgrade , so the new package isn ' t
/ / applied immediately - - it takes effect once the current one expires . Make
/ / that explicit so it isn ' t mistaken for an immediate switch.
Row (
crossAxisAlignment: CrossAxisAlignment . start ,
children: [
const Icon ( Icons . info_outline_rounded , size: 18 , color: MyColors . textColor ) ,
8. width ,
Expanded (
child: LocaleKeys . downgradeAppliedAfterExpiry . tr ( ) . toText ( fontSize: 13 , color: MyColors . textColor ) ,
) ,
] ,
) . toContainer (
backgroundColor: MyColors . greyButtonColor ,
paddingAll: 10 ,
borderRadius: 6 ,
) ,
] ,
) ,
) ,
Expanded (
child: Consumer < SubscriptionsVM > (
builder: ( BuildContext context , model , Widget ? child ) {
final counts = model . branchSelectionList = = null ? _SelectedCounts ( 0 , 0 ) : _selectedCounts ( model . branchSelectionList ! ) ;
final canProceed = model . branchSelectionList ! = null & & counts . branches > = _branchesToRemove & & counts . users > = _usersToRemove ;
return Column (
children: [
if ( model . branchSelectionList ! = null )
Padding (
padding: const EdgeInsets . symmetric ( horizontal: 12 ) ,
child: _buildRequirementCounter ( model . branchSelectionList ! ) ,
) ,
if ( model . branchSelectionList ! = null ) 8. height ,
Expanded (
child: model . branchSelectionList = = null
? const Center ( child: CircularProgressIndicator ( ) )
@ -77,19 +161,23 @@ class _DowngradeDataSheetState extends State<DowngradeDataSheet> {
) ,
) ,
ShowFillButton (
title: " Next " ,
title: LocaleKeys . next . tr ( ) ,
maxWidth: double . infinity ,
margin: const EdgeInsets . all ( 12 ) ,
isDisabled: ! canProceed ,
onPressed: ( ) async {
List < int > listOfBranches = [ ] ;
List < int > listOfUsers = [ ] ;
for ( var element in model . branchSelectionList ! ) {
if ( element . isSelected ) {
listOfBranches . add ( element . branchId ) ;
for ( var branch in model . branchSelectionList ! ) {
if ( branch . isSelected ) {
listOfBranches . add ( branch . branchId ) ;
for ( var user in branch . usersList ) {
listOfUsers . add ( user . userId ) ;
}
} else {
for ( var element in element . usersList ) {
if ( element . isSelected ) {
listOfUsers . add ( element . userId ) ;
for ( var user in branch . usersList ) {
if ( user . isSelected ) {
listOfUsers . add ( user . userId ) ;
}
}
}
@ -103,7 +191,7 @@ class _DowngradeDataSheetState extends State<DowngradeDataSheet> {
Utils . showLoading ( context ) ;
GenericRespModel response = await model . payForSubscription (
subscriptionId: widget . subscription . id ! ,
isStartNow: tru e,
isStartNow: fals e,
isRenew: false ,
amount: widget . subscription . price . toString ( ) ,
isDegrade: true ,
@ -152,15 +240,21 @@ class _DowngradeDataSheetState extends State<DowngradeDataSheet> {
crossAxisAlignment: CrossAxisAlignment . start ,
mainAxisSize: MainAxisSize . min ,
children: [
customCheckBox ( model . isSelected ) . onPress ( ( ) {
/ / Padding around the checkbox widens its tap target ( 18 x18 alone is too small to
/ / hit reliably ) without growing the checkbox ' s own visual size or changing the
/ / row ' s separate tap-to-expand behavior.
Padding (
padding: const EdgeInsets . all ( 10 ) ,
child: customCheckBox ( model . isSelected ) ,
) . onPress ( ( ) {
model . isSelected = ! model . isSelected ;
if ( model . isSelected ) {
for ( var element in model . usersList ) {
element . isSelected = true ;
for ( var user in model . usersList ) {
user . isSelected = true ;
}
} else {
for ( var element in model . usersList ) {
element . isSelected = false ;
for ( var user in model . usersList ) {
user . isSelected = false ;
}
}
model . isOpend = true ;
@ -265,3 +359,10 @@ class _DowngradeDataSheetState extends State<DowngradeDataSheet> {
) ;
}
}
class _SelectedCounts {
final int branches ;
final int users ;
_SelectedCounts ( this . branches , this . users ) ;
}