push display scenes and automations

This commit is contained in:
ashrafzarkanisala
2024-11-27 19:41:43 +03:00
parent 69e2295180
commit cf817fd5dc
13 changed files with 141 additions and 282 deletions

View File

@ -18,13 +18,13 @@ class DeviceManagementPage extends StatelessWidget with HelperResponsiveLayout {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return MultiBlocProvider( return MultiBlocProvider(
providers: [ providers: [
BlocProvider(
create: (context) => DeviceManagementBloc()..add(FetchDevices()),
),
BlocProvider( BlocProvider(
create: (context) => create: (context) =>
SwitchTabsBloc()..add(const TriggerSwitchTabsEvent(false)), SwitchTabsBloc()..add(const TriggerSwitchTabsEvent(false)),
), ),
BlocProvider(
create: (context) => DeviceManagementBloc()..add(FetchDevices()),
),
], ],
child: WebScaffold( child: WebScaffold(
appBarTitle: FittedBox( appBarTitle: FittedBox(
@ -101,12 +101,11 @@ class DeviceManagementPage extends StatelessWidget with HelperResponsiveLayout {
builder: (context, deviceState) { builder: (context, deviceState) {
if (deviceState is DeviceManagementLoading) { if (deviceState is DeviceManagementLoading) {
return const Center(child: CircularProgressIndicator()); return const Center(child: CircularProgressIndicator());
} else if (deviceState is DeviceManagementLoaded || } else if (deviceState is DeviceManagementLoaded) {
deviceState is DeviceManagementFiltered) { return DeviceManagementBody(devices: deviceState.devices);
final devices = (deviceState as dynamic).devices ?? } else if (deviceState is DeviceManagementFiltered) {
(deviceState as DeviceManagementFiltered).filteredDevices; return DeviceManagementBody(
devices: deviceState.filteredDevices);
return DeviceManagementBody(devices: devices);
} else { } else {
return const Center(child: Text('Error fetching Devices')); return const Center(child: Text('Error fetching Devices'));
} }

View File

@ -18,14 +18,6 @@ class _DeviceSearchFiltersState extends State<DeviceSearchFilters>
final TextEditingController unitNameController = TextEditingController(); final TextEditingController unitNameController = TextEditingController();
final TextEditingController productNameController = TextEditingController(); final TextEditingController productNameController = TextEditingController();
@override
void dispose() {
communityController.dispose();
unitNameController.dispose();
productNameController.dispose();
super.dispose();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return isExtraLargeScreenSize(context) return isExtraLargeScreenSize(context)

View File

@ -13,6 +13,7 @@ part 'routine_event.dart';
part 'routine_state.dart'; part 'routine_state.dart';
const spaceId = '25c96044-fadf-44bb-93c7-3c079e527ce6'; const spaceId = '25c96044-fadf-44bb-93c7-3c079e527ce6';
const communityId = '25c96044-fadf-44bb-93c7-3c079e527ce6';
class RoutineBloc extends Bloc<RoutineEvent, RoutineState> { class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
RoutineBloc() : super(const RoutineState()) { RoutineBloc() : super(const RoutineState()) {
@ -114,7 +115,7 @@ 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); final scenes = await SceneApi.getScenesByUnitId(event.unitId, event.communityId);
emit(state.copyWith( emit(state.copyWith(
scenes: scenes, scenes: scenes,
isLoading: false, isLoading: false,
@ -233,7 +234,7 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
final result = await SceneApi.createScene(createSceneModel); final result = await SceneApi.createScene(createSceneModel);
if (result['success']) { if (result['success']) {
emit(_resetState()); emit(_resetState());
add(const LoadScenes(spaceId)); add(const LoadScenes(spaceId, communityId));
} else { } else {
emit(state.copyWith( emit(state.copyWith(
isLoading: false, isLoading: false,

View File

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

View File

@ -1,177 +1,5 @@
import 'dart:convert'; import 'dart:convert';
import 'package:syncrow_web/pages/routiens/models/create_scene_and_autoamtion/create_scene_model.dart';
// class CreateAutomationModel {
// String unitUuid;
// String automationName;
// String decisionExpr;
// EffectiveTime effectiveTime;
// List<CreateCondition> conditions;
// List<CreateSceneAction> actions;
// CreateAutomationModel({
// required this.unitUuid,
// required this.automationName,
// required this.decisionExpr,
// required this.effectiveTime,
// required this.conditions,
// required this.actions,
// });
// CreateAutomationModel copyWith({
// String? unitUuid,
// String? automationName,
// String? decisionExpr,
// EffectiveTime? effectiveTime,
// List<CreateCondition>? conditions,
// List<CreateSceneAction>? actions,
// }) {
// return CreateAutomationModel(
// unitUuid: unitUuid ?? this.unitUuid,
// automationName: automationName ?? this.automationName,
// decisionExpr: decisionExpr ?? this.decisionExpr,
// effectiveTime: effectiveTime ?? this.effectiveTime,
// conditions: conditions ?? this.conditions,
// actions: actions ?? this.actions,
// );
// }
// Map<String, dynamic> toMap([String? automationId]) {
// return {
// if (automationId == null) 'spaceUuid': unitUuid,
// 'automationName': automationName,
// 'decisionExpr': decisionExpr,
// 'effectiveTime': effectiveTime.toMap(),
// 'conditions': conditions.map((x) => x.toMap()).toList(),
// 'actions': actions.map((x) => x.toMap()).toList(),
// };
// }
// factory CreateAutomationModel.fromMap(Map<String, dynamic> map) {
// return CreateAutomationModel(
// unitUuid: map['spaceUuid'] ?? '',
// automationName: map['automationName'] ?? '',
// decisionExpr: map['decisionExpr'] ?? '',
// effectiveTime: EffectiveTime.fromMap(map['effectiveTime']),
// conditions: List<CreateCondition>.from(
// map['conditions']?.map((x) => CreateCondition.fromMap(x))),
// actions: List<CreateSceneAction>.from(
// map['actions']?.map((x) => CreateSceneAction.fromMap(x))),
// );
// }
// String toJson([String? automationId]) => json.encode(toMap(automationId));
// factory CreateAutomationModel.fromJson(String source) =>
// CreateAutomationModel.fromMap(json.decode(source));
// @override
// String toString() {
// return 'CreateAutomationModel(unitUuid: $unitUuid, automationName: $automationName, decisionExpr: $decisionExpr, effectiveTime: $effectiveTime, conditions: $conditions, actions: $actions)';
// }
// }
// class EffectiveTime {
// String start;
// String end;
// String loops;
// EffectiveTime({
// required this.start,
// required this.end,
// required this.loops,
// });
// Map<String, dynamic> toMap() {
// return {
// 'start': start,
// 'end': end,
// 'loops': loops,
// };
// }
// factory EffectiveTime.fromMap(Map<String, dynamic> map) {
// return EffectiveTime(
// start: map['start'] ?? '',
// end: map['end'] ?? '',
// loops: map['loops'] ?? '',
// );
// }
// @override
// String toString() => 'EffectiveTime(start: $start, end: $end, loops: $loops)';
// }
// class CreateCondition {
// int code;
// String entityId;
// String entityType;
// ConditionExpr expr;
// CreateCondition({
// required this.code,
// required this.entityId,
// required this.entityType,
// required this.expr,
// });
// Map<String, dynamic> toMap() {
// return {
// 'code': code,
// 'entityId': entityId,
// 'entityType': entityType,
// 'expr': expr.toMap(),
// };
// }
// factory CreateCondition.fromMap(Map<String, dynamic> map) {
// return CreateCondition(
// code: map['code'] ?? 0,
// entityId: map['entityId'] ?? '',
// entityType: map['entityType'] ?? '',
// expr: ConditionExpr.fromMap(map['expr']),
// );
// }
// @override
// String toString() =>
// 'CreateCondition(code: $code, entityId: $entityId, entityType: $entityType, expr: $expr)';
// }
// class ConditionExpr {
// String statusCode;
// String comparator;
// dynamic statusValue;
// ConditionExpr({
// required this.statusCode,
// required this.comparator,
// required this.statusValue,
// });
// Map<String, dynamic> toMap() {
// return {
// 'statusCode': statusCode,
// 'comparator': comparator,
// 'statusValue': statusValue,
// };
// }
// factory ConditionExpr.fromMap(Map<String, dynamic> map) {
// return ConditionExpr(
// statusCode: map['statusCode'] ?? '',
// comparator: map['comparator'] ?? '',
// statusValue: map['statusValue'],
// );
// }
// @override
// String toString() =>
// 'ConditionExpr(statusCode: $statusCode, comparator: $comparator, statusValue: $statusValue)';
// }
import 'dart:convert';
class CreateAutomationModel { class CreateAutomationModel {
String spaceUuid; String spaceUuid;
String automationName; String automationName;

View File

@ -22,9 +22,9 @@ class ScenesModel {
name: json["name"] ?? '', name: json["name"] ?? '',
status: json["status"] ?? '', status: json["status"] ?? '',
type: json["type"] ?? '', type: json["type"] ?? '',
icon: (isAutomation ?? false) icon: isAutomation == true
? Assets.automation ? Assets.automation
: json["icon"] as String?, : (json["icon"] as String?),
); );
Map<String, dynamic> toJson() => { Map<String, dynamic> toJson() => {

View File

@ -49,8 +49,7 @@ class RoutinesView extends StatelessWidget {
const SizedBox( const SizedBox(
height: 30, height: 30,
), ),
const FetchRoutineScenesAutomation(), const Expanded(child: FetchRoutineScenesAutomation()),
const Spacer(),
], ],
), ),
); );

View File

@ -4,12 +4,14 @@ 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/pages/routiens/widgets/main_routine_view/routine_view_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';
class FetchRoutineScenesAutomation extends StatefulWidget { class FetchRoutineScenesAutomation extends StatefulWidget {
const FetchRoutineScenesAutomation({super.key}); const FetchRoutineScenesAutomation({super.key});
@override @override
State<FetchRoutineScenesAutomation> createState() => _FetchRoutineScenesState(); State<FetchRoutineScenesAutomation> createState() =>
_FetchRoutineScenesState();
} }
class _FetchRoutineScenesState extends State<FetchRoutineScenesAutomation> { class _FetchRoutineScenesState extends State<FetchRoutineScenesAutomation> {
@ -17,7 +19,7 @@ class _FetchRoutineScenesState extends State<FetchRoutineScenesAutomation> {
void initState() { void initState() {
super.initState(); super.initState();
context.read<RoutineBloc>() context.read<RoutineBloc>()
..add(const LoadScenes(spaceId)) ..add(const LoadScenes(spaceId, communityId))
..add(const LoadAutomation(spaceId)); ..add(const LoadAutomation(spaceId));
} }
@ -25,83 +27,84 @@ class _FetchRoutineScenesState extends State<FetchRoutineScenesAutomation> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocBuilder<RoutineBloc, RoutineState>( return BlocBuilder<RoutineBloc, RoutineState>(
builder: (context, state) { builder: (context, state) {
debugPrint(state.scenes.toString()); return SizedBox(
debugPrint(state.automations.toString()); height: 500,
child: Column(
return Column( crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min, children: [
crossAxisAlignment: CrossAxisAlignment.start, if (state.isLoading)
children: [ const Center(
Text( child: CircularProgressIndicator(),
"Scenes (Tab to Run)", ),
style: Theme.of(context).textTheme.titleLarge?.copyWith( Text(
color: ColorsManager.grayColor, "Scenes (Tab to Run)",
fontWeight: FontWeight.bold, style: Theme.of(context).textTheme.titleLarge?.copyWith(
), color: ColorsManager.grayColor,
), fontWeight: FontWeight.bold,
const SizedBox( ),
height: 10, ),
), const SizedBox(height: 10),
state.loadScenesErrorMessage != null if (state.scenes.isEmpty)
? Text(state.loadScenesErrorMessage ?? '')
: state.scenes.isNotEmpty
? SizedBox(
height: 200,
child: ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemCount: state.scenes.length,
itemBuilder: (context, index) {
return RoutineViewCard(
onTap: () {},
textString: state.scenes[index].name,
icon: state.scenes[index].icon ?? Assets.logoHorizontal,
);
},
),
)
: const CircularProgressIndicator(),
const SizedBox(
height: 30,
),
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text( Text(
"Automations", "No scenes found",
style: Theme.of(context).textTheme.titleLarge?.copyWith( style: context.textTheme.bodyMedium?.copyWith(
color: ColorsManager.grayColor, color: ColorsManager.grayColor,
fontWeight: FontWeight.bold, ),
),
), ),
const SizedBox( if (state.scenes.isNotEmpty)
height: 10, SizedBox(
height: 200,
child: ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemCount: state.scenes.length,
itemBuilder: (context, index) {
return RoutineViewCard(
onTap: () {},
textString: state.scenes[index].name,
icon: state.scenes[index].icon ?? Assets.logoHorizontal,
);
},
),
), ),
state.loadAutomationErrorMessage != null const SizedBox(height: 30),
? Text(state.loadAutomationErrorMessage ?? '') Text(
: state.automations.isNotEmpty "Automations",
? Expanded( style: Theme.of(context).textTheme.titleLarge?.copyWith(
child: SizedBox( color: ColorsManager.grayColor,
height: 200, fontWeight: FontWeight.bold,
child: ListView.builder( ),
shrinkWrap: true, ),
scrollDirection: Axis.horizontal, const SizedBox(height: 10),
itemCount: state.automations.length, if (state.automations.isEmpty)
itemBuilder: (context, index) { Text(
return RoutineViewCard( "No automations found",
onTap: () {}, style: context.textTheme.bodyMedium?.copyWith(
textString: state.automations[index].name, color: ColorsManager.grayColor,
icon: Assets.automation, ),
); ),
}, if (state.automations.isNotEmpty)
), SizedBox(
), height: 200,
) child: ListView.builder(
: const CircularProgressIndicator(), shrinkWrap: true,
], scrollDirection: Axis.horizontal,
) itemCount: state.automations.length,
], itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.only(right: 8.0),
child: RoutineViewCard(
onTap: () {},
textString: state.automations[index].name,
icon: state.automations[index].icon ??
Assets.automation,
),
);
},
),
),
],
),
); );
}, },
); );

View File

@ -47,8 +47,16 @@ class RoutineViewCard extends StatelessWidget {
), ),
height: 70, height: 70,
width: 70, width: 70,
child: (icon is String) && icon.contains('.svg') child: (icon is String)
? SvgPicture.asset(icon) ? icon.endsWith('.svg')
? SvgPicture.asset(
icon,
fit: BoxFit.contain,
)
: Image.asset(
icon,
fit: BoxFit.contain,
)
: Icon( : Icon(
icon, icon,
color: ColorsManager.dialogBlueTitle, color: ColorsManager.dialogBlueTitle,

View File

@ -1,8 +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/common/custom_table.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/bloc/switch_tabs/switch_tabs_bloc.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/bloc/switch_tabs/switch_tabs_bloc.dart';
import 'package:syncrow_web/pages/home/bloc/home_bloc.dart';
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart'; import 'package:syncrow_web/pages/routiens/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

@ -18,7 +18,7 @@ class _ScenesAndAutomationsState extends State<ScenesAndAutomations> {
void initState() { void initState() {
super.initState(); super.initState();
context.read<RoutineBloc>() context.read<RoutineBloc>()
..add(const LoadScenes(spaceId)) ..add(const LoadScenes(spaceId, communityId))
..add(const LoadAutomation(spaceId)); ..add(const LoadAutomation(spaceId));
} }
@ -34,7 +34,9 @@ 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.toLowerCase().contains(state.searchText!.toLowerCase()) return scene.name
.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

@ -69,14 +69,21 @@ class SceneApi {
//get scene by unit id //get scene by unit id
static Future<List<ScenesModel>> getScenesByUnitId(String unitId) async { static Future<List<ScenesModel>> getScenesByUnitId(
String unitId, String communityId,
{showInDevice = false}) async {
try { try {
final response = await _httpService.get( final response = await _httpService.get(
path: ApiEndpoints.getSpaceScenes.replaceAll('{unitUuid}', unitId), path: ApiEndpoints.getUnitScenes
.replaceAll('{spaceUuid}', unitId)
.replaceAll('{communityUuid}', communityId),
queryParameters: {'showInHomePage': showInDevice},
showServerMessage: false, showServerMessage: false,
expectedResponseModel: (json) { expectedResponseModel: (json) {
final scenesJson = json['data'] as List;
List<ScenesModel> scenes = []; List<ScenesModel> scenes = [];
for (var scene in json) { for (var scene in scenesJson) {
scenes.add(ScenesModel.fromJson(scene)); scenes.add(ScenesModel.fromJson(scene));
} }
return scenes; return scenes;
@ -88,6 +95,25 @@ class SceneApi {
} }
} }
// static Future<List<ScenesModel>> getScenesByUnitId(String unitId) async {
// try {
// final response = await _httpService.get(
// path: ApiEndpoints.getSpaceScenes.replaceAll('{unitUuid}', unitId),
// showServerMessage: false,
// expectedResponseModel: (json) {
// List<ScenesModel> scenes = [];
// for (var scene in json) {
// scenes.add(ScenesModel.fromJson(scene));
// }
// return scenes;
// },
// );
// return response;
// } catch (e) {
// rethrow;
// }
// }
//getAutomation //getAutomation
static Future<List<ScenesModel>> getAutomationByUnitId(String unitId) async { static Future<List<ScenesModel>> getAutomationByUnitId(String unitId) async {

View File

@ -55,4 +55,6 @@ abstract class ApiEndpoints {
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 =
'/communities/{communityUuid}/spaces/{spaceUuid}/scenes';
} }