Refactor menu view to use sections and buttons

Extracted menu sections and buttons into separate data structures for better
organization and readability in the menu view. Updated MenuList widget to
dynamically render buttons based on the new data structure.
This commit is contained in:
Mohammad Salameh
2024-04-23 15:11:01 +03:00
parent 5f402d02ea
commit 88588d9fa8
3 changed files with 171 additions and 32 deletions

View File

@ -6,8 +6,10 @@ import 'package:syncrow_app/features/menu/view/widgets/menu_list.dart';
import 'package:syncrow_app/features/menu/view/widgets/profile_tab.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/navigation/routing_constants.dart';
import 'package:syncrow_app/utils/context_extension.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
import 'package:syncrow_app/utils/resource_manager/constants.dart';
class MenuView extends StatelessWidget {
@ -33,11 +35,10 @@ class MenuView extends StatelessWidget {
child: Column(
children: [
const ProfileTab(),
...MenuCubit.of(context).menuLists.map(
(list) => MenuList(
listModel: list,
),
),
for (var section in menuSections)
MenuList(
section: section,
),
const SizedBox(
height: 15,
),
@ -75,3 +76,123 @@ class MenuView extends StatelessWidget {
);
}
}
List<Map<String, Object>> menuSections = [
//Home Management
{
'title': 'Home Management',
'color': ColorsManager.primaryColor,
'buttons': [
{
'title': 'Create a Home',
'Icon': Assets.homeManagementIconsCreateHome,
'page': null
},
{
'title': 'Join a Home',
'Icon': Assets.homeManagementIconsJoinAHome,
'page': null
},
{
'title': 'Manage Your Home',
'Icon': Assets.homeManagementIconsManageYourHome,
'page': null
},
],
},
//General Settings
{
'title': 'General Settings',
'color': const Color(0xFF0030CB),
'buttons': [
{
'title': 'Voice Assistant',
'Icon': Assets.generalSettingsIconsVoiceAssistant,
'page': null
},
{
'title': 'Temperature unit',
'Icon': Assets.generalSettingsIconsTemperatureUnit,
'page': null
},
{
'title': 'Touch tone on panel',
'Icon': Assets.generalSettingsIconsTouchTone,
'page': null
},
{
'title': 'Language',
'Icon': Assets.generalSettingsIconsLanguage,
'page': null
},
{
'title': 'Network Diagnosis',
'Icon': Assets.generalSettingsIconsNetworkDiagnosis,
'page': null
},
{
'title': 'Clear Cache',
'Icon': Assets.generalSettingsIconsClearCache,
'page': null
},
],
},
//Messages Center
{
'title': 'Messages Center',
'color': const Color(0xFF0088FF),
'buttons': [
{
'title': 'Alerts',
'Icon': Assets.messagesCenterIconsAlerts,
'page': null
},
{
'title': 'Messages',
'Icon': Assets.messagesCenterIconsMessages,
'page': null
},
{'title': 'FAQs', 'Icon': Assets.messagesCenterIconsFAQs, 'page': null},
{
'title': 'Help & Feedback',
'Icon': Assets.messagesCenterIconsHelpAndFeedbacks,
'page': null
},
],
},
//Security And Privacy
{
'title': 'Security And Privacy',
'color': const Color(0xFF8AB9FF),
'buttons': [
{
'title': 'Security',
'Icon': Assets.securityAndPrivacyIconsSecurty,
'page': null
},
{
'title': 'Privacy',
'Icon': Assets.securityAndPrivacyIconsPrivacy,
'page': null
},
],
},
//Legal Information
{
'title': 'Legal Information',
'color': const Color(0xFF001B72),
'buttons': [
{'title': 'About', 'Icon': Assets.leagalInfoIconsAbout, 'page': null},
{
'title': 'Privacy Policy',
'Icon': Assets.leagalInfoIconsPrivacyPolicy,
'page': null
},
{
'title': 'User Agreement',
'Icon': Assets.leagalInfoIconsUserAgreement,
'page': null
},
],
},
];

View File

@ -4,14 +4,15 @@ import 'package:syncrow_app/features/menu/view/widgets/menu_list_divider.dart';
import 'package:syncrow_app/features/menu/view/widgets/menu_list_item.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
import 'package:syncrow_app/generated/assets.dart';
class MenuList extends StatelessWidget {
const MenuList({
super.key,
required this.listModel,
required this.section,
});
final MenuListModel listModel;
final Map<String, dynamic> section;
@override
Widget build(BuildContext context) {
@ -20,7 +21,7 @@ class MenuList extends StatelessWidget {
children: [
const SizedBox(height: 5),
BodySmall(
text: listModel.label!,
text: section['title'] as String,
),
const SizedBox(height: 5),
DefaultContainer(
@ -28,10 +29,13 @@ class MenuList extends StatelessWidget {
shrinkWrap: true,
padding: const EdgeInsets.all(0),
physics: const NeverScrollableScrollPhysics(),
itemCount: listModel.listItems!.length,
itemCount: section['buttons'].length,
itemBuilder: (context, index) {
return MenuListItem(
listItem: listModel.listItems![index]!,
title: section['buttons'][index]['title'] as String,
icon: section['buttons'][index]['Icon'] as String,
page: section['buttons'][index]['page'] as Widget?,
color: section['color'],
);
},
separatorBuilder: (context, index) => const MenuListDivider()),

View File

@ -1,43 +1,57 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_app/features/menu/model/list_item_model.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class MenuListItem extends StatelessWidget {
const MenuListItem({
super.key,
required this.listItem,
required this.title,
required this.icon,
required this.page,
required this.color,
});
final ListItemModel listItem;
final String title;
final String icon;
final Widget? page;
final Color color;
@override
Widget build(BuildContext context) {
return Column(
children: [
Row(
children: [
Container(
return InkWell(
onTap: () {
if (page == null) {
return;
}
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) => page!));
},
child: Row(
children: [
Container(
margin: const EdgeInsets.only(right: 10),
height: 33,
width: 33,
decoration: BoxDecoration(
color: ColorsManager.primaryColor,
color: color,
borderRadius: BorderRadius.circular(15),
),
child: listItem.icon != null
? SvgPicture.asset(
listItem.icon!,
)
: null,
),
BodyMedium(
text: listItem.label!,
)
],
),
],
child: Center(
child: SizedBox.square(
dimension: 15,
child: SvgPicture.asset(
icon,
width: 15,
height: 15,
fit: BoxFit.contain,
),
),
)),
BodyMedium(
text: title,
)
],
),
);
}
}