diff --git a/lib/pages/common/custom_table.dart b/lib/pages/common/custom_table.dart index 22baba36..60abc0d2 100644 --- a/lib/pages/common/custom_table.dart +++ b/lib/pages/common/custom_table.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:syncrow_web/pages/device_managment/all_devices/bloc/device_managment_bloc.dart'; +import 'package:syncrow_web/pages/device_managment/all_devices/bloc/device_mgmt_bloc/device_managment_bloc.dart'; import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/constants/assets.dart'; import 'package:syncrow_web/utils/extension/build_context_x.dart'; diff --git a/lib/pages/device_managment/all_devices/bloc/device_managment_bloc.dart b/lib/pages/device_managment/all_devices/bloc/device_mgmt_bloc/device_managment_bloc.dart similarity index 100% rename from lib/pages/device_managment/all_devices/bloc/device_managment_bloc.dart rename to lib/pages/device_managment/all_devices/bloc/device_mgmt_bloc/device_managment_bloc.dart diff --git a/lib/pages/device_managment/all_devices/bloc/device_managment_event.dart b/lib/pages/device_managment/all_devices/bloc/device_mgmt_bloc/device_managment_event.dart similarity index 100% rename from lib/pages/device_managment/all_devices/bloc/device_managment_event.dart rename to lib/pages/device_managment/all_devices/bloc/device_mgmt_bloc/device_managment_event.dart diff --git a/lib/pages/device_managment/all_devices/bloc/device_managment_state.dart b/lib/pages/device_managment/all_devices/bloc/device_mgmt_bloc/device_managment_state.dart similarity index 100% rename from lib/pages/device_managment/all_devices/bloc/device_managment_state.dart rename to lib/pages/device_managment/all_devices/bloc/device_mgmt_bloc/device_managment_state.dart diff --git a/lib/pages/device_managment/all_devices/bloc/switch_tabs/switch_tabs_bloc.dart b/lib/pages/device_managment/all_devices/bloc/switch_tabs/switch_tabs_bloc.dart new file mode 100644 index 00000000..3eaccf70 --- /dev/null +++ b/lib/pages/device_managment/all_devices/bloc/switch_tabs/switch_tabs_bloc.dart @@ -0,0 +1,28 @@ +import 'dart:async'; + +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; + +part 'switch_tabs_event.dart'; +part 'switch_tabs_state.dart'; + +class SwitchTabsBloc extends Bloc { + SwitchTabsBloc() : super(SwitchTabsInitial()) { + on(_switchTab); + on(_newRoutineView); + } + + FutureOr _switchTab( + TriggerSwitchTabsEvent event, + Emitter emit, + ) { + emit(SelectedTabState(event.isRoutineView)); + } + + FutureOr _newRoutineView( + CreateNewRoutineViewEvent event, + Emitter emit, + ) { + emit(ShowCreateRoutineState(event.showCreateNewRoutineView)); + } +} diff --git a/lib/pages/device_managment/all_devices/bloc/switch_tabs/switch_tabs_event.dart b/lib/pages/device_managment/all_devices/bloc/switch_tabs/switch_tabs_event.dart new file mode 100644 index 00000000..98cad361 --- /dev/null +++ b/lib/pages/device_managment/all_devices/bloc/switch_tabs/switch_tabs_event.dart @@ -0,0 +1,21 @@ +part of 'switch_tabs_bloc.dart'; + +sealed class SwitchTabsEvent extends Equatable { + const SwitchTabsEvent(); +} + +class TriggerSwitchTabsEvent extends SwitchTabsEvent { + final bool isRoutineView; + const TriggerSwitchTabsEvent(this.isRoutineView); + + @override + List get props => [isRoutineView]; +} + +class CreateNewRoutineViewEvent extends SwitchTabsEvent { + final bool showCreateNewRoutineView; + const CreateNewRoutineViewEvent(this.showCreateNewRoutineView); + + @override + List get props => [showCreateNewRoutineView]; +} diff --git a/lib/pages/device_managment/all_devices/bloc/switch_tabs/switch_tabs_state.dart b/lib/pages/device_managment/all_devices/bloc/switch_tabs/switch_tabs_state.dart new file mode 100644 index 00000000..dd01aeaa --- /dev/null +++ b/lib/pages/device_managment/all_devices/bloc/switch_tabs/switch_tabs_state.dart @@ -0,0 +1,26 @@ +part of 'switch_tabs_bloc.dart'; + +sealed class SwitchTabsState extends Equatable { + const SwitchTabsState(); +} + +final class SwitchTabsInitial extends SwitchTabsState { + @override + List get props => []; +} + +class SelectedTabState extends SwitchTabsState { + final bool selectedTab; + const SelectedTabState(this.selectedTab); + + @override + List get props => [selectedTab]; +} + +class ShowCreateRoutineState extends SwitchTabsState { + final bool showCreateRoutine; + const ShowCreateRoutineState(this.showCreateRoutine); + + @override + List get props => [showCreateRoutine]; +} diff --git a/lib/pages/device_managment/all_devices/view/device_managment_page.dart b/lib/pages/device_managment/all_devices/view/device_managment_page.dart index 8ed8c35e..d163a718 100644 --- a/lib/pages/device_managment/all_devices/view/device_managment_page.dart +++ b/lib/pages/device_managment/all_devices/view/device_managment_page.dart @@ -1,18 +1,30 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:syncrow_web/pages/device_managment/all_devices/bloc/device_managment_bloc.dart'; +import 'package:syncrow_web/pages/device_managment/all_devices/bloc/device_mgmt_bloc/device_managment_bloc.dart'; +import 'package:syncrow_web/pages/device_managment/all_devices/bloc/switch_tabs/switch_tabs_bloc.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/widgets/device_managment_body.dart'; import 'package:syncrow_web/pages/device_managment/shared/navigate_home_grid_view.dart'; -import 'package:syncrow_web/web_layout/web_scaffold.dart'; +import 'package:syncrow_web/pages/routiens/view/create_new_routine_view.dart'; +import 'package:syncrow_web/pages/routiens/view/routines_view.dart'; +import 'package:syncrow_web/utils/color_manager.dart'; +import 'package:syncrow_web/utils/extension/build_context_x.dart'; import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart'; +import 'package:syncrow_web/web_layout/web_scaffold.dart'; class DeviceManagementPage extends StatelessWidget with HelperResponsiveLayout { const DeviceManagementPage({super.key}); @override Widget build(BuildContext context) { - return BlocProvider( - create: (context) => DeviceManagementBloc()..add(FetchDevices()), + return MultiBlocProvider( + providers: [ + BlocProvider( + create: (context) => DeviceManagementBloc()..add(FetchDevices()), + ), + BlocProvider( + create: (context) => SwitchTabsBloc()..add(const TriggerSwitchTabsEvent(false)), + ), + ], child: WebScaffold( appBarTitle: FittedBox( child: Text( @@ -20,26 +32,74 @@ class DeviceManagementPage extends StatelessWidget with HelperResponsiveLayout { style: Theme.of(context).textTheme.headlineLarge, ), ), + centerBody: BlocBuilder(builder: (context, state) { + return Row( + mainAxisSize: MainAxisSize.min, + children: [ + TextButton( + style: TextButton.styleFrom( + backgroundColor: null, + ), + onPressed: () { + context.read().add(const TriggerSwitchTabsEvent(false)); + }, + child: Text( + 'Devices', + style: context.textTheme.titleMedium?.copyWith( + color: state is SelectedTabState && state.selectedTab == false + ? ColorsManager.whiteColors + : ColorsManager.grayColor, + fontWeight: + (state is SelectedTabState) && state.selectedTab == false ? FontWeight.w700 : FontWeight.w400, + ), + ), + ), + TextButton( + style: TextButton.styleFrom( + backgroundColor: null, + ), + onPressed: () { + context.read().add(const TriggerSwitchTabsEvent(true)); + }, + child: Text( + 'Routines', + style: context.textTheme.titleMedium?.copyWith( + color: (state is SelectedTabState) && state.selectedTab == true + ? ColorsManager.whiteColors + : ColorsManager.grayColor, + fontWeight: + (state is SelectedTabState) && state.selectedTab == true ? FontWeight.w700 : FontWeight.w400, + ), + ), + ), + ], + ); + }), rightBody: const NavigateHomeGridView(), - scaffoldBody: BlocBuilder( - builder: (context, state) { - if (state is DeviceManagementLoading) { - return const Center(child: CircularProgressIndicator()); - } else if (state is DeviceManagementLoaded || state is DeviceManagementFiltered) { - final devices = state is DeviceManagementLoaded - ? state.devices - : (state as DeviceManagementFiltered).filteredDevices; + scaffoldBody: BlocBuilder(builder: (context, state) { + if (state is SelectedTabState && state.selectedTab) { + return const RoutinesView(); + } + if (state is ShowCreateRoutineState && state.showCreateRoutine) { + return const CreateNewRoutineView(); + } - return DeviceManagementBody(devices: devices); - } else { - return const Center(child: Text('Error fetching Devices')); - } - }, - ), + return BlocBuilder( + builder: (context, deviceState) { + if (deviceState is DeviceManagementLoading) { + return const Center(child: CircularProgressIndicator()); + } else if (deviceState is DeviceManagementLoaded || deviceState is DeviceManagementFiltered) { + final devices = + (deviceState as dynamic).devices ?? (deviceState as DeviceManagementFiltered).filteredDevices; + + return DeviceManagementBody(devices: devices); + } else { + return const Center(child: Text('Error fetching Devices')); + } + }, + ); + }), ), ); } } - - - diff --git a/lib/pages/device_managment/all_devices/widgets/device_managment_body.dart b/lib/pages/device_managment/all_devices/widgets/device_managment_body.dart index 12c66403..0788e08d 100644 --- a/lib/pages/device_managment/all_devices/widgets/device_managment_body.dart +++ b/lib/pages/device_managment/all_devices/widgets/device_managment_body.dart @@ -3,7 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_web/pages/common/buttons/default_button.dart'; import 'package:syncrow_web/pages/common/custom_table.dart'; import 'package:syncrow_web/pages/common/filter/filter_widget.dart'; -import 'package:syncrow_web/pages/device_managment/all_devices/bloc/device_managment_bloc.dart'; +import 'package:syncrow_web/pages/device_managment/all_devices/bloc/device_mgmt_bloc/device_managment_bloc.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/widgets/device_search_filters.dart'; import 'package:syncrow_web/pages/device_managment/shared/device_batch_control_dialog.dart'; @@ -57,15 +57,12 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout { 'Low Battery ($lowBatteryCount)', ]; - final buttonLabel = - (selectedDevices.length > 1) ? 'Batch Control' : 'Control'; + final buttonLabel = (selectedDevices.length > 1) ? 'Batch Control' : 'Control'; return Column( children: [ Container( - padding: isLargeScreenSize(context) - ? const EdgeInsets.all(30) - : const EdgeInsets.all(15), + padding: isLargeScreenSize(context) ? const EdgeInsets.all(30) : const EdgeInsets.all(15), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -74,9 +71,7 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout { tabs: tabs, selectedIndex: selectedIndex, onTabChanged: (index) { - context - .read() - .add(SelectedFilterChanged(index)); + context.read().add(SelectedFilterChanged(index)); }, ), const SizedBox(height: 20), @@ -98,14 +93,11 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout { ), ); } else if (selectedDevices.length > 1) { - final productTypes = selectedDevices - .map((device) => device.productType) - .toSet(); + final productTypes = selectedDevices.map((device) => device.productType).toSet(); if (productTypes.length == 1) { showDialog( context: context, - builder: (context) => - DeviceBatchControlDialog( + builder: (context) => DeviceBatchControlDialog( devices: selectedDevices, ), ); @@ -119,9 +111,7 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout { textAlign: TextAlign.center, style: TextStyle( fontSize: 12, - color: isControlButtonEnabled - ? Colors.white - : Colors.grey, + color: isControlButtonEnabled ? Colors.white : Colors.grey, ), ), ), @@ -132,17 +122,13 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout { ), Expanded( child: Padding( - padding: isLargeScreenSize(context) - ? const EdgeInsets.all(30) - : const EdgeInsets.all(15), + padding: isLargeScreenSize(context) ? const EdgeInsets.all(30) : const EdgeInsets.all(15), child: DynamicTable( withSelectAll: true, cellDecoration: containerDecoration, onRowSelected: (index, isSelected, row) { final selectedDevice = devicesToShow[index]; - context - .read() - .add(SelectDevice(selectedDevice)); + context.read().add(SelectDevice(selectedDevice)); }, withCheckBox: true, size: MediaQuery.of(context).size, @@ -160,44 +146,27 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout { ], data: devicesToShow.map((device) { final combinedSpaceNames = device.spaces != null - ? device.spaces! - .map((space) => space.spaceName) - .join(' > ') + - (device.community != null - ? ' > ${device.community!.name}' - : '') - : (device.community != null - ? device.community!.name - : ''); + ? device.spaces!.map((space) => space.spaceName).join(' > ') + + (device.community != null ? ' > ${device.community!.name}' : '') + : (device.community != null ? device.community!.name : ''); return [ device.name ?? '', device.productName ?? '', device.uuid ?? '', - (device.spaces != null && device.spaces!.isNotEmpty) - ? device.spaces![0].spaceName - : '', + (device.spaces != null && device.spaces!.isNotEmpty) ? device.spaces![0].spaceName : '', combinedSpaceNames, - device.batteryLevel != null - ? '${device.batteryLevel}%' - : '-', - formatDateTime(DateTime.fromMillisecondsSinceEpoch( - (device.createTime ?? 0) * 1000)), + device.batteryLevel != null ? '${device.batteryLevel}%' : '-', + formatDateTime(DateTime.fromMillisecondsSinceEpoch((device.createTime ?? 0) * 1000)), device.online == true ? 'Online' : 'Offline', - formatDateTime(DateTime.fromMillisecondsSinceEpoch( - (device.updateTime ?? 0) * 1000)), + formatDateTime(DateTime.fromMillisecondsSinceEpoch((device.updateTime ?? 0) * 1000)), ]; }).toList(), onSelectionChanged: (selectedRows) { - context - .read() - .add(UpdateSelection(selectedRows)); + context.read().add(UpdateSelection(selectedRows)); }, - initialSelectedIds: context - .read() - .selectedDevices - .map((device) => device.uuid!) - .toList(), + initialSelectedIds: + context.read().selectedDevices.map((device) => device.uuid!).toList(), isEmpty: devicesToShow.isEmpty, ), ), diff --git a/lib/pages/device_managment/all_devices/widgets/device_search_filters.dart b/lib/pages/device_managment/all_devices/widgets/device_search_filters.dart index 71974156..d9e47aa6 100644 --- a/lib/pages/device_managment/all_devices/widgets/device_search_filters.dart +++ b/lib/pages/device_managment/all_devices/widgets/device_search_filters.dart @@ -1,10 +1,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:syncrow_web/pages/common/text_field/custom_text_field.dart'; -import 'package:syncrow_web/pages/device_managment/all_devices/bloc/device_managment_bloc.dart'; import 'package:syncrow_web/pages/common/buttons/search_reset_buttons.dart'; +import 'package:syncrow_web/pages/common/text_field/custom_text_field.dart'; +import 'package:syncrow_web/pages/device_managment/all_devices/bloc/device_mgmt_bloc/device_managment_bloc.dart'; import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart'; -import 'package:syncrow_web/utils/style.dart'; class DeviceSearchFilters extends StatefulWidget { const DeviceSearchFilters({super.key}); @@ -13,8 +12,7 @@ class DeviceSearchFilters extends StatefulWidget { State createState() => _DeviceSearchFiltersState(); } -class _DeviceSearchFiltersState extends State - with HelperResponsiveLayout { +class _DeviceSearchFiltersState extends State with HelperResponsiveLayout { final TextEditingController communityController = TextEditingController(); final TextEditingController unitNameController = TextEditingController(); final TextEditingController productNameController = TextEditingController(); @@ -36,8 +34,7 @@ class _DeviceSearchFiltersState extends State const SizedBox(width: 20), _buildSearchField("Space Name", unitNameController, 200), const SizedBox(width: 20), - _buildSearchField( - "Device Name / Product Name", productNameController, 300), + _buildSearchField("Device Name / Product Name", productNameController, 300), const SizedBox(width: 20), _buildSearchResetButtons(), ], @@ -62,8 +59,7 @@ class _DeviceSearchFiltersState extends State ); } - Widget _buildSearchField( - String title, TextEditingController controller, double width) { + Widget _buildSearchField(String title, TextEditingController controller, double width) { return Container( child: StatefulTextField( title: title, diff --git a/lib/pages/routiens/view/create_new_routine_view.dart b/lib/pages/routiens/view/create_new_routine_view.dart new file mode 100644 index 00000000..dc770946 --- /dev/null +++ b/lib/pages/routiens/view/create_new_routine_view.dart @@ -0,0 +1,10 @@ +import 'package:flutter/material.dart'; + +class CreateNewRoutineView extends StatelessWidget { + const CreateNewRoutineView({super.key}); + + @override + Widget build(BuildContext context) { + return const Placeholder(); + } +} diff --git a/lib/pages/routiens/view/routines_view.dart b/lib/pages/routiens/view/routines_view.dart new file mode 100644 index 00000000..5a19db08 --- /dev/null +++ b/lib/pages/routiens/view/routines_view.dart @@ -0,0 +1,61 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_web/pages/device_managment/all_devices/bloc/switch_tabs/switch_tabs_bloc.dart'; +import 'package:syncrow_web/utils/color_manager.dart'; + +class RoutinesView extends StatelessWidget { + const RoutinesView({super.key}); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.all(16), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text("Create New Routines", + style: Theme.of(context).textTheme.titleMedium?.copyWith( + fontWeight: FontWeight.bold, + color: ColorsManager.grayColor, + )), + SizedBox( + height: 200, + width: 150, + child: GestureDetector( + onTap: () { + BlocProvider.of(context).add( + const CreateNewRoutineViewEvent(true), + ); + }, + child: Card( + elevation: 3, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + color: ColorsManager.whiteColors, + child: Center( + child: Container( + decoration: BoxDecoration( + color: ColorsManager.graysColor, + borderRadius: BorderRadius.circular(120), + border: Border.all(color: ColorsManager.greyColor, width: 2.0), + ), + height: 70, + width: 70, + child: Icon( + Icons.add, + color: ColorsManager.dialogBlueTitle, + size: 40, + ), + )), + ), + ), + ), + const Spacer(), + ], + ), + ); + } +}