committed by
GitHub
43 changed files with 732 additions and 68 deletions
@ -0,0 +1,87 @@ |
|||
import 'package:core/models/common.dart'; |
|||
import 'package:flutter/material.dart'; |
|||
import 'package:get/get.dart'; |
|||
|
|||
class Navigation extends StatefulWidget { |
|||
const Navigation({ |
|||
super.key, |
|||
this.activedMenu, |
|||
this.menus = const [], |
|||
this.onMenuExpanded, |
|||
}); |
|||
|
|||
final List<Menu> menus; |
|||
final String? activedMenu; |
|||
final void Function(Menu menu)? onMenuExpanded; |
|||
|
|||
@override |
|||
State<Navigation> createState() => _NavigationState(); |
|||
} |
|||
|
|||
class _NavigationState extends State<Navigation> { |
|||
@override |
|||
Widget build(BuildContext context) { |
|||
return _renderNavigations(widget.menus); |
|||
} |
|||
|
|||
Widget _renderNavigations(List<Menu> menus) { |
|||
var mainMenus = menus.where((menu) => menu.children?.isNotEmpty == false); |
|||
var subMenus = menus.where((menu) => menu.children?.isNotEmpty == true); |
|||
|
|||
return Column( |
|||
children: [ |
|||
_renderMenus(subMenus.toList()), |
|||
...mainMenus.map((menu) => _buildMenuItem(menu)), |
|||
], |
|||
); |
|||
} |
|||
|
|||
Widget _renderMenus(List<Menu> menus) { |
|||
return ExpansionPanelList.radio( |
|||
initialOpenPanelValue: widget.activedMenu, |
|||
expandedHeaderPadding: const EdgeInsets.all(0), |
|||
expansionCallback: (panelIndex, isExpanded) { |
|||
if (widget.onMenuExpanded != null) { |
|||
widget.onMenuExpanded!(menus[panelIndex]); |
|||
} |
|||
}, |
|||
children: menus.map<ExpansionPanelRadio>((Menu menu) { |
|||
var body = menu.children?.isNotEmpty == true |
|||
? _renderNavigations(menu.children!) |
|||
: _buildMenuItem(menu); |
|||
return ExpansionPanelRadio( |
|||
canTapOnHeader: true, |
|||
headerBuilder: (BuildContext context, bool isExpanded) { |
|||
return SizedBox( |
|||
height: 30, |
|||
child: ListTile( |
|||
title: Text( |
|||
(menu.meta?['displayName']?.toString().tr ?? menu.displayName).padLeft(menu.level * 4)), |
|||
), |
|||
); |
|||
}, |
|||
body: body, |
|||
value: menu.name, |
|||
); |
|||
}).toList(), |
|||
); |
|||
} |
|||
|
|||
Widget _buildMenuItem(Menu menu) { |
|||
return InkWell( |
|||
onTap: () { |
|||
Get.toNamed(menu.path); |
|||
}, |
|||
child: FractionallySizedBox( |
|||
widthFactor: 1, |
|||
child: Container( |
|||
height: 30, |
|||
margin: const EdgeInsets.only(top: 10), |
|||
child: Text( |
|||
(menu.meta?['displayName']?.toString().tr ?? menu.displayName).padLeft(menu.level * 8), |
|||
), |
|||
), |
|||
), |
|||
); |
|||
} |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
class MenuState { |
|||
|
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
import 'dart:ui'; |
|||
|
|||
class ColorUtils { |
|||
static Color fromHex(String hexString) { |
|||
final buffer = StringBuffer(); |
|||
if (hexString.length == 6 || hexString.length == 7) buffer.write('ff'); |
|||
buffer.write(hexString.replaceFirst('#', '')); |
|||
return Color(int.parse(buffer.toString(), radix: 16)); |
|||
} |
|||
} |
|||
|
|||
extension HexStringToColor on String { |
|||
Color toColor() { |
|||
return ColorUtils.fromHex(this); |
|||
} |
|||
} |
|||
@ -0,0 +1 @@ |
|||
export './not_found/index.dart'; |
|||
@ -0,0 +1 @@ |
|||
export 'view.dart'; |
|||
@ -0,0 +1,23 @@ |
|||
import 'package:bruno/bruno.dart'; |
|||
import 'package:flutter/material.dart'; |
|||
import 'package:get/get.dart'; |
|||
|
|||
class PageNotFound extends StatelessWidget { |
|||
const PageNotFound({super.key}); |
|||
|
|||
@override |
|||
Widget build(BuildContext context) { |
|||
return Scaffold( |
|||
appBar: AppBar( |
|||
title: Text("404Message".tr) |
|||
), |
|||
body: BrnAbnormalStateWidget( |
|||
img: Image.asset( |
|||
'res/images/no_data.png', |
|||
scale: 3.0, |
|||
), |
|||
content: "404MessageDetail".tr, |
|||
), |
|||
); |
|||
} |
|||
} |
|||
@ -1,10 +1,38 @@ |
|||
import 'package:core/models/common.dart'; |
|||
import 'package:notifications/models/common.dart'; |
|||
import 'package:platforms/modes/menu.dto.dart'; |
|||
|
|||
class HomeState { |
|||
HomeState({ |
|||
this.activedMenu, |
|||
this.menus = const [], |
|||
this.favoriteMenus = const [], |
|||
this.notifications = const [], |
|||
}); |
|||
String? activedMenu; |
|||
List<MenuDto> menus; |
|||
List<UserFavoriteMenuDto> favoriteMenus; |
|||
List<NotificationPaylod> notifications; |
|||
|
|||
List<Menu> getMenus() => _buildTreeRecursive(menus, null, 0); |
|||
|
|||
List<Menu> _buildTreeRecursive(List<MenuDto> treeMenus, String? parentId, int level) { |
|||
List<Menu> results = []; |
|||
var tempList = treeMenus.where((menu) => menu.parentId == parentId).toList(); |
|||
for (int i = 0; i < tempList.length; i++) { |
|||
var menu = Menu( |
|||
id: tempList[i].id.hashCode, |
|||
path: tempList[i].path, |
|||
name: tempList[i].name, |
|||
displayName: tempList[i].displayName, |
|||
description: tempList[i].description, |
|||
redirect: tempList[i].redirect, |
|||
meta: tempList[i].meta, |
|||
level: level + 1 |
|||
); |
|||
menu.children = _buildTreeRecursive(treeMenus, tempList[i].id, menu.level); |
|||
results.add(menu); |
|||
} |
|||
return results; |
|||
} |
|||
} |
|||
@ -0,0 +1,5 @@ |
|||
export 'search.dart'; |
|||
export 'menu_drawer.dart'; |
|||
export 'my_favorite.dart'; |
|||
export 'notification_bar.dart'; |
|||
export 'quick_navigation.dart'; |
|||
@ -0,0 +1,76 @@ |
|||
import 'package:components/widgets/menu/index.dart'; |
|||
import 'package:core/models/common.dart'; |
|||
import 'package:flutter/material.dart'; |
|||
|
|||
class MenuDrawer extends StatelessWidget { |
|||
const MenuDrawer({ |
|||
super.key, |
|||
this.activedMenu, |
|||
this.menus = const [], |
|||
required this.onMenuRefresh, |
|||
this.onMenuExpanded, |
|||
}); |
|||
|
|||
final String? activedMenu; |
|||
final List<Menu> menus; |
|||
final void Function(Menu menu)? onMenuExpanded; |
|||
final Future<void> Function() onMenuRefresh; |
|||
|
|||
@override |
|||
Widget build(BuildContext context) { |
|||
return RefreshIndicator( |
|||
onRefresh: onMenuRefresh, |
|||
child: Drawer( |
|||
width: 260, |
|||
child: Column( |
|||
children: [ |
|||
_buildLogo(), |
|||
Expanded( |
|||
child: SingleChildScrollView( |
|||
physics: const AlwaysScrollableScrollPhysics(), |
|||
child: Column( |
|||
children: [ |
|||
Navigation( |
|||
activedMenu: activedMenu, |
|||
menus: menus, |
|||
onMenuExpanded: onMenuExpanded, |
|||
), |
|||
], |
|||
), |
|||
) |
|||
), |
|||
], |
|||
), |
|||
), |
|||
); |
|||
} |
|||
|
|||
Widget _buildLogo() { |
|||
return Container( |
|||
height: 24, |
|||
margin: const EdgeInsets.all(10), |
|||
child: Row( |
|||
children: [ |
|||
Padding( |
|||
padding: const EdgeInsets.only(left: 10), |
|||
child: Image.asset( |
|||
'res/images/logo.png', |
|||
height: 20, |
|||
width: 20, |
|||
), |
|||
), |
|||
const Padding( |
|||
padding: EdgeInsets.only(left: 10), |
|||
child: Text( |
|||
'abp flutter', |
|||
style: TextStyle( |
|||
fontSize: 20, |
|||
fontWeight: FontWeight.w400, |
|||
), |
|||
), |
|||
), |
|||
], |
|||
), |
|||
); |
|||
} |
|||
} |
|||
@ -0,0 +1,42 @@ |
|||
import 'package:components/widgets/empty/index.dart'; |
|||
import 'package:flutter/material.dart'; |
|||
import 'package:get/get.dart'; |
|||
import 'package:platforms/modes/menu.dto.dart'; |
|||
|
|||
class MyFavorite extends StatelessWidget { |
|||
const MyFavorite({ |
|||
super.key, |
|||
required this.favoriteMenus, |
|||
required this.favoriteMenuBuilder, |
|||
}); |
|||
|
|||
final List<UserFavoriteMenuDto> favoriteMenus; |
|||
final Widget Function(UserFavoriteMenuDto favoriteMenu) favoriteMenuBuilder; |
|||
|
|||
@override |
|||
Widget build(BuildContext context) { |
|||
return ExpansionTile( |
|||
initiallyExpanded: true, |
|||
title: Text('Label:MyFavorite'.tr, |
|||
style: Theme.of(context).textTheme.titleMedium, |
|||
), |
|||
children: [ |
|||
GridView.builder( |
|||
shrinkWrap: true, |
|||
physics: const NeverScrollableScrollPhysics(), |
|||
itemCount: favoriteMenus.length, |
|||
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( |
|||
crossAxisCount: 4, |
|||
crossAxisSpacing: 5, |
|||
), |
|||
itemBuilder: (BuildContext context, int index) { |
|||
if (index >= favoriteMenus.length) { |
|||
return Empty.none; |
|||
} |
|||
return favoriteMenuBuilder(favoriteMenus[index]); |
|||
}, |
|||
), |
|||
], |
|||
); |
|||
} |
|||
} |
|||
@ -0,0 +1,55 @@ |
|||
import 'package:bruno/bruno.dart'; |
|||
import 'package:components/widgets/empty/index.dart'; |
|||
import 'package:flutter/material.dart'; |
|||
import 'package:notifications/models/common.dart'; |
|||
import 'package:notifications/models/notification.dart'; |
|||
|
|||
class NotificationBar extends StatelessWidget { |
|||
const NotificationBar({ |
|||
super.key, |
|||
required this.notifications |
|||
}); |
|||
|
|||
final List<NotificationPaylod> notifications; |
|||
|
|||
@override |
|||
Widget build(BuildContext context) { |
|||
if (notifications.isEmpty) { |
|||
return Empty.none; |
|||
} |
|||
return SizedBox( |
|||
height: 40, |
|||
child: SingleChildScrollView( |
|||
child: Column( |
|||
children: notifications.map<BrnNoticeBar>((payload) { |
|||
return BrnNoticeBar( |
|||
padding: const EdgeInsets.only(left: 5, right: 5, top: 3), |
|||
leftWidget: Image.asset( |
|||
'res/images/notification.png', |
|||
height: 30, |
|||
width: 30, |
|||
), |
|||
content: payload.title, |
|||
marquee: true, |
|||
noticeStyle: _mapNoticeStyles(payload.severity), |
|||
); |
|||
}).toList(), |
|||
), |
|||
), |
|||
); |
|||
} |
|||
|
|||
NoticeStyle _mapNoticeStyles(NotificationSeverity? severity) { |
|||
if (severity == null) return NoticeStyles.normalNoticeWithArrow; |
|||
switch (severity) { |
|||
case NotificationSeverity.info: |
|||
case NotificationSeverity.success: |
|||
return NoticeStyles.succeedWithArrow; |
|||
case NotificationSeverity.fatal: |
|||
case NotificationSeverity.error: |
|||
return NoticeStyles.failWithArrow; |
|||
case NotificationSeverity.warn: |
|||
return NoticeStyles.warningWithArrow; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
import 'package:flutter/material.dart'; |
|||
import 'package:get/get.dart'; |
|||
|
|||
class QuickNavigation extends StatelessWidget { |
|||
const QuickNavigation({ |
|||
super.key, |
|||
this.menus = const [], |
|||
}); |
|||
|
|||
final List<Widget> menus; |
|||
|
|||
@override |
|||
Widget build(BuildContext context) { |
|||
return ExpansionTile( |
|||
initiallyExpanded: true, |
|||
title: Text('Label:QuickNavigation'.tr, |
|||
style: Theme.of(context).textTheme.titleMedium, |
|||
), |
|||
children: [ |
|||
SizedBox( |
|||
height: 120, |
|||
child: GridView.count( |
|||
shrinkWrap: true, |
|||
crossAxisCount: 4, |
|||
crossAxisSpacing: 5, |
|||
physics: const NeverScrollableScrollPhysics(), |
|||
children: menus, |
|||
), |
|||
), |
|||
], |
|||
); |
|||
} |
|||
} |
|||
@ -1,3 +1,4 @@ |
|||
export './center/index.dart'; |
|||
export './home/index.dart'; |
|||
export './work/index.dart'; |
|||
export './error/index.dart'; |
|||
@ -1,5 +1,7 @@ |
|||
class PublicRoutes { |
|||
static String main = '/main'; |
|||
static String home = '/home'; |
|||
static String work = '/work'; |
|||
static String center = '/center'; |
|||
static String notFound = '/error/not_found'; |
|||
} |
|||
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 6.4 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 5.6 KiB |
Loading…
Reference in new issue