Merge pull request #132 from SyncrowIOT/fix_routine_popup_and_wall_sensor_bugs

Fix routine popup and wall sensor bugs
This commit is contained in:
mohammadnemer1
2025-04-07 16:43:48 +03:00
committed by GitHub
10 changed files with 463 additions and 392 deletions

View File

@ -2,6 +2,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/common/bloc/project_manager.dart'; import 'package:syncrow_web/pages/common/bloc/project_manager.dart';
import 'package:syncrow_web/pages/routines/bloc/create_routine_bloc/create_routine_event.dart'; import 'package:syncrow_web/pages/routines/bloc/create_routine_bloc/create_routine_event.dart';
import 'package:syncrow_web/pages/routines/bloc/create_routine_bloc/create_routine_state.dart'; import 'package:syncrow_web/pages/routines/bloc/create_routine_bloc/create_routine_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/pages/spaces_management/all_spaces/model/space_model.dart';
import 'package:syncrow_web/services/space_mana_api.dart'; import 'package:syncrow_web/services/space_mana_api.dart';
@ -10,11 +11,12 @@ class CreateRoutineBloc extends Bloc<CreateRoutineEvent, CreateRoutineState> {
on<SpaceOnlyWithDevicesEvent>(_fetchSpaceOnlyWithDevices); on<SpaceOnlyWithDevicesEvent>(_fetchSpaceOnlyWithDevices);
on<SaveCommunityIdAndSpaceIdEvent>(saveSpaceIdCommunityId); on<SaveCommunityIdAndSpaceIdEvent>(saveSpaceIdCommunityId);
on<ResetSelectedEvent>(resetSelected); on<ResetSelectedEvent>(resetSelected);
on<FetchCommunityEvent>(_fetchCommunity);
} }
String selectedSpaceId = ''; String selectedSpaceId = '';
String selectedCommunityId = ''; String selectedCommunityId = '';
List<CommunityModel> communities = [];
List<SpaceModel> spacesOnlyWithDevices = []; List<SpaceModel> spacesOnlyWithDevices = [];
Future<void> _fetchSpaceOnlyWithDevices( Future<void> _fetchSpaceOnlyWithDevices(
@ -30,7 +32,7 @@ class CreateRoutineBloc extends Bloc<CreateRoutineEvent, CreateRoutineState> {
emit(SpaceWithDeviceLoadedState(spacesOnlyWithDevices)); emit(SpaceWithDeviceLoadedState(spacesOnlyWithDevices));
} catch (e) { } catch (e) {
emit(SpaceTreeErrorState('Error loading communities and spaces: $e')); emit(SpaceTreeErrorState('Error loading spaces: $e'));
} }
} }
@ -48,4 +50,18 @@ class CreateRoutineBloc extends Bloc<CreateRoutineEvent, CreateRoutineState> {
selectedCommunityId = ''; selectedCommunityId = '';
emit(const ResetSelectedState()); emit(const ResetSelectedState());
} }
Future<void> _fetchCommunity(
FetchCommunityEvent event, Emitter<CreateRoutineState> emit) async {
emit(const CommunitiesLoadingState());
try {
final projectUuid = await ProjectManager.getProjectUUID() ?? '';
communities =
await CommunitySpaceManagementApi().fetchCommunities(projectUuid);
emit(const CommunityLoadedState());
} catch (e) {
emit(SpaceTreeErrorState('Error loading communities $e'));
}
}
} }

View File

@ -41,3 +41,11 @@ class ResetSelectedEvent extends CreateRoutineEvent {
@override @override
List<Object> get props => []; List<Object> get props => [];
} }
class FetchCommunityEvent extends CreateRoutineEvent {
const FetchCommunityEvent();
@override
List<Object> get props => [];
}

View File

@ -44,3 +44,10 @@ class ResetSelectedState extends CreateRoutineState {
const ResetSelectedState(); const ResetSelectedState();
} }
class CommunityLoadedState extends CreateRoutineState {
const CommunityLoadedState();
}
class CommunitiesLoadingState extends CreateRoutineState {
const CommunitiesLoadingState();
}

View File

@ -1,12 +1,11 @@
import 'package:dropdown_button2/dropdown_button2.dart'; import 'package:dropdown_button2/dropdown_button2.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.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/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
class CommunityDropdown extends StatelessWidget { class CommunityDropdown extends StatelessWidget {
final String? selectedValue; final String? selectedValue;
final List<CommunityModel> communities;
final Function(String?) onChanged; final Function(String?) onChanged;
final TextEditingController _searchController = TextEditingController(); final TextEditingController _searchController = TextEditingController();
@ -14,6 +13,7 @@ class CommunityDropdown extends StatelessWidget {
Key? key, Key? key,
required this.selectedValue, required this.selectedValue,
required this.onChanged, required this.onChanged,
required this.communities,
}) : super(key: key); }) : super(key: key);
@override @override
@ -32,123 +32,123 @@ class CommunityDropdown extends StatelessWidget {
), ),
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
BlocBuilder<SpaceTreeBloc, SpaceTreeState>( SizedBox(
builder: (context, state) { child: Container(
return SizedBox( decoration: BoxDecoration(
child: Container( borderRadius: BorderRadius.circular(10),
),
child: DropdownButton2<String>(
underline: const SizedBox(),
value: selectedValue,
items: communities.map((community) {
return DropdownMenuItem<String>(
value: community.uuid,
child: Text(
' ${community.name}',
overflow: TextOverflow.ellipsis,
maxLines: 1,
),
);
}).toList(),
onChanged: onChanged,
style: const TextStyle(color: Colors.black),
hint: Padding(
padding: const EdgeInsets.only(left: 10),
child: Text(
" Please Select",
style: Theme.of(context).textTheme.bodySmall!.copyWith(
color: ColorsManager.textGray,
),
),
),
customButton: Container(
height: 45,
decoration: BoxDecoration(
border: Border.all(color: ColorsManager.textGray, width: 1.0),
borderRadius: BorderRadius.circular(10),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
flex: 5,
child: Text(
selectedValue != null
? " ${communities.firstWhere((element) => element.uuid == selectedValue).name}"
: ' Please Select',
style: Theme.of(context).textTheme.bodySmall!.copyWith(
color: selectedValue != null
? Colors.black
: ColorsManager.textGray,
),
overflow: TextOverflow.ellipsis,
),
),
Expanded(
child: Container(
decoration: BoxDecoration(
color: Colors.grey[100],
borderRadius: const BorderRadius.only(
topRight: Radius.circular(10),
bottomRight: Radius.circular(10),
),
),
height: 45,
child: const Icon(
Icons.keyboard_arrow_down,
color: ColorsManager.textGray,
),
),
),
],
),
),
dropdownStyleData: DropdownStyleData(
maxHeight: MediaQuery.of(context).size.height * 0.4,
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
), ),
child: DropdownButton2<String>( ),
underline: SizedBox(), dropdownSearchData: DropdownSearchData(
value: selectedValue, searchController: _searchController,
items: state.communityList.map((community) { searchInnerWidgetHeight: 50,
return DropdownMenuItem<String>( searchInnerWidget: Container(
value: community.uuid, height: 50,
child: Text( padding:
' ${community.name}', const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
overflow: TextOverflow.ellipsis, child: TextFormField(
maxLines: 1, style: const TextStyle(color: Colors.black),
controller: _searchController,
decoration: InputDecoration(
isDense: true,
contentPadding: const EdgeInsets.symmetric(
horizontal: 10,
vertical: 12,
), ),
); hintText: 'Search for community...',
}).toList(), border: OutlineInputBorder(
onChanged: onChanged, borderRadius: BorderRadius.circular(8),
style: TextStyle(color: Colors.black),
hint: Padding(
padding: EdgeInsets.only(left: 10),
child: Text(
" Please Select",
style: Theme.of(context).textTheme.bodySmall!.copyWith(
color: ColorsManager.textGray,
),
),
),
customButton: Container(
height: 45,
decoration: BoxDecoration(
border: Border.all(color: ColorsManager.textGray, width: 1.0),
borderRadius: BorderRadius.circular(10),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
flex: 5,
child: Text(
selectedValue != null
? " ${state.communityList.firstWhere((element) => element.uuid == selectedValue).name}"
: ' Please Select',
style: Theme.of(context).textTheme.bodySmall!.copyWith(
color:
selectedValue != null ? Colors.black : ColorsManager.textGray,
),
overflow: TextOverflow.ellipsis,
),
),
Expanded(
child: Container(
decoration: BoxDecoration(
color: Colors.grey[100],
borderRadius: const BorderRadius.only(
topRight: Radius.circular(10),
bottomRight: Radius.circular(10),
),
),
height: 45,
child: const Icon(
Icons.keyboard_arrow_down,
color: ColorsManager.textGray,
),
),
),
],
),
),
dropdownStyleData: DropdownStyleData(
maxHeight: MediaQuery.of(context).size.height * 0.4,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
),
),
dropdownSearchData: DropdownSearchData(
searchController: _searchController,
searchInnerWidgetHeight: 50,
searchInnerWidget: Container(
height: 50,
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
child: TextFormField(
style: const TextStyle(color: Colors.black),
controller: _searchController,
decoration: InputDecoration(
isDense: true,
contentPadding: const EdgeInsets.symmetric(
horizontal: 10,
vertical: 12,
),
hintText: 'Search for community...',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
),
),
), ),
), ),
searchMatchFn: (item, searchValue) {
final communityName = (item.child as Text).data?.toLowerCase() ?? '';
return communityName.contains(searchValue.toLowerCase().trim());
},
),
onMenuStateChange: (isOpen) {
if (!isOpen) {
_searchController.clear();
}
},
menuItemStyleData: const MenuItemStyleData(
height: 40,
), ),
), ),
)); searchMatchFn: (item, searchValue) {
}, final communityName =
), (item.child as Text).data?.toLowerCase() ?? '';
return communityName
.contains(searchValue.toLowerCase().trim());
},
),
onMenuStateChange: (isOpen) {
if (!isOpen) {
_searchController.clear();
}
},
menuItemStyleData: const MenuItemStyleData(
height: 40,
),
),
))
], ],
), ),
); );

View File

@ -5,11 +5,10 @@ import 'package:syncrow_web/pages/routines/bloc/create_routine_bloc/create_routi
import 'package:syncrow_web/pages/routines/bloc/create_routine_bloc/create_routine_bloc.dart'; import 'package:syncrow_web/pages/routines/bloc/create_routine_bloc/create_routine_bloc.dart';
import 'package:syncrow_web/pages/routines/create_new_routines/commu_dropdown.dart'; import 'package:syncrow_web/pages/routines/create_new_routines/commu_dropdown.dart';
import 'package:syncrow_web/pages/routines/create_new_routines/space_dropdown.dart'; import 'package:syncrow_web/pages/routines/create_new_routines/space_dropdown.dart';
import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
class CreateNewRoutinesDialog extends StatefulWidget { class CreateNewRoutinesDialog extends StatefulWidget {
const CreateNewRoutinesDialog({Key? key}) : super(key: key); const CreateNewRoutinesDialog({super.key});
@override @override
State<CreateNewRoutinesDialog> createState() => State<CreateNewRoutinesDialog> createState() =>
@ -19,136 +18,160 @@ class CreateNewRoutinesDialog extends StatefulWidget {
class _CreateNewRoutinesDialogState extends State<CreateNewRoutinesDialog> { class _CreateNewRoutinesDialogState extends State<CreateNewRoutinesDialog> {
String? _selectedCommunity; String? _selectedCommunity;
String? _selectedSpace; String? _selectedSpace;
void _fetchSpaces(String communityId) {
context
.read<CreateRoutineBloc>()
.add(SpaceOnlyWithDevicesEvent(communityId));
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocBuilder<CreateRoutineBloc, CreateRoutineState>( return BlocProvider(
builder: (context, state) { create: (BuildContext context) =>
final _bloc = BlocProvider.of<CreateRoutineBloc>(context); CreateRoutineBloc()..add(const FetchCommunityEvent()),
final spaces = _bloc.spacesOnlyWithDevices; child: BlocBuilder<CreateRoutineBloc, CreateRoutineState>(
final isLoading = state is SpaceWithDeviceLoadingState; builder: (context, state) {
final _bloc = BlocProvider.of<CreateRoutineBloc>(context);
final spaces = _bloc.spacesOnlyWithDevices;
final isLoadingCommunities = state is CommunitiesLoadingState;
final isLoadingSpaces = state is SpaceWithDeviceLoadingState;
String spaceHint = 'Select a community first';
if (_selectedCommunity != null) {
if (isLoadingSpaces) {
spaceHint = 'Loading spaces...';
} else if (spaces.isEmpty) {
spaceHint = 'No spaces available';
} else {
spaceHint = 'Select Space';
}
}
String spaceHint = 'Select a community first'; return AlertDialog(
backgroundColor: Colors.white,
if (_selectedCommunity != null) { insetPadding: EdgeInsets.zero,
if (isLoading) { contentPadding: EdgeInsets.zero,
spaceHint = 'Loading spaces...'; shape: RoundedRectangleBorder(
} else if (spaces.isEmpty) { borderRadius: BorderRadius.circular(12)),
spaceHint = 'No spaces available'; title: Text(
} else { 'Create New Routines',
spaceHint = 'Select Space'; textAlign: TextAlign.center,
} style: Theme.of(context).textTheme.bodyMedium!.copyWith(
} color: ColorsManager.primaryColor,
),
return AlertDialog(
backgroundColor: Colors.white,
insetPadding: EdgeInsets.zero,
contentPadding: EdgeInsets.zero,
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
title: Text(
'Create New Routines',
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
color: ColorsManager.primaryColor,
),
),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Divider(),
Padding(
padding: const EdgeInsets.only(left: 15, right: 15),
child: CommunityDropdown(
selectedValue: _selectedCommunity,
onChanged: (String? newValue) {
setState(() {
_selectedCommunity = newValue;
_selectedSpace = null;
});
if (newValue != null) {
_fetchSpaces(newValue);
}
},
),
), ),
const SizedBox(height: 5), content: Stack(
Padding(
padding: const EdgeInsets.only(left: 15, right: 15),
child: SpaceDropdown(
hintMessage: spaceHint,
spaces: spaces,
selectedValue: _selectedSpace,
onChanged: (String? newValue) {
setState(() {
_selectedSpace = newValue;
});
},
),
),
const Divider(),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [ children: [
Padding( Column(
padding: const EdgeInsets.only( mainAxisSize: MainAxisSize.min,
left: 20, children: [
right: 20, const Divider(),
), Padding(
child: TextButton( padding: const EdgeInsets.only(left: 15, right: 15),
onPressed: () { child: CommunityDropdown(
Navigator.of(context).pop(); communities: _bloc.communities,
}, selectedValue: _selectedCommunity,
child: Text( onChanged: (String? newValue) {
'Cancel', setState(() {
style: Theme.of(context).textTheme.bodyMedium!.copyWith( _selectedCommunity = newValue;
fontWeight: FontWeight.w400, _selectedSpace = null;
fontSize: 14, });
color: ColorsManager.blackColor, if (newValue != null) {
), _bloc.add(SpaceOnlyWithDevicesEvent(newValue));
}
},
),
), ),
), const SizedBox(height: 5),
), Padding(
Padding( padding: const EdgeInsets.only(left: 15, right: 15),
padding: const EdgeInsets.only( child: SpaceDropdown(
left: 20, hintMessage: spaceHint,
right: 20, spaces: spaces,
), selectedValue: _selectedSpace,
child: TextButton( onChanged: (String? newValue) {
onPressed: setState(() {
_selectedCommunity != null && _selectedSpace != null _selectedSpace = newValue;
? () { });
Navigator.of(context).pop({ },
'community': _selectedCommunity, ),
'space': _selectedSpace, ),
}); const Divider(),
} Row(
: null, mainAxisAlignment: MainAxisAlignment.spaceAround,
child: Text( children: [
'Next', Padding(
style: Theme.of(context).textTheme.bodyMedium!.copyWith( padding: const EdgeInsets.only(
fontWeight: FontWeight.w400, left: 20,
fontSize: 14, right: 20,
color: _selectedCommunity != null && ),
child: TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text(
'Cancel',
style: Theme.of(context)
.textTheme
.bodyMedium!
.copyWith(
fontWeight: FontWeight.w400,
fontSize: 14,
color: ColorsManager.blackColor,
),
),
),
),
Padding(
padding: const EdgeInsets.only(
left: 20,
right: 20,
),
child: TextButton(
onPressed: _selectedCommunity != null &&
_selectedSpace != null _selectedSpace != null
? ColorsManager.blueColor ? () {
: Colors.blue.shade100, Navigator.of(context).pop({
'community': _selectedCommunity,
'space': _selectedSpace,
});
}
: null,
child: Text(
'Next',
style: Theme.of(context)
.textTheme
.bodyMedium!
.copyWith(
fontWeight: FontWeight.w400,
fontSize: 14,
color: _selectedCommunity != null &&
_selectedSpace != null
? ColorsManager.blueColor
: Colors.blue.shade100,
),
),
), ),
),
],
),
const SizedBox(height: 10),
],
),
if (isLoadingCommunities)
const SizedBox(
height: 200,
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Center(
child: CircularProgressIndicator(
color: ColorsManager.primaryColor,
),
),
],
), ),
), ),
),
], ],
), ),
SizedBox(height: 10), );
], },
), ));
);
},
);
} }
} }

View File

@ -244,11 +244,12 @@ class CurrentDistanceFunction extends WpsFunctions {
@override @override
List<WpsOperationalValue> getOperationalValues() { List<WpsOperationalValue> getOperationalValues() {
List<WpsOperationalValue> values = []; List<WpsOperationalValue> values = [];
for (int temp = min; temp <= max; temp += step) { for (int cm = min; cm <= max; cm += step) {
values.add(WpsOperationalValue( values.add(WpsOperationalValue(
icon: Assets.assetsTempreture, icon: Assets.assetsTempreture,
description: "${temp}CM", description: "${cm}CM",
value: temp,
value: cm,
)); ));
} }
return values; return values;

View File

@ -105,9 +105,7 @@ class IfContainer extends StatelessWidget {
); );
}, },
onAcceptWithDetails: (data) async { onAcceptWithDetails: (data) async {
print('data.data=${data.data}');
final uniqueCustomId = const Uuid().v4(); final uniqueCustomId = const Uuid().v4();
final mutableData = Map<String, dynamic>.from(data.data); final mutableData = Map<String, dynamic>.from(data.data);
mutableData['uniqueCustomId'] = uniqueCustomId; mutableData['uniqueCustomId'] = uniqueCustomId;

View File

@ -31,165 +31,185 @@ class _FetchRoutineScenesState extends State<FetchRoutineScenesAutomation>
? const Center( ? const Center(
child: CircularProgressIndicator(), child: CircularProgressIndicator(),
) )
: Padding( : SingleChildScrollView(
padding: const EdgeInsets.symmetric(vertical: 16.0), child: Padding(
child: Column( padding: const EdgeInsets.symmetric(vertical: 16.0),
crossAxisAlignment: CrossAxisAlignment.start, child: Column(
mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start,
children: [ mainAxisSize: MainAxisSize.min,
Text( children: [
"Scenes (Tab to Run)", Text(
style: Theme.of(context).textTheme.titleLarge?.copyWith( "Scenes (Tab to Run)",
color: ColorsManager.grayColor, style: Theme.of(context).textTheme.titleLarge?.copyWith(
fontWeight: FontWeight.bold, color: ColorsManager.grayColor,
), fontWeight: FontWeight.bold,
), ),
const SizedBox(height: 10), ),
if (state.scenes.isEmpty) const SizedBox(height: 10),
Expanded( if (state.scenes.isEmpty)
child: Text( Text(
"No scenes found", "No scenes found",
style: context.textTheme.bodyMedium?.copyWith( style: context.textTheme.bodyMedium?.copyWith(
color: ColorsManager.grayColor, color: ColorsManager.grayColor,
), ),
), ),
), if (state.scenes.isNotEmpty)
if (state.scenes.isNotEmpty) SizedBox(
ConstrainedBox( height: 200,
constraints: BoxConstraints( child: ListView.builder(
maxHeight: isSmallScreenSize(context) ? 190 : 200, shrinkWrap: true,
maxWidth: MediaQuery.sizeOf(context).width * 0.8), scrollDirection: Axis.horizontal,
child: ListView.builder( itemCount: state.scenes.length,
scrollDirection: Axis.horizontal, itemBuilder: (context, index) {
itemCount: state.scenes.length, final scene = state.scenes[index];
itemBuilder: (context, index) { final isLoading =
final scene = state.scenes[index]; state.loadingSceneId == scene.id;
final isLoading =
state.loadingSceneId == scene.id;
return Padding( return Padding(
padding: EdgeInsets.only( padding: EdgeInsets.only(
right: isSmallScreenSize(context) ? 4.0 : 8.0, right:
), isSmallScreenSize(context) ? 4.0 : 8.0,
child: RoutineViewCard( ),
isLoading: isLoading, child: Column(
sceneOnTap: () { children: [
context.read<RoutineBloc>().add( RoutineViewCard(
SceneTrigger( isLoading: isLoading,
sceneId: scene.id, sceneOnTap: () {
name: scene.name)); context.read<RoutineBloc>().add(
}, SceneTrigger(
status: state.scenes[index].status, sceneId: scene.id,
communityId: name: scene.name));
state.scenes[index].communityId ?? '', },
spaceId: state.scenes[index].spaceId, status: state.scenes[index].status,
sceneId: state.scenes[index].sceneTuyaId!, communityId:
automationId: state.scenes[index].id, state.scenes[index].communityId ??
cardType: 'scenes', '',
spaceName: state.scenes[index].spaceName, spaceId: state.scenes[index].spaceId,
onTap: () { sceneId:
BlocProvider.of<RoutineBloc>(context).add( state.scenes[index].sceneTuyaId!,
const CreateNewRoutineViewEvent( automationId: state.scenes[index].id,
createRoutineView: true), cardType: 'scenes',
); spaceName:
context.read<RoutineBloc>().add( state.scenes[index].spaceName,
GetSceneDetails( onTap: () {
sceneId: state.scenes[index].id, BlocProvider.of<RoutineBloc>(context)
isTabToRun: true, .add(
isUpdate: true, const CreateNewRoutineViewEvent(
), createRoutineView: true),
); );
}, context.read<RoutineBloc>().add(
textString: state.scenes[index].name, GetSceneDetails(
icon: state.scenes[index].icon ?? sceneId:
Assets.logoHorizontal, state.scenes[index].id,
isFromScenes: true, isTabToRun: true,
iconInBytes: state.scenes[index].iconInBytes, isUpdate: true,
), ),
); );
}), },
textString: state.scenes[index].name,
icon: state.scenes[index].icon ??
Assets.logoHorizontal,
isFromScenes: true,
iconInBytes:
state.scenes[index].iconInBytes,
),
],
),
);
}),
),
const SizedBox(height: 10),
Text(
"Automations",
style: Theme.of(context).textTheme.titleLarge?.copyWith(
color: ColorsManager.grayColor,
fontWeight: FontWeight.bold,
),
), ),
const SizedBox(height: 10), const SizedBox(height: 3),
Text( if (state.automations.isEmpty)
"Automations", Text(
style: Theme.of(context).textTheme.titleLarge?.copyWith(
color: ColorsManager.grayColor,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 3),
if (state.automations.isEmpty)
Expanded(
child: Text(
"No automations found", "No automations found",
style: context.textTheme.bodyMedium?.copyWith( style: context.textTheme.bodyMedium?.copyWith(
color: ColorsManager.grayColor, color: ColorsManager.grayColor,
), ),
), ),
), if (state.automations.isNotEmpty)
if (state.automations.isNotEmpty) SizedBox(
ConstrainedBox( height: 200,
constraints: BoxConstraints(
maxHeight: isSmallScreenSize(context) ? 190 : 195,
),
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: state.automations.length,
itemBuilder: (context, index) {
final isLoading = state.automations!
.contains(state.automations[index].id);
return Padding( child: ListView.builder(
padding: EdgeInsets.only( shrinkWrap: true,
right: isSmallScreenSize(context) ? 4.0 : 8.0, scrollDirection: Axis.horizontal,
), itemCount: state.automations.length,
child: RoutineViewCard( itemBuilder: (context, index) {
isLoading: isLoading, final isLoading = state.automations!
onChanged: (v) { .contains(state.automations[index].id);
// BlocProvider.of<RoutineBloc>(context)
context.read<RoutineBloc>().add( return Column(
UpdateAutomationStatus( children: [
automationId: Padding(
state.automations[index].id, padding: EdgeInsets.only(
automationStatusUpdate: right: isSmallScreenSize(context)
AutomationStatusUpdate( ? 4.0
spaceUuid: state : 8.0,
.automations[index] ),
.spaceId, child: RoutineViewCard(
isEnable: v), isLoading: isLoading,
communityId: state onChanged: (v) {
.automations[index].communityId, context.read<RoutineBloc>().add(
), UpdateAutomationStatus(
); automationId: state
}, .automations[index].id,
status: state.automations[index].status, automationStatusUpdate:
communityId: '', AutomationStatusUpdate(
spaceId: state.automations[index].spaceId, spaceUuid: state
sceneId: '', .automations[
automationId: state.automations[index].id, index]
cardType: 'automations', .spaceId,
spaceName: state.scenes[index].spaceName, isEnable: v),
onTap: () { communityId: state
BlocProvider.of<RoutineBloc>(context).add( .automations[index]
const CreateNewRoutineViewEvent( .communityId,
createRoutineView: true), ),
); );
context.read<RoutineBloc>().add( },
GetAutomationDetails( status: state.automations[index].status,
automationId: communityId: '',
state.automations[index].id, spaceId:
isAutomation: true, state.automations[index].spaceId,
isUpdate: true), sceneId: '',
); automationId:
}, state.automations[index].id,
textString: state.automations[index].name, cardType: 'automations',
icon: state.automations[index].icon ?? spaceName:
Assets.automation, state.scenes[index].spaceName,
), 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

@ -177,6 +177,8 @@ class _RoutineViewCardState extends State<RoutineViewCard> {
: (widget.icon is String && : (widget.icon is String &&
widget.icon.endsWith('.svg')) widget.icon.endsWith('.svg'))
? SvgPicture.asset( ? SvgPicture.asset(
height: iconSize,
width: iconSize,
widget.icon, widget.icon,
fit: BoxFit.contain, fit: BoxFit.contain,
) )

View File

@ -13,7 +13,6 @@ 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/routines/bloc/functions_bloc/functions_bloc_bloc.dart'; import 'package:syncrow_web/pages/routines/bloc/functions_bloc/functions_bloc_bloc.dart';
class WallPresenceSensor extends StatefulWidget { class WallPresenceSensor extends StatefulWidget {
final List<DeviceFunction> functions; final List<DeviceFunction> functions;
final AllDevicesModel? device; final AllDevicesModel? device;
@ -171,7 +170,7 @@ class _WallPresenceSensorState extends State<WallPresenceSensor> {
orElse: () => DeviceFunctionData( orElse: () => DeviceFunctionData(
entityId: '', entityId: '',
functionCode: selectedFunction, functionCode: selectedFunction,
operationName: '', operationName: state.selectedOperationName ?? '',
value: null, value: null,
), ),
); );
@ -251,11 +250,8 @@ class _ValueSelector extends StatelessWidget {
); );
} }
bool _isSliderFunction(String function) => [ bool _isSliderFunction(String function) =>
'dis_current', ['dis_current', 'presence_time', 'illuminance_value'].contains(function);
'presence_time',
'illuminance_value'
].contains(function);
} }
class _SliderValueSelector extends StatelessWidget { class _SliderValueSelector extends StatelessWidget {