Implemented side tree to devices and rountines screen

This commit is contained in:
Abdullah Alassaf
2025-01-04 17:45:15 +03:00
parent 0341844ea9
commit a98f7e77a3
88 changed files with 1551 additions and 1202 deletions

View File

@ -58,16 +58,18 @@ class CustomExpansionTileState extends State<CustomExpansionTile> {
children: [ children: [
// Checkbox with independent state management // Checkbox with independent state management
Checkbox( Checkbox(
value: false, value: widget.isSelected,
onChanged: (bool? value) { onChanged: (bool? value) {
setState(() {}); if (widget.onItemSelected != null) {
widget.onItemSelected!();
}
}, },
side: WidgetStateBorderSide.resolveWith((states) { side: WidgetStateBorderSide.resolveWith((states) {
return const BorderSide(color: ColorsManager.grayBorder); return const BorderSide(color: ColorsManager.grayBorder);
}), }),
fillColor: WidgetStateProperty.resolveWith((states) { fillColor: WidgetStateProperty.resolveWith((states) {
if (states.contains(WidgetState.selected)) { if (states.contains(WidgetState.selected)) {
return ColorsManager.grayBorder; return ColorsManager.blue1;
} else { } else {
return ColorsManager.checkBoxFillColor; return ColorsManager.checkBoxFillColor;
} }

View File

@ -0,0 +1,25 @@
import 'package:flutter/material.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
class SpacesSideTree extends StatefulWidget {
final List<CommunityModel> communities;
final String? selectedSpaceUuid;
const SpacesSideTree({
super.key,
required this.communities,
this.selectedSpaceUuid,
});
@override
State<SpacesSideTree> createState() => _SpacesSideTreeState();
}
class _SpacesSideTreeState extends State<SpacesSideTree> {
String _searchQuery = '';
String? _selectedSpaceUuid;
String? _selectedId;
@override
Widget build(BuildContext context) {
return const Placeholder();
}
}

View File

@ -6,7 +6,9 @@ import 'package:go_router/go_router.dart';
import 'package:syncrow_web/pages/auth/bloc/auth_bloc.dart'; import 'package:syncrow_web/pages/auth/bloc/auth_bloc.dart';
import 'package:syncrow_web/pages/home/bloc/home_bloc.dart'; import 'package:syncrow_web/pages/home/bloc/home_bloc.dart';
import 'package:syncrow_web/pages/home/bloc/home_event.dart'; import 'package:syncrow_web/pages/home/bloc/home_event.dart';
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart'; import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart';
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_bloc.dart';
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_event.dart';
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_bloc.dart'; import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_bloc.dart';
import 'package:syncrow_web/services/locator.dart'; import 'package:syncrow_web/services/locator.dart';
import 'package:syncrow_web/utils/app_routes.dart'; import 'package:syncrow_web/utils/app_routes.dart';
@ -15,8 +17,7 @@ import 'package:syncrow_web/utils/theme/theme.dart';
Future<void> main() async { Future<void> main() async {
try { try {
const environment = const environment = String.fromEnvironment('FLAVOR', defaultValue: 'development');
String.fromEnvironment('FLAVOR', defaultValue: 'development');
await dotenv.load(fileName: '.env.$environment'); await dotenv.load(fileName: '.env.$environment');
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
initialSetup(); initialSetup();
@ -48,14 +49,16 @@ class MyApp extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return MultiBlocProvider( return MultiBlocProvider(
providers: [ providers: [
BlocProvider( BlocProvider(create: (context) => HomeBloc()..add(const FetchUserInfo())),
create: (context) => HomeBloc()..add(const FetchUserInfo())),
BlocProvider<VisitorPasswordBloc>( BlocProvider<VisitorPasswordBloc>(
create: (context) => VisitorPasswordBloc(), create: (context) => VisitorPasswordBloc(),
), ),
BlocProvider<RoutineBloc>( BlocProvider<RoutineBloc>(
create: (context) => RoutineBloc(), create: (context) => RoutineBloc(),
), ),
BlocProvider<SpaceTreeBloc>(
create: (context) => SpaceTreeBloc()..add(InitialEvent()),
),
], ],
child: MaterialApp.router( child: MaterialApp.router(
debugShowCheckedModeBanner: false, debugShowCheckedModeBanner: false,

View File

@ -6,8 +6,7 @@ import 'package:syncrow_web/services/devices_mang_api.dart';
part 'device_managment_event.dart'; part 'device_managment_event.dart';
part 'device_managment_state.dart'; part 'device_managment_state.dart';
class DeviceManagementBloc class DeviceManagementBloc extends Bloc<DeviceManagementEvent, DeviceManagementState> {
extends Bloc<DeviceManagementEvent, DeviceManagementState> {
int _selectedIndex = 0; int _selectedIndex = 0;
List<AllDevicesModel> _devices = []; List<AllDevicesModel> _devices = [];
int _onlineCount = 0; int _onlineCount = 0;
@ -18,6 +17,8 @@ class DeviceManagementBloc
String currentProductName = ''; String currentProductName = '';
String? currentCommunity; String? currentCommunity;
String? currentUnitName; String? currentUnitName;
String? communityId;
String? spaceId;
DeviceManagementBloc() : super(DeviceManagementInitial()) { DeviceManagementBloc() : super(DeviceManagementInitial()) {
on<FetchDevices>(_onFetchDevices); on<FetchDevices>(_onFetchDevices);
@ -30,11 +31,16 @@ class DeviceManagementBloc
on<UpdateSelection>(_onUpdateSelection); on<UpdateSelection>(_onUpdateSelection);
} }
Future<void> _onFetchDevices( Future<void> _onFetchDevices(FetchDevices event, Emitter<DeviceManagementState> emit) async {
FetchDevices event, Emitter<DeviceManagementState> emit) async {
emit(DeviceManagementLoading()); emit(DeviceManagementLoading());
try { try {
final devices = await DevicesManagementApi().fetchDevices(); if (event.communityId.isNotEmpty) {
communityId = event.communityId;
}
if (event.spaceId.isNotEmpty) {
spaceId = event.spaceId;
}
final devices = await DevicesManagementApi().fetchDevices(communityId ?? '', spaceId ?? '');
_selectedDevices.clear(); _selectedDevices.clear();
_devices = devices; _devices = devices;
_filteredDevices = devices; _filteredDevices = devices;
@ -53,8 +59,7 @@ class DeviceManagementBloc
} }
} }
void _onFilterDevices( void _onFilterDevices(FilterDevices event, Emitter<DeviceManagementState> emit) async {
FilterDevices event, Emitter<DeviceManagementState> emit) async {
if (_devices.isNotEmpty) { if (_devices.isNotEmpty) {
_filteredDevices = List.from(_devices.where((device) { _filteredDevices = List.from(_devices.where((device) {
switch (event.filter) { switch (event.filter) {
@ -85,8 +90,7 @@ class DeviceManagementBloc
} }
} }
Future<void> _onResetFilters( Future<void> _onResetFilters(ResetFilters event, Emitter<DeviceManagementState> emit) async {
ResetFilters event, Emitter<DeviceManagementState> emit) async {
currentProductName = ''; currentProductName = '';
_selectedDevices.clear(); _selectedDevices.clear();
_filteredDevices = List.from(_devices); _filteredDevices = List.from(_devices);
@ -102,8 +106,7 @@ class DeviceManagementBloc
)); ));
} }
void _onResetSelectedDevices( void _onResetSelectedDevices(ResetSelectedDevices event, Emitter<DeviceManagementState> emit) {
ResetSelectedDevices event, Emitter<DeviceManagementState> emit) {
_selectedDevices.clear(); _selectedDevices.clear();
if (state is DeviceManagementLoaded) { if (state is DeviceManagementLoaded) {
@ -129,14 +132,12 @@ class DeviceManagementBloc
} }
} }
void _onSelectedFilterChanged( void _onSelectedFilterChanged(SelectedFilterChanged event, Emitter<DeviceManagementState> emit) {
SelectedFilterChanged event, Emitter<DeviceManagementState> emit) {
_selectedIndex = event.selectedIndex; _selectedIndex = event.selectedIndex;
add(FilterDevices(_getFilterFromIndex(_selectedIndex))); add(FilterDevices(_getFilterFromIndex(_selectedIndex)));
} }
void _onSelectDevice( void _onSelectDevice(SelectDevice event, Emitter<DeviceManagementState> emit) {
SelectDevice event, Emitter<DeviceManagementState> emit) {
final selectedUuid = event.selectedDevice.uuid; final selectedUuid = event.selectedDevice.uuid;
if (_selectedDevices.any((device) => device.uuid == selectedUuid)) { if (_selectedDevices.any((device) => device.uuid == selectedUuid)) {
@ -147,8 +148,7 @@ class DeviceManagementBloc
List<AllDevicesModel> clonedSelectedDevices = List.from(_selectedDevices); List<AllDevicesModel> clonedSelectedDevices = List.from(_selectedDevices);
bool isControlButtonEnabled = bool isControlButtonEnabled = _checkIfControlButtonEnabled(clonedSelectedDevices);
_checkIfControlButtonEnabled(clonedSelectedDevices);
if (state is DeviceManagementLoaded) { if (state is DeviceManagementLoaded) {
emit(DeviceManagementLoaded( emit(DeviceManagementLoaded(
@ -157,8 +157,7 @@ class DeviceManagementBloc
onlineCount: _onlineCount, onlineCount: _onlineCount,
offlineCount: _offlineCount, offlineCount: _offlineCount,
lowBatteryCount: _lowBatteryCount, lowBatteryCount: _lowBatteryCount,
selectedDevice: selectedDevice: clonedSelectedDevices.isNotEmpty ? clonedSelectedDevices : null,
clonedSelectedDevices.isNotEmpty ? clonedSelectedDevices : null,
isControlButtonEnabled: isControlButtonEnabled, isControlButtonEnabled: isControlButtonEnabled,
)); ));
} else if (state is DeviceManagementFiltered) { } else if (state is DeviceManagementFiltered) {
@ -168,15 +167,13 @@ class DeviceManagementBloc
onlineCount: _onlineCount, onlineCount: _onlineCount,
offlineCount: _offlineCount, offlineCount: _offlineCount,
lowBatteryCount: _lowBatteryCount, lowBatteryCount: _lowBatteryCount,
selectedDevice: selectedDevice: clonedSelectedDevices.isNotEmpty ? clonedSelectedDevices : null,
clonedSelectedDevices.isNotEmpty ? clonedSelectedDevices : null,
isControlButtonEnabled: isControlButtonEnabled, isControlButtonEnabled: isControlButtonEnabled,
)); ));
} }
} }
void _onUpdateSelection( void _onUpdateSelection(UpdateSelection event, Emitter<DeviceManagementState> emit) {
UpdateSelection event, Emitter<DeviceManagementState> emit) {
List<AllDevicesModel> selectedDevices = []; List<AllDevicesModel> selectedDevices = [];
List<AllDevicesModel> devicesToSelectFrom = []; List<AllDevicesModel> devicesToSelectFrom = [];
@ -219,8 +216,7 @@ class DeviceManagementBloc
bool _checkIfControlButtonEnabled(List<AllDevicesModel> selectedDevices) { bool _checkIfControlButtonEnabled(List<AllDevicesModel> selectedDevices) {
if (selectedDevices.length > 1) { if (selectedDevices.length > 1) {
final productTypes = final productTypes = selectedDevices.map((device) => device.productType).toSet();
selectedDevices.map((device) => device.productType).toSet();
return productTypes.length == 1; return productTypes.length == 1;
} else if (selectedDevices.length == 1) { } else if (selectedDevices.length == 1) {
return true; return true;
@ -231,10 +227,8 @@ class DeviceManagementBloc
void _calculateDeviceCounts() { void _calculateDeviceCounts() {
_onlineCount = _devices.where((device) => device.online == true).length; _onlineCount = _devices.where((device) => device.online == true).length;
_offlineCount = _devices.where((device) => device.online == false).length; _offlineCount = _devices.where((device) => device.online == false).length;
_lowBatteryCount = _devices _lowBatteryCount =
.where((device) => _devices.where((device) => device.batteryLevel != null && device.batteryLevel! < 20).length;
device.batteryLevel != null && device.batteryLevel! < 20)
.length;
} }
String _getFilterFromIndex(int index) { String _getFilterFromIndex(int index) {
@ -250,8 +244,7 @@ class DeviceManagementBloc
} }
} }
void _onSearchDevices( void _onSearchDevices(SearchDevices event, Emitter<DeviceManagementState> emit) {
SearchDevices event, Emitter<DeviceManagementState> emit) {
if ((event.community == null || event.community!.isEmpty) && if ((event.community == null || event.community!.isEmpty) &&
(event.unitName == null || event.unitName!.isEmpty) && (event.unitName == null || event.unitName!.isEmpty) &&
(event.productName == null || event.productName!.isEmpty)) { (event.productName == null || event.productName!.isEmpty)) {
@ -280,33 +273,22 @@ class DeviceManagementBloc
final filteredDevices = devicesToSearch.where((device) { final filteredDevices = devicesToSearch.where((device) {
final matchesCommunity = event.community == null || final matchesCommunity = event.community == null ||
event.community!.isEmpty || event.community!.isEmpty ||
(device.community?.name (device.community?.name?.toLowerCase().contains(event.community!.toLowerCase()) ??
?.toLowerCase()
.contains(event.community!.toLowerCase()) ??
false); false);
final matchesUnit = event.unitName == null || final matchesUnit = event.unitName == null ||
event.unitName!.isEmpty || event.unitName!.isEmpty ||
(device.spaces != null && (device.spaces != null &&
device.spaces!.isNotEmpty && device.spaces!.isNotEmpty &&
device.spaces![0].spaceName device.spaces![0].spaceName!.toLowerCase().contains(event.unitName!.toLowerCase()));
!.toLowerCase()
.contains(event.unitName!.toLowerCase()));
final matchesProductName = event.productName == null || final matchesProductName = event.productName == null ||
event.productName!.isEmpty || event.productName!.isEmpty ||
(device.name (device.name?.toLowerCase().contains(event.productName!.toLowerCase()) ?? false);
?.toLowerCase()
.contains(event.productName!.toLowerCase()) ??
false);
final matchesDeviceName = event.productName == null || final matchesDeviceName = event.productName == null ||
event.productName!.isEmpty || event.productName!.isEmpty ||
(device.categoryName (device.categoryName?.toLowerCase().contains(event.productName!.toLowerCase()) ??
?.toLowerCase()
.contains(event.productName!.toLowerCase()) ??
false); false);
return matchesCommunity && return matchesCommunity && matchesUnit && (matchesProductName || matchesDeviceName);
matchesUnit &&
(matchesProductName || matchesDeviceName);
}).toList(); }).toList();
emit(DeviceManagementFiltered( emit(DeviceManagementFiltered(

View File

@ -7,7 +7,14 @@ abstract class DeviceManagementEvent extends Equatable {
List<Object?> get props => []; List<Object?> get props => [];
} }
class FetchDevices extends DeviceManagementEvent {} class FetchDevices extends DeviceManagementEvent {
final String communityId;
final String spaceId;
const FetchDevices(this.communityId, this.spaceId);
@override
List<Object?> get props => [communityId, spaceId];
}
class FilterDevices extends DeviceManagementEvent { class FilterDevices extends DeviceManagementEvent {
final String filter; final String filter;

View File

@ -2,11 +2,11 @@ import 'package:syncrow_web/pages/device_managment/all_devices/models/device_com
import 'package:syncrow_web/pages/device_managment/all_devices/models/device_space_model.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/models/device_space_model.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/room.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/models/room.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/unit.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/models/unit.dart';
import 'package:syncrow_web/pages/routiens/models/ac/ac_function.dart'; import 'package:syncrow_web/pages/routines/models/ac/ac_function.dart';
import 'package:syncrow_web/pages/routiens/models/device_functions.dart'; import 'package:syncrow_web/pages/routines/models/device_functions.dart';
import 'package:syncrow_web/pages/routiens/models/gang_switches/one_gang_switch/one_gang_switch.dart'; import 'package:syncrow_web/pages/routines/models/gang_switches/one_gang_switch/one_gang_switch.dart';
import 'package:syncrow_web/pages/routiens/models/gang_switches/three_gang_switch/three_gang_switch.dart'; import 'package:syncrow_web/pages/routines/models/gang_switches/three_gang_switch/three_gang_switch.dart';
import 'package:syncrow_web/pages/routiens/models/gang_switches/two_gang_switch/two_gang_switch.dart'; import 'package:syncrow_web/pages/routines/models/gang_switches/two_gang_switch/two_gang_switch.dart';
import 'package:syncrow_web/utils/constants/assets.dart'; import 'package:syncrow_web/utils/constants/assets.dart';
import 'package:syncrow_web/utils/enum/device_types.dart'; import 'package:syncrow_web/utils/enum/device_types.dart';
@ -142,9 +142,7 @@ class AllDevicesModel {
productName = json['productName']?.toString(); productName = json['productName']?.toString();
if (json['spaces'] != null && json['spaces'] is List) { if (json['spaces'] != null && json['spaces'] is List) {
spaces = (json['spaces'] as List) spaces = (json['spaces'] as List).map((space) => DeviceSpaceModel.fromJson(space)).toList();
.map((space) => DeviceSpaceModel.fromJson(space))
.toList();
} }
} }
@ -192,8 +190,7 @@ SOS
String tempIcon = ''; String tempIcon = '';
if (type == DeviceType.LightBulb) { if (type == DeviceType.LightBulb) {
tempIcon = Assets.lightBulb; tempIcon = Assets.lightBulb;
} else if (type == DeviceType.CeilingSensor || } else if (type == DeviceType.CeilingSensor || type == DeviceType.WallSensor) {
type == DeviceType.WallSensor) {
tempIcon = Assets.sensors; tempIcon = Assets.sensors;
} else if (type == DeviceType.AC) { } else if (type == DeviceType.AC) {
tempIcon = Assets.ac; tempIcon = Assets.ac;
@ -248,34 +245,25 @@ SOS
case '1G': case '1G':
return [ return [
OneGangSwitchFunction(deviceId: uuid ?? '', deviceName: name ?? ''), OneGangSwitchFunction(deviceId: uuid ?? '', deviceName: name ?? ''),
OneGangCountdownFunction( OneGangCountdownFunction(deviceId: uuid ?? '', deviceName: name ?? ''),
deviceId: uuid ?? '', deviceName: name ?? ''),
]; ];
case '2G': case '2G':
return [ return [
TwoGangSwitch1Function(deviceId: uuid ?? '', deviceName: name ?? ''), TwoGangSwitch1Function(deviceId: uuid ?? '', deviceName: name ?? ''),
TwoGangSwitch2Function(deviceId: uuid ?? '', deviceName: name ?? ''), TwoGangSwitch2Function(deviceId: uuid ?? '', deviceName: name ?? ''),
TwoGangCountdown1Function( TwoGangCountdown1Function(deviceId: uuid ?? '', deviceName: name ?? ''),
deviceId: uuid ?? '', deviceName: name ?? ''), TwoGangCountdown2Function(deviceId: uuid ?? '', deviceName: name ?? ''),
TwoGangCountdown2Function(
deviceId: uuid ?? '', deviceName: name ?? ''),
]; ];
case '3G': case '3G':
return [ return [
ThreeGangSwitch1Function( ThreeGangSwitch1Function(deviceId: uuid ?? '', deviceName: name ?? ''),
deviceId: uuid ?? '', deviceName: name ?? ''), ThreeGangSwitch2Function(deviceId: uuid ?? '', deviceName: name ?? ''),
ThreeGangSwitch2Function( ThreeGangSwitch3Function(deviceId: uuid ?? '', deviceName: name ?? ''),
deviceId: uuid ?? '', deviceName: name ?? ''), ThreeGangCountdown1Function(deviceId: uuid ?? '', deviceName: name ?? ''),
ThreeGangSwitch3Function( ThreeGangCountdown2Function(deviceId: uuid ?? '', deviceName: name ?? ''),
deviceId: uuid ?? '', deviceName: name ?? ''), ThreeGangCountdown3Function(deviceId: uuid ?? '', deviceName: name ?? ''),
ThreeGangCountdown1Function(
deviceId: uuid ?? '', deviceName: name ?? ''),
ThreeGangCountdown2Function(
deviceId: uuid ?? '', deviceName: name ?? ''),
ThreeGangCountdown3Function(
deviceId: uuid ?? '', deviceName: name ?? ''),
]; ];
default: default:

View File

@ -3,9 +3,9 @@ import 'package:flutter_bloc/flutter_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/device_mgmt_bloc/device_managment_bloc.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/widgets/device_managment_body.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/pages/device_managment/shared/navigate_home_grid_view.dart';
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart'; import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart';
import 'package:syncrow_web/pages/routiens/view/create_new_routine_view.dart'; import 'package:syncrow_web/pages/routines/view/create_new_routine_view.dart';
import 'package:syncrow_web/pages/routiens/view/routines_view.dart'; import 'package:syncrow_web/pages/routines/view/routines_view.dart';
import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/extension/build_context_x.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/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
@ -19,7 +19,7 @@ class DeviceManagementPage extends StatelessWidget with HelperResponsiveLayout {
return MultiBlocProvider( return MultiBlocProvider(
providers: [ providers: [
BlocProvider( BlocProvider(
create: (context) => DeviceManagementBloc()..add(FetchDevices()), create: (context) => DeviceManagementBloc()..add(const FetchDevices('', '')),
), ),
], ],
child: WebScaffold( child: WebScaffold(

View File

@ -8,6 +8,7 @@ import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_mo
import 'package:syncrow_web/pages/device_managment/all_devices/widgets/device_search_filters.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'; import 'package:syncrow_web/pages/device_managment/shared/device_batch_control_dialog.dart';
import 'package:syncrow_web/pages/device_managment/shared/device_control_dialog.dart'; import 'package:syncrow_web/pages/device_managment/shared/device_control_dialog.dart';
import 'package:syncrow_web/pages/space_tree/view/side_spaces_view.dart';
import 'package:syncrow_web/utils/format_date_time.dart'; import 'package:syncrow_web/utils/format_date_time.dart';
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart'; import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
import 'package:syncrow_web/utils/style.dart'; import 'package:syncrow_web/utils/style.dart';
@ -59,118 +60,143 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
final buttonLabel = (selectedDevices.length > 1) ? 'Batch Control' : 'Control'; final buttonLabel = (selectedDevices.length > 1) ? 'Batch Control' : 'Control';
return Column( return Row(
children: [ children: [
Container( Flexible(child: SideSpacesView(
padding: isLargeScreenSize(context) ? const EdgeInsets.all(30) : const EdgeInsets.all(15), onSelectAction: (String communityId, String spaceId) {
context.read<DeviceManagementBloc>().add(FetchDevices(communityId, spaceId));
},
)),
Flexible(
flex: 3,
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
FilterWidget(
size: MediaQuery.of(context).size,
tabs: tabs,
selectedIndex: selectedIndex,
onTabChanged: (index) {
context.read<DeviceManagementBloc>().add(SelectedFilterChanged(index));
},
),
const SizedBox(height: 20),
const DeviceSearchFilters(),
const SizedBox(height: 12),
Container( Container(
height: 45, padding: isLargeScreenSize(context)
width: 125, ? const EdgeInsets.all(30)
decoration: containerDecoration, : const EdgeInsets.all(15),
child: Center( child: Column(
child: DefaultButton( crossAxisAlignment: CrossAxisAlignment.start,
onPressed: isControlButtonEnabled children: [
? () { FilterWidget(
if (selectedDevices.length == 1) { size: MediaQuery.of(context).size,
showDialog( tabs: tabs,
context: context, selectedIndex: selectedIndex,
builder: (context) => DeviceControlDialog( onTabChanged: (index) {
device: selectedDevices.first, context.read<DeviceManagementBloc>().add(SelectedFilterChanged(index));
), },
); ),
} else if (selectedDevices.length > 1) { const SizedBox(height: 20),
final productTypes = selectedDevices.map((device) => device.productType).toSet(); const DeviceSearchFilters(),
if (productTypes.length == 1) { const SizedBox(height: 12),
showDialog( Container(
context: context, height: 45,
builder: (context) => DeviceBatchControlDialog( width: 125,
devices: selectedDevices, decoration: containerDecoration,
), child: Center(
); child: DefaultButton(
} onPressed: isControlButtonEnabled
} ? () {
} if (selectedDevices.length == 1) {
: null, showDialog(
borderRadius: 9, context: context,
child: Text( builder: (context) => DeviceControlDialog(
buttonLabel, device: selectedDevices.first,
textAlign: TextAlign.center, ),
style: TextStyle( );
fontSize: 12, } else if (selectedDevices.length > 1) {
color: isControlButtonEnabled ? Colors.white : Colors.grey, final productTypes = selectedDevices
.map((device) => device.productType)
.toSet();
if (productTypes.length == 1) {
showDialog(
context: context,
builder: (context) => DeviceBatchControlDialog(
devices: selectedDevices,
),
);
}
}
}
: null,
borderRadius: 9,
child: Text(
buttonLabel,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 12,
color: isControlButtonEnabled ? Colors.white : Colors.grey,
),
),
),
), ),
), ),
), ],
), ),
), ),
Expanded(
child: Padding(
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<DeviceManagementBloc>().add(SelectDevice(selectedDevice));
},
withCheckBox: true,
size: MediaQuery.of(context).size,
uuidIndex: 2,
headers: const [
'Device Name',
'Product Name',
'Device ID',
'Space Name',
'location',
'Battery Level',
'Installation Date and Time',
'Status',
'Last Offline Date and Time',
],
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 : '');
return [
device.name ?? '',
device.productName ?? '',
device.uuid ?? '',
(device.spaces != null && device.spaces!.isNotEmpty)
? device.spaces![0].spaceName
: '',
combinedSpaceNames,
device.batteryLevel != null ? '${device.batteryLevel}%' : '-',
formatDateTime(DateTime.fromMillisecondsSinceEpoch(
(device.createTime ?? 0) * 1000)),
device.online == true ? 'Online' : 'Offline',
formatDateTime(DateTime.fromMillisecondsSinceEpoch(
(device.updateTime ?? 0) * 1000)),
];
}).toList(),
onSelectionChanged: (selectedRows) {
context.read<DeviceManagementBloc>().add(UpdateSelection(selectedRows));
},
initialSelectedIds: context
.read<DeviceManagementBloc>()
.selectedDevices
.map((device) => device.uuid!)
.toList(),
isEmpty: devicesToShow.isEmpty,
),
),
)
], ],
), ),
), ),
Expanded(
child: Padding(
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<DeviceManagementBloc>().add(SelectDevice(selectedDevice));
},
withCheckBox: true,
size: MediaQuery.of(context).size,
uuidIndex: 2,
headers: const [
'Device Name',
'Product Name',
'Device ID',
'Space Name',
'location',
'Battery Level',
'Installation Date and Time',
'Status',
'Last Offline Date and Time',
],
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 : '');
return [
device.name ?? '',
device.productName ?? '',
device.uuid ?? '',
(device.spaces != null && device.spaces!.isNotEmpty) ? device.spaces![0].spaceName : '',
combinedSpaceNames,
device.batteryLevel != null ? '${device.batteryLevel}%' : '-',
formatDateTime(DateTime.fromMillisecondsSinceEpoch((device.createTime ?? 0) * 1000)),
device.online == true ? 'Online' : 'Offline',
formatDateTime(DateTime.fromMillisecondsSinceEpoch((device.updateTime ?? 0) * 1000)),
];
}).toList(),
onSelectionChanged: (selectedRows) {
context.read<DeviceManagementBloc>().add(UpdateSelection(selectedRows));
},
initialSelectedIds:
context.read<DeviceManagementBloc>().selectedDevices.map((device) => device.uuid!).toList(),
isEmpty: devicesToShow.isEmpty,
),
),
)
], ],
); );
}, },

View File

@ -12,8 +12,7 @@ class DeviceSearchFilters extends StatefulWidget {
State<DeviceSearchFilters> createState() => _DeviceSearchFiltersState(); State<DeviceSearchFilters> createState() => _DeviceSearchFiltersState();
} }
class _DeviceSearchFiltersState extends State<DeviceSearchFilters> class _DeviceSearchFiltersState extends State<DeviceSearchFilters> with HelperResponsiveLayout {
with HelperResponsiveLayout {
final TextEditingController communityController = TextEditingController(); final TextEditingController communityController = TextEditingController();
final TextEditingController unitNameController = TextEditingController(); final TextEditingController unitNameController = TextEditingController();
final TextEditingController productNameController = TextEditingController(); final TextEditingController productNameController = TextEditingController();
@ -27,8 +26,7 @@ class _DeviceSearchFiltersState extends State<DeviceSearchFilters>
const SizedBox(width: 20), const SizedBox(width: 20),
_buildSearchField("Space Name", unitNameController, 200), _buildSearchField("Space Name", unitNameController, 200),
const SizedBox(width: 20), const SizedBox(width: 20),
_buildSearchField( _buildSearchField("Device Name / Product Name", productNameController, 300),
"Device Name / Product Name", productNameController, 300),
const SizedBox(width: 20), const SizedBox(width: 20),
_buildSearchResetButtons(), _buildSearchResetButtons(),
], ],
@ -53,8 +51,7 @@ class _DeviceSearchFiltersState extends State<DeviceSearchFilters>
); );
} }
Widget _buildSearchField( Widget _buildSearchField(String title, TextEditingController controller, double width) {
String title, TextEditingController controller, double width) {
return Container( return Container(
child: StatefulTextField( child: StatefulTextField(
title: title, title: title,
@ -88,7 +85,7 @@ class _DeviceSearchFiltersState extends State<DeviceSearchFilters>
productNameController.clear(); productNameController.clear();
context.read<DeviceManagementBloc>() context.read<DeviceManagementBloc>()
..add(ResetFilters()) ..add(ResetFilters())
..add(FetchDevices()); ..add(const FetchDevices('', ''));
}, },
); );
} }

View File

@ -1,44 +1,44 @@
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:graphview/GraphView.dart'; // import 'package:graphview/GraphView.dart';
import 'package:syncrow_web/pages/auth/model/user_model.dart'; import 'package:syncrow_web/pages/auth/model/user_model.dart';
import 'package:syncrow_web/pages/home/bloc/home_event.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/bloc/home_state.dart';
import 'package:syncrow_web/pages/home/home_model/home_item_model.dart'; import 'package:syncrow_web/pages/home/home_model/home_item_model.dart';
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart'; import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart';
import 'package:syncrow_web/services/home_api.dart'; import 'package:syncrow_web/services/home_api.dart';
import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/constants/assets.dart'; import 'package:syncrow_web/utils/constants/assets.dart';
import 'package:syncrow_web/utils/constants/routes_const.dart'; import 'package:syncrow_web/utils/constants/routes_const.dart';
class HomeBloc extends Bloc<HomeEvent, HomeState> { class HomeBloc extends Bloc<HomeEvent, HomeState> {
final Graph graph = Graph()..isTree = true; // final Graph graph = Graph()..isTree = true;
final BuchheimWalkerConfiguration builder = BuchheimWalkerConfiguration(); // final BuchheimWalkerConfiguration builder = BuchheimWalkerConfiguration();
List<Node> sourcesList = []; // List<Node> sourcesList = [];
List<Node> destinationsList = []; // List<Node> destinationsList = [];
UserModel? user; UserModel? user;
HomeBloc() : super((HomeInitial())) { HomeBloc() : super((HomeInitial())) {
on<CreateNewNode>(_createNode); // on<CreateNewNode>(_createNode);
on<FetchUserInfo>(_fetchUserInfo); on<FetchUserInfo>(_fetchUserInfo);
} }
void _createNode(CreateNewNode event, Emitter<HomeState> emit) async { // void _createNode(CreateNewNode event, Emitter<HomeState> emit) async {
emit(HomeInitial()); // emit(HomeInitial());
sourcesList.add(event.sourceNode); // sourcesList.add(event.sourceNode);
destinationsList.add(event.destinationNode); // destinationsList.add(event.destinationNode);
for (int i = 0; i < sourcesList.length; i++) { // for (int i = 0; i < sourcesList.length; i++) {
graph.addEdge(sourcesList[i], destinationsList[i]); // graph.addEdge(sourcesList[i], destinationsList[i]);
} // }
builder // builder
..siblingSeparation = (100) // ..siblingSeparation = (100)
..levelSeparation = (150) // ..levelSeparation = (150)
..subtreeSeparation = (150) // ..subtreeSeparation = (150)
..orientation = (BuchheimWalkerConfiguration.ORIENTATION_TOP_BOTTOM); // ..orientation = (BuchheimWalkerConfiguration.ORIENTATION_TOP_BOTTOM);
emit(HomeUpdateTree(graph: graph, builder: builder)); // emit(HomeUpdateTree(graph: graph, builder: builder));
} // }
Future _fetchUserInfo(FetchUserInfo event, Emitter<HomeState> emit) async { Future _fetchUserInfo(FetchUserInfo event, Emitter<HomeState> emit) async {
try { try {

View File

@ -1,5 +1,5 @@
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import 'package:graphview/GraphView.dart'; // import 'package:graphview/GraphView.dart';
abstract class HomeEvent extends Equatable { abstract class HomeEvent extends Equatable {
const HomeEvent(); const HomeEvent();
@ -8,15 +8,15 @@ abstract class HomeEvent extends Equatable {
List<Object> get props => []; List<Object> get props => [];
} }
class CreateNewNode extends HomeEvent { // class CreateNewNode extends HomeEvent {
final Node sourceNode; // final Node sourceNode;
final Node destinationNode; // final Node destinationNode;
const CreateNewNode( // const CreateNewNode(
{required this.sourceNode, required this.destinationNode}); // {required this.sourceNode, required this.destinationNode});
@override // @override
List<Object> get props => [sourceNode, destinationNode]; // List<Object> get props => [sourceNode, destinationNode];
} // }
class FetchUserInfo extends HomeEvent { class FetchUserInfo extends HomeEvent {
const FetchUserInfo(); const FetchUserInfo();

View File

@ -1,5 +1,5 @@
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import 'package:graphview/GraphView.dart'; // import 'package:graphview/GraphView.dart';
abstract class HomeState extends Equatable { abstract class HomeState extends Equatable {
const HomeState(); const HomeState();
@ -10,17 +10,17 @@ abstract class HomeState extends Equatable {
class HomeInitial extends HomeState {} class HomeInitial extends HomeState {}
class HomeCounterState extends HomeState { // class HomeCounterState extends HomeState {
final int counter; // final int counter;
const HomeCounterState(this.counter); // const HomeCounterState(this.counter);
} // }
class HomeUpdateTree extends HomeState { // class HomeUpdateTree extends HomeState {
final Graph graph; // final Graph graph;
final BuchheimWalkerConfiguration builder; // final BuchheimWalkerConfiguration builder;
const HomeUpdateTree({required this.graph, required this.builder}); // const HomeUpdateTree({required this.graph, required this.builder});
@override // @override
List<Object> get props => [graph, builder]; // List<Object> get props => [graph, builder];
} // }

View File

@ -41,8 +41,7 @@ class HomeMobilePage extends StatelessWidget {
SizedBox(height: size.height * 0.05), SizedBox(height: size.height * 0.05),
const Text( const Text(
'ACCESS YOUR APPS', 'ACCESS YOUR APPS',
style: style: TextStyle(fontSize: 20, fontWeight: FontWeight.w700),
TextStyle(fontSize: 20, fontWeight: FontWeight.w700),
), ),
const SizedBox(height: 30), const SizedBox(height: 30),
Expanded( Expanded(
@ -51,9 +50,8 @@ class HomeMobilePage extends StatelessWidget {
height: size.height * 0.6, height: size.height * 0.6,
width: size.width * 0.68, width: size.width * 0.68,
child: GridView.builder( child: GridView.builder(
itemCount: 8, itemCount: 3,
gridDelegate: gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2, crossAxisCount: 2,
crossAxisSpacing: 20.0, crossAxisSpacing: 20.0,
mainAxisSpacing: 20.0, mainAxisSpacing: 20.0,
@ -65,8 +63,7 @@ class HomeMobilePage extends StatelessWidget {
active: homeItems[index]['active'], active: homeItems[index]['active'],
name: homeItems[index]['title'], name: homeItems[index]['title'],
img: homeItems[index]['icon'], img: homeItems[index]['icon'],
onTap: () => onTap: () => homeBloc.homeItems[index].onPress(context),
homeBloc.homeItems[index].onPress(context),
); );
}, },
), ),
@ -97,33 +94,33 @@ class HomeMobilePage extends StatelessWidget {
'icon': Assets.devicesIcon, 'icon': Assets.devicesIcon,
'active': true, 'active': true,
}, },
{ // {
'title': 'Move in', // 'title': 'Move in',
'icon': Assets.moveinIcon, // 'icon': Assets.moveinIcon,
'active': false, // 'active': false,
}, // },
{ // {
'title': 'Construction', // 'title': 'Construction',
'icon': Assets.constructionIcon, // 'icon': Assets.constructionIcon,
'active': false, // 'active': false,
}, // },
{ // {
'title': 'Energy', // 'title': 'Energy',
'icon': Assets.energyIcon, // 'icon': Assets.energyIcon,
'color': ColorsManager.slidingBlueColor.withOpacity(0.2), // 'color': ColorsManager.slidingBlueColor.withOpacity(0.2),
'active': false, // 'active': false,
}, // },
{ // {
'title': 'Integrations', // 'title': 'Integrations',
'icon': Assets.integrationsIcon, // 'icon': Assets.integrationsIcon,
'color': ColorsManager.slidingBlueColor.withOpacity(0.2), // 'color': ColorsManager.slidingBlueColor.withOpacity(0.2),
'active': false, // 'active': false,
}, // },
{ // {
'title': 'Asset', // 'title': 'Asset',
'icon': Assets.assetIcon, // 'icon': Assets.assetIcon,
'color': ColorsManager.slidingBlueColor.withOpacity(0.2), // 'color': ColorsManager.slidingBlueColor.withOpacity(0.2),
'active': false, // 'active': false,
}, // },
]; ];
} }

View File

@ -32,43 +32,48 @@ class HomeWebPage extends StatelessWidget {
scaffoldBody: SizedBox( scaffoldBody: SizedBox(
height: size.height, height: size.height,
width: size.width, width: size.width,
child: Column( child: Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
SizedBox(height: size.height * 0.1), Column(
Text( mainAxisAlignment: MainAxisAlignment.center,
'ACCESS YOUR APPS', crossAxisAlignment: CrossAxisAlignment.center,
style: Theme.of(context) children: [
.textTheme SizedBox(height: size.height * 0.1),
.headlineLarge! Text(
.copyWith(color: Colors.black, fontSize: 40), 'ACCESS YOUR APPS',
), style: Theme.of(context)
const SizedBox(height: 30), .textTheme
Expanded( .headlineLarge!
flex: 4, .copyWith(color: Colors.black, fontSize: 40),
child: SizedBox(
height: size.height * 0.6,
width: size.width * 0.68,
child: GridView.builder(
itemCount: 3, //8
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4,
crossAxisSpacing: 20.0,
mainAxisSpacing: 20.0,
childAspectRatio: 1.5,
),
itemBuilder: (context, index) {
return HomeCard(
index: index,
active: homeBloc.homeItems[index].active!,
name: homeBloc.homeItems[index].title!,
img: homeBloc.homeItems[index].icon!,
onTap: () => homeBloc.homeItems[index].onPress(context),
);
},
), ),
), const SizedBox(height: 30),
Expanded(
flex: 4,
child: SizedBox(
height: size.height * 0.6,
width: size.width * 0.68,
child: GridView.builder(
itemCount: 3, //8
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4,
crossAxisSpacing: 20.0,
mainAxisSpacing: 20.0,
childAspectRatio: 1.5,
),
itemBuilder: (context, index) {
return HomeCard(
index: index,
active: homeBloc.homeItems[index].active!,
name: homeBloc.homeItems[index].title!,
img: homeBloc.homeItems[index].icon!,
onTap: () => homeBloc.homeItems[index].onPress(context),
);
},
),
),
),
],
), ),
], ],
), ),

View File

@ -1,185 +1,185 @@
import 'package:flutter/material.dart'; // import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; // import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:graphview/GraphView.dart'; // import 'package:graphview/GraphView.dart';
import 'package:syncrow_web/pages/home/bloc/home_bloc.dart'; // import 'package:syncrow_web/pages/home/bloc/home_bloc.dart';
import 'package:syncrow_web/pages/home/bloc/home_event.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/bloc/home_state.dart';
class TreeWidget extends StatelessWidget { // class TreeWidget extends StatelessWidget {
const TreeWidget({super.key}); // const TreeWidget({super.key});
@override // @override
Widget build(BuildContext context) { // Widget build(BuildContext context) {
// final HomeBloc homeBloc = BlocProvider.of<HomeBloc>(context); // // final HomeBloc homeBloc = BlocProvider.of<HomeBloc>(context);
String firstNodeName = ''; // String firstNodeName = '';
String secondNodeName = ''; // String secondNodeName = '';
return SafeArea( // return SafeArea(
child: Container( // child: Container(
padding: const EdgeInsets.all(24), // padding: const EdgeInsets.all(24),
width: MediaQuery.sizeOf(context).width, // width: MediaQuery.sizeOf(context).width,
height: MediaQuery.sizeOf(context).height, // height: MediaQuery.sizeOf(context).height,
alignment: AlignmentDirectional.center, // alignment: AlignmentDirectional.center,
child: Column( // child: Column(
mainAxisSize: MainAxisSize.max, // mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.center, // crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center, // mainAxisAlignment: MainAxisAlignment.center,
children: [ // children: [
BlocBuilder<HomeBloc, HomeState>(builder: (context, state) { // BlocBuilder<HomeBloc, HomeState>(builder: (context, state) {
if (state is HomeInitial) { // if (state is HomeInitial) {
return Wrap( // return Wrap(
children: [ // children: [
SizedBox( // SizedBox(
width: 100, // width: 100,
child: TextFormField( // child: TextFormField(
decoration: const InputDecoration( // decoration: const InputDecoration(
labelText: "Subtree separation"), // labelText: "Subtree separation"),
onChanged: (text) { // onChanged: (text) {
firstNodeName = text; // firstNodeName = text;
}, // },
), // ),
), // ),
const SizedBox( // const SizedBox(
width: 8, // width: 8,
), // ),
Container( // Container(
width: 100, // width: 100,
child: TextFormField( // child: TextFormField(
decoration: InputDecoration(labelText: "Node Name"), // decoration: InputDecoration(labelText: "Node Name"),
onChanged: (text) { // onChanged: (text) {
secondNodeName = text; // secondNodeName = text;
}, // },
), // ),
), // ),
ElevatedButton( // ElevatedButton(
onPressed: () { // onPressed: () {
final node1 = Node.Id(firstNodeName); // final node1 = Node.Id(firstNodeName);
final node2 = Node.Id(secondNodeName); // final node2 = Node.Id(secondNodeName);
context.read<HomeBloc>().add(CreateNewNode( // context.read<HomeBloc>().add(CreateNewNode(
sourceNode: node1, destinationNode: node2)); // sourceNode: node1, destinationNode: node2));
}, // },
child: Text("Add"), // child: Text("Add"),
) // )
], // ],
); // );
} // }
if (state is HomeUpdateTree) { // if (state is HomeUpdateTree) {
return Expanded( // return Expanded(
child: InteractiveViewer( // child: InteractiveViewer(
constrained: false, // constrained: false,
boundaryMargin: const EdgeInsets.all(100), // boundaryMargin: const EdgeInsets.all(100),
minScale: 0.01, // minScale: 0.01,
maxScale: 5.6, // maxScale: 5.6,
child: GraphView( // child: GraphView(
graph: state.graph, // graph: state.graph,
algorithm: BuchheimWalkerAlgorithm( // algorithm: BuchheimWalkerAlgorithm(
state.builder, TreeEdgeRenderer(state.builder)), // state.builder, TreeEdgeRenderer(state.builder)),
paint: Paint() // paint: Paint()
..color = Colors.green // ..color = Colors.green
..strokeWidth = 1 // ..strokeWidth = 1
..style = PaintingStyle.stroke, // ..style = PaintingStyle.stroke,
builder: (Node node) { // builder: (Node node) {
// I can decide what widget should be shown here based on the id // // I can decide what widget should be shown here based on the id
var nodeName = node.key!.value; // var nodeName = node.key!.value;
return rectangleWidget(nodeName, node, context); // return rectangleWidget(nodeName, node, context);
}, // },
)), // )),
); // );
} else { // } else {
return Container(); // return Container();
} // }
}) // })
], // ],
), // ),
), // ),
); // );
} // }
} // }
Widget rectangleWidget(String text, Node node, BuildContext blocContext) { // Widget rectangleWidget(String text, Node node, BuildContext blocContext) {
String nodeName = ''; // String nodeName = '';
return InkWell( // return InkWell(
onTap: () { // onTap: () {
showDialog( // showDialog(
context: blocContext, // context: blocContext,
builder: (BuildContext context) { // builder: (BuildContext context) {
return AlertDialog( // return AlertDialog(
title: const Text('Add a child'), // title: const Text('Add a child'),
content: TextField( // content: TextField(
decoration: // decoration:
const InputDecoration(hintText: 'Enter your text here'), // const InputDecoration(hintText: 'Enter your text here'),
onChanged: (value) { // onChanged: (value) {
nodeName = value; // nodeName = value;
}, // },
), // ),
actions: <Widget>[ // actions: <Widget>[
TextButton( // TextButton(
onPressed: () { // onPressed: () {
Navigator.of(context).pop(); // Navigator.of(context).pop();
}, // },
child: Text('Close'), // child: Text('Close'),
), // ),
TextButton( // TextButton(
onPressed: () { // onPressed: () {
if (nodeName.isNotEmpty) { // if (nodeName.isNotEmpty) {
final newNode = Node.Id(nodeName); // final newNode = Node.Id(nodeName);
blocContext.read<HomeBloc>().add(CreateNewNode( // blocContext.read<HomeBloc>().add(CreateNewNode(
sourceNode: node, destinationNode: newNode)); // sourceNode: node, destinationNode: newNode));
} // }
Navigator.of(context).pop(); // Navigator.of(context).pop();
}, // },
child: Text('Add'), // child: Text('Add'),
), // ),
], // ],
); // );
}, // },
); // );
}, // },
child: Container( // child: Container(
width: MediaQuery.of(blocContext).size.width * 0.2, // width: MediaQuery.of(blocContext).size.width * 0.2,
margin: EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0), // margin: EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0),
padding: EdgeInsets.all(20.0), // padding: EdgeInsets.all(20.0),
decoration: BoxDecoration( // decoration: BoxDecoration(
color: Colors.white, // color: Colors.white,
borderRadius: BorderRadius.circular(10.0), // borderRadius: BorderRadius.circular(10.0),
boxShadow: [ // boxShadow: [
BoxShadow( // BoxShadow(
color: Colors.grey.withOpacity(0.5), // color: Colors.grey.withOpacity(0.5),
spreadRadius: 2, // spreadRadius: 2,
blurRadius: 5, // blurRadius: 5,
offset: Offset(0, 3), // changes position of shadow // offset: Offset(0, 3), // changes position of shadow
), // ),
], // ],
), // ),
child: Row( // child: Row(
children: [ // children: [
const SizedBox( // const SizedBox(
child: Icon( // child: Icon(
Icons.location_on, // Icons.location_on,
color: Colors.blue, // color: Colors.blue,
size: 40.0, // size: 40.0,
), // ),
), // ),
const SizedBox(width: 10.0), // const SizedBox(width: 10.0),
SizedBox( // SizedBox(
child: Text( // child: Text(
text, // text,
style: const TextStyle( // style: const TextStyle(
fontSize: 24.0, // fontSize: 24.0,
fontWeight: FontWeight.bold, // fontWeight: FontWeight.bold,
), // ),
), // ),
), // ),
const Spacer(), // const Spacer(),
Container( // Container(
child: const Icon( // child: const Icon(
Icons.add_circle_outline, // Icons.add_circle_outline,
color: Colors.grey, // color: Colors.grey,
size: 24.0, // size: 24.0,
), // ),
), // ),
], // ],
), // ),
), // ),
); // );
} // }

View File

@ -1,85 +0,0 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart';
import 'package:syncrow_web/pages/routiens/widgets/routine_dialogs/ac_dialog.dart';
import 'package:syncrow_web/pages/routiens/widgets/routine_dialogs/one_gang_switch_dialog.dart';
import 'package:syncrow_web/pages/routiens/widgets/routine_dialogs/three_gang_switch_dialog.dart';
import 'package:syncrow_web/pages/routiens/widgets/routine_dialogs/two_gang_switch_dialog.dart';
import 'package:syncrow_web/pages/routiens/models/device_functions.dart';
class DeviceDialogHelper {
static Future<Map<String, dynamic>?> showDeviceDialog(
BuildContext context,
Map<String, dynamic> data, {
required bool removeComparetors,
}) async {
final functions = data['functions'] as List<DeviceFunction>;
try {
final result = await _getDialogForDeviceType(
context,
data['productType'],
data,
functions,
removeComparetors: removeComparetors,
);
if (result != null) {
return result;
}
} catch (e) {
debugPrint('Error: $e');
}
return null;
}
static Future<Map<String, dynamic>?> _getDialogForDeviceType(
BuildContext context,
String productType,
Map<String, dynamic> data,
List<DeviceFunction> functions,
{required bool removeComparetors}) async {
final routineBloc = context.read<RoutineBloc>();
final deviceSelectedFunctions =
routineBloc.state.selectedFunctions[data['uniqueCustomId']] ?? [];
switch (productType) {
case 'AC':
return ACHelper.showACFunctionsDialog(
context,
functions,
data['device'],
deviceSelectedFunctions,
data['uniqueCustomId'],
removeComparetors);
case '1G':
return OneGangSwitchHelper.showSwitchFunctionsDialog(
context,
functions,
data['device'],
deviceSelectedFunctions,
data['uniqueCustomId'],
removeComparetors);
case '2G':
return TwoGangSwitchHelper.showSwitchFunctionsDialog(
context,
functions,
data['device'],
deviceSelectedFunctions,
data['uniqueCustomId'],
removeComparetors);
case '3G':
return ThreeGangSwitchHelper.showSwitchFunctionsDialog(
context,
functions,
data['device'],
deviceSelectedFunctions,
data['uniqueCustomId'],
removeComparetors);
default:
return null;
}
}
}

View File

@ -1,69 +0,0 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart';
import 'package:syncrow_web/pages/routiens/view/create_new_routine_view.dart';
import 'package:syncrow_web/pages/routiens/widgets/main_routine_view/fetch_routine_scenes_automation.dart';
import 'package:syncrow_web/pages/routiens/widgets/main_routine_view/routine_view_card.dart';
import 'package:syncrow_web/utils/color_manager.dart';
class RoutinesView extends StatefulWidget {
const RoutinesView({super.key});
@override
State<RoutinesView> createState() => _RoutinesViewState();
}
class _RoutinesViewState extends State<RoutinesView> {
@override
void initState() {
super.initState();
context.read<RoutineBloc>().add(FetchDevicesInRoutine());
}
@override
Widget build(BuildContext context) {
return BlocBuilder<RoutineBloc, RoutineState>(
builder: (context, state) {
if (state.createRoutineView) {
return const CreateNewRoutineView();
}
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.titleLarge?.copyWith(
color: ColorsManager.grayColor,
fontWeight: FontWeight.bold,
),
),
const SizedBox(
height: 10,
),
RoutineViewCard(
onTap: () {
context.read<RoutineBloc>().add(
(ResetRoutineState()),
);
BlocProvider.of<RoutineBloc>(context).add(
const CreateNewRoutineViewEvent(createRoutineView: true),
);
},
icon: Icons.add,
textString: '',
),
const SizedBox(
height: 15,
),
const Expanded(child: FetchRoutineScenesAutomation()),
],
),
);
},
);
}
}

View File

@ -1,143 +0,0 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart';
import 'package:syncrow_web/pages/routiens/widgets/main_routine_view/routine_view_card.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';
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
class FetchRoutineScenesAutomation extends StatefulWidget {
const FetchRoutineScenesAutomation({super.key});
@override
State<FetchRoutineScenesAutomation> createState() => _FetchRoutineScenesState();
}
class _FetchRoutineScenesState extends State<FetchRoutineScenesAutomation>
with HelperResponsiveLayout {
@override
void initState() {
super.initState();
context.read<RoutineBloc>()
..add(const LoadScenes(spaceId, communityId))
..add(const LoadAutomation(spaceId));
}
@override
Widget build(BuildContext context) {
return BlocBuilder<RoutineBloc, RoutineState>(
builder: (context, state) {
return state.isLoading
? const Center(
child: CircularProgressIndicator(),
)
: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(
"Scenes (Tab to Run)",
style: Theme.of(context).textTheme.titleLarge?.copyWith(
color: ColorsManager.grayColor,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 10),
if (state.scenes.isEmpty)
Text(
"No scenes found",
style: context.textTheme.bodyMedium?.copyWith(
color: ColorsManager.grayColor,
),
),
if (state.scenes.isNotEmpty)
ConstrainedBox(
constraints: BoxConstraints(
maxHeight: isSmallScreenSize(context) ? 160 : 170,
),
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: state.scenes.length,
itemBuilder: (context, index) => Padding(
padding: EdgeInsets.only(
right: isSmallScreenSize(context) ? 4.0 : 8.0,
),
child: RoutineViewCard(
onTap: () {
BlocProvider.of<RoutineBloc>(context).add(
const CreateNewRoutineViewEvent(createRoutineView: true),
);
context.read<RoutineBloc>().add(
GetSceneDetails(
sceneId: state.scenes[index].id,
isTabToRun: true,
isUpdate: true,
),
);
},
textString: state.scenes[index].name,
icon: state.scenes[index].icon ?? Assets.logoHorizontal,
isFromScenes: true,
iconInBytes: state.scenes[index].iconInBytes,
),
),
),
),
const SizedBox(height: 15),
Text(
"Automations",
style: Theme.of(context).textTheme.titleLarge?.copyWith(
color: ColorsManager.grayColor,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 10),
if (state.automations.isEmpty)
Text(
"No automations found",
style: context.textTheme.bodyMedium?.copyWith(
color: ColorsManager.grayColor,
),
),
if (state.automations.isNotEmpty)
ConstrainedBox(
constraints: BoxConstraints(
maxHeight: isSmallScreenSize(context) ? 160 : 170,
),
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: state.automations.length,
itemBuilder: (context, index) => Padding(
padding: EdgeInsets.only(
right: isSmallScreenSize(context) ? 4.0 : 8.0,
),
child: RoutineViewCard(
onTap: () {
BlocProvider.of<RoutineBloc>(context).add(
const CreateNewRoutineViewEvent(createRoutineView: true),
);
context.read<RoutineBloc>().add(
GetAutomationDetails(
automationId: state.automations[index].id,
isAutomation: true,
isUpdate: true),
);
},
textString: state.automations[index].name,
icon: state.automations[index].icon ?? Assets.automation,
),
),
),
),
],
),
),
);
},
);
}
}

View File

@ -1,7 +1,7 @@
import 'dart:async'; import 'dart:async';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/routiens/bloc/effective_period/effect_period_event.dart'; import 'package:syncrow_web/pages/routines/bloc/effective_period/effect_period_event.dart';
import 'package:syncrow_web/pages/routiens/bloc/effective_period/effect_period_state.dart'; import 'package:syncrow_web/pages/routines/bloc/effective_period/effect_period_state.dart';
import 'package:syncrow_web/utils/constants/app_enum.dart'; import 'package:syncrow_web/utils/constants/app_enum.dart';
class EffectPeriodBloc extends Bloc<EffectPeriodEvent, EffectPeriodState> { class EffectPeriodBloc extends Bloc<EffectPeriodEvent, EffectPeriodState> {

View File

@ -1,5 +1,5 @@
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import 'package:syncrow_web/pages/routiens/models/create_scene_and_autoamtion/create_automation_model.dart'; import 'package:syncrow_web/pages/routines/models/create_scene_and_autoamtion/create_automation_model.dart';
import 'package:syncrow_web/utils/constants/app_enum.dart'; import 'package:syncrow_web/utils/constants/app_enum.dart';
abstract class EffectPeriodEvent extends Equatable { abstract class EffectPeriodEvent extends Equatable {

View File

@ -2,7 +2,7 @@ import 'dart:async';
import 'package:bloc/bloc.dart'; import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import 'package:syncrow_web/pages/routiens/models/device_functions.dart'; import 'package:syncrow_web/pages/routines/models/device_functions.dart';
part 'functions_bloc_event.dart'; part 'functions_bloc_event.dart';
part 'functions_bloc_state.dart'; part 'functions_bloc_state.dart';
@ -26,8 +26,7 @@ class FunctionBloc extends Bloc<FunctionBlocEvent, FunctionBlocState> {
functionCode: event.functionData.functionCode, functionCode: event.functionData.functionCode,
operationName: event.functionData.operationName, operationName: event.functionData.operationName,
value: event.functionData.value ?? existingData.value, value: event.functionData.value ?? existingData.value,
valueDescription: event.functionData.valueDescription ?? valueDescription: event.functionData.valueDescription ?? existingData.valueDescription,
existingData.valueDescription,
condition: event.functionData.condition ?? existingData.condition, condition: event.functionData.condition ?? existingData.condition,
); );
} else { } else {
@ -59,10 +58,8 @@ class FunctionBloc extends Bloc<FunctionBlocEvent, FunctionBlocState> {
); );
} }
FutureOr<void> _onSelectFunction( FutureOr<void> _onSelectFunction(SelectFunction event, Emitter<FunctionBlocState> emit) {
SelectFunction event, Emitter<FunctionBlocState> emit) {
emit(state.copyWith( emit(state.copyWith(
selectedFunction: event.functionCode, selectedFunction: event.functionCode, selectedOperationName: event.operationName));
selectedOperationName: event.operationName));
} }
} }

View File

@ -4,12 +4,12 @@ import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
import 'package:syncrow_web/pages/routiens/models/create_scene_and_autoamtion/create_automation_model.dart'; import 'package:syncrow_web/pages/routines/models/create_scene_and_autoamtion/create_automation_model.dart';
import 'package:syncrow_web/pages/routiens/models/create_scene_and_autoamtion/create_scene_model.dart'; import 'package:syncrow_web/pages/routines/models/create_scene_and_autoamtion/create_scene_model.dart';
import 'package:syncrow_web/pages/routiens/models/delay/delay_fucntions.dart'; import 'package:syncrow_web/pages/routines/models/delay/delay_fucntions.dart';
import 'package:syncrow_web/pages/routiens/models/device_functions.dart'; import 'package:syncrow_web/pages/routines/models/device_functions.dart';
import 'package:syncrow_web/pages/routiens/models/routine_details_model.dart'; import 'package:syncrow_web/pages/routines/models/routine_details_model.dart';
import 'package:syncrow_web/pages/routiens/models/routine_model.dart'; import 'package:syncrow_web/pages/routines/models/routine_model.dart';
import 'package:syncrow_web/services/devices_mang_api.dart'; import 'package:syncrow_web/services/devices_mang_api.dart';
import 'package:syncrow_web/services/routines_api.dart'; import 'package:syncrow_web/services/routines_api.dart';
import 'package:syncrow_web/utils/constants/assets.dart'; import 'package:syncrow_web/utils/constants/assets.dart';
@ -19,8 +19,8 @@ import 'package:uuid/uuid.dart';
part 'routine_event.dart'; part 'routine_event.dart';
part 'routine_state.dart'; part 'routine_state.dart';
const spaceId = '25c96044-fadf-44bb-93c7-3c079e527ce6'; String spaceId = '25c96044-fadf-44bb-93c7-3c079e527ce6';
const communityId = 'aff21a57-2f91-4e5c-b99b-0182c3ab65a9'; String communityId = 'aff21a57-2f91-4e5c-b99b-0182c3ab65a9';
class RoutineBloc extends Bloc<RoutineEvent, RoutineState> { class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
RoutineBloc() : super(const RoutineState()) { RoutineBloc() : super(const RoutineState()) {
@ -57,8 +57,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
emit(state.copyWith(routineTab: event.isRoutineTab, createRoutineView: false)); emit(state.copyWith(routineTab: event.isRoutineTab, createRoutineView: false));
add(ResetRoutineState()); add(ResetRoutineState());
if (event.isRoutineTab) { if (event.isRoutineTab) {
add(const LoadScenes(spaceId, communityId)); add(LoadScenes(spaceId, communityId));
add(const LoadAutomation(spaceId)); add(LoadAutomation(spaceId));
} }
} }
@ -156,18 +156,25 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
emit(state.copyWith(isLoading: true, errorMessage: null)); emit(state.copyWith(isLoading: true, errorMessage: null));
try { try {
final scenes = await SceneApi.getScenesByUnitId(event.unitId, event.communityId); spaceId = event.spaceId;
communityId = event.communityId;
List<ScenesModel> scenes = [];
if (communityId.isNotEmpty && spaceId.isNotEmpty) {
scenes = await SceneApi.getScenes(event.spaceId, event.communityId);
}
emit(state.copyWith( emit(state.copyWith(
scenes: scenes, scenes: scenes,
isLoading: false, isLoading: false,
)); ));
} catch (e) { } catch (e) {
emit(state.copyWith( emit(state.copyWith(
isLoading: false, isLoading: false,
loadScenesErrorMessage: 'Failed to load scenes', loadScenesErrorMessage: 'Failed to load scenes',
errorMessage: '', errorMessage: '',
loadAutomationErrorMessage: '', loadAutomationErrorMessage: '',
)); scenes: []));
} }
} }
@ -175,27 +182,22 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
emit(state.copyWith(isLoading: true, errorMessage: null)); emit(state.copyWith(isLoading: true, errorMessage: null));
try { try {
final automations = await SceneApi.getAutomationByUnitId(event.unitId); spaceId = event.spaceId;
if (automations.isNotEmpty) { List<ScenesModel> automations = [];
emit(state.copyWith( if (spaceId.isNotEmpty) {
automations: automations, automations = await SceneApi.getAutomation(event.spaceId);
isLoading: false, }
)); emit(state.copyWith(
} else { automations: automations,
emit(state.copyWith( isLoading: false,
));
} catch (e) {
emit(state.copyWith(
isLoading: false, isLoading: false,
loadAutomationErrorMessage: 'Failed to load automations', loadAutomationErrorMessage: 'Failed to load automations',
errorMessage: '', errorMessage: '',
loadScenesErrorMessage: '', loadScenesErrorMessage: '',
)); automations: []));
}
} catch (e) {
emit(state.copyWith(
isLoading: false,
loadAutomationErrorMessage: 'Failed to load automations',
errorMessage: '',
loadScenesErrorMessage: '',
));
} }
} }
@ -290,8 +292,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
final result = await SceneApi.createScene(createSceneModel); final result = await SceneApi.createScene(createSceneModel);
if (result['success']) { if (result['success']) {
add(ResetRoutineState()); add(ResetRoutineState());
add(const LoadScenes(spaceId, communityId)); add(LoadScenes(spaceId, communityId));
add(const LoadAutomation(spaceId)); add(LoadAutomation(spaceId));
} else { } else {
emit(state.copyWith( emit(state.copyWith(
isLoading: false, isLoading: false,
@ -419,8 +421,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
final result = await SceneApi.createAutomation(createAutomationModel); final result = await SceneApi.createAutomation(createAutomationModel);
if (result['success']) { if (result['success']) {
add(ResetRoutineState()); add(ResetRoutineState());
add(const LoadAutomation(spaceId)); add(LoadAutomation(spaceId));
add(const LoadScenes(spaceId, communityId)); add(LoadScenes(spaceId, communityId));
} else { } else {
emit(state.copyWith( emit(state.copyWith(
isLoading: false, isLoading: false,
@ -785,8 +787,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
SceneApi.deleteAutomation(unitUuid: spaceId, automationId: state.automationId ?? ''); SceneApi.deleteAutomation(unitUuid: spaceId, automationId: state.automationId ?? '');
} }
add(const LoadScenes(spaceId, communityId)); add(LoadScenes(spaceId, communityId));
add(const LoadAutomation(spaceId)); add(LoadAutomation(spaceId));
add(ResetRoutineState()); add(ResetRoutineState());
emit(state.copyWith(isLoading: false, createRoutineView: false)); emit(state.copyWith(isLoading: false, createRoutineView: false));
} catch (e) { } catch (e) {
@ -814,7 +816,7 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
FutureOr<void> _fetchDevices(FetchDevicesInRoutine event, Emitter<RoutineState> emit) async { FutureOr<void> _fetchDevices(FetchDevicesInRoutine event, Emitter<RoutineState> emit) async {
emit(state.copyWith(isLoading: true)); emit(state.copyWith(isLoading: true));
try { try {
final devices = await DevicesManagementApi().fetchDevices(); final devices = await DevicesManagementApi().fetchDevices(communityId, spaceId);
emit(state.copyWith(isLoading: false, devices: devices)); emit(state.copyWith(isLoading: false, devices: devices));
} catch (e) { } catch (e) {
@ -892,8 +894,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
final result = await SceneApi.updateScene(createSceneModel, state.sceneId ?? ''); final result = await SceneApi.updateScene(createSceneModel, state.sceneId ?? '');
if (result['success']) { if (result['success']) {
add(ResetRoutineState()); add(ResetRoutineState());
add(const LoadScenes(spaceId, communityId)); add(LoadScenes(spaceId, communityId));
add(const LoadAutomation(spaceId)); add(LoadAutomation(spaceId));
} else { } else {
emit(state.copyWith( emit(state.copyWith(
isLoading: false, isLoading: false,
@ -1021,8 +1023,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
if (result['success']) { if (result['success']) {
add(ResetRoutineState()); add(ResetRoutineState());
add(const LoadAutomation(spaceId)); add(LoadAutomation(spaceId));
add(const LoadScenes(spaceId, communityId)); add(LoadScenes(spaceId, communityId));
} else { } else {
emit(state.copyWith( emit(state.copyWith(
isLoading: false, isLoading: false,

View File

@ -27,22 +27,22 @@ class AddToThenContainer extends RoutineEvent {
} }
class LoadScenes extends RoutineEvent { class LoadScenes extends RoutineEvent {
final String unitId; final String spaceId;
final String communityId; final String communityId;
const LoadScenes(this.unitId, this.communityId); const LoadScenes(this.spaceId, this.communityId);
@override @override
List<Object> get props => [unitId, communityId]; List<Object> get props => [spaceId, communityId];
} }
class LoadAutomation extends RoutineEvent { class LoadAutomation extends RoutineEvent {
final String unitId; final String spaceId;
const LoadAutomation(this.unitId); const LoadAutomation(this.spaceId);
@override @override
List<Object> get props => [unitId]; List<Object> get props => [spaceId];
} }
class AddFunctionToRoutine extends RoutineEvent { class AddFunctionToRoutine extends RoutineEvent {

View File

@ -1,7 +1,7 @@
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/routiens/bloc/setting_bloc/setting_event.dart'; import 'package:syncrow_web/pages/routines/bloc/setting_bloc/setting_event.dart';
import 'package:syncrow_web/pages/routiens/bloc/setting_bloc/setting_state.dart'; import 'package:syncrow_web/pages/routines/bloc/setting_bloc/setting_state.dart';
import 'package:syncrow_web/pages/routiens/models/icon_model.dart'; import 'package:syncrow_web/pages/routines/models/icon_model.dart';
import 'package:syncrow_web/services/routines_api.dart'; import 'package:syncrow_web/services/routines_api.dart';
class SettingBloc extends Bloc<SettingEvent, SettingState> { class SettingBloc extends Bloc<SettingEvent, SettingState> {

View File

@ -1,5 +1,5 @@
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import 'package:syncrow_web/pages/routiens/models/icon_model.dart'; import 'package:syncrow_web/pages/routines/models/icon_model.dart';
abstract class SettingState extends Equatable { abstract class SettingState extends Equatable {
const SettingState(); const SettingState();

View File

@ -0,0 +1,62 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart';
import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/ac_dialog.dart';
import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/one_gang_switch_dialog.dart';
import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/three_gang_switch_dialog.dart';
import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/two_gang_switch_dialog.dart';
import 'package:syncrow_web/pages/routines/models/device_functions.dart';
class DeviceDialogHelper {
static Future<Map<String, dynamic>?> showDeviceDialog(
BuildContext context,
Map<String, dynamic> data, {
required bool removeComparetors,
}) async {
final functions = data['functions'] as List<DeviceFunction>;
try {
final result = await _getDialogForDeviceType(
context,
data['productType'],
data,
functions,
removeComparetors: removeComparetors,
);
if (result != null) {
return result;
}
} catch (e) {
debugPrint('Error: $e');
}
return null;
}
static Future<Map<String, dynamic>?> _getDialogForDeviceType(BuildContext context,
String productType, Map<String, dynamic> data, List<DeviceFunction> functions,
{required bool removeComparetors}) async {
final routineBloc = context.read<RoutineBloc>();
final deviceSelectedFunctions =
routineBloc.state.selectedFunctions[data['uniqueCustomId']] ?? [];
switch (productType) {
case 'AC':
return ACHelper.showACFunctionsDialog(context, functions, data['device'],
deviceSelectedFunctions, data['uniqueCustomId'], removeComparetors);
case '1G':
return OneGangSwitchHelper.showSwitchFunctionsDialog(context, functions, data['device'],
deviceSelectedFunctions, data['uniqueCustomId'], removeComparetors);
case '2G':
return TwoGangSwitchHelper.showSwitchFunctionsDialog(context, functions, data['device'],
deviceSelectedFunctions, data['uniqueCustomId'], removeComparetors);
case '3G':
return ThreeGangSwitchHelper.showSwitchFunctionsDialog(context, functions, data['device'],
deviceSelectedFunctions, data['uniqueCustomId'], removeComparetors);
default:
return null;
}
}
}

View File

@ -3,9 +3,9 @@ import 'dart:convert';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart'; import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart';
import 'package:syncrow_web/pages/routiens/widgets/dialog_header.dart'; import 'package:syncrow_web/pages/routines/widgets/dialog_header.dart';
import 'package:syncrow_web/pages/routiens/widgets/dialog_footer.dart'; import 'package:syncrow_web/pages/routines/widgets/dialog_footer.dart';
import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/constants/assets.dart'; import 'package:syncrow_web/utils/constants/assets.dart';
import 'package:syncrow_web/utils/extension/build_context_x.dart'; import 'package:syncrow_web/utils/extension/build_context_x.dart';

View File

@ -1,6 +1,6 @@
import 'package:syncrow_web/pages/device_managment/ac/model/ac_model.dart'; import 'package:syncrow_web/pages/device_managment/ac/model/ac_model.dart';
import 'package:syncrow_web/pages/routiens/models/ac/ac_operational_value.dart'; import 'package:syncrow_web/pages/routines/models/ac/ac_operational_value.dart';
import 'package:syncrow_web/pages/routiens/models/device_functions.dart'; import 'package:syncrow_web/pages/routines/models/device_functions.dart';
import 'package:syncrow_web/utils/constants/app_enum.dart'; import 'package:syncrow_web/utils/constants/app_enum.dart';
import 'package:syncrow_web/utils/constants/assets.dart'; import 'package:syncrow_web/utils/constants/assets.dart';

View File

@ -1,5 +1,5 @@
import 'package:syncrow_web/pages/routiens/models/gang_switches/base_switch_function.dart'; import 'package:syncrow_web/pages/routines/models/gang_switches/base_switch_function.dart';
import 'package:syncrow_web/pages/routiens/models/gang_switches/switch_operational_value.dart'; import 'package:syncrow_web/pages/routines/models/gang_switches/switch_operational_value.dart';
import 'package:syncrow_web/utils/constants/assets.dart'; import 'package:syncrow_web/utils/constants/assets.dart';
class DelayFunction extends BaseSwitchFunction { class DelayFunction extends BaseSwitchFunction {

View File

@ -1,5 +1,5 @@
import 'package:syncrow_web/pages/routiens/models/device_functions.dart'; import 'package:syncrow_web/pages/routines/models/device_functions.dart';
import 'package:syncrow_web/pages/routiens/models/gang_switches/switch_operational_value.dart'; import 'package:syncrow_web/pages/routines/models/gang_switches/switch_operational_value.dart';
abstract class BaseSwitchFunction extends DeviceFunction<bool> { abstract class BaseSwitchFunction extends DeviceFunction<bool> {
BaseSwitchFunction({ BaseSwitchFunction({

View File

@ -1,5 +1,5 @@
import 'package:syncrow_web/pages/routiens/models/gang_switches/base_switch_function.dart'; import 'package:syncrow_web/pages/routines/models/gang_switches/base_switch_function.dart';
import 'package:syncrow_web/pages/routiens/models/gang_switches/switch_operational_value.dart'; import 'package:syncrow_web/pages/routines/models/gang_switches/switch_operational_value.dart';
import 'package:syncrow_web/utils/constants/assets.dart'; import 'package:syncrow_web/utils/constants/assets.dart';
class OneGangSwitchFunction extends BaseSwitchFunction { class OneGangSwitchFunction extends BaseSwitchFunction {

View File

@ -1,5 +1,5 @@
import 'package:syncrow_web/pages/routiens/models/gang_switches/base_switch_function.dart'; import 'package:syncrow_web/pages/routines/models/gang_switches/base_switch_function.dart';
import 'package:syncrow_web/pages/routiens/models/gang_switches/switch_operational_value.dart'; import 'package:syncrow_web/pages/routines/models/gang_switches/switch_operational_value.dart';
import 'package:syncrow_web/utils/constants/assets.dart'; import 'package:syncrow_web/utils/constants/assets.dart';
class ThreeGangSwitch1Function extends BaseSwitchFunction { class ThreeGangSwitch1Function extends BaseSwitchFunction {
@ -26,8 +26,7 @@ class ThreeGangSwitch1Function extends BaseSwitchFunction {
} }
class ThreeGangCountdown1Function extends BaseSwitchFunction { class ThreeGangCountdown1Function extends BaseSwitchFunction {
ThreeGangCountdown1Function( ThreeGangCountdown1Function({required super.deviceId, required super.deviceName})
{required super.deviceId, required super.deviceName})
: super( : super(
code: 'countdown_1', code: 'countdown_1',
operationName: 'Light 1 Countdown', operationName: 'Light 1 Countdown',
@ -71,8 +70,7 @@ class ThreeGangSwitch2Function extends BaseSwitchFunction {
} }
class ThreeGangCountdown2Function extends BaseSwitchFunction { class ThreeGangCountdown2Function extends BaseSwitchFunction {
ThreeGangCountdown2Function( ThreeGangCountdown2Function({required super.deviceId, required super.deviceName})
{required super.deviceId, required super.deviceName})
: super( : super(
code: 'countdown_2', code: 'countdown_2',
operationName: 'Light 2 Countdown', operationName: 'Light 2 Countdown',
@ -116,8 +114,7 @@ class ThreeGangSwitch3Function extends BaseSwitchFunction {
} }
class ThreeGangCountdown3Function extends BaseSwitchFunction { class ThreeGangCountdown3Function extends BaseSwitchFunction {
ThreeGangCountdown3Function( ThreeGangCountdown3Function({required super.deviceId, required super.deviceName})
{required super.deviceId, required super.deviceName})
: super( : super(
code: 'countdown_3', code: 'countdown_3',
operationName: 'Light 3 Countdown', operationName: 'Light 3 Countdown',

View File

@ -1,5 +1,5 @@
import 'package:syncrow_web/pages/routiens/models/gang_switches/base_switch_function.dart'; import 'package:syncrow_web/pages/routines/models/gang_switches/base_switch_function.dart';
import 'package:syncrow_web/pages/routiens/models/gang_switches/switch_operational_value.dart'; import 'package:syncrow_web/pages/routines/models/gang_switches/switch_operational_value.dart';
import 'package:syncrow_web/utils/constants/assets.dart'; import 'package:syncrow_web/utils/constants/assets.dart';
class TwoGangSwitch1Function extends BaseSwitchFunction { class TwoGangSwitch1Function extends BaseSwitchFunction {
@ -49,8 +49,7 @@ class TwoGangSwitch2Function extends BaseSwitchFunction {
} }
class TwoGangCountdown1Function extends BaseSwitchFunction { class TwoGangCountdown1Function extends BaseSwitchFunction {
TwoGangCountdown1Function( TwoGangCountdown1Function({required super.deviceId, required super.deviceName})
{required super.deviceId, required super.deviceName})
: super( : super(
code: 'countdown_1', code: 'countdown_1',
operationName: 'Light 1 Countdown', operationName: 'Light 1 Countdown',
@ -71,8 +70,7 @@ class TwoGangCountdown1Function extends BaseSwitchFunction {
} }
class TwoGangCountdown2Function extends BaseSwitchFunction { class TwoGangCountdown2Function extends BaseSwitchFunction {
TwoGangCountdown2Function( TwoGangCountdown2Function({required super.deviceId, required super.deviceName})
{required super.deviceId, required super.deviceName})
: super( : super(
code: 'countdown_2', code: 'countdown_2',
operationName: 'Light 2 Countdown', operationName: 'Light 2 Countdown',

View File

@ -1,7 +1,7 @@
import 'dart:convert'; import 'dart:convert';
import 'package:syncrow_web/pages/routiens/models/create_scene_and_autoamtion/create_automation_model.dart'; import 'package:syncrow_web/pages/routines/models/create_scene_and_autoamtion/create_automation_model.dart';
import 'package:syncrow_web/pages/routiens/models/create_scene_and_autoamtion/create_scene_model.dart'; import 'package:syncrow_web/pages/routines/models/create_scene_and_autoamtion/create_scene_model.dart';
class RoutineDetailsModel { class RoutineDetailsModel {
final String spaceUuid; final String spaceUuid;

View File

@ -1,8 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:syncrow_web/pages/routiens/widgets/conditions_routines_devices_view.dart'; import 'package:syncrow_web/pages/routines/widgets/conditions_routines_devices_view.dart';
import 'package:syncrow_web/pages/routiens/widgets/if_container.dart'; import 'package:syncrow_web/pages/routines/widgets/if_container.dart';
import 'package:syncrow_web/pages/routiens/widgets/routine_search_and_buttons.dart'; import 'package:syncrow_web/pages/routines/widgets/routine_search_and_buttons.dart';
import 'package:syncrow_web/pages/routiens/widgets/then_container.dart'; import 'package:syncrow_web/pages/routines/widgets/then_container.dart';
import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
class CreateNewRoutineView extends StatelessWidget { class CreateNewRoutineView extends StatelessWidget {

View File

@ -1,7 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:syncrow_web/pages/routiens/widgets/routine_dialogs/effictive_period_dialog.dart'; import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/effictive_period_dialog.dart';
import 'package:syncrow_web/pages/routiens/widgets/period_option.dart'; import 'package:syncrow_web/pages/routines/widgets/period_option.dart';
import 'package:syncrow_web/pages/routiens/widgets/repeat_days.dart'; import 'package:syncrow_web/pages/routines/widgets/repeat_days.dart';
import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
class EffectivePeriodView extends StatelessWidget { class EffectivePeriodView extends StatelessWidget {

View File

@ -0,0 +1,95 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart';
import 'package:syncrow_web/pages/routines/view/create_new_routine_view.dart';
import 'package:syncrow_web/pages/routines/widgets/main_routine_view/fetch_routine_scenes_automation.dart';
import 'package:syncrow_web/pages/routines/widgets/main_routine_view/routine_view_card.dart';
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_bloc.dart';
import 'package:syncrow_web/pages/space_tree/view/side_spaces_view.dart';
import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/snack_bar.dart';
class RoutinesView extends StatefulWidget {
const RoutinesView({super.key});
@override
State<RoutinesView> createState() => _RoutinesViewState();
}
class _RoutinesViewState extends State<RoutinesView> {
@override
void initState() {
super.initState();
context.read<RoutineBloc>().add(FetchDevicesInRoutine());
}
@override
Widget build(BuildContext context) {
return BlocBuilder<RoutineBloc, RoutineState>(
builder: (context, state) {
if (state.createRoutineView) {
return const CreateNewRoutineView();
}
return Row(
children: [
Expanded(child: SideSpacesView(
onSelectAction: (String communityId, String spaceId) {
context.read<RoutineBloc>()
..add(LoadScenes(spaceId, communityId))
..add(LoadAutomation(spaceId));
},
)),
Expanded(
flex: 3,
child: Padding(
padding: const EdgeInsets.all(16),
child: Row(
children: [
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
"Create New Routines",
style: Theme.of(context).textTheme.titleLarge?.copyWith(
color: ColorsManager.grayColor,
fontWeight: FontWeight.bold,
),
),
const SizedBox(
height: 10,
),
RoutineViewCard(
onTap: () {
if (context.read<SpaceTreeBloc>().selectedCommunityId.isNotEmpty &&
context.read<SpaceTreeBloc>().selectedSpaceId.isNotEmpty) {
context.read<RoutineBloc>().add(
(ResetRoutineState()),
);
BlocProvider.of<RoutineBloc>(context).add(
const CreateNewRoutineViewEvent(createRoutineView: true),
);
} else {
CustomSnackBar.redSnackBar('Please select a space');
}
},
icon: Icons.add,
textString: '',
),
const SizedBox(
height: 15,
),
const Expanded(child: FetchRoutineScenesAutomation()),
],
),
],
),
),
),
],
);
},
);
}
}

View File

@ -1,11 +1,11 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart'; import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart';
import 'package:syncrow_web/pages/routiens/widgets/dragable_card.dart'; import 'package:syncrow_web/pages/routines/widgets/dragable_card.dart';
import 'package:syncrow_web/pages/routiens/widgets/routine_devices.dart'; import 'package:syncrow_web/pages/routines/widgets/routine_devices.dart';
import 'package:syncrow_web/pages/routiens/widgets/routines_title_widget.dart'; import 'package:syncrow_web/pages/routines/widgets/routines_title_widget.dart';
import 'package:syncrow_web/pages/routiens/widgets/scenes_and_automations.dart'; import 'package:syncrow_web/pages/routines/widgets/scenes_and_automations.dart';
import 'package:syncrow_web/pages/routiens/widgets/search_bar_condition_title.dart'; import 'package:syncrow_web/pages/routines/widgets/search_bar_condition_title.dart';
import 'package:syncrow_web/utils/constants/assets.dart'; import 'package:syncrow_web/utils/constants/assets.dart';
class ConditionsRoutinesDevicesView extends StatelessWidget { class ConditionsRoutinesDevicesView extends StatelessWidget {

View File

@ -1,7 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/common/custom_dialog.dart'; import 'package:syncrow_web/pages/common/custom_dialog.dart';
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart'; import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart';
import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
class DeleteSceneWidget extends StatelessWidget { class DeleteSceneWidget extends StatelessWidget {

View File

@ -3,8 +3,8 @@ import 'dart:convert';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart'; import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart';
import 'package:syncrow_web/pages/routiens/models/device_functions.dart'; import 'package:syncrow_web/pages/routines/models/device_functions.dart';
import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/extension/build_context_x.dart'; import 'package:syncrow_web/utils/extension/build_context_x.dart';

View File

@ -1,8 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart'; import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart';
import 'package:syncrow_web/pages/routiens/helper/dialog_helper/device_dialog_helper.dart'; import 'package:syncrow_web/pages/routines/helper/dialog_helper/device_dialog_helper.dart';
import 'package:syncrow_web/pages/routiens/widgets/dragable_card.dart'; import 'package:syncrow_web/pages/routines/widgets/dragable_card.dart';
import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/constants/assets.dart'; import 'package:syncrow_web/utils/constants/assets.dart';
import 'package:syncrow_web/utils/extension/build_context_x.dart'; import 'package:syncrow_web/utils/extension/build_context_x.dart';
@ -26,9 +26,7 @@ class IfContainer extends StatelessWidget {
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
const Text('IF', const Text('IF', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
style: TextStyle(
fontSize: 18, fontWeight: FontWeight.bold)),
if (state.isAutomation && state.ifItems.isNotEmpty) if (state.isAutomation && state.ifItems.isNotEmpty)
AutomationOperatorSelector( AutomationOperatorSelector(
selectedOperator: state.selectedAutomationOperator), selectedOperator: state.selectedAutomationOperator),
@ -55,44 +53,34 @@ class IfContainer extends StatelessWidget {
(index) => GestureDetector( (index) => GestureDetector(
onTap: () async { onTap: () async {
if (!state.isTabToRun) { if (!state.isTabToRun) {
final result = await DeviceDialogHelper final result = await DeviceDialogHelper.showDeviceDialog(
.showDeviceDialog( context, state.ifItems[index],
context, state.ifItems[index], removeComparetors: false);
removeComparetors: false);
if (result != null) { if (result != null) {
context.read<RoutineBloc>().add( context
AddToIfContainer( .read<RoutineBloc>()
state.ifItems[index], false)); .add(AddToIfContainer(state.ifItems[index], false));
} else if (![ } else if (!['AC', '1G', '2G', '3G']
'AC', .contains(state.ifItems[index]['productType'])) {
'1G', context
'2G', .read<RoutineBloc>()
'3G' .add(AddToIfContainer(state.ifItems[index], false));
].contains(
state.ifItems[index]['productType'])) {
context.read<RoutineBloc>().add(
AddToIfContainer(
state.ifItems[index], false));
} }
} }
}, },
child: DraggableCard( child: DraggableCard(
imagePath: imagePath: state.ifItems[index]['imagePath'] ?? '',
state.ifItems[index]['imagePath'] ?? '',
title: state.ifItems[index]['title'] ?? '', title: state.ifItems[index]['title'] ?? '',
deviceData: state.ifItems[index], deviceData: state.ifItems[index],
padding: const EdgeInsets.symmetric( padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 8),
horizontal: 4, vertical: 8),
isFromThen: false, isFromThen: false,
isFromIf: true, isFromIf: true,
onRemove: () { onRemove: () {
context.read<RoutineBloc>().add( context.read<RoutineBloc>().add(RemoveDragCard(
RemoveDragCard( index: index,
index: index, isFromThen: false,
isFromThen: false, key: state.ifItems[index]['uniqueCustomId']));
key: state.ifItems[index]
['uniqueCustomId']));
}, },
), ),
)), )),
@ -113,23 +101,15 @@ class IfContainer extends StatelessWidget {
if (!state.isTabToRun) { if (!state.isTabToRun) {
if (mutableData['deviceId'] == 'tab_to_run') { if (mutableData['deviceId'] == 'tab_to_run') {
context context.read<RoutineBloc>().add(AddToIfContainer(mutableData, true));
.read<RoutineBloc>()
.add(AddToIfContainer(mutableData, true));
} else { } else {
final result = await DeviceDialogHelper.showDeviceDialog( final result = await DeviceDialogHelper.showDeviceDialog(context, mutableData,
context, mutableData,
removeComparetors: false); removeComparetors: false);
if (result != null) { if (result != null) {
context context.read<RoutineBloc>().add(AddToIfContainer(mutableData, false));
.read<RoutineBloc>() } else if (!['AC', '1G', '2G', '3G'].contains(mutableData['productType'])) {
.add(AddToIfContainer(mutableData, false)); context.read<RoutineBloc>().add(AddToIfContainer(mutableData, false));
} else if (!['AC', '1G', '2G', '3G']
.contains(mutableData['productType'])) {
context
.read<RoutineBloc>()
.add(AddToIfContainer(mutableData, false));
} }
} }
} }
@ -175,9 +155,7 @@ class AutomationOperatorSelector extends StatelessWidget {
), ),
), ),
onPressed: () { onPressed: () {
context context.read<RoutineBloc>().add(const ChangeAutomationOperator(operator: 'or'));
.read<RoutineBloc>()
.add(const ChangeAutomationOperator(operator: 'or'));
}, },
), ),
Container( Container(
@ -203,9 +181,7 @@ class AutomationOperatorSelector extends StatelessWidget {
), ),
), ),
onPressed: () { onPressed: () {
context context.read<RoutineBloc>().add(const ChangeAutomationOperator(operator: 'and'));
.read<RoutineBloc>()
.add(const ChangeAutomationOperator(operator: 'and'));
}, },
), ),
], ],

View File

@ -0,0 +1,143 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart';
import 'package:syncrow_web/pages/routines/widgets/main_routine_view/routine_view_card.dart';
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_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';
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
class FetchRoutineScenesAutomation extends StatefulWidget {
const FetchRoutineScenesAutomation({super.key});
@override
State<FetchRoutineScenesAutomation> createState() => _FetchRoutineScenesState();
}
class _FetchRoutineScenesState extends State<FetchRoutineScenesAutomation>
with HelperResponsiveLayout {
@override
void initState() {
super.initState();
context.read<RoutineBloc>()
..add(LoadScenes(context.read<SpaceTreeBloc>().selectedSpaceId,
context.read<SpaceTreeBloc>().selectedCommunityId))
..add(LoadAutomation(context.read<SpaceTreeBloc>().selectedSpaceId));
}
@override
Widget build(BuildContext context) {
return BlocBuilder<RoutineBloc, RoutineState>(
builder: (context, state) {
return state.isLoading
? const Center(
child: CircularProgressIndicator(),
)
: Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(
"Scenes (Tab to Run)",
style: Theme.of(context).textTheme.titleLarge?.copyWith(
color: ColorsManager.grayColor,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 10),
if (state.scenes.isEmpty)
Text(
"No scenes found",
style: context.textTheme.bodyMedium?.copyWith(
color: ColorsManager.grayColor,
),
),
if (state.scenes.isNotEmpty)
ConstrainedBox(
constraints: BoxConstraints(
maxHeight: isSmallScreenSize(context) ? 160 : 170,
maxWidth: MediaQuery.sizeOf(context).width * 0.7),
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: state.scenes.length,
itemBuilder: (context, index) => Padding(
padding: EdgeInsets.only(
right: isSmallScreenSize(context) ? 4.0 : 8.0,
),
child: RoutineViewCard(
onTap: () {
BlocProvider.of<RoutineBloc>(context).add(
const CreateNewRoutineViewEvent(createRoutineView: true),
);
context.read<RoutineBloc>().add(
GetSceneDetails(
sceneId: state.scenes[index].id,
isTabToRun: true,
isUpdate: true,
),
);
},
textString: state.scenes[index].name,
icon: state.scenes[index].icon ?? Assets.logoHorizontal,
isFromScenes: true,
iconInBytes: state.scenes[index].iconInBytes,
),
),
),
),
const SizedBox(height: 15),
Text(
"Automations",
style: Theme.of(context).textTheme.titleLarge?.copyWith(
color: ColorsManager.grayColor,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 10),
if (state.automations.isEmpty)
Text(
"No automations found",
style: context.textTheme.bodyMedium?.copyWith(
color: ColorsManager.grayColor,
),
),
if (state.automations.isNotEmpty)
ConstrainedBox(
constraints: BoxConstraints(
maxHeight: isSmallScreenSize(context) ? 160 : 170,
maxWidth: MediaQuery.sizeOf(context).width * 0.7),
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: state.automations.length,
itemBuilder: (context, index) => Padding(
padding: EdgeInsets.only(
right: isSmallScreenSize(context) ? 4.0 : 8.0,
),
child: RoutineViewCard(
onTap: () {
BlocProvider.of<RoutineBloc>(context).add(
const CreateNewRoutineViewEvent(createRoutineView: true),
);
context.read<RoutineBloc>().add(
GetAutomationDetails(
automationId: state.automations[index].id,
isAutomation: true,
isUpdate: true),
);
},
textString: state.automations[index].name,
icon: state.automations[index].icon ?? Assets.automation,
),
),
),
),
],
),
);
},
);
}
}

View File

@ -70,15 +70,13 @@ class RoutineViewCard extends StatelessWidget with HelperResponsiveLayout {
height: iconSize, height: iconSize,
width: iconSize, width: iconSize,
child: (isFromScenes ?? false) child: (isFromScenes ?? false)
? (iconInBytes != null && ? (iconInBytes != null && iconInBytes?.isNotEmpty == true)
iconInBytes?.isNotEmpty == true)
? Image.memory( ? Image.memory(
iconInBytes!, iconInBytes!,
height: iconSize, height: iconSize,
width: iconSize, width: iconSize,
fit: BoxFit.contain, fit: BoxFit.contain,
errorBuilder: (context, error, stackTrace) => errorBuilder: (context, error, stackTrace) => Image.asset(
Image.asset(
Assets.logo, Assets.logo,
height: iconSize, height: iconSize,
width: iconSize, width: iconSize,

View File

@ -1,9 +1,9 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/routiens/bloc/effective_period/effect_period_bloc.dart'; import 'package:syncrow_web/pages/routines/bloc/effective_period/effect_period_bloc.dart';
import 'package:syncrow_web/pages/routiens/bloc/effective_period/effect_period_event.dart'; import 'package:syncrow_web/pages/routines/bloc/effective_period/effect_period_event.dart';
import 'package:syncrow_web/pages/routiens/bloc/effective_period/effect_period_state.dart'; import 'package:syncrow_web/pages/routines/bloc/effective_period/effect_period_state.dart';
import 'package:syncrow_web/pages/routiens/widgets/routine_dialogs/effictive_period_dialog.dart'; import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/effictive_period_dialog.dart';
import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/constants/app_enum.dart'; import 'package:syncrow_web/utils/constants/app_enum.dart';

View File

@ -1,8 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/routiens/bloc/effective_period/effect_period_bloc.dart'; import 'package:syncrow_web/pages/routines/bloc/effective_period/effect_period_bloc.dart';
import 'package:syncrow_web/pages/routiens/bloc/effective_period/effect_period_event.dart'; import 'package:syncrow_web/pages/routines/bloc/effective_period/effect_period_event.dart';
import 'package:syncrow_web/pages/routiens/bloc/effective_period/effect_period_state.dart'; import 'package:syncrow_web/pages/routines/bloc/effective_period/effect_period_state.dart';
import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
class RepeatDays extends StatelessWidget { class RepeatDays extends StatelessWidget {

View File

@ -1,8 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart'; import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart';
import 'package:syncrow_web/pages/routiens/widgets/dragable_card.dart'; import 'package:syncrow_web/pages/routines/widgets/dragable_card.dart';
class RoutineDevices extends StatelessWidget { class RoutineDevices extends StatelessWidget {
const RoutineDevices({super.key}); const RoutineDevices({super.key});
@ -35,9 +35,7 @@ class RoutineDevices extends StatelessWidget {
children: deviceList.asMap().entries.map((entry) { children: deviceList.asMap().entries.map((entry) {
final device = entry.value; final device = entry.value;
if (state.searchText != null && state.searchText!.isNotEmpty) { if (state.searchText != null && state.searchText!.isNotEmpty) {
return device.name! return device.name!.toLowerCase().contains(state.searchText!.toLowerCase())
.toLowerCase()
.contains(state.searchText!.toLowerCase())
? DraggableCard( ? DraggableCard(
imagePath: device.getDefaultIcon(device.productType), imagePath: device.getDefaultIcon(device.productType),
title: device.name ?? '', title: device.name ?? '',

View File

@ -1,16 +1,16 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart'; import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart';
import 'package:syncrow_web/pages/routiens/models/ac/ac_function.dart'; import 'package:syncrow_web/pages/routines/models/ac/ac_function.dart';
import 'package:syncrow_web/pages/routiens/models/ac/ac_operational_value.dart'; import 'package:syncrow_web/pages/routines/models/ac/ac_operational_value.dart';
import 'package:syncrow_web/pages/routiens/models/device_functions.dart'; import 'package:syncrow_web/pages/routines/models/device_functions.dart';
import 'package:syncrow_web/pages/routiens/widgets/dialog_footer.dart'; import 'package:syncrow_web/pages/routines/widgets/dialog_footer.dart';
import 'package:syncrow_web/pages/routiens/widgets/dialog_header.dart'; import 'package:syncrow_web/pages/routines/widgets/dialog_header.dart';
import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/extension/build_context_x.dart'; import 'package:syncrow_web/utils/extension/build_context_x.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/routiens/bloc/functions_bloc/functions_bloc_bloc.dart'; import 'package:syncrow_web/pages/routines/bloc/functions_bloc/functions_bloc_bloc.dart';
class ACHelper { class ACHelper {
static Future<Map<String, dynamic>?> showACFunctionsDialog( static Future<Map<String, dynamic>?> showACFunctionsDialog(

View File

@ -1,10 +1,10 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart'; import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart';
import 'package:syncrow_web/pages/routiens/models/device_functions.dart'; import 'package:syncrow_web/pages/routines/models/device_functions.dart';
import 'package:syncrow_web/pages/routiens/widgets/dialog_header.dart'; import 'package:syncrow_web/pages/routines/widgets/dialog_header.dart';
import 'package:syncrow_web/pages/routiens/widgets/dialog_footer.dart'; import 'package:syncrow_web/pages/routines/widgets/dialog_footer.dart';
import 'package:syncrow_web/utils/constants/assets.dart'; import 'package:syncrow_web/utils/constants/assets.dart';
class AutomationDialog extends StatefulWidget { class AutomationDialog extends StatefulWidget {
@ -31,10 +31,8 @@ class _AutomationDialogState extends State<AutomationDialog> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
List<DeviceFunctionData>? functions = context List<DeviceFunctionData>? functions =
.read<RoutineBloc>() context.read<RoutineBloc>().state.selectedFunctions[widget.uniqueCustomId];
.state
.selectedFunctions[widget.uniqueCustomId];
for (DeviceFunctionData data in functions ?? []) { for (DeviceFunctionData data in functions ?? []) {
if (data.entityId == widget.automationId) { if (data.entityId == widget.automationId) {
selectedAutomationActionExecutor = data.value; selectedAutomationActionExecutor = data.value;
@ -67,8 +65,7 @@ class _AutomationDialogState extends State<AutomationDialog> {
}), }),
), ),
ListTile( ListTile(
leading: leading: SvgPicture.asset(Assets.acPowerOff, width: 24, height: 24),
SvgPicture.asset(Assets.acPowerOff, width: 24, height: 24),
title: const Text('Disable'), title: const Text('Disable'),
trailing: Radio<String?>( trailing: Radio<String?>(
value: 'rule_disable', value: 'rule_disable',

View File

@ -1,10 +1,10 @@
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart'; import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart';
import 'package:syncrow_web/pages/routiens/models/device_functions.dart'; import 'package:syncrow_web/pages/routines/models/device_functions.dart';
import 'package:syncrow_web/pages/routiens/widgets/dialog_footer.dart'; import 'package:syncrow_web/pages/routines/widgets/dialog_footer.dart';
import 'package:syncrow_web/pages/routiens/widgets/dialog_header.dart'; import 'package:syncrow_web/pages/routines/widgets/dialog_header.dart';
class DelayHelper { class DelayHelper {
static Future<Map<String, dynamic>?> showDelayPickerDialog( static Future<Map<String, dynamic>?> showDelayPickerDialog(

View File

@ -1,6 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart'; import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart';
import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/extension/build_context_x.dart'; import 'package:syncrow_web/utils/extension/build_context_x.dart';

View File

@ -1,7 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/routiens/bloc/effective_period/effect_period_bloc.dart'; import 'package:syncrow_web/pages/routines/bloc/effective_period/effect_period_bloc.dart';
import 'package:syncrow_web/pages/routiens/bloc/effective_period/effect_period_event.dart'; import 'package:syncrow_web/pages/routines/bloc/effective_period/effect_period_event.dart';
import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/constants/app_enum.dart'; import 'package:syncrow_web/utils/constants/app_enum.dart';
import 'package:syncrow_web/utils/extension/build_context_x.dart'; import 'package:syncrow_web/utils/extension/build_context_x.dart';

View File

@ -2,14 +2,14 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
import 'package:syncrow_web/pages/routiens/bloc/functions_bloc/functions_bloc_bloc.dart'; import 'package:syncrow_web/pages/routines/bloc/functions_bloc/functions_bloc_bloc.dart';
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart'; import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart';
import 'package:syncrow_web/pages/routiens/helper/duration_format_helper.dart'; import 'package:syncrow_web/pages/routines/helper/duration_format_helper.dart';
import 'package:syncrow_web/pages/routiens/models/device_functions.dart'; import 'package:syncrow_web/pages/routines/models/device_functions.dart';
import 'package:syncrow_web/pages/routiens/models/gang_switches/base_switch_function.dart'; import 'package:syncrow_web/pages/routines/models/gang_switches/base_switch_function.dart';
import 'package:syncrow_web/pages/routiens/models/gang_switches/switch_operational_value.dart'; import 'package:syncrow_web/pages/routines/models/gang_switches/switch_operational_value.dart';
import 'package:syncrow_web/pages/routiens/widgets/dialog_footer.dart'; import 'package:syncrow_web/pages/routines/widgets/dialog_footer.dart';
import 'package:syncrow_web/pages/routiens/widgets/dialog_header.dart'; import 'package:syncrow_web/pages/routines/widgets/dialog_header.dart';
import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/extension/build_context_x.dart'; import 'package:syncrow_web/utils/extension/build_context_x.dart';
@ -22,23 +22,21 @@ class OneGangSwitchHelper {
String uniqueCustomId, String uniqueCustomId,
bool removeComparetors, bool removeComparetors,
) async { ) async {
List<BaseSwitchFunction> acFunctions = List<BaseSwitchFunction> acFunctions = functions.whereType<BaseSwitchFunction>().toList();
functions.whereType<BaseSwitchFunction>().toList();
return showDialog<Map<String, dynamic>?>( return showDialog<Map<String, dynamic>?>(
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
return BlocProvider( return BlocProvider(
create: (_) => FunctionBloc() create: (_) => FunctionBloc()..add(InitializeFunctions(deviceSelectedFunctions ?? [])),
..add(InitializeFunctions(deviceSelectedFunctions ?? [])),
child: AlertDialog( child: AlertDialog(
contentPadding: EdgeInsets.zero, contentPadding: EdgeInsets.zero,
content: BlocBuilder<FunctionBloc, FunctionBlocState>( content: BlocBuilder<FunctionBloc, FunctionBlocState>(
builder: (context, state) { builder: (context, state) {
final selectedFunction = state.selectedFunction; final selectedFunction = state.selectedFunction;
final selectedOperationName = state.selectedOperationName; final selectedOperationName = state.selectedOperationName;
final selectedFunctionData = state.addedFunctions final selectedFunctionData =
.firstWhere((f) => f.functionCode == selectedFunction, state.addedFunctions.firstWhere((f) => f.functionCode == selectedFunction,
orElse: () => DeviceFunctionData( orElse: () => DeviceFunctionData(
entityId: '', entityId: '',
functionCode: selectedFunction ?? '', functionCode: selectedFunction ?? '',
@ -85,12 +83,9 @@ class OneGangSwitchHelper {
color: ColorsManager.textGray, color: ColorsManager.textGray,
), ),
onTap: () { onTap: () {
context context.read<FunctionBloc>().add(SelectFunction(
.read<FunctionBloc>()
.add(SelectFunction(
functionCode: function.code, functionCode: function.code,
operationName: operationName: function.operationName,
function.operationName,
)); ));
}, },
); );
@ -180,8 +175,7 @@ class OneGangSwitchHelper {
); );
} }
final selectedFn = final selectedFn = acFunctions.firstWhere((f) => f.code == selectedFunction);
acFunctions.firstWhere((f) => f.code == selectedFunction);
final values = selectedFn.getOperationalValues(); final values = selectedFn.getOperationalValues();
return _buildOperationalValuesList( return _buildOperationalValuesList(
@ -218,11 +212,11 @@ class OneGangSwitchHelper {
selectedFunctionData, selectedFunctionData,
), ),
const SizedBox(height: 20), const SizedBox(height: 20),
_buildCountDownDisplay(context, initialValue, device, operationName, _buildCountDownDisplay(
selectedFunctionData, selectCode), context, initialValue, device, operationName, selectedFunctionData, selectCode),
const SizedBox(height: 20), const SizedBox(height: 20),
_buildCountDownSlider(context, initialValue, device, operationName, _buildCountDownSlider(
selectedFunctionData, selectCode), context, initialValue, device, operationName, selectedFunctionData, selectCode),
], ],
); );
} }
@ -263,8 +257,7 @@ class OneGangSwitchHelper {
minHeight: 40.0, minHeight: 40.0,
minWidth: 40.0, minWidth: 40.0,
), ),
isSelected: isSelected: conditions.map((c) => c == (currentCondition ?? "==")).toList(),
conditions.map((c) => c == (currentCondition ?? "==")).toList(),
children: conditions.map((c) => Text(c)).toList(), children: conditions.map((c) => Text(c)).toList(),
); );
} }
@ -312,8 +305,7 @@ class OneGangSwitchHelper {
value: (initialValue ?? 0).toDouble(), value: (initialValue ?? 0).toDouble(),
min: operationalValues.minValue?.toDouble() ?? 0.0, min: operationalValues.minValue?.toDouble() ?? 0.0,
max: operationalValues.maxValue?.toDouble() ?? 0.0, max: operationalValues.maxValue?.toDouble() ?? 0.0,
divisions: (((operationalValues.maxValue ?? 0) - divisions: (((operationalValues.maxValue ?? 0) - (operationalValues.minValue ?? 0)) /
(operationalValues.minValue ?? 0)) /
(operationalValues.stepValue ?? 1)) (operationalValues.stepValue ?? 1))
.round(), .round(),
onChanged: (value) { onChanged: (value) {
@ -365,13 +357,9 @@ class OneGangSwitchHelper {
style: context.textTheme.bodyMedium, style: context.textTheme.bodyMedium,
), ),
trailing: Icon( trailing: Icon(
isSelected isSelected ? Icons.radio_button_checked : Icons.radio_button_unchecked,
? Icons.radio_button_checked
: Icons.radio_button_unchecked,
size: 24, size: 24,
color: isSelected color: isSelected ? ColorsManager.primaryColorWithOpacity : ColorsManager.textGray,
? ColorsManager.primaryColorWithOpacity
: ColorsManager.textGray,
), ),
onTap: () { onTap: () {
if (!isSelected) { if (!isSelected) {
@ -383,8 +371,7 @@ class OneGangSwitchHelper {
operationName: operationName, operationName: operationName,
value: value.value, value: value.value,
condition: selectedFunctionData?.condition, condition: selectedFunctionData?.condition,
valueDescription: valueDescription: selectedFunctionData?.valueDescription,
selectedFunctionData?.valueDescription,
), ),
), ),
); );

View File

@ -1,17 +1,17 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/routiens/bloc/effective_period/effect_period_bloc.dart'; import 'package:syncrow_web/pages/routines/bloc/effective_period/effect_period_bloc.dart';
import 'package:syncrow_web/pages/routiens/bloc/effective_period/effect_period_event.dart'; import 'package:syncrow_web/pages/routines/bloc/effective_period/effect_period_event.dart';
import 'package:syncrow_web/pages/routiens/bloc/effective_period/effect_period_state.dart'; import 'package:syncrow_web/pages/routines/bloc/effective_period/effect_period_state.dart';
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart'; import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart';
import 'package:syncrow_web/pages/routiens/bloc/setting_bloc/setting_bloc.dart'; import 'package:syncrow_web/pages/routines/bloc/setting_bloc/setting_bloc.dart';
import 'package:syncrow_web/pages/routiens/bloc/setting_bloc/setting_event.dart'; import 'package:syncrow_web/pages/routines/bloc/setting_bloc/setting_event.dart';
import 'package:syncrow_web/pages/routiens/bloc/setting_bloc/setting_state.dart'; import 'package:syncrow_web/pages/routines/bloc/setting_bloc/setting_state.dart';
import 'package:syncrow_web/pages/routiens/models/create_scene_and_autoamtion/create_automation_model.dart'; import 'package:syncrow_web/pages/routines/models/create_scene_and_autoamtion/create_automation_model.dart';
import 'package:syncrow_web/pages/routiens/models/icon_model.dart'; import 'package:syncrow_web/pages/routines/models/icon_model.dart';
import 'package:syncrow_web/pages/routiens/view/effective_period_view.dart'; import 'package:syncrow_web/pages/routines/view/effective_period_view.dart';
import 'package:syncrow_web/pages/routiens/widgets/delete_scene.dart'; import 'package:syncrow_web/pages/routines/widgets/delete_scene.dart';
import 'package:syncrow_web/pages/routiens/widgets/dialog_header.dart'; import 'package:syncrow_web/pages/routines/widgets/dialog_header.dart';
import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';

View File

@ -2,14 +2,14 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
import 'package:syncrow_web/pages/routiens/bloc/functions_bloc/functions_bloc_bloc.dart'; import 'package:syncrow_web/pages/routines/bloc/functions_bloc/functions_bloc_bloc.dart';
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart'; import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart';
import 'package:syncrow_web/pages/routiens/helper/duration_format_helper.dart'; import 'package:syncrow_web/pages/routines/helper/duration_format_helper.dart';
import 'package:syncrow_web/pages/routiens/models/device_functions.dart'; import 'package:syncrow_web/pages/routines/models/device_functions.dart';
import 'package:syncrow_web/pages/routiens/models/gang_switches/base_switch_function.dart'; import 'package:syncrow_web/pages/routines/models/gang_switches/base_switch_function.dart';
import 'package:syncrow_web/pages/routiens/models/gang_switches/switch_operational_value.dart'; import 'package:syncrow_web/pages/routines/models/gang_switches/switch_operational_value.dart';
import 'package:syncrow_web/pages/routiens/widgets/dialog_footer.dart'; import 'package:syncrow_web/pages/routines/widgets/dialog_footer.dart';
import 'package:syncrow_web/pages/routiens/widgets/dialog_header.dart'; import 'package:syncrow_web/pages/routines/widgets/dialog_header.dart';
import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/extension/build_context_x.dart'; import 'package:syncrow_web/utils/extension/build_context_x.dart';
@ -22,23 +22,21 @@ class ThreeGangSwitchHelper {
String uniqueCustomId, String uniqueCustomId,
bool removeComparetors, bool removeComparetors,
) async { ) async {
List<BaseSwitchFunction> switchFunctions = List<BaseSwitchFunction> switchFunctions = functions.whereType<BaseSwitchFunction>().toList();
functions.whereType<BaseSwitchFunction>().toList();
return showDialog<Map<String, dynamic>?>( return showDialog<Map<String, dynamic>?>(
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
return BlocProvider( return BlocProvider(
create: (_) => FunctionBloc() create: (_) => FunctionBloc()..add(InitializeFunctions(deviceSelectedFunctions ?? [])),
..add(InitializeFunctions(deviceSelectedFunctions ?? [])),
child: AlertDialog( child: AlertDialog(
contentPadding: EdgeInsets.zero, contentPadding: EdgeInsets.zero,
content: BlocBuilder<FunctionBloc, FunctionBlocState>( content: BlocBuilder<FunctionBloc, FunctionBlocState>(
builder: (context, state) { builder: (context, state) {
final selectedFunction = state.selectedFunction; final selectedFunction = state.selectedFunction;
final selectedOperationName = state.selectedOperationName; final selectedOperationName = state.selectedOperationName;
final selectedFunctionData = state.addedFunctions final selectedFunctionData =
.firstWhere((f) => f.functionCode == selectedFunction, state.addedFunctions.firstWhere((f) => f.functionCode == selectedFunction,
orElse: () => DeviceFunctionData( orElse: () => DeviceFunctionData(
entityId: '', entityId: '',
functionCode: selectedFunction ?? '', functionCode: selectedFunction ?? '',
@ -85,12 +83,9 @@ class ThreeGangSwitchHelper {
color: ColorsManager.textGray, color: ColorsManager.textGray,
), ),
onTap: () { onTap: () {
context context.read<FunctionBloc>().add(SelectFunction(
.read<FunctionBloc>()
.add(SelectFunction(
functionCode: function.code, functionCode: function.code,
operationName: operationName: function.operationName,
function.operationName,
)); ));
}, },
); );
@ -182,8 +177,7 @@ class ThreeGangSwitchHelper {
); );
} }
final selectedFn = final selectedFn = switchFunctions.firstWhere((f) => f.code == selectedFunction);
switchFunctions.firstWhere((f) => f.code == selectedFunction);
final values = selectedFn.getOperationalValues(); final values = selectedFn.getOperationalValues();
return _buildOperationalValuesList( return _buildOperationalValuesList(
@ -220,11 +214,11 @@ class ThreeGangSwitchHelper {
selectedFunctionData, selectedFunctionData,
), ),
const SizedBox(height: 20), const SizedBox(height: 20),
_buildCountDownDisplay(context, initialValue, device, operationName, _buildCountDownDisplay(
selectedFunctionData, selectCode), context, initialValue, device, operationName, selectedFunctionData, selectCode),
const SizedBox(height: 20), const SizedBox(height: 20),
_buildCountDownSlider(context, initialValue, device, operationName, _buildCountDownSlider(
selectedFunctionData, selectCode), context, initialValue, device, operationName, selectedFunctionData, selectCode),
], ],
); );
} }
@ -265,8 +259,7 @@ class ThreeGangSwitchHelper {
minHeight: 40.0, minHeight: 40.0,
minWidth: 40.0, minWidth: 40.0,
), ),
isSelected: isSelected: conditions.map((c) => c == (currentCondition ?? "==")).toList(),
conditions.map((c) => c == (currentCondition ?? "==")).toList(),
children: conditions.map((c) => Text(c)).toList(), children: conditions.map((c) => Text(c)).toList(),
); );
} }
@ -314,8 +307,7 @@ class ThreeGangSwitchHelper {
value: (initialValue ?? 0).toDouble(), value: (initialValue ?? 0).toDouble(),
min: operationalValues.minValue?.toDouble() ?? 0.0, min: operationalValues.minValue?.toDouble() ?? 0.0,
max: operationalValues.maxValue?.toDouble() ?? 0.0, max: operationalValues.maxValue?.toDouble() ?? 0.0,
divisions: (((operationalValues.maxValue ?? 0) - divisions: (((operationalValues.maxValue ?? 0) - (operationalValues.minValue ?? 0)) /
(operationalValues.minValue ?? 0)) /
(operationalValues.stepValue ?? 1)) (operationalValues.stepValue ?? 1))
.round(), .round(),
onChanged: (value) { onChanged: (value) {
@ -367,13 +359,9 @@ class ThreeGangSwitchHelper {
style: context.textTheme.bodyMedium, style: context.textTheme.bodyMedium,
), ),
trailing: Icon( trailing: Icon(
isSelected isSelected ? Icons.radio_button_checked : Icons.radio_button_unchecked,
? Icons.radio_button_checked
: Icons.radio_button_unchecked,
size: 24, size: 24,
color: isSelected color: isSelected ? ColorsManager.primaryColorWithOpacity : ColorsManager.textGray,
? ColorsManager.primaryColorWithOpacity
: ColorsManager.textGray,
), ),
onTap: () { onTap: () {
if (!isSelected) { if (!isSelected) {
@ -385,8 +373,7 @@ class ThreeGangSwitchHelper {
operationName: operationName, operationName: operationName,
value: value.value, value: value.value,
condition: selectedFunctionData?.condition, condition: selectedFunctionData?.condition,
valueDescription: valueDescription: selectedFunctionData?.valueDescription,
selectedFunctionData?.valueDescription,
), ),
), ),
); );

View File

@ -2,14 +2,14 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
import 'package:syncrow_web/pages/routiens/bloc/functions_bloc/functions_bloc_bloc.dart'; import 'package:syncrow_web/pages/routines/bloc/functions_bloc/functions_bloc_bloc.dart';
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart'; import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart';
import 'package:syncrow_web/pages/routiens/helper/duration_format_helper.dart'; import 'package:syncrow_web/pages/routines/helper/duration_format_helper.dart';
import 'package:syncrow_web/pages/routiens/models/device_functions.dart'; import 'package:syncrow_web/pages/routines/models/device_functions.dart';
import 'package:syncrow_web/pages/routiens/models/gang_switches/base_switch_function.dart'; import 'package:syncrow_web/pages/routines/models/gang_switches/base_switch_function.dart';
import 'package:syncrow_web/pages/routiens/models/gang_switches/switch_operational_value.dart'; import 'package:syncrow_web/pages/routines/models/gang_switches/switch_operational_value.dart';
import 'package:syncrow_web/pages/routiens/widgets/dialog_footer.dart'; import 'package:syncrow_web/pages/routines/widgets/dialog_footer.dart';
import 'package:syncrow_web/pages/routiens/widgets/dialog_header.dart'; import 'package:syncrow_web/pages/routines/widgets/dialog_header.dart';
import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/extension/build_context_x.dart'; import 'package:syncrow_web/utils/extension/build_context_x.dart';
@ -22,23 +22,21 @@ class TwoGangSwitchHelper {
String uniqueCustomId, String uniqueCustomId,
bool removeComparetors, bool removeComparetors,
) async { ) async {
List<BaseSwitchFunction> switchFunctions = List<BaseSwitchFunction> switchFunctions = functions.whereType<BaseSwitchFunction>().toList();
functions.whereType<BaseSwitchFunction>().toList();
return showDialog<Map<String, dynamic>?>( return showDialog<Map<String, dynamic>?>(
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
return BlocProvider( return BlocProvider(
create: (_) => FunctionBloc() create: (_) => FunctionBloc()..add(InitializeFunctions(deviceSelectedFunctions ?? [])),
..add(InitializeFunctions(deviceSelectedFunctions ?? [])),
child: AlertDialog( child: AlertDialog(
contentPadding: EdgeInsets.zero, contentPadding: EdgeInsets.zero,
content: BlocBuilder<FunctionBloc, FunctionBlocState>( content: BlocBuilder<FunctionBloc, FunctionBlocState>(
builder: (context, state) { builder: (context, state) {
final selectedFunction = state.selectedFunction; final selectedFunction = state.selectedFunction;
final selectedOperationName = state.selectedOperationName; final selectedOperationName = state.selectedOperationName;
final selectedFunctionData = state.addedFunctions final selectedFunctionData =
.firstWhere((f) => f.functionCode == selectedFunction, state.addedFunctions.firstWhere((f) => f.functionCode == selectedFunction,
orElse: () => DeviceFunctionData( orElse: () => DeviceFunctionData(
entityId: '', entityId: '',
functionCode: selectedFunction ?? '', functionCode: selectedFunction ?? '',
@ -85,12 +83,9 @@ class TwoGangSwitchHelper {
color: ColorsManager.textGray, color: ColorsManager.textGray,
), ),
onTap: () { onTap: () {
context context.read<FunctionBloc>().add(SelectFunction(
.read<FunctionBloc>()
.add(SelectFunction(
functionCode: function.code, functionCode: function.code,
operationName: operationName: function.operationName,
function.operationName,
)); ));
}, },
); );
@ -166,8 +161,7 @@ class TwoGangSwitchHelper {
required String operationName, required String operationName,
required bool removeComparetors, required bool removeComparetors,
}) { }) {
if (selectedFunction == 'countdown_1' || if (selectedFunction == 'countdown_1' || selectedFunction == 'countdown_2') {
selectedFunction == 'countdown_2') {
final initialValue = selectedFunctionData?.value ?? 200; final initialValue = selectedFunctionData?.value ?? 200;
return _buildTemperatureSelector( return _buildTemperatureSelector(
context: context, context: context,
@ -181,8 +175,7 @@ class TwoGangSwitchHelper {
); );
} }
final selectedFn = final selectedFn = switchFunctions.firstWhere((f) => f.code == selectedFunction);
switchFunctions.firstWhere((f) => f.code == selectedFunction);
final values = selectedFn.getOperationalValues(); final values = selectedFn.getOperationalValues();
return _buildOperationalValuesList( return _buildOperationalValuesList(
@ -219,11 +212,11 @@ class TwoGangSwitchHelper {
selectedFunctionData, selectedFunctionData,
), ),
const SizedBox(height: 20), const SizedBox(height: 20),
_buildCountDownDisplay(context, initialValue, device, operationName, _buildCountDownDisplay(
selectedFunctionData, selectCode), context, initialValue, device, operationName, selectedFunctionData, selectCode),
const SizedBox(height: 20), const SizedBox(height: 20),
_buildCountDownSlider(context, initialValue, device, operationName, _buildCountDownSlider(
selectedFunctionData, selectCode), context, initialValue, device, operationName, selectedFunctionData, selectCode),
], ],
); );
} }
@ -264,8 +257,7 @@ class TwoGangSwitchHelper {
minHeight: 40.0, minHeight: 40.0,
minWidth: 40.0, minWidth: 40.0,
), ),
isSelected: isSelected: conditions.map((c) => c == (currentCondition ?? "==")).toList(),
conditions.map((c) => c == (currentCondition ?? "==")).toList(),
children: conditions.map((c) => Text(c)).toList(), children: conditions.map((c) => Text(c)).toList(),
); );
} }
@ -313,8 +305,7 @@ class TwoGangSwitchHelper {
value: (initialValue ?? 0).toDouble(), value: (initialValue ?? 0).toDouble(),
min: operationalValues.minValue?.toDouble() ?? 0.0, min: operationalValues.minValue?.toDouble() ?? 0.0,
max: operationalValues.maxValue?.toDouble() ?? 0.0, max: operationalValues.maxValue?.toDouble() ?? 0.0,
divisions: (((operationalValues.maxValue ?? 0) - divisions: (((operationalValues.maxValue ?? 0) - (operationalValues.minValue ?? 0)) /
(operationalValues.minValue ?? 0)) /
(operationalValues.stepValue ?? 1)) (operationalValues.stepValue ?? 1))
.round(), .round(),
onChanged: (value) { onChanged: (value) {
@ -366,13 +357,9 @@ class TwoGangSwitchHelper {
style: context.textTheme.bodyMedium, style: context.textTheme.bodyMedium,
), ),
trailing: Icon( trailing: Icon(
isSelected isSelected ? Icons.radio_button_checked : Icons.radio_button_unchecked,
? Icons.radio_button_checked
: Icons.radio_button_unchecked,
size: 24, size: 24,
color: isSelected color: isSelected ? ColorsManager.primaryColorWithOpacity : ColorsManager.textGray,
? ColorsManager.primaryColorWithOpacity
: ColorsManager.textGray,
), ),
onTap: () { onTap: () {
if (!isSelected) { if (!isSelected) {
@ -384,8 +371,7 @@ class TwoGangSwitchHelper {
operationName: operationName, operationName: operationName,
value: value.value, value: value.value,
condition: selectedFunctionData?.condition, condition: selectedFunctionData?.condition,
valueDescription: valueDescription: selectedFunctionData?.valueDescription,
selectedFunctionData?.valueDescription,
), ),
), ),
); );

View File

@ -1,10 +1,10 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/common/buttons/default_button.dart'; import 'package:syncrow_web/pages/common/buttons/default_button.dart';
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart'; import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart';
import 'package:syncrow_web/pages/routiens/helper/save_routine_helper.dart'; import 'package:syncrow_web/pages/routines/helper/save_routine_helper.dart';
import 'package:syncrow_web/pages/routiens/widgets/routine_dialogs/discard_dialog.dart'; import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/discard_dialog.dart';
import 'package:syncrow_web/pages/routiens/widgets/routine_dialogs/setting_dialog.dart'; import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/setting_dialog.dart';
import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/extension/build_context_x.dart'; import 'package:syncrow_web/utils/extension/build_context_x.dart';
import 'package:syncrow_web/utils/style.dart'; import 'package:syncrow_web/utils/style.dart';

View File

@ -1,7 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart'; import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart';
import 'package:syncrow_web/pages/routiens/widgets/dragable_card.dart'; import 'package:syncrow_web/pages/routines/widgets/dragable_card.dart';
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_bloc.dart';
import 'package:syncrow_web/utils/constants/assets.dart'; import 'package:syncrow_web/utils/constants/assets.dart';
class ScenesAndAutomations extends StatefulWidget { class ScenesAndAutomations extends StatefulWidget {
@ -18,8 +19,9 @@ class _ScenesAndAutomationsState extends State<ScenesAndAutomations> {
void initState() { void initState() {
super.initState(); super.initState();
context.read<RoutineBloc>() context.read<RoutineBloc>()
..add(const LoadScenes(spaceId, communityId)) ..add(LoadScenes(context.read<SpaceTreeBloc>().selectedSpaceId,
..add(const LoadAutomation(spaceId)); context.read<SpaceTreeBloc>().selectedCommunityId))
..add(LoadAutomation(context.read<SpaceTreeBloc>().selectedSpaceId));
} }
@override @override
@ -34,9 +36,7 @@ class _ScenesAndAutomationsState extends State<ScenesAndAutomations> {
children: scenes.asMap().entries.map((entry) { children: scenes.asMap().entries.map((entry) {
final scene = entry.value; final scene = entry.value;
if (state.searchText != null && state.searchText!.isNotEmpty) { if (state.searchText != null && state.searchText!.isNotEmpty) {
return scene.name return scene.name.toLowerCase().contains(state.searchText!.toLowerCase())
.toLowerCase()
.contains(state.searchText!.toLowerCase())
? DraggableCard( ? DraggableCard(
imagePath: scene.icon ?? Assets.loginLogo, imagePath: scene.icon ?? Assets.loginLogo,
title: scene.name, title: scene.name,

View File

@ -1,8 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.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/common/text_field/custom_text_field.dart';
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart'; import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart';
import 'package:syncrow_web/pages/routiens/widgets/routines_title_widget.dart'; import 'package:syncrow_web/pages/routines/widgets/routines_title_widget.dart';
import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart'; import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';

View File

@ -2,11 +2,11 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart'; import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart';
import 'package:syncrow_web/pages/routiens/widgets/routine_dialogs/automation_dialog.dart'; import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/automation_dialog.dart';
import 'package:syncrow_web/pages/routiens/widgets/routine_dialogs/delay_dialog.dart'; import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/delay_dialog.dart';
import 'package:syncrow_web/pages/routiens/helper/dialog_helper/device_dialog_helper.dart'; import 'package:syncrow_web/pages/routines/helper/dialog_helper/device_dialog_helper.dart';
import 'package:syncrow_web/pages/routiens/widgets/dragable_card.dart'; import 'package:syncrow_web/pages/routines/widgets/dragable_card.dart';
import 'package:syncrow_web/utils/constants/assets.dart'; import 'package:syncrow_web/utils/constants/assets.dart';
import 'package:uuid/uuid.dart'; import 'package:uuid/uuid.dart';

View File

@ -0,0 +1,69 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_event.dart';
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_state.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart';
import 'package:syncrow_web/services/space_mana_api.dart';
class SpaceTreeBloc extends Bloc<SpaceTreeEvent, SpaceTreeState> {
String selectedCommunityId = '';
String selectedSpaceId = '';
SpaceTreeBloc() : super(const SpaceTreeState()) {
on<InitialEvent>(_fetchSpaces);
on<OnSelectSpaceEvent>(_onSelectSpace);
}
_fetchSpaces(InitialEvent event, Emitter<SpaceTreeState> emit) async {
emit(SpaceTreeLoadingState());
try {
// _onloadProducts();
List<CommunityModel> communities = await CommunitySpaceManagementApi().fetchCommunities();
List<CommunityModel> updatedCommunities = await Future.wait(
communities.map((community) async {
List<SpaceModel> spaces =
await CommunitySpaceManagementApi().getSpaceHierarchy(community.uuid);
return CommunityModel(
uuid: community.uuid,
createdAt: community.createdAt,
updatedAt: community.updatedAt,
name: community.name,
description: community.description,
spaces: spaces,
region: community.region,
);
}).toList(),
);
if (updatedCommunities.isNotEmpty &&
state.selectedSpace.isEmpty &&
state.selectedCommunity.isEmpty) {
selectedCommunityId = updatedCommunities[0].uuid;
} else {
selectedCommunityId = state.selectedCommunity;
selectedSpaceId = state.selectedSpace;
}
emit(state.copyWith(
communitiesList: updatedCommunities,
selectedCommunity: selectedCommunityId,
selectedSpace: selectedSpaceId));
} catch (e) {
emit(SpaceTreeErrorState('Error loading communities and spaces: $e'));
}
}
_onSelectSpace(OnSelectSpaceEvent event, Emitter<SpaceTreeState> emit) async {
try {
selectedCommunityId = event.communityId;
selectedSpaceId = event.spaceId;
emit(state.copyWith(
communitiesList: state.spacesList,
selectedCommunity: event.communityId,
selectedSpace: event.spaceId));
} catch (e) {
emit(const SpaceTreeErrorState('Something went wrong'));
}
}
}

View File

@ -0,0 +1,29 @@
import 'package:equatable/equatable.dart';
class SpaceTreeEvent extends Equatable {
const SpaceTreeEvent();
@override
List<Object> get props => [];
}
class InitialEvent extends SpaceTreeEvent {}
class OnSelectSpaceEvent extends SpaceTreeEvent {
final String communityId;
final String spaceId;
const OnSelectSpaceEvent(this.communityId, this.spaceId);
@override
List<Object> get props => [communityId, spaceId];
}
class SearchForSpace extends SpaceTreeEvent {
final String searchQuery;
const SearchForSpace(this.searchQuery);
@override
List<Object> get props => [searchQuery];
}

View File

@ -0,0 +1,31 @@
import 'package:equatable/equatable.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
class SpaceTreeState extends Equatable {
final List<CommunityModel> spacesList;
final String selectedSpace;
final String selectedCommunity;
const SpaceTreeState(
{this.spacesList = const [], this.selectedSpace = '', this.selectedCommunity = ''});
SpaceTreeState copyWith(
{List<CommunityModel>? communitiesList, String? selectedSpace, String? selectedCommunity}) {
return SpaceTreeState(
spacesList: communitiesList ?? this.spacesList,
selectedSpace: selectedSpace ?? this.selectedSpace,
selectedCommunity: selectedCommunity ?? this.selectedCommunity);
}
@override
List<Object?> get props => [spacesList, selectedSpace, selectedCommunity];
}
class SpaceTreeLoadingState extends SpaceTreeState {}
class SpaceTreeErrorState extends SpaceTreeState {
final String message;
const SpaceTreeErrorState(this.message);
@override
List<Object?> get props => [message];
}

View File

@ -0,0 +1,26 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_bloc.dart';
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_state.dart';
import 'package:syncrow_web/pages/space_tree/view/space_tree_view.dart';
class SideSpacesView extends StatelessWidget {
final Function onSelectAction;
const SideSpacesView({required this.onSelectAction, super.key});
@override
Widget build(BuildContext context) {
return BlocConsumer<SpaceTreeBloc, SpaceTreeState>(
listener: (context, state) {},
builder: (context, state) {
return SpaceTreeView(
communities: state.spacesList,
selectedSpaceUuid: state.selectedSpace,
selectedCommunityId: state.selectedCommunity,
buildContext: context,
action: onSelectAction,
isLoading: state is SpaceTreeLoadingState,
);
});
}
}

View File

@ -0,0 +1,251 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/svg.dart';
import 'package:syncrow_web/common/widgets/search_bar.dart';
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_bloc.dart';
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_event.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/community_tile.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/space_tile_widget.dart';
import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/constants/assets.dart';
import 'package:syncrow_web/utils/style.dart';
class SpaceTreeView extends StatefulWidget {
final List<CommunityModel> communities;
final String? selectedCommunityId;
final String? selectedSpaceUuid;
final BuildContext buildContext;
final Function action;
final bool isLoading;
const SpaceTreeView(
{super.key,
this.selectedCommunityId,
required this.communities,
this.selectedSpaceUuid,
required this.buildContext,
required this.action,
required this.isLoading});
@override
State<SpaceTreeView> createState() => _SpaceTreeViewState();
}
class _SpaceTreeViewState extends State<SpaceTreeView> {
String _searchQuery = ''; // Track search query
String? _selectedSpaceUuid;
String? _selectedCommunityId;
String? _expandedId;
@override
void initState() {
super.initState();
// _selectedId = widget.selectedSpaceUuid; // Initialize with the passed selected space UUID
_selectedCommunityId = widget.selectedCommunityId;
_selectedSpaceUuid = widget.selectedSpaceUuid;
}
@override
void didUpdateWidget(covariant SpaceTreeView oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.selectedSpaceUuid != oldWidget.selectedSpaceUuid ||
widget.selectedCommunityId != oldWidget.selectedCommunityId) {
setState(() {
// _selectedId = widget.selectedSpaceUuid;
_selectedCommunityId = widget.selectedCommunityId;
_selectedSpaceUuid = widget.selectedSpaceUuid;
});
}
}
// Function to filter communities based on the search query
List<CommunityModel> _filterCommunities() {
_expandedId = null;
if (_searchQuery.isEmpty) {
// Reset the selected community and space UUIDs if there's no query
// _selectedSpaceUuid = null;
// _selectedCommunityId = null;
return widget.communities;
}
// Filter communities and expand only those that match the query
return widget.communities.where((community) {
final containsQueryInCommunity =
community.name.toLowerCase().contains(_searchQuery.toLowerCase());
final containsQueryInSpaces =
community.spaces.any((space) => _containsQuery(space, _searchQuery.toLowerCase()));
return containsQueryInCommunity || containsQueryInSpaces;
}).toList();
}
// Helper function to determine if any space or its children match the search query
bool _containsQuery(SpaceModel space, String query) {
final matchesSpace = space.name.toLowerCase().contains(query);
final matchesChildren =
space.children.any((child) => _containsQuery(child, query)); // Recursive check for children
// If the space or any of its children match the query, expand this space
if (matchesSpace || matchesChildren) {
_expandedId = space.uuid;
}
return matchesSpace || matchesChildren;
}
bool _isSpaceOrChildSelected(SpaceModel space) {
// Return true if the current space or any of its child spaces is selected
if (_expandedId == space.uuid) {
return true;
}
// Recursively check if any child spaces match the query
for (var child in space.children) {
if (_isSpaceOrChildSelected(child)) {
return true;
}
}
return false;
}
@override
Widget build(BuildContext context) {
final filteredCommunities = _filterCommunities();
return Container(
// width: MediaQuery.sizeOf(context).width * 0.25,
height: MediaQuery.sizeOf(context).height,
margin: const EdgeInsets.only(right: 24),
decoration: subSectionContainerDecoration,
child: widget.isLoading
? const Center(child: CircularProgressIndicator())
: Column(
mainAxisSize: MainAxisSize.min, // Ensures the Column only takes necessary height
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Communities title with the add button
Container(
decoration: subSectionContainerDecoration,
padding: const EdgeInsets.all(16.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('Communities',
style: Theme.of(context).textTheme.titleMedium?.copyWith(
color: Colors.black,
)),
GestureDetector(
onTap: () => _navigateToBlank(context),
child: Container(
width: 30,
height: 30,
decoration: const BoxDecoration(
color: ColorsManager.whiteColors,
shape: BoxShape.circle,
),
child: Center(
child: SvgPicture.asset(
Assets.roundedAddIcon,
width: 24,
height: 24,
),
),
),
),
],
),
),
// Search bar
CustomSearchBar(
onSearchChanged: (query) {
setState(() {
_selectedSpaceUuid = null;
_searchQuery = query;
});
},
),
const SizedBox(height: 16),
// Community list
Expanded(
child: ListView(
children: filteredCommunities.map((community) {
return _buildCommunityTile(context, community);
}).toList(),
),
),
],
),
);
}
void _navigateToBlank(BuildContext context) {
setState(() {
// _selectedId = '';
_selectedSpaceUuid = '';
});
// context.read<SpaceManagementBloc>().add(
// NewCommunityEvent(communities: widget.communities),
// );
}
Widget _buildCommunityTile(BuildContext context, CommunityModel community) {
bool hasChildren = community.spaces.isNotEmpty;
return CommunityTile(
title: community.name,
key: ValueKey(community.uuid),
isSelected: _selectedCommunityId == community.uuid,
isExpanded: false,
onItemSelected: () {
setState(() {
_selectedCommunityId = community.uuid;
_selectedSpaceUuid = null;
});
widget.buildContext.read<SpaceTreeBloc>().add(
OnSelectSpaceEvent(community.uuid, ''),
);
widget.action(community.uuid, '');
},
onExpansionChanged: (String title, bool expanded) {
_handleExpansionChange(community.uuid, expanded);
},
children: hasChildren
? community.spaces.map((space) => _buildSpaceTile(space, community)).toList()
: null,
);
}
Widget _buildSpaceTile(SpaceModel space, CommunityModel community) {
return SpaceTile(
title: space.name,
key: ValueKey(space.uuid),
isSelected: _selectedSpaceUuid == space.uuid,
initiallyExpanded: _isSpaceOrChildSelected(space),
onExpansionChanged: (bool expanded) {
_handleExpansionChange(space.uuid ?? '', expanded);
},
onItemSelected: () {
setState(() {
_selectedSpaceUuid = space.uuid;
_selectedCommunityId = community.uuid;
});
widget.buildContext.read<SpaceTreeBloc>().add(
OnSelectSpaceEvent(community.uuid, space.uuid ?? ''),
);
widget.action(community.uuid, space.uuid);
},
children: space.children.isNotEmpty
? space.children.map((childSpace) => _buildSpaceTile(childSpace, community)).toList()
: [],
);
}
void _handleExpansionChange(String uuid, bool expanded) {}
}

View File

@ -1,5 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:syncrow_web/common/custom_expansion_tile.dart'; import 'package:syncrow_web/common/widgets/custom_expansion_tile.dart';
class CommunityTile extends StatelessWidget { class CommunityTile extends StatelessWidget {
final String title; final String title;

View File

@ -1,7 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/svg.dart'; import 'package:flutter_svg/svg.dart';
import 'package:syncrow_web/common/search_bar.dart'; import 'package:syncrow_web/common/widgets/search_bar.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/bloc/space_management_bloc.dart'; import 'package:syncrow_web/pages/spaces_management/all_spaces/bloc/space_management_bloc.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/bloc/space_management_event.dart'; import 'package:syncrow_web/pages/spaces_management/all_spaces/bloc/space_management_event.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart'; import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
@ -34,8 +34,7 @@ class _SidebarWidgetState extends State<SidebarWidget> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_selectedId = widget _selectedId = widget.selectedSpaceUuid; // Initialize with the passed selected space UUID
.selectedSpaceUuid; // Initialize with the passed selected space UUID
} }
@override @override
@ -60,8 +59,8 @@ class _SidebarWidgetState extends State<SidebarWidget> {
return widget.communities.where((community) { return widget.communities.where((community) {
final containsQueryInCommunity = final containsQueryInCommunity =
community.name.toLowerCase().contains(_searchQuery.toLowerCase()); community.name.toLowerCase().contains(_searchQuery.toLowerCase());
final containsQueryInSpaces = community.spaces final containsQueryInSpaces =
.any((space) => _containsQuery(space, _searchQuery.toLowerCase())); community.spaces.any((space) => _containsQuery(space, _searchQuery.toLowerCase()));
return containsQueryInCommunity || containsQueryInSpaces; return containsQueryInCommunity || containsQueryInSpaces;
}).toList(); }).toList();
@ -70,8 +69,8 @@ class _SidebarWidgetState extends State<SidebarWidget> {
// Helper function to determine if any space or its children match the search query // Helper function to determine if any space or its children match the search query
bool _containsQuery(SpaceModel space, String query) { bool _containsQuery(SpaceModel space, String query) {
final matchesSpace = space.name.toLowerCase().contains(query); final matchesSpace = space.name.toLowerCase().contains(query);
final matchesChildren = space.children.any((child) => final matchesChildren =
_containsQuery(child, query)); // Recursive check for children space.children.any((child) => _containsQuery(child, query)); // Recursive check for children
// If the space or any of its children match the query, expand this space // If the space or any of its children match the query, expand this space
if (matchesSpace || matchesChildren) { if (matchesSpace || matchesChildren) {
@ -105,8 +104,7 @@ class _SidebarWidgetState extends State<SidebarWidget> {
width: 300, width: 300,
decoration: subSectionContainerDecoration, decoration: subSectionContainerDecoration,
child: Column( child: Column(
mainAxisSize: mainAxisSize: MainAxisSize.min, // Ensures the Column only takes necessary height
MainAxisSize.min, // Ensures the Column only takes necessary height
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
// Communities title with the add button // Communities title with the add button
@ -194,9 +192,7 @@ class _SidebarWidgetState extends State<SidebarWidget> {
_handleExpansionChange(community.uuid, expanded); _handleExpansionChange(community.uuid, expanded);
}, },
children: hasChildren children: hasChildren
? community.spaces ? community.spaces.map((space) => _buildSpaceTile(space, community)).toList()
.map((space) => _buildSpaceTile(space, community))
.toList()
: null, // Render spaces within the community : null, // Render spaces within the community
); );
} }
@ -218,14 +214,11 @@ class _SidebarWidgetState extends State<SidebarWidget> {
}); });
context.read<SpaceManagementBloc>().add( context.read<SpaceManagementBloc>().add(
SelectSpaceEvent( SelectSpaceEvent(selectedCommunity: community, selectedSpace: space),
selectedCommunity: community, selectedSpace: space),
); );
}, },
children: space.children.isNotEmpty children: space.children.isNotEmpty
? space.children ? space.children.map((childSpace) => _buildSpaceTile(childSpace, community)).toList()
.map((childSpace) => _buildSpaceTile(childSpace, community))
.toList()
: [], // Recursively render child spaces if available : [], // Recursively render child spaces if available
); );
} }

View File

@ -1,5 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:syncrow_web/common/custom_expansion_tile.dart'; import 'package:syncrow_web/common/widgets/custom_expansion_tile.dart';
class SpaceTile extends StatefulWidget { class SpaceTile extends StatefulWidget {
final String title; final String title;

View File

@ -9,12 +9,18 @@ import 'package:syncrow_web/pages/device_managment/water_heater/models/schedule_
import 'package:syncrow_web/pages/visitor_password/model/device_model.dart'; import 'package:syncrow_web/pages/visitor_password/model/device_model.dart';
import 'package:syncrow_web/services/api/http_service.dart'; import 'package:syncrow_web/services/api/http_service.dart';
import 'package:syncrow_web/utils/constants/api_const.dart'; import 'package:syncrow_web/utils/constants/api_const.dart';
import 'package:syncrow_web/utils/constants/temp_const.dart';
class DevicesManagementApi { class DevicesManagementApi {
Future<List<AllDevicesModel>> fetchDevices() async { Future<List<AllDevicesModel>> fetchDevices(String communityId, String spaceId) async {
try { try {
final response = await HTTPService().get( final response = await HTTPService().get(
path: ApiEndpoints.getAllDevices, path: communityId.isNotEmpty && spaceId.isNotEmpty
? ApiEndpoints.getSpaceDevices
.replaceAll('{spaceUuid}', spaceId)
.replaceAll('{communityUuid}', communityId)
.replaceAll('{projectId}', TempConst.projectId)
: ApiEndpoints.getAllDevices,
showServerMessage: true, showServerMessage: true,
expectedResponseModel: (json) { expectedResponseModel: (json) {
List<dynamic> jsonData = json; List<dynamic> jsonData = json;
@ -85,8 +91,7 @@ class DevicesManagementApi {
} }
} }
Future<bool> deviceBatchControl( Future<bool> deviceBatchControl(List<String> uuids, String code, dynamic value) async {
List<String> uuids, String code, dynamic value) async {
try { try {
final body = { final body = {
'devicesUuid': uuids, 'devicesUuid': uuids,
@ -110,8 +115,7 @@ class DevicesManagementApi {
} }
} }
static Future<List<DeviceModel>> getDevicesByGatewayId( static Future<List<DeviceModel>> getDevicesByGatewayId(String gatewayId) async {
String gatewayId) async {
final response = await HTTPService().get( final response = await HTTPService().get(
path: ApiEndpoints.gatewayApi.replaceAll('{gatewayUuid}', gatewayId), path: ApiEndpoints.gatewayApi.replaceAll('{gatewayUuid}', gatewayId),
showServerMessage: false, showServerMessage: false,
@ -145,9 +149,7 @@ class DevicesManagementApi {
String code, String code,
) async { ) async {
final response = await HTTPService().get( final response = await HTTPService().get(
path: ApiEndpoints.getDeviceLogs path: ApiEndpoints.getDeviceLogs.replaceAll('{uuid}', uuid).replaceAll('{code}', code),
.replaceAll('{uuid}', uuid)
.replaceAll('{code}', code),
showServerMessage: false, showServerMessage: false,
expectedResponseModel: (json) { expectedResponseModel: (json) {
return DeviceReport.fromJson(json); return DeviceReport.fromJson(json);
@ -220,8 +222,7 @@ class DevicesManagementApi {
} }
} }
Future<bool> addScheduleRecord( Future<bool> addScheduleRecord(ScheduleEntry sendSchedule, String uuid) async {
ScheduleEntry sendSchedule, String uuid) async {
try { try {
final response = await HTTPService().post( final response = await HTTPService().post(
path: ApiEndpoints.scheduleByDeviceId.replaceAll('{deviceUuid}', uuid), path: ApiEndpoints.scheduleByDeviceId.replaceAll('{deviceUuid}', uuid),
@ -238,8 +239,7 @@ class DevicesManagementApi {
} }
} }
Future<List<ScheduleModel>> getDeviceSchedules( Future<List<ScheduleModel>> getDeviceSchedules(String uuid, String category) async {
String uuid, String category) async {
try { try {
final response = await HTTPService().get( final response = await HTTPService().get(
path: ApiEndpoints.getScheduleByDeviceId path: ApiEndpoints.getScheduleByDeviceId
@ -262,9 +262,7 @@ class DevicesManagementApi {
} }
Future<bool> updateScheduleRecord( Future<bool> updateScheduleRecord(
{required bool enable, {required bool enable, required String uuid, required String scheduleId}) async {
required String uuid,
required String scheduleId}) async {
try { try {
final response = await HTTPService().put( final response = await HTTPService().put(
path: ApiEndpoints.updateScheduleByDeviceId path: ApiEndpoints.updateScheduleByDeviceId
@ -285,8 +283,7 @@ class DevicesManagementApi {
} }
} }
Future<bool> editScheduleRecord( Future<bool> editScheduleRecord(String uuid, ScheduleEntry newSchedule) async {
String uuid, ScheduleEntry newSchedule) async {
try { try {
final response = await HTTPService().put( final response = await HTTPService().put(
path: ApiEndpoints.scheduleByDeviceId.replaceAll('{deviceUuid}', uuid), path: ApiEndpoints.scheduleByDeviceId.replaceAll('{deviceUuid}', uuid),

View File

@ -1,9 +1,9 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:syncrow_web/pages/routiens/models/create_scene_and_autoamtion/create_automation_model.dart'; import 'package:syncrow_web/pages/routines/models/create_scene_and_autoamtion/create_automation_model.dart';
import 'package:syncrow_web/pages/routiens/models/create_scene_and_autoamtion/create_scene_model.dart'; import 'package:syncrow_web/pages/routines/models/create_scene_and_autoamtion/create_scene_model.dart';
import 'package:syncrow_web/pages/routiens/models/icon_model.dart'; import 'package:syncrow_web/pages/routines/models/icon_model.dart';
import 'package:syncrow_web/pages/routiens/models/routine_details_model.dart'; import 'package:syncrow_web/pages/routines/models/routine_details_model.dart';
import 'package:syncrow_web/pages/routiens/models/routine_model.dart'; import 'package:syncrow_web/pages/routines/models/routine_model.dart';
import 'package:syncrow_web/services/api/http_service.dart'; import 'package:syncrow_web/services/api/http_service.dart';
import 'package:syncrow_web/utils/constants/api_const.dart'; import 'package:syncrow_web/utils/constants/api_const.dart';
import 'package:syncrow_web/utils/constants/temp_const.dart'; import 'package:syncrow_web/utils/constants/temp_const.dart';
@ -12,8 +12,7 @@ class SceneApi {
static final HTTPService _httpService = HTTPService(); static final HTTPService _httpService = HTTPService();
// //create scene // //create scene
static Future<Map<String, dynamic>> createScene( static Future<Map<String, dynamic>> createScene(CreateSceneModel createSceneModel) async {
CreateSceneModel createSceneModel) async {
try { try {
debugPrint('create scene model: ${createSceneModel.toMap()}'); debugPrint('create scene model: ${createSceneModel.toMap()}');
final response = await _httpService.post( final response = await _httpService.post(
@ -70,13 +69,12 @@ class SceneApi {
//get scenes by community id and space id //get scenes by community id and space id
static Future<List<ScenesModel>> getScenesByUnitId( static Future<List<ScenesModel>> getScenes(String spaceId, String communityId,
String unitId, String communityId,
{showInDevice = false}) async { {showInDevice = false}) async {
try { try {
final response = await _httpService.get( final response = await _httpService.get(
path: ApiEndpoints.getUnitScenes path: ApiEndpoints.getScenes
.replaceAll('{spaceUuid}', unitId) .replaceAll('{spaceUuid}', spaceId)
.replaceAll('{communityUuid}', communityId) .replaceAll('{communityUuid}', communityId)
.replaceAll('{projectId}', TempConst.projectId), .replaceAll('{projectId}', TempConst.projectId),
queryParameters: {'showInHomePage': showInDevice}, queryParameters: {'showInHomePage': showInDevice},
@ -99,10 +97,10 @@ class SceneApi {
//getAutomation //getAutomation
static Future<List<ScenesModel>> getAutomationByUnitId(String unitId) async { static Future<List<ScenesModel>> getAutomation(String spaceId) async {
try { try {
final response = await _httpService.get( final response = await _httpService.get(
path: ApiEndpoints.getSpaceAutomation.replaceAll('{unitUuid}', unitId), path: ApiEndpoints.getSpaceAutomation.replaceAll('{spaceUuid}', spaceId),
showServerMessage: false, showServerMessage: false,
expectedResponseModel: (json) { expectedResponseModel: (json) {
List<ScenesModel> scenes = []; List<ScenesModel> scenes = [];
@ -132,12 +130,10 @@ class SceneApi {
// } // }
//automation details //automation details
static Future<RoutineDetailsModel> getAutomationDetails( static Future<RoutineDetailsModel> getAutomationDetails(String automationId) async {
String automationId) async {
try { try {
final response = await _httpService.get( final response = await _httpService.get(
path: ApiEndpoints.getAutomationDetails path: ApiEndpoints.getAutomationDetails.replaceAll('{automationId}', automationId),
.replaceAll('{automationId}', automationId),
showServerMessage: false, showServerMessage: false,
expectedResponseModel: (json) => RoutineDetailsModel.fromMap(json), expectedResponseModel: (json) => RoutineDetailsModel.fromMap(json),
); );
@ -152,8 +148,7 @@ class SceneApi {
try { try {
final response = await _httpService.put( final response = await _httpService.put(
path: ApiEndpoints.updateScene.replaceAll('{sceneId}', sceneId), path: ApiEndpoints.updateScene.replaceAll('{sceneId}', sceneId),
body: createSceneModel body: createSceneModel.toJson(sceneId.isNotEmpty == true ? sceneId : null),
.toJson(sceneId.isNotEmpty == true ? sceneId : null),
expectedResponseModel: (json) { expectedResponseModel: (json) {
return json; return json;
}, },
@ -165,14 +160,11 @@ class SceneApi {
} }
//update automation //update automation
static updateAutomation( static updateAutomation(CreateAutomationModel createAutomationModel, String automationId) async {
CreateAutomationModel createAutomationModel, String automationId) async {
try { try {
final response = await _httpService.put( final response = await _httpService.put(
path: ApiEndpoints.updateAutomation path: ApiEndpoints.updateAutomation.replaceAll('{automationId}', automationId),
.replaceAll('{automationId}', automationId), body: createAutomationModel.toJson(automationId.isNotEmpty == true ? automationId : null),
body: createAutomationModel
.toJson(automationId.isNotEmpty == true ? automationId : null),
expectedResponseModel: (json) { expectedResponseModel: (json) {
return json; return json;
}, },
@ -189,8 +181,7 @@ class SceneApi {
final response = await _httpService.get( final response = await _httpService.get(
path: ApiEndpoints.getScene.replaceAll('{sceneId}', sceneId), path: ApiEndpoints.getScene.replaceAll('{sceneId}', sceneId),
showServerMessage: false, showServerMessage: false,
expectedResponseModel: (json) => expectedResponseModel: (json) => RoutineDetailsModel.fromMap(json['data']),
RoutineDetailsModel.fromMap(json['data']),
); );
return response; return response;
} catch (e) { } catch (e) {
@ -199,8 +190,7 @@ class SceneApi {
} }
//delete Scene //delete Scene
static Future<bool> deleteScene( static Future<bool> deleteScene({required String unitUuid, required String sceneId}) async {
{required String unitUuid, required String sceneId}) async {
try { try {
final response = await _httpService.delete( final response = await _httpService.delete(
path: ApiEndpoints.deleteScene path: ApiEndpoints.deleteScene

View File

@ -25,6 +25,8 @@ abstract class ApiEndpoints {
////// Devices Management //////////////// ////// Devices Management ////////////////
static const String getAllDevices = '/device'; static const String getAllDevices = '/device';
static const String getSpaceDevices =
'/projects/{projectId}/communities/{communityUuid}/spaces/{spaceUuid}/devices';
static const String getDeviceStatus = '/device/{uuid}/functions/status'; static const String getDeviceStatus = '/device/{uuid}/functions/status';
static const String getBatchStatus = '/device/status/batch'; static const String getBatchStatus = '/device/status/batch';
@ -38,8 +40,10 @@ abstract class ApiEndpoints {
// Space Module // Space Module
static const String createSpace = '/projects/{projectId}/communities/{communityId}/spaces'; static const String createSpace = '/projects/{projectId}/communities/{communityId}/spaces';
static const String listSpaces = '/projects/{projectId}/communities/{communityId}/spaces'; static const String listSpaces = '/projects/{projectId}/communities/{communityId}/spaces';
static const String deleteSpace = '/projects/{projectId}/communities/{communityId}/spaces/{spaceId}'; static const String deleteSpace =
static const String updateSpace = '/projects/{projectId}/communities/{communityId}/spaces/{spaceId}'; '/projects/{projectId}/communities/{communityId}/spaces/{spaceId}';
static const String updateSpace =
'/projects/{projectId}/communities/{communityId}/spaces/{spaceId}';
static const String getSpace = '/projects/{projectId}/communities/{communityId}/spaces/{spaceId}'; static const String getSpace = '/projects/{projectId}/communities/{communityId}/spaces/{spaceId}';
static const String getSpaceHierarchy = '/projects/{projectId}/communities/{communityId}/spaces'; static const String getSpaceHierarchy = '/projects/{projectId}/communities/{communityId}/spaces';
@ -63,18 +67,19 @@ abstract class ApiEndpoints {
//product //product
static const String listProducts = '/products'; static const String listProducts = '/products';
static const String getSpaceScenes = '/scene/tap-to-run/{unitUuid}'; static const String getSpaceScenes = '/scene/tap-to-run/{spaceUuid}';
static const String getSpaceAutomation = '/automation/{unitUuid}'; static const String getSpaceAutomation = '/automation/{spaceUuid}';
static const String getIconScene = '/scene/icon'; static const String getIconScene = '/scene/icon';
static const String createScene = '/scene/tap-to-run'; static const String createScene = '/scene/tap-to-run';
static const String createAutomation = '/automation'; static const String createAutomation = '/automation';
static const String getUnitScenes = '/projects/{projectId}/communities/{communityUuid}/spaces/{spaceUuid}/scenes'; static const String getScenes =
'/projects/{projectId}/communities/{communityUuid}/spaces/{spaceUuid}/scenes';
static const String getAutomationDetails = '/automation/details/{automationId}'; static const String getAutomationDetails = '/automation/details/{automationId}';
static const String getScene = '/scene/tap-to-run/{sceneId}'; static const String getScene = '/scene/tap-to-run/{sceneId}';
static const String deleteScene = '/scene/tap-to-run/{sceneId}'; static const String deleteScene = '/scene/tap-to-run/{sceneId}';
static const String deleteAutomation = '/automation/{automationId}'; static const String deleteAutomation = '/automation/{automationId}';
static const String updateScene = '/scene/tap-to-run/{sceneId}'; static const String updateScene = '/scene/tap-to-run/{sceneId}';
static const String updateAutomation = '/automation/{automationId}'; static const String updateAutomation = '/automation/{automationId}';
} }