mirror of
https://github.com/SyncrowIOT/web.git
synced 2026-03-11 10:11:45 +00:00
Compare commits
21 Commits
bugfix/com
...
bugfix/SP-
| Author | SHA1 | Date | |
|---|---|---|---|
| d423a3eb59 | |||
| 9bddd151bb | |||
| 0b628c85a5 | |||
| 7ee335ab1a | |||
| d5ad06335b | |||
| d9ef5b4574 | |||
| c58f2eb24e | |||
| 4e94d2df89 | |||
| 2f5c5d7da1 | |||
| ff4ce8ed01 | |||
| 1aa6b78fb4 | |||
| e003d9b8b3 | |||
| 76e44c8910 | |||
| 02c788d03a | |||
| 938f8c6b51 | |||
| 3ce9a313f7 | |||
| b732b0b957 | |||
| fb6b922df4 | |||
| ce6e7700bc | |||
| 8d388ac482 | |||
| 875787919e |
@ -1,28 +0,0 @@
|
|||||||
import 'dart:async';
|
|
||||||
|
|
||||||
import 'package:bloc/bloc.dart';
|
|
||||||
import 'package:equatable/equatable.dart';
|
|
||||||
|
|
||||||
part 'switch_tabs_event.dart';
|
|
||||||
part 'switch_tabs_state.dart';
|
|
||||||
|
|
||||||
class SwitchTabsBloc extends Bloc<SwitchTabsEvent, SwitchTabsState> {
|
|
||||||
SwitchTabsBloc() : super(SwitchTabsInitial()) {
|
|
||||||
on<TriggerSwitchTabsEvent>(_switchTab);
|
|
||||||
on<CreateNewRoutineViewEvent>(_newRoutineView);
|
|
||||||
}
|
|
||||||
|
|
||||||
FutureOr<void> _switchTab(
|
|
||||||
TriggerSwitchTabsEvent event,
|
|
||||||
Emitter<SwitchTabsState> emit,
|
|
||||||
) {
|
|
||||||
emit(SelectedTabState(event.isRoutineView));
|
|
||||||
}
|
|
||||||
|
|
||||||
FutureOr<void> _newRoutineView(
|
|
||||||
CreateNewRoutineViewEvent event,
|
|
||||||
Emitter<SwitchTabsState> emit,
|
|
||||||
) {
|
|
||||||
emit(ShowCreateRoutineState(event.showCreateNewRoutineView));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,21 +0,0 @@
|
|||||||
part of 'switch_tabs_bloc.dart';
|
|
||||||
|
|
||||||
sealed class SwitchTabsEvent extends Equatable {
|
|
||||||
const SwitchTabsEvent();
|
|
||||||
}
|
|
||||||
|
|
||||||
class TriggerSwitchTabsEvent extends SwitchTabsEvent {
|
|
||||||
final bool isRoutineView;
|
|
||||||
const TriggerSwitchTabsEvent(this.isRoutineView);
|
|
||||||
|
|
||||||
@override
|
|
||||||
List<Object?> get props => [isRoutineView];
|
|
||||||
}
|
|
||||||
|
|
||||||
class CreateNewRoutineViewEvent extends SwitchTabsEvent {
|
|
||||||
final bool showCreateNewRoutineView;
|
|
||||||
const CreateNewRoutineViewEvent(this.showCreateNewRoutineView);
|
|
||||||
|
|
||||||
@override
|
|
||||||
List<Object?> get props => [showCreateNewRoutineView];
|
|
||||||
}
|
|
||||||
@ -1,26 +0,0 @@
|
|||||||
part of 'switch_tabs_bloc.dart';
|
|
||||||
|
|
||||||
sealed class SwitchTabsState extends Equatable {
|
|
||||||
const SwitchTabsState();
|
|
||||||
}
|
|
||||||
|
|
||||||
final class SwitchTabsInitial extends SwitchTabsState {
|
|
||||||
@override
|
|
||||||
List<Object> get props => [];
|
|
||||||
}
|
|
||||||
|
|
||||||
class SelectedTabState extends SwitchTabsState {
|
|
||||||
final bool selectedTab;
|
|
||||||
const SelectedTabState(this.selectedTab);
|
|
||||||
|
|
||||||
@override
|
|
||||||
List<Object?> get props => [selectedTab];
|
|
||||||
}
|
|
||||||
|
|
||||||
class ShowCreateRoutineState extends SwitchTabsState {
|
|
||||||
final bool showCreateRoutine;
|
|
||||||
const ShowCreateRoutineState(this.showCreateRoutine);
|
|
||||||
|
|
||||||
@override
|
|
||||||
List<Object?> get props => [showCreateRoutine];
|
|
||||||
}
|
|
||||||
@ -1,9 +1,9 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/all_devices/bloc/device_mgmt_bloc/device_managment_bloc.dart';
|
import 'package:syncrow_web/pages/device_managment/all_devices/bloc/device_mgmt_bloc/device_managment_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/all_devices/bloc/switch_tabs/switch_tabs_bloc.dart';
|
|
||||||
import 'package:syncrow_web/pages/device_managment/all_devices/widgets/device_managment_body.dart';
|
import 'package:syncrow_web/pages/device_managment/all_devices/widgets/device_managment_body.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/shared/navigate_home_grid_view.dart';
|
import 'package:syncrow_web/pages/device_managment/shared/navigate_home_grid_view.dart';
|
||||||
|
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/routiens/view/create_new_routine_view.dart';
|
import 'package:syncrow_web/pages/routiens/view/create_new_routine_view.dart';
|
||||||
import 'package:syncrow_web/pages/routiens/view/routines_view.dart';
|
import 'package:syncrow_web/pages/routiens/view/routines_view.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
@ -18,10 +18,6 @@ class DeviceManagementPage extends StatelessWidget with HelperResponsiveLayout {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MultiBlocProvider(
|
return MultiBlocProvider(
|
||||||
providers: [
|
providers: [
|
||||||
BlocProvider(
|
|
||||||
create: (context) =>
|
|
||||||
SwitchTabsBloc()..add(const TriggerSwitchTabsEvent(false)),
|
|
||||||
),
|
|
||||||
BlocProvider(
|
BlocProvider(
|
||||||
create: (context) => DeviceManagementBloc()..add(FetchDevices()),
|
create: (context) => DeviceManagementBloc()..add(FetchDevices()),
|
||||||
),
|
),
|
||||||
@ -33,8 +29,7 @@ class DeviceManagementPage extends StatelessWidget with HelperResponsiveLayout {
|
|||||||
style: Theme.of(context).textTheme.headlineLarge,
|
style: Theme.of(context).textTheme.headlineLarge,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
centerBody: BlocBuilder<SwitchTabsBloc, SwitchTabsState>(
|
centerBody: BlocBuilder<RoutineBloc, RoutineState>(builder: (context, state) {
|
||||||
builder: (context, state) {
|
|
||||||
return Row(
|
return Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
@ -44,20 +39,14 @@ class DeviceManagementPage extends StatelessWidget with HelperResponsiveLayout {
|
|||||||
),
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
context
|
context
|
||||||
.read<SwitchTabsBloc>()
|
.read<RoutineBloc>()
|
||||||
.add(const TriggerSwitchTabsEvent(false));
|
.add(const TriggerSwitchTabsEvent(isRoutineTab: false));
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
'Devices',
|
'Devices',
|
||||||
style: context.textTheme.titleMedium?.copyWith(
|
style: context.textTheme.titleMedium?.copyWith(
|
||||||
color:
|
color: !state.routineTab ? ColorsManager.whiteColors : ColorsManager.grayColor,
|
||||||
state is SelectedTabState && state.selectedTab == false
|
fontWeight: !state.routineTab ? FontWeight.w700 : FontWeight.w400,
|
||||||
? ColorsManager.whiteColors
|
|
||||||
: ColorsManager.grayColor,
|
|
||||||
fontWeight: (state is SelectedTabState) &&
|
|
||||||
state.selectedTab == false
|
|
||||||
? FontWeight.w700
|
|
||||||
: FontWeight.w400,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -66,21 +55,13 @@ class DeviceManagementPage extends StatelessWidget with HelperResponsiveLayout {
|
|||||||
backgroundColor: null,
|
backgroundColor: null,
|
||||||
),
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
context
|
context.read<RoutineBloc>().add(const TriggerSwitchTabsEvent(isRoutineTab: true));
|
||||||
.read<SwitchTabsBloc>()
|
|
||||||
.add(const TriggerSwitchTabsEvent(true));
|
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
'Routines',
|
'Routines',
|
||||||
style: context.textTheme.titleMedium?.copyWith(
|
style: context.textTheme.titleMedium?.copyWith(
|
||||||
color:
|
color: state.routineTab ? ColorsManager.whiteColors : ColorsManager.grayColor,
|
||||||
(state is SelectedTabState) && state.selectedTab == true
|
fontWeight: state.routineTab ? FontWeight.w700 : FontWeight.w400,
|
||||||
? ColorsManager.whiteColors
|
|
||||||
: ColorsManager.grayColor,
|
|
||||||
fontWeight:
|
|
||||||
(state is SelectedTabState) && state.selectedTab == true
|
|
||||||
? FontWeight.w700
|
|
||||||
: FontWeight.w400,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -88,13 +69,12 @@ class DeviceManagementPage extends StatelessWidget with HelperResponsiveLayout {
|
|||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
rightBody: const NavigateHomeGridView(),
|
rightBody: const NavigateHomeGridView(),
|
||||||
scaffoldBody: BlocBuilder<SwitchTabsBloc, SwitchTabsState>(
|
scaffoldBody: BlocBuilder<RoutineBloc, RoutineState>(builder: (context, state) {
|
||||||
builder: (context, state) {
|
if (state.routineTab) {
|
||||||
if (state is SelectedTabState && state.selectedTab) {
|
|
||||||
return const RoutinesView();
|
return const RoutinesView();
|
||||||
}
|
}
|
||||||
if (state is ShowCreateRoutineState && state.showCreateRoutine) {
|
if (state.createRoutineView) {
|
||||||
return const CreateNewRoutineView();
|
return CreateNewRoutineView();
|
||||||
}
|
}
|
||||||
|
|
||||||
return BlocBuilder<DeviceManagementBloc, DeviceManagementState>(
|
return BlocBuilder<DeviceManagementBloc, DeviceManagementState>(
|
||||||
@ -104,8 +84,7 @@ class DeviceManagementPage extends StatelessWidget with HelperResponsiveLayout {
|
|||||||
} else if (deviceState is DeviceManagementLoaded) {
|
} else if (deviceState is DeviceManagementLoaded) {
|
||||||
return DeviceManagementBody(devices: deviceState.devices);
|
return DeviceManagementBody(devices: deviceState.devices);
|
||||||
} else if (deviceState is DeviceManagementFiltered) {
|
} else if (deviceState is DeviceManagementFiltered) {
|
||||||
return DeviceManagementBody(
|
return DeviceManagementBody(devices: deviceState.filteredDevices);
|
||||||
devices: deviceState.filteredDevices);
|
|
||||||
} else {
|
} else {
|
||||||
return const Center(child: Text('Error fetching Devices'));
|
return const Center(child: Text('Error fetching Devices'));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import 'package:syncrow_web/pages/auth/model/user_model.dart';
|
|||||||
import 'package:syncrow_web/pages/home/bloc/home_event.dart';
|
import 'package:syncrow_web/pages/home/bloc/home_event.dart';
|
||||||
import 'package:syncrow_web/pages/home/bloc/home_state.dart';
|
import 'package:syncrow_web/pages/home/bloc/home_state.dart';
|
||||||
import 'package:syncrow_web/pages/home/home_model/home_item_model.dart';
|
import 'package:syncrow_web/pages/home/home_model/home_item_model.dart';
|
||||||
|
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart';
|
||||||
import 'package:syncrow_web/services/home_api.dart';
|
import 'package:syncrow_web/services/home_api.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
@ -41,8 +42,7 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
|
|||||||
|
|
||||||
Future _fetchUserInfo(FetchUserInfo event, Emitter<HomeState> emit) async {
|
Future _fetchUserInfo(FetchUserInfo event, Emitter<HomeState> emit) async {
|
||||||
try {
|
try {
|
||||||
var uuid =
|
var uuid = await const FlutterSecureStorage().read(key: UserModel.userUuidKey);
|
||||||
await const FlutterSecureStorage().read(key: UserModel.userUuidKey);
|
|
||||||
user = await HomeApi().fetchUserInfo(uuid);
|
user = await HomeApi().fetchUserInfo(uuid);
|
||||||
emit(HomeInitial());
|
emit(HomeInitial());
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -84,6 +84,8 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
|
|||||||
icon: Assets.devicesIcon,
|
icon: Assets.devicesIcon,
|
||||||
active: true,
|
active: true,
|
||||||
onPress: (context) {
|
onPress: (context) {
|
||||||
|
BlocProvider.of<RoutineBloc>(context)
|
||||||
|
.add(const TriggerSwitchTabsEvent(isRoutineTab: false));
|
||||||
context.go(RoutesConst.deviceManagementPage);
|
context.go(RoutesConst.deviceManagementPage);
|
||||||
},
|
},
|
||||||
color: ColorsManager.primaryColor,
|
color: ColorsManager.primaryColor,
|
||||||
|
|||||||
@ -16,6 +16,7 @@ class EffectPeriodBloc extends Bloc<EffectPeriodEvent, EffectPeriodState> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
EffectPeriodBloc() : super(EffectPeriodState.initial()) {
|
EffectPeriodBloc() : super(EffectPeriodState.initial()) {
|
||||||
|
on<InitialEffectPeriodEvent>(_initialEvent);
|
||||||
on<SetPeriod>(_onSetPeriod);
|
on<SetPeriod>(_onSetPeriod);
|
||||||
on<ToggleDay>(_onToggleDay);
|
on<ToggleDay>(_onToggleDay);
|
||||||
on<SetCustomTime>(_onSetCustomTime);
|
on<SetCustomTime>(_onSetCustomTime);
|
||||||
@ -24,6 +25,15 @@ class EffectPeriodBloc extends Bloc<EffectPeriodEvent, EffectPeriodState> {
|
|||||||
on<SetDays>(_setAllDays);
|
on<SetDays>(_setAllDays);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _initialEvent(InitialEffectPeriodEvent event, Emitter<EffectPeriodState> emit) {
|
||||||
|
add(SetCustomTime(event.effectiveTime.start, event.effectiveTime.end));
|
||||||
|
emit(state.copyWith(
|
||||||
|
selectedDaysBinary: event.effectiveTime.loops,
|
||||||
|
customStartTime: event.effectiveTime.start,
|
||||||
|
customEndTime: event.effectiveTime.end,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
void _onSetPeriod(SetPeriod event, Emitter<EffectPeriodState> emit) {
|
void _onSetPeriod(SetPeriod event, Emitter<EffectPeriodState> emit) {
|
||||||
String startTime = '';
|
String startTime = '';
|
||||||
String endTime = '';
|
String endTime = '';
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:syncrow_web/pages/routiens/models/create_scene_and_autoamtion/create_automation_model.dart';
|
||||||
import 'package:syncrow_web/utils/constants/app_enum.dart';
|
import 'package:syncrow_web/utils/constants/app_enum.dart';
|
||||||
|
|
||||||
abstract class EffectPeriodEvent extends Equatable {
|
abstract class EffectPeriodEvent extends Equatable {
|
||||||
@ -8,6 +9,15 @@ abstract class EffectPeriodEvent extends Equatable {
|
|||||||
List<Object> get props => [];
|
List<Object> get props => [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class InitialEffectPeriodEvent extends EffectPeriodEvent {
|
||||||
|
final EffectiveTime effectiveTime;
|
||||||
|
|
||||||
|
const InitialEffectPeriodEvent(this.effectiveTime);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [effectiveTime];
|
||||||
|
}
|
||||||
|
|
||||||
class SetPeriod extends EffectPeriodEvent {
|
class SetPeriod extends EffectPeriodEvent {
|
||||||
final EnumEffectivePeriodOptions period;
|
final EnumEffectivePeriodOptions period;
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -84,8 +84,7 @@ class RemoveDragCard extends RoutineEvent {
|
|||||||
final int index;
|
final int index;
|
||||||
final bool isFromThen;
|
final bool isFromThen;
|
||||||
final String key;
|
final String key;
|
||||||
const RemoveDragCard(
|
const RemoveDragCard({required this.index, required this.isFromThen, required this.key});
|
||||||
{required this.index, required this.isFromThen, required this.key});
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [index, isFromThen, key];
|
List<Object> get props => [index, isFromThen, key];
|
||||||
}
|
}
|
||||||
@ -105,12 +104,10 @@ class EffectiveTimePeriodEvent extends RoutineEvent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class CreateAutomationEvent extends RoutineEvent {
|
class CreateAutomationEvent extends RoutineEvent {
|
||||||
// final CreateAutomationModel createAutomationModel;
|
|
||||||
final String? automationId;
|
final String? automationId;
|
||||||
final bool updateAutomation;
|
final bool updateAutomation;
|
||||||
|
|
||||||
const CreateAutomationEvent({
|
const CreateAutomationEvent({
|
||||||
//required this.createAutomationModel,
|
|
||||||
this.automationId,
|
this.automationId,
|
||||||
this.updateAutomation = false,
|
this.updateAutomation = false,
|
||||||
});
|
});
|
||||||
@ -159,21 +156,55 @@ class InitializeRoutineState extends RoutineEvent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class DeleteScene extends RoutineEvent {
|
class DeleteScene extends RoutineEvent {
|
||||||
final String sceneId;
|
const DeleteScene();
|
||||||
final String unitUuid;
|
|
||||||
const DeleteScene({required this.sceneId, required this.unitUuid});
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [sceneId];
|
List<Object> get props => [];
|
||||||
}
|
}
|
||||||
|
|
||||||
class DeleteAutomation extends RoutineEvent {
|
// class DeleteAutomation extends RoutineEvent {
|
||||||
final String automationId;
|
// final String automationId;
|
||||||
final String unitUuid;
|
// const DeleteAutomation({required this.automationId});
|
||||||
const DeleteAutomation({required this.automationId, required this.unitUuid});
|
// @override
|
||||||
|
// List<Object> get props => [automationId];
|
||||||
|
// }
|
||||||
|
|
||||||
|
class UpdateScene extends RoutineEvent {
|
||||||
|
const UpdateScene();
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [automationId];
|
List<Object> get props => [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class UpdateAutomation extends RoutineEvent {
|
||||||
|
const UpdateAutomation();
|
||||||
|
@override
|
||||||
|
List<Object> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
class SetAutomationActionExecutor extends RoutineEvent {
|
||||||
|
final String automationActionExecutor;
|
||||||
|
const SetAutomationActionExecutor({required this.automationActionExecutor});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [automationActionExecutor];
|
||||||
|
}
|
||||||
|
|
||||||
|
class TriggerSwitchTabsEvent extends RoutineEvent {
|
||||||
|
final bool isRoutineTab;
|
||||||
|
const TriggerSwitchTabsEvent({required this.isRoutineTab});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [isRoutineTab];
|
||||||
|
}
|
||||||
|
|
||||||
|
class CreateNewRoutineViewEvent extends RoutineEvent {
|
||||||
|
final bool createRoutineView;
|
||||||
|
const CreateNewRoutineViewEvent({required this.createRoutineView});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [createRoutineView];
|
||||||
|
}
|
||||||
|
|
||||||
|
class FetchDevicesInRoutine extends RoutineEvent {}
|
||||||
|
|
||||||
class ResetRoutineState extends RoutineEvent {}
|
class ResetRoutineState extends RoutineEvent {}
|
||||||
|
|
||||||
class ClearFunctions extends RoutineEvent {}
|
class ClearFunctions extends RoutineEvent {}
|
||||||
|
|
||||||
|
class ResetErrorMessage extends RoutineEvent {}
|
||||||
|
|||||||
@ -21,29 +21,36 @@ class RoutineState extends Equatable {
|
|||||||
final String? sceneId;
|
final String? sceneId;
|
||||||
final String? automationId;
|
final String? automationId;
|
||||||
final bool? isUpdate;
|
final bool? isUpdate;
|
||||||
|
final List<AllDevicesModel> devices;
|
||||||
|
// final String? automationActionExecutor;
|
||||||
|
final bool routineTab;
|
||||||
|
final bool createRoutineView;
|
||||||
|
|
||||||
const RoutineState({
|
const RoutineState(
|
||||||
this.ifItems = const [],
|
{this.ifItems = const [],
|
||||||
this.thenItems = const [],
|
this.thenItems = const [],
|
||||||
this.availableCards = const [],
|
this.availableCards = const [],
|
||||||
this.scenes = const [],
|
this.scenes = const [],
|
||||||
this.automations = const [],
|
this.automations = const [],
|
||||||
this.selectedFunctions = const {},
|
this.selectedFunctions = const {},
|
||||||
this.isLoading = false,
|
this.isLoading = false,
|
||||||
this.errorMessage,
|
this.errorMessage,
|
||||||
this.routineName,
|
this.routineName,
|
||||||
this.selectedIcon,
|
this.selectedIcon,
|
||||||
this.loadScenesErrorMessage,
|
this.loadScenesErrorMessage,
|
||||||
this.loadAutomationErrorMessage,
|
this.loadAutomationErrorMessage,
|
||||||
this.searchText,
|
this.searchText,
|
||||||
this.isTabToRun = false,
|
this.isTabToRun = false,
|
||||||
this.isAutomation = false,
|
this.isAutomation = false,
|
||||||
this.selectedAutomationOperator = 'or',
|
this.selectedAutomationOperator = 'or',
|
||||||
this.effectiveTime,
|
this.effectiveTime,
|
||||||
this.sceneId,
|
this.sceneId,
|
||||||
this.automationId,
|
this.automationId,
|
||||||
this.isUpdate,
|
this.isUpdate,
|
||||||
});
|
this.devices = const [],
|
||||||
|
// this.automationActionExecutor,
|
||||||
|
this.routineTab = false,
|
||||||
|
this.createRoutineView = false});
|
||||||
|
|
||||||
RoutineState copyWith({
|
RoutineState copyWith({
|
||||||
List<Map<String, dynamic>>? ifItems,
|
List<Map<String, dynamic>>? ifItems,
|
||||||
@ -65,31 +72,39 @@ class RoutineState extends Equatable {
|
|||||||
String? sceneId,
|
String? sceneId,
|
||||||
String? automationId,
|
String? automationId,
|
||||||
bool? isUpdate,
|
bool? isUpdate,
|
||||||
|
List<AllDevicesModel>? devices,
|
||||||
|
// String? automationActionExecutor,
|
||||||
|
TextEditingController? nameController,
|
||||||
|
bool? routineTab,
|
||||||
|
bool? createRoutineView,
|
||||||
}) {
|
}) {
|
||||||
return RoutineState(
|
return RoutineState(
|
||||||
ifItems: ifItems ?? this.ifItems,
|
ifItems: ifItems ?? this.ifItems,
|
||||||
thenItems: thenItems ?? this.thenItems,
|
thenItems: thenItems ?? this.thenItems,
|
||||||
scenes: scenes ?? this.scenes,
|
scenes: scenes ?? this.scenes,
|
||||||
automations: automations ?? this.automations,
|
automations: automations ?? this.automations,
|
||||||
selectedFunctions: selectedFunctions ?? this.selectedFunctions,
|
selectedFunctions: selectedFunctions ?? this.selectedFunctions,
|
||||||
isLoading: isLoading ?? this.isLoading,
|
isLoading: isLoading ?? this.isLoading,
|
||||||
errorMessage: errorMessage ?? this.errorMessage,
|
errorMessage: errorMessage ?? this.errorMessage,
|
||||||
routineName: routineName ?? this.routineName,
|
routineName: routineName ?? this.routineName,
|
||||||
selectedIcon: selectedIcon ?? this.selectedIcon,
|
selectedIcon: selectedIcon ?? this.selectedIcon,
|
||||||
loadScenesErrorMessage:
|
loadScenesErrorMessage:
|
||||||
loadScenesErrorMessage ?? this.loadScenesErrorMessage,
|
loadScenesErrorMessage ?? this.loadScenesErrorMessage,
|
||||||
loadAutomationErrorMessage:
|
loadAutomationErrorMessage:
|
||||||
loadAutomationErrorMessage ?? this.loadAutomationErrorMessage,
|
loadAutomationErrorMessage ?? this.loadAutomationErrorMessage,
|
||||||
searchText: searchText ?? this.searchText,
|
searchText: searchText ?? this.searchText,
|
||||||
isTabToRun: isTabToRun ?? this.isTabToRun,
|
isTabToRun: isTabToRun ?? this.isTabToRun,
|
||||||
isAutomation: isAutomation ?? this.isAutomation,
|
isAutomation: isAutomation ?? this.isAutomation,
|
||||||
selectedAutomationOperator:
|
selectedAutomationOperator:
|
||||||
selectedAutomationOperator ?? this.selectedAutomationOperator,
|
selectedAutomationOperator ?? this.selectedAutomationOperator,
|
||||||
effectiveTime: effectiveTime ?? this.effectiveTime,
|
effectiveTime: effectiveTime ?? this.effectiveTime,
|
||||||
sceneId: sceneId ?? this.sceneId,
|
sceneId: sceneId ?? this.sceneId,
|
||||||
automationId: automationId ?? this.automationId,
|
automationId: automationId ?? this.automationId,
|
||||||
isUpdate: isUpdate ?? this.isUpdate,
|
isUpdate: isUpdate ?? this.isUpdate,
|
||||||
);
|
devices: devices ?? this.devices,
|
||||||
|
// automationActionExecutor: automationActionExecutor ?? this.automationActionExecutor,
|
||||||
|
routineTab: routineTab ?? this.routineTab,
|
||||||
|
createRoutineView: createRoutineView ?? this.createRoutineView);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -112,6 +127,10 @@ class RoutineState extends Equatable {
|
|||||||
effectiveTime,
|
effectiveTime,
|
||||||
sceneId,
|
sceneId,
|
||||||
automationId,
|
automationId,
|
||||||
isUpdate
|
isUpdate,
|
||||||
|
devices,
|
||||||
|
// automationActionExecutor,
|
||||||
|
routineTab,
|
||||||
|
createRoutineView
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
@ -6,10 +8,11 @@ import 'package:syncrow_web/pages/routiens/widgets/dialog_header.dart';
|
|||||||
import 'package:syncrow_web/pages/routiens/widgets/dialog_footer.dart';
|
import 'package:syncrow_web/pages/routiens/widgets/dialog_footer.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
|
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
||||||
|
|
||||||
class SaveRoutineHelper {
|
class SaveRoutineHelper {
|
||||||
static Future<bool?> showSaveRoutineDialog(BuildContext context) async {
|
static Future<void> showSaveRoutineDialog(BuildContext context) async {
|
||||||
return showDialog<bool?>(
|
return showDialog<void>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
return BlocBuilder<RoutineBloc, RoutineState>(
|
return BlocBuilder<RoutineBloc, RoutineState>(
|
||||||
@ -98,18 +101,29 @@ class SaveRoutineHelper {
|
|||||||
final functions =
|
final functions =
|
||||||
state.selectedFunctions[item['uniqueCustomId']] ?? [];
|
state.selectedFunctions[item['uniqueCustomId']] ?? [];
|
||||||
return ListTile(
|
return ListTile(
|
||||||
leading: SvgPicture.asset(
|
leading: item['type'] == 'tap_to_run'
|
||||||
item['imagePath'],
|
? Image.memory(
|
||||||
width: 22,
|
base64Decode(item['icon']),
|
||||||
height: 22,
|
width: 22,
|
||||||
|
height: 22,
|
||||||
|
)
|
||||||
|
: SvgPicture.asset(
|
||||||
|
item['imagePath'],
|
||||||
|
width: 22,
|
||||||
|
height: 22,
|
||||||
|
),
|
||||||
|
title: Text(
|
||||||
|
item['title'],
|
||||||
|
style: context.textTheme.bodySmall?.copyWith(
|
||||||
|
fontSize: 14,
|
||||||
|
color: ColorsManager.grayColor,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
title:
|
|
||||||
Text(item['title'], style: const TextStyle(fontSize: 14)),
|
|
||||||
subtitle: Wrap(
|
subtitle: Wrap(
|
||||||
children: functions
|
children: functions
|
||||||
.map((f) => Text(
|
.map((f) => Text(
|
||||||
'${f.operationName}: ${f.value}, ',
|
'${f.operationName}: ${f.value}, ',
|
||||||
style: const TextStyle(
|
style: context.textTheme.bodySmall?.copyWith(
|
||||||
color: ColorsManager.grayColor, fontSize: 8),
|
color: ColorsManager.grayColor, fontSize: 8),
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
maxLines: 3,
|
maxLines: 3,
|
||||||
@ -124,24 +138,33 @@ class SaveRoutineHelper {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (state.errorMessage != null)
|
// if (state.errorMessage != null || state.errorMessage!.isNotEmpty)
|
||||||
Padding(
|
// Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
// padding: const EdgeInsets.all(8.0),
|
||||||
child: Text(
|
// child: Text(
|
||||||
state.errorMessage!,
|
// state.errorMessage!,
|
||||||
style: const TextStyle(color: Colors.red),
|
// style: const TextStyle(color: Colors.red),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
DialogFooter(
|
DialogFooter(
|
||||||
onCancel: () => Navigator.pop(context, false),
|
onCancel: () => Navigator.pop(context),
|
||||||
onConfirm: () {
|
onConfirm: () async {
|
||||||
if (state.isAutomation) {
|
if (state.isAutomation) {
|
||||||
context.read<RoutineBloc>().add(const CreateAutomationEvent());
|
if (state.isUpdate ?? false) {
|
||||||
|
context.read<RoutineBloc>().add(const UpdateAutomation());
|
||||||
|
} else {
|
||||||
|
context.read<RoutineBloc>().add(const CreateAutomationEvent());
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
context.read<RoutineBloc>().add(const CreateSceneEvent());
|
if (state.isUpdate ?? false) {
|
||||||
|
context.read<RoutineBloc>().add(const UpdateScene());
|
||||||
|
} else {
|
||||||
|
context.read<RoutineBloc>().add(const CreateSceneEvent());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// if (state.errorMessage == null || state.errorMessage!.isEmpty) {
|
||||||
Navigator.pop(context, true);
|
Navigator.pop(context);
|
||||||
|
// }
|
||||||
},
|
},
|
||||||
isConfirmEnabled: true,
|
isConfirmEnabled: true,
|
||||||
),
|
),
|
||||||
|
|||||||
@ -17,7 +17,7 @@ class CreateAutomationModel {
|
|||||||
required this.actions,
|
required this.actions,
|
||||||
});
|
});
|
||||||
|
|
||||||
Map<String, dynamic> toMap() {
|
Map<String, dynamic> toMap([String? automationId]) {
|
||||||
return {
|
return {
|
||||||
'spaceUuid': spaceUuid,
|
'spaceUuid': spaceUuid,
|
||||||
'automationName': automationName,
|
'automationName': automationName,
|
||||||
@ -41,7 +41,7 @@ class CreateAutomationModel {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
String toJson() => json.encode(toMap());
|
String toJson(String? automationId) => json.encode(toMap(automationId));
|
||||||
|
|
||||||
factory CreateAutomationModel.fromJson(String source) =>
|
factory CreateAutomationModel.fromJson(String source) =>
|
||||||
CreateAutomationModel.fromMap(json.decode(source));
|
CreateAutomationModel.fromMap(json.decode(source));
|
||||||
@ -92,7 +92,7 @@ class Condition {
|
|||||||
return {
|
return {
|
||||||
'code': code,
|
'code': code,
|
||||||
'entityId': entityId,
|
'entityId': entityId,
|
||||||
'entityType': entityType,
|
'entityType': 'device_report',
|
||||||
'expr': expr.toMap(),
|
'expr': expr.toMap(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -137,11 +137,13 @@ class ConditionExpr {
|
|||||||
|
|
||||||
class AutomationAction {
|
class AutomationAction {
|
||||||
String entityId;
|
String entityId;
|
||||||
|
String? actionType;
|
||||||
String actionExecutor;
|
String actionExecutor;
|
||||||
ExecutorProperty? executorProperty;
|
ExecutorProperty? executorProperty;
|
||||||
|
|
||||||
AutomationAction({
|
AutomationAction({
|
||||||
required this.entityId,
|
required this.entityId,
|
||||||
|
this.actionType,
|
||||||
required this.actionExecutor,
|
required this.actionExecutor,
|
||||||
this.executorProperty,
|
this.executorProperty,
|
||||||
});
|
});
|
||||||
@ -150,12 +152,15 @@ class AutomationAction {
|
|||||||
return {
|
return {
|
||||||
'entityId': entityId,
|
'entityId': entityId,
|
||||||
'actionExecutor': actionExecutor,
|
'actionExecutor': actionExecutor,
|
||||||
'executorProperty': executorProperty?.toMap(),
|
if (executorProperty != null)
|
||||||
|
'executorProperty': executorProperty?.toMap(),
|
||||||
|
'actionType': actionType
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
factory AutomationAction.fromMap(Map<String, dynamic> map) {
|
factory AutomationAction.fromMap(Map<String, dynamic> map) {
|
||||||
return AutomationAction(
|
return AutomationAction(
|
||||||
|
actionType: map['actionType'],
|
||||||
entityId: map['entityId'] ?? '',
|
entityId: map['entityId'] ?? '',
|
||||||
actionExecutor: map['actionExecutor'] ?? '',
|
actionExecutor: map['actionExecutor'] ?? '',
|
||||||
executorProperty: map['executorProperty'] != null
|
executorProperty: map['executorProperty'] != null
|
||||||
|
|||||||
@ -95,10 +95,12 @@ class CreateSceneModel {
|
|||||||
|
|
||||||
class CreateSceneAction {
|
class CreateSceneAction {
|
||||||
String entityId;
|
String entityId;
|
||||||
|
String? actionType;
|
||||||
String actionExecutor;
|
String actionExecutor;
|
||||||
CreateSceneExecutorProperty? executorProperty;
|
CreateSceneExecutorProperty? executorProperty;
|
||||||
|
|
||||||
CreateSceneAction({
|
CreateSceneAction({
|
||||||
|
this.actionType,
|
||||||
required this.entityId,
|
required this.entityId,
|
||||||
required this.actionExecutor,
|
required this.actionExecutor,
|
||||||
required this.executorProperty,
|
required this.executorProperty,
|
||||||
@ -110,6 +112,7 @@ class CreateSceneAction {
|
|||||||
CreateSceneExecutorProperty? executorProperty,
|
CreateSceneExecutorProperty? executorProperty,
|
||||||
}) {
|
}) {
|
||||||
return CreateSceneAction(
|
return CreateSceneAction(
|
||||||
|
actionType: actionType ?? this.actionType,
|
||||||
entityId: entityId ?? this.entityId,
|
entityId: entityId ?? this.entityId,
|
||||||
actionExecutor: actionExecutor ?? this.actionExecutor,
|
actionExecutor: actionExecutor ?? this.actionExecutor,
|
||||||
executorProperty: executorProperty ?? this.executorProperty,
|
executorProperty: executorProperty ?? this.executorProperty,
|
||||||
@ -125,6 +128,7 @@ class CreateSceneAction {
|
|||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
|
"actionType": actionType,
|
||||||
'entityId': entityId,
|
'entityId': entityId,
|
||||||
'actionExecutor': actionExecutor,
|
'actionExecutor': actionExecutor,
|
||||||
};
|
};
|
||||||
@ -133,6 +137,7 @@ class CreateSceneAction {
|
|||||||
|
|
||||||
factory CreateSceneAction.fromMap(Map<String, dynamic> map) {
|
factory CreateSceneAction.fromMap(Map<String, dynamic> map) {
|
||||||
return CreateSceneAction(
|
return CreateSceneAction(
|
||||||
|
actionType: map['actionType'],
|
||||||
entityId: map['entityId'] ?? '',
|
entityId: map['entityId'] ?? '',
|
||||||
actionExecutor: map['actionExecutor'] ?? '',
|
actionExecutor: map['actionExecutor'] ?? '',
|
||||||
executorProperty:
|
executorProperty:
|
||||||
|
|||||||
@ -13,6 +13,8 @@ class RoutineDetailsModel {
|
|||||||
final EffectiveTime? effectiveTime;
|
final EffectiveTime? effectiveTime;
|
||||||
final List<RoutineCondition>? conditions;
|
final List<RoutineCondition>? conditions;
|
||||||
final String? type;
|
final String? type;
|
||||||
|
final String? sceneId;
|
||||||
|
final String? automationId;
|
||||||
|
|
||||||
RoutineDetailsModel({
|
RoutineDetailsModel({
|
||||||
required this.spaceUuid,
|
required this.spaceUuid,
|
||||||
@ -24,6 +26,8 @@ class RoutineDetailsModel {
|
|||||||
this.effectiveTime,
|
this.effectiveTime,
|
||||||
this.conditions,
|
this.conditions,
|
||||||
this.type,
|
this.type,
|
||||||
|
this.sceneId,
|
||||||
|
this.automationId,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Convert to CreateSceneModel
|
// Convert to CreateSceneModel
|
||||||
@ -57,12 +61,14 @@ class RoutineDetailsModel {
|
|||||||
'name': name,
|
'name': name,
|
||||||
'decisionExpr': decisionExpr,
|
'decisionExpr': decisionExpr,
|
||||||
'actions': actions.map((x) => x.toMap()).toList(),
|
'actions': actions.map((x) => x.toMap()).toList(),
|
||||||
if (iconId != null) 'iconId': iconId,
|
if (iconId != null) 'iconUuid': iconId,
|
||||||
if (showInDevice != null) 'showInDevice': showInDevice,
|
if (showInDevice != null) 'showInDevice': showInDevice,
|
||||||
if (effectiveTime != null) 'effectiveTime': effectiveTime!.toMap(),
|
if (effectiveTime != null) 'effectiveTime': effectiveTime!.toMap(),
|
||||||
if (conditions != null)
|
if (conditions != null)
|
||||||
'conditions': conditions!.map((x) => x.toMap()).toList(),
|
'conditions': conditions!.map((x) => x.toMap()).toList(),
|
||||||
if (type != null) 'type': type,
|
if (type != null) 'type': type,
|
||||||
|
if (sceneId != null) 'sceneId': sceneId,
|
||||||
|
if (automationId != null) 'automationId': automationId,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,7 +80,7 @@ class RoutineDetailsModel {
|
|||||||
actions: List<RoutineAction>.from(
|
actions: List<RoutineAction>.from(
|
||||||
map['actions']?.map((x) => RoutineAction.fromMap(x)) ?? [],
|
map['actions']?.map((x) => RoutineAction.fromMap(x)) ?? [],
|
||||||
),
|
),
|
||||||
iconId: map['iconId'],
|
iconId: map['iconUuid'],
|
||||||
showInDevice: map['showInDevice'],
|
showInDevice: map['showInDevice'],
|
||||||
effectiveTime: map['effectiveTime'] != null
|
effectiveTime: map['effectiveTime'] != null
|
||||||
? EffectiveTime.fromMap(map['effectiveTime'])
|
? EffectiveTime.fromMap(map['effectiveTime'])
|
||||||
@ -84,6 +90,8 @@ class RoutineDetailsModel {
|
|||||||
map['conditions'].map((x) => RoutineCondition.fromMap(x)))
|
map['conditions'].map((x) => RoutineCondition.fromMap(x)))
|
||||||
: null,
|
: null,
|
||||||
type: map['type'],
|
type: map['type'],
|
||||||
|
sceneId: map['sceneId'],
|
||||||
|
automationId: map['automationId'],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,12 +104,18 @@ class RoutineDetailsModel {
|
|||||||
class RoutineAction {
|
class RoutineAction {
|
||||||
final String entityId;
|
final String entityId;
|
||||||
final String actionExecutor;
|
final String actionExecutor;
|
||||||
|
final String? name;
|
||||||
final RoutineExecutorProperty? executorProperty;
|
final RoutineExecutorProperty? executorProperty;
|
||||||
|
final String productType;
|
||||||
|
final String? type;
|
||||||
|
|
||||||
RoutineAction({
|
RoutineAction({
|
||||||
required this.entityId,
|
required this.entityId,
|
||||||
required this.actionExecutor,
|
required this.actionExecutor,
|
||||||
|
required this.productType,
|
||||||
this.executorProperty,
|
this.executorProperty,
|
||||||
|
this.name,
|
||||||
|
this.type,
|
||||||
});
|
});
|
||||||
|
|
||||||
CreateSceneAction toCreateSceneAction() {
|
CreateSceneAction toCreateSceneAction() {
|
||||||
@ -124,6 +138,8 @@ class RoutineAction {
|
|||||||
return {
|
return {
|
||||||
'entityId': entityId,
|
'entityId': entityId,
|
||||||
'actionExecutor': actionExecutor,
|
'actionExecutor': actionExecutor,
|
||||||
|
if (type != null) 'type': type,
|
||||||
|
if (name != null) 'name': name,
|
||||||
if (executorProperty != null)
|
if (executorProperty != null)
|
||||||
'executorProperty': executorProperty!.toMap(),
|
'executorProperty': executorProperty!.toMap(),
|
||||||
};
|
};
|
||||||
@ -133,6 +149,9 @@ class RoutineAction {
|
|||||||
return RoutineAction(
|
return RoutineAction(
|
||||||
entityId: map['entityId'] ?? '',
|
entityId: map['entityId'] ?? '',
|
||||||
actionExecutor: map['actionExecutor'] ?? '',
|
actionExecutor: map['actionExecutor'] ?? '',
|
||||||
|
productType: map['productType'] ?? '',
|
||||||
|
name: map['name'] ?? '',
|
||||||
|
type: map['type'] ?? '',
|
||||||
executorProperty: map['executorProperty'] != null
|
executorProperty: map['executorProperty'] != null
|
||||||
? RoutineExecutorProperty.fromMap(map['executorProperty'])
|
? RoutineExecutorProperty.fromMap(map['executorProperty'])
|
||||||
: null,
|
: null,
|
||||||
@ -189,12 +208,14 @@ class RoutineCondition {
|
|||||||
final String entityId;
|
final String entityId;
|
||||||
final String entityType;
|
final String entityType;
|
||||||
final RoutineConditionExpr expr;
|
final RoutineConditionExpr expr;
|
||||||
|
final String productType;
|
||||||
|
|
||||||
RoutineCondition({
|
RoutineCondition({
|
||||||
required this.code,
|
required this.code,
|
||||||
required this.entityId,
|
required this.entityId,
|
||||||
required this.entityType,
|
required this.entityType,
|
||||||
required this.expr,
|
required this.expr,
|
||||||
|
required this.productType,
|
||||||
});
|
});
|
||||||
|
|
||||||
Condition toCondition() {
|
Condition toCondition() {
|
||||||
@ -221,6 +242,7 @@ class RoutineCondition {
|
|||||||
entityId: map['entityId'] ?? '',
|
entityId: map['entityId'] ?? '',
|
||||||
entityType: map['entityType'] ?? '',
|
entityType: map['entityType'] ?? '',
|
||||||
expr: RoutineConditionExpr.fromMap(map['expr']),
|
expr: RoutineConditionExpr.fromMap(map['expr']),
|
||||||
|
productType: map['productType'] ?? '',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,6 +16,7 @@ class CreateNewRoutineView extends StatelessWidget {
|
|||||||
this.routineId,
|
this.routineId,
|
||||||
this.isScene = true,
|
this.isScene = true,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return Container(
|
||||||
@ -67,7 +68,7 @@ class CreateNewRoutineView extends StatelessWidget {
|
|||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
color: ColorsManager.dialogBlueTitle,
|
color: ColorsManager.dialogBlueTitle,
|
||||||
),
|
),
|
||||||
|
|
||||||
/// THEN Container
|
/// THEN Container
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Card(
|
child: Card(
|
||||||
|
|||||||
@ -1,20 +1,30 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/all_devices/bloc/switch_tabs/switch_tabs_bloc.dart';
|
|
||||||
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart';
|
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/routiens/view/create_new_routine_view.dart';
|
import 'package:syncrow_web/pages/routiens/view/create_new_routine_view.dart';
|
||||||
import 'package:syncrow_web/pages/routiens/widgets/main_routine_view/fetch_routine_scenes_automation.dart';
|
import 'package:syncrow_web/pages/routiens/widgets/main_routine_view/fetch_routine_scenes_automation.dart';
|
||||||
import 'package:syncrow_web/pages/routiens/widgets/main_routine_view/routine_view_card.dart';
|
import 'package:syncrow_web/pages/routiens/widgets/main_routine_view/routine_view_card.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
|
||||||
class RoutinesView extends StatelessWidget {
|
class RoutinesView extends StatefulWidget {
|
||||||
const RoutinesView({super.key});
|
const RoutinesView({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<RoutinesView> createState() => _RoutinesViewState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _RoutinesViewState extends State<RoutinesView> {
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
context.read<RoutineBloc>().add(FetchDevicesInRoutine());
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocBuilder<SwitchTabsBloc, SwitchTabsState>(
|
return BlocBuilder<RoutineBloc, RoutineState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
if (state is ShowCreateRoutineState && state.showCreateRoutine) {
|
if (state.createRoutineView) {
|
||||||
return const CreateNewRoutineView();
|
return const CreateNewRoutineView();
|
||||||
}
|
}
|
||||||
return Padding(
|
return Padding(
|
||||||
@ -36,12 +46,12 @@ class RoutinesView extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
RoutineViewCard(
|
RoutineViewCard(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
BlocProvider.of<SwitchTabsBloc>(context).add(
|
|
||||||
const CreateNewRoutineViewEvent(true),
|
|
||||||
);
|
|
||||||
context.read<RoutineBloc>().add(
|
context.read<RoutineBloc>().add(
|
||||||
(ResetRoutineState()),
|
(ResetRoutineState()),
|
||||||
);
|
);
|
||||||
|
BlocProvider.of<RoutineBloc>(context).add(
|
||||||
|
const CreateNewRoutineViewEvent(createRoutineView: true),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
icon: Icons.add,
|
icon: Icons.add,
|
||||||
textString: '',
|
textString: '',
|
||||||
|
|||||||
88
lib/pages/routiens/widgets/delete_scene.dart
Normal file
88
lib/pages/routiens/widgets/delete_scene.dart
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/common/custom_dialog.dart';
|
||||||
|
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart';
|
||||||
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
|
||||||
|
class DeleteSceneWidget extends StatelessWidget {
|
||||||
|
const DeleteSceneWidget({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const SizedBox(
|
||||||
|
height: 10,
|
||||||
|
),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () async {
|
||||||
|
await showCustomDialog(
|
||||||
|
context: context,
|
||||||
|
message: 'Are you sure you want to delete this scene?',
|
||||||
|
actions: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
alignment: AlignmentDirectional.center,
|
||||||
|
child: Text(
|
||||||
|
'Cancel',
|
||||||
|
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
||||||
|
color: ColorsManager.textGray,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(width: 1, height: 50, color: ColorsManager.greyColor),
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
context.read<RoutineBloc>().add(const DeleteScene());
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
alignment: AlignmentDirectional.center,
|
||||||
|
child: Text(
|
||||||
|
'Confirm',
|
||||||
|
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
||||||
|
color: ColorsManager.primaryColorWithOpacity,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
const Icon(
|
||||||
|
Icons.delete,
|
||||||
|
color: ColorsManager.red,
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
width: 2,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'Delete',
|
||||||
|
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
||||||
|
color: ColorsManager.red,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 10,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -35,6 +35,20 @@ class DraggableCard extends StatelessWidget {
|
|||||||
final deviceFunctions =
|
final deviceFunctions =
|
||||||
state.selectedFunctions[deviceData['uniqueCustomId']] ?? [];
|
state.selectedFunctions[deviceData['uniqueCustomId']] ?? [];
|
||||||
|
|
||||||
|
int index = state.thenItems.indexWhere(
|
||||||
|
(item) => item['uniqueCustomId'] == deviceData['uniqueCustomId']);
|
||||||
|
|
||||||
|
if (index != -1) {
|
||||||
|
return _buildCardContent(context, deviceFunctions, padding: padding);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ifIndex = state.ifItems.indexWhere(
|
||||||
|
(item) => item['uniqueCustomId'] == deviceData['uniqueCustomId']);
|
||||||
|
|
||||||
|
if (ifIndex != -1) {
|
||||||
|
return _buildCardContent(context, deviceFunctions, padding: padding);
|
||||||
|
}
|
||||||
|
|
||||||
return Draggable<Map<String, dynamic>>(
|
return Draggable<Map<String, dynamic>>(
|
||||||
data: deviceData,
|
data: deviceData,
|
||||||
feedback: Transform.rotate(
|
feedback: Transform.rotate(
|
||||||
@ -79,19 +93,19 @@ class DraggableCard extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
padding: const EdgeInsets.all(8),
|
padding: const EdgeInsets.all(8),
|
||||||
child: imagePath.contains('.svg')
|
child: deviceData['type'] == 'tap_to_run'
|
||||||
? SvgPicture.asset(
|
? Image.memory(
|
||||||
imagePath,
|
base64Decode(deviceData['icon']),
|
||||||
)
|
)
|
||||||
: Image.memory(
|
: SvgPicture.asset(
|
||||||
base64Decode(imagePath),
|
imagePath,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 3),
|
padding: const EdgeInsets.symmetric(horizontal: 3),
|
||||||
child: Text(
|
child: Text(
|
||||||
title,
|
deviceData['title'] ?? deviceData['name'] ?? title,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
maxLines: 2,
|
maxLines: 2,
|
||||||
@ -104,7 +118,6 @@ class DraggableCard extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (deviceFunctions.isNotEmpty)
|
if (deviceFunctions.isNotEmpty)
|
||||||
// const Divider(height: 1),
|
|
||||||
...deviceFunctions.map((function) => Row(
|
...deviceFunctions.map((function) => Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
|
|||||||
@ -11,8 +11,7 @@ class FetchRoutineScenesAutomation extends StatefulWidget {
|
|||||||
const FetchRoutineScenesAutomation({super.key});
|
const FetchRoutineScenesAutomation({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<FetchRoutineScenesAutomation> createState() =>
|
State<FetchRoutineScenesAutomation> createState() => _FetchRoutineScenesState();
|
||||||
_FetchRoutineScenesState();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class _FetchRoutineScenesState extends State<FetchRoutineScenesAutomation>
|
class _FetchRoutineScenesState extends State<FetchRoutineScenesAutomation>
|
||||||
@ -67,49 +66,23 @@ class _FetchRoutineScenesState extends State<FetchRoutineScenesAutomation>
|
|||||||
padding: EdgeInsets.only(
|
padding: EdgeInsets.only(
|
||||||
right: isSmallScreenSize(context) ? 4.0 : 8.0,
|
right: isSmallScreenSize(context) ? 4.0 : 8.0,
|
||||||
),
|
),
|
||||||
child: Stack(
|
child: RoutineViewCard(
|
||||||
children: [
|
onTap: () {
|
||||||
RoutineViewCard(
|
BlocProvider.of<RoutineBloc>(context).add(
|
||||||
onTap: () {},
|
const CreateNewRoutineViewEvent(createRoutineView: true),
|
||||||
textString: state.scenes[index].name,
|
);
|
||||||
icon: state.scenes[index].icon ??
|
context.read<RoutineBloc>().add(
|
||||||
Assets.logoHorizontal,
|
GetSceneDetails(
|
||||||
isFromScenes: true,
|
sceneId: state.scenes[index].id,
|
||||||
iconInBytes:
|
isTabToRun: true,
|
||||||
state.scenes[index].iconInBytes,
|
isUpdate: true,
|
||||||
),
|
|
||||||
Positioned(
|
|
||||||
top: 0,
|
|
||||||
right: 0,
|
|
||||||
child: InkWell(
|
|
||||||
onTap: () => context
|
|
||||||
.read<RoutineBloc>()
|
|
||||||
.add(
|
|
||||||
DeleteScene(
|
|
||||||
sceneId: state.scenes[index].id,
|
|
||||||
unitUuid: spaceId,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: Container(
|
|
||||||
height: 20,
|
|
||||||
width: 20,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: ColorsManager.whiteColors,
|
|
||||||
shape: BoxShape.circle,
|
|
||||||
border: Border.all(
|
|
||||||
color: ColorsManager.grayColor,
|
|
||||||
width: 2.0,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
child: const Center(
|
);
|
||||||
child: Icon(Icons.delete,
|
},
|
||||||
size: 15,
|
textString: state.scenes[index].name,
|
||||||
color: ColorsManager.grayColor),
|
icon: state.scenes[index].icon ?? Assets.logoHorizontal,
|
||||||
),
|
isFromScenes: true,
|
||||||
),
|
iconInBytes: state.scenes[index].iconInBytes,
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -142,46 +115,20 @@ class _FetchRoutineScenesState extends State<FetchRoutineScenesAutomation>
|
|||||||
padding: EdgeInsets.only(
|
padding: EdgeInsets.only(
|
||||||
right: isSmallScreenSize(context) ? 4.0 : 8.0,
|
right: isSmallScreenSize(context) ? 4.0 : 8.0,
|
||||||
),
|
),
|
||||||
child: Stack(
|
child: RoutineViewCard(
|
||||||
children: [
|
onTap: () {
|
||||||
RoutineViewCard(
|
BlocProvider.of<RoutineBloc>(context).add(
|
||||||
onTap: () {},
|
const CreateNewRoutineViewEvent(createRoutineView: true),
|
||||||
textString: state.automations[index].name,
|
);
|
||||||
icon: state.automations[index].icon ??
|
context.read<RoutineBloc>().add(
|
||||||
Assets.automation,
|
GetAutomationDetails(
|
||||||
),
|
automationId: state.automations[index].id,
|
||||||
Positioned(
|
isAutomation: true,
|
||||||
top: 0,
|
isUpdate: true),
|
||||||
right: 0,
|
);
|
||||||
child: InkWell(
|
},
|
||||||
onTap: () =>
|
textString: state.automations[index].name,
|
||||||
context.read<RoutineBloc>().add(
|
icon: state.automations[index].icon ?? Assets.automation,
|
||||||
DeleteAutomation(
|
|
||||||
automationId: state
|
|
||||||
.automations[index].id,
|
|
||||||
unitUuid: spaceId,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: Container(
|
|
||||||
height: 20,
|
|
||||||
width: 20,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: ColorsManager.whiteColors,
|
|
||||||
shape: BoxShape.circle,
|
|
||||||
border: Border.all(
|
|
||||||
color: ColorsManager.grayColor,
|
|
||||||
width: 2.0,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: const Center(
|
|
||||||
child: Icon(Icons.delete,
|
|
||||||
size: 15,
|
|
||||||
color: ColorsManager.grayColor),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/all_devices/bloc/device_mgmt_bloc/device_managment_bloc.dart';
|
|
||||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
|
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
|
||||||
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart';
|
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/routiens/widgets/dragable_card.dart';
|
import 'package:syncrow_web/pages/routiens/widgets/dragable_card.dart';
|
||||||
@ -10,68 +9,67 @@ class RoutineDevices extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider(
|
return BlocBuilder<RoutineBloc, RoutineState>(
|
||||||
create: (context) => DeviceManagementBloc()..add(FetchDevices()),
|
builder: (context, state) {
|
||||||
child: BlocBuilder<DeviceManagementBloc, DeviceManagementState>(
|
if (state.isLoading) {
|
||||||
builder: (context, state) {
|
|
||||||
if (state is DeviceManagementLoaded) {
|
|
||||||
List<AllDevicesModel> deviceList = state.devices
|
|
||||||
.where((device) =>
|
|
||||||
device.productType == 'AC' ||
|
|
||||||
device.productType == '1G' ||
|
|
||||||
device.productType == '2G' ||
|
|
||||||
device.productType == '3G')
|
|
||||||
.toList();
|
|
||||||
|
|
||||||
// Provide the RoutineBloc to the child widgets
|
|
||||||
return BlocBuilder<RoutineBloc, RoutineState>(
|
|
||||||
builder: (context, routineState) {
|
|
||||||
return Wrap(
|
|
||||||
spacing: 10,
|
|
||||||
runSpacing: 10,
|
|
||||||
children: deviceList.asMap().entries.map((entry) {
|
|
||||||
final device = entry.value;
|
|
||||||
if (routineState.searchText != null && routineState.searchText!.isNotEmpty) {
|
|
||||||
return device.name!
|
|
||||||
.toLowerCase()
|
|
||||||
.contains(routineState.searchText!.toLowerCase())
|
|
||||||
? DraggableCard(
|
|
||||||
imagePath: device.getDefaultIcon(device.productType),
|
|
||||||
title: device.name ?? '',
|
|
||||||
deviceData: {
|
|
||||||
'device': device,
|
|
||||||
'imagePath': device.getDefaultIcon(device.productType),
|
|
||||||
'title': device.name ?? '',
|
|
||||||
'deviceId': device.uuid,
|
|
||||||
'productType': device.productType,
|
|
||||||
'functions': device.functions,
|
|
||||||
'uniqueCustomId': '',
|
|
||||||
},
|
|
||||||
)
|
|
||||||
: Container();
|
|
||||||
} else {
|
|
||||||
return DraggableCard(
|
|
||||||
imagePath: device.getDefaultIcon(device.productType),
|
|
||||||
title: device.name ?? '',
|
|
||||||
deviceData: {
|
|
||||||
'device': device,
|
|
||||||
'imagePath': device.getDefaultIcon(device.productType),
|
|
||||||
'title': device.name ?? '',
|
|
||||||
'deviceId': device.uuid,
|
|
||||||
'productType': device.productType,
|
|
||||||
'functions': device.functions,
|
|
||||||
'uniqueCustomId': '',
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}).toList(),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return const Center(child: CircularProgressIndicator());
|
return const Center(child: CircularProgressIndicator());
|
||||||
},
|
}
|
||||||
),
|
|
||||||
|
Future.delayed(const Duration(seconds: 1), () {
|
||||||
|
if (state.devices.isEmpty) {
|
||||||
|
return const Center(child: Text('No devices found'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
List<AllDevicesModel> deviceList = state.devices
|
||||||
|
.where((device) =>
|
||||||
|
device.productType == 'AC' ||
|
||||||
|
device.productType == '1G' ||
|
||||||
|
device.productType == '2G' ||
|
||||||
|
device.productType == '3G')
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
return Wrap(
|
||||||
|
spacing: 10,
|
||||||
|
runSpacing: 10,
|
||||||
|
children: deviceList.asMap().entries.map((entry) {
|
||||||
|
final device = entry.value;
|
||||||
|
if (state.searchText != null && state.searchText!.isNotEmpty) {
|
||||||
|
return device.name!
|
||||||
|
.toLowerCase()
|
||||||
|
.contains(state.searchText!.toLowerCase())
|
||||||
|
? DraggableCard(
|
||||||
|
imagePath: device.getDefaultIcon(device.productType),
|
||||||
|
title: device.name ?? '',
|
||||||
|
deviceData: {
|
||||||
|
'device': device,
|
||||||
|
'imagePath': device.getDefaultIcon(device.productType),
|
||||||
|
'title': device.name ?? '',
|
||||||
|
'deviceId': device.uuid,
|
||||||
|
'productType': device.productType,
|
||||||
|
'functions': device.functions,
|
||||||
|
'uniqueCustomId': '',
|
||||||
|
},
|
||||||
|
)
|
||||||
|
: Container();
|
||||||
|
} else {
|
||||||
|
return DraggableCard(
|
||||||
|
imagePath: device.getDefaultIcon(device.productType),
|
||||||
|
title: device.name ?? '',
|
||||||
|
deviceData: {
|
||||||
|
'device': device,
|
||||||
|
'imagePath': device.getDefaultIcon(device.productType),
|
||||||
|
'title': device.name ?? '',
|
||||||
|
'deviceId': device.uuid,
|
||||||
|
'productType': device.productType,
|
||||||
|
'functions': device.functions,
|
||||||
|
'uniqueCustomId': '',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}).toList(),
|
||||||
|
);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,20 +11,36 @@ class AutomationDialog extends StatefulWidget {
|
|||||||
final String automationName;
|
final String automationName;
|
||||||
final String automationId;
|
final String automationId;
|
||||||
final String uniqueCustomId;
|
final String uniqueCustomId;
|
||||||
|
final String? passedAutomationActionExecutor;
|
||||||
|
|
||||||
const AutomationDialog({
|
const AutomationDialog({
|
||||||
super.key,
|
super.key,
|
||||||
required this.automationName,
|
required this.automationName,
|
||||||
required this.automationId,
|
required this.automationId,
|
||||||
required this.uniqueCustomId,
|
required this.uniqueCustomId,
|
||||||
|
this.passedAutomationActionExecutor,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_AutomationDialogState createState() => _AutomationDialogState();
|
State<AutomationDialog> createState() => _AutomationDialogState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _AutomationDialogState extends State<AutomationDialog> {
|
class _AutomationDialogState extends State<AutomationDialog> {
|
||||||
bool _isEnabled = true;
|
String? selectedAutomationActionExecutor;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
List<DeviceFunctionData>? functions = context
|
||||||
|
.read<RoutineBloc>()
|
||||||
|
.state
|
||||||
|
.selectedFunctions[widget.uniqueCustomId];
|
||||||
|
for (DeviceFunctionData data in functions ?? []) {
|
||||||
|
if (data.entityId == widget.automationId) {
|
||||||
|
selectedAutomationActionExecutor = data.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -41,26 +57,25 @@ class _AutomationDialogState extends State<AutomationDialog> {
|
|||||||
ListTile(
|
ListTile(
|
||||||
leading: SvgPicture.asset(Assets.acPower, width: 24, height: 24),
|
leading: SvgPicture.asset(Assets.acPower, width: 24, height: 24),
|
||||||
title: const Text('Enable'),
|
title: const Text('Enable'),
|
||||||
trailing: Radio<bool>(
|
trailing: Radio<String?>(
|
||||||
value: true,
|
value: 'rule_enable',
|
||||||
groupValue: _isEnabled,
|
groupValue: selectedAutomationActionExecutor,
|
||||||
onChanged: (bool? value) {
|
onChanged: (String? value) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_isEnabled = value!;
|
selectedAutomationActionExecutor = 'rule_enable';
|
||||||
});
|
});
|
||||||
},
|
}),
|
||||||
),
|
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
leading:
|
leading:
|
||||||
SvgPicture.asset(Assets.acPowerOff, width: 24, height: 24),
|
SvgPicture.asset(Assets.acPowerOff, width: 24, height: 24),
|
||||||
title: const Text('Disable'),
|
title: const Text('Disable'),
|
||||||
trailing: Radio<bool>(
|
trailing: Radio<String?>(
|
||||||
value: false,
|
value: 'rule_disable',
|
||||||
groupValue: _isEnabled,
|
groupValue: selectedAutomationActionExecutor,
|
||||||
onChanged: (bool? value) {
|
onChanged: (String? value) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_isEnabled = value!;
|
selectedAutomationActionExecutor = 'rule_disable';
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -68,23 +83,25 @@ class _AutomationDialogState extends State<AutomationDialog> {
|
|||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
DialogFooter(
|
DialogFooter(
|
||||||
onConfirm: () {
|
onConfirm: () {
|
||||||
context.read<RoutineBloc>().add(
|
if (selectedAutomationActionExecutor != null) {
|
||||||
AddFunctionToRoutine(
|
context.read<RoutineBloc>().add(
|
||||||
[
|
AddFunctionToRoutine(
|
||||||
DeviceFunctionData(
|
[
|
||||||
entityId: widget.automationId,
|
DeviceFunctionData(
|
||||||
functionCode: 'automation',
|
entityId: widget.automationId,
|
||||||
value: _isEnabled ? 'rule_enable' : 'rule_disable',
|
functionCode: 'automation',
|
||||||
operationName: 'Automation',
|
value: selectedAutomationActionExecutor,
|
||||||
),
|
operationName: 'Automation',
|
||||||
],
|
),
|
||||||
widget.uniqueCustomId,
|
],
|
||||||
),
|
widget.uniqueCustomId,
|
||||||
);
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
Navigator.of(context).pop(true);
|
Navigator.of(context).pop(true);
|
||||||
},
|
},
|
||||||
onCancel: () => Navigator.of(context).pop(false),
|
onCancel: () => Navigator.of(context).pop(),
|
||||||
isConfirmEnabled: true,
|
isConfirmEnabled: selectedAutomationActionExecutor != null,
|
||||||
dialogWidth: 400,
|
dialogWidth: 400,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/all_devices/bloc/switch_tabs/switch_tabs_bloc.dart';
|
|
||||||
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart';
|
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
||||||
@ -49,11 +48,11 @@ class DiscardDialog {
|
|||||||
onConfirm: () {
|
onConfirm: () {
|
||||||
context.read<RoutineBloc>().add(ResetRoutineState());
|
context.read<RoutineBloc>().add(ResetRoutineState());
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
BlocProvider.of<SwitchTabsBloc>(context).add(
|
BlocProvider.of<RoutineBloc>(context).add(
|
||||||
const CreateNewRoutineViewEvent(false),
|
const CreateNewRoutineViewEvent(createRoutineView: false),
|
||||||
);
|
);
|
||||||
BlocProvider.of<SwitchTabsBloc>(context).add(
|
BlocProvider.of<RoutineBloc>(context).add(
|
||||||
const TriggerSwitchTabsEvent(true),
|
const TriggerSwitchTabsEvent(isRoutineTab: true),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/routiens/bloc/effective_period/effect_period_bloc.dart';
|
import 'package:syncrow_web/pages/routiens/bloc/effective_period/effect_period_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/routiens/bloc/effective_period/effect_period_event.dart';
|
||||||
import 'package:syncrow_web/pages/routiens/bloc/effective_period/effect_period_state.dart';
|
import 'package:syncrow_web/pages/routiens/bloc/effective_period/effect_period_state.dart';
|
||||||
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart';
|
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/routiens/bloc/setting_bloc/setting_bloc.dart';
|
import 'package:syncrow_web/pages/routiens/bloc/setting_bloc/setting_bloc.dart';
|
||||||
@ -9,6 +10,7 @@ import 'package:syncrow_web/pages/routiens/bloc/setting_bloc/setting_state.dart'
|
|||||||
import 'package:syncrow_web/pages/routiens/models/create_scene_and_autoamtion/create_automation_model.dart';
|
import 'package:syncrow_web/pages/routiens/models/create_scene_and_autoamtion/create_automation_model.dart';
|
||||||
import 'package:syncrow_web/pages/routiens/models/icon_model.dart';
|
import 'package:syncrow_web/pages/routiens/models/icon_model.dart';
|
||||||
import 'package:syncrow_web/pages/routiens/view/effective_period_view.dart';
|
import 'package:syncrow_web/pages/routiens/view/effective_period_view.dart';
|
||||||
|
import 'package:syncrow_web/pages/routiens/widgets/delete_scene.dart';
|
||||||
import 'package:syncrow_web/pages/routiens/widgets/dialog_header.dart';
|
import 'package:syncrow_web/pages/routiens/widgets/dialog_header.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
@ -22,11 +24,18 @@ class SettingHelper {
|
|||||||
context: context,
|
context: context,
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
final isAutomation = context.read<RoutineBloc>().state.isAutomation;
|
final isAutomation = context.read<RoutineBloc>().state.isAutomation;
|
||||||
|
final effectiveTime = context.read<RoutineBloc>().state.effectiveTime;
|
||||||
|
|
||||||
return MultiBlocProvider(
|
return MultiBlocProvider(
|
||||||
providers: [
|
providers: [
|
||||||
BlocProvider(
|
if (effectiveTime != null)
|
||||||
create: (_) => EffectPeriodBloc(),
|
BlocProvider(
|
||||||
),
|
create: (_) => EffectPeriodBloc()..add(InitialEffectPeriodEvent(effectiveTime)),
|
||||||
|
),
|
||||||
|
if (effectiveTime == null)
|
||||||
|
BlocProvider(
|
||||||
|
create: (_) => EffectPeriodBloc(),
|
||||||
|
),
|
||||||
BlocProvider(
|
BlocProvider(
|
||||||
create: (_) => SettingBloc()..add(InitialEvent(selectedIcon: iconId ?? ''))),
|
create: (_) => SettingBloc()..add(InitialEvent(selectedIcon: iconId ?? ''))),
|
||||||
],
|
],
|
||||||
@ -44,7 +53,7 @@ class SettingHelper {
|
|||||||
}
|
}
|
||||||
return Container(
|
return Container(
|
||||||
width: context.read<SettingBloc>().isExpanded ? 800 : 400,
|
width: context.read<SettingBloc>().isExpanded ? 800 : 400,
|
||||||
height: context.read<SettingBloc>().isExpanded && isAutomation ? 500 : 300,
|
height: context.read<SettingBloc>().isExpanded && isAutomation ? 500 : 350,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
@ -167,6 +176,9 @@ class SettingHelper {
|
|||||||
fontSize: 14)),
|
fontSize: 14)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
if (context.read<RoutineBloc>().state.isUpdate ??
|
||||||
|
false)
|
||||||
|
const DeleteSceneWidget()
|
||||||
],
|
],
|
||||||
)),
|
)),
|
||||||
],
|
],
|
||||||
@ -284,6 +296,9 @@ class SettingHelper {
|
|||||||
fontSize: 14)),
|
fontSize: 14)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
if (context.read<RoutineBloc>().state.isUpdate ??
|
||||||
|
false)
|
||||||
|
const DeleteSceneWidget()
|
||||||
],
|
],
|
||||||
)),
|
)),
|
||||||
],
|
],
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/common/buttons/default_button.dart';
|
import 'package:syncrow_web/pages/common/buttons/default_button.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/all_devices/bloc/switch_tabs/switch_tabs_bloc.dart';
|
|
||||||
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart';
|
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/routiens/helper/save_routine_helper.dart';
|
import 'package:syncrow_web/pages/routiens/helper/save_routine_helper.dart';
|
||||||
import 'package:syncrow_web/pages/routiens/widgets/routine_dialogs/discard_dialog.dart';
|
import 'package:syncrow_web/pages/routiens/widgets/routine_dialogs/discard_dialog.dart';
|
||||||
@ -10,20 +9,47 @@ import 'package:syncrow_web/utils/color_manager.dart';
|
|||||||
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
||||||
import 'package:syncrow_web/utils/style.dart';
|
import 'package:syncrow_web/utils/style.dart';
|
||||||
|
|
||||||
class RoutineSearchAndButtons extends StatelessWidget {
|
class RoutineSearchAndButtons extends StatefulWidget {
|
||||||
const RoutineSearchAndButtons({
|
const RoutineSearchAndButtons({
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<RoutineSearchAndButtons> createState() => _RoutineSearchAndButtonsState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _RoutineSearchAndButtonsState extends State<RoutineSearchAndButtons> {
|
||||||
|
late TextEditingController _nameController;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_nameController = TextEditingController();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_nameController.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocBuilder<RoutineBloc, RoutineState>(
|
return BlocBuilder<RoutineBloc, RoutineState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
|
_nameController.text = state.routineName ?? '';
|
||||||
return LayoutBuilder(
|
return LayoutBuilder(
|
||||||
builder: (BuildContext context, BoxConstraints constraints) {
|
builder: (BuildContext context, BoxConstraints constraints) {
|
||||||
return Wrap(
|
return Wrap(
|
||||||
runSpacing: 16,
|
runSpacing: 16,
|
||||||
children: [
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: Text(
|
||||||
|
state.errorMessage ?? '',
|
||||||
|
style: const TextStyle(color: Colors.red),
|
||||||
|
),
|
||||||
|
),
|
||||||
Row(
|
Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.end,
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
@ -37,24 +63,6 @@ class RoutineSearchAndButtons extends StatelessWidget {
|
|||||||
constraints: BoxConstraints(
|
constraints: BoxConstraints(
|
||||||
maxWidth:
|
maxWidth:
|
||||||
constraints.maxWidth > 700 ? 450 : constraints.maxWidth - 32),
|
constraints.maxWidth > 700 ? 450 : constraints.maxWidth - 32),
|
||||||
// child: StatefulTextField(
|
|
||||||
// title: 'Routine Name',
|
|
||||||
// initialValue: state.routineName ?? '',
|
|
||||||
// height: 40,
|
|
||||||
// // controller: TextEditingController(),
|
|
||||||
// hintText: 'Please enter the name',
|
|
||||||
// boxDecoration: containerWhiteDecoration,
|
|
||||||
// elevation: 0,
|
|
||||||
// borderRadius: 15,
|
|
||||||
// isRequired: true,
|
|
||||||
// width: 450,
|
|
||||||
// onSubmitted: (value) {
|
|
||||||
// // context.read<RoutineBloc>().add(SetRoutineName(value));
|
|
||||||
// },
|
|
||||||
// onChanged: (value) {
|
|
||||||
// context.read<RoutineBloc>().add(SetRoutineName(value));
|
|
||||||
// },
|
|
||||||
// ),
|
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
@ -81,7 +89,7 @@ class RoutineSearchAndButtons extends StatelessWidget {
|
|||||||
child: TextFormField(
|
child: TextFormField(
|
||||||
style: context.textTheme.bodyMedium!
|
style: context.textTheme.bodyMedium!
|
||||||
.copyWith(color: ColorsManager.blackColor),
|
.copyWith(color: ColorsManager.blackColor),
|
||||||
initialValue: state.routineName,
|
controller: _nameController,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: 'Please enter the name',
|
hintText: 'Please enter the name',
|
||||||
hintStyle: context.textTheme.bodyMedium!
|
hintStyle: context.textTheme.bodyMedium!
|
||||||
@ -90,8 +98,10 @@ class RoutineSearchAndButtons extends StatelessWidget {
|
|||||||
const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
|
const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
),
|
),
|
||||||
onChanged: (value) {
|
onTapOutside: (_) {
|
||||||
context.read<RoutineBloc>().add(SetRoutineName(value));
|
context
|
||||||
|
.read<RoutineBloc>()
|
||||||
|
.add(SetRoutineName(_nameController.text));
|
||||||
},
|
},
|
||||||
validator: (value) {
|
validator: (value) {
|
||||||
if (value == null || value.isEmpty) {
|
if (value == null || value.isEmpty) {
|
||||||
@ -115,6 +125,7 @@ class RoutineSearchAndButtons extends StatelessWidget {
|
|||||||
? () async {
|
? () async {
|
||||||
final result = await SettingHelper.showSettingDialog(
|
final result = await SettingHelper.showSettingDialog(
|
||||||
context: context,
|
context: context,
|
||||||
|
iconId: state.selectedIcon ?? '',
|
||||||
);
|
);
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
context
|
context
|
||||||
@ -208,16 +219,18 @@ class RoutineSearchAndButtons extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final result =
|
// final result =
|
||||||
await SaveRoutineHelper.showSaveRoutineDialog(context);
|
// await
|
||||||
if (result != null && result) {
|
BlocProvider.of<RoutineBloc>(context).add(ResetErrorMessage());
|
||||||
BlocProvider.of<SwitchTabsBloc>(context).add(
|
SaveRoutineHelper.showSaveRoutineDialog(context);
|
||||||
const CreateNewRoutineViewEvent(false),
|
// if (result != null && result) {
|
||||||
);
|
// BlocProvider.of<RoutineBloc>(context).add(
|
||||||
BlocProvider.of<SwitchTabsBloc>(context).add(
|
// const CreateNewRoutineViewEvent(createRoutineView: false),
|
||||||
const TriggerSwitchTabsEvent(true),
|
// );
|
||||||
);
|
// BlocProvider.of<RoutineBloc>(context).add(
|
||||||
}
|
// const TriggerSwitchTabsEvent(isRoutineTab: true),
|
||||||
|
// );
|
||||||
|
// }
|
||||||
},
|
},
|
||||||
borderRadius: 15,
|
borderRadius: 15,
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
@ -249,8 +262,7 @@ class RoutineSearchAndButtons extends StatelessWidget {
|
|||||||
onPressed: state.isAutomation || state.isTabToRun
|
onPressed: state.isAutomation || state.isTabToRun
|
||||||
? () async {
|
? () async {
|
||||||
final result = await SettingHelper.showSettingDialog(
|
final result = await SettingHelper.showSettingDialog(
|
||||||
context: context,
|
context: context, iconId: state.selectedIcon ?? '');
|
||||||
);
|
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
context.read<RoutineBloc>().add(AddSelectedIcon(result));
|
context.read<RoutineBloc>().add(AddSelectedIcon(result));
|
||||||
}
|
}
|
||||||
@ -301,7 +313,7 @@ class RoutineSearchAndButtons extends StatelessWidget {
|
|||||||
width: 200,
|
width: 200,
|
||||||
child: Center(
|
child: Center(
|
||||||
child: DefaultButton(
|
child: DefaultButton(
|
||||||
onPressed: () {
|
onPressed: () async {
|
||||||
if (state.routineName == null || state.routineName!.isEmpty) {
|
if (state.routineName == null || state.routineName!.isEmpty) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(
|
SnackBar(
|
||||||
@ -335,7 +347,18 @@ class RoutineSearchAndButtons extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// final result =
|
||||||
|
// await
|
||||||
|
BlocProvider.of<RoutineBloc>(context).add(ResetErrorMessage());
|
||||||
SaveRoutineHelper.showSaveRoutineDialog(context);
|
SaveRoutineHelper.showSaveRoutineDialog(context);
|
||||||
|
// if (result != null && result) {
|
||||||
|
// BlocProvider.of<RoutineBloc>(context).add(
|
||||||
|
// const CreateNewRoutineViewEvent(createRoutineView: false),
|
||||||
|
// );
|
||||||
|
// BlocProvider.of<RoutineBloc>(context).add(
|
||||||
|
// const TriggerSwitchTabsEvent(isRoutineTab: true),
|
||||||
|
// );
|
||||||
|
// }
|
||||||
},
|
},
|
||||||
borderRadius: 15,
|
borderRadius: 15,
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
|
|||||||
@ -30,69 +30,112 @@ class ThenContainer extends StatelessWidget {
|
|||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 18, fontWeight: FontWeight.bold)),
|
fontSize: 18, fontWeight: FontWeight.bold)),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
Wrap(
|
state.isLoading && state.isUpdate == true
|
||||||
spacing: 8,
|
? const Center(
|
||||||
runSpacing: 8,
|
child: CircularProgressIndicator(),
|
||||||
children: List.generate(
|
)
|
||||||
state.thenItems.length,
|
: Wrap(
|
||||||
(index) => GestureDetector(
|
spacing: 8,
|
||||||
onTap: () async {
|
runSpacing: 8,
|
||||||
if (state.thenItems[index]['deviceId'] ==
|
children: List.generate(
|
||||||
'delay') {
|
state.thenItems.length,
|
||||||
final result = await DelayHelper
|
(index) => GestureDetector(
|
||||||
.showDelayPickerDialog(
|
onTap: () async {
|
||||||
context, state.thenItems[index]);
|
if (state.thenItems[index]
|
||||||
|
['deviceId'] ==
|
||||||
|
'delay') {
|
||||||
|
final result = await DelayHelper
|
||||||
|
.showDelayPickerDialog(context,
|
||||||
|
state.thenItems[index]);
|
||||||
|
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
context
|
context
|
||||||
.read<RoutineBloc>()
|
.read<RoutineBloc>()
|
||||||
.add(AddToThenContainer({
|
.add(AddToThenContainer({
|
||||||
...state.thenItems[index],
|
...state.thenItems[index],
|
||||||
'imagePath': Assets.delay,
|
'imagePath': Assets.delay,
|
||||||
'title': 'Delay',
|
'title': 'Delay',
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final result = await DeviceDialogHelper
|
if (state.thenItems[index]['type'] ==
|
||||||
.showDeviceDialog(
|
'automation') {
|
||||||
context, state.thenItems[index],
|
final result = await showDialog<bool>(
|
||||||
removeComparetors: true);
|
context: context,
|
||||||
|
builder: (BuildContext context) =>
|
||||||
|
AutomationDialog(
|
||||||
|
automationName:
|
||||||
|
state.thenItems[index]
|
||||||
|
['name'] ??
|
||||||
|
'Automation',
|
||||||
|
automationId:
|
||||||
|
state.thenItems[index]
|
||||||
|
['deviceId'] ??
|
||||||
|
'',
|
||||||
|
uniqueCustomId:
|
||||||
|
state.thenItems[index]
|
||||||
|
['uniqueCustomId'],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
context.read<RoutineBloc>().add(
|
context
|
||||||
AddToThenContainer(
|
.read<RoutineBloc>()
|
||||||
state.thenItems[index]));
|
.add(AddToThenContainer({
|
||||||
} else if (!['AC', '1G', '2G', '3G']
|
...state.thenItems[index],
|
||||||
.contains(state.thenItems[index]
|
'imagePath':
|
||||||
['productType'])) {
|
Assets.automation,
|
||||||
context.read<RoutineBloc>().add(
|
'title':
|
||||||
AddToThenContainer(
|
state.thenItems[index]
|
||||||
state.thenItems[index]));
|
['name'] ??
|
||||||
}
|
state.thenItems[index]
|
||||||
},
|
['title'],
|
||||||
child: DraggableCard(
|
}));
|
||||||
imagePath: state.thenItems[index]
|
}
|
||||||
['imagePath'] ??
|
return;
|
||||||
'',
|
}
|
||||||
title:
|
|
||||||
state.thenItems[index]['title'] ?? '',
|
final result = await DeviceDialogHelper
|
||||||
deviceData: state.thenItems[index],
|
.showDeviceDialog(
|
||||||
padding: const EdgeInsets.symmetric(
|
context, state.thenItems[index],
|
||||||
horizontal: 4, vertical: 8),
|
removeComparetors: true);
|
||||||
isFromThen: true,
|
|
||||||
isFromIf: false,
|
if (result != null) {
|
||||||
onRemove: () {
|
context.read<RoutineBloc>().add(
|
||||||
context.read<RoutineBloc>().add(
|
AddToThenContainer(
|
||||||
RemoveDragCard(
|
state.thenItems[index]));
|
||||||
index: index,
|
} else if (!['AC', '1G', '2G', '3G']
|
||||||
isFromThen: true,
|
.contains(state.thenItems[index]
|
||||||
key: state.thenItems[index]
|
['productType'])) {
|
||||||
['uniqueCustomId']));
|
context.read<RoutineBloc>().add(
|
||||||
},
|
AddToThenContainer(
|
||||||
),
|
state.thenItems[index]));
|
||||||
))),
|
}
|
||||||
|
},
|
||||||
|
child: DraggableCard(
|
||||||
|
imagePath: state.thenItems[index]
|
||||||
|
['imagePath'] ??
|
||||||
|
'',
|
||||||
|
title: state.thenItems[index]
|
||||||
|
['title'] ??
|
||||||
|
'',
|
||||||
|
deviceData: state.thenItems[index],
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 4, vertical: 8),
|
||||||
|
isFromThen: true,
|
||||||
|
isFromIf: false,
|
||||||
|
onRemove: () {
|
||||||
|
context.read<RoutineBloc>().add(
|
||||||
|
RemoveDragCard(
|
||||||
|
index: index,
|
||||||
|
isFromThen: true,
|
||||||
|
key: state.thenItems[index]
|
||||||
|
['uniqueCustomId']));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
))),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -109,6 +152,12 @@ class ThenContainer extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mutableData['type'] == 'automation') {
|
if (mutableData['type'] == 'automation') {
|
||||||
|
int index = state.thenItems.indexWhere(
|
||||||
|
(item) => item['deviceId'] == mutableData['deviceId']);
|
||||||
|
if (index != -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
final result = await showDialog<bool>(
|
final result = await showDialog<bool>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (BuildContext context) => AutomationDialog(
|
builder: (BuildContext context) => AutomationDialog(
|
||||||
@ -129,9 +178,14 @@ class ThenContainer extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mutableData['type'] == 'tap_to_run' && state.isAutomation) {
|
if (mutableData['type'] == 'tap_to_run' && state.isAutomation) {
|
||||||
|
int index = state.thenItems.indexWhere(
|
||||||
|
(item) => item['deviceId'] == mutableData['deviceId']);
|
||||||
|
if (index != -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
context.read<RoutineBloc>().add(AddToThenContainer({
|
context.read<RoutineBloc>().add(AddToThenContainer({
|
||||||
...mutableData,
|
...mutableData,
|
||||||
'imagePath': Assets.logo,
|
'imagePath': mutableData['imagePath'] ?? Assets.logo,
|
||||||
'title': mutableData['name'],
|
'title': mutableData['name'],
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/model/community_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/model/product_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/product_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/model/space_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/bloc/space_management_event.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/bloc/space_management_event.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/bloc/space_management_state.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/bloc/space_management_state.dart';
|
||||||
import 'package:syncrow_web/services/product_api.dart';
|
import 'package:syncrow_web/services/product_api.dart';
|
||||||
import 'package:syncrow_web/services/space_mana_api.dart';
|
import 'package:syncrow_web/services/space_mana_api.dart';
|
||||||
|
|
||||||
@ -1,7 +1,7 @@
|
|||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/model/community_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/model/space_model.dart'; // Import for Offset
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart'; // Import for Offset
|
||||||
|
|
||||||
abstract class SpaceManagementEvent extends Equatable {
|
abstract class SpaceManagementEvent extends Equatable {
|
||||||
const SpaceManagementEvent();
|
const SpaceManagementEvent();
|
||||||
@ -1,7 +1,7 @@
|
|||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/model/community_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/model/product_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/product_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/model/space_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart';
|
||||||
|
|
||||||
abstract class SpaceManagementState extends Equatable {
|
abstract class SpaceManagementState extends Equatable {
|
||||||
const SpaceManagementState();
|
const SpaceManagementState();
|
||||||
@ -1,5 +1,5 @@
|
|||||||
import 'package:syncrow_web/pages/auth/model/region_model.dart';
|
import 'package:syncrow_web/pages/auth/model/region_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/model/space_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart';
|
||||||
|
|
||||||
class CommunityModel {
|
class CommunityModel {
|
||||||
final String uuid;
|
final String uuid;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
import 'package:syncrow_web/pages/spaces_management/model/space_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart';
|
||||||
|
|
||||||
class Connection {
|
class Connection {
|
||||||
final SpaceModel startSpace;
|
final SpaceModel startSpace;
|
||||||
@ -1,7 +1,7 @@
|
|||||||
import 'dart:ui';
|
import 'dart:ui';
|
||||||
import 'package:syncrow_web/pages/spaces_management/model/community_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/model/connection_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/connection_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/model/selected_product_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/selected_product_model.dart';
|
||||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
import 'package:uuid/uuid.dart';
|
import 'package:uuid/uuid.dart';
|
||||||
|
|
||||||
@ -1,13 +1,13 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/shared/navigate_home_grid_view.dart';
|
import 'package:syncrow_web/pages/device_managment/shared/navigate_home_grid_view.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/bloc/space_management_bloc.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/bloc/space_management_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/bloc/space_management_event.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/bloc/space_management_event.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/bloc/space_management_state.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/bloc/space_management_state.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/model/community_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/model/product_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/product_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/model/space_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/widgets/loaded_space_widget.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/loaded_space_widget.dart';
|
||||||
import 'package:syncrow_web/services/product_api.dart';
|
import 'package:syncrow_web/services/product_api.dart';
|
||||||
import 'package:syncrow_web/services/space_mana_api.dart';
|
import 'package:syncrow_web/services/space_mana_api.dart';
|
||||||
import 'package:syncrow_web/web_layout/web_scaffold.dart';
|
import 'package:syncrow_web/web_layout/web_scaffold.dart';
|
||||||
@ -1,9 +1,9 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
import 'package:syncrow_web/pages/common/buttons/default_button.dart';
|
import 'package:syncrow_web/pages/common/buttons/default_button.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/model/product_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/product_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/model/selected_product_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/selected_product_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/widgets/counter_widget.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/counter_widget.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
||||||
@ -1,9 +1,9 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/bloc/space_management_bloc.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/bloc/space_management_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/bloc/space_management_event.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/bloc/space_management_event.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/model/community_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/widgets/dialogs/create_community_dialog.dart';
|
import 'package:syncrow_web/pages/spaces_management/create_community/view/create_community_dialog.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
|
||||||
class BlankCommunityWidget extends StatefulWidget {
|
class BlankCommunityWidget extends StatefulWidget {
|
||||||
@ -72,7 +72,8 @@ class _BlankCommunityWidgetState extends State<BlankCommunityWidget> {
|
|||||||
showDialog(
|
showDialog(
|
||||||
context: parentContext,
|
context: parentContext,
|
||||||
builder: (context) => CreateCommunityDialog(
|
builder: (context) => CreateCommunityDialog(
|
||||||
communities: widget.communities,
|
isEditMode: false,
|
||||||
|
existingCommunityNames: widget.communities.map((community) => community.name).toList(),
|
||||||
onCreateCommunity: (String communityName, String description) {
|
onCreateCommunity: (String communityName, String description) {
|
||||||
parentContext.read<SpaceManagementBloc>().add(
|
parentContext.read<SpaceManagementBloc>().add(
|
||||||
CreateCommunityEvent(
|
CreateCommunityEvent(
|
||||||
@ -84,4 +85,5 @@ class _BlankCommunityWidgetState extends State<BlankCommunityWidget> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1,10 +1,12 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
import 'package:syncrow_web/pages/common/buttons/default_button.dart';
|
import 'package:syncrow_web/pages/common/buttons/default_button.dart';
|
||||||
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
|
||||||
|
import 'package:syncrow_web/pages/spaces_management/create_community/view/create_community_dialog.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
|
|
||||||
class CommunityStructureHeader extends StatelessWidget {
|
class CommunityStructureHeader extends StatefulWidget {
|
||||||
final String? communityName;
|
final String? communityName;
|
||||||
final bool isEditingName;
|
final bool isEditingName;
|
||||||
final bool isSave;
|
final bool isSave;
|
||||||
@ -13,19 +15,28 @@ class CommunityStructureHeader extends StatelessWidget {
|
|||||||
final VoidCallback onDelete;
|
final VoidCallback onDelete;
|
||||||
final VoidCallback onEditName;
|
final VoidCallback onEditName;
|
||||||
final ValueChanged<String> onNameSubmitted;
|
final ValueChanged<String> onNameSubmitted;
|
||||||
|
final List<CommunityModel> communities;
|
||||||
|
final CommunityModel? community;
|
||||||
|
|
||||||
const CommunityStructureHeader({
|
const CommunityStructureHeader(
|
||||||
Key? key,
|
{super.key,
|
||||||
required this.communityName,
|
required this.communityName,
|
||||||
required this.isSave,
|
required this.isSave,
|
||||||
required this.isEditingName,
|
required this.isEditingName,
|
||||||
required this.nameController,
|
required this.nameController,
|
||||||
required this.onSave,
|
required this.onSave,
|
||||||
required this.onDelete,
|
required this.onDelete,
|
||||||
required this.onEditName,
|
required this.onEditName,
|
||||||
required this.onNameSubmitted,
|
required this.onNameSubmitted,
|
||||||
}) : super(key: key);
|
this.community,
|
||||||
|
required this.communities});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<CommunityStructureHeader> createState() =>
|
||||||
|
_CommunityStructureHeaderState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _CommunityStructureHeaderState extends State<CommunityStructureHeader> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
@ -60,47 +71,63 @@ class CommunityStructureHeader extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _showCreateCommunityDialog(BuildContext parentContext) {
|
||||||
|
showDialog(
|
||||||
|
context: parentContext,
|
||||||
|
builder: (context) => CreateCommunityDialog(
|
||||||
|
isEditMode: true,
|
||||||
|
existingCommunityNames:
|
||||||
|
widget.communities.map((community) => community.name).toList(),
|
||||||
|
initialName: widget.community?.name ?? '',
|
||||||
|
onCreateCommunity: (String communityName, String description) {
|
||||||
|
widget.onNameSubmitted(communityName);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Widget _buildCommunityInfo(ThemeData theme, double screenWidth) {
|
Widget _buildCommunityInfo(ThemeData theme, double screenWidth) {
|
||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
'Community Structure',
|
'Community Structure',
|
||||||
style: theme.textTheme.headlineLarge?.copyWith(color: ColorsManager.blackColor),
|
style: theme.textTheme.headlineLarge
|
||||||
|
?.copyWith(color: ColorsManager.blackColor),
|
||||||
),
|
),
|
||||||
if (communityName != null)
|
if (widget.communityName != null)
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
if (!isEditingName)
|
if (!widget.isEditingName)
|
||||||
Flexible(
|
Flexible(
|
||||||
child: Text(
|
child: Text(
|
||||||
communityName!,
|
widget.communityName!,
|
||||||
style:
|
style: theme.textTheme.bodyLarge
|
||||||
theme.textTheme.bodyLarge?.copyWith(color: ColorsManager.blackColor),
|
?.copyWith(color: ColorsManager.blackColor),
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (isEditingName)
|
if (widget.isEditingName)
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: screenWidth * 0.1,
|
width: screenWidth * 0.1,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
controller: nameController,
|
controller: widget.nameController,
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
isDense: true,
|
isDense: true,
|
||||||
),
|
),
|
||||||
style:
|
style: theme.textTheme.bodyLarge
|
||||||
theme.textTheme.bodyLarge?.copyWith(color: ColorsManager.blackColor),
|
?.copyWith(color: ColorsManager.blackColor),
|
||||||
onSubmitted: onNameSubmitted,
|
onSubmitted: widget.onNameSubmitted,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 2),
|
const SizedBox(width: 2),
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap: onEditName,
|
onTap: () => _showCreateCommunityDialog(context),
|
||||||
child: SvgPicture.asset(
|
child: SvgPicture.asset(
|
||||||
Assets.iconEdit,
|
Assets.iconEdit,
|
||||||
width: 16,
|
width: 16,
|
||||||
@ -110,7 +137,7 @@ class CommunityStructureHeader extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (isSave) ...[
|
if (widget.isSave) ...[
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
_buildActionButtons(theme),
|
_buildActionButtons(theme),
|
||||||
],
|
],
|
||||||
@ -127,8 +154,9 @@ class CommunityStructureHeader extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
_buildButton(
|
_buildButton(
|
||||||
label: "Save",
|
label: "Save",
|
||||||
icon: const Icon(Icons.save, size: 18, color: ColorsManager.spaceColor),
|
icon: const Icon(Icons.save,
|
||||||
onPressed: onSave,
|
size: 18, color: ColorsManager.spaceColor),
|
||||||
|
onPressed: widget.onSave,
|
||||||
theme: theme),
|
theme: theme),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@ -159,7 +187,8 @@ class CommunityStructureHeader extends StatelessWidget {
|
|||||||
Flexible(
|
Flexible(
|
||||||
child: Text(
|
child: Text(
|
||||||
label,
|
label,
|
||||||
style: theme.textTheme.bodySmall?.copyWith(color: ColorsManager.blackColor),
|
style: theme.textTheme.bodySmall
|
||||||
|
?.copyWith(color: ColorsManager.blackColor),
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
),
|
),
|
||||||
@ -4,19 +4,19 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||||||
|
|
||||||
// Syncrow project imports
|
// Syncrow project imports
|
||||||
import 'package:syncrow_web/pages/common/buttons/add_space_button.dart';
|
import 'package:syncrow_web/pages/common/buttons/add_space_button.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/bloc/space_management_bloc.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/bloc/space_management_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/bloc/space_management_event.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/bloc/space_management_event.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/model/product_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/product_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/model/selected_product_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/selected_product_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/model/space_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/model/community_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/model/connection_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/connection_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/widgets/blank_community_widget.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/blank_community_widget.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/widgets/community_structure_header_widget.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/community_structure_header_widget.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/widgets/dialogs/create_space_dialog.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/dialogs/create_space_dialog.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/widgets/curved_line_painter.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/curved_line_painter.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/widgets/space_card_widget.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/space_card_widget.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/widgets/space_container_widget.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/space_container_widget.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
|
||||||
class CommunityStructureArea extends StatefulWidget {
|
class CommunityStructureArea extends StatefulWidget {
|
||||||
@ -119,7 +119,9 @@ class _CommunityStructureAreaState extends State<CommunityStructureArea> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
CommunityStructureHeader(
|
CommunityStructureHeader(
|
||||||
|
communities: widget.communities,
|
||||||
communityName: widget.selectedCommunity?.name,
|
communityName: widget.selectedCommunity?.name,
|
||||||
|
community: widget.selectedCommunity,
|
||||||
isSave: isSave(spaces),
|
isSave: isSave(spaces),
|
||||||
isEditingName: isEditingName,
|
isEditingName: isEditingName,
|
||||||
nameController: _nameController,
|
nameController: _nameController,
|
||||||
@ -1,5 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/model/connection_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/connection_model.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
|
||||||
class CurvedLinePainter extends CustomPainter {
|
class CurvedLinePainter extends CustomPainter {
|
||||||
@ -2,12 +2,12 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
import 'package:syncrow_web/pages/common/buttons/cancel_button.dart';
|
import 'package:syncrow_web/pages/common/buttons/cancel_button.dart';
|
||||||
import 'package:syncrow_web/pages/common/buttons/default_button.dart';
|
import 'package:syncrow_web/pages/common/buttons/default_button.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/model/product_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/product_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/model/selected_product_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/selected_product_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/model/space_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/widgets/add_device_type_widget.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/add_device_type_widget.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/widgets/dialogs/icon_selection_dialog.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/dialogs/icon_selection_dialog.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/widgets/hoverable_button.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/hoverable_button.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
import 'package:syncrow_web/utils/constants/space_icon_const.dart';
|
import 'package:syncrow_web/utils/constants/space_icon_const.dart';
|
||||||
@ -1,10 +1,10 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/model/community_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/model/product_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/product_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/model/space_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/widgets/community_structure_widget.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/community_structure_widget.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/widgets/gradient_canvas_border_widget.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/gradient_canvas_border_widget.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/widgets/sidebar_widget.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/sidebar_widget.dart';
|
||||||
|
|
||||||
class LoadedSpaceView extends StatefulWidget {
|
class LoadedSpaceView extends StatefulWidget {
|
||||||
final List<CommunityModel> communities;
|
final List<CommunityModel> communities;
|
||||||
@ -2,12 +2,12 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
import 'package:syncrow_web/common/search_bar.dart';
|
import 'package:syncrow_web/common/search_bar.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/bloc/space_management_bloc.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/bloc/space_management_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/bloc/space_management_event.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/bloc/space_management_event.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/model/community_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/model/space_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/widgets/community_tile.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/community_tile.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/widgets/space_tile_widget.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/space_tile_widget.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
import 'package:syncrow_web/utils/style.dart';
|
import 'package:syncrow_web/utils/style.dart';
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'community_dialog_event.dart';
|
||||||
|
import 'community_dialog_state.dart';
|
||||||
|
|
||||||
|
class CommunityDialogBloc extends Bloc<CommunityDialogEvent, CommunityDialogState> {
|
||||||
|
final List<String> existingCommunityNames;
|
||||||
|
|
||||||
|
CommunityDialogBloc(this.existingCommunityNames)
|
||||||
|
: super(CommunityDialogInitial()) {
|
||||||
|
on<ValidateCommunityNameEvent>((event, emit) {
|
||||||
|
final trimmedName = event.name.trim();
|
||||||
|
final isNameValid = !existingCommunityNames.contains(trimmedName);
|
||||||
|
final isNameEmpty = trimmedName.isEmpty;
|
||||||
|
|
||||||
|
emit(CommunityNameValidationState(
|
||||||
|
isNameValid: isNameValid,
|
||||||
|
isNameEmpty: isNameEmpty,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
|
||||||
|
abstract class CommunityDialogEvent extends Equatable {
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
class ValidateCommunityNameEvent extends CommunityDialogEvent {
|
||||||
|
final String name;
|
||||||
|
|
||||||
|
ValidateCommunityNameEvent(this.name);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [name];
|
||||||
|
}
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
|
||||||
|
abstract class CommunityDialogState extends Equatable {
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
class CommunityDialogInitial extends CommunityDialogState {}
|
||||||
|
|
||||||
|
class CommunityNameValidationState extends CommunityDialogState {
|
||||||
|
final bool isNameValid;
|
||||||
|
final bool isNameEmpty;
|
||||||
|
|
||||||
|
CommunityNameValidationState({
|
||||||
|
required this.isNameValid,
|
||||||
|
required this.isNameEmpty,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [isNameValid, isNameEmpty];
|
||||||
|
}
|
||||||
@ -0,0 +1,170 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/spaces_management/create_community/bloc/community_dialog_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/spaces_management/create_community/bloc/community_dialog_event.dart';
|
||||||
|
import 'package:syncrow_web/pages/spaces_management/create_community/bloc/community_dialog_state.dart';
|
||||||
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
import 'package:syncrow_web/pages/common/buttons/cancel_button.dart';
|
||||||
|
import 'package:syncrow_web/pages/common/buttons/default_button.dart';
|
||||||
|
|
||||||
|
class CreateCommunityDialog extends StatelessWidget {
|
||||||
|
final Function(String name, String description) onCreateCommunity;
|
||||||
|
final List<String> existingCommunityNames;
|
||||||
|
final bool isEditMode;
|
||||||
|
final String? initialName;
|
||||||
|
|
||||||
|
const CreateCommunityDialog({
|
||||||
|
super.key,
|
||||||
|
required this.onCreateCommunity,
|
||||||
|
required this.existingCommunityNames,
|
||||||
|
required this.isEditMode,
|
||||||
|
this.initialName,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final nameController =
|
||||||
|
TextEditingController(text: isEditMode ? initialName : '');
|
||||||
|
|
||||||
|
return BlocProvider(
|
||||||
|
create: (_) => CommunityDialogBloc(existingCommunityNames),
|
||||||
|
child: Dialog(
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(20),
|
||||||
|
),
|
||||||
|
backgroundColor: ColorsManager.transparentColor,
|
||||||
|
child: Stack(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
width: MediaQuery.of(context).size.width * 0.3,
|
||||||
|
padding: const EdgeInsets.all(20),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: ColorsManager.whiteColors,
|
||||||
|
borderRadius: BorderRadius.circular(20),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: ColorsManager.blackColor.withOpacity(0.25),
|
||||||
|
blurRadius: 20,
|
||||||
|
spreadRadius: 5,
|
||||||
|
offset: const Offset(0, 5),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
child: BlocBuilder<CommunityDialogBloc, CommunityDialogState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
bool isNameValid = true;
|
||||||
|
bool isNameEmpty = false;
|
||||||
|
|
||||||
|
if (state is CommunityNameValidationState) {
|
||||||
|
isNameValid = state.isNameValid;
|
||||||
|
isNameEmpty = state.isNameEmpty;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
isEditMode ? 'Edit Community Name' : 'Community Name',
|
||||||
|
style: Theme.of(context).textTheme.headlineMedium,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 18),
|
||||||
|
TextField(
|
||||||
|
controller: nameController,
|
||||||
|
onChanged: (value) {
|
||||||
|
context
|
||||||
|
.read<CommunityDialogBloc>()
|
||||||
|
.add(ValidateCommunityNameEvent(value));
|
||||||
|
},
|
||||||
|
style: const TextStyle(
|
||||||
|
color: ColorsManager.blackColor,
|
||||||
|
),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
hintText: 'Please enter the community name',
|
||||||
|
filled: true,
|
||||||
|
fillColor: ColorsManager.boxColor,
|
||||||
|
enabledBorder: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: isNameValid && !isNameEmpty
|
||||||
|
? ColorsManager.boxColor
|
||||||
|
: ColorsManager.red,
|
||||||
|
width: 1,
|
||||||
|
),
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
|
),
|
||||||
|
focusedBorder: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
|
borderSide: const BorderSide(
|
||||||
|
color: ColorsManager.boxColor,
|
||||||
|
width: 1.5,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (!isNameValid)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 8.0),
|
||||||
|
child: Text(
|
||||||
|
'*Name already exists.',
|
||||||
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodySmall
|
||||||
|
?.copyWith(color: ColorsManager.red),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (isNameEmpty)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 8.0),
|
||||||
|
child: Text(
|
||||||
|
'*Name should not be empty.',
|
||||||
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodySmall
|
||||||
|
?.copyWith(color: ColorsManager.red),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 24),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: CancelButton(
|
||||||
|
label: 'Cancel',
|
||||||
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 16),
|
||||||
|
Expanded(
|
||||||
|
child: DefaultButton(
|
||||||
|
onPressed: () {
|
||||||
|
if (isNameValid && !isNameEmpty) {
|
||||||
|
onCreateCommunity(
|
||||||
|
nameController.text.trim(),
|
||||||
|
"",
|
||||||
|
);
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
backgroundColor: isNameValid && !isNameEmpty
|
||||||
|
? ColorsManager.secondaryColor
|
||||||
|
: ColorsManager.lightGrayColor,
|
||||||
|
borderRadius: 10,
|
||||||
|
foregroundColor: ColorsManager.whiteColors,
|
||||||
|
child: const Text('OK'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,177 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:syncrow_web/pages/common/buttons/cancel_button.dart';
|
|
||||||
import 'package:syncrow_web/pages/common/buttons/default_button.dart';
|
|
||||||
import 'package:syncrow_web/pages/spaces_management/model/community_model.dart';
|
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
|
||||||
|
|
||||||
class CreateCommunityDialog extends StatefulWidget {
|
|
||||||
final Function(String name, String description) onCreateCommunity;
|
|
||||||
final List<CommunityModel> communities;
|
|
||||||
|
|
||||||
const CreateCommunityDialog(
|
|
||||||
{super.key, required this.onCreateCommunity, required this.communities});
|
|
||||||
|
|
||||||
@override
|
|
||||||
CreateCommunityDialogState createState() => CreateCommunityDialogState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class CreateCommunityDialogState extends State<CreateCommunityDialog> {
|
|
||||||
String enteredName = '';
|
|
||||||
bool isNameFieldExist = false;
|
|
||||||
bool isNameEmpty = false;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final screenWidth = MediaQuery.of(context).size.width;
|
|
||||||
|
|
||||||
return Dialog(
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(20),
|
|
||||||
),
|
|
||||||
backgroundColor:
|
|
||||||
ColorsManager.transparentColor, // Transparent for shadow effect
|
|
||||||
child: Stack(
|
|
||||||
children: [
|
|
||||||
// Background container with shadow and rounded corners
|
|
||||||
Container(
|
|
||||||
width: screenWidth * 0.3,
|
|
||||||
padding: const EdgeInsets.all(20),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: ColorsManager.whiteColors,
|
|
||||||
borderRadius: BorderRadius.circular(20),
|
|
||||||
boxShadow: [
|
|
||||||
BoxShadow(
|
|
||||||
color: ColorsManager.blackColor.withOpacity(0.25),
|
|
||||||
blurRadius: 20,
|
|
||||||
spreadRadius: 5,
|
|
||||||
offset: const Offset(0, 5),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
const Text(
|
|
||||||
'Community Name',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 20,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
// Input field for the community name
|
|
||||||
TextField(
|
|
||||||
onChanged: (value) {
|
|
||||||
setState(() {
|
|
||||||
enteredName = value.trim();
|
|
||||||
isNameFieldExist = widget.communities.any(
|
|
||||||
(community) => community.name == enteredName,
|
|
||||||
);
|
|
||||||
if (value.isEmpty) {
|
|
||||||
isNameEmpty = true;
|
|
||||||
} else {
|
|
||||||
isNameEmpty = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
style: const TextStyle(
|
|
||||||
color: ColorsManager.blackColor,
|
|
||||||
),
|
|
||||||
decoration: InputDecoration(
|
|
||||||
hintText: 'Please enter the community name',
|
|
||||||
filled: true,
|
|
||||||
fillColor: ColorsManager.boxColor,
|
|
||||||
hintStyle: const TextStyle(
|
|
||||||
fontSize: 14,
|
|
||||||
color: ColorsManager.grayBorder,
|
|
||||||
fontWeight: FontWeight.w400,
|
|
||||||
),
|
|
||||||
border: OutlineInputBorder(
|
|
||||||
borderSide: BorderSide(
|
|
||||||
color: isNameFieldExist || isNameEmpty
|
|
||||||
? ColorsManager.red
|
|
||||||
: ColorsManager.boxColor,
|
|
||||||
width: 1),
|
|
||||||
borderRadius: BorderRadius.circular(10),
|
|
||||||
),
|
|
||||||
enabledBorder: OutlineInputBorder(
|
|
||||||
borderSide: BorderSide(
|
|
||||||
color: isNameFieldExist || isNameEmpty
|
|
||||||
? ColorsManager.red
|
|
||||||
: ColorsManager.boxColor, width: 1),
|
|
||||||
borderRadius: BorderRadius.circular(10),
|
|
||||||
),
|
|
||||||
focusedBorder: OutlineInputBorder(
|
|
||||||
borderRadius: BorderRadius.circular(10),
|
|
||||||
borderSide: BorderSide(
|
|
||||||
color: isNameFieldExist || isNameEmpty
|
|
||||||
? ColorsManager.red
|
|
||||||
: ColorsManager.boxColor,
|
|
||||||
width: 1),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (isNameFieldExist)
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(top: 8.0),
|
|
||||||
child: Text(
|
|
||||||
'*Name already exists.',
|
|
||||||
style: Theme.of(context)
|
|
||||||
.textTheme
|
|
||||||
.bodySmall
|
|
||||||
?.copyWith(color: ColorsManager.red),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (isNameEmpty)
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(top: 8.0),
|
|
||||||
child: Text(
|
|
||||||
'*Name should not be empty.',
|
|
||||||
style: Theme.of(context)
|
|
||||||
.textTheme
|
|
||||||
.bodySmall
|
|
||||||
?.copyWith(color: ColorsManager.red),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 24),
|
|
||||||
// Action buttons
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
child: CancelButton(
|
|
||||||
label: 'Cancel',
|
|
||||||
onPressed: () => Navigator.of(context).pop(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 16),
|
|
||||||
Expanded(
|
|
||||||
child: DefaultButton(
|
|
||||||
onPressed: () {
|
|
||||||
if (enteredName.isNotEmpty && !isNameFieldExist) {
|
|
||||||
widget.onCreateCommunity(
|
|
||||||
enteredName,
|
|
||||||
"",
|
|
||||||
);
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
backgroundColor: isNameFieldExist || isNameEmpty
|
|
||||||
? ColorsManager.lightGrayColor
|
|
||||||
: ColorsManager.secondaryColor,
|
|
||||||
borderRadius: 10,
|
|
||||||
foregroundColor: ColorsManager.whiteColors,
|
|
||||||
child: const Text('OK'),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,5 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/model/product_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/product_model.dart';
|
||||||
import 'package:syncrow_web/services/api/http_service.dart';
|
import 'package:syncrow_web/services/api/http_service.dart';
|
||||||
import 'package:syncrow_web/utils/constants/api_const.dart';
|
import 'package:syncrow_web/utils/constants/api_const.dart';
|
||||||
|
|
||||||
|
|||||||
@ -36,7 +36,6 @@ class SceneApi {
|
|||||||
static Future<Map<String, dynamic>> createAutomation(
|
static Future<Map<String, dynamic>> createAutomation(
|
||||||
CreateAutomationModel createAutomationModel) async {
|
CreateAutomationModel createAutomationModel) async {
|
||||||
try {
|
try {
|
||||||
debugPrint("automation body ${createAutomationModel.toMap()}");
|
|
||||||
final response = await _httpService.post(
|
final response = await _httpService.post(
|
||||||
path: ApiEndpoints.createAutomation,
|
path: ApiEndpoints.createAutomation,
|
||||||
body: createAutomationModel.toMap(),
|
body: createAutomationModel.toMap(),
|
||||||
@ -138,29 +137,49 @@ class SceneApi {
|
|||||||
path: ApiEndpoints.getAutomationDetails
|
path: ApiEndpoints.getAutomationDetails
|
||||||
.replaceAll('{automationId}', automationId),
|
.replaceAll('{automationId}', automationId),
|
||||||
showServerMessage: false,
|
showServerMessage: false,
|
||||||
expectedResponseModel: (json) => RoutineDetailsModel.fromJson(json),
|
expectedResponseModel: (json) => RoutineDetailsModel.fromMap(json),
|
||||||
|
);
|
||||||
|
return response;
|
||||||
|
} catch (e) {
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//update Scene
|
||||||
|
static updateScene(CreateSceneModel createSceneModel, String sceneId) async {
|
||||||
|
try {
|
||||||
|
final response = await _httpService.put(
|
||||||
|
path: ApiEndpoints.updateScene.replaceAll('{sceneId}', sceneId),
|
||||||
|
body: createSceneModel
|
||||||
|
.toJson(sceneId.isNotEmpty == true ? sceneId : null),
|
||||||
|
expectedResponseModel: (json) {
|
||||||
|
return json;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
return response;
|
||||||
|
} catch (e) {
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//update automation
|
||||||
|
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),
|
||||||
|
expectedResponseModel: (json) {
|
||||||
|
return json;
|
||||||
|
},
|
||||||
);
|
);
|
||||||
return response;
|
return response;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//
|
|
||||||
// //updateAutomationStatus
|
|
||||||
// static Future<bool> updateAutomationStatus(String automationId,
|
|
||||||
// AutomationStatusUpdate createAutomationEnable) async {
|
|
||||||
// try {
|
|
||||||
// final response = await _httpService.put(
|
|
||||||
// path: ApiEndpoints.updateAutomationStatus
|
|
||||||
// .replaceAll('{automationId}', automationId),
|
|
||||||
// body: createAutomationEnable.toMap(),
|
|
||||||
// expectedResponseModel: (json) => json['success'],
|
|
||||||
// );
|
|
||||||
// return response;
|
|
||||||
// } catch (e) {
|
|
||||||
// rethrow;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
//getScene
|
//getScene
|
||||||
static Future<RoutineDetailsModel> getSceneDetails(String sceneId) async {
|
static Future<RoutineDetailsModel> getSceneDetails(String sceneId) async {
|
||||||
@ -168,52 +187,15 @@ class SceneApi {
|
|||||||
final response = await _httpService.get(
|
final response = await _httpService.get(
|
||||||
path: ApiEndpoints.getScene.replaceAll('{sceneId}', sceneId),
|
path: ApiEndpoints.getScene.replaceAll('{sceneId}', sceneId),
|
||||||
showServerMessage: false,
|
showServerMessage: false,
|
||||||
expectedResponseModel: (json) => RoutineDetailsModel.fromJson(json),
|
expectedResponseModel: (json) =>
|
||||||
|
RoutineDetailsModel.fromMap(json['data']),
|
||||||
);
|
);
|
||||||
return response;
|
return response;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//
|
|
||||||
// //update Scene
|
|
||||||
// static updateScene(CreateSceneModel createSceneModel, String sceneId) async {
|
|
||||||
// try {
|
|
||||||
// final response = await _httpService.put(
|
|
||||||
// path: ApiEndpoints.updateScene.replaceAll('{sceneId}', sceneId),
|
|
||||||
// body: createSceneModel
|
|
||||||
// .toJson(sceneId.isNotEmpty == true ? sceneId : null),
|
|
||||||
// expectedResponseModel: (json) {
|
|
||||||
// return json;
|
|
||||||
// },
|
|
||||||
// );
|
|
||||||
// return response;
|
|
||||||
// } catch (e) {
|
|
||||||
// rethrow;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// //update automation
|
|
||||||
// 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),
|
|
||||||
// expectedResponseModel: (json) {
|
|
||||||
// return json;
|
|
||||||
// },
|
|
||||||
// );
|
|
||||||
// return response;
|
|
||||||
// } catch (e) {
|
|
||||||
// rethrow;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
//delete Scene
|
//delete Scene
|
||||||
static Future<bool> deleteScene(
|
static Future<bool> deleteScene(
|
||||||
{required String unitUuid, required String sceneId}) async {
|
{required String unitUuid, required String sceneId}) async {
|
||||||
@ -230,7 +212,7 @@ class SceneApi {
|
|||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// delete automation
|
// delete automation
|
||||||
static Future<bool> deleteAutomation(
|
static Future<bool> deleteAutomation(
|
||||||
{required String unitUuid, required String automationId}) async {
|
{required String unitUuid, required String automationId}) async {
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/model/community_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/model/selected_product_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/selected_product_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/model/space_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/model/space_response_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_response_model.dart';
|
||||||
import 'package:syncrow_web/services/api/http_service.dart';
|
import 'package:syncrow_web/services/api/http_service.dart';
|
||||||
import 'package:syncrow_web/utils/constants/api_const.dart';
|
import 'package:syncrow_web/utils/constants/api_const.dart';
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import 'package:syncrow_web/pages/access_management/view/access_management.dart'
|
|||||||
import 'package:syncrow_web/pages/auth/view/login_page.dart';
|
import 'package:syncrow_web/pages/auth/view/login_page.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/all_devices/view/device_managment_page.dart';
|
import 'package:syncrow_web/pages/device_managment/all_devices/view/device_managment_page.dart';
|
||||||
import 'package:syncrow_web/pages/home/view/home_page.dart';
|
import 'package:syncrow_web/pages/home/view/home_page.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/view/spaces_management_page.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/view/spaces_management_page.dart';
|
||||||
import 'package:syncrow_web/pages/visitor_password/view/visitor_password_dialog.dart';
|
import 'package:syncrow_web/pages/visitor_password/view/visitor_password_dialog.dart';
|
||||||
import 'package:syncrow_web/utils/constants/routes_const.dart';
|
import 'package:syncrow_web/utils/constants/routes_const.dart';
|
||||||
|
|
||||||
@ -32,7 +32,7 @@ class AppRoutes {
|
|||||||
),
|
),
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: RoutesConst.spacesManagementPage,
|
path: RoutesConst.spacesManagementPage,
|
||||||
builder: (context, state) => SpaceManagementPage()),
|
builder: (context, state) => const SpaceManagementPage()),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -74,4 +74,7 @@ abstract class ApiEndpoints {
|
|||||||
static const String deleteScene = '/scene/tap-to-run/{sceneId}';
|
static const String deleteScene = '/scene/tap-to-run/{sceneId}';
|
||||||
|
|
||||||
static const String deleteAutomation = '/automation/{automationId}';
|
static const String deleteAutomation = '/automation/{automationId}';
|
||||||
|
static const String updateScene = '/scene/tap-to-run/{sceneId}';
|
||||||
|
|
||||||
|
static const String updateAutomation = '/automation/{automationId}';
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
import 'package:syncrow_web/utils/navigation_service.dart';
|
import 'package:syncrow_web/utils/navigation_service.dart';
|
||||||
|
|
||||||
class CustomSnackBar {
|
class CustomSnackBar {
|
||||||
@ -11,6 +12,35 @@ class CustomSnackBar {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static redSnackBar(String message) {
|
||||||
|
final key = NavigationService.snackbarKey;
|
||||||
|
BuildContext? currentContext = key?.currentContext;
|
||||||
|
if (key != null && currentContext != null) {
|
||||||
|
final snackBar = SnackBar(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
backgroundColor: ColorsManager.red,
|
||||||
|
content: Row(mainAxisAlignment: MainAxisAlignment.center, children: [
|
||||||
|
const Icon(
|
||||||
|
Icons.check_circle,
|
||||||
|
color: ColorsManager.whiteColors,
|
||||||
|
size: 32,
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
width: 8,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
message,
|
||||||
|
style: Theme.of(currentContext)
|
||||||
|
.textTheme
|
||||||
|
.bodySmall!
|
||||||
|
.copyWith(fontSize: 14, fontWeight: FontWeight.w500, color: Colors.green),
|
||||||
|
)
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
key.currentState?.showSnackBar(snackBar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static greenSnackBar(String message) {
|
static greenSnackBar(String message) {
|
||||||
final key = NavigationService.snackbarKey;
|
final key = NavigationService.snackbarKey;
|
||||||
BuildContext? currentContext = key?.currentContext;
|
BuildContext? currentContext = key?.currentContext;
|
||||||
@ -29,8 +59,10 @@ class CustomSnackBar {
|
|||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
message,
|
message,
|
||||||
style: Theme.of(currentContext).textTheme.bodySmall!.copyWith(
|
style: Theme.of(currentContext)
|
||||||
fontSize: 14, fontWeight: FontWeight.w500, color: Colors.green),
|
.textTheme
|
||||||
|
.bodySmall!
|
||||||
|
.copyWith(fontSize: 14, fontWeight: FontWeight.w500, color: Colors.green),
|
||||||
)
|
)
|
||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user