From f773c9e52ca730771e4557e9d7772ab9b18ae1ca Mon Sep 17 00:00:00 2001 From: ashrafzarkanisala Date: Wed, 21 Aug 2024 00:47:56 +0300 Subject: [PATCH] adding basic widget for device managment --- lib/core/extension/build_context_x.dart | 17 ++ lib/main.dart | 71 ++++--- .../view/access_management.dart | 191 ++++++++---------- lib/pages/common/filter/filter_widget.dart | 73 +++++++ .../bloc/device_managment_bloc.dart | 13 ++ .../bloc/device_managment_event.dart | 8 + .../bloc/device_managment_state.dart | 10 + .../view/device_managment_page.dart | 23 +++ .../widgets/device_managment_body.dart | 57 ++++++ lib/pages/home/bloc/home_bloc.dart | 27 +-- .../responsive_layout_helper.dart | 16 ++ lib/web_layout/web_app_bar.dart | 24 +-- 12 files changed, 356 insertions(+), 174 deletions(-) create mode 100644 lib/core/extension/build_context_x.dart create mode 100644 lib/pages/common/filter/filter_widget.dart create mode 100644 lib/pages/device_managment/bloc/device_managment_bloc.dart create mode 100644 lib/pages/device_managment/bloc/device_managment_event.dart create mode 100644 lib/pages/device_managment/bloc/device_managment_state.dart create mode 100644 lib/pages/device_managment/view/device_managment_page.dart create mode 100644 lib/pages/device_managment/widgets/device_managment_body.dart create mode 100644 lib/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart diff --git a/lib/core/extension/build_context_x.dart b/lib/core/extension/build_context_x.dart new file mode 100644 index 00000000..50bc5972 --- /dev/null +++ b/lib/core/extension/build_context_x.dart @@ -0,0 +1,17 @@ +import 'package:flutter/material.dart'; + +extension BuildContextExt on BuildContext { + ThemeData get theme => Theme.of(this); + + TextTheme get textTheme => Theme.of(this).textTheme; + + AppBarTheme get appBarTheme => Theme.of(this).appBarTheme; + + Size get screenSize => MediaQuery.of(this).size; + + double get screenWidth => MediaQuery.of(this).size.width; + + double get screenHeight => MediaQuery.of(this).size.height; + + double get textScale => MediaQuery.textScalerOf(this).scale(1); +} diff --git a/lib/main.dart b/lib/main.dart index dcabeaa2..c9d66e8e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -28,39 +28,44 @@ class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MultiBlocProvider( - providers: [ - BlocProvider(create: (context) => HomeBloc()), - ], - child: MaterialApp( - debugShowCheckedModeBanner: false, // Hide debug banner - scrollBehavior: const MaterialScrollBehavior().copyWith( - dragDevices: { - PointerDeviceKind.mouse, - PointerDeviceKind.touch, - PointerDeviceKind.stylus, - PointerDeviceKind.unknown, - }, - ), + providers: [ + BlocProvider(create: (context) => HomeBloc()), + ], + child: MaterialApp( + debugShowCheckedModeBanner: false, // Hide debug banner + scrollBehavior: const MaterialScrollBehavior().copyWith( + dragDevices: { + PointerDeviceKind.mouse, + PointerDeviceKind.touch, + PointerDeviceKind.stylus, + PointerDeviceKind.unknown, + }, + ), + theme: ThemeData( + textTheme: const TextTheme( + bodySmall: TextStyle( + fontSize: 13, + color: ColorsManager.whiteColors, + fontWeight: FontWeight.bold), + bodyMedium: TextStyle(color: Colors.black87, fontSize: 14), + bodyLarge: TextStyle(fontSize: 16, color: Colors.white), + headlineSmall: TextStyle(color: Colors.black87, fontSize: 18), + headlineMedium: TextStyle(color: Colors.black87, fontSize: 20), + headlineLarge: TextStyle( + color: Colors.white, + fontSize: 24, + fontWeight: FontWeight.bold, + ), + ), - theme: ThemeData( - textTheme: const TextTheme( - bodySmall: TextStyle(fontSize: 13, color: ColorsManager.whiteColors, fontWeight: FontWeight.bold), - bodyMedium: TextStyle(color: Colors.black87, fontSize: 14), - bodyLarge: TextStyle(fontSize: 16, color: Colors.white), - headlineSmall: TextStyle(color: Colors.black87, fontSize: 18), - headlineMedium: TextStyle(color: Colors.black87, fontSize: 20), - headlineLarge: TextStyle( - color: Colors.white, - fontSize: 24, - fontWeight: FontWeight.bold, - ), - ), - - colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), // Set up color scheme - useMaterial3: true, // Enable Material 3 - ), - // home: AddDeviceDialog() - home:isLoggedIn == 'Success' ? const HomePage() : const LoginPage(), - )); + colorScheme: ColorScheme.fromSeed( + seedColor: Colors.deepPurple), // Set up color scheme + useMaterial3: true, // Enable Material 3 + ), + // home: AddDeviceDialog() + // home:isLoggedIn == 'Success' ? + home: const HomePage() + // : const LoginPage(), + )); } } diff --git a/lib/pages/access_management/view/access_management.dart b/lib/pages/access_management/view/access_management.dart index 55570324..137eeeb7 100644 --- a/lib/pages/access_management/view/access_management.dart +++ b/lib/pages/access_management/view/access_management.dart @@ -6,6 +6,7 @@ import 'package:syncrow_web/pages/access_management/bloc/access_state.dart'; import 'package:syncrow_web/pages/common/custom_table.dart'; import 'package:syncrow_web/pages/common/date_time_widget.dart'; import 'package:syncrow_web/pages/common/default_button.dart'; +import 'package:syncrow_web/pages/common/filter/filter_widget.dart'; import 'package:syncrow_web/pages/visitor_password/view/visitor_password_dialog.dart'; import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/constants/const.dart'; @@ -36,8 +37,11 @@ class AccessManagementPage extends StatelessWidget { .copyWith(color: Colors.white), ), ], - scaffoldBody: BlocProvider(create: (BuildContext context) => AccessBloc()..add(FetchTableData()), - child: BlocConsumer(listener: (context, state) { + scaffoldBody: BlocProvider( + create: (BuildContext context) => + AccessBloc()..add(FetchTableData()), + child: BlocConsumer( + listener: (context, state) { if (state is FailedState) { // CustomSnackBar.displaySnackBar( // state.errorMessage @@ -52,60 +56,20 @@ class AccessManagementPage extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Container( - decoration: containerDecoration, - height: size.height * 0.05, - child: Flexible( - child: ListView.builder( - scrollDirection: Axis.horizontal, - itemCount: BlocProvider.of(context).tabs.length, - shrinkWrap: true, - itemBuilder: (context, index) { - final isSelected = index == - BlocProvider.of(context).selectedIndex; - return InkWell( - onTap: () { - BlocProvider.of(context).add(TabChangedEvent(index)); - }, - child: Container( - decoration: BoxDecoration( - color: ColorsManager.boxColor, - border: Border.all( - color: isSelected ? Colors.blue : Colors.transparent, - width: 2.0,), - borderRadius: index == 0 - ? const BorderRadius.only( - topLeft: Radius.circular(10), - bottomLeft: Radius.circular(10)) - : index == 3 - ? const BorderRadius.only( - topRight: Radius.circular(10), - bottomRight: Radius.circular(10)) - : null), - padding: const EdgeInsets.only(left: 10,right: 10), - child: Center( - child: Text( - BlocProvider.of(context).tabs[index], - style: TextStyle( - color: isSelected - ? Colors.blue - : Colors.black, - ), - ), - ), - ), - ); - }, - ), - ), - ), + FilterWidget( + size: size, + tabs: accessBloc.tabs, + selectedIndex: accessBloc.selectedIndex, + onTabChanged: (index) { + accessBloc.add(TabChangedEvent(index)); + }, + ), const SizedBox( height: 20, ), Row( children: [ Column( - crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ @@ -126,37 +90,43 @@ class AccessManagementPage extends StatelessWidget { ), DateTimeWebWidget( isRequired: false, - title: 'Access Time', - size: size, - endTime: () { - accessBloc.add(SelectTime(context: context, isStart: false)); - }, - startTime: () { - accessBloc.add(SelectTime(context: context, isStart: true)); - }, - firstString:BlocProvider.of(context).startTime , - secondString:BlocProvider.of(context).endTime , - ) , + title: 'Access Time', + size: size, + endTime: () { + accessBloc.add( + SelectTime(context: context, isStart: false)); + }, + startTime: () { + accessBloc.add( + SelectTime(context: context, isStart: true)); + }, + firstString: + BlocProvider.of(context).startTime, + secondString: + BlocProvider.of(context).endTime, + ), const SizedBox( width: 15, ), - SizedBox( width: size.width * 0.06, child: Column( children: [ Text(''), Container( - decoration: containerDecoration, - child: DefaultButton( - onPressed: () { - accessBloc.add(FilterDataEvent( - passwordName: accessBloc.passwordName.text, - startTime: accessBloc.effectiveTimeTimeStamp, - endTime: accessBloc.expirationTimeTimeStamp - )); - }, borderRadius: 9, - child: const Text('Search'))), + decoration: containerDecoration, + child: DefaultButton( + onPressed: () { + accessBloc.add(FilterDataEvent( + passwordName: + accessBloc.passwordName.text, + startTime: accessBloc + .effectiveTimeTimeStamp, + endTime: accessBloc + .expirationTimeTimeStamp)); + }, + borderRadius: 9, + child: const Text('Search'))), ], ), ), @@ -198,18 +168,19 @@ class AccessManagementPage extends StatelessWidget { Container( width: size.width * 0.15, decoration: containerDecoration, - child: DefaultButton( - onPressed: () { - showDialog( - context: context, - barrierDismissible: false, - builder: (BuildContext context) { - return const VisitorPasswordDialog(); - }, - ); - }, + child: DefaultButton( + onPressed: () { + showDialog( + context: context, + barrierDismissible: false, + builder: (BuildContext context) { + return const VisitorPasswordDialog(); + }, + ); + }, borderRadius: 8, - child: const Text('+ Create Visitor Password ')), + child: + const Text('+ Create Visitor Password ')), ), const SizedBox( width: 10, @@ -234,41 +205,39 @@ class AccessManagementPage extends StatelessWidget { ), Expanded( child: state is TableLoaded - ? DynamicTable( - withCheckBox: false, - size: size, - cellDecoration: containerDecoration, - headers: const [ - 'Name', - 'Access Type', - 'Access Period', - 'Device Id', - 'Authorizer', - 'Authorization Date & Time', - 'Access Status' - ], - data: state.data.map((item) { - return [ - item.passwodName.toString(), - item.passwordType.value, - ('${accessBloc.timestampToDate(item.effectiveTime)} - ${accessBloc.timestampToDate(item.invalidTime)}'), - item.deviceUuid.toString(), - '', - '', - '' - ]; - }).toList(), - ) + ? DynamicTable( + withCheckBox: false, + size: size, + cellDecoration: containerDecoration, + headers: const [ + 'Name', + 'Access Type', + 'Access Period', + 'Device Id', + 'Authorizer', + 'Authorization Date & Time', + 'Access Status' + ], + data: state.data.map((item) { + return [ + item.passwodName.toString(), + item.passwordType.value, + ('${accessBloc.timestampToDate(item.effectiveTime)} - ${accessBloc.timestampToDate(item.invalidTime)}'), + item.deviceUuid.toString(), + '', + '', + '' + ]; + }).toList(), + ) : const Center(child: CircularProgressIndicator()), ) - ], ), ); }))); } - // Container TableWidget(Size size, TableLoaded state,AccessBloc accessBloc) { // return Container( // decoration: containerDecoration, @@ -339,5 +308,3 @@ class AccessManagementPage extends StatelessWidget { // ); // } } - - diff --git a/lib/pages/common/filter/filter_widget.dart b/lib/pages/common/filter/filter_widget.dart new file mode 100644 index 00000000..9d70aebd --- /dev/null +++ b/lib/pages/common/filter/filter_widget.dart @@ -0,0 +1,73 @@ +import 'package:flutter/material.dart'; +import 'package:syncrow_web/utils/color_manager.dart'; +import 'package:syncrow_web/utils/style.dart'; + +class FilterWidget extends StatelessWidget { + const FilterWidget({ + super.key, + required this.size, + required this.tabs, + required this.selectedIndex, + required this.onTabChanged, + }); + + final Size size; + final List tabs; + final int selectedIndex; + final Function(int) onTabChanged; + + @override + Widget build(BuildContext context) { + return Container( + decoration: containerDecoration, + height: size.height * 0.05, + child: ListView.builder( + scrollDirection: Axis.horizontal, + itemCount: tabs.length, + shrinkWrap: true, + itemBuilder: (context, index) { + final isSelected = index == selectedIndex; + return InkWell( + onTap: () { + onTabChanged(index); + }, + child: Container( + decoration: BoxDecoration( + color: ColorsManager.boxColor, + border: Border.all( + color: isSelected ? Colors.blue : Colors.transparent, + width: 2.0, + ), + borderRadius: _getBorderRadius(index), + ), + padding: const EdgeInsets.only(left: 10, right: 10), + child: Center( + child: Text( + tabs[index], + style: TextStyle( + color: isSelected ? Colors.blue : Colors.black, + ), + ), + ), + ), + ); + }, + ), + ); + } + + BorderRadius? _getBorderRadius(int index) { + if (index == 0) { + return const BorderRadius.only( + topLeft: Radius.circular(10), + bottomLeft: Radius.circular(10), + ); + } else if (index == tabs.length - 1) { + return const BorderRadius.only( + topRight: Radius.circular(10), + bottomRight: Radius.circular(10), + ); + } + return null; + } +} diff --git a/lib/pages/device_managment/bloc/device_managment_bloc.dart b/lib/pages/device_managment/bloc/device_managment_bloc.dart new file mode 100644 index 00000000..d2b8c72c --- /dev/null +++ b/lib/pages/device_managment/bloc/device_managment_bloc.dart @@ -0,0 +1,13 @@ +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; + +part 'device_managment_event.dart'; +part 'device_managment_state.dart'; + +class DeviceManagmentBloc extends Bloc { + DeviceManagmentBloc() : super(DeviceManagmentInitial()) { + on((event, emit) { + // TODO: implement event handler + }); + } +} diff --git a/lib/pages/device_managment/bloc/device_managment_event.dart b/lib/pages/device_managment/bloc/device_managment_event.dart new file mode 100644 index 00000000..2ea61dc2 --- /dev/null +++ b/lib/pages/device_managment/bloc/device_managment_event.dart @@ -0,0 +1,8 @@ +part of 'device_managment_bloc.dart'; + +sealed class DeviceManagmentEvent extends Equatable { + const DeviceManagmentEvent(); + + @override + List get props => []; +} diff --git a/lib/pages/device_managment/bloc/device_managment_state.dart b/lib/pages/device_managment/bloc/device_managment_state.dart new file mode 100644 index 00000000..49977564 --- /dev/null +++ b/lib/pages/device_managment/bloc/device_managment_state.dart @@ -0,0 +1,10 @@ +part of 'device_managment_bloc.dart'; + +sealed class DeviceManagmentState extends Equatable { + const DeviceManagmentState(); + + @override + List get props => []; +} + +final class DeviceManagmentInitial extends DeviceManagmentState {} diff --git a/lib/pages/device_managment/view/device_managment_page.dart b/lib/pages/device_managment/view/device_managment_page.dart new file mode 100644 index 00000000..6891e943 --- /dev/null +++ b/lib/pages/device_managment/view/device_managment_page.dart @@ -0,0 +1,23 @@ +import 'package:flutter/material.dart'; +import 'package:syncrow_web/pages/device_managment/widgets/device_managment_body.dart'; +import 'package:syncrow_web/web_layout/web_scaffold.dart'; + +class DeviceManagementPage extends StatelessWidget { + const DeviceManagementPage({super.key}); + + @override + Widget build(BuildContext context) { + return WebScaffold( + enableMenuSideba: true, + appBarTitle: Row( + children: [ + Text( + 'Device Management', + style: Theme.of(context).textTheme.headlineLarge, + ) + ], + ), + scaffoldBody: const DeviceManagementBody(), + ); + } +} diff --git a/lib/pages/device_managment/widgets/device_managment_body.dart b/lib/pages/device_managment/widgets/device_managment_body.dart new file mode 100644 index 00000000..1b842bbb --- /dev/null +++ b/lib/pages/device_managment/widgets/device_managment_body.dart @@ -0,0 +1,57 @@ +import 'package:flutter/material.dart'; +import 'package:syncrow_web/core/extension/build_context_x.dart'; +import 'package:syncrow_web/pages/common/filter/filter_widget.dart'; +import 'package:syncrow_web/utils/style.dart'; + +class DeviceManagementBody extends StatelessWidget { + const DeviceManagementBody({super.key}); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.all(30), + height: context.screenHeight, + width: context.screenWidth, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + FilterWidget( + size: context.screenSize, + tabs: ['All', 'Online', 'Offline', 'Low Battery'], + selectedIndex: 0, + onTabChanged: (index) {}, + ), + const SizedBox( + height: 20, + ), + Wrap( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + 'Community', + style: context.textTheme.bodyMedium!.copyWith( + fontWeight: FontWeight.w400, + color: const Color(0xff000000)), + ), + Container( + width: context.screenWidth * 0.15, + margin: const EdgeInsets.only(top: 8), + decoration: containerDecoration, + child: TextFormField( + //: accessBloc.passwordName, + style: const TextStyle(color: Colors.black), + decoration: textBoxDecoration()! + .copyWith(hintText: 'Please enter'), + )), + ], + ), + ], + ) + ], + ), + ); + } +} diff --git a/lib/pages/home/bloc/home_bloc.dart b/lib/pages/home/bloc/home_bloc.dart index db233d3c..2b0b5035 100644 --- a/lib/pages/home/bloc/home_bloc.dart +++ b/lib/pages/home/bloc/home_bloc.dart @@ -5,6 +5,7 @@ import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:graphview/GraphView.dart'; import 'package:syncrow_web/pages/access_management/view/access_management.dart'; import 'package:syncrow_web/pages/auth/model/user_model.dart'; +import 'package:syncrow_web/pages/device_managment/view/device_managment_page.dart'; import 'package:syncrow_web/pages/home/bloc/home_event.dart'; import 'package:syncrow_web/pages/home/bloc/home_state.dart'; import 'package:syncrow_web/pages/home/home_model/home_item_model.dart'; @@ -22,7 +23,6 @@ class HomeBloc extends Bloc { HomeBloc() : super((HomeInitial())) { on(_createNode); fetchUserInfo(); - } void _createNode(CreateNewNode event, Emitter emit) async { @@ -41,12 +41,10 @@ class HomeBloc extends Bloc { emit(HomeUpdateTree(graph: graph, builder: builder)); } - - Future fetchUserInfo() async { try { var uuid = - await const FlutterSecureStorage().read(key: UserModel.userUuidKey); + await const FlutterSecureStorage().read(key: UserModel.userUuidKey); user = await HomeApi().fetchUserInfo(uuid); emit(HomeUserInfoLoaded(user!)); // Emit state after fetching user info } catch (e) { @@ -70,8 +68,7 @@ class HomeBloc extends Bloc { title: 'Space\nManagement', icon: Assets.spaseManagementIcon, active: true, - onPress: (context) { - }, + onPress: (context) {}, color: ColorsManager.primaryColor, ), HomeItemModel( @@ -79,6 +76,9 @@ class HomeBloc extends Bloc { icon: Assets.devicesIcon, active: true, onPress: (context) { + Navigator.of(context).push( + MaterialPageRoute(builder: (context) => const DeviceManagementPage()), + ); }, color: ColorsManager.primaryColor, ), @@ -86,40 +86,35 @@ class HomeBloc extends Bloc { title: 'Move in', icon: Assets.moveinIcon, active: false, - onPress: (context) { - }, + onPress: (context) {}, color: ColorsManager.primaryColor, ), HomeItemModel( title: 'Construction', icon: Assets.constructionIcon, active: false, - onPress: (context) { - }, + onPress: (context) {}, color: ColorsManager.primaryColor, ), HomeItemModel( title: 'Energy', icon: Assets.energyIcon, active: false, - onPress: (context) { - }, + onPress: (context) {}, color: ColorsManager.slidingBlueColor.withOpacity(0.2), ), HomeItemModel( title: 'Integrations', icon: Assets.integrationsIcon, active: false, - onPress: (context) { - }, + onPress: (context) {}, color: ColorsManager.slidingBlueColor.withOpacity(0.2), ), HomeItemModel( title: 'Asset', icon: Assets.assetIcon, active: false, - onPress: (context) { - }, + onPress: (context) {}, color: ColorsManager.slidingBlueColor.withOpacity(0.2), ), ]; diff --git a/lib/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart b/lib/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart new file mode 100644 index 00000000..265bf2cf --- /dev/null +++ b/lib/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart @@ -0,0 +1,16 @@ +import 'package:flutter/material.dart'; + +mixin HelperResponsiveLayout { + bool isSmallScreenSize(BuildContext context) { + return MediaQuery.of(context).size.width < 700; + } + + bool isMediumScreenSize(BuildContext context) { + return MediaQuery.of(context).size.width >= 700 && + MediaQuery.of(context).size.width < 1200; + } + + bool isLargeScreenSize(BuildContext context) { + return MediaQuery.of(context).size.width >= 1200; + } +} diff --git a/lib/web_layout/web_app_bar.dart b/lib/web_layout/web_app_bar.dart index 7b1ee1a7..6ad54d0b 100644 --- a/lib/web_layout/web_app_bar.dart +++ b/lib/web_layout/web_app_bar.dart @@ -12,11 +12,10 @@ class WebAppBar extends StatelessWidget { @override Widget build(BuildContext context) { return BlocBuilder(builder: (context, state) { - return Container( - height: 100, - decoration: const BoxDecoration(color: ColorsManager.secondaryColor), - padding: const EdgeInsets.all(10), - child: Expanded( + return Container( + height: 100, + decoration: const BoxDecoration(color: ColorsManager.secondaryColor), + padding: const EdgeInsets.all(10), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -52,17 +51,16 @@ class WebAppBar extends StatelessWidget { const SizedBox( width: 10, ), - if(HomeBloc.user!=null) - Text( - '${HomeBloc.user!.firstName.toString() ?? ''} ${HomeBloc.user!.lastName.toString() ?? ''} ', - style: Theme.of(context).textTheme.bodyLarge, - ), + if (HomeBloc.user != null) + Text( + '${HomeBloc.user!.firstName.toString()} ${HomeBloc.user!.lastName.toString()} ', + style: Theme.of(context).textTheme.bodyLarge, + ), ], ) ], ), - ), - ); - }); + ); + }); } }