mirror of
https://github.com/SyncrowIOT/syncrow-app.git
synced 2026-03-11 02:31:44 +00:00
Compare commits
29 Commits
password_c
...
feat/refac
| Author | SHA1 | Date | |
|---|---|---|---|
| 391d6349cc | |||
| 9c873fb0c5 | |||
| e9615cd351 | |||
| 52f6be3db0 | |||
| 34536e6584 | |||
| 7d51ca1f12 | |||
| ff31c54e7b | |||
| 944de7b373 | |||
| ab4f8c593d | |||
| 977fd12721 | |||
| e4a3d4c50b | |||
| 29f82945a6 | |||
| 87a4a88417 | |||
| dcccc4db3a | |||
| 36e5df38ee | |||
| 7571e35a70 | |||
| 995fd8d0a6 | |||
| b7b48006af | |||
| ea202812cd | |||
| 79f224f481 | |||
| 80d2651370 | |||
| 7071f50d49 | |||
| 13a4bf25b3 | |||
| f6a12f2e92 | |||
| 5c65bac076 | |||
| 489789da0a | |||
| d025da6daf | |||
| 5a7ed3ec7c | |||
| 1558996891 |
@ -1,7 +1,7 @@
|
||||
import UIKit
|
||||
import Flutter
|
||||
|
||||
@UIApplicationMain
|
||||
@main
|
||||
@objc class AppDelegate: FlutterAppDelegate {
|
||||
override func application(
|
||||
_ application: UIApplication,
|
||||
|
||||
@ -11,7 +11,7 @@ import 'package:syncrow_app/features/app_layout/view/widgets/app_bar_home_dropdo
|
||||
import 'package:syncrow_app/features/auth/model/user_model.dart';
|
||||
import 'package:syncrow_app/features/dashboard/view/dashboard_view.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
|
||||
import 'package:syncrow_app/features/devices/model/room_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/subspace_model.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/devices_view_body.dart';
|
||||
import 'package:syncrow_app/features/menu/view/menu_view.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart';
|
||||
@ -55,7 +55,8 @@ class HomeCubit extends Cubit<HomeState> {
|
||||
|
||||
Future fetchUserInfo() async {
|
||||
try {
|
||||
var uuid = await const FlutterSecureStorage().read(key: UserModel.userUuidKey);
|
||||
var uuid =
|
||||
await const FlutterSecureStorage().read(key: UserModel.userUuidKey);
|
||||
user = await ProfileApi().fetchUserInfo(uuid);
|
||||
emit(HomeUserInfoLoaded(user!)); // Emit state after fetching user info
|
||||
} catch (e) {
|
||||
@ -76,9 +77,12 @@ class HomeCubit extends Cubit<HomeState> {
|
||||
selectedSpace = null;
|
||||
selectedRoom = null;
|
||||
pageIndex = 0;
|
||||
OneSignal.User.pushSubscription.removeObserver((stateChanges) => oneSignalSubscriptionObserver);
|
||||
OneSignal.Notifications.removePermissionObserver((permission) => oneSignalPermissionObserver);
|
||||
OneSignal.Notifications.removeClickListener((event) => oneSignalClickListenerObserver);
|
||||
OneSignal.User.pushSubscription
|
||||
.removeObserver((stateChanges) => oneSignalSubscriptionObserver);
|
||||
OneSignal.Notifications.removePermissionObserver(
|
||||
(permission) => oneSignalPermissionObserver);
|
||||
OneSignal.Notifications.removeClickListener(
|
||||
(event) => oneSignalClickListenerObserver);
|
||||
return super.close();
|
||||
}
|
||||
|
||||
@ -88,7 +92,7 @@ class HomeCubit extends Cubit<HomeState> {
|
||||
|
||||
SpaceModel? selectedSpace;
|
||||
|
||||
RoomModel? selectedRoom;
|
||||
SubSpaceModel? selectedRoom;
|
||||
|
||||
PageController devicesPageController = PageController();
|
||||
|
||||
@ -120,7 +124,9 @@ class HomeCubit extends Cubit<HomeState> {
|
||||
return;
|
||||
}
|
||||
|
||||
var userUuid = await const FlutterSecureStorage().read(key: UserModel.userUuidKey) ?? '';
|
||||
var userUuid =
|
||||
await const FlutterSecureStorage().read(key: UserModel.userUuidKey) ??
|
||||
'';
|
||||
if (userUuid.isNotEmpty) {
|
||||
await OneSignal.login(userUuid);
|
||||
}
|
||||
@ -128,21 +134,24 @@ class HomeCubit extends Cubit<HomeState> {
|
||||
await OneSignal.User.pushSubscription.optIn();
|
||||
|
||||
//this function will be called once a user is subscribed
|
||||
oneSignalSubscriptionObserver = OneSignal.User.pushSubscription.addObserver((state) async {
|
||||
oneSignalSubscriptionObserver =
|
||||
OneSignal.User.pushSubscription.addObserver((state) async {
|
||||
if (state.current.optedIn) {
|
||||
await _sendSubscriptionId();
|
||||
}
|
||||
});
|
||||
|
||||
// Send the player id when a user allows notifications
|
||||
oneSignalPermissionObserver = OneSignal.Notifications.addPermissionObserver((state) async {
|
||||
oneSignalPermissionObserver =
|
||||
OneSignal.Notifications.addPermissionObserver((state) async {
|
||||
await _sendSubscriptionId();
|
||||
});
|
||||
|
||||
//check if the player id is sent, if not send it again
|
||||
await _sendSubscriptionId();
|
||||
|
||||
oneSignalClickListenerObserver = OneSignal.Notifications.addClickListener((event) async {
|
||||
oneSignalClickListenerObserver =
|
||||
OneSignal.Notifications.addClickListener((event) async {
|
||||
//Once the user clicks on the notification
|
||||
});
|
||||
} catch (err) {
|
||||
@ -173,7 +182,7 @@ class HomeCubit extends Cubit<HomeState> {
|
||||
if (index == 0) {
|
||||
unselectRoom();
|
||||
} else {
|
||||
selectedRoom = selectedSpace!.rooms![index - 1];
|
||||
selectedRoom = selectedSpace!.subspaces[index - 1];
|
||||
emitSafe(RoomSelected(selectedRoom!));
|
||||
}
|
||||
}
|
||||
@ -188,7 +197,7 @@ class HomeCubit extends Cubit<HomeState> {
|
||||
if (index <= 0) {
|
||||
unselectRoom();
|
||||
} else {
|
||||
selectedRoom = selectedSpace!.rooms![index - 1];
|
||||
selectedRoom = selectedSpace!.subspaces[index - 1];
|
||||
emitSafe(RoomSelected(selectedRoom!));
|
||||
}
|
||||
}
|
||||
@ -211,9 +220,10 @@ class HomeCubit extends Cubit<HomeState> {
|
||||
}
|
||||
|
||||
//////////////////////////////////////// API ////////////////////////////////////////
|
||||
generateInvitation(String unitId) async {
|
||||
generateInvitation(SpaceModel unit) async {
|
||||
try {
|
||||
final invitationCode = await SpacesAPI.generateInvitationCode(unitId);
|
||||
final invitationCode =
|
||||
await SpacesAPI.generateInvitationCode(unit.id, unit.community.uuid);
|
||||
if (invitationCode.isNotEmpty) {
|
||||
Share.share('The invitation code is $invitationCode');
|
||||
CustomSnackBar.displaySnackBar(
|
||||
@ -229,10 +239,12 @@ class HomeCubit extends Cubit<HomeState> {
|
||||
|
||||
Future<bool> joinAUnit(String code) async {
|
||||
try {
|
||||
var uuid = await const FlutterSecureStorage().read(key: UserModel.userUuidKey) ?? '';
|
||||
Map<String, String> body = {'userUuid': uuid, 'inviteCode': code};
|
||||
var userUuid =
|
||||
await const FlutterSecureStorage().read(key: UserModel.userUuidKey) ??
|
||||
'';
|
||||
Map<String, String> body = {'inviteCode': code};
|
||||
|
||||
final success = await SpacesAPI.joinUnit(body);
|
||||
final success = await SpacesAPI.joinUnit(userUuid, body);
|
||||
if (success) {
|
||||
await fetchUnitsByUserId();
|
||||
CustomSnackBar.displaySnackBar('Done successfully');
|
||||
@ -247,7 +259,7 @@ class HomeCubit extends Cubit<HomeState> {
|
||||
fetchUnitsByUserId() async {
|
||||
emitSafe(GetSpacesLoading());
|
||||
try {
|
||||
spaces = await SpacesAPI.getUnitsByUserId();
|
||||
spaces = await SpacesAPI.getSpacesByUserId();
|
||||
} catch (failure) {
|
||||
emitSafe(GetSpacesError("No units found"));
|
||||
return;
|
||||
@ -265,13 +277,14 @@ class HomeCubit extends Cubit<HomeState> {
|
||||
fetchRoomsByUnitId(SpaceModel space) async {
|
||||
emitSafe(GetSpaceRoomsLoading());
|
||||
try {
|
||||
space.rooms = await SpacesAPI.getRoomsBySpaceId(space.id!);
|
||||
space.subspaces =
|
||||
await SpacesAPI.getSubSpaceBySpaceId(space.community.uuid, space.id);
|
||||
} catch (failure) {
|
||||
emitSafe(GetSpaceRoomsError(failure.toString()));
|
||||
return;
|
||||
}
|
||||
if (space.rooms != null && space.rooms!.isNotEmpty) {
|
||||
emitSafe(GetSpaceRoomsSuccess(space.rooms!));
|
||||
if (space.subspaces != null && space.subspaces!.isNotEmpty) {
|
||||
emitSafe(GetSpaceRoomsSuccess(space.subspaces!));
|
||||
} else {
|
||||
emitSafe(GetSpaceRoomsError("No rooms found"));
|
||||
}
|
||||
@ -347,7 +360,8 @@ class HomeCubit extends Cubit<HomeState> {
|
||||
size: 32,
|
||||
),
|
||||
style: ButtonStyle(
|
||||
foregroundColor: WidgetStateProperty.all(ColorsManager.textPrimaryColor),
|
||||
foregroundColor:
|
||||
WidgetStateProperty.all(ColorsManager.textPrimaryColor),
|
||||
),
|
||||
onPressed: () {
|
||||
Navigator.pushNamed(
|
||||
@ -368,7 +382,8 @@ class HomeCubit extends Cubit<HomeState> {
|
||||
NavigationService.navigatorKey.currentContext!
|
||||
.read<SmartSceneSelectBloc>()
|
||||
.add(const SmartSceneClearEvent());
|
||||
BlocProvider.of<EffectPeriodBloc>(NavigationService.navigatorKey.currentState!.context)
|
||||
BlocProvider.of<EffectPeriodBloc>(
|
||||
NavigationService.navigatorKey.currentState!.context)
|
||||
.add(ResetEffectivePeriod());
|
||||
NavigationService.navigatorKey.currentContext!
|
||||
.read<CreateSceneBloc>()
|
||||
@ -381,7 +396,8 @@ class HomeCubit extends Cubit<HomeState> {
|
||||
size: 28,
|
||||
),
|
||||
style: ButtonStyle(
|
||||
foregroundColor: WidgetStateProperty.all(ColorsManager.textPrimaryColor),
|
||||
foregroundColor:
|
||||
WidgetStateProperty.all(ColorsManager.textPrimaryColor),
|
||||
),
|
||||
onPressed: () {},
|
||||
),
|
||||
@ -414,7 +430,8 @@ class HomeCubit extends Cubit<HomeState> {
|
||||
};
|
||||
|
||||
static var bottomNavItems = [
|
||||
defaultBottomNavBarItem(icon: Assets.assetsIconsDashboard, label: 'Dashboard'),
|
||||
defaultBottomNavBarItem(
|
||||
icon: Assets.assetsIconsDashboard, label: 'Dashboard'),
|
||||
// defaultBottomNavBarItem(icon: Assets.assetsIconslayout, label: 'Layout'),
|
||||
defaultBottomNavBarItem(icon: Assets.assetsIconsDevices, label: 'Devices'),
|
||||
defaultBottomNavBarItem(icon: Assets.assetsIconsRoutines, label: 'Routine'),
|
||||
@ -440,7 +457,8 @@ class HomeCubit extends Cubit<HomeState> {
|
||||
|
||||
void updateDevice(String deviceId) async {
|
||||
try {
|
||||
final response = await DevicesAPI.firmwareDevice(deviceId: deviceId, firmwareVersion: '0');
|
||||
final response = await DevicesAPI.firmwareDevice(
|
||||
deviceId: deviceId, firmwareVersion: '0');
|
||||
if (response['success'] ?? false) {
|
||||
CustomSnackBar.displaySnackBar('No updates available');
|
||||
}
|
||||
@ -448,7 +466,8 @@ class HomeCubit extends Cubit<HomeState> {
|
||||
}
|
||||
}
|
||||
|
||||
BottomNavigationBarItem defaultBottomNavBarItem({required String icon, required String label}) {
|
||||
BottomNavigationBarItem defaultBottomNavBarItem(
|
||||
{required String icon, required String label}) {
|
||||
return BottomNavigationBarItem(
|
||||
icon: SvgPicture.asset(icon),
|
||||
activeIcon: SvgPicture.asset(
|
||||
|
||||
@ -33,7 +33,7 @@ class GetSpacesError extends HomeError {
|
||||
class GetSpaceRoomsLoading extends HomeLoading {}
|
||||
|
||||
class GetSpaceRoomsSuccess extends HomeSuccess {
|
||||
final List<RoomModel> rooms;
|
||||
final List<SubSpaceModel> rooms;
|
||||
|
||||
GetSpaceRoomsSuccess(this.rooms);
|
||||
}
|
||||
@ -50,7 +50,7 @@ class SpaceSelected extends HomeState {
|
||||
}
|
||||
|
||||
class RoomSelected extends HomeState {
|
||||
final RoomModel room;
|
||||
final SubSpaceModel room;
|
||||
|
||||
RoomSelected(this.room);
|
||||
}
|
||||
|
||||
27
lib/features/app_layout/model/community_model.dart
Normal file
27
lib/features/app_layout/model/community_model.dart
Normal file
@ -0,0 +1,27 @@
|
||||
class Community {
|
||||
final String uuid;
|
||||
final String name;
|
||||
final String description;
|
||||
|
||||
Community({
|
||||
required this.uuid,
|
||||
required this.name,
|
||||
this.description = '',
|
||||
});
|
||||
|
||||
factory Community.fromJson(Map<String, dynamic> json) {
|
||||
return Community(
|
||||
uuid: json['uuid'] ?? '',
|
||||
name: json['name'] ?? 'Unnamed Community',
|
||||
description: json['description'] ?? '',
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'uuid': uuid,
|
||||
'name': name,
|
||||
'description': description,
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -1,37 +1,53 @@
|
||||
import 'package:syncrow_app/features/devices/model/room_model.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
||||
import 'package:syncrow_app/features/app_layout/model/community_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/subspace_model.dart';
|
||||
|
||||
class SpaceModel {
|
||||
final String? id;
|
||||
final String? name;
|
||||
final SpaceType type;
|
||||
late List<RoomModel>? rooms;
|
||||
final String id;
|
||||
final String name;
|
||||
final Community community;
|
||||
late List<SubSpaceModel> subspaces;
|
||||
|
||||
SpaceModel({
|
||||
required this.type,
|
||||
required this.id,
|
||||
required this.name,
|
||||
required this.rooms,
|
||||
required this.community,
|
||||
this.subspaces = const [], // Default to an empty list
|
||||
});
|
||||
|
||||
/// Converts the instance into JSON format.
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'id': id,
|
||||
'name': name,
|
||||
'rooms': rooms,
|
||||
'spaceName': name,
|
||||
'community': community.toJson(),
|
||||
'subspaces': subspaces.map((room) => room.toJson()).toList(),
|
||||
};
|
||||
}
|
||||
|
||||
/// Factory constructor to create an instance from JSON.
|
||||
factory SpaceModel.fromJson(Map<String, dynamic> json) {
|
||||
// Extract and log each part of space data
|
||||
final id = json['uuid'] ?? '';
|
||||
final name = json['spaceName'] ?? 'Unnamed Space';
|
||||
final communityJson = json['community'] ?? {};
|
||||
|
||||
return SpaceModel(
|
||||
id: json['uuid'],
|
||||
name: json['name'],
|
||||
type: spaceTypesMap[json['type']]!,
|
||||
rooms: [],
|
||||
id: id,
|
||||
name: name,
|
||||
community: Community.fromJson(
|
||||
communityJson), // Ensure Community is created correctly
|
||||
subspaces: (json['subspaces'] as List<dynamic>?)
|
||||
?.map((item) => SubSpaceModel.fromJson(item))
|
||||
.toList() ??
|
||||
[],
|
||||
);
|
||||
}
|
||||
|
||||
/// Helper method to parse a list of SpaceModel from JSON.
|
||||
static List<SpaceModel> fromJsonList(List<dynamic> jsonList) {
|
||||
return jsonList.map((item) => SpaceModel.fromJson(item)).toList();
|
||||
return jsonList.map((item) {
|
||||
final spaceData = item['space']; // Extract the `space` object
|
||||
return SpaceModel.fromJson(spaceData); // Pass to SpaceModel.fromJson
|
||||
}).toList();
|
||||
}
|
||||
}
|
||||
|
||||
@ -284,11 +284,13 @@ class AuthCubit extends Cubit<AuthState> {
|
||||
await login();
|
||||
}
|
||||
emit(AuthOtpSuccess());
|
||||
} else {
|
||||
emit(AuthLoginError(message: 'Something went wrong'));
|
||||
}
|
||||
// else {
|
||||
// emit(AuthLoginError(message: 'Something went wrong'));
|
||||
// }
|
||||
} catch (failure) {
|
||||
emit(AuthLoginError(message: 'Something went wrong'));
|
||||
emit(AuthErrorStatusWithoutMsg());
|
||||
//emit(AuthLoginError(message: 'Something went wrong'));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,12 +25,14 @@ class DeviceManagerBloc extends Bloc<DeviceManagerEvent, DeviceManagerState> {
|
||||
|
||||
static List<DevicesCategoryModel>? allCategories;
|
||||
|
||||
Future<void> _onFetchAllDevices(FetchAllDevices event, Emitter<DeviceManagerState> emit) async {
|
||||
Future<void> _onFetchAllDevices(
|
||||
FetchAllDevices event, Emitter<DeviceManagerState> emit) async {
|
||||
emit(state.copyWith(loading: true));
|
||||
try {
|
||||
final allDevices = await HomeManagementAPI.fetchDevicesByUnitId();
|
||||
emit(state.copyWith(devices: allDevices, loading: false));
|
||||
} catch (e) {
|
||||
print(e);
|
||||
emit(state.copyWith(error: e.toString(), loading: false));
|
||||
}
|
||||
}
|
||||
@ -39,21 +41,27 @@ class DeviceManagerBloc extends Bloc<DeviceManagerEvent, DeviceManagerState> {
|
||||
FetchDevicesByRoomId event, Emitter<DeviceManagerState> emit) async {
|
||||
emit(state.copyWith(loading: true));
|
||||
try {
|
||||
final devices = await DevicesAPI.getDevicesByRoomId(event.roomId);
|
||||
final devices = await DevicesAPI.getDevicesByRoomId(
|
||||
communityUuid: event.unit.community.uuid,
|
||||
spaceUuid: event.unit.id,
|
||||
roomId: event.roomId,
|
||||
);
|
||||
emit(state.copyWith(devices: devices, loading: false));
|
||||
} catch (e) {
|
||||
emit(state.copyWith(error: e.toString(), loading: false));
|
||||
}
|
||||
}
|
||||
|
||||
void _onSelectCategory(SelectCategory event, Emitter<DeviceManagerState> emit) {
|
||||
void _onSelectCategory(
|
||||
SelectCategory event, Emitter<DeviceManagerState> emit) {
|
||||
for (var i = 0; i < allCategories!.length; i++) {
|
||||
allCategories![i].isSelected = i == event.index;
|
||||
}
|
||||
emit(state.copyWith(categoryChanged: true));
|
||||
}
|
||||
|
||||
void _onUnselectAllCategories(UnselectAllCategories event, Emitter<DeviceManagerState> emit) {
|
||||
void _onUnselectAllCategories(
|
||||
UnselectAllCategories event, Emitter<DeviceManagerState> emit) {
|
||||
for (var category in allCategories!) {
|
||||
category.isSelected = false;
|
||||
}
|
||||
@ -97,7 +105,8 @@ class DeviceManagerBloc extends Bloc<DeviceManagerEvent, DeviceManagerState> {
|
||||
_updateDevicesStatus(category, emit);
|
||||
}
|
||||
|
||||
void _onTurnOnOffDevice(TurnOnOffDevice event, Emitter<DeviceManagerState> emit) {
|
||||
void _onTurnOnOffDevice(
|
||||
TurnOnOffDevice event, Emitter<DeviceManagerState> emit) {
|
||||
var device = event.device;
|
||||
device.isOnline = !device.isOnline!;
|
||||
DevicesCategoryModel category = allCategories!.firstWhere((category) {
|
||||
@ -120,7 +129,8 @@ class DeviceManagerBloc extends Bloc<DeviceManagerEvent, DeviceManagerState> {
|
||||
emit(state.copyWith(categoryChanged: true)); // Set category changed state
|
||||
}
|
||||
|
||||
void _updateDevicesStatus(DevicesCategoryModel category, Emitter<DeviceManagerState> emit) {
|
||||
void _updateDevicesStatus(
|
||||
DevicesCategoryModel category, Emitter<DeviceManagerState> emit) {
|
||||
if (category.devices != null && category.devices!.isNotEmpty) {
|
||||
bool? tempStatus = category.devices![0].isOnline;
|
||||
for (var device in category.devices!) {
|
||||
@ -140,7 +150,8 @@ class DeviceManagerBloc extends Bloc<DeviceManagerEvent, DeviceManagerState> {
|
||||
try {
|
||||
final deviceFunctions = await DevicesAPI.deviceFunctions(event.deviceId);
|
||||
|
||||
emit(state.copyWith(functionsLoading: false, deviceFunctions: deviceFunctions));
|
||||
emit(state.copyWith(
|
||||
functionsLoading: false, deviceFunctions: deviceFunctions));
|
||||
} catch (e) {
|
||||
emit(state.copyWith(functionsLoading: false, error: e.toString()));
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:syncrow_app/features/app_layout/model/space_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_category_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_control_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||
@ -15,8 +16,9 @@ class FetchAllDevices extends DeviceManagerEvent {}
|
||||
|
||||
class FetchDevicesByRoomId extends DeviceManagerEvent {
|
||||
final String roomId;
|
||||
final SpaceModel unit;
|
||||
|
||||
const FetchDevicesByRoomId(this.roomId);
|
||||
const FetchDevicesByRoomId(this.roomId, this.unit);
|
||||
|
||||
@override
|
||||
List<Object> get props => [roomId];
|
||||
|
||||
@ -23,14 +23,22 @@ import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
||||
part 'devices_state.dart';
|
||||
|
||||
class DevicesCubit extends Cubit<DevicesState> {
|
||||
Future<void> _initializeDevices(SpaceModel selectedSpace) async {
|
||||
// Fetch devices for each room in the selected space
|
||||
for (var room in selectedSpace.subspaces ?? []) {
|
||||
await fetchDevicesByRoomId(selectedSpace, room.id!);
|
||||
}
|
||||
|
||||
// Fetch groups based on the selected space ID
|
||||
await fetchGroups(selectedSpace.id ?? '');
|
||||
}
|
||||
|
||||
DevicesCubit._() : super(DevicesInitial()) {
|
||||
if (HomeCubit.getInstance().selectedSpace != null &&
|
||||
HomeCubit.getInstance().spaces!.isNotEmpty) {
|
||||
// fetchGroups(HomeCubit.getInstance().selectedSpace!.id!);
|
||||
for (var room in HomeCubit.getInstance().selectedSpace!.rooms!) {
|
||||
fetchDevicesByRoomId(room.id!);
|
||||
}
|
||||
fetchGroups(HomeCubit.getInstance().selectedSpace?.id ?? '');
|
||||
final selectedSpace = HomeCubit.getInstance().selectedSpace;
|
||||
final spaces = HomeCubit.getInstance().spaces;
|
||||
|
||||
if (selectedSpace != null && spaces != null && spaces.isNotEmpty) {
|
||||
_initializeDevices(selectedSpace);
|
||||
}
|
||||
}
|
||||
|
||||
@ -87,10 +95,10 @@ class DevicesCubit extends Cubit<DevicesState> {
|
||||
return const DoorsListView();
|
||||
case DeviceType.Curtain:
|
||||
return const CurtainListView();
|
||||
// case DeviceType.ThreeGang:
|
||||
// return const ThreeGangSwitchesView();
|
||||
// case DeviceType.Gateway:
|
||||
// return const GateWayView();
|
||||
// case DeviceType.ThreeGang:
|
||||
// return const ThreeGangSwitchesView();
|
||||
// case DeviceType.Gateway:
|
||||
// return const GateWayView();
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
@ -104,8 +112,8 @@ class DevicesCubit extends Cubit<DevicesState> {
|
||||
List<DeviceModel> get allDevices {
|
||||
List<DeviceModel> devices = [];
|
||||
if (HomeCubit.getInstance().selectedSpace != null &&
|
||||
HomeCubit.getInstance().selectedSpace!.rooms != null) {
|
||||
for (var room in HomeCubit.getInstance().selectedSpace!.rooms!) {
|
||||
HomeCubit.getInstance().selectedSpace!.subspaces != null) {
|
||||
for (var room in HomeCubit.getInstance().selectedSpace!.subspaces!) {
|
||||
if (room.devices != null) {
|
||||
devices.addAll(room.devices!);
|
||||
}
|
||||
@ -275,7 +283,7 @@ class DevicesCubit extends Cubit<DevicesState> {
|
||||
deviceId,
|
||||
HomeCubit.getInstance()
|
||||
.selectedSpace!
|
||||
.rooms!
|
||||
.subspaces!
|
||||
.indexOf(HomeCubit.getInstance().selectedRoom!),
|
||||
code: control.code);
|
||||
});
|
||||
@ -303,20 +311,26 @@ class DevicesCubit extends Cubit<DevicesState> {
|
||||
}
|
||||
}
|
||||
|
||||
fetchDevicesByRoomId(String? roomId) async {
|
||||
fetchDevicesByRoomId(SpaceModel? unit, String? roomId) async {
|
||||
if (roomId == null) return;
|
||||
|
||||
emitSafe(GetDevicesLoading());
|
||||
int roomIndex =
|
||||
HomeCubit.getInstance().selectedSpace!.rooms!.indexWhere((element) => element.id == roomId);
|
||||
int roomIndex = HomeCubit.getInstance()
|
||||
.selectedSpace!
|
||||
.subspaces!
|
||||
.indexWhere((element) => element.id == roomId);
|
||||
try {
|
||||
HomeCubit.getInstance().selectedSpace!.rooms![roomIndex].devices =
|
||||
await DevicesAPI.getDevicesByRoomId(roomId);
|
||||
HomeCubit.getInstance().selectedSpace!.subspaces![roomIndex].devices =
|
||||
await DevicesAPI.getDevicesByRoomId(
|
||||
communityUuid: unit!.community.uuid,
|
||||
spaceUuid: unit.id,
|
||||
roomId: roomId);
|
||||
} catch (e) {
|
||||
emitSafe(GetDevicesError(e.toString()));
|
||||
return;
|
||||
}
|
||||
final devices = HomeCubit.getInstance().selectedSpace!.rooms![roomIndex].devices;
|
||||
final devices =
|
||||
HomeCubit.getInstance().selectedSpace!.subspaces![roomIndex].devices;
|
||||
emitSafe(GetDevicesSuccess(devices));
|
||||
|
||||
//get status for each device
|
||||
@ -333,7 +347,7 @@ class DevicesCubit extends Cubit<DevicesState> {
|
||||
emitSafe(GetDeviceStatusLoading(code: code));
|
||||
int deviceIndex = HomeCubit.getInstance()
|
||||
.selectedSpace!
|
||||
.rooms![roomIndex]
|
||||
.subspaces![roomIndex]
|
||||
.devices!
|
||||
.indexWhere((element) => element.uuid == deviceUuid);
|
||||
List<StatusModel> statuses = [];
|
||||
@ -346,8 +360,11 @@ class DevicesCubit extends Cubit<DevicesState> {
|
||||
emitSafe(GetDeviceStatusError(e.toString()));
|
||||
return;
|
||||
}
|
||||
HomeCubit.getInstance().selectedSpace!.rooms![roomIndex].devices![deviceIndex].status =
|
||||
statuses;
|
||||
HomeCubit.getInstance()
|
||||
.selectedSpace!
|
||||
.subspaces![roomIndex]
|
||||
.devices![deviceIndex]
|
||||
.status = statuses;
|
||||
emitSafe(GetDeviceStatusSuccess(code: code));
|
||||
}
|
||||
|
||||
@ -396,8 +413,6 @@ class DevicesCubit extends Cubit<DevicesState> {
|
||||
// emitSafe(LightBrightnessChanged(value));
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
}
|
||||
|
||||
enum LightMode {
|
||||
|
||||
35
lib/features/devices/model/subspace_model.dart
Normal file
35
lib/features/devices/model/subspace_model.dart
Normal file
@ -0,0 +1,35 @@
|
||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||
|
||||
class SubSpaceModel {
|
||||
final String? id;
|
||||
final String? name;
|
||||
List<DeviceModel>? devices;
|
||||
|
||||
SubSpaceModel({
|
||||
required this.id,
|
||||
required this.name,
|
||||
required this.devices,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'id': id,
|
||||
'name': name,
|
||||
'devices': devices?.map((device) => device.toJson()).toList(),
|
||||
};
|
||||
}
|
||||
|
||||
factory SubSpaceModel.fromJson(Map<String, dynamic> json) {
|
||||
List<DeviceModel> devices = [];
|
||||
if (json['devices'] != null) {
|
||||
for (var device in json['devices']) {
|
||||
devices.add(DeviceModel.fromJson(device));
|
||||
}
|
||||
}
|
||||
return SubSpaceModel(
|
||||
id: json['uuid'],
|
||||
name: json['subspaceName'],
|
||||
devices: devices,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -22,6 +22,8 @@ class ACsView extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
print("ACsView deviceModel UUID: ${deviceModel?.uuid}");
|
||||
|
||||
return BlocProvider(
|
||||
create: (context) => ACsBloc(acId: deviceModel?.uuid ?? '')
|
||||
..add(AcsInitial(allAcs: deviceModel != null ? false : true)),
|
||||
@ -66,12 +68,14 @@ class ACsView extends StatelessWidget {
|
||||
child: state is AcsLoadingState
|
||||
? const Center(
|
||||
child: DefaultContainer(
|
||||
width: 50, height: 50, child: CircularProgressIndicator()),
|
||||
width: 50,
|
||||
height: 50,
|
||||
child: CircularProgressIndicator()),
|
||||
)
|
||||
: RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
BlocProvider.of<ACsBloc>(context)
|
||||
.add(AcsInitial(allAcs: deviceModel != null ? false : true));
|
||||
BlocProvider.of<ACsBloc>(context).add(AcsInitial(
|
||||
allAcs: deviceModel != null ? false : true));
|
||||
},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.only(top: 40),
|
||||
|
||||
@ -69,6 +69,7 @@ class DevicesViewBody extends StatelessWidget {
|
||||
|
||||
Expanded(
|
||||
child: PageView(
|
||||
|
||||
controller: HomeCubit.getInstance().devicesPageController,
|
||||
onPageChanged: (index) {
|
||||
HomeCubit.getInstance().devicesPageChanged(index);
|
||||
@ -78,8 +79,8 @@ class DevicesViewBody extends StatelessWidget {
|
||||
groupsList: DevicesCubit.getInstance().allCategories ?? [],
|
||||
),
|
||||
if (HomeCubit.getInstance().selectedSpace != null)
|
||||
if (HomeCubit.getInstance().selectedSpace!.rooms != null)
|
||||
...HomeCubit.getInstance().selectedSpace!.rooms!.map((room) {
|
||||
if (HomeCubit.getInstance().selectedSpace!.subspaces != null)
|
||||
...HomeCubit.getInstance().selectedSpace!.subspaces!.map((room) {
|
||||
return RoomPage(
|
||||
room: room,
|
||||
);
|
||||
@ -95,7 +96,7 @@ class DevicesViewBody extends StatelessWidget {
|
||||
),
|
||||
child: SmoothPageIndicator(
|
||||
controller: HomeCubit.getInstance().devicesPageController,
|
||||
count: HomeCubit.getInstance().selectedSpace!.rooms!.length + 1,
|
||||
count: HomeCubit.getInstance().selectedSpace!.subspaces!.length + 1,
|
||||
effect: const WormEffect(
|
||||
paintStyle: PaintingStyle.stroke,
|
||||
dotHeight: 8,
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:syncrow_app/features/devices/model/subspace_model.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:syncrow_app/features/devices/model/room_model.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/room_page_switch.dart';
|
||||
@ -8,7 +9,7 @@ import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
class RoomPage extends StatefulWidget {
|
||||
const RoomPage({super.key, required this.room});
|
||||
|
||||
final RoomModel room;
|
||||
final SubSpaceModel room;
|
||||
|
||||
@override
|
||||
_RoomPageState createState() => _RoomPageState();
|
||||
|
||||
@ -87,6 +87,7 @@ class RoomPageSwitch extends StatelessWidget {
|
||||
///
|
||||
/// The [device] parameter represents the device model.
|
||||
void showDeviceInterface(DeviceModel device, BuildContext context) {
|
||||
|
||||
switch (device.productType) {
|
||||
case DeviceType.AC:
|
||||
Navigator.push(
|
||||
|
||||
@ -39,14 +39,14 @@ class RoomsSlider extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
if (HomeCubit.getInstance().selectedSpace != null)
|
||||
if (HomeCubit.getInstance().selectedSpace!.rooms != null)
|
||||
...HomeCubit.getInstance().selectedSpace!.rooms!.map(
|
||||
if (HomeCubit.getInstance().selectedSpace!.subspaces != null)
|
||||
...HomeCubit.getInstance().selectedSpace!.subspaces!.map(
|
||||
(room) => InkWell(
|
||||
onTap: () {
|
||||
HomeCubit.getInstance().roomSliderPageChanged(
|
||||
HomeCubit.getInstance()
|
||||
.selectedSpace!
|
||||
.rooms!
|
||||
.subspaces!
|
||||
.indexOf(room));
|
||||
},
|
||||
child: TitleMedium(
|
||||
|
||||
@ -40,10 +40,13 @@ class SceneListview extends StatelessWidget {
|
||||
sceneName: scene.name,
|
||||
),
|
||||
);
|
||||
context.read<SmartSceneSelectBloc>().add(const SmartSceneClearEvent());
|
||||
context
|
||||
.read<SmartSceneSelectBloc>()
|
||||
.add(const SmartSceneClearEvent());
|
||||
|
||||
BlocProvider.of<CreateSceneBloc>(context)
|
||||
.add(FetchSceneTasksEvent(sceneId: scene.id, isAutomation: false));
|
||||
BlocProvider.of<CreateSceneBloc>(context).add(
|
||||
FetchSceneTasksEvent(
|
||||
sceneId: scene.id, isAutomation: false));
|
||||
|
||||
/// the state to set the scene type must be after the fetch
|
||||
BlocProvider.of<CreateSceneBloc>(context)
|
||||
@ -56,14 +59,27 @@ class SceneListview extends StatelessWidget {
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Image.memory(
|
||||
height: 32,
|
||||
width: 32,
|
||||
scene.iconInBytes,
|
||||
fit: BoxFit.fill,
|
||||
errorBuilder: (context, error, stackTrace) => Image.asset(
|
||||
height: 32, width: 32, fit: BoxFit.fill, Assets.assetsIconsLogo),
|
||||
),
|
||||
child: scene.iconInBytes != null &&
|
||||
scene.iconInBytes.isNotEmpty
|
||||
? Image.memory(
|
||||
scene.iconInBytes,
|
||||
height: 32,
|
||||
width: 32,
|
||||
fit: BoxFit.fill,
|
||||
errorBuilder: (context, error, stackTrace) =>
|
||||
Image.asset(
|
||||
Assets.assetsIconsLogo,
|
||||
height: 32,
|
||||
width: 32,
|
||||
fit: BoxFit.fill,
|
||||
),
|
||||
)
|
||||
: Image.asset(
|
||||
Assets.assetsIconsLogo,
|
||||
height: 32,
|
||||
width: 32,
|
||||
fit: BoxFit.fill,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: BodyMedium(
|
||||
|
||||
@ -61,7 +61,9 @@ class CreateUnitBloc extends Bloc<CreateUnitEvent, CreateUnitState> {
|
||||
var storage = const FlutterSecureStorage();
|
||||
var userId = await storage.read(key: UserModel.userUuidKey) ?? '';
|
||||
|
||||
Map<String, String> communityBody = {'communityName': event.communityName};
|
||||
Map<String, String> communityBody = {
|
||||
'communityName': event.communityName
|
||||
};
|
||||
final response = await HomeCreation.createCommunity(communityBody);
|
||||
if (response['data']['uuid'] != '') {
|
||||
// final result =
|
||||
@ -75,15 +77,22 @@ class CreateUnitBloc extends Bloc<CreateUnitEvent, CreateUnitState> {
|
||||
|
||||
if (buildingId.isNotEmpty) {
|
||||
final floorId = await _createFloor(
|
||||
floorName: event.floorName, buildingId: buildingId, userId: userId);
|
||||
floorName: event.floorName,
|
||||
buildingId: buildingId,
|
||||
userId: userId);
|
||||
|
||||
if (floorId.isNotEmpty) {
|
||||
final unitId =
|
||||
await _createUnit(unitName: event.unitName, floorId: floorId, userId: userId);
|
||||
final unitId = await _createUnit(
|
||||
unitName: event.unitName, floorId: floorId, userId: userId);
|
||||
|
||||
if (unitId.isNotEmpty && rooms.isNotEmpty) {
|
||||
rooms.forEach((room) async {
|
||||
await _createNewRoom(roomName: room, unitId: unitId, userId: userId);
|
||||
await _createNewRoom(
|
||||
roomName: room,
|
||||
unitId: unitId,
|
||||
userId: userId,
|
||||
communityId: response['data']['uuid'],
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -99,7 +108,8 @@ class CreateUnitBloc extends Bloc<CreateUnitEvent, CreateUnitState> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> _assignToCommunity({required String communityId, required String userId}) async {
|
||||
Future<bool> _assignToCommunity(
|
||||
{required String communityId, required String userId}) async {
|
||||
try {
|
||||
Map<String, String> body = {
|
||||
'communityUuid': communityId,
|
||||
@ -114,9 +124,14 @@ Future<bool> _assignToCommunity({required String communityId, required String us
|
||||
}
|
||||
|
||||
Future<String> _createBuilding(
|
||||
{required String buildingName, required String communityId, required String userId}) async {
|
||||
{required String buildingName,
|
||||
required String communityId,
|
||||
required String userId}) async {
|
||||
try {
|
||||
Map<String, String> body = {'buildingName': buildingName, 'communityUuid': communityId};
|
||||
Map<String, String> body = {
|
||||
'buildingName': buildingName,
|
||||
'communityUuid': communityId
|
||||
};
|
||||
final response = await HomeCreation.createBuilding(body);
|
||||
// if (response['data']['uuid'] != '') {
|
||||
// final result = await _assignToBuilding(buildingId: response['data']['uuid'], userId: userId);
|
||||
@ -130,7 +145,8 @@ Future<String> _createBuilding(
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> _assignToBuilding({required String buildingId, required String userId}) async {
|
||||
Future<bool> _assignToBuilding(
|
||||
{required String buildingId, required String userId}) async {
|
||||
try {
|
||||
Map<String, String> body = {
|
||||
'buildingUuid': buildingId,
|
||||
@ -145,9 +161,14 @@ Future<bool> _assignToBuilding({required String buildingId, required String user
|
||||
}
|
||||
|
||||
Future<String> _createFloor(
|
||||
{required String floorName, required String buildingId, required String userId}) async {
|
||||
{required String floorName,
|
||||
required String buildingId,
|
||||
required String userId}) async {
|
||||
try {
|
||||
Map<String, String> body = {'floorName': floorName, 'buildingUuid': buildingId};
|
||||
Map<String, String> body = {
|
||||
'floorName': floorName,
|
||||
'buildingUuid': buildingId
|
||||
};
|
||||
final response = await HomeCreation.createFloor(body);
|
||||
// if (response['data']['uuid'] != '') {
|
||||
// final result = await _assignToFloor(buildingId: response['data']['uuid'], userId: userId);
|
||||
@ -161,7 +182,8 @@ Future<String> _createFloor(
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> _assignToFloor({required String buildingId, required String userId}) async {
|
||||
Future<bool> _assignToFloor(
|
||||
{required String buildingId, required String userId}) async {
|
||||
try {
|
||||
Map<String, String> body = {
|
||||
'floorUuid': buildingId,
|
||||
@ -176,12 +198,15 @@ Future<bool> _assignToFloor({required String buildingId, required String userId}
|
||||
}
|
||||
|
||||
Future<String> _createUnit(
|
||||
{required String unitName, required String floorId, required String userId}) async {
|
||||
{required String unitName,
|
||||
required String floorId,
|
||||
required String userId}) async {
|
||||
try {
|
||||
Map<String, String> body = {'unitName': unitName, 'floorUuid': floorId};
|
||||
final response = await HomeCreation.createUnit(body);
|
||||
if (response['data']['uuid'] != '') {
|
||||
final result = await _assignToUnit(unitId: response['data']['uuid'], userId: userId);
|
||||
final result =
|
||||
await _assignToUnit(unitId: response['data']['uuid'], userId: userId);
|
||||
|
||||
return result ? response['data']['uuid'] : '';
|
||||
} else {
|
||||
@ -192,7 +217,8 @@ Future<String> _createUnit(
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> _assignToUnit({required String unitId, required String userId}) async {
|
||||
Future<bool> _assignToUnit(
|
||||
{required String unitId, required String userId}) async {
|
||||
try {
|
||||
Map<String, String> body = {
|
||||
'unitUuid': unitId,
|
||||
@ -207,10 +233,14 @@ Future<bool> _assignToUnit({required String unitId, required String userId}) asy
|
||||
}
|
||||
|
||||
Future<String> _createNewRoom(
|
||||
{required String roomName, required String unitId, required String userId}) async {
|
||||
{required String roomName,
|
||||
required String unitId,
|
||||
required String userId,
|
||||
required String communityId}) async {
|
||||
try {
|
||||
Map<String, String> body = {'roomName': roomName, 'unitUuid': unitId};
|
||||
final response = await HomeCreation.createRoom(body);
|
||||
Map<String, String> body = {'subspaceName': roomName};
|
||||
final response = await HomeCreation.createRoom(
|
||||
communityId: communityId, spaceId: unitId, body: body);
|
||||
// if (response['data']['uuid'] != '') {
|
||||
// final result = await _assignToRoom(roomId: response['data']['uuid'], userId: userId);
|
||||
|
||||
@ -223,7 +253,8 @@ Future<String> _createNewRoom(
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> _assignToRoom({required String roomId, required String userId}) async {
|
||||
Future<bool> _assignToRoom(
|
||||
{required String roomId, required String userId}) async {
|
||||
try {
|
||||
Map<String, String> body = {
|
||||
'roomUuid': roomId,
|
||||
|
||||
@ -17,12 +17,15 @@ class ManageUnitBloc extends Bloc<ManageUnitEvent, ManageUnitState> {
|
||||
on<FetchDevicesByRoomIdEvent>(_fetchDevicesByRoomId);
|
||||
on<AssignRoomEvent>(_assignDevice);
|
||||
on<AddNewRoom>(_addNewRoom);
|
||||
on<UnassignRoomEvent>(_unassignDevice);
|
||||
}
|
||||
|
||||
void _fetchRoomsAndDevices(FetchRoomsEvent event, Emitter<ManageUnitState> emit) async {
|
||||
void _fetchRoomsAndDevices(
|
||||
FetchRoomsEvent event, Emitter<ManageUnitState> emit) async {
|
||||
try {
|
||||
emit(LoadingState());
|
||||
final roomsList = await SpacesAPI.getRoomsBySpaceId(event.unitId);
|
||||
final roomsList = await SpacesAPI.getSubSpaceBySpaceId(
|
||||
event.unit.community.uuid, event.unit.id);
|
||||
emit(FetchRoomsState(devicesList: allDevices, roomsList: roomsList));
|
||||
} catch (e) {
|
||||
emit(const ErrorState(message: 'Something went wrong'));
|
||||
@ -30,11 +33,15 @@ class ManageUnitBloc extends Bloc<ManageUnitEvent, ManageUnitState> {
|
||||
}
|
||||
}
|
||||
|
||||
void _fetchDevicesByRoomId(FetchDevicesByRoomIdEvent event, Emitter<ManageUnitState> emit) async {
|
||||
void _fetchDevicesByRoomId(
|
||||
FetchDevicesByRoomIdEvent event, Emitter<ManageUnitState> emit) async {
|
||||
try {
|
||||
Map<String, bool> roomDevicesId = {};
|
||||
emit(LoadingState());
|
||||
final devicesList = await DevicesAPI.getDevicesByRoomId(event.roomId);
|
||||
final devicesList = await DevicesAPI.getDevicesByRoomId(
|
||||
communityUuid: event.unit.community.uuid,
|
||||
spaceUuid: event.unit.id,
|
||||
roomId: event.roomId);
|
||||
allDevices = await HomeManagementAPI.fetchDevicesByUserId();
|
||||
|
||||
List<String> allDevicesIds = [];
|
||||
@ -61,13 +68,18 @@ class ManageUnitBloc extends Bloc<ManageUnitEvent, ManageUnitState> {
|
||||
}
|
||||
}
|
||||
|
||||
void _assignDevice(AssignRoomEvent event, Emitter<ManageUnitState> emit) async {
|
||||
void _assignDevice(
|
||||
AssignRoomEvent event, Emitter<ManageUnitState> emit) async {
|
||||
try {
|
||||
Map<String, bool> roomDevicesId = {};
|
||||
emit(LoadingState());
|
||||
Map<String, String> body = {"deviceUuid": event.deviceId, "roomUuid": event.roomId};
|
||||
await HomeManagementAPI.assignDeviceToRoom(body);
|
||||
final devicesList = await DevicesAPI.getDevicesByRoomId(event.roomId);
|
||||
|
||||
await HomeManagementAPI.assignDeviceToRoom(
|
||||
event.unit.community.uuid, event.unit.id, event.roomId, event.deviceId);
|
||||
final devicesList = await DevicesAPI.getDevicesByRoomId(
|
||||
communityUuid: event.unit.community.uuid,
|
||||
spaceUuid: event.unit.id,
|
||||
roomId: event.roomId);
|
||||
|
||||
List<String> allDevicesIds = [];
|
||||
|
||||
@ -93,13 +105,56 @@ class ManageUnitBloc extends Bloc<ManageUnitEvent, ManageUnitState> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void _unassignDevice(
|
||||
UnassignRoomEvent event, Emitter<ManageUnitState> emit) async {
|
||||
try {
|
||||
Map<String, bool> roomDevicesId = {};
|
||||
emit(LoadingState());
|
||||
|
||||
await HomeManagementAPI.unAssignDeviceToRoom(
|
||||
event.unit.community.uuid, event.unit.id, event.roomId, event.deviceId);
|
||||
final devicesList = await DevicesAPI.getDevicesByRoomId(
|
||||
communityUuid: event.unit.community.uuid,
|
||||
spaceUuid: event.unit.id,
|
||||
roomId: event.roomId);
|
||||
|
||||
List<String> allDevicesIds = [];
|
||||
|
||||
allDevices.forEach((element) {
|
||||
allDevicesIds.add(element.uuid!);
|
||||
});
|
||||
|
||||
devicesList.forEach((e) {
|
||||
if (allDevicesIds.contains(e.uuid!)) {
|
||||
roomDevicesId[e.uuid!] = true;
|
||||
} else {
|
||||
roomDevicesId[e.uuid!] = false;
|
||||
}
|
||||
});
|
||||
emit(FetchDeviceByRoomIdState(
|
||||
roomDevices: devicesList,
|
||||
allDevices: allDevices,
|
||||
roomDevicesId: roomDevicesId,
|
||||
roomId: event.roomId));
|
||||
} catch (e) {
|
||||
emit(const ErrorState(message: 'Something went wrong'));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
_addNewRoom(AddNewRoom event, Emitter<ManageUnitState> emit) async {
|
||||
Map<String, String> body = {'roomName': event.roomName, 'unitUuid': event.unitId};
|
||||
Map<String, String> body = {'subspaceName': event.roomName};
|
||||
try {
|
||||
emit(LoadingState());
|
||||
final response = await HomeCreation.createRoom(body);
|
||||
final response = await HomeCreation.createRoom(
|
||||
communityId: event.unit.community.uuid,
|
||||
spaceId: event.unit.id,
|
||||
body: body);
|
||||
if (response['data']['uuid'] != '') {
|
||||
final roomsList = await SpacesAPI.getRoomsBySpaceId(event.unitId);
|
||||
final roomsList = await SpacesAPI.getSubSpaceBySpaceId(
|
||||
event.unit.community.uuid, event.unit.id);
|
||||
allDevices = await HomeManagementAPI.fetchDevicesByUserId();
|
||||
emit(FetchRoomsState(devicesList: allDevices, roomsList: roomsList));
|
||||
await HomeCubit.getInstance().fetchUnitsByUserId();
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:syncrow_app/features/app_layout/model/space_model.dart';
|
||||
|
||||
abstract class ManageUnitEvent extends Equatable {
|
||||
const ManageUnitEvent();
|
||||
@ -12,39 +13,54 @@ class InitialEvent extends ManageUnitEvent {}
|
||||
class LoadingEvent extends ManageUnitEvent {}
|
||||
|
||||
class FetchRoomsEvent extends ManageUnitEvent {
|
||||
final String unitId;
|
||||
final SpaceModel unit;
|
||||
|
||||
const FetchRoomsEvent({required this.unitId});
|
||||
const FetchRoomsEvent({required this.unit});
|
||||
|
||||
@override
|
||||
List<Object> get props => [unitId];
|
||||
List<Object> get props => [unit];
|
||||
}
|
||||
|
||||
class FetchDevicesByRoomIdEvent extends ManageUnitEvent {
|
||||
final String roomId;
|
||||
final SpaceModel unit;
|
||||
|
||||
const FetchDevicesByRoomIdEvent({required this.roomId});
|
||||
const FetchDevicesByRoomIdEvent({required this.roomId, required this.unit});
|
||||
|
||||
@override
|
||||
List<Object> get props => [roomId];
|
||||
List<Object> get props => [roomId, unit];
|
||||
}
|
||||
|
||||
class AddNewRoom extends ManageUnitEvent {
|
||||
final String roomName;
|
||||
final String unitId;
|
||||
final SpaceModel unit;
|
||||
|
||||
const AddNewRoom({required this.roomName, required this.unitId});
|
||||
const AddNewRoom({required this.roomName, required this.unit});
|
||||
|
||||
@override
|
||||
List<Object> get props => [roomName, unitId];
|
||||
List<Object> get props => [roomName, unit];
|
||||
}
|
||||
|
||||
class AssignRoomEvent extends ManageUnitEvent {
|
||||
final String roomId;
|
||||
final String deviceId;
|
||||
final SpaceModel unit;
|
||||
|
||||
const AssignRoomEvent({required this.roomId, required this.deviceId});
|
||||
const AssignRoomEvent(
|
||||
{required this.roomId, required this.deviceId, required this.unit});
|
||||
|
||||
@override
|
||||
List<Object> get props => [roomId];
|
||||
List<Object> get props => [roomId, unit];
|
||||
}
|
||||
|
||||
class UnassignRoomEvent extends ManageUnitEvent {
|
||||
final String roomId;
|
||||
final String deviceId;
|
||||
final SpaceModel unit;
|
||||
|
||||
const UnassignRoomEvent(
|
||||
{required this.roomId, required this.deviceId, required this.unit});
|
||||
|
||||
@override
|
||||
List<Object> get props => [roomId, unit];
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/room_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/subspace_model.dart';
|
||||
|
||||
abstract class ManageUnitState extends Equatable {
|
||||
const ManageUnitState();
|
||||
@ -14,7 +15,7 @@ class InitialState extends ManageUnitState {}
|
||||
class LoadingState extends ManageUnitState {}
|
||||
|
||||
class FetchRoomsState extends ManageUnitState {
|
||||
final List<RoomModel> roomsList;
|
||||
final List<SubSpaceModel> roomsList;
|
||||
final List<DeviceModel> devicesList;
|
||||
|
||||
const FetchRoomsState({required this.devicesList, required this.roomsList});
|
||||
|
||||
@ -44,7 +44,8 @@ class JoinHomeView extends StatelessWidget {
|
||||
controller: textEditingController,
|
||||
decoration: InputDecoration(
|
||||
hintText: 'Invitatoin code',
|
||||
hintStyle: context.bodyMedium.copyWith(color: Colors.grey),
|
||||
hintStyle:
|
||||
context.bodyMedium.copyWith(color: Colors.grey),
|
||||
border: InputBorder.none,
|
||||
),
|
||||
),
|
||||
@ -52,10 +53,12 @@ class JoinHomeView extends StatelessWidget {
|
||||
IconButton(
|
||||
onPressed: () async {
|
||||
if (textEditingController.text.isEmpty) {
|
||||
CustomSnackBar.displaySnackBar('Please enter the invitation code');
|
||||
CustomSnackBar.displaySnackBar(
|
||||
'Please enter the invitation code');
|
||||
return;
|
||||
}
|
||||
if (await HomeCubit.getInstance().joinAUnit(textEditingController.text)) {
|
||||
if (await HomeCubit.getInstance()
|
||||
.joinAUnit(textEditingController.text)) {
|
||||
CustomSnackBar.displaySnackBar('Done successfully');
|
||||
Navigator.of(context).pop();
|
||||
} else {
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:syncrow_app/features/app_layout/model/space_model.dart';
|
||||
import 'package:syncrow_app/features/menu/bloc/manage_unit_bloc/manage_unit_bloc.dart';
|
||||
import 'package:syncrow_app/features/menu/bloc/manage_unit_bloc/manage_unit_event.dart';
|
||||
import 'package:syncrow_app/features/menu/bloc/manage_unit_bloc/manage_unit_state.dart';
|
||||
@ -11,16 +12,24 @@ import 'package:syncrow_app/utils/helpers/snack_bar.dart';
|
||||
class AssignDeviceView extends StatelessWidget {
|
||||
final String unitId;
|
||||
final String roomId;
|
||||
const AssignDeviceView({super.key, required this.unitId, required this.roomId});
|
||||
final SpaceModel unit;
|
||||
const AssignDeviceView(
|
||||
{super.key,
|
||||
required this.unitId,
|
||||
required this.roomId,
|
||||
required this.unit});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider(
|
||||
create: (context) => ManageUnitBloc()..add(FetchDevicesByRoomIdEvent(roomId: roomId)),
|
||||
child: BlocConsumer<ManageUnitBloc, ManageUnitState>(listener: (context, state) {
|
||||
create: (context) => ManageUnitBloc()
|
||||
..add(FetchDevicesByRoomIdEvent(roomId: roomId, unit: unit)),
|
||||
child: BlocConsumer<ManageUnitBloc, ManageUnitState>(
|
||||
listener: (context, state) {
|
||||
if (state is FetchDeviceByRoomIdState) {
|
||||
if (state.allDevices.isEmpty) {
|
||||
CustomSnackBar.displaySnackBar('You do not have the permission to assign devices');
|
||||
CustomSnackBar.displaySnackBar(
|
||||
'You do not have the permission to assign devices');
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
}
|
||||
@ -34,7 +43,8 @@ class AssignDeviceView extends StatelessWidget {
|
||||
width: MediaQuery.sizeOf(context).width,
|
||||
height: MediaQuery.sizeOf(context).height,
|
||||
child: GridView.builder(
|
||||
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
gridDelegate:
|
||||
const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
crossAxisSpacing: 10.0,
|
||||
mainAxisSpacing: 10.0,
|
||||
@ -52,11 +62,14 @@ class AssignDeviceView extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start,
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
state.allDevices[index].icon!,
|
||||
@ -64,19 +77,42 @@ class AssignDeviceView extends StatelessWidget {
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
if (state.roomDevicesId[
|
||||
state.allDevices[index].uuid!] ??
|
||||
false == false) {
|
||||
BlocProvider.of<ManageUnitBloc>(context).add(
|
||||
AssignRoomEvent(
|
||||
deviceId:
|
||||
state.allDevices[index].uuid ?? '',
|
||||
bool isAssigned =
|
||||
state.roomDevicesId[state
|
||||
.allDevices[index]
|
||||
.uuid!] ??
|
||||
false;
|
||||
if (isAssigned) {
|
||||
BlocProvider.of<
|
||||
ManageUnitBloc>(
|
||||
context)
|
||||
.add(UnassignRoomEvent(
|
||||
deviceId: state
|
||||
.allDevices[
|
||||
index]
|
||||
.uuid ??
|
||||
'',
|
||||
unit: unit,
|
||||
roomId: roomId));
|
||||
} else {
|
||||
// Tick (assign) the device
|
||||
BlocProvider.of<
|
||||
ManageUnitBloc>(
|
||||
context)
|
||||
.add(AssignRoomEvent(
|
||||
deviceId: state
|
||||
.allDevices[
|
||||
index]
|
||||
.uuid ??
|
||||
'',
|
||||
unit: unit,
|
||||
roomId: roomId));
|
||||
}
|
||||
},
|
||||
child: SvgPicture.asset(
|
||||
state.roomDevicesId[
|
||||
state.allDevices[index].uuid!] ??
|
||||
state.roomDevicesId[state
|
||||
.allDevices[index]
|
||||
.uuid!] ??
|
||||
false
|
||||
? Assets.blueCheckboxIcon
|
||||
: Assets.emptyCheckboxIcon,
|
||||
|
||||
@ -60,7 +60,7 @@ class HomeSettingsView extends StatelessWidget {
|
||||
onTap: () {
|
||||
Navigator.of(context).push(CustomPageRoute(
|
||||
builder: (context) => RoomsView(
|
||||
unitId: space?.id ?? '',
|
||||
unit: space!,
|
||||
)));
|
||||
},
|
||||
child: Container(
|
||||
@ -112,7 +112,7 @@ class HomeSettingsView extends StatelessWidget {
|
||||
padding: const EdgeInsets.only(bottom: 10),
|
||||
child: GestureDetector(
|
||||
onTap: () async {
|
||||
await HomeCubit.getInstance().generateInvitation(space?.id ?? '');
|
||||
await HomeCubit.getInstance().generateInvitation(space!);
|
||||
},
|
||||
child: const Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/app_layout/model/space_model.dart';
|
||||
import 'package:syncrow_app/features/menu/bloc/manage_unit_bloc/manage_unit_bloc.dart';
|
||||
import 'package:syncrow_app/features/menu/bloc/manage_unit_bloc/manage_unit_event.dart';
|
||||
import 'package:syncrow_app/features/menu/bloc/manage_unit_bloc/manage_unit_state.dart';
|
||||
@ -11,14 +12,14 @@ import 'package:syncrow_app/utils/helpers/snack_bar.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
|
||||
class RoomsView extends StatelessWidget {
|
||||
final String unitId;
|
||||
const RoomsView({super.key, required this.unitId});
|
||||
final SpaceModel unit;
|
||||
const RoomsView({super.key, required this.unit});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
TextEditingController textEditingController = TextEditingController();
|
||||
return BlocProvider(
|
||||
create: (context) => ManageUnitBloc()..add(FetchRoomsEvent(unitId: unitId)),
|
||||
create: (context) => ManageUnitBloc()..add(FetchRoomsEvent(unit:unit )),
|
||||
child: BlocConsumer<ManageUnitBloc, ManageUnitState>(
|
||||
listener: (context, state) {},
|
||||
builder: (context, state) {
|
||||
@ -62,7 +63,8 @@ class RoomsView extends StatelessWidget {
|
||||
MaterialPageRoute(
|
||||
builder: (context) => AssignDeviceView(
|
||||
roomId: state.roomsList[index].id ?? '',
|
||||
unitId: unitId,
|
||||
unitId: unit.id,
|
||||
unit: unit,
|
||||
)),
|
||||
);
|
||||
},
|
||||
@ -100,14 +102,14 @@ class RoomsView extends StatelessWidget {
|
||||
BlocProvider.of<ManageUnitBloc>(context).add(
|
||||
AddNewRoom(
|
||||
roomName: textEditingController.text,
|
||||
unitId: unitId));
|
||||
unit: unit));
|
||||
textEditingController.clear();
|
||||
},
|
||||
child: const Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
BodyMedium(
|
||||
text: 'Add Space',
|
||||
text: 'Add Room',
|
||||
fontColor: ColorsManager.primaryColor,
|
||||
),
|
||||
],
|
||||
|
||||
@ -60,7 +60,8 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
|
||||
String selectedIcon = '';
|
||||
bool showInDeviceScreen = false;
|
||||
|
||||
FutureOr<void> _onAddSceneTask(AddTaskEvent event, Emitter<CreateSceneState> emit) {
|
||||
FutureOr<void> _onAddSceneTask(
|
||||
AddTaskEvent event, Emitter<CreateSceneState> emit) {
|
||||
emit(CreateSceneLoading());
|
||||
if (event.isAutomation == true) {
|
||||
final copyList = List<SceneStaticFunction>.from(automationTempTasksList);
|
||||
@ -95,7 +96,8 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
|
||||
}
|
||||
}
|
||||
|
||||
void addToTempTaskList(TempHoldSceneTasksEvent event, Emitter<CreateSceneState> emit) {
|
||||
void addToTempTaskList(
|
||||
TempHoldSceneTasksEvent event, Emitter<CreateSceneState> emit) {
|
||||
emit(CreateSceneLoading());
|
||||
bool updated = false;
|
||||
|
||||
@ -180,7 +182,8 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
|
||||
));
|
||||
}
|
||||
|
||||
void addToTempAutomationTaskList(TempHoldSceneTasksEvent event, Emitter<CreateSceneState> emit) {
|
||||
void addToTempAutomationTaskList(
|
||||
TempHoldSceneTasksEvent event, Emitter<CreateSceneState> emit) {
|
||||
emit(CreateSceneLoading());
|
||||
bool updated = false;
|
||||
for (var element in automationTempTasksList) {
|
||||
@ -202,8 +205,10 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
|
||||
],
|
||||
comparator: automationComparatorValues[element.code],
|
||||
);
|
||||
automationTempTasksList[automationTempTasksList.indexOf(element)] = updatedElement;
|
||||
automationSelectedValues[updatedElement.code] = event.deviceControlModel.value;
|
||||
automationTempTasksList[automationTempTasksList.indexOf(element)] =
|
||||
updatedElement;
|
||||
automationSelectedValues[updatedElement.code] =
|
||||
event.deviceControlModel.value;
|
||||
updated = true;
|
||||
break;
|
||||
}
|
||||
@ -223,10 +228,12 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
|
||||
icon: '',
|
||||
),
|
||||
],
|
||||
comparator: automationComparatorValues[event.deviceControlModel.code] ?? '==',
|
||||
comparator:
|
||||
automationComparatorValues[event.deviceControlModel.code] ?? '==',
|
||||
);
|
||||
automationTempTasksList.add(newElement);
|
||||
automationSelectedValues[newElement.code] = event.deviceControlModel.value;
|
||||
automationSelectedValues[newElement.code] =
|
||||
event.deviceControlModel.value;
|
||||
}
|
||||
emit(AddSceneTask(
|
||||
tasksList: tasksList,
|
||||
@ -235,7 +242,8 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
|
||||
));
|
||||
}
|
||||
|
||||
FutureOr<void> _selectedValue(SelectedValueEvent event, Emitter<CreateSceneState> emit) {
|
||||
FutureOr<void> _selectedValue(
|
||||
SelectedValueEvent event, Emitter<CreateSceneState> emit) {
|
||||
if (event.isAutomation == true) {
|
||||
automationSelectedValues[event.code] = event.value;
|
||||
automationComparatorValues[event.code] = event.comparator ?? '==';
|
||||
@ -272,7 +280,8 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
|
||||
));
|
||||
}
|
||||
|
||||
FutureOr<void> _removeTaskById(RemoveTaskByIdEvent event, Emitter<CreateSceneState> emit) {
|
||||
FutureOr<void> _removeTaskById(
|
||||
RemoveTaskByIdEvent event, Emitter<CreateSceneState> emit) {
|
||||
emit(CreateSceneLoading());
|
||||
if (event.isAutomation == true) {
|
||||
for (var element in automationTasksList) {
|
||||
@ -345,7 +354,8 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
|
||||
: await SceneApi.createScene(event.createSceneModel!);
|
||||
} else if (event.createAutomationModel != null) {
|
||||
response = event.updateScene
|
||||
? await SceneApi.updateAutomation(event.createAutomationModel!, event.sceneId)
|
||||
? await SceneApi.updateAutomation(
|
||||
event.createAutomationModel!, event.sceneId)
|
||||
: await SceneApi.createAutomation(event.createAutomationModel!);
|
||||
}
|
||||
|
||||
@ -359,12 +369,14 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
|
||||
automationComparatorValues.clear();
|
||||
selectedIcon = '';
|
||||
showInDeviceScreen = false;
|
||||
effectiveTime = EffectiveTime(start: '00:00', end: '23:59', loops: '1111111');
|
||||
effectiveTime =
|
||||
EffectiveTime(start: '00:00', end: '23:59', loops: '1111111');
|
||||
sceneType = CreateSceneEnum.none;
|
||||
conditionRule = 'or';
|
||||
emit(const CreateSceneWithTasks(success: true));
|
||||
CustomSnackBar.greenSnackBar(
|
||||
event.updateScene ? 'Scene updated successfully' : 'Scene created successfully');
|
||||
CustomSnackBar.greenSnackBar(event.updateScene
|
||||
? 'Scene updated successfully'
|
||||
: 'Scene created successfully');
|
||||
} else {
|
||||
emit(const CreateSceneError(message: 'Something went wrong'));
|
||||
}
|
||||
@ -378,7 +390,8 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
|
||||
}
|
||||
}
|
||||
|
||||
FutureOr<void> _clearTaskList(ClearTaskListEvent event, Emitter<CreateSceneState> emit) {
|
||||
FutureOr<void> _clearTaskList(
|
||||
ClearTaskListEvent event, Emitter<CreateSceneState> emit) {
|
||||
emit(CreateSceneLoading());
|
||||
automationTasksList.clear();
|
||||
tasksList.clear();
|
||||
@ -389,7 +402,8 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
|
||||
));
|
||||
}
|
||||
|
||||
FutureOr<void> _clearTabToRunSetting(ClearTabToRunSetting event, Emitter<CreateSceneState> emit) {
|
||||
FutureOr<void> _clearTabToRunSetting(
|
||||
ClearTabToRunSetting event, Emitter<CreateSceneState> emit) {
|
||||
emit(CreateSceneLoading());
|
||||
selectedIcon = '';
|
||||
showInDeviceScreen = false;
|
||||
@ -416,7 +430,8 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
|
||||
automationComparatorValues.clear();
|
||||
selectedIcon = '';
|
||||
showInDeviceScreen = false;
|
||||
effectiveTime = EffectiveTime(start: '00:00', end: '23:59', loops: '1111111');
|
||||
effectiveTime =
|
||||
EffectiveTime(start: '00:00', end: '23:59', loops: '1111111');
|
||||
sceneType = CreateSceneEnum.none;
|
||||
conditionRule = 'or';
|
||||
|
||||
@ -425,10 +440,14 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
|
||||
: await SceneApi.getSceneDetails(event.sceneId);
|
||||
if (response.id.isNotEmpty) {
|
||||
if (event.isAutomation) {
|
||||
automationTasksList = List<SceneStaticFunction>.from(getTaskListFunctionsFromApi(
|
||||
actions: [], isAutomation: true, conditions: response.conditions));
|
||||
automationTasksList = List<SceneStaticFunction>.from(
|
||||
getTaskListFunctionsFromApi(
|
||||
actions: [],
|
||||
isAutomation: true,
|
||||
conditions: response.conditions));
|
||||
tasksList = List<SceneStaticFunction>.from(
|
||||
getTaskListFunctionsFromApi(actions: response.actions, isAutomation: false));
|
||||
getTaskListFunctionsFromApi(
|
||||
actions: response.actions, isAutomation: false));
|
||||
|
||||
conditionRule = response.decisionExpr ?? conditionRule;
|
||||
|
||||
@ -441,11 +460,13 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
|
||||
: EffectiveTime(start: '00:00', end: '23:59', loops: '1111111');
|
||||
|
||||
// Set the days directly from the API response
|
||||
BlocProvider.of<EffectPeriodBloc>(NavigationService.navigatorKey.currentContext!)
|
||||
BlocProvider.of<EffectPeriodBloc>(
|
||||
NavigationService.navigatorKey.currentContext!)
|
||||
.add(SetDays(response.effectiveTime?.loops ?? '1111111'));
|
||||
|
||||
// Set Custom Time and reset days first
|
||||
BlocProvider.of<EffectPeriodBloc>(NavigationService.navigatorKey.currentContext!)
|
||||
BlocProvider.of<EffectPeriodBloc>(
|
||||
NavigationService.navigatorKey.currentContext!)
|
||||
.add(SetCustomTime(effectiveTime!.start, effectiveTime!.end));
|
||||
|
||||
emit(AddSceneTask(
|
||||
@ -457,7 +478,8 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
|
||||
showInDevice: showInDeviceScreen));
|
||||
} else {
|
||||
tasksList = List<SceneStaticFunction>.from(
|
||||
getTaskListFunctionsFromApi(actions: response.actions, isAutomation: false));
|
||||
getTaskListFunctionsFromApi(
|
||||
actions: response.actions, isAutomation: false));
|
||||
selectedIcon = response.icon!;
|
||||
showInDeviceScreen = response.showInDevice!;
|
||||
emit(AddSceneTask(
|
||||
@ -475,7 +497,8 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
|
||||
}
|
||||
}
|
||||
|
||||
FutureOr<void> _fetchIconScene(SceneIconEvent event, Emitter<CreateSceneState> emit) async {
|
||||
FutureOr<void> _fetchIconScene(
|
||||
SceneIconEvent event, Emitter<CreateSceneState> emit) async {
|
||||
emit(CreateSceneLoading());
|
||||
try {
|
||||
iconModelList = await SceneApi.getIcon();
|
||||
@ -491,7 +514,8 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
|
||||
}
|
||||
}
|
||||
|
||||
FutureOr<void> _iconSelected(IconSelected event, Emitter<CreateSceneState> emit) async {
|
||||
FutureOr<void> _iconSelected(
|
||||
IconSelected event, Emitter<CreateSceneState> emit) async {
|
||||
try {
|
||||
if (event.confirmSelection) {
|
||||
selectedIcon = event.iconId;
|
||||
@ -531,7 +555,8 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
|
||||
return days[index];
|
||||
}
|
||||
|
||||
FutureOr<void> _clearTempTaskList(ClearTempTaskListEvent event, Emitter<CreateSceneState> emit) {
|
||||
FutureOr<void> _clearTempTaskList(
|
||||
ClearTempTaskListEvent event, Emitter<CreateSceneState> emit) {
|
||||
emit(CreateSceneLoading());
|
||||
if (event.isAutomation == true) {
|
||||
automationTempTasksList.clear();
|
||||
@ -575,13 +600,18 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
|
||||
}
|
||||
}
|
||||
|
||||
FutureOr<void> _deleteScene(DeleteSceneEvent event, Emitter<CreateSceneState> emit) async {
|
||||
FutureOr<void> _deleteScene(
|
||||
DeleteSceneEvent event, Emitter<CreateSceneState> emit) async {
|
||||
emit(DeleteSceneLoading());
|
||||
|
||||
try {
|
||||
final response = sceneType.name == CreateSceneEnum.deviceStatusChanges.name
|
||||
? await SceneApi.deleteAutomation(automationId: event.sceneId, unitUuid: event.unitUuid)
|
||||
: await SceneApi.deleteScene(sceneId: event.sceneId, unitUuid: event.unitUuid);
|
||||
final response =
|
||||
sceneType.name == CreateSceneEnum.deviceStatusChanges.name
|
||||
? await SceneApi.deleteAutomation(
|
||||
automationId: event.sceneId, unitUuid: event.unitUuid)
|
||||
: await SceneApi.deleteScene(
|
||||
sceneId: event.sceneId,
|
||||
);
|
||||
if (response == true) {
|
||||
emit(const DeleteSceneSuccess(true));
|
||||
} else {
|
||||
@ -592,7 +622,8 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
|
||||
}
|
||||
}
|
||||
|
||||
FutureOr<void> _updateTaskValue(UpdateTaskEvent event, Emitter<CreateSceneState> emit) {
|
||||
FutureOr<void> _updateTaskValue(
|
||||
UpdateTaskEvent event, Emitter<CreateSceneState> emit) {
|
||||
emit(CreateSceneLoading());
|
||||
if (event.isAutomation == true) {
|
||||
for (var i = 0; i < automationTasksList.length; i++) {
|
||||
@ -628,7 +659,8 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
|
||||
));
|
||||
}
|
||||
|
||||
FutureOr<void> _selectConditionRule(SelectConditionEvent event, Emitter<CreateSceneState> emit) {
|
||||
FutureOr<void> _selectConditionRule(
|
||||
SelectConditionEvent event, Emitter<CreateSceneState> emit) {
|
||||
emit(CreateSceneInitial());
|
||||
if (event.condition.contains('any')) {
|
||||
conditionRule = 'or';
|
||||
@ -643,7 +675,8 @@ class CreateSceneBloc extends Bloc<CreateSceneEvent, CreateSceneState>
|
||||
));
|
||||
}
|
||||
|
||||
FutureOr<void> _sceneTypeEvent(SceneTypeEvent event, Emitter<CreateSceneState> emit) {
|
||||
FutureOr<void> _sceneTypeEvent(
|
||||
SceneTypeEvent event, Emitter<CreateSceneState> emit) {
|
||||
// emit(CreateSceneInitial());
|
||||
|
||||
if (event.type == CreateSceneEnum.tabToRun) {
|
||||
|
||||
@ -24,7 +24,9 @@ class SceneBloc extends Bloc<SceneEvent, SceneState> {
|
||||
|
||||
try {
|
||||
if (event.unitId.isNotEmpty) {
|
||||
scenes = await SceneApi.getScenesByUnitId(event.unitId, showInDevice: event.showInDevice);
|
||||
scenes = await SceneApi.getScenesByUnitId(
|
||||
event.unitId, event.unit.community.uuid,
|
||||
showInDevice: event.showInDevice);
|
||||
emit(SceneLoaded(scenes, automationList));
|
||||
} else {
|
||||
emit(const SceneError(message: 'Unit ID is empty'));
|
||||
@ -34,7 +36,8 @@ class SceneBloc extends Bloc<SceneEvent, SceneState> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onLoadAutomation(LoadAutomation event, Emitter<SceneState> emit) async {
|
||||
Future<void> _onLoadAutomation(
|
||||
LoadAutomation event, Emitter<SceneState> emit) async {
|
||||
emit(SceneLoading());
|
||||
|
||||
try {
|
||||
@ -49,7 +52,8 @@ class SceneBloc extends Bloc<SceneEvent, SceneState> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onSceneTrigger(SceneTrigger event, Emitter<SceneState> emit) async {
|
||||
Future<void> _onSceneTrigger(
|
||||
SceneTrigger event, Emitter<SceneState> emit) async {
|
||||
final currentState = state;
|
||||
if (currentState is SceneLoaded) {
|
||||
emit(SceneLoaded(
|
||||
@ -76,8 +80,9 @@ class SceneBloc extends Bloc<SceneEvent, SceneState> {
|
||||
UpdateAutomationStatus event, Emitter<SceneState> emit) async {
|
||||
final currentState = state;
|
||||
if (currentState is SceneLoaded) {
|
||||
final newLoadingStates = Map<String, bool>.from(currentState.loadingStates)
|
||||
..[event.automationId] = true;
|
||||
final newLoadingStates =
|
||||
Map<String, bool>.from(currentState.loadingStates)
|
||||
..[event.automationId] = true;
|
||||
|
||||
emit(SceneLoaded(
|
||||
currentState.scenes,
|
||||
@ -86,11 +91,11 @@ class SceneBloc extends Bloc<SceneEvent, SceneState> {
|
||||
));
|
||||
|
||||
try {
|
||||
final success =
|
||||
await SceneApi.updateAutomationStatus(event.automationId, event.automationStatusUpdate);
|
||||
final success = await SceneApi.updateAutomationStatus(
|
||||
event.automationId, event.automationStatusUpdate);
|
||||
if (success) {
|
||||
automationList =
|
||||
await SceneApi.getAutomationByUnitId(event.automationStatusUpdate.unitUuid);
|
||||
automationList = await SceneApi.getAutomationByUnitId(
|
||||
event.automationStatusUpdate.spaceUuid);
|
||||
newLoadingStates[event.automationId] = false;
|
||||
emit(SceneLoaded(
|
||||
currentState.scenes,
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:syncrow_app/features/app_layout/model/space_model.dart';
|
||||
import 'package:syncrow_app/features/scene/model/update_automation.dart';
|
||||
|
||||
abstract class SceneEvent extends Equatable {
|
||||
@ -11,8 +12,9 @@ abstract class SceneEvent extends Equatable {
|
||||
class LoadScenes extends SceneEvent {
|
||||
final String unitId;
|
||||
final bool showInDevice;
|
||||
final SpaceModel unit;
|
||||
|
||||
const LoadScenes(this.unitId, {this.showInDevice = false});
|
||||
const LoadScenes(this.unitId, this.unit, {this.showInDevice = false});
|
||||
|
||||
@override
|
||||
List<Object> get props => [unitId, showInDevice];
|
||||
|
||||
@ -17,7 +17,7 @@ class TabBarBloc extends Bloc<TabBarEvent, TabBarState> {
|
||||
if (event.roomId == "-1") {
|
||||
deviceManagerBloc.add(FetchAllDevices());
|
||||
} else {
|
||||
deviceManagerBloc.add(FetchDevicesByRoomId(event.roomId));
|
||||
deviceManagerBloc.add(FetchDevicesByRoomId(event.roomId,event.unit));
|
||||
}
|
||||
emit(TabSelected(
|
||||
roomId: event.roomId, selectedTabIndex: event.selectedIndex));
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import 'package:syncrow_app/features/app_layout/model/space_model.dart';
|
||||
|
||||
abstract class TabBarEvent {
|
||||
const TabBarEvent();
|
||||
}
|
||||
@ -5,5 +7,7 @@ abstract class TabBarEvent {
|
||||
class TabChanged extends TabBarEvent {
|
||||
final int selectedIndex;
|
||||
final String roomId;
|
||||
const TabChanged({required this.selectedIndex, required this.roomId});
|
||||
final SpaceModel unit;
|
||||
const TabChanged(
|
||||
{required this.selectedIndex, required this.roomId, required this.unit});
|
||||
}
|
||||
|
||||
@ -124,7 +124,7 @@ mixin SceneLogicHelper {
|
||||
));
|
||||
} else {
|
||||
final createSceneModel = CreateSceneModel(
|
||||
unitUuid: HomeCubit.getInstance().selectedSpace!.id ?? '',
|
||||
spaceUuid: HomeCubit.getInstance().selectedSpace!.id ?? '',
|
||||
iconId: sceneBloc.selectedIcon,
|
||||
showInDevice: sceneBloc.showInDeviceScreen,
|
||||
sceneName: sceneName.text,
|
||||
|
||||
@ -39,7 +39,7 @@ class CreateAutomationModel {
|
||||
|
||||
Map<String, dynamic> toMap([String? automationId]) {
|
||||
return {
|
||||
if (automationId == null) 'unitUuid': unitUuid,
|
||||
if (automationId == null) 'spaceUuid': unitUuid,
|
||||
'automationName': automationName,
|
||||
'decisionExpr': decisionExpr,
|
||||
'effectiveTime': effectiveTime.toMap(),
|
||||
@ -50,7 +50,7 @@ class CreateAutomationModel {
|
||||
|
||||
factory CreateAutomationModel.fromMap(Map<String, dynamic> map) {
|
||||
return CreateAutomationModel(
|
||||
unitUuid: map['unitUuid'] ?? '',
|
||||
unitUuid: map['spaceUuid'] ?? '',
|
||||
automationName: map['automationName'] ?? '',
|
||||
decisionExpr: map['decisionExpr'] ?? '',
|
||||
effectiveTime: EffectiveTime.fromMap(map['effectiveTime']),
|
||||
|
||||
@ -3,7 +3,7 @@ import 'dart:convert';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
class CreateSceneModel {
|
||||
String unitUuid;
|
||||
String spaceUuid;
|
||||
String iconId;
|
||||
bool showInDevice;
|
||||
String sceneName;
|
||||
@ -11,7 +11,7 @@ class CreateSceneModel {
|
||||
List<CreateSceneAction> actions;
|
||||
|
||||
CreateSceneModel({
|
||||
required this.unitUuid,
|
||||
required this.spaceUuid,
|
||||
required this.iconId,
|
||||
required this.showInDevice,
|
||||
required this.sceneName,
|
||||
@ -20,15 +20,16 @@ class CreateSceneModel {
|
||||
});
|
||||
|
||||
CreateSceneModel copyWith({
|
||||
String? unitUuid,
|
||||
String? spaceUuid,
|
||||
String? iconId,
|
||||
bool? showInDevice,
|
||||
String? sceneName,
|
||||
String? decisionExpr,
|
||||
List<CreateSceneAction>? actions,
|
||||
bool? showInHomePage,
|
||||
}) {
|
||||
return CreateSceneModel(
|
||||
unitUuid: unitUuid ?? this.unitUuid,
|
||||
spaceUuid: spaceUuid ?? this.spaceUuid,
|
||||
iconId: iconId ?? this.iconId,
|
||||
showInDevice: showInDevice ?? this.showInDevice,
|
||||
sceneName: sceneName ?? this.sceneName,
|
||||
@ -39,7 +40,7 @@ class CreateSceneModel {
|
||||
|
||||
Map<String, dynamic> toMap([String? sceneId]) {
|
||||
return {
|
||||
if (sceneId == null) 'unitUuid': unitUuid,
|
||||
if (sceneId == null) 'spaceUuid': spaceUuid,
|
||||
if (iconId.isNotEmpty) 'iconUuid': iconId,
|
||||
'showInHomePage': showInDevice,
|
||||
'sceneName': sceneName,
|
||||
@ -50,23 +51,24 @@ class CreateSceneModel {
|
||||
|
||||
factory CreateSceneModel.fromMap(Map<String, dynamic> map) {
|
||||
return CreateSceneModel(
|
||||
unitUuid: map['unitUuid'] ?? '',
|
||||
iconId: map['iconUuid'] ?? '',
|
||||
spaceUuid: map['spaceUuid'] ?? '',
|
||||
showInDevice: map['showInHomePage'] ?? false,
|
||||
iconId: map['iconUuid'] ?? '',
|
||||
sceneName: map['sceneName'] ?? '',
|
||||
decisionExpr: map['decisionExpr'] ?? '',
|
||||
actions:
|
||||
List<CreateSceneAction>.from(map['actions']?.map((x) => CreateSceneAction.fromMap(x))),
|
||||
actions: List<CreateSceneAction>.from(
|
||||
map['actions']?.map((x) => CreateSceneAction.fromMap(x))),
|
||||
);
|
||||
}
|
||||
|
||||
String toJson([String? sceneId]) => json.encode(toMap(sceneId));
|
||||
|
||||
factory CreateSceneModel.fromJson(String source) => CreateSceneModel.fromMap(json.decode(source));
|
||||
factory CreateSceneModel.fromJson(String source) =>
|
||||
CreateSceneModel.fromMap(json.decode(source));
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'CreateSceneModel(unitUuid: $unitUuid, sceneName: $sceneName, decisionExpr: $decisionExpr, actions: $actions)';
|
||||
return 'CreateSceneModel(unitUuid: $spaceUuid, sceneName: $sceneName, decisionExpr: $decisionExpr, actions: $actions)';
|
||||
}
|
||||
|
||||
@override
|
||||
@ -74,7 +76,7 @@ class CreateSceneModel {
|
||||
if (identical(this, other)) return true;
|
||||
|
||||
return other is CreateSceneModel &&
|
||||
other.unitUuid == unitUuid &&
|
||||
other.spaceUuid == spaceUuid &&
|
||||
other.iconId == iconId &&
|
||||
other.showInDevice == showInDevice &&
|
||||
other.sceneName == sceneName &&
|
||||
@ -84,7 +86,10 @@ class CreateSceneModel {
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return unitUuid.hashCode ^ sceneName.hashCode ^ decisionExpr.hashCode ^ actions.hashCode;
|
||||
return spaceUuid.hashCode ^
|
||||
sceneName.hashCode ^
|
||||
decisionExpr.hashCode ^
|
||||
actions.hashCode;
|
||||
}
|
||||
}
|
||||
|
||||
@ -130,7 +135,8 @@ class CreateSceneAction {
|
||||
return CreateSceneAction(
|
||||
entityId: map['entityId'] ?? '',
|
||||
actionExecutor: map['actionExecutor'] ?? '',
|
||||
executorProperty: CreateSceneExecutorProperty.fromMap(map['executorProperty']),
|
||||
executorProperty:
|
||||
CreateSceneExecutorProperty.fromMap(map['executorProperty']),
|
||||
);
|
||||
}
|
||||
|
||||
@ -154,7 +160,8 @@ class CreateSceneAction {
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => entityId.hashCode ^ actionExecutor.hashCode ^ executorProperty.hashCode;
|
||||
int get hashCode =>
|
||||
entityId.hashCode ^ actionExecutor.hashCode ^ executorProperty.hashCode;
|
||||
}
|
||||
|
||||
class CreateSceneExecutorProperty {
|
||||
@ -218,5 +225,6 @@ class CreateSceneExecutorProperty {
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => functionCode.hashCode ^ functionValue.hashCode ^ delaySeconds.hashCode;
|
||||
int get hashCode =>
|
||||
functionCode.hashCode ^ functionValue.hashCode ^ delaySeconds.hashCode;
|
||||
}
|
||||
|
||||
@ -25,28 +25,34 @@ class SceneDetailsModel {
|
||||
this.effectiveTime,
|
||||
});
|
||||
|
||||
factory SceneDetailsModel.fromRawJson(String str) => SceneDetailsModel.fromJson(json.decode(str));
|
||||
factory SceneDetailsModel.fromRawJson(String str) =>
|
||||
SceneDetailsModel.fromJson(json.decode(str));
|
||||
|
||||
String toRawJson() => json.encode(toJson());
|
||||
|
||||
factory SceneDetailsModel.fromJson(Map<String, dynamic> json) => SceneDetailsModel(
|
||||
id: json["id"],
|
||||
name: json["name"],
|
||||
status: json["status"],
|
||||
type: json["type"],
|
||||
actions: (json["actions"] as List)
|
||||
.map((x) => Action.fromJson(x))
|
||||
.where((x) => x != null)
|
||||
.toList()
|
||||
.cast<Action>(),
|
||||
conditions: json["conditions"] != null
|
||||
? (json["conditions"] as List).map((x) => Condition.fromJson(x)).toList()
|
||||
: null,
|
||||
decisionExpr: json["decisionExpr"],
|
||||
effectiveTime:
|
||||
json["effectiveTime"] != null ? EffectiveTime.fromJson(json["effectiveTime"]) : null,
|
||||
icon: json["iconUuid"] != null ? json["iconUuid"] ?? '' : '',
|
||||
showInDevice: json['showInHome'] != null ? json['showInHome'] ?? false : false);
|
||||
factory SceneDetailsModel.fromJson(Map<String, dynamic> json) =>
|
||||
SceneDetailsModel(
|
||||
id: json["uuid"] ?? json["id"],
|
||||
name: json["name"],
|
||||
status: json["status"],
|
||||
type: json["type"],
|
||||
actions: (json["actions"] as List)
|
||||
.map((x) => Action.fromJson(x))
|
||||
.where((x) => x != null)
|
||||
.toList()
|
||||
.cast<Action>(),
|
||||
conditions: json["conditions"] != null
|
||||
? (json["conditions"] as List)
|
||||
.map((x) => Condition.fromJson(x))
|
||||
.toList()
|
||||
: null,
|
||||
decisionExpr: json["decisionExpr"],
|
||||
effectiveTime: json["effectiveTime"] != null
|
||||
? EffectiveTime.fromJson(json["effectiveTime"])
|
||||
: null,
|
||||
icon: json["iconUuid"] != null ? json["iconUuid"] ?? '' : '',
|
||||
showInDevice:
|
||||
json['showInHome'] != null ? json['showInHome'] ?? false : false);
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
"id": id,
|
||||
@ -54,8 +60,9 @@ class SceneDetailsModel {
|
||||
"status": status,
|
||||
"type": type,
|
||||
"actions": List<dynamic>.from(actions.map((x) => x.toJson())),
|
||||
"conditions":
|
||||
conditions != null ? List<dynamic>.from(conditions!.map((x) => x.toJson())) : null,
|
||||
"conditions": conditions != null
|
||||
? List<dynamic>.from(conditions!.map((x) => x.toJson()))
|
||||
: null,
|
||||
"decisionExpr": decisionExpr,
|
||||
"effectiveTime": effectiveTime?.toJson(),
|
||||
};
|
||||
@ -116,7 +123,8 @@ class ExecutorProperty {
|
||||
this.delaySeconds,
|
||||
});
|
||||
|
||||
factory ExecutorProperty.fromJson(Map<String, dynamic> json) => ExecutorProperty(
|
||||
factory ExecutorProperty.fromJson(Map<String, dynamic> json) =>
|
||||
ExecutorProperty(
|
||||
functionCode: json["functionCode"] ?? '',
|
||||
functionValue: json["functionValue"] ?? '',
|
||||
delaySeconds: json["delaySeconds"] ?? 0,
|
||||
@ -142,7 +150,8 @@ class Condition {
|
||||
required this.expr,
|
||||
});
|
||||
|
||||
factory Condition.fromRawJson(String str) => Condition.fromJson(json.decode(str));
|
||||
factory Condition.fromRawJson(String str) =>
|
||||
Condition.fromJson(json.decode(str));
|
||||
|
||||
String toRawJson() => json.encode(toJson());
|
||||
|
||||
@ -200,7 +209,8 @@ class EffectiveTime {
|
||||
required this.loops,
|
||||
});
|
||||
|
||||
factory EffectiveTime.fromRawJson(String str) => EffectiveTime.fromJson(json.decode(str));
|
||||
factory EffectiveTime.fromRawJson(String str) =>
|
||||
EffectiveTime.fromJson(json.decode(str));
|
||||
|
||||
String toRawJson() => json.encode(toJson());
|
||||
|
||||
|
||||
@ -3,32 +3,40 @@ import 'dart:typed_data';
|
||||
|
||||
class ScenesModel {
|
||||
final String id;
|
||||
final String? sceneTuyaId;
|
||||
final String name;
|
||||
final String status;
|
||||
final String type;
|
||||
final String icon;
|
||||
final String? icon;
|
||||
|
||||
ScenesModel(
|
||||
{required this.id,
|
||||
this.sceneTuyaId,
|
||||
required this.name,
|
||||
required this.status,
|
||||
required this.type,
|
||||
required this.icon});
|
||||
this.icon});
|
||||
|
||||
factory ScenesModel.fromRawJson(String str) => ScenesModel.fromJson(json.decode(str));
|
||||
factory ScenesModel.fromRawJson(String str) =>
|
||||
ScenesModel.fromJson(json.decode(str));
|
||||
|
||||
String toRawJson() => json.encode(toJson());
|
||||
Uint8List get iconInBytes => base64Decode(icon);
|
||||
|
||||
factory ScenesModel.fromJson(Map<String, dynamic> json) => ScenesModel(
|
||||
id: json["id"],
|
||||
name: json["name"] ?? '',
|
||||
status: json["status"] ?? '',
|
||||
type: json["type"] ?? '',
|
||||
icon: json["icon"] ?? '');
|
||||
Uint8List get iconInBytes => base64Decode(icon ?? '');
|
||||
|
||||
factory ScenesModel.fromJson(Map<String, dynamic> json) {
|
||||
return ScenesModel(
|
||||
id: json["id"] ?? json["uuid"] ?? '', // Fallback to empty string if id is null
|
||||
sceneTuyaId: json["sceneTuyaId"] as String?, // Nullable
|
||||
name: json["name"] ?? '', // Fallback to empty string if name is null
|
||||
status:
|
||||
json["status"] ?? '', // Fallback to empty string if status is null
|
||||
type: json["type"] ?? '', // Fallback to empty string if type is null
|
||||
icon: json["icon"] as String?, // Nullable
|
||||
);
|
||||
}
|
||||
Map<String, dynamic> toJson() => {
|
||||
"id": id,
|
||||
"sceneTuyaId": sceneTuyaId ?? '',
|
||||
"name": name,
|
||||
"status": status,
|
||||
"type": type,
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import 'dart:convert';
|
||||
|
||||
class AutomationStatusUpdate {
|
||||
final String unitUuid;
|
||||
final String spaceUuid;
|
||||
final bool isEnable;
|
||||
|
||||
AutomationStatusUpdate({
|
||||
required this.unitUuid,
|
||||
required this.spaceUuid,
|
||||
required this.isEnable,
|
||||
});
|
||||
|
||||
@ -16,23 +16,23 @@ class AutomationStatusUpdate {
|
||||
|
||||
factory AutomationStatusUpdate.fromJson(Map<String, dynamic> json) =>
|
||||
AutomationStatusUpdate(
|
||||
unitUuid: json["unitUuid"],
|
||||
spaceUuid: json["spaceUuid"],
|
||||
isEnable: json["isEnable"],
|
||||
);
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
"unitUuid": unitUuid,
|
||||
"spaceUuid": spaceUuid,
|
||||
"isEnable": isEnable,
|
||||
};
|
||||
|
||||
factory AutomationStatusUpdate.fromMap(Map<String, dynamic> map) =>
|
||||
AutomationStatusUpdate(
|
||||
unitUuid: map["unitUuid"],
|
||||
spaceUuid: map["spaceUuid"],
|
||||
isEnable: map["isEnable"],
|
||||
);
|
||||
|
||||
Map<String, dynamic> toMap() => {
|
||||
"unitUuid": unitUuid,
|
||||
"spaceUuid": spaceUuid,
|
||||
"isEnable": isEnable,
|
||||
};
|
||||
}
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
|
||||
import 'package:syncrow_app/features/app_layout/model/space_model.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
|
||||
import 'package:syncrow_app/features/devices/model/room_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/subspace_model.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_bloc.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_event.dart';
|
||||
import 'package:syncrow_app/features/scene/widgets/scene_devices/scene_devices_body.dart';
|
||||
@ -26,20 +27,21 @@ class _SceneRoomsTabBarDevicesViewState
|
||||
extends State<SceneRoomsTabBarDevicesView>
|
||||
with SingleTickerProviderStateMixin {
|
||||
late final TabController _tabController;
|
||||
List<RoomModel>? rooms = [];
|
||||
List<SubSpaceModel>? rooms = [];
|
||||
late final SpaceModel selectedSpace;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
rooms = List.from(HomeCubit.getInstance().selectedSpace?.rooms ?? []);
|
||||
selectedSpace = HomeCubit.getInstance().selectedSpace!;
|
||||
rooms = List.from(HomeCubit.getInstance().selectedSpace?.subspaces ?? []);
|
||||
if (rooms != null) {
|
||||
if (rooms![0].id != '-1') {
|
||||
rooms?.insert(
|
||||
0,
|
||||
RoomModel(
|
||||
SubSpaceModel(
|
||||
name: 'All Devices',
|
||||
devices: DevicesCubit.getInstance().allDevices,
|
||||
id: '-1',
|
||||
type: SpaceType.Room,
|
||||
),
|
||||
);
|
||||
}
|
||||
@ -56,8 +58,10 @@ class _SceneRoomsTabBarDevicesViewState
|
||||
final value = _tabController.index;
|
||||
|
||||
/// select tab
|
||||
context.read<TabBarBloc>().add(
|
||||
TabChanged(selectedIndex: value, roomId: rooms?[value].id ?? ''));
|
||||
context.read<TabBarBloc>().add(TabChanged(
|
||||
selectedIndex: value,
|
||||
roomId: rooms?[value].id ?? '',
|
||||
unit: selectedSpace));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
|
||||
import 'package:syncrow_app/features/app_layout/model/community_model.dart';
|
||||
import 'package:syncrow_app/features/app_layout/model/space_model.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/scene_listview.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/scene_bloc/scene_bloc.dart';
|
||||
@ -21,32 +23,47 @@ class SceneView extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider(
|
||||
create: (BuildContext context) => SceneBloc()
|
||||
..add(LoadScenes(HomeCubit.getInstance().selectedSpace?.id ?? '', showInDevice: pageType))
|
||||
..add(LoadScenes(
|
||||
HomeCubit.getInstance().selectedSpace?.id ?? '',
|
||||
HomeCubit.getInstance().selectedSpace ??
|
||||
SpaceModel(
|
||||
id: '-1',
|
||||
name: '',
|
||||
community: Community(
|
||||
uuid: '-1',
|
||||
name: '',
|
||||
)),
|
||||
showInDevice: pageType))
|
||||
..add(LoadAutomation(HomeCubit.getInstance().selectedSpace?.id ?? '')),
|
||||
child: BlocBuilder<CreateSceneBloc, CreateSceneState>(
|
||||
builder: (context, state) {
|
||||
if (state is DeleteSceneSuccess) {
|
||||
if (state.success) {
|
||||
BlocProvider.of<SceneBloc>(context).add(LoadScenes(
|
||||
HomeCubit.getInstance().selectedSpace!.id!,HomeCubit.getInstance().selectedSpace!,
|
||||
showInDevice: pageType));
|
||||
BlocProvider.of<SceneBloc>(context).add(
|
||||
LoadScenes(HomeCubit.getInstance().selectedSpace!.id!, showInDevice: pageType));
|
||||
BlocProvider.of<SceneBloc>(context)
|
||||
.add(LoadAutomation(HomeCubit.getInstance().selectedSpace!.id!));
|
||||
LoadAutomation(HomeCubit.getInstance().selectedSpace!.id!));
|
||||
}
|
||||
}
|
||||
if (state is CreateSceneWithTasks) {
|
||||
if (state.success == true) {
|
||||
BlocProvider.of<SceneBloc>(context).add(LoadScenes(
|
||||
HomeCubit.getInstance().selectedSpace!.id!,HomeCubit.getInstance().selectedSpace!,
|
||||
showInDevice: pageType));
|
||||
BlocProvider.of<SceneBloc>(context).add(
|
||||
LoadScenes(HomeCubit.getInstance().selectedSpace!.id!, showInDevice: pageType));
|
||||
BlocProvider.of<SceneBloc>(context)
|
||||
.add(LoadAutomation(HomeCubit.getInstance().selectedSpace!.id!));
|
||||
context.read<SmartSceneSelectBloc>().add(const SmartSceneClearEvent());
|
||||
LoadAutomation(HomeCubit.getInstance().selectedSpace!.id!));
|
||||
context
|
||||
.read<SmartSceneSelectBloc>()
|
||||
.add(const SmartSceneClearEvent());
|
||||
}
|
||||
}
|
||||
return BlocListener<SceneBloc, SceneState>(
|
||||
listener: (context, state) {
|
||||
if (state is SceneTriggerSuccess) {
|
||||
context.showCustomSnackbar(
|
||||
message: 'Scene ${state.sceneName} triggered successfully!');
|
||||
message:
|
||||
'Scene ${state.sceneName} triggered successfully!');
|
||||
}
|
||||
},
|
||||
child: HomeCubit.getInstance().spaces?.isEmpty ?? true
|
||||
@ -83,25 +100,30 @@ class SceneView extends StatelessWidget {
|
||||
child: ListView(
|
||||
children: [
|
||||
Theme(
|
||||
data: ThemeData()
|
||||
.copyWith(dividerColor: Colors.transparent),
|
||||
data: ThemeData().copyWith(
|
||||
dividerColor: Colors.transparent),
|
||||
child: ExpansionTile(
|
||||
tilePadding: const EdgeInsets.symmetric(horizontal: 6),
|
||||
tilePadding:
|
||||
const EdgeInsets.symmetric(
|
||||
horizontal: 6),
|
||||
initiallyExpanded: true,
|
||||
iconColor: ColorsManager.grayColor,
|
||||
title: const BodyMedium(text: 'Tap to run routines'),
|
||||
title: const BodyMedium(
|
||||
text: 'Tap to run routines'),
|
||||
children: [
|
||||
scenes.isNotEmpty
|
||||
? SceneGrid(
|
||||
scenes: scenes,
|
||||
loadingSceneId: state.loadingSceneId,
|
||||
loadingSceneId:
|
||||
state.loadingSceneId,
|
||||
disablePlayButton: false,
|
||||
loadingStates:
|
||||
state.loadingStates, // Add this line
|
||||
loadingStates: state
|
||||
.loadingStates, // Add this line
|
||||
)
|
||||
: const Center(
|
||||
child: BodyMedium(
|
||||
text: 'No scenes have been added yet',
|
||||
text:
|
||||
'No scenes have been added yet',
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
@ -111,25 +133,30 @@ class SceneView extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
Theme(
|
||||
data: ThemeData()
|
||||
.copyWith(dividerColor: Colors.transparent),
|
||||
data: ThemeData().copyWith(
|
||||
dividerColor: Colors.transparent),
|
||||
child: ExpansionTile(
|
||||
initiallyExpanded: true,
|
||||
iconColor: ColorsManager.grayColor,
|
||||
tilePadding: const EdgeInsets.symmetric(horizontal: 6),
|
||||
title: const BodyMedium(text: 'Automation'),
|
||||
tilePadding:
|
||||
const EdgeInsets.symmetric(
|
||||
horizontal: 6),
|
||||
title: const BodyMedium(
|
||||
text: 'Automation'),
|
||||
children: [
|
||||
automationList.isNotEmpty
|
||||
? SceneGrid(
|
||||
scenes: automationList,
|
||||
loadingSceneId: state.loadingSceneId,
|
||||
loadingSceneId:
|
||||
state.loadingSceneId,
|
||||
disablePlayButton: true,
|
||||
loadingStates:
|
||||
state.loadingStates, // Add this line
|
||||
loadingStates: state
|
||||
.loadingStates, // Add this line
|
||||
)
|
||||
: const Center(
|
||||
child: BodyMedium(
|
||||
text: 'No automations have been added yet',
|
||||
text:
|
||||
'No automations have been added yet',
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
|
||||
@ -24,7 +24,7 @@ class DeleteRoutineButton extends StatelessWidget {
|
||||
if (state.success) {
|
||||
navigateToRoute(context, Routes.homeRoute);
|
||||
BlocProvider.of<SceneBloc>(context)
|
||||
.add(LoadScenes(HomeCubit.getInstance().selectedSpace!.id!));
|
||||
.add(LoadScenes(HomeCubit.getInstance().selectedSpace!.id!,HomeCubit.getInstance().selectedSpace!));
|
||||
BlocProvider.of<SceneBloc>(context).add(
|
||||
LoadAutomation(HomeCubit.getInstance().selectedSpace!.id!));
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@ import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/device_manager_bloc/device_manager_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/device_manager_bloc/device_manager_state.dart';
|
||||
import 'package:syncrow_app/features/devices/model/room_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/subspace_model.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_bloc.dart';
|
||||
import 'package:syncrow_app/features/scene/bloc/tab_change/tab_change_state.dart';
|
||||
import 'package:syncrow_app/features/scene/enum/create_scene_enum.dart';
|
||||
@ -24,7 +25,7 @@ class SceneDevicesBody extends StatelessWidget {
|
||||
}) : _tabController = tabController;
|
||||
|
||||
final TabController _tabController;
|
||||
final List<RoomModel>? rooms;
|
||||
final List<SubSpaceModel>? rooms;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -76,7 +77,7 @@ class SceneDevicesBody extends StatelessWidget {
|
||||
}
|
||||
|
||||
Widget _buildRoomTab(
|
||||
RoomModel room, BuildContext context, bool isAutomationDeviceStatus) {
|
||||
SubSpaceModel room, BuildContext context, bool isAutomationDeviceStatus) {
|
||||
return BlocBuilder<DeviceManagerBloc, DeviceManagerState>(
|
||||
builder: (context, state) {
|
||||
if (state.loading && state.devices == null) {
|
||||
|
||||
@ -38,8 +38,8 @@ class SceneItem extends StatelessWidget {
|
||||
onTap: () {
|
||||
context.read<SmartSceneSelectBloc>().add(const SmartSceneClearEvent());
|
||||
if (disablePlayButton == false) {
|
||||
BlocProvider.of<CreateSceneBloc>(context)
|
||||
.add(FetchSceneTasksEvent(sceneId: scene.id, isAutomation: false));
|
||||
BlocProvider.of<CreateSceneBloc>(context).add(
|
||||
FetchSceneTasksEvent(sceneId: scene.id, isAutomation: false));
|
||||
|
||||
/// the state to set the scene type must be after the fetch
|
||||
BlocProvider.of<CreateSceneBloc>(context)
|
||||
@ -73,22 +73,32 @@ class SceneItem extends StatelessWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
if (!disablePlayButton)
|
||||
if (!disablePlayButton && scene.iconInBytes != null && scene.iconInBytes.isNotEmpty)
|
||||
Image.memory(
|
||||
scene.iconInBytes,
|
||||
height: 32,
|
||||
width: 32,
|
||||
fit: BoxFit.fill,
|
||||
errorBuilder: (context, error, stackTrace) => Image.asset(
|
||||
Assets.assetsIconsLogo,
|
||||
height: 32,
|
||||
width: 32,
|
||||
fit: BoxFit.fill),
|
||||
),
|
||||
if (disablePlayButton || scene.iconInBytes == null || scene.iconInBytes.isEmpty)
|
||||
SvgPicture.asset(
|
||||
Assets.automationIcon,
|
||||
height: 32,
|
||||
width: 32,
|
||||
scene.iconInBytes,
|
||||
fit: BoxFit.fill,
|
||||
errorBuilder: (context, error, stackTrace) =>
|
||||
Image.asset(height: 32, width: 32, fit: BoxFit.fill, Assets.assetsIconsLogo),
|
||||
),
|
||||
if (disablePlayButton)
|
||||
SvgPicture.asset(height: 32, width: 32, fit: BoxFit.fill, Assets.automationIcon),
|
||||
disablePlayButton == false
|
||||
? IconButton(
|
||||
padding: EdgeInsets.zero,
|
||||
onPressed: () {
|
||||
context.read<SceneBloc>().add(SceneTrigger(scene.id, scene.name));
|
||||
context
|
||||
.read<SceneBloc>()
|
||||
.add(SceneTrigger(scene.id, scene.name));
|
||||
},
|
||||
icon: isLoading
|
||||
? const Center(
|
||||
@ -110,11 +120,15 @@ class SceneItem extends StatelessWidget {
|
||||
activeColor: ColorsManager.primaryColor,
|
||||
value: scene.status == 'enable' ? true : false,
|
||||
onChanged: (value) {
|
||||
context.read<SceneBloc>().add(UpdateAutomationStatus(
|
||||
automationStatusUpdate: AutomationStatusUpdate(
|
||||
isEnable: value,
|
||||
unitUuid: HomeCubit.getInstance().selectedSpace!.id!),
|
||||
automationId: scene.id));
|
||||
context.read<SceneBloc>().add(
|
||||
UpdateAutomationStatus(
|
||||
automationStatusUpdate:
|
||||
AutomationStatusUpdate(
|
||||
isEnable: value,
|
||||
spaceUuid: HomeCubit.getInstance()
|
||||
.selectedSpace!
|
||||
.id!),
|
||||
automationId: scene.id));
|
||||
},
|
||||
),
|
||||
],
|
||||
|
||||
@ -17,7 +17,7 @@ class SmartEnableTabRun extends StatelessWidget {
|
||||
width: double.infinity,
|
||||
child: BlocBuilder<SceneBloc, SceneState>(
|
||||
bloc: context.read<SceneBloc>()
|
||||
..add(LoadScenes(HomeCubit.getInstance().selectedSpace?.id ?? '')),
|
||||
..add(LoadScenes(HomeCubit.getInstance().selectedSpace?.id ?? '',HomeCubit.getInstance().selectedSpace!)),
|
||||
builder: (context, state) {
|
||||
if (state is SceneLoading) {
|
||||
return const Align(
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/app_layout/model/community_model.dart';
|
||||
import 'package:syncrow_app/features/app_layout/model/space_model.dart';
|
||||
import 'package:syncrow_app/features/app_layout/view/app_layout.dart';
|
||||
import 'package:syncrow_app/features/auth/view/otp_view.dart';
|
||||
import 'package:syncrow_app/features/auth/view/login_view.dart';
|
||||
@ -84,9 +86,18 @@ class Router {
|
||||
DeviceManagerBloc()..add(FetchAllDevices()),
|
||||
),
|
||||
BlocProvider(
|
||||
create: (BuildContext context) => TabBarBloc(
|
||||
context.read<DeviceManagerBloc>())
|
||||
..add(const TabChanged(selectedIndex: 0, roomId: '-1')),
|
||||
create: (BuildContext context) =>
|
||||
TabBarBloc(context.read<DeviceManagerBloc>())
|
||||
..add(TabChanged(
|
||||
selectedIndex: 0,
|
||||
roomId: '-1',
|
||||
unit: SpaceModel(
|
||||
id: '-1',
|
||||
name: '',
|
||||
community: Community(
|
||||
uuid: '-1',
|
||||
name: '',
|
||||
)))),
|
||||
),
|
||||
],
|
||||
child: const SceneRoomsTabBarDevicesView(),
|
||||
|
||||
@ -53,17 +53,26 @@ abstract class ApiEndpoints {
|
||||
//POST
|
||||
static const String addUnit = '/unit';
|
||||
static const String addUnitToUser = '/unit/user';
|
||||
static const String verifyInvitationCode =
|
||||
'/user/{userUuid}/spaces/verify-code';
|
||||
|
||||
//GET
|
||||
static const String unitByUuid = '/unit/';
|
||||
static const String unitChild = '/unit/child/';
|
||||
static const String listSubspace =
|
||||
'/communities/{communityUuid}/spaces/{spaceUuid}/subspaces';
|
||||
static const String unitParent = '/unit/parent/{unitUuid}';
|
||||
static const String unitUser = '/unit/user/';
|
||||
static const String invitationCode = '/unit/{unitUuid}/invitation-code';
|
||||
static const String verifyInvitationCode = '/unit/user/verify-code';
|
||||
static const String invitationCode =
|
||||
'/communities/{communityUuid}/spaces/{unitUuid}/invitation-code';
|
||||
|
||||
//PUT
|
||||
static const String renameUnit = '/unit/{unitUuid}';
|
||||
|
||||
//Subspace Module
|
||||
//POST
|
||||
static const String addSubSpace =
|
||||
'/communities/{communityUuid}/spaces/{spaceUuid}/subspaces';
|
||||
|
||||
///Room Module
|
||||
//POST
|
||||
static const String addRoom = '/room';
|
||||
@ -75,6 +84,12 @@ abstract class ApiEndpoints {
|
||||
//PUT
|
||||
static const String renameRoom = '/room/{roomUuid}';
|
||||
|
||||
//SPACE Module
|
||||
//GET
|
||||
static const String userSpaces = '/user/{userUuid}/spaces';
|
||||
static const String spaceDevices =
|
||||
'/communities/{communityUuid}/spaces/{spaceUuid}/devices';
|
||||
|
||||
///Group Module
|
||||
//POST
|
||||
static const String addGroup = '/group';
|
||||
@ -101,12 +116,15 @@ abstract class ApiEndpoints {
|
||||
static const String openDoorLock = '/door-lock/open/{doorLockUuid}';
|
||||
|
||||
//GET
|
||||
static const String deviceByRoom = '/device/room';
|
||||
static const String deviceByRoom =
|
||||
'/communities/{communityUuid}/spaces/{spaceUuid}/subspaces/{subSpaceUuid}/devices';
|
||||
static const String deviceByUuid = '/device/{deviceUuid}';
|
||||
static const String deviceFunctions = '/device/{deviceUuid}/functions';
|
||||
static const String gatewayApi = '/device/gateway/{gatewayUuid}/devices';
|
||||
static const String deviceFunctionsStatus = '/device/{deviceUuid}/functions/status';
|
||||
static const String powerClamp = '/device/{powerClampUuid}/power-clamp/status';
|
||||
static const String deviceFunctionsStatus =
|
||||
'/device/{deviceUuid}/functions/status';
|
||||
static const String powerClamp =
|
||||
'/device/{powerClampUuid}/power-clamp/status';
|
||||
|
||||
///Device Permission Module
|
||||
//POST
|
||||
@ -116,18 +134,20 @@ abstract class ApiEndpoints {
|
||||
//PUT
|
||||
static const String editDevicePermission = '/device-permission/edit/{userId}';
|
||||
|
||||
static const String assignDeviceToRoom = '/device/room';
|
||||
static const String assignDeviceToRoom =
|
||||
'/communities/{communityUuid}/spaces/{spaceUuid}/subspaces/{subSpaceUuid}/devices/{deviceUuid}';
|
||||
|
||||
/// Scene & Automation API ////////////////////
|
||||
/// POST
|
||||
static const String createScene = '/scene/tap-to-run';
|
||||
static const String triggerScene = '/scene/tap-to-run/trigger/{sceneId}';
|
||||
static const String triggerScene = '/scene/tap-to-run/{sceneId}/trigger';
|
||||
static const String createAutomation = '/automation';
|
||||
|
||||
/// GET
|
||||
static const String getUnitScenes = '/scene/tap-to-run/{unitUuid}';
|
||||
static const String getUnitScenes =
|
||||
'/communities/{communityUuid}/spaces/{spaceUuid}/scenes';
|
||||
|
||||
static const String getScene = '/scene/tap-to-run/details/{sceneId}';
|
||||
static const String getScene = '/scene/tap-to-run/{sceneId}';
|
||||
static const String getIconScene = '/scene/icon';
|
||||
|
||||
static const String getUnitAutomation = '/automation/{unitUuid}';
|
||||
@ -144,10 +164,9 @@ abstract class ApiEndpoints {
|
||||
'/automation/status/{automationId}';
|
||||
|
||||
/// DELETE
|
||||
static const String deleteScene = '/scene/tap-to-run/{unitUuid}/{sceneId}';
|
||||
static const String deleteScene = '/scene/tap-to-run/{sceneId}';
|
||||
|
||||
static const String deleteAutomation =
|
||||
'/automation/{unitUuid}/{automationId}';
|
||||
static const String deleteAutomation = '/automation/{automationId}';
|
||||
|
||||
//////////////////////Door Lock //////////////////////
|
||||
//online
|
||||
|
||||
@ -65,6 +65,7 @@ class DevicesAPI {
|
||||
showServerMessage: false,
|
||||
expectedResponseModel: (json) => DevicesCategoryModel.fromJsonList(json),
|
||||
);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@ -142,23 +143,41 @@ class DevicesAPI {
|
||||
return response;
|
||||
}
|
||||
|
||||
static Future<List<DeviceModel>> getDevicesByRoomId(String roomId) async {
|
||||
final response = await _httpService.get(
|
||||
path: ApiEndpoints.deviceByRoom,
|
||||
queryParameters: {"roomUuid": roomId},
|
||||
showServerMessage: false,
|
||||
expectedResponseModel: (json) {
|
||||
if (json == null || json.isEmpty || json == []) {
|
||||
return <DeviceModel>[];
|
||||
}
|
||||
List<DeviceModel> devices = [];
|
||||
for (var device in json) {
|
||||
devices.add(DeviceModel.fromJson(device));
|
||||
}
|
||||
return devices;
|
||||
},
|
||||
);
|
||||
return response;
|
||||
static Future<List<DeviceModel>> getDevicesByRoomId({
|
||||
required String communityUuid,
|
||||
required String spaceUuid,
|
||||
required String roomId,
|
||||
}) async {
|
||||
try {
|
||||
final String path = ApiEndpoints.deviceByRoom
|
||||
.replaceAll('{communityUuid}', communityUuid)
|
||||
.replaceAll('{spaceUuid}', spaceUuid)
|
||||
.replaceAll('{subSpaceUuid}', roomId);
|
||||
|
||||
final response = await _httpService.get(
|
||||
path: path,
|
||||
showServerMessage: false,
|
||||
expectedResponseModel: (json) {
|
||||
final data = json['data'];
|
||||
|
||||
if (data == null || data.isEmpty) {
|
||||
return <DeviceModel>[];
|
||||
}
|
||||
if (json == null || json.isEmpty || json == []) {
|
||||
return <DeviceModel>[];
|
||||
}
|
||||
return data
|
||||
.map<DeviceModel>((device) => DeviceModel.fromJson(device))
|
||||
.toList();
|
||||
},
|
||||
);
|
||||
|
||||
return response;
|
||||
} catch (e) {
|
||||
// Log the error if needed
|
||||
// Return an empty list in case of error
|
||||
return <DeviceModel>[];
|
||||
}
|
||||
}
|
||||
|
||||
static Future<List<DeviceModel>> getDevicesByGatewayId(
|
||||
|
||||
@ -4,7 +4,8 @@ import 'package:syncrow_app/services/api/http_service.dart';
|
||||
class HomeCreation {
|
||||
static final HTTPService _httpService = HTTPService();
|
||||
|
||||
static Future<Map<String, dynamic>> createCommunity(Map<String, String> body) async {
|
||||
static Future<Map<String, dynamic>> createCommunity(
|
||||
Map<String, String> body) async {
|
||||
try {
|
||||
final response = await _httpService.post(
|
||||
path: ApiEndpoints.addCommunity,
|
||||
@ -20,7 +21,8 @@ class HomeCreation {
|
||||
}
|
||||
}
|
||||
|
||||
static Future<Map<String, dynamic>> assignUserToCommunity(Map<String, String> body) async {
|
||||
static Future<Map<String, dynamic>> assignUserToCommunity(
|
||||
Map<String, String> body) async {
|
||||
try {
|
||||
final response = await _httpService.post(
|
||||
path: ApiEndpoints.addCommunityToUser,
|
||||
@ -36,7 +38,8 @@ class HomeCreation {
|
||||
}
|
||||
}
|
||||
|
||||
static Future<Map<String, dynamic>> createBuilding(Map<String, String> body) async {
|
||||
static Future<Map<String, dynamic>> createBuilding(
|
||||
Map<String, String> body) async {
|
||||
try {
|
||||
final response = await _httpService.post(
|
||||
path: ApiEndpoints.addBuilding,
|
||||
@ -52,7 +55,8 @@ class HomeCreation {
|
||||
}
|
||||
}
|
||||
|
||||
static Future<Map<String, dynamic>> assignUserToBuilding(Map<String, String> body) async {
|
||||
static Future<Map<String, dynamic>> assignUserToBuilding(
|
||||
Map<String, String> body) async {
|
||||
try {
|
||||
final response = await _httpService.post(
|
||||
path: ApiEndpoints.addBuildingToUser,
|
||||
@ -68,7 +72,8 @@ class HomeCreation {
|
||||
}
|
||||
}
|
||||
|
||||
static Future<Map<String, dynamic>> createFloor(Map<String, String> body) async {
|
||||
static Future<Map<String, dynamic>> createFloor(
|
||||
Map<String, String> body) async {
|
||||
try {
|
||||
final response = await _httpService.post(
|
||||
path: ApiEndpoints.addFloor,
|
||||
@ -84,7 +89,8 @@ class HomeCreation {
|
||||
}
|
||||
}
|
||||
|
||||
static Future<Map<String, dynamic>> assignUserToFloor(Map<String, String> body) async {
|
||||
static Future<Map<String, dynamic>> assignUserToFloor(
|
||||
Map<String, String> body) async {
|
||||
try {
|
||||
final response = await _httpService.post(
|
||||
path: ApiEndpoints.addBuildingToUser,
|
||||
@ -100,7 +106,8 @@ class HomeCreation {
|
||||
}
|
||||
}
|
||||
|
||||
static Future<Map<String, dynamic>> createUnit(Map<String, String> body) async {
|
||||
static Future<Map<String, dynamic>> createUnit(
|
||||
Map<String, String> body) async {
|
||||
try {
|
||||
final response = await _httpService.post(
|
||||
path: ApiEndpoints.addUnit,
|
||||
@ -116,7 +123,8 @@ class HomeCreation {
|
||||
}
|
||||
}
|
||||
|
||||
static Future<Map<String, dynamic>> assignUserToUnit(Map<String, String> body) async {
|
||||
static Future<Map<String, dynamic>> assignUserToUnit(
|
||||
Map<String, String> body) async {
|
||||
try {
|
||||
final response = await _httpService.post(
|
||||
path: ApiEndpoints.addUnitToUser,
|
||||
@ -132,10 +140,17 @@ class HomeCreation {
|
||||
}
|
||||
}
|
||||
|
||||
static Future<Map<String, dynamic>> createRoom(Map<String, String> body) async {
|
||||
static Future<Map<String, dynamic>> createRoom({
|
||||
required String communityId,
|
||||
required String spaceId,
|
||||
required Map<String, String> body,
|
||||
}) async {
|
||||
try {
|
||||
final fullPath = ApiEndpoints.addSubSpace
|
||||
.replaceAll('{communityUuid}', communityId)
|
||||
.replaceAll('{spaceUuid}', spaceId);
|
||||
final response = await _httpService.post(
|
||||
path: ApiEndpoints.addRoom,
|
||||
path: fullPath,
|
||||
body: body,
|
||||
showServerMessage: false,
|
||||
expectedResponseModel: (json) {
|
||||
@ -148,7 +163,8 @@ class HomeCreation {
|
||||
}
|
||||
}
|
||||
|
||||
static Future<Map<String, dynamic>> assignUserToRoom(Map<String, String> body) async {
|
||||
static Future<Map<String, dynamic>> assignUserToRoom(
|
||||
Map<String, String> body) async {
|
||||
try {
|
||||
final response = await _httpService.post(
|
||||
path: ApiEndpoints.addRoomToUser,
|
||||
|
||||
@ -28,24 +28,46 @@ class HomeManagementAPI {
|
||||
|
||||
static Future<List<DeviceModel>> fetchDevicesByUnitId() async {
|
||||
List<DeviceModel> list = [];
|
||||
await _httpService.get(
|
||||
path: ApiEndpoints.getDevicesByUnitId.replaceAll(
|
||||
"{unitUuid}", HomeCubit.getInstance().selectedSpace?.id ?? ''),
|
||||
|
||||
try {
|
||||
// Retrieve selected space details
|
||||
final selectedSpace = HomeCubit.getInstance().selectedSpace;
|
||||
final communityUuid = selectedSpace?.community?.uuid ?? '';
|
||||
final spaceUuid = selectedSpace?.id ?? '';
|
||||
|
||||
// Ensure both placeholders are replaced
|
||||
final path = ApiEndpoints.spaceDevices
|
||||
.replaceAll('{communityUuid}', communityUuid)
|
||||
.replaceAll('{spaceUuid}', spaceUuid);
|
||||
await _httpService.get(
|
||||
path: path,
|
||||
showServerMessage: false,
|
||||
expectedResponseModel: (json) {
|
||||
json.forEach((value) {
|
||||
list.add(DeviceModel.fromJson(value));
|
||||
});
|
||||
});
|
||||
if (json['data'] != null) {
|
||||
json['data'].forEach((value) {
|
||||
list.add(DeviceModel.fromJson(value));
|
||||
});
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// Debugging: Log successful fetch
|
||||
} catch (e) {
|
||||
// Log the error for debugging
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
static Future<Map<String, dynamic>> assignDeviceToRoom(
|
||||
Map<String, String> body) async {
|
||||
static Future<Map<String, dynamic>> assignDeviceToRoom(String communityId,
|
||||
String spaceId, String subSpaceId, String deviceId) async {
|
||||
try {
|
||||
final response = await _httpService.put(
|
||||
path: ApiEndpoints.assignDeviceToRoom,
|
||||
body: body,
|
||||
final response = await _httpService.post(
|
||||
path: ApiEndpoints.assignDeviceToRoom
|
||||
.replaceAll('{communityUuid}', communityId)
|
||||
.replaceAll('{spaceUuid}', spaceId)
|
||||
.replaceAll('{subSpaceUuid}', subSpaceId)
|
||||
.replaceAll('{deviceUuid}', deviceId),
|
||||
expectedResponseModel: (json) {
|
||||
return json;
|
||||
},
|
||||
@ -55,4 +77,24 @@ class HomeManagementAPI {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
static Future<Map<String, dynamic>> unAssignDeviceToRoom(String communityId,
|
||||
String spaceId, String subSpaceId, String deviceId) async {
|
||||
try {
|
||||
final response = await _httpService.delete(
|
||||
path: ApiEndpoints.assignDeviceToRoom
|
||||
.replaceAll('{communityUuid}', communityId)
|
||||
.replaceAll('{spaceUuid}', spaceId)
|
||||
.replaceAll('{subSpaceUuid}', subSpaceId)
|
||||
.replaceAll('{deviceUuid}', deviceId),
|
||||
expectedResponseModel: (json) {
|
||||
return json;
|
||||
},
|
||||
);
|
||||
return response;
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:syncrow_app/features/scene/model/create_automation_model.dart';
|
||||
import 'package:syncrow_app/features/scene/model/create_scene_model.dart';
|
||||
import 'package:syncrow_app/features/scene/model/icon_model.dart';
|
||||
@ -11,7 +13,8 @@ class SceneApi {
|
||||
static final HTTPService _httpService = HTTPService();
|
||||
|
||||
//create scene
|
||||
static Future<Map<String, dynamic>> createScene(CreateSceneModel createSceneModel) async {
|
||||
static Future<Map<String, dynamic>> createScene(
|
||||
CreateSceneModel createSceneModel) async {
|
||||
try {
|
||||
final response = await _httpService.post(
|
||||
path: ApiEndpoints.createScene,
|
||||
@ -47,15 +50,21 @@ class SceneApi {
|
||||
|
||||
//get scene by unit id
|
||||
|
||||
static Future<List<ScenesModel>> getScenesByUnitId(String unitId, {showInDevice = false}) async {
|
||||
static Future<List<ScenesModel>> getScenesByUnitId(
|
||||
String unitId, String communityId,
|
||||
{showInDevice = false}) async {
|
||||
try {
|
||||
final response = await _httpService.get(
|
||||
path: ApiEndpoints.getUnitScenes.replaceAll('{unitUuid}', unitId),
|
||||
path: ApiEndpoints.getUnitScenes
|
||||
.replaceAll('{spaceUuid}', unitId)
|
||||
.replaceAll('{communityUuid}', communityId),
|
||||
queryParameters: {'showInHomePage': showInDevice},
|
||||
showServerMessage: false,
|
||||
expectedResponseModel: (json) {
|
||||
final scenesJson = json['data'] as List;
|
||||
|
||||
List<ScenesModel> scenes = [];
|
||||
for (var scene in json) {
|
||||
for (var scene in scenesJson) {
|
||||
scenes.add(ScenesModel.fromJson(scene));
|
||||
}
|
||||
return scenes;
|
||||
@ -102,10 +111,12 @@ class SceneApi {
|
||||
}
|
||||
|
||||
//automation details
|
||||
static Future<SceneDetailsModel> getAutomationDetails(String automationId) async {
|
||||
static Future<SceneDetailsModel> getAutomationDetails(
|
||||
String automationId) async {
|
||||
try {
|
||||
final response = await _httpService.get(
|
||||
path: ApiEndpoints.getAutomationDetails.replaceAll('{automationId}', automationId),
|
||||
path: ApiEndpoints.getAutomationDetails
|
||||
.replaceAll('{automationId}', automationId),
|
||||
showServerMessage: false,
|
||||
expectedResponseModel: (json) => SceneDetailsModel.fromJson(json),
|
||||
);
|
||||
@ -116,11 +127,12 @@ class SceneApi {
|
||||
}
|
||||
|
||||
//updateAutomationStatus
|
||||
static Future<bool> updateAutomationStatus(
|
||||
String automationId, AutomationStatusUpdate createAutomationEnable) async {
|
||||
static Future<bool> updateAutomationStatus(String automationId,
|
||||
AutomationStatusUpdate createAutomationEnable) async {
|
||||
try {
|
||||
final response = await _httpService.put(
|
||||
path: ApiEndpoints.updateAutomationStatus.replaceAll('{automationId}', automationId),
|
||||
path: ApiEndpoints.updateAutomationStatus
|
||||
.replaceAll('{automationId}', automationId),
|
||||
body: createAutomationEnable.toMap(),
|
||||
expectedResponseModel: (json) => json['success'],
|
||||
);
|
||||
@ -135,7 +147,13 @@ class SceneApi {
|
||||
final response = await _httpService.get(
|
||||
path: ApiEndpoints.getScene.replaceAll('{sceneId}', sceneId),
|
||||
showServerMessage: false,
|
||||
expectedResponseModel: (json) => SceneDetailsModel.fromJson(json),
|
||||
expectedResponseModel: (json) {
|
||||
if (json != null && json['data'] != null) {
|
||||
return SceneDetailsModel.fromJson(json['data']);
|
||||
} else {
|
||||
throw Exception('Data field is null');
|
||||
}
|
||||
},
|
||||
);
|
||||
return response;
|
||||
} catch (e) {
|
||||
@ -163,7 +181,8 @@ class SceneApi {
|
||||
try {
|
||||
final response = await _httpService.put(
|
||||
path: ApiEndpoints.updateScene.replaceAll('{sceneId}', sceneId),
|
||||
body: createSceneModel.toJson(sceneId.isNotEmpty == true ? sceneId : null),
|
||||
body: createSceneModel
|
||||
.toJson(sceneId.isNotEmpty == true ? sceneId : null),
|
||||
expectedResponseModel: (json) {
|
||||
return json;
|
||||
},
|
||||
@ -175,11 +194,14 @@ class SceneApi {
|
||||
}
|
||||
|
||||
//update automation
|
||||
static updateAutomation(CreateAutomationModel createAutomationModel, String automationId) async {
|
||||
static updateAutomation(
|
||||
CreateAutomationModel createAutomationModel, String automationId) async {
|
||||
try {
|
||||
final response = await _httpService.put(
|
||||
path: ApiEndpoints.updateAutomation.replaceAll('{automationId}', automationId),
|
||||
body: createAutomationModel.toJson(automationId.isNotEmpty == true ? automationId : null),
|
||||
path: ApiEndpoints.updateAutomation
|
||||
.replaceAll('{automationId}', automationId),
|
||||
body: createAutomationModel
|
||||
.toJson(automationId.isNotEmpty == true ? automationId : null),
|
||||
expectedResponseModel: (json) {
|
||||
return json;
|
||||
},
|
||||
@ -192,12 +214,10 @@ class SceneApi {
|
||||
|
||||
//delete Scene
|
||||
|
||||
static Future<bool> deleteScene({required String unitUuid, required String sceneId}) async {
|
||||
static Future<bool> deleteScene({required String sceneId}) async {
|
||||
try {
|
||||
final response = await _httpService.delete(
|
||||
path: ApiEndpoints.deleteScene
|
||||
.replaceAll('{sceneId}', sceneId)
|
||||
.replaceAll('{unitUuid}', unitUuid),
|
||||
path: ApiEndpoints.deleteScene.replaceAll('{sceneId}', sceneId),
|
||||
showServerMessage: false,
|
||||
expectedResponseModel: (json) => json['statusCode'] == 200,
|
||||
);
|
||||
@ -213,8 +233,7 @@ class SceneApi {
|
||||
try {
|
||||
final response = await _httpService.delete(
|
||||
path: ApiEndpoints.deleteAutomation
|
||||
.replaceAll('{automationId}', automationId)
|
||||
.replaceAll('{unitUuid}', unitUuid),
|
||||
.replaceAll('{automationId}', automationId),
|
||||
showServerMessage: false,
|
||||
expectedResponseModel: (json) => json['statusCode'] == 200,
|
||||
);
|
||||
|
||||
@ -1,55 +1,89 @@
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import 'package:syncrow_app/features/app_layout/model/space_model.dart';
|
||||
import 'package:syncrow_app/features/auth/model/user_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/room_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/subspace_model.dart';
|
||||
import 'package:syncrow_app/services/api/api_links_endpoints.dart';
|
||||
import 'package:syncrow_app/services/api/http_service.dart';
|
||||
|
||||
class SpacesAPI {
|
||||
static final HTTPService _httpService = HTTPService();
|
||||
|
||||
static Future<List<SpaceModel>> getUnitsByUserId() async {
|
||||
var uuid = await const FlutterSecureStorage().read(key: UserModel.userUuidKey);
|
||||
final response = await _httpService.get(
|
||||
path: "${ApiEndpoints.unitUser}$uuid",
|
||||
showServerMessage: false,
|
||||
expectedResponseModel: (json) => SpaceModel.fromJsonList(json),
|
||||
);
|
||||
return response;
|
||||
static Future<List<SpaceModel>> getSpacesByUserId() async {
|
||||
try {
|
||||
var uuid =
|
||||
await const FlutterSecureStorage().read(key: UserModel.userUuidKey);
|
||||
if (uuid == null) throw Exception("User UUID is missing");
|
||||
|
||||
final path = ApiEndpoints.userSpaces.replaceFirst('{userUuid}', uuid);
|
||||
final response = await _httpService.get(
|
||||
path: path,
|
||||
showServerMessage: false,
|
||||
expectedResponseModel: (json) {
|
||||
return SpaceModel.fromJsonList(json['data']);
|
||||
},
|
||||
);
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
rethrow; // Rethrow the error to be caught by `fetchUnitsByUserId`
|
||||
}
|
||||
}
|
||||
|
||||
static Future<List<RoomModel>> getRoomsBySpaceId(String unitId) async {
|
||||
static Future<List<SubSpaceModel>> getSubSpaceBySpaceId(
|
||||
String communityId, String spaceId) async {
|
||||
try {
|
||||
// Construct the API path
|
||||
final path = ApiEndpoints.listSubspace
|
||||
.replaceFirst('{communityUuid}', communityId)
|
||||
.replaceFirst('{spaceUuid}', spaceId);
|
||||
|
||||
final response = await _httpService.get(
|
||||
path: path,
|
||||
queryParameters: {"page": 1, "pageSize": 10},
|
||||
showServerMessage: false,
|
||||
expectedResponseModel: (json) {
|
||||
List<SubSpaceModel> rooms = [];
|
||||
if (json['data'] != null) {
|
||||
for (var subspace in json['data']) {
|
||||
rooms.add(SubSpaceModel.fromJson(subspace));
|
||||
}
|
||||
} else {
|
||||
print("Warning: 'data' key is missing or null in response JSON.");
|
||||
}
|
||||
return rooms;
|
||||
},
|
||||
);
|
||||
|
||||
return response;
|
||||
} catch (error, stackTrace) {
|
||||
return []; // Return an empty list if there's an error
|
||||
}
|
||||
}
|
||||
|
||||
static Future<String> generateInvitationCode(
|
||||
String unitId, String communityId) async {
|
||||
final response = await _httpService.get(
|
||||
path: "${ApiEndpoints.unitChild}$unitId",
|
||||
queryParameters: {"page": 1, "pageSize": 10},
|
||||
path: ApiEndpoints.invitationCode
|
||||
.replaceAll('{unitUuid}', unitId)
|
||||
.replaceAll('{communityUuid}', communityId),
|
||||
showServerMessage: false,
|
||||
expectedResponseModel: (json) {
|
||||
List<RoomModel> rooms = [];
|
||||
for (var room in json['children']) {
|
||||
rooms.add(RoomModel.fromJson(room));
|
||||
if (json != null && json['data'] != null) {
|
||||
return json['data']['invitationCode'];
|
||||
} else {
|
||||
throw Exception('Data field is null');
|
||||
}
|
||||
return rooms;
|
||||
},
|
||||
);
|
||||
return response;
|
||||
}
|
||||
|
||||
static Future<String> generateInvitationCode(
|
||||
String unitId,
|
||||
) async {
|
||||
final response = await _httpService.get(
|
||||
path: ApiEndpoints.invitationCode.replaceAll('{unitUuid}', unitId),
|
||||
showServerMessage: false,
|
||||
expectedResponseModel: (json) => json['invitationCode'],
|
||||
);
|
||||
return response;
|
||||
}
|
||||
|
||||
static Future<bool> joinUnit(
|
||||
String userId,
|
||||
Map<String, String> body,
|
||||
) async {
|
||||
final response = await _httpService.post(
|
||||
path: ApiEndpoints.verifyInvitationCode,
|
||||
path: ApiEndpoints.verifyInvitationCode.replaceAll('{userUuid}', userId),
|
||||
showServerMessage: false,
|
||||
body: body,
|
||||
expectedResponseModel: (json) => json['success'],
|
||||
|
||||
Reference in New Issue
Block a user