28 changed files with 494 additions and 46 deletions
@ -0,0 +1,90 @@ |
|||||
|
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 SingleChildScrollView( |
||||
|
child: Container( |
||||
|
child: _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.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.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,35 @@ |
|||||
|
import 'package:core/models/common.dart'; |
||||
import 'package:platforms/modes/menu.dto.dart'; |
import 'package:platforms/modes/menu.dto.dart'; |
||||
|
|
||||
class HomeState { |
class HomeState { |
||||
HomeState({ |
HomeState({ |
||||
|
this.activedMenu, |
||||
this.menus = const [], |
this.menus = const [], |
||||
this.favoriteMenus = const [], |
this.favoriteMenus = const [], |
||||
}); |
}); |
||||
|
String? activedMenu; |
||||
List<MenuDto> menus; |
List<MenuDto> menus; |
||||
List<UserFavoriteMenuDto> favoriteMenus; |
List<UserFavoriteMenuDto> favoriteMenus; |
||||
|
|
||||
|
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; |
||||
|
} |
||||
} |
} |
||||
@ -1,3 +1,4 @@ |
|||||
export './center/index.dart'; |
export './center/index.dart'; |
||||
export './home/index.dart'; |
export './home/index.dart'; |
||||
export './work/index.dart'; |
export './work/index.dart'; |
||||
|
export './error/index.dart'; |
||||
@ -1,5 +1,7 @@ |
|||||
class PublicRoutes { |
class PublicRoutes { |
||||
|
static String main = '/main'; |
||||
static String home = '/home'; |
static String home = '/home'; |
||||
static String work = '/work'; |
static String work = '/work'; |
||||
static String center = '/center'; |
static String center = '/center'; |
||||
|
static String notFound = '/error/not_found'; |
||||
} |
} |
||||
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 5.6 KiB |
Loading…
Reference in new issue