Skip to content

Commit 3272453

Browse files
committed
refactor(app_configuration): implement dynamic tabbed interface for saved headlines filters limit
- Replace static form fields with a dynamic tabbed interface - Introduce TabController and map AppUserRole to tabs - Refactor TextEditingController implementation to use a map - Abstract logic for getting and updating saved filters limit by role - Improve code maintainability and extensibility for different user roles
1 parent 2573bcb commit 3272453

File tree

1 file changed

+111
-99
lines changed

1 file changed

+111
-99
lines changed

lib/app_configuration/widgets/saved_headlines_filters_limit_form.dart

Lines changed: 111 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import 'package:core/core.dart';
22
import 'package:flutter/material.dart';
33
import 'package:flutter_news_app_web_dashboard_full_source_code/app_configuration/widgets/app_config_form_fields.dart';
44
import 'package:flutter_news_app_web_dashboard_full_source_code/l10n/l10n.dart';
5+
import 'package:flutter_news_app_web_dashboard_full_source_code/shared/extensions/app_user_role_l10n.dart';
6+
import 'package:ui_kit/ui_kit.dart';
57

68
/// {@template saved_headlines_filters_limit_form}
79
/// A form for configuring saved headlines filter limits within the
@@ -30,14 +32,18 @@ class SavedHeadlinesFiltersLimitForm extends StatefulWidget {
3032
}
3133

3234
class _SavedHeadlinesFiltersLimitFormState
33-
extends State<SavedHeadlinesFiltersLimitForm> {
34-
late final TextEditingController _guestController;
35-
late final TextEditingController _standardController;
36-
late final TextEditingController _premiumController;
35+
extends State<SavedHeadlinesFiltersLimitForm>
36+
with SingleTickerProviderStateMixin {
37+
late TabController _tabController;
38+
late final Map<AppUserRole, TextEditingController> _controllers;
3739

3840
@override
3941
void initState() {
4042
super.initState();
43+
_tabController = TabController(
44+
length: AppUserRole.values.length,
45+
vsync: this,
46+
);
4147
_initializeControllers();
4248
}
4349

@@ -46,125 +52,131 @@ class _SavedHeadlinesFiltersLimitFormState
4652
super.didUpdateWidget(oldWidget);
4753
if (widget.remoteConfig.userPreferenceConfig !=
4854
oldWidget.remoteConfig.userPreferenceConfig) {
49-
_updateControllers();
55+
_updateControllerValues();
5056
}
5157
}
5258

5359
void _initializeControllers() {
54-
final config = widget.remoteConfig.userPreferenceConfig;
55-
_guestController =
56-
TextEditingController(
57-
text: config.guestSavedFiltersLimit.toString(),
58-
)
59-
..selection = TextSelection.collapsed(
60-
offset: config.guestSavedFiltersLimit.toString().length,
61-
);
62-
_standardController =
63-
TextEditingController(
64-
text: config.authenticatedSavedFiltersLimit.toString(),
65-
)
66-
..selection = TextSelection.collapsed(
67-
offset: config.authenticatedSavedFiltersLimit.toString().length,
68-
);
69-
_premiumController =
70-
TextEditingController(
71-
text: config.premiumSavedFiltersLimit.toString(),
72-
)
73-
..selection = TextSelection.collapsed(
74-
offset: config.premiumSavedFiltersLimit.toString().length,
75-
);
60+
_controllers = {
61+
for (final role in AppUserRole.values)
62+
role: TextEditingController(
63+
text: _getSavedFiltersLimit(
64+
widget.remoteConfig.userPreferenceConfig,
65+
role,
66+
).toString(),
67+
)..selection = TextSelection.collapsed(
68+
offset: _getSavedFiltersLimit(
69+
widget.remoteConfig.userPreferenceConfig,
70+
role,
71+
).toString().length,
72+
),
73+
};
7674
}
7775

78-
void _updateControllers() {
79-
final config = widget.remoteConfig.userPreferenceConfig;
80-
81-
final newGuestValue = config.guestSavedFiltersLimit.toString();
82-
if (_guestController.text != newGuestValue) {
83-
_guestController.text = newGuestValue;
84-
_guestController.selection = TextSelection.collapsed(
85-
offset: newGuestValue.length,
86-
);
87-
}
88-
89-
final newStandardValue = config.authenticatedSavedFiltersLimit.toString();
90-
if (_standardController.text != newStandardValue) {
91-
_standardController.text = newStandardValue;
92-
_standardController.selection = TextSelection.collapsed(
93-
offset: newStandardValue.length,
94-
);
95-
}
96-
97-
final newPremiumValue = config.premiumSavedFiltersLimit.toString();
98-
if (_premiumController.text != newPremiumValue) {
99-
_premiumController.text = newPremiumValue;
100-
_premiumController.selection = TextSelection.collapsed(
101-
offset: newPremiumValue.length,
102-
);
76+
void _updateControllerValues() {
77+
for (final role in AppUserRole.values) {
78+
final newLimit = _getSavedFiltersLimit(
79+
widget.remoteConfig.userPreferenceConfig,
80+
role,
81+
).toString();
82+
if (_controllers[role]?.text != newLimit) {
83+
_controllers[role]?.text = newLimit;
84+
_controllers[role]?.selection = TextSelection.collapsed(
85+
offset: newLimit.length,
86+
);
87+
}
10388
}
10489
}
10590

10691
@override
10792
void dispose() {
108-
_guestController.dispose();
109-
_standardController.dispose();
110-
_premiumController.dispose();
93+
_tabController.dispose();
94+
for (final controller in _controllers.values) {
95+
controller.dispose();
96+
}
11197
super.dispose();
11298
}
11399

114100
@override
115101
Widget build(BuildContext context) {
116102
final l10n = AppLocalizationsX(context).l10n;
117-
final userPreferenceConfig = widget.remoteConfig.userPreferenceConfig;
118103

119104
return Column(
120105
crossAxisAlignment: CrossAxisAlignment.start,
121106
children: [
122-
AppConfigIntField(
123-
label: l10n.savedHeadlinesFilterLimitsTitle,
124-
description: l10n.savedHeadlinesFilterLimitsTitle,
125-
value: userPreferenceConfig.guestSavedFiltersLimit,
126-
onChanged: (newLimit) {
127-
widget.onConfigChanged(
128-
widget.remoteConfig.copyWith(
129-
userPreferenceConfig: userPreferenceConfig.copyWith(
130-
guestSavedFiltersLimit: newLimit,
131-
),
132-
),
133-
);
134-
},
135-
controller: _guestController,
107+
Align(
108+
alignment: AlignmentDirectional.centerStart,
109+
child: SizedBox(
110+
height: kTextTabBarHeight,
111+
child: TabBar(
112+
controller: _tabController,
113+
tabAlignment: TabAlignment.start,
114+
isScrollable: true,
115+
tabs: AppUserRole.values
116+
.map((role) => Tab(text: role.l10n(context)))
117+
.toList(),
118+
),
119+
),
136120
),
137-
AppConfigIntField(
138-
label: l10n.savedHeadlinesFilterLimitsTitle,
139-
description: l10n.savedHeadlinesFilterLimitsTitle,
140-
value: userPreferenceConfig.authenticatedSavedFiltersLimit,
141-
onChanged: (newLimit) {
142-
widget.onConfigChanged(
143-
widget.remoteConfig.copyWith(
144-
userPreferenceConfig: userPreferenceConfig.copyWith(
145-
authenticatedSavedFiltersLimit: newLimit,
146-
),
147-
),
148-
);
149-
},
150-
controller: _standardController,
151-
),
152-
AppConfigIntField(
153-
label: l10n.savedHeadlinesFilterLimitsTitle,
154-
description: l10n.savedHeadlinesFilterLimitsTitle,
155-
value: userPreferenceConfig.premiumSavedFiltersLimit,
156-
onChanged: (newLimit) {
157-
widget.onConfigChanged(
158-
widget.remoteConfig.copyWith(
159-
userPreferenceConfig: userPreferenceConfig.copyWith(
160-
premiumSavedFiltersLimit: newLimit,
161-
),
162-
),
163-
);
164-
},
165-
controller: _premiumController,
121+
const SizedBox(height: AppSpacing.lg),
122+
SizedBox(
123+
height: 120,
124+
child: TabBarView(
125+
controller: _tabController,
126+
children: AppUserRole.values.map((role) {
127+
final config = widget.remoteConfig.userPreferenceConfig;
128+
return AppConfigIntField(
129+
label: l10n.savedHeadlinesLimitLabel,
130+
description: l10n.savedHeadlinesLimitDescription,
131+
value: _getSavedFiltersLimit(config, role),
132+
onChanged: (value) {
133+
widget.onConfigChanged(
134+
widget.remoteConfig.copyWith(
135+
userPreferenceConfig:
136+
_updateSavedFiltersLimit(config, value, role),
137+
),
138+
);
139+
},
140+
controller: _controllers[role],
141+
);
142+
}).toList(),
143+
),
166144
),
167145
],
168146
);
169147
}
148+
149+
/// Retrieves the saved filters limit for a given [AppUserRole].
150+
///
151+
/// This helper method abstracts the logic for accessing the correct limit
152+
/// from the [UserPreferenceConfig] based on the provided [role].
153+
int _getSavedFiltersLimit(UserPreferenceConfig config, AppUserRole role) {
154+
switch (role) {
155+
case AppUserRole.guestUser:
156+
return config.guestSavedFiltersLimit;
157+
case AppUserRole.standardUser:
158+
return config.authenticatedSavedFiltersLimit;
159+
case AppUserRole.premiumUser:
160+
return config.premiumSavedFiltersLimit;
161+
}
162+
}
163+
164+
/// Updates the saved filters limit for a given [AppUserRole].
165+
///
166+
/// This helper method abstracts the logic for updating the correct limit
167+
/// within the [UserPreferenceConfig] based on the provided [role] and [value].
168+
UserPreferenceConfig _updateSavedFiltersLimit(
169+
UserPreferenceConfig config,
170+
int value,
171+
AppUserRole role,
172+
) {
173+
switch (role) {
174+
case AppUserRole.guestUser:
175+
return config.copyWith(guestSavedFiltersLimit: value);
176+
case AppUserRole.standardUser:
177+
return config.copyWith(authenticatedSavedFiltersLimit: value);
178+
case AppUserRole.premiumUser:
179+
return config.copyWith(premiumSavedFiltersLimit: value);
180+
}
181+
}
170182
}

0 commit comments

Comments
 (0)