Compare commits

..

36 Commits

Author SHA1 Message Date
c160220fca Hide region field 2024-12-23 00:52:05 +03:00
c362973c94 Hide unused widgets 2024-12-17 01:55:08 +03:00
4490715b55 Merge pull request #61 from SyncrowIOT/feat/update-endpoint-with-project
Added project entity
2024-12-11 16:16:59 +04:00
4896b6c593 changed endpoint for communtiies and spaces, hardcoded p[roject value for now 2024-12-10 09:50:42 +04:00
246098b83a Read icon from fetch scene api 2024-12-05 12:42:53 +03:00
26f50d59dd Bug fixes 2024-12-05 11:19:22 +03:00
610cdf83a0 Merge pull request #59 from SyncrowIOT/bugfix/SP-852
Bugfix/sp 852
2024-12-04 12:10:02 +04:00
d423a3eb59 added focused border 2024-12-04 11:14:02 +04:00
9bddd151bb added bloc for create community 2024-12-04 11:05:46 +04:00
0b628c85a5 updated create community dialog to mange edit/create 2024-12-04 10:36:41 +04:00
768996ca45 Merge pull request #58 from SyncrowIOT/dev
Dev
2024-12-03 16:02:31 +03:00
7ee335ab1a Bug fixes 2024-12-03 12:01:17 +03:00
d5ad06335b Merge pull request #57 from SyncrowIOT/routines_issues
Routines issues
2024-12-03 01:04:12 +03:00
d9ef5b4574 push fixes and merge 2024-12-03 01:02:13 +03:00
c58f2eb24e fixed autoamtion update 2024-12-03 00:29:59 +03:00
4e94d2df89 Bug fixes 2024-12-03 00:02:52 +03:00
2f5c5d7da1 rule_disable selected & CreateAutomation actionType 2024-12-02 16:49:44 +03:00
ff4ce8ed01 Bug fixes 2024-12-02 03:58:31 +03:00
1aa6b78fb4 Bug fixes 2024-12-01 12:05:19 +03:00
e003d9b8b3 Merge pull request #56 from SyncrowIOT/routines_fixes
Routines fixes
2024-12-01 10:50:54 +03:00
5da42e975a Merge pull request #46 from SyncrowIOT/dev
Dev
2024-10-30 16:38:18 +03:00
bc02664a09 Merge pull request #40 from SyncrowIOT/dev
Dev
2024-10-09 21:36:15 +03:00
057ea8515a Merge pull request #37 from SyncrowIOT/dev
Dev
2024-10-09 11:50:32 +03:00
9cc9fd7f24 Merge pull request #24 from SyncrowIOT/dev
Dev
2024-09-12 16:32:36 +03:00
f5958c1599 Merge pull request #21 from SyncrowIOT/dev
fix changes
2024-09-09 15:03:21 +03:00
1d0ef20015 Merge pull request #20 from SyncrowIOT/dev
fix changes
2024-09-09 14:30:05 +03:00
2b7a70e0a1 Merge pull request #19 from SyncrowIOT/dev
Dev
2024-09-09 13:13:36 +03:00
321a9b5fa2 Merge pull request #17 from SyncrowIOT/dev
Dev
2024-09-09 12:17:55 +03:00
9058f29787 Merged with dev 2024-09-08 23:24:04 +03:00
fd497d5797 Updated the pipeline 2024-09-04 17:05:13 +03:00
5f4aa93e01 remove last workflows 2024-09-04 17:01:28 +03:00
96bf262466 setup new staging 2024-09-04 16:55:06 +03:00
2969e936d0 ci: add Azure Static Web Apps workflow file
on-behalf-of: @Azure opensource@microsoft.com
2024-09-04 16:51:55 +03:00
e6d0e95ddc Updated github workflowf file 2024-09-04 01:07:31 +03:00
c7b1ed5b8e Added staging base url 2024-09-04 00:50:16 +03:00
d0e7d12279 test deploy 2024-09-03 17:06:28 +03:00
92 changed files with 1819 additions and 1686 deletions

View File

@ -0,0 +1,60 @@
name: Azure Static Web Apps CI/CD
on:
push:
branches:
- main
pull_request:
types: [opened, synchronize, reopened, closed]
branches:
- main
jobs:
build_and_deploy_job:
if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.action != 'closed')
runs-on: ubuntu-latest
name: Build and Deploy Job
steps:
- name: Checkout Code
uses: actions/checkout@v3
with:
submodules: true
lfs: false
- name: Set up Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: '3.22.2' # Specify the Flutter version you want to use
- name: Install dependencies
run: flutter pub get
- name: Build Flutter Web App
run: flutter build web --release --dart-define=FLAVOR=production
- name: Build And Deploy
id: builddeploy
uses: Azure/static-web-apps-deploy@v1
with:
azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_MANGO_BUSH_01E607F10 }}
repo_token: ${{ secrets.GITHUB_TOKEN }} # Used for Github integrations (i.e. PR comments)
action: "upload"
###### Repository/Build Configurations - These values can be configured to match your app requirements. ######
# For more information regarding Static Web App workflow configurations, please visit: https://aka.ms/swaworkflowconfig
app_location: "/build/web" # App source code path
api_location: "" # Api source code path - optional
output_location: "/build/web" # Built app content directory - optional
###### End of Repository/Build Configurations ######
close_pull_request_job:
if: github.event_name == 'pull_request' && github.event.action == 'closed'
runs-on: ubuntu-latest
name: Close Pull Request Job
steps:
- name: Close Pull Request
id: closepullrequest
uses: Azure/static-web-apps-deploy@v1
with:
azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_MANGO_BUSH_01E607F10 }}
action: "close"

View File

@ -11,7 +11,7 @@ import 'package:syncrow_web/pages/common/filter/filter_widget.dart';
import 'package:syncrow_web/pages/common/text_field/custom_web_textfield.dart'; import 'package:syncrow_web/pages/common/text_field/custom_web_textfield.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/visitor_password/view/visitor_password_dialog.dart'; import 'package:syncrow_web/pages/visitor_password/view/visitor_password_dialog.dart';
import 'package:syncrow_web/utils/color_manager.dart'; // import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/constants/app_enum.dart'; import 'package:syncrow_web/utils/constants/app_enum.dart';
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';
@ -27,8 +27,7 @@ class AccessManagementPage extends StatelessWidget with HelperResponsiveLayout {
final isLargeScreen = isLargeScreenSize(context); final isLargeScreen = isLargeScreenSize(context);
final isSmallScreen = isSmallScreenSize(context); final isSmallScreen = isSmallScreenSize(context);
final isHalfMediumScreen = isHafMediumScreenSize(context); final isHalfMediumScreen = isHafMediumScreenSize(context);
final padding = final padding = isLargeScreen ? const EdgeInsets.all(30) : const EdgeInsets.all(15);
isLargeScreen ? const EdgeInsets.all(30) : const EdgeInsets.all(15);
return WebScaffold( return WebScaffold(
enableMenuSidebar: false, enableMenuSidebar: false,
@ -40,8 +39,7 @@ class AccessManagementPage extends StatelessWidget with HelperResponsiveLayout {
), ),
rightBody: const NavigateHomeGridView(), rightBody: const NavigateHomeGridView(),
scaffoldBody: BlocProvider( scaffoldBody: BlocProvider(
create: (BuildContext context) => create: (BuildContext context) => AccessBloc()..add(FetchTableData()),
AccessBloc()..add(FetchTableData()),
child: BlocConsumer<AccessBloc, AccessState>( child: BlocConsumer<AccessBloc, AccessState>(
listener: (context, state) {}, listener: (context, state) {},
builder: (context, state) { builder: (context, state) {
@ -95,14 +93,11 @@ class AccessManagementPage extends StatelessWidget with HelperResponsiveLayout {
return [ return [
item.passwordName, item.passwordName,
item.passwordType.value, item.passwordType.value,
accessBloc accessBloc.timestampToDate(item.effectiveTime),
.timestampToDate(item.effectiveTime), accessBloc.timestampToDate(item.invalidTime),
accessBloc
.timestampToDate(item.invalidTime),
item.deviceName.toString(), item.deviceName.toString(),
item.authorizerEmail.toString(), item.authorizerEmail.toString(),
accessBloc accessBloc.timestampToDate(item.invalidTime),
.timestampToDate(item.invalidTime),
item.passwordStatus.value, item.passwordStatus.value,
]; ];
}).toList(), }).toList(),
@ -113,8 +108,7 @@ class AccessManagementPage extends StatelessWidget with HelperResponsiveLayout {
}))); })));
} }
Wrap _buildVisitorAdminPasswords( Wrap _buildVisitorAdminPasswords(BuildContext context, AccessBloc accessBloc) {
BuildContext context, AccessBloc accessBloc) {
return Wrap( return Wrap(
spacing: 10, spacing: 10,
runSpacing: 10, runSpacing: 10,
@ -140,23 +134,22 @@ class AccessManagementPage extends StatelessWidget with HelperResponsiveLayout {
borderRadius: 8, borderRadius: 8,
child: Text( child: Text(
'Create Visitor Password ', 'Create Visitor Password ',
style: context.textTheme.titleSmall! style: context.textTheme.titleSmall!.copyWith(color: Colors.white, fontSize: 12),
.copyWith(color: Colors.white, fontSize: 12),
)),
),
Container(
width: 133,
height: 42,
decoration: containerDecoration,
child: DefaultButton(
borderRadius: 8,
backgroundColor: ColorsManager.whiteColors,
child: Text(
'Admin Password',
style: context.textTheme.titleSmall!
.copyWith(color: Colors.black, fontSize: 12),
)), )),
), ),
// Container(
// width: 133,
// height: 42,
// decoration: containerDecoration,
// child: DefaultButton(
// borderRadius: 8,
// backgroundColor: ColorsManager.whiteColors,
// child: Text(
// 'Admin Password',
// style: context.textTheme.titleSmall!
// .copyWith(color: Colors.black, fontSize: 12),
// )),
// ),
], ],
); );
} }
@ -179,10 +172,8 @@ class AccessManagementPage extends StatelessWidget with HelperResponsiveLayout {
description: '', description: '',
onSubmitted: (value) { onSubmitted: (value) {
accessBloc.add(FilterDataEvent( accessBloc.add(FilterDataEvent(
emailAuthorizer: emailAuthorizer: accessBloc.emailAuthorizer.text.toLowerCase(),
accessBloc.emailAuthorizer.text.toLowerCase(), selectedTabIndex: BlocProvider.of<AccessBloc>(context).selectedIndex,
selectedTabIndex:
BlocProvider.of<AccessBloc>(context).selectedIndex,
passwordName: accessBloc.passwordName.text.toLowerCase(), passwordName: accessBloc.passwordName.text.toLowerCase(),
startTime: accessBloc.effectiveTimeTimeStamp, startTime: accessBloc.effectiveTimeTimeStamp,
endTime: accessBloc.expirationTimeTimeStamp)); endTime: accessBloc.expirationTimeTimeStamp));
@ -200,10 +191,8 @@ class AccessManagementPage extends StatelessWidget with HelperResponsiveLayout {
description: '', description: '',
onSubmitted: (value) { onSubmitted: (value) {
accessBloc.add(FilterDataEvent( accessBloc.add(FilterDataEvent(
emailAuthorizer: emailAuthorizer: accessBloc.emailAuthorizer.text.toLowerCase(),
accessBloc.emailAuthorizer.text.toLowerCase(), selectedTabIndex: BlocProvider.of<AccessBloc>(context).selectedIndex,
selectedTabIndex:
BlocProvider.of<AccessBloc>(context).selectedIndex,
passwordName: accessBloc.passwordName.text.toLowerCase(), passwordName: accessBloc.passwordName.text.toLowerCase(),
startTime: accessBloc.effectiveTimeTimeStamp, startTime: accessBloc.effectiveTimeTimeStamp,
endTime: accessBloc.expirationTimeTimeStamp)); endTime: accessBloc.expirationTimeTimeStamp));
@ -232,8 +221,7 @@ class AccessManagementPage extends StatelessWidget with HelperResponsiveLayout {
onSearch: () { onSearch: () {
accessBloc.add(FilterDataEvent( accessBloc.add(FilterDataEvent(
emailAuthorizer: accessBloc.emailAuthorizer.text.toLowerCase(), emailAuthorizer: accessBloc.emailAuthorizer.text.toLowerCase(),
selectedTabIndex: selectedTabIndex: BlocProvider.of<AccessBloc>(context).selectedIndex,
BlocProvider.of<AccessBloc>(context).selectedIndex,
passwordName: accessBloc.passwordName.text.toLowerCase(), passwordName: accessBloc.passwordName.text.toLowerCase(),
startTime: accessBloc.effectiveTimeTimeStamp, startTime: accessBloc.effectiveTimeTimeStamp,
endTime: accessBloc.expirationTimeTimeStamp)); endTime: accessBloc.expirationTimeTimeStamp));
@ -261,10 +249,8 @@ class AccessManagementPage extends StatelessWidget with HelperResponsiveLayout {
description: '', description: '',
onSubmitted: (value) { onSubmitted: (value) {
accessBloc.add(FilterDataEvent( accessBloc.add(FilterDataEvent(
emailAuthorizer: emailAuthorizer: accessBloc.emailAuthorizer.text.toLowerCase(),
accessBloc.emailAuthorizer.text.toLowerCase(), selectedTabIndex: BlocProvider.of<AccessBloc>(context).selectedIndex,
selectedTabIndex:
BlocProvider.of<AccessBloc>(context).selectedIndex,
passwordName: accessBloc.passwordName.text.toLowerCase(), passwordName: accessBloc.passwordName.text.toLowerCase(),
startTime: accessBloc.effectiveTimeTimeStamp, startTime: accessBloc.effectiveTimeTimeStamp,
endTime: accessBloc.expirationTimeTimeStamp)); endTime: accessBloc.expirationTimeTimeStamp));
@ -288,8 +274,7 @@ class AccessManagementPage extends StatelessWidget with HelperResponsiveLayout {
onSearch: () { onSearch: () {
accessBloc.add(FilterDataEvent( accessBloc.add(FilterDataEvent(
emailAuthorizer: accessBloc.emailAuthorizer.text.toLowerCase(), emailAuthorizer: accessBloc.emailAuthorizer.text.toLowerCase(),
selectedTabIndex: selectedTabIndex: BlocProvider.of<AccessBloc>(context).selectedIndex,
BlocProvider.of<AccessBloc>(context).selectedIndex,
passwordName: accessBloc.passwordName.text.toLowerCase(), passwordName: accessBloc.passwordName.text.toLowerCase(),
startTime: accessBloc.effectiveTimeTimeStamp, startTime: accessBloc.effectiveTimeTimeStamp,
endTime: accessBloc.expirationTimeTimeStamp)); endTime: accessBloc.expirationTimeTimeStamp));

View File

@ -31,8 +31,7 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
////////////////////////////// forget password ////////////////////////////////// ////////////////////////////// forget password //////////////////////////////////
final TextEditingController forgetEmailController = TextEditingController(); final TextEditingController forgetEmailController = TextEditingController();
final TextEditingController forgetPasswordController = final TextEditingController forgetPasswordController = TextEditingController();
TextEditingController();
final TextEditingController forgetOtp = TextEditingController(); final TextEditingController forgetOtp = TextEditingController();
final forgetFormKey = GlobalKey<FormState>(); final forgetFormKey = GlobalKey<FormState>();
final forgetEmailKey = GlobalKey<FormState>(); final forgetEmailKey = GlobalKey<FormState>();
@ -49,12 +48,12 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
return; return;
} }
_remainingTime = 1; _remainingTime = 1;
add(UpdateTimerEvent( add(UpdateTimerEvent(remainingTime: _remainingTime, isButtonEnabled: false));
remainingTime: _remainingTime, isButtonEnabled: false));
try { try {
forgetEmailValidate = ''; forgetEmailValidate = '';
_remainingTime = (await AuthenticationAPI.sendOtp( _remainingTime = (await AuthenticationAPI.sendOtp(
email: forgetEmailController.text, regionUuid: regionUuid))!; email: forgetEmailController.text,
))!;
} on DioException catch (e) { } on DioException catch (e) {
if (e.response!.statusCode == 400) { if (e.response!.statusCode == 400) {
final errorData = e.response!.data; final errorData = e.response!.data;
@ -86,8 +85,7 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
_timer?.cancel(); _timer?.cancel();
add(const UpdateTimerEvent(remainingTime: 0, isButtonEnabled: true)); add(const UpdateTimerEvent(remainingTime: 0, isButtonEnabled: true));
} else { } else {
add(UpdateTimerEvent( add(UpdateTimerEvent(remainingTime: _remainingTime, isButtonEnabled: false));
remainingTime: _remainingTime, isButtonEnabled: false));
} }
}); });
} }
@ -97,8 +95,7 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
emit(const TimerState(isButtonEnabled: true, remainingTime: 0)); emit(const TimerState(isButtonEnabled: true, remainingTime: 0));
} }
Future<void> changePassword( Future<void> changePassword(ChangePasswordEvent event, Emitter<AuthState> emit) async {
ChangePasswordEvent event, Emitter<AuthState> emit) async {
emit(LoadingForgetState()); emit(LoadingForgetState());
try { try {
var response = await AuthenticationAPI.verifyOtp( var response = await AuthenticationAPI.verifyOtp(
@ -114,8 +111,7 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
} }
} on DioException catch (e) { } on DioException catch (e) {
final errorData = e.response!.data; final errorData = e.response!.data;
String errorMessage = String errorMessage = errorData['error']['message'] ?? 'something went wrong';
errorData['error']['message'] ?? 'something went wrong';
validate = errorMessage; validate = errorMessage;
emit(AuthInitialState()); emit(AuthInitialState());
} }
@ -129,16 +125,14 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
} }
void _onUpdateTimer(UpdateTimerEvent event, Emitter<AuthState> emit) { void _onUpdateTimer(UpdateTimerEvent event, Emitter<AuthState> emit) {
emit(TimerState( emit(TimerState(isButtonEnabled: event.isButtonEnabled, remainingTime: event.remainingTime));
isButtonEnabled: event.isButtonEnabled,
remainingTime: event.remainingTime));
} }
///////////////////////////////////// login ///////////////////////////////////// ///////////////////////////////////// login /////////////////////////////////////
final TextEditingController loginEmailController = TextEditingController(); final TextEditingController loginEmailController = TextEditingController();
final TextEditingController loginPasswordController = TextEditingController(); final TextEditingController loginPasswordController = TextEditingController();
final loginFormKey = GlobalKey<FormState>(); final loginFormKey = GlobalKey<FormState>();
bool isChecked = false; bool isChecked = true;
bool obscureText = true; bool obscureText = true;
String newPassword = ''; String newPassword = '';
String maskedEmail = ''; String maskedEmail = '';
@ -146,7 +140,7 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
String validate = ''; String validate = '';
String forgetValidate = ''; String forgetValidate = '';
String forgetEmailValidate = ''; String forgetEmailValidate = '';
String regionUuid = ''; // String regionUuid = '';
static Token token = Token.emptyConstructor(); static Token token = Token.emptyConstructor();
static UserModel? user; static UserModel? user;
bool showValidationMessage = false; bool showValidationMessage = false;
@ -163,9 +157,9 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
token = await AuthenticationAPI.loginWithEmail( token = await AuthenticationAPI.loginWithEmail(
model: LoginWithEmailModel( model: LoginWithEmailModel(
email: event.username, email: event.username,
password: event.password, password: event.password,
regionUuid: event.regionUuid), ),
); );
} catch (failure) { } catch (failure) {
validate = 'Invalid Credentials!'; validate = 'Invalid Credentials!';
@ -175,8 +169,7 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
if (token.accessTokenIsNotEmpty) { if (token.accessTokenIsNotEmpty) {
FlutterSecureStorage storage = const FlutterSecureStorage(); FlutterSecureStorage storage = const FlutterSecureStorage();
await storage.write( await storage.write(key: Token.loginAccessTokenKey, value: token.accessToken);
key: Token.loginAccessTokenKey, value: token.accessToken);
const FlutterSecureStorage().write( const FlutterSecureStorage().write(
key: UserModel.userUuidKey, key: UserModel.userUuidKey,
value: Token.decodeToken(token.accessToken)['uuid'].toString()); value: Token.decodeToken(token.accessToken)['uuid'].toString());
@ -334,14 +327,12 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
static Future<String> getTokenAndValidate() async { static Future<String> getTokenAndValidate() async {
try { try {
const storage = FlutterSecureStorage(); const storage = FlutterSecureStorage();
final firstLaunch = await SharedPreferencesHelper.readBoolFromSP( final firstLaunch =
StringsManager.firstLaunch) ?? await SharedPreferencesHelper.readBoolFromSP(StringsManager.firstLaunch) ?? true;
true;
if (firstLaunch) { if (firstLaunch) {
storage.deleteAll(); storage.deleteAll();
} }
await SharedPreferencesHelper.saveBoolToSP( await SharedPreferencesHelper.saveBoolToSP(StringsManager.firstLaunch, false);
StringsManager.firstLaunch, false);
final value = await storage.read(key: Token.loginAccessTokenKey) ?? ''; final value = await storage.read(key: Token.loginAccessTokenKey) ?? '';
if (value.isEmpty) { if (value.isEmpty) {
return 'Token not found'; return 'Token not found';
@ -376,7 +367,7 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
Future selectRegion(SelectRegionEvent event, Emitter<AuthState> emit) async { Future selectRegion(SelectRegionEvent event, Emitter<AuthState> emit) async {
try { try {
emit(AuthLoading()); emit(AuthLoading());
regionUuid = event.val; // regionUuid = event.val;
add(CheckEnableEvent()); add(CheckEnableEvent());
emit(AuthInitialState()); emit(AuthInitialState());
} catch (e) { } catch (e) {
@ -394,9 +385,7 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
final String formattedTime = [ final String formattedTime = [
if (days > 0) '${days}d', // Append 'd' for days if (days > 0) '${days}d', // Append 'd' for days
if (days > 0 || hours > 0) if (days > 0 || hours > 0)
hours hours.toString().padLeft(2, '0'), // Show hours if there are days or hours
.toString()
.padLeft(2, '0'), // Show hours if there are days or hours
minutes.toString().padLeft(2, '0'), minutes.toString().padLeft(2, '0'),
seconds.toString().padLeft(2, '0'), seconds.toString().padLeft(2, '0'),
].join(':'); ].join(':');
@ -411,8 +400,7 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
emit(AuthLoading()); emit(AuthLoading());
checkValidate = isChecked == true && checkValidate = isChecked == true &&
loginPasswordController.text.isNotEmpty && loginPasswordController.text.isNotEmpty &&
loginEmailController.text.isNotEmpty && loginEmailController.text.isNotEmpty;
regionUuid != '';
emit(LoginInitial()); emit(LoginInitial());
return checkValidate; return checkValidate;
} }

View File

@ -10,16 +10,16 @@ abstract class AuthEvent extends Equatable {
class LoginButtonPressed extends AuthEvent { class LoginButtonPressed extends AuthEvent {
final String username; final String username;
final String password; final String password;
final String regionUuid; // final String regionUuid;
const LoginButtonPressed({ const LoginButtonPressed({
required this.username, required this.username,
required this.password, required this.password,
required this.regionUuid, // required this.regionUuid,
}); });
@override @override
List<Object> get props => [username, password, regionUuid]; List<Object> get props => [username, password];
} }
class CheckBoxEvent extends AuthEvent { class CheckBoxEvent extends AuthEvent {
@ -49,13 +49,9 @@ class UpdateTimerEvent extends AuthEvent {
const UpdateTimerEvent({required this.remainingTime, required this.isButtonEnabled}); const UpdateTimerEvent({required this.remainingTime, required this.isButtonEnabled});
} }
class ChangePasswordEvent extends AuthEvent { class ChangePasswordEvent extends AuthEvent {}
} class SendOtpEvent extends AuthEvent {}
class SendOtpEvent extends AuthEvent {
}
class PasswordVisibleEvent extends AuthEvent { class PasswordVisibleEvent extends AuthEvent {
final bool? newValue; final bool? newValue;

View File

@ -1,19 +1,19 @@
class LoginWithEmailModel { class LoginWithEmailModel {
final String email; final String email;
final String password; final String password;
final String regionUuid; // final String regionUuid;
LoginWithEmailModel({ LoginWithEmailModel({
required this.email, required this.email,
required this.password, required this.password,
required this.regionUuid, // required this.regionUuid,
}); });
factory LoginWithEmailModel.fromJson(Map<String, dynamic> json) { factory LoginWithEmailModel.fromJson(Map<String, dynamic> json) {
return LoginWithEmailModel( return LoginWithEmailModel(
email: json['email'], email: json['email'],
password: json['password'], password: json['password'],
regionUuid: json['regionUuid'], // regionUuid: json['regionUuid'],
); );
} }
@ -21,7 +21,7 @@ class LoginWithEmailModel {
return { return {
'email': email, 'email': email,
'password': password, 'password': password,
'regionUuid': regionUuid, // 'regionUuid': regionUuid,
}; };
} }
} }

View File

@ -124,18 +124,18 @@ class ForgetPasswordWebPage extends StatelessWidget {
.copyWith(fontSize: 14, fontWeight: FontWeight.w400), .copyWith(fontSize: 14, fontWeight: FontWeight.w400),
), ),
const SizedBox(height: 10), const SizedBox(height: 10),
Column( // Column(
crossAxisAlignment: CrossAxisAlignment.start, // crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start, // mainAxisAlignment: MainAxisAlignment.start,
children: [ // children: [
const SizedBox(height: 10), // const SizedBox(height: 10),
Form( // Form(
key: forgetBloc.forgetRegionKey, // key: forgetBloc.forgetRegionKey,
child: SizedBox( // child: SizedBox(
child: // child:
_buildDropdownField(context, forgetBloc, size))) // _buildDropdownField(context, forgetBloc, size)))
], // ],
), // ),
const SizedBox(height: 20), const SizedBox(height: 20),
Form( Form(
key: forgetBloc.forgetEmailKey, key: forgetBloc.forgetEmailKey,
@ -459,9 +459,9 @@ class ForgetPasswordWebPage extends StatelessWidget {
), ),
); );
}).toList(), }).toList(),
value: loginBloc.regionList!.any((region) => region.id == loginBloc.regionUuid) // value: loginBloc.regionList!.any((region) => region.id == loginBloc.regionUuid)
? loginBloc.regionUuid // ? loginBloc.regionUuid
: null, // : null,
onChanged: (String? value) { onChanged: (String? value) {
if (value != null) { if (value != null) {
loginBloc.add(SelectRegionEvent(val: value)); loginBloc.add(SelectRegionEvent(val: value));

View File

@ -6,7 +6,7 @@ import 'package:go_router/go_router.dart';
import 'package:syncrow_web/pages/auth/bloc/auth_bloc.dart'; import 'package:syncrow_web/pages/auth/bloc/auth_bloc.dart';
import 'package:syncrow_web/pages/auth/bloc/auth_event.dart'; import 'package:syncrow_web/pages/auth/bloc/auth_event.dart';
import 'package:syncrow_web/pages/auth/bloc/auth_state.dart'; import 'package:syncrow_web/pages/auth/bloc/auth_state.dart';
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/auth/view/forget_password_page.dart'; import 'package:syncrow_web/pages/auth/view/forget_password_page.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/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
@ -112,44 +112,44 @@ class LoginMobilePage extends StatelessWidget {
color: Colors.white, fontSize: 24, fontWeight: FontWeight.bold), color: Colors.white, fontSize: 24, fontWeight: FontWeight.bold),
), ),
const SizedBox(height: 30), const SizedBox(height: 30),
Column( // Column(
crossAxisAlignment: CrossAxisAlignment.start, // crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start, // mainAxisAlignment: MainAxisAlignment.start,
children: [ // children: [
Text( // Text(
"Country/Region", // "Country/Region",
style: Theme.of(context).textTheme.bodySmall, // style: Theme.of(context).textTheme.bodySmall,
), // ),
SizedBox( // SizedBox(
child: DropdownButtonFormField<String>( // child: DropdownButtonFormField<String>(
validator: loginBloc.validateRegion, // validator: loginBloc.validateRegion,
icon: const Icon( // icon: const Icon(
Icons.keyboard_arrow_down_outlined, // Icons.keyboard_arrow_down_outlined,
), // ),
decoration: textBoxDecoration()!.copyWith( // decoration: textBoxDecoration()!.copyWith(
hintText: null, // hintText: null,
), // ),
hint: const Align( // hint: const Align(
alignment: Alignment.centerLeft, // alignment: Alignment.centerLeft,
child: Text( // child: Text(
'Select your region/country', // 'Select your region/country',
textAlign: TextAlign.center, // textAlign: TextAlign.center,
), // ),
), // ),
isDense: true, // isDense: true,
style: const TextStyle(color: Colors.black), // style: const TextStyle(color: Colors.black),
items: loginBloc.regionList!.map((RegionModel region) { // items: loginBloc.regionList!.map((RegionModel region) {
return DropdownMenuItem<String>( // return DropdownMenuItem<String>(
value: region.name, // value: region.name,
child: Text(region.name), // child: Text(region.name),
); // );
}).toList(), // }).toList(),
onChanged: (String? value) {}, // onChanged: (String? value) {},
), // ),
) // )
], // ],
), // ),
const SizedBox(height: 20.0), // const SizedBox(height: 20.0),
Column( Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
@ -207,7 +207,10 @@ class LoginMobilePage extends StatelessWidget {
}, },
child: Text( child: Text(
"Forgot Password?", "Forgot Password?",
style: Theme.of(context).textTheme.bodySmall, style: Theme.of(context)
.textTheme
.bodySmall!
.copyWith(color: ColorsManager.blackColor),
), ),
), ),
], ],
@ -276,7 +279,6 @@ class LoginMobilePage extends StatelessWidget {
if (loginBloc.loginFormKey.currentState!.validate()) { if (loginBloc.loginFormKey.currentState!.validate()) {
loginBloc.add( loginBloc.add(
LoginButtonPressed( LoginButtonPressed(
regionUuid: '',
username: loginBloc.loginEmailController.text, username: loginBloc.loginEmailController.text,
password: loginBloc.loginPasswordController.text, password: loginBloc.loginPasswordController.text,
), ),

View File

@ -155,16 +155,16 @@ class _LoginWebPageState extends State<LoginWebPage> with HelperResponsiveLayout
children: <Widget>[ children: <Widget>[
const SizedBox(height: 40), const SizedBox(height: 40),
Text('Login', style: Theme.of(context).textTheme.headlineLarge), Text('Login', style: Theme.of(context).textTheme.headlineLarge),
SizedBox(height: size.height * 0.03), // SizedBox(height: size.height * 0.03),
_buildDropdownField(context, loginBloc, size), // _buildDropdownField(context, loginBloc, size),
const SizedBox(height: 20.0), const SizedBox(height: 20.0),
_buildEmailField(context, loginBloc), _buildEmailField(context, loginBloc),
const SizedBox(height: 20.0), const SizedBox(height: 20.0),
_buildPasswordField(context, loginBloc), _buildPasswordField(context, loginBloc),
const SizedBox(height: 20), const SizedBox(height: 20),
_buildForgotPassword(context), _buildForgotPassword(context),
const SizedBox(height: 20), // const SizedBox(height: 20),
_buildCheckbox(context, loginBloc, size), // _buildCheckbox(context, loginBloc, size),
const SizedBox(height: 20.0), const SizedBox(height: 20.0),
_buildSignInButton(context, loginBloc, size), _buildSignInButton(context, loginBloc, size),
const SizedBox(height: 15.0), const SizedBox(height: 15.0),
@ -219,11 +219,11 @@ class _LoginWebPageState extends State<LoginWebPage> with HelperResponsiveLayout
), ),
); );
}).toList(), }).toList(),
value: loginBloc.regionList!.any( // value: loginBloc.regionList!.any(
(region) => region.id == loginBloc.regionUuid, // (region) => region.id == loginBloc.regionUuid,
) // )
? loginBloc.regionUuid // ? loginBloc.regionUuid
: null, // : null,
onChanged: (String? value) { onChanged: (String? value) {
if (value != null) { if (value != null) {
loginBloc.add(CheckEnableEvent()); loginBloc.add(CheckEnableEvent());
@ -462,7 +462,7 @@ class _LoginWebPageState extends State<LoginWebPage> with HelperResponsiveLayout
onPressed: () { onPressed: () {
if (loginBloc.loginFormKey.currentState!.validate()) { if (loginBloc.loginFormKey.currentState!.validate()) {
loginBloc.add(LoginButtonPressed( loginBloc.add(LoginButtonPressed(
regionUuid: loginBloc.regionUuid, // regionUuid: loginBloc.regionUuid,
username: loginBloc.loginEmailController.text, username: loginBloc.loginEmailController.text,
password: loginBloc.loginPasswordController.text, password: loginBloc.loginPasswordController.text,
)); ));

View File

@ -8,7 +8,7 @@ import 'package:syncrow_web/pages/device_managment/ac/view/batch_control_list/ba
import 'package:syncrow_web/pages/device_managment/ac/view/batch_control_list/batch_fan_speed.dart'; import 'package:syncrow_web/pages/device_managment/ac/view/batch_control_list/batch_fan_speed.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/factory_reset_model.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/models/factory_reset_model.dart';
import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart'; import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart';
import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart'; // import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart';
import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.dart'; import 'package:syncrow_web/pages/device_managment/shared/toggle_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';
@ -26,7 +26,8 @@ class AcDeviceBatchControlView extends StatelessWidget with HelperResponsiveLayo
final isLarge = isLargeScreenSize(context); final isLarge = isLargeScreenSize(context);
final isMedium = isMediumScreenSize(context); final isMedium = isMediumScreenSize(context);
return BlocProvider( return BlocProvider(
create: (context) => AcBloc(deviceId: devicesIds.first)..add(AcFetchBatchStatusEvent(devicesIds)), create: (context) =>
AcBloc(deviceId: devicesIds.first)..add(AcFetchBatchStatusEvent(devicesIds)),
child: BlocBuilder<AcBloc, AcsState>( child: BlocBuilder<AcBloc, AcsState>(
builder: (context, state) { builder: (context, state) {
if (state is ACStatusLoaded) { if (state is ACStatusLoaded) {
@ -98,7 +99,8 @@ class AcDeviceBatchControlView extends StatelessWidget with HelperResponsiveLayo
), ),
Text( Text(
'h', 'h',
style: context.textTheme.bodySmall!.copyWith(color: ColorsManager.blackColor), style:
context.textTheme.bodySmall!.copyWith(color: ColorsManager.blackColor),
), ),
Text( Text(
'30', '30',
@ -107,7 +109,9 @@ class AcDeviceBatchControlView extends StatelessWidget with HelperResponsiveLayo
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
), ),
Text('m', style: context.textTheme.bodySmall!.copyWith(color: ColorsManager.blackColor)), Text('m',
style: context.textTheme.bodySmall!
.copyWith(color: ColorsManager.blackColor)),
IconButton( IconButton(
onPressed: () {}, onPressed: () {},
icon: const Icon( icon: const Icon(
@ -138,7 +142,7 @@ class AcDeviceBatchControlView extends StatelessWidget with HelperResponsiveLayo
)); ));
}, },
), ),
FirmwareUpdateWidget(deviceId: devicesIds.first, version: 5), // FirmwareUpdateWidget(deviceId: devicesIds.first, version: 5),
FactoryResetWidget( FactoryResetWidget(
callFactoryReset: () { callFactoryReset: () {
context.read<AcBloc>().add(AcFactoryResetEvent( context.read<AcBloc>().add(AcFactoryResetEvent(

View File

@ -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));
}
}

View File

@ -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];
}

View File

@ -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];
}

View File

@ -1,9 +1,9 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/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 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'));
} }

View File

@ -6,7 +6,7 @@ import 'package:syncrow_web/pages/device_managment/ceiling_sensor/bloc/ceiling_e
import 'package:syncrow_web/pages/device_managment/ceiling_sensor/bloc/ceiling_state.dart'; import 'package:syncrow_web/pages/device_managment/ceiling_sensor/bloc/ceiling_state.dart';
import 'package:syncrow_web/pages/device_managment/ceiling_sensor/model/ceiling_sensor_model.dart'; import 'package:syncrow_web/pages/device_managment/ceiling_sensor/model/ceiling_sensor_model.dart';
import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart'; import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart';
import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart'; // import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart';
import 'package:syncrow_web/pages/device_managment/shared/sensors_widgets/presence_space_type.dart'; import 'package:syncrow_web/pages/device_managment/shared/sensors_widgets/presence_space_type.dart';
import 'package:syncrow_web/pages/device_managment/shared/sensors_widgets/presence_update_data.dart'; import 'package:syncrow_web/pages/device_managment/shared/sensors_widgets/presence_update_data.dart';
import 'package:syncrow_web/pages/device_managment/shared/sensors_widgets/presense_nobody_time.dart'; import 'package:syncrow_web/pages/device_managment/shared/sensors_widgets/presense_nobody_time.dart';
@ -110,7 +110,7 @@ class CeilingSensorBatchControlView extends StatelessWidget with HelperResponsiv
), ),
), ),
), ),
FirmwareUpdateWidget(deviceId: devicesIds.first, version: 4), // FirmwareUpdateWidget(deviceId: devicesIds.first, version: 4),
FactoryResetWidget( FactoryResetWidget(
callFactoryReset: () { callFactoryReset: () {
context.read<CeilingSensorBloc>().add( context.read<CeilingSensorBloc>().add(

View File

@ -6,11 +6,10 @@ import 'package:syncrow_web/pages/device_managment/curtain/bloc/curtain_bloc.dar
import 'package:syncrow_web/pages/device_managment/curtain/bloc/curtain_event.dart'; import 'package:syncrow_web/pages/device_managment/curtain/bloc/curtain_event.dart';
import 'package:syncrow_web/pages/device_managment/curtain/bloc/curtain_state.dart'; import 'package:syncrow_web/pages/device_managment/curtain/bloc/curtain_state.dart';
import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart'; import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart';
import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart'; // import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart';
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart'; import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
class CurtainBatchStatusView extends StatelessWidget class CurtainBatchStatusView extends StatelessWidget with HelperResponsiveLayout {
with HelperResponsiveLayout {
const CurtainBatchStatusView({super.key, required this.devicesIds}); const CurtainBatchStatusView({super.key, required this.devicesIds});
final List<String> devicesIds; final List<String> devicesIds;
@ -18,8 +17,8 @@ class CurtainBatchStatusView extends StatelessWidget
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocProvider( return BlocProvider(
create: (context) => CurtainBloc(deviceId: devicesIds.first) create: (context) =>
..add(CurtainFetchBatchStatus(devicesIds)), CurtainBloc(deviceId: devicesIds.first)..add(CurtainFetchBatchStatus(devicesIds)),
child: BlocBuilder<CurtainBloc, CurtainState>( child: BlocBuilder<CurtainBloc, CurtainState>(
builder: (context, state) { builder: (context, state) {
if (state is CurtainStatusLoading) { if (state is CurtainStatusLoading) {
@ -68,7 +67,7 @@ class CurtainBatchStatusView extends StatelessWidget
)); ));
}, },
), ),
FirmwareUpdateWidget(deviceId: devicesIds.first, version: 5), // FirmwareUpdateWidget(deviceId: devicesIds.first, version: 5),
FactoryResetWidget( FactoryResetWidget(
callFactoryReset: () { callFactoryReset: () {
context.read<CurtainBloc>().add( context.read<CurtainBloc>().add(

View File

@ -4,11 +4,10 @@ import 'package:syncrow_web/pages/device_managment/all_devices/models/factory_re
import 'package:syncrow_web/pages/device_managment/door_lock/bloc/door_lock_bloc.dart'; import 'package:syncrow_web/pages/device_managment/door_lock/bloc/door_lock_bloc.dart';
import 'package:syncrow_web/pages/device_managment/door_lock/bloc/door_lock_event.dart'; import 'package:syncrow_web/pages/device_managment/door_lock/bloc/door_lock_event.dart';
import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart'; import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart';
import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart'; // import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart';
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart'; import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
class DoorLockBatchControlView extends StatelessWidget class DoorLockBatchControlView extends StatelessWidget with HelperResponsiveLayout {
with HelperResponsiveLayout {
const DoorLockBatchControlView({super.key, required this.devicesIds}); const DoorLockBatchControlView({super.key, required this.devicesIds});
final List<String> devicesIds; final List<String> devicesIds;
@ -18,17 +17,17 @@ class DoorLockBatchControlView extends StatelessWidget
return Row( return Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
SizedBox( // SizedBox(
width: 170, // width: 170,
height: 140, // height: 140,
child: FirmwareUpdateWidget( // child: FirmwareUpdateWidget(
deviceId: devicesIds.first, // deviceId: devicesIds.first,
version: 12, // version: 12,
), // ),
), // ),
const SizedBox( // const SizedBox(
width: 12, // width: 12,
), // ),
SizedBox( SizedBox(
width: 170, width: 170,
height: 140, height: 140,

View File

@ -6,17 +6,15 @@ import 'package:syncrow_web/pages/device_managment/garage_door/bloc/garage_door_
import 'package:syncrow_web/pages/device_managment/garage_door/bloc/garage_door_state.dart'; import 'package:syncrow_web/pages/device_managment/garage_door/bloc/garage_door_state.dart';
import 'package:syncrow_web/pages/device_managment/garage_door/models/garage_door_model.dart'; import 'package:syncrow_web/pages/device_managment/garage_door/models/garage_door_model.dart';
import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart'; import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart';
import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart'; // import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart';
import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.dart'; import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.dart';
import 'package:syncrow_web/utils/constants/assets.dart'; import 'package:syncrow_web/utils/constants/assets.dart';
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart'; import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
class GarageDoorBatchControlView extends StatelessWidget class GarageDoorBatchControlView extends StatelessWidget with HelperResponsiveLayout {
with HelperResponsiveLayout {
final List<String> deviceIds; final List<String> deviceIds;
const GarageDoorBatchControlView({Key? key, required this.deviceIds}) const GarageDoorBatchControlView({Key? key, required this.deviceIds}) : super(key: key);
: super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -39,8 +37,7 @@ class GarageDoorBatchControlView extends StatelessWidget
); );
} }
Widget _buildStatusControls( Widget _buildStatusControls(BuildContext context, GarageDoorStatusModel status) {
BuildContext context, GarageDoorStatusModel status) {
final isExtraLarge = isExtraLargeScreenSize(context); final isExtraLarge = isExtraLargeScreenSize(context);
final isLarge = isLargeScreenSize(context); final isLarge = isLargeScreenSize(context);
final isMedium = isMediumScreenSize(context); final isMedium = isMediumScreenSize(context);
@ -75,10 +72,10 @@ class GarageDoorBatchControlView extends StatelessWidget
); );
}, },
), ),
FirmwareUpdateWidget( // FirmwareUpdateWidget(
deviceId: deviceIds.first, // deviceId: deviceIds.first,
version: 12, // version: 12,
), // ),
FactoryResetWidget( FactoryResetWidget(
callFactoryReset: () { callFactoryReset: () {
context.read<GarageDoorBloc>().add( context.read<GarageDoorBloc>().add(

View File

@ -3,11 +3,10 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/factory_reset_model.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/models/factory_reset_model.dart';
import 'package:syncrow_web/pages/device_managment/gateway/bloc/gate_way_bloc.dart'; import 'package:syncrow_web/pages/device_managment/gateway/bloc/gate_way_bloc.dart';
import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart'; import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart';
import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart'; // import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart';
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart'; import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
class GatewayBatchControlView extends StatelessWidget class GatewayBatchControlView extends StatelessWidget with HelperResponsiveLayout {
with HelperResponsiveLayout {
const GatewayBatchControlView({super.key, required this.gatewayIds}); const GatewayBatchControlView({super.key, required this.gatewayIds});
final List<String> gatewayIds; final List<String> gatewayIds;
@ -24,14 +23,13 @@ class GatewayBatchControlView extends StatelessWidget
return Row( return Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
SizedBox( // SizedBox(
width: 170, // width: 170,
height: 140, // height: 140,
child: FirmwareUpdateWidget( // child: FirmwareUpdateWidget(deviceId: gatewayIds.first, version: 2)),
deviceId: gatewayIds.first, version: 2)), // const SizedBox(
const SizedBox( // width: 12,
width: 12, // ),
),
SizedBox( SizedBox(
width: 170, width: 170,
height: 140, height: 140,
@ -40,8 +38,7 @@ class GatewayBatchControlView extends StatelessWidget
context.read<GateWayBloc>().add( context.read<GateWayBloc>().add(
GateWayFactoryReset( GateWayFactoryReset(
deviceId: gatewayIds.first, deviceId: gatewayIds.first,
factoryReset: factoryReset: FactoryResetModel(devicesUuid: gatewayIds),
FactoryResetModel(devicesUuid: gatewayIds),
), ),
); );
}, },

View File

@ -4,7 +4,7 @@ import 'package:syncrow_web/pages/device_managment/all_devices/models/factory_re
import 'package:syncrow_web/pages/device_managment/main_door_sensor/bloc/main_door_sensor_bloc.dart'; import 'package:syncrow_web/pages/device_managment/main_door_sensor/bloc/main_door_sensor_bloc.dart';
import 'package:syncrow_web/pages/device_managment/main_door_sensor/bloc/main_door_sensor_event.dart'; import 'package:syncrow_web/pages/device_managment/main_door_sensor/bloc/main_door_sensor_event.dart';
import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart'; import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart';
import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart'; // import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart';
class MainDoorSensorBatchView extends StatelessWidget { class MainDoorSensorBatchView extends StatelessWidget {
const MainDoorSensorBatchView({super.key, required this.devicesIds}); const MainDoorSensorBatchView({super.key, required this.devicesIds});
@ -16,17 +16,17 @@ class MainDoorSensorBatchView extends StatelessWidget {
return Row( return Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
SizedBox( // SizedBox(
width: 170, // width: 170,
height: 140, // height: 140,
child: FirmwareUpdateWidget( // child: FirmwareUpdateWidget(
deviceId: devicesIds.first, // deviceId: devicesIds.first,
version: 12, // version: 12,
), // ),
), // ),
const SizedBox( // const SizedBox(
width: 12, // width: 12,
), // ),
SizedBox( SizedBox(
width: 170, width: 170,
height: 140, height: 140,

View File

@ -4,16 +4,14 @@ import 'package:syncrow_web/pages/device_managment/all_devices/models/factory_re
import 'package:syncrow_web/pages/device_managment/one_g_glass_switch/bloc/one_gang_glass_switch_bloc.dart'; import 'package:syncrow_web/pages/device_managment/one_g_glass_switch/bloc/one_gang_glass_switch_bloc.dart';
import 'package:syncrow_web/pages/device_managment/one_g_glass_switch/models/once_gang_glass_status_model.dart'; import 'package:syncrow_web/pages/device_managment/one_g_glass_switch/models/once_gang_glass_status_model.dart';
import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart'; import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart';
import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart'; // import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart';
import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.dart'; import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.dart';
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart'; import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
class OneGangGlassSwitchBatchControlView extends StatelessWidget class OneGangGlassSwitchBatchControlView extends StatelessWidget with HelperResponsiveLayout {
with HelperResponsiveLayout {
final List<String> deviceIds; final List<String> deviceIds;
const OneGangGlassSwitchBatchControlView( const OneGangGlassSwitchBatchControlView({required this.deviceIds, super.key});
{required this.deviceIds, super.key});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -36,8 +34,7 @@ class OneGangGlassSwitchBatchControlView extends StatelessWidget
); );
} }
Widget _buildStatusControls( Widget _buildStatusControls(BuildContext context, OneGangGlassStatusModel status) {
BuildContext context, OneGangGlassStatusModel status) {
final isExtraLarge = isExtraLargeScreenSize(context); final isExtraLarge = isExtraLargeScreenSize(context);
final isLarge = isLargeScreenSize(context); final isLarge = isLargeScreenSize(context);
final isMedium = isMediumScreenSize(context); final isMedium = isMediumScreenSize(context);
@ -71,10 +68,10 @@ class OneGangGlassSwitchBatchControlView extends StatelessWidget
); );
}, },
), ),
FirmwareUpdateWidget( // FirmwareUpdateWidget(
deviceId: deviceIds.first, // deviceId: deviceIds.first,
version: 12, // version: 12,
), // ),
FactoryResetWidget( FactoryResetWidget(
callFactoryReset: () { callFactoryReset: () {
context.read<OneGangGlassSwitchBloc>().add( context.read<OneGangGlassSwitchBloc>().add(

View File

@ -6,12 +6,11 @@ import 'package:syncrow_web/pages/device_managment/one_gang_switch/bloc/wall_lig
import 'package:syncrow_web/pages/device_managment/one_gang_switch/bloc/wall_light_switch_state.dart'; import 'package:syncrow_web/pages/device_managment/one_gang_switch/bloc/wall_light_switch_state.dart';
import 'package:syncrow_web/pages/device_managment/one_gang_switch/models/wall_light_status_model.dart'; import 'package:syncrow_web/pages/device_managment/one_gang_switch/models/wall_light_status_model.dart';
import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart'; import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart';
import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart'; // import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart';
import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.dart'; import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.dart';
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart'; import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
class WallLightBatchControlView extends StatelessWidget class WallLightBatchControlView extends StatelessWidget with HelperResponsiveLayout {
with HelperResponsiveLayout {
const WallLightBatchControlView({super.key, required this.deviceIds}); const WallLightBatchControlView({super.key, required this.deviceIds});
final List<String> deviceIds; final List<String> deviceIds;
@ -27,8 +26,7 @@ class WallLightBatchControlView extends StatelessWidget
return const Center(child: CircularProgressIndicator()); return const Center(child: CircularProgressIndicator());
} else if (state is WallLightSwitchStatusLoaded) { } else if (state is WallLightSwitchStatusLoaded) {
return _buildStatusControls(context, state.status); return _buildStatusControls(context, state.status);
} else if (state is WallLightSwitchError || } else if (state is WallLightSwitchError || state is WallLightSwitchControlError) {
state is WallLightSwitchControlError) {
return const Center(child: Text('Error fetching status')); return const Center(child: Text('Error fetching status'));
} else { } else {
return const Center(child: CircularProgressIndicator()); return const Center(child: CircularProgressIndicator());
@ -38,8 +36,7 @@ class WallLightBatchControlView extends StatelessWidget
); );
} }
Widget _buildStatusControls( Widget _buildStatusControls(BuildContext context, WallLightStatusModel status) {
BuildContext context, WallLightStatusModel status) {
final isExtraLarge = isExtraLargeScreenSize(context); final isExtraLarge = isExtraLargeScreenSize(context);
final isLarge = isLargeScreenSize(context); final isLarge = isLargeScreenSize(context);
final isMedium = isMediumScreenSize(context); final isMedium = isMediumScreenSize(context);
@ -74,15 +71,14 @@ class WallLightBatchControlView extends StatelessWidget
); );
}, },
), ),
FirmwareUpdateWidget( // FirmwareUpdateWidget(
deviceId: deviceIds.first, // deviceId: deviceIds.first,
version: 12, // version: 12,
), // ),
FactoryResetWidget( FactoryResetWidget(
callFactoryReset: () { callFactoryReset: () {
context.read<WallLightSwitchBloc>().add(WallLightFactoryReset( context.read<WallLightSwitchBloc>().add(WallLightFactoryReset(
deviceId: status.uuid, deviceId: status.uuid, factoryReset: FactoryResetModel(devicesUuid: deviceIds)));
factoryReset: FactoryResetModel(devicesUuid: deviceIds)));
}, },
), ),
], ],

View File

@ -6,21 +6,19 @@ import 'package:syncrow_web/pages/device_managment/power_clamp/bloc/smart_power_
import 'package:syncrow_web/pages/device_managment/power_clamp/bloc/smart_power_state.dart'; import 'package:syncrow_web/pages/device_managment/power_clamp/bloc/smart_power_state.dart';
import 'package:syncrow_web/pages/device_managment/power_clamp/models/power_clamp_batch_model.dart'; import 'package:syncrow_web/pages/device_managment/power_clamp/models/power_clamp_batch_model.dart';
import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart'; import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart';
import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart'; // import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart';
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart'; import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
class PowerClampBatchControlView extends StatelessWidget class PowerClampBatchControlView extends StatelessWidget with HelperResponsiveLayout {
with HelperResponsiveLayout {
final List<String> deviceIds; final List<String> deviceIds;
const PowerClampBatchControlView({Key? key, required this.deviceIds}) const PowerClampBatchControlView({Key? key, required this.deviceIds}) : super(key: key);
: super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocProvider( return BlocProvider(
create: (context) => SmartPowerBloc(deviceId: deviceIds.first) create: (context) =>
..add(SmartPowerFetchBatchEvent(deviceIds)), SmartPowerBloc(deviceId: deviceIds.first)..add(SmartPowerFetchBatchEvent(deviceIds)),
child: BlocBuilder<SmartPowerBloc, SmartPowerState>( child: BlocBuilder<SmartPowerBloc, SmartPowerState>(
builder: (context, state) { builder: (context, state) {
if (state is SmartPowerLoading) { if (state is SmartPowerLoading) {
@ -37,18 +35,17 @@ class PowerClampBatchControlView extends StatelessWidget
); );
} }
Widget _buildStatusControls( Widget _buildStatusControls(BuildContext context, PowerClampBatchModel status) {
BuildContext context, PowerClampBatchModel status) {
return Row( return Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
SizedBox( // SizedBox(
width: 170, // width: 170,
// height: 140, // // height: 140,
child: FirmwareUpdateWidget(deviceId: deviceIds.first, version: 2)), // child: FirmwareUpdateWidget(deviceId: deviceIds.first, version: 2)),
const SizedBox( // const SizedBox(
width: 12, // width: 12,
), // ),
SizedBox( SizedBox(
width: 170, width: 170,
height: 140, height: 140,

View File

@ -1,128 +1,128 @@
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/device_managment/shared/device_controls_container.dart'; // import 'package:syncrow_web/pages/device_managment/shared/device_controls_container.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';
class FirmwareUpdateWidget extends StatefulWidget { // class FirmwareUpdateWidget extends StatefulWidget {
const FirmwareUpdateWidget({super.key, required this.deviceId, required this.version}); // const FirmwareUpdateWidget({super.key, required this.deviceId, required this.version});
final String deviceId; // final String deviceId;
final int version; // final int version;
@override // @override
State<FirmwareUpdateWidget> createState() => _FirmwareUpdateWidgetState(); // State<FirmwareUpdateWidget> createState() => _FirmwareUpdateWidgetState();
} // }
class _FirmwareUpdateWidgetState extends State<FirmwareUpdateWidget> { // class _FirmwareUpdateWidgetState extends State<FirmwareUpdateWidget> {
bool _showConfirmation = false; // bool _showConfirmation = false;
void _toggleConfirmation() { // void _toggleConfirmation() {
setState(() { // setState(() {
_showConfirmation = !_showConfirmation; // _showConfirmation = !_showConfirmation;
}); // });
} // }
@override // @override
Widget build(BuildContext context) { // Widget build(BuildContext context) {
return DeviceControlsContainer( // return DeviceControlsContainer(
child: _showConfirmation // child: _showConfirmation
? Column( // ? Column(
crossAxisAlignment: CrossAxisAlignment.start, // crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween, // mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ // children: [
Column( // Column(
children: [ // children: [
Text( // Text(
'Firmware Update', // 'Firmware Update',
style: context.textTheme.titleMedium!.copyWith( // style: context.textTheme.titleMedium!.copyWith(
fontWeight: FontWeight.bold, // fontWeight: FontWeight.bold,
color: ColorsManager.blackColor, // color: ColorsManager.blackColor,
), // ),
), // ),
Text( // Text(
'Are you sure?', // 'Are you sure?',
style: context.textTheme.bodySmall!.copyWith( // style: context.textTheme.bodySmall!.copyWith(
color: ColorsManager.grayColor, // color: ColorsManager.grayColor,
), // ),
), // ),
], // ],
), // ),
Row( // Row(
children: [ // children: [
Flexible( // Flexible(
child: DefaultButton( // child: DefaultButton(
height: 20, // height: 20,
elevation: 0, // elevation: 0,
padding: 0, // padding: 0,
onPressed: _toggleConfirmation, // onPressed: _toggleConfirmation,
backgroundColor: ColorsManager.greyColor, // backgroundColor: ColorsManager.greyColor,
child: Text( // child: Text(
'Cancel', // 'Cancel',
style: context.textTheme.bodyMedium!.copyWith( // style: context.textTheme.bodyMedium!.copyWith(
color: ColorsManager.blackColor, // color: ColorsManager.blackColor,
fontWeight: FontWeight.w400, // fontWeight: FontWeight.w400,
fontSize: 12, // fontSize: 12,
), // ),
), // ),
), // ),
), // ),
const SizedBox(width: 8), // const SizedBox(width: 8),
Flexible( // Flexible(
child: DefaultButton( // child: DefaultButton(
height: 20, // height: 20,
elevation: 0, // elevation: 0,
padding: 0, // padding: 0,
onPressed: () { // onPressed: () {
_toggleConfirmation(); // _toggleConfirmation();
}, // },
backgroundColor: ColorsManager.primaryColor, // backgroundColor: ColorsManager.primaryColor,
child: Text( // child: Text(
'Update', // 'Update',
style: context.textTheme.bodyMedium!.copyWith( // style: context.textTheme.bodyMedium!.copyWith(
color: ColorsManager.whiteColors, // color: ColorsManager.whiteColors,
fontWeight: FontWeight.w400, // fontWeight: FontWeight.w400,
fontSize: 12, // fontSize: 12,
), // ),
), // ),
), // ),
), // ),
], // ],
), // ),
], // ],
) // )
: GestureDetector( // : GestureDetector(
onTap: _toggleConfirmation, // onTap: _toggleConfirmation,
child: Column( // child: Column(
crossAxisAlignment: CrossAxisAlignment.start, // crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween, // mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ // children: [
ClipOval( // ClipOval(
child: Container( // child: Container(
color: ColorsManager.whiteColors, // color: ColorsManager.whiteColors,
height: 60, // height: 60,
width: 60, // width: 60,
child: Padding( // child: Padding(
padding: const EdgeInsets.all(12.0), // padding: const EdgeInsets.all(12.0),
child: SvgPicture.asset( // child: SvgPicture.asset(
Assets.firmware, // Assets.firmware,
fit: BoxFit.cover, // fit: BoxFit.cover,
), // ),
), // ),
), // ),
), // ),
Text( // Text(
'Firmware Update', // 'Firmware Update',
style: context.textTheme.titleMedium!.copyWith( // style: context.textTheme.titleMedium!.copyWith(
fontWeight: FontWeight.w400, // fontWeight: FontWeight.w400,
color: ColorsManager.blackColor, // color: ColorsManager.blackColor,
), // ),
), // ),
], // ],
), // ),
), // ),
); // );
} // }
} // }

View File

@ -18,20 +18,21 @@ class SOSBatchControlView extends StatelessWidget {
return Row( return Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
SizedBox( // SizedBox(
width: 170, // width: 170,
// height: 140, // // height: 140,
child: FirmwareUpdateWidget(deviceId: deviceIds.first, version: 2)), // child: FirmwareUpdateWidget(deviceId: deviceIds.first, version: 2)),
const SizedBox( // const SizedBox(
width: 12, // width: 12,
), // ),
SizedBox( SizedBox(
width: 170, width: 170,
height: 140, height: 140,
child: FactoryResetWidget( child: FactoryResetWidget(
callFactoryReset: () { callFactoryReset: () {
context.read<SosDeviceBloc>().add( context.read<SosDeviceBloc>().add(SosFactoryReset(
SosFactoryReset(deviceId: deviceIds.first, factoryReset: FactoryResetModel(devicesUuid: deviceIds))); deviceId: deviceIds.first,
factoryReset: FactoryResetModel(devicesUuid: deviceIds)));
}, },
), ),
), ),

View File

@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/factory_reset_model.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/models/factory_reset_model.dart';
import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart'; import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart';
import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart'; // import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart';
import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.dart'; import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.dart';
import 'package:syncrow_web/pages/device_managment/three_g_glass_switch/bloc/three_gang_glass_switch_bloc.dart'; import 'package:syncrow_web/pages/device_managment/three_g_glass_switch/bloc/three_gang_glass_switch_bloc.dart';
import 'package:syncrow_web/pages/device_managment/three_g_glass_switch/models/three_gang_glass_switch.dart'; import 'package:syncrow_web/pages/device_managment/three_g_glass_switch/models/three_gang_glass_switch.dart';
@ -98,10 +98,10 @@ class ThreeGangGlassSwitchBatchControlView extends StatelessWidget with HelperRe
); );
}, },
), ),
FirmwareUpdateWidget( // FirmwareUpdateWidget(
deviceId: deviceIds.first, // deviceId: deviceIds.first,
version: 12, // adjust the version according to your requirement // version: 12, // adjust the version according to your requirement
), // ),
FactoryResetWidget( FactoryResetWidget(
callFactoryReset: () { callFactoryReset: () {
context.read<ThreeGangGlassSwitchBloc>().add( context.read<ThreeGangGlassSwitchBloc>().add(

View File

@ -2,14 +2,13 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/factory_reset_model.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/models/factory_reset_model.dart';
import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart'; import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart';
import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart'; // import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart';
import 'package:syncrow_web/pages/device_managment/three_gang_switch/bloc/living_room_bloc.dart'; import 'package:syncrow_web/pages/device_managment/three_gang_switch/bloc/living_room_bloc.dart';
import 'package:syncrow_web/pages/device_managment/three_gang_switch/models/living_room_model.dart'; import 'package:syncrow_web/pages/device_managment/three_gang_switch/models/living_room_model.dart';
import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.dart'; import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.dart';
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart'; import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
class LivingRoomBatchControlsView extends StatelessWidget class LivingRoomBatchControlsView extends StatelessWidget with HelperResponsiveLayout {
with HelperResponsiveLayout {
const LivingRoomBatchControlsView({super.key, required this.deviceIds}); const LivingRoomBatchControlsView({super.key, required this.deviceIds});
final List<String> deviceIds; final List<String> deviceIds;
@ -17,16 +16,15 @@ class LivingRoomBatchControlsView extends StatelessWidget
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocProvider( return BlocProvider(
create: (context) => LivingRoomBloc(deviceId: deviceIds.first) create: (context) =>
..add(LivingRoomFetchBatchEvent(deviceIds)), LivingRoomBloc(deviceId: deviceIds.first)..add(LivingRoomFetchBatchEvent(deviceIds)),
child: BlocBuilder<LivingRoomBloc, LivingRoomState>( child: BlocBuilder<LivingRoomBloc, LivingRoomState>(
builder: (context, state) { builder: (context, state) {
if (state is LivingRoomDeviceStatusLoading) { if (state is LivingRoomDeviceStatusLoading) {
return const Center(child: CircularProgressIndicator()); return const Center(child: CircularProgressIndicator());
} else if (state is LivingRoomDeviceStatusLoaded) { } else if (state is LivingRoomDeviceStatusLoaded) {
return _buildStatusControls(context, state.status); return _buildStatusControls(context, state.status);
} else if (state is LivingRoomDeviceManagementError || } else if (state is LivingRoomDeviceManagementError || state is LivingRoomControlError) {
state is LivingRoomControlError) {
return const Center(child: Text('Error fetching status')); return const Center(child: Text('Error fetching status'));
} else { } else {
return const Center(child: CircularProgressIndicator()); return const Center(child: CircularProgressIndicator());
@ -36,8 +34,7 @@ class LivingRoomBatchControlsView extends StatelessWidget
); );
} }
Widget _buildStatusControls( Widget _buildStatusControls(BuildContext context, LivingRoomStatusModel status) {
BuildContext context, LivingRoomStatusModel status) {
final isExtraLarge = isExtraLargeScreenSize(context); final isExtraLarge = isExtraLargeScreenSize(context);
final isLarge = isLargeScreenSize(context); final isLarge = isLargeScreenSize(context);
final isMedium = isMediumScreenSize(context); final isMedium = isMediumScreenSize(context);
@ -102,10 +99,10 @@ class LivingRoomBatchControlsView extends StatelessWidget
); );
}, },
), ),
FirmwareUpdateWidget( // FirmwareUpdateWidget(
deviceId: deviceIds.first, // deviceId: deviceIds.first,
version: 12, // version: 12,
), // ),
FactoryResetWidget(callFactoryReset: () { FactoryResetWidget(callFactoryReset: () {
context.read<LivingRoomBloc>().add( context.read<LivingRoomBloc>().add(
LivingRoomFactoryResetEvent( LivingRoomFactoryResetEvent(

View File

@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/factory_reset_model.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/models/factory_reset_model.dart';
import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart'; import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart';
import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart'; // import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart';
import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.dart'; import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.dart';
import 'package:syncrow_web/pages/device_managment/two_g_glass_switch/bloc/two_gang_glass_switch_bloc.dart'; import 'package:syncrow_web/pages/device_managment/two_g_glass_switch/bloc/two_gang_glass_switch_bloc.dart';
import 'package:syncrow_web/pages/device_managment/two_g_glass_switch/models/two_gang_glass_status_model.dart'; import 'package:syncrow_web/pages/device_managment/two_g_glass_switch/models/two_gang_glass_status_model.dart';
@ -16,8 +16,8 @@ class TwoGangGlassSwitchBatchControlView extends StatelessWidget with HelperResp
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocProvider( return BlocProvider(
create: (context) => create: (context) => TwoGangGlassSwitchBloc(deviceId: deviceIds.first)
TwoGangGlassSwitchBloc(deviceId: deviceIds.first)..add(TwoGangGlassSwitchFetchBatchStatusEvent(deviceIds)), ..add(TwoGangGlassSwitchFetchBatchStatusEvent(deviceIds)),
child: BlocBuilder<TwoGangGlassSwitchBloc, TwoGangGlassSwitchState>( child: BlocBuilder<TwoGangGlassSwitchBloc, TwoGangGlassSwitchState>(
builder: (context, state) { builder: (context, state) {
if (state is TwoGangGlassSwitchLoading) { if (state is TwoGangGlassSwitchLoading) {
@ -83,10 +83,10 @@ class TwoGangGlassSwitchBatchControlView extends StatelessWidget with HelperResp
); );
}, },
), ),
FirmwareUpdateWidget( // FirmwareUpdateWidget(
deviceId: deviceIds.first, // deviceId: deviceIds.first,
version: 12, // adjust the version according to your requirement // version: 12, // adjust the version according to your requirement
), // ),
FactoryResetWidget( FactoryResetWidget(
callFactoryReset: () { callFactoryReset: () {
context.read<TwoGangGlassSwitchBloc>().add( context.read<TwoGangGlassSwitchBloc>().add(

View File

@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/factory_reset_model.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/models/factory_reset_model.dart';
import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart'; import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart';
import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart'; // import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart';
import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.dart'; import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.dart';
import 'package:syncrow_web/pages/device_managment/two_gang_switch/bloc/two_gang_switch_bloc.dart'; import 'package:syncrow_web/pages/device_managment/two_gang_switch/bloc/two_gang_switch_bloc.dart';
import 'package:syncrow_web/pages/device_managment/two_gang_switch/bloc/two_gang_switch_event.dart'; import 'package:syncrow_web/pages/device_managment/two_gang_switch/bloc/two_gang_switch_event.dart';
@ -10,8 +10,7 @@ import 'package:syncrow_web/pages/device_managment/two_gang_switch/bloc/two_gang
import 'package:syncrow_web/pages/device_managment/two_gang_switch/models/two_gang_status_model.dart'; import 'package:syncrow_web/pages/device_managment/two_gang_switch/models/two_gang_status_model.dart';
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart'; import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
class TwoGangBatchControlView extends StatelessWidget class TwoGangBatchControlView extends StatelessWidget with HelperResponsiveLayout {
with HelperResponsiveLayout {
const TwoGangBatchControlView({super.key, required this.deviceIds}); const TwoGangBatchControlView({super.key, required this.deviceIds});
final List<String> deviceIds; final List<String> deviceIds;
@ -27,8 +26,7 @@ class TwoGangBatchControlView extends StatelessWidget
return const Center(child: CircularProgressIndicator()); return const Center(child: CircularProgressIndicator());
} else if (state is TwoGangSwitchStatusLoaded) { } else if (state is TwoGangSwitchStatusLoaded) {
return _buildStatusControls(context, state.status); return _buildStatusControls(context, state.status);
} else if (state is TwoGangSwitchError || } else if (state is TwoGangSwitchError || state is TwoGangSwitchControlError) {
state is TwoGangSwitchControlError) {
return const Center(child: Text('Error fetching status')); return const Center(child: Text('Error fetching status'));
} else { } else {
return const Center(child: CircularProgressIndicator()); return const Center(child: CircularProgressIndicator());
@ -84,10 +82,10 @@ class TwoGangBatchControlView extends StatelessWidget
)); ));
}, },
), ),
FirmwareUpdateWidget( // FirmwareUpdateWidget(
deviceId: deviceIds.first, // deviceId: deviceIds.first,
version: 12, // version: 12,
), // ),
FactoryResetWidget(callFactoryReset: () { FactoryResetWidget(callFactoryReset: () {
context.read<TwoGangSwitchBloc>().add( context.read<TwoGangSwitchBloc>().add(
TwoGangFactoryReset( TwoGangFactoryReset(

View File

@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/factory_reset_model.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/models/factory_reset_model.dart';
import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart'; import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart';
import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart'; // import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart';
import 'package:syncrow_web/pages/device_managment/shared/sensors_widgets/presence_update_data.dart'; import 'package:syncrow_web/pages/device_managment/shared/sensors_widgets/presence_update_data.dart';
import 'package:syncrow_web/pages/device_managment/wall_sensor/bloc/wall_bloc.dart'; import 'package:syncrow_web/pages/device_managment/wall_sensor/bloc/wall_bloc.dart';
import 'package:syncrow_web/pages/device_managment/wall_sensor/bloc/wall_event.dart'; import 'package:syncrow_web/pages/device_managment/wall_sensor/bloc/wall_event.dart';
@ -113,7 +113,7 @@ class WallSensorBatchControlView extends StatelessWidget with HelperResponsiveLa
), ),
), ),
), ),
FirmwareUpdateWidget(deviceId: devicesIds.first, version: 2), // FirmwareUpdateWidget(deviceId: devicesIds.first, version: 2),
FactoryResetWidget( FactoryResetWidget(
callFactoryReset: () { callFactoryReset: () {
context.read<WallSensorBloc>().add( context.read<WallSensorBloc>().add(

View File

@ -2,15 +2,14 @@ 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/batch_control/factory_reset.dart'; import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart';
import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart'; // import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart';
import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.dart'; import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.dart';
import 'package:syncrow_web/pages/device_managment/water_heater/bloc/water_heater_bloc.dart'; import 'package:syncrow_web/pages/device_managment/water_heater/bloc/water_heater_bloc.dart';
import 'package:syncrow_web/pages/device_managment/water_heater/models/water_heater_status_model.dart'; import 'package:syncrow_web/pages/device_managment/water_heater/models/water_heater_status_model.dart';
import 'package:syncrow_web/utils/constants/assets.dart'; import 'package:syncrow_web/utils/constants/assets.dart';
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart'; import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
class WaterHEaterBatchControlView extends StatelessWidget class WaterHEaterBatchControlView extends StatelessWidget with HelperResponsiveLayout {
with HelperResponsiveLayout {
const WaterHEaterBatchControlView({super.key, required this.deviceIds}); const WaterHEaterBatchControlView({super.key, required this.deviceIds});
final List<String> deviceIds; final List<String> deviceIds;
@ -18,8 +17,8 @@ class WaterHEaterBatchControlView extends StatelessWidget
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocProvider( return BlocProvider(
create: (context) => WaterHeaterBloc() create: (context) =>
..add(FetchWaterHeaterBatchStatusEvent(devicesUuid: deviceIds)), WaterHeaterBloc()..add(FetchWaterHeaterBatchStatusEvent(devicesUuid: deviceIds)),
child: BlocBuilder<WaterHeaterBloc, WaterHeaterState>( child: BlocBuilder<WaterHeaterBloc, WaterHeaterState>(
builder: (context, state) { builder: (context, state) {
if (state is WaterHeaterLoadingState) { if (state is WaterHeaterLoadingState) {
@ -36,8 +35,7 @@ class WaterHEaterBatchControlView extends StatelessWidget
); );
} }
Widget _buildStatusControls( Widget _buildStatusControls(BuildContext context, WaterHeaterStatusModel status) {
BuildContext context, WaterHeaterStatusModel status) {
final isExtraLarge = isExtraLargeScreenSize(context); final isExtraLarge = isExtraLargeScreenSize(context);
final isLarge = isLargeScreenSize(context); final isLarge = isLargeScreenSize(context);
final isMedium = isMediumScreenSize(context); final isMedium = isMediumScreenSize(context);
@ -73,10 +71,10 @@ class WaterHEaterBatchControlView extends StatelessWidget
); );
}, },
), ),
FirmwareUpdateWidget( // FirmwareUpdateWidget(
deviceId: deviceIds.first, // deviceId: deviceIds.first,
version: 12, // version: 12,
), // ),
FactoryResetWidget( FactoryResetWidget(
callFactoryReset: () {}, callFactoryReset: () {},
), ),

View File

@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/factory_reset_model.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/models/factory_reset_model.dart';
import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart'; import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart';
import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart'; // import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart';
import 'package:syncrow_web/pages/device_managment/water_leak/bloc/water_leak_bloc.dart'; import 'package:syncrow_web/pages/device_managment/water_leak/bloc/water_leak_bloc.dart';
import 'package:syncrow_web/pages/device_managment/water_leak/bloc/water_leak_event.dart'; import 'package:syncrow_web/pages/device_managment/water_leak/bloc/water_leak_event.dart';
@ -10,18 +10,16 @@ import 'package:syncrow_web/pages/device_managment/water_leak/bloc/water_leak_st
import 'package:syncrow_web/pages/device_managment/water_leak/model/water_leak_status_model.dart'; import 'package:syncrow_web/pages/device_managment/water_leak/model/water_leak_status_model.dart';
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart'; import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
class WaterLeakBatchControlView extends StatelessWidget class WaterLeakBatchControlView extends StatelessWidget with HelperResponsiveLayout {
with HelperResponsiveLayout {
final List<String> deviceIds; final List<String> deviceIds;
const WaterLeakBatchControlView({Key? key, required this.deviceIds}) const WaterLeakBatchControlView({Key? key, required this.deviceIds}) : super(key: key);
: super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocProvider( return BlocProvider(
create: (context) => WaterLeakBloc(deviceIds.first) create: (context) =>
..add(FetchWaterLeakBatchStatusEvent(deviceIds)), WaterLeakBloc(deviceIds.first)..add(FetchWaterLeakBatchStatusEvent(deviceIds)),
child: BlocBuilder<WaterLeakBloc, WaterLeakState>( child: BlocBuilder<WaterLeakBloc, WaterLeakState>(
builder: (context, state) { builder: (context, state) {
if (state is WaterLeakLoadingState) { if (state is WaterLeakLoadingState) {
@ -38,18 +36,17 @@ class WaterLeakBatchControlView extends StatelessWidget
); );
} }
Widget _buildStatusControls( Widget _buildStatusControls(BuildContext context, WaterLeakStatusModel status) {
BuildContext context, WaterLeakStatusModel status) {
return Row( return Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
SizedBox( // SizedBox(
width: 170, // width: 170,
height: 140, // height: 140,
child: FirmwareUpdateWidget(deviceId: deviceIds.first, version: 2)), // child: FirmwareUpdateWidget(deviceId: deviceIds.first, version: 2)),
const SizedBox( // const SizedBox(
width: 12, // width: 12,
), // ),
SizedBox( SizedBox(
width: 170, width: 170,
height: 140, height: 140,

View File

@ -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,44 +84,46 @@ 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,
), ),
HomeItemModel( // HomeItemModel(
title: 'Move in', // title: 'Move in',
icon: Assets.moveinIcon, // icon: Assets.moveinIcon,
active: false, // active: false,
onPress: (context) {}, // onPress: (context) {},
color: ColorsManager.primaryColor, // color: ColorsManager.primaryColor,
), // ),
HomeItemModel( // HomeItemModel(
title: 'Construction', // title: 'Construction',
icon: Assets.constructionIcon, // icon: Assets.constructionIcon,
active: false, // active: false,
onPress: (context) {}, // onPress: (context) {},
color: ColorsManager.primaryColor, // color: ColorsManager.primaryColor,
), // ),
HomeItemModel( // HomeItemModel(
title: 'Energy', // title: 'Energy',
icon: Assets.energyIcon, // icon: Assets.energyIcon,
active: false, // active: false,
onPress: (context) {}, // onPress: (context) {},
color: ColorsManager.slidingBlueColor.withOpacity(0.2), // color: ColorsManager.slidingBlueColor.withOpacity(0.2),
), // ),
HomeItemModel( // HomeItemModel(
title: 'Integrations', // title: 'Integrations',
icon: Assets.integrationsIcon, // icon: Assets.integrationsIcon,
active: false, // active: false,
onPress: (context) {}, // onPress: (context) {},
color: ColorsManager.slidingBlueColor.withOpacity(0.2), // color: ColorsManager.slidingBlueColor.withOpacity(0.2),
), // ),
HomeItemModel( // HomeItemModel(
title: 'Asset', // title: 'Asset',
icon: Assets.assetIcon, // icon: Assets.assetIcon,
active: false, // active: false,
onPress: (context) {}, // onPress: (context) {},
color: ColorsManager.slidingBlueColor.withOpacity(0.2), // color: ColorsManager.slidingBlueColor.withOpacity(0.2),
), // ),
]; ];
} }

View File

@ -51,7 +51,7 @@ class HomeWebPage extends StatelessWidget {
height: size.height * 0.6, height: size.height * 0.6,
width: size.width * 0.68, width: size.width * 0.68,
child: GridView.builder( child: GridView.builder(
itemCount: 8, itemCount: 3, //8
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4, crossAxisCount: 4,
crossAxisSpacing: 20.0, crossAxisSpacing: 20.0,

File diff suppressed because it is too large Load Diff

View File

@ -187,8 +187,24 @@ class SetAutomationActionExecutor extends RoutineEvent {
List<Object> get props => [automationActionExecutor]; 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 FetchDevicesInRoutine extends RoutineEvent {}
class ResetRoutineState extends RoutineEvent {} class ResetRoutineState extends RoutineEvent {}
class ClearFunctions extends RoutineEvent {} class ClearFunctions extends RoutineEvent {}
class ResetErrorMessage extends RoutineEvent {}

View File

@ -22,32 +22,35 @@ class RoutineState extends Equatable {
final String? automationId; final String? automationId;
final bool? isUpdate; final bool? isUpdate;
final List<AllDevicesModel> devices; final List<AllDevicesModel> devices;
final String? automationActionExecutor; // 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.devices = const [],
this.automationActionExecutor, // this.automationActionExecutor,
}); this.routineTab = false,
this.createRoutineView = false});
RoutineState copyWith({ RoutineState copyWith({
List<Map<String, dynamic>>? ifItems, List<Map<String, dynamic>>? ifItems,
@ -70,35 +73,38 @@ class RoutineState extends Equatable {
String? automationId, String? automationId,
bool? isUpdate, bool? isUpdate,
List<AllDevicesModel>? devices, List<AllDevicesModel>? devices,
String? automationActionExecutor, // 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, devices: devices ?? this.devices,
automationActionExecutor: // automationActionExecutor: automationActionExecutor ?? this.automationActionExecutor,
automationActionExecutor ?? this.automationActionExecutor, routineTab: routineTab ?? this.routineTab,
); createRoutineView: createRoutineView ?? this.createRoutineView);
} }
@override @override
@ -123,6 +129,8 @@ class RoutineState extends Equatable {
automationId, automationId,
isUpdate, isUpdate,
devices, devices,
automationActionExecutor, // automationActionExecutor,
routineTab,
createRoutineView
]; ];
} }

View File

@ -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>(
@ -54,27 +57,23 @@ class SaveRoutineHelper {
), ),
if (state.isAutomation) if (state.isAutomation)
...state.ifItems.map((item) { ...state.ifItems.map((item) {
final functions = state.selectedFunctions[ final functions =
item['uniqueCustomId']] ?? state.selectedFunctions[item['uniqueCustomId']] ?? [];
[];
return ListTile( return ListTile(
leading: SvgPicture.asset( leading: SvgPicture.asset(
item['imagePath'], item['imagePath'],
width: 22, width: 22,
height: 22, height: 22,
), ),
title: Text(item['title'], title:
style: const TextStyle(fontSize: 14)), 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: const TextStyle(
color: ColorsManager color: ColorsManager.grayColor, fontSize: 8),
.grayColor, overflow: TextOverflow.ellipsis,
fontSize: 8),
overflow:
TextOverflow.ellipsis,
maxLines: 3, maxLines: 3,
)) ))
.toList(), .toList(),
@ -99,25 +98,33 @@ class SaveRoutineHelper {
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
...state.thenItems.map((item) { ...state.thenItems.map((item) {
final functions = state.selectedFunctions[ final functions =
item['uniqueCustomId']] ?? state.selectedFunctions[item['uniqueCustomId']] ?? [];
[];
return ListTile( return ListTile(
leading: SvgPicture.asset( leading: item['type'] == 'tap_to_run' || item['type'] == 'scene'
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: color: ColorsManager.grayColor, fontSize: 8),
ColorsManager.grayColor,
fontSize: 8),
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
maxLines: 3, maxLines: 3,
)) ))
@ -131,42 +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) {
if (state.automationId != null) { if (state.isUpdate ?? false) {
context context.read<RoutineBloc>().add(const UpdateAutomation());
.read<RoutineBloc>()
.add(const UpdateAutomation());
} else { } else {
context context.read<RoutineBloc>().add(const CreateAutomationEvent());
.read<RoutineBloc>()
.add(const CreateAutomationEvent());
} }
} else { } else {
if (state.sceneId != null) { if (state.isUpdate ?? false) {
context context.read<RoutineBloc>().add(const UpdateScene());
.read<RoutineBloc>()
.add(const UpdateScene());
} else { } else {
context context.read<RoutineBloc>().add(const CreateSceneEvent());
.read<RoutineBloc>()
.add(const CreateSceneEvent());
}
if (context.read<RoutineBloc>().state.errorMessage ==
null) {
Navigator.pop(context, true);
} }
} }
// if (state.errorMessage == null || state.errorMessage!.isEmpty) {
Navigator.pop(context);
// }
}, },
isConfirmEnabled: true, isConfirmEnabled: true,
), ),

View File

@ -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

View File

@ -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:

View File

@ -48,8 +48,7 @@ class RoutineDetailsModel {
spaceUuid: spaceUuid, spaceUuid: spaceUuid,
automationName: name, automationName: name,
decisionExpr: decisionExpr, decisionExpr: decisionExpr,
effectiveTime: effectiveTime: effectiveTime ?? EffectiveTime(start: '', end: '', loops: ''),
effectiveTime ?? EffectiveTime(start: '', end: '', loops: ''),
conditions: conditions?.map((c) => c.toCondition()).toList() ?? [], conditions: conditions?.map((c) => c.toCondition()).toList() ?? [],
actions: actions.map((a) => a.toAutomationAction()).toList(), actions: actions.map((a) => a.toAutomationAction()).toList(),
); );
@ -64,8 +63,7 @@ class RoutineDetailsModel {
if (iconId != null) 'iconUuid': 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 (sceneId != null) 'sceneId': sceneId,
if (automationId != null) 'automationId': automationId, if (automationId != null) 'automationId': automationId,
@ -82,12 +80,10 @@ class RoutineDetailsModel {
), ),
iconId: map['iconUuid'], iconId: map['iconUuid'],
showInDevice: map['showInDevice'], showInDevice: map['showInDevice'],
effectiveTime: map['effectiveTime'] != null effectiveTime:
? EffectiveTime.fromMap(map['effectiveTime']) map['effectiveTime'] != null ? EffectiveTime.fromMap(map['effectiveTime']) : null,
: null,
conditions: map['conditions'] != null conditions: map['conditions'] != null
? List<RoutineCondition>.from( ? List<RoutineCondition>.from(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'], sceneId: map['sceneId'],
@ -108,15 +104,16 @@ class RoutineAction {
final RoutineExecutorProperty? executorProperty; final RoutineExecutorProperty? executorProperty;
final String productType; final String productType;
final String? type; final String? type;
final String? icon;
RoutineAction({ RoutineAction(
required this.entityId, {required this.entityId,
required this.actionExecutor, required this.actionExecutor,
required this.productType, required this.productType,
this.executorProperty, this.executorProperty,
this.name, this.name,
this.type, this.type,
}); this.icon});
CreateSceneAction toCreateSceneAction() { CreateSceneAction toCreateSceneAction() {
return CreateSceneAction( return CreateSceneAction(
@ -140,22 +137,21 @@ class RoutineAction {
'actionExecutor': actionExecutor, 'actionExecutor': actionExecutor,
if (type != null) 'type': type, if (type != null) 'type': type,
if (name != null) 'name': name, if (name != null) 'name': name,
if (executorProperty != null) if (executorProperty != null) 'executorProperty': executorProperty!.toMap(),
'executorProperty': executorProperty!.toMap(),
}; };
} }
factory RoutineAction.fromMap(Map<String, dynamic> map) { factory RoutineAction.fromMap(Map<String, dynamic> map) {
return RoutineAction( return RoutineAction(
entityId: map['entityId'] ?? '', entityId: map['entityId'] ?? '',
actionExecutor: map['actionExecutor'] ?? '', actionExecutor: map['actionExecutor'] ?? '',
productType: map['productType'] ?? '', productType: map['productType'] ?? '',
name: map['name'] ?? '', name: map['name'] ?? '',
type: map['type'] ?? '', type: map['type'] ?? '',
executorProperty: map['executorProperty'] != null executorProperty: map['executorProperty'] != null
? RoutineExecutorProperty.fromMap(map['executorProperty']) ? RoutineExecutorProperty.fromMap(map['executorProperty'])
: null, : null,
); icon: map['icon']);
} }
} }

View File

@ -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/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';
@ -23,12 +22,10 @@ class _RoutinesViewState extends State<RoutinesView> {
@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(
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
@ -49,12 +46,12 @@ class _RoutinesViewState extends State<RoutinesView> {
), ),
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: '',

View File

@ -33,31 +33,24 @@ class DeleteSceneWidget extends StatelessWidget {
alignment: AlignmentDirectional.center, alignment: AlignmentDirectional.center,
child: Text( child: Text(
'Cancel', 'Cancel',
style: Theme.of(context) style: Theme.of(context).textTheme.bodyMedium!.copyWith(
.textTheme
.bodyMedium!
.copyWith(
color: ColorsManager.textGray, color: ColorsManager.textGray,
), ),
), ),
), ),
), ),
Container( Container(width: 1, height: 50, color: ColorsManager.greyColor),
width: 1, height: 50, color: ColorsManager.greyColor),
InkWell( InkWell(
onTap: () { onTap: () {
context.read<RoutineBloc>().add(const DeleteScene()); context.read<RoutineBloc>().add(const DeleteScene());
Navigator.of(context).pop(); Navigator.of(context).pop();
Navigator.of(context).pop(true); Navigator.of(context).pop();
}, },
child: Container( child: Container(
alignment: AlignmentDirectional.center, alignment: AlignmentDirectional.center,
child: Text( child: Text(
'Confirm', 'Confirm',
style: Theme.of(context) style: Theme.of(context).textTheme.bodyMedium!.copyWith(
.textTheme
.bodyMedium!
.copyWith(
color: ColorsManager.primaryColorWithOpacity, color: ColorsManager.primaryColorWithOpacity,
), ),
), ),

View File

@ -32,15 +32,27 @@ class DraggableCard extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocBuilder<RoutineBloc, RoutineState>( return BlocBuilder<RoutineBloc, RoutineState>(
builder: (context, state) { builder: (context, state) {
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(
angle: -0.1, angle: -0.1,
child: child: _buildCardContent(context, deviceFunctions, padding: padding),
_buildCardContent(context, deviceFunctions, padding: padding),
), ),
childWhenDragging: _buildGreyContainer(), childWhenDragging: _buildGreyContainer(),
child: _buildCardContent(context, deviceFunctions, padding: padding), child: _buildCardContent(context, deviceFunctions, padding: padding),
@ -49,8 +61,7 @@ class DraggableCard extends StatelessWidget {
); );
} }
Widget _buildCardContent( Widget _buildCardContent(BuildContext context, List<DeviceFunctionData> deviceFunctions,
BuildContext context, List<DeviceFunctionData> deviceFunctions,
{EdgeInsetsGeometry? padding}) { {EdgeInsetsGeometry? padding}) {
return Stack( return Stack(
children: [ children: [
@ -79,17 +90,13 @@ class DraggableCard extends StatelessWidget {
), ),
), ),
padding: const EdgeInsets.all(8), padding: const EdgeInsets.all(8),
child: imagePath.contains('.svg') child: deviceData['type'] == 'tap_to_run' || deviceData['type'] == 'scene'
? SvgPicture.asset( ? Image.memory(
imagePath, base64Decode(deviceData['icon']),
) )
: imagePath.contains('.png') : SvgPicture.asset(
? Image.asset( imagePath,
imagePath, ),
)
: Image.memory(
base64Decode(imagePath),
),
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
Padding( Padding(
@ -152,8 +159,7 @@ class DraggableCard extends StatelessWidget {
} }
String _formatFunctionValue(DeviceFunctionData function) { String _formatFunctionValue(DeviceFunctionData function) {
if (function.functionCode == 'temp_set' || if (function.functionCode == 'temp_set' || function.functionCode == 'temp_current') {
function.functionCode == 'temp_current') {
return '${(function.value / 10).toStringAsFixed(0)}°C'; return '${(function.value / 10).toStringAsFixed(0)}°C';
} else if (function.functionCode.contains('countdown')) { } else if (function.functionCode.contains('countdown')) {
final seconds = function.value.toInt(); final seconds = function.value.toInt();

View File

@ -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/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';
@ -69,8 +68,8 @@ class _FetchRoutineScenesState extends State<FetchRoutineScenesAutomation>
), ),
child: RoutineViewCard( child: RoutineViewCard(
onTap: () { onTap: () {
BlocProvider.of<SwitchTabsBloc>(context).add( BlocProvider.of<RoutineBloc>(context).add(
const CreateNewRoutineViewEvent(true), const CreateNewRoutineViewEvent(createRoutineView: true),
); );
context.read<RoutineBloc>().add( context.read<RoutineBloc>().add(
GetSceneDetails( GetSceneDetails(
@ -118,8 +117,8 @@ class _FetchRoutineScenesState extends State<FetchRoutineScenesAutomation>
), ),
child: RoutineViewCard( child: RoutineViewCard(
onTap: () { onTap: () {
BlocProvider.of<SwitchTabsBloc>(context).add( BlocProvider.of<RoutineBloc>(context).add(
const CreateNewRoutineViewEvent(true), const CreateNewRoutineViewEvent(createRoutineView: true),
); );
context.read<RoutineBloc>().add( context.read<RoutineBloc>().add(
GetAutomationDetails( GetAutomationDetails(

View File

@ -7,98 +7,106 @@ 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/constants/assets.dart'; import 'package:syncrow_web/utils/constants/assets.dart';
class AutomationDialog extends StatelessWidget { 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
Widget build(BuildContext context) { State<AutomationDialog> createState() => _AutomationDialogState();
return BlocBuilder<RoutineBloc, RoutineState>( }
builder: (context, state) {
final isEnabled = state.automationActionExecutor == 'rule_enable';
return Dialog( class _AutomationDialogState extends State<AutomationDialog> {
shape: String? selectedAutomationActionExecutor;
RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
child: Container( @override
width: 400, void initState() {
padding: const EdgeInsets.all(16), super.initState();
child: Column( List<DeviceFunctionData>? functions = context
mainAxisSize: MainAxisSize.min, .read<RoutineBloc>()
children: [ .state
DialogHeader(automationName), .selectedFunctions[widget.uniqueCustomId];
const SizedBox(height: 16), for (DeviceFunctionData data in functions ?? []) {
ListTile( if (data.entityId == widget.automationId) {
leading: selectedAutomationActionExecutor = data.value;
SvgPicture.asset(Assets.acPower, width: 24, height: 24), }
title: const Text('Enable'), }
trailing: Radio<bool>( }
value: true,
groupValue: isEnabled, @override
onChanged: (bool? value) { Widget build(BuildContext context) {
if (value == true) { return Dialog(
context.read<RoutineBloc>().add( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
const SetAutomationActionExecutor( child: Container(
automationActionExecutor: 'rule_enable', width: 400,
), padding: const EdgeInsets.all(16),
); child: Column(
} mainAxisSize: MainAxisSize.min,
}, children: [
), DialogHeader(widget.automationName),
), const SizedBox(height: 16),
ListTile( ListTile(
leading: SvgPicture.asset(Assets.acPowerOff, leading: SvgPicture.asset(Assets.acPower, width: 24, height: 24),
width: 24, height: 24), title: const Text('Enable'),
title: const Text('Disable'), trailing: Radio<String?>(
trailing: Radio<bool>( value: 'rule_enable',
value: false, groupValue: selectedAutomationActionExecutor,
groupValue: isEnabled, onChanged: (String? value) {
onChanged: (bool? value) { setState(() {
if (value == false) { selectedAutomationActionExecutor = 'rule_enable';
context.read<RoutineBloc>().add( });
const SetAutomationActionExecutor( }),
automationActionExecutor: 'rule_disable',
),
);
}
},
),
),
const SizedBox(height: 16),
DialogFooter(
onConfirm: () {
context.read<RoutineBloc>().add(
AddFunctionToRoutine(
[
DeviceFunctionData(
entityId: automationId,
functionCode: 'automation',
value: state.automationActionExecutor,
operationName: 'Automation',
),
],
uniqueCustomId,
),
);
Navigator.of(context).pop(true);
},
onCancel: () => Navigator.of(context).pop(false),
isConfirmEnabled: true,
dialogWidth: 400,
),
],
), ),
), ListTile(
); leading:
}, SvgPicture.asset(Assets.acPowerOff, width: 24, height: 24),
title: const Text('Disable'),
trailing: Radio<String?>(
value: 'rule_disable',
groupValue: selectedAutomationActionExecutor,
onChanged: (String? value) {
setState(() {
selectedAutomationActionExecutor = 'rule_disable';
});
},
),
),
const SizedBox(height: 16),
DialogFooter(
onConfirm: () {
if (selectedAutomationActionExecutor != null) {
context.read<RoutineBloc>().add(
AddFunctionToRoutine(
[
DeviceFunctionData(
entityId: widget.automationId,
functionCode: 'automation',
value: selectedAutomationActionExecutor,
operationName: 'Automation',
),
],
widget.uniqueCustomId,
),
);
}
Navigator.of(context).pop(true);
},
onCancel: () => Navigator.of(context).pop(),
isConfirmEnabled: selectedAutomationActionExecutor != null,
dialogWidth: 400,
),
],
),
),
); );
} }
} }

View File

@ -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),
); );
}); });
} }

View File

@ -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';
@ -16,8 +15,7 @@ class RoutineSearchAndButtons extends StatefulWidget {
}); });
@override @override
State<RoutineSearchAndButtons> createState() => State<RoutineSearchAndButtons> createState() => _RoutineSearchAndButtonsState();
_RoutineSearchAndButtonsState();
} }
class _RoutineSearchAndButtonsState extends State<RoutineSearchAndButtons> { class _RoutineSearchAndButtonsState extends State<RoutineSearchAndButtons> {
@ -37,20 +35,21 @@ class _RoutineSearchAndButtonsState extends State<RoutineSearchAndButtons> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocConsumer<RoutineBloc, RoutineState>( return BlocBuilder<RoutineBloc, RoutineState>(
listenWhen: (previous, current) =>
previous.routineName != current.routineName,
listener: (context, state) {
if (state.routineName != _nameController.text) {
_nameController.text = state.routineName ?? '';
}
},
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: [
@ -62,9 +61,8 @@ class _RoutineSearchAndButtonsState extends State<RoutineSearchAndButtons> {
children: [ children: [
ConstrainedBox( ConstrainedBox(
constraints: BoxConstraints( constraints: BoxConstraints(
maxWidth: constraints.maxWidth > 700 maxWidth:
? 450 constraints.maxWidth > 700 ? 450 : constraints.maxWidth - 32),
: constraints.maxWidth - 32),
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@ -73,13 +71,10 @@ class _RoutineSearchAndButtonsState extends State<RoutineSearchAndButtons> {
children: [ children: [
Text('* ', Text('* ',
style: context.textTheme.bodyMedium! style: context.textTheme.bodyMedium!
.copyWith( .copyWith(color: ColorsManager.red, fontSize: 13)),
color: ColorsManager.red,
fontSize: 13)),
Text( Text(
'Routine Name', 'Routine Name',
style: context.textTheme.bodyMedium! style: context.textTheme.bodyMedium!.copyWith(
.copyWith(
fontSize: 13, fontSize: 13,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: ColorsManager.blackColor, color: ColorsManager.blackColor,
@ -93,24 +88,20 @@ class _RoutineSearchAndButtonsState extends State<RoutineSearchAndButtons> {
decoration: containerWhiteDecoration, decoration: containerWhiteDecoration,
child: TextFormField( child: TextFormField(
style: context.textTheme.bodyMedium! style: context.textTheme.bodyMedium!
.copyWith( .copyWith(color: ColorsManager.blackColor),
color: ColorsManager.blackColor),
controller: _nameController, controller: _nameController,
decoration: InputDecoration( decoration: InputDecoration(
hintText: 'Please enter the name', hintText: 'Please enter the name',
hintStyle: context.textTheme.bodyMedium! hintStyle: context.textTheme.bodyMedium!
.copyWith( .copyWith(fontSize: 12, color: ColorsManager.grayColor),
fontSize: 12,
color: ColorsManager.grayColor),
contentPadding: contentPadding:
const EdgeInsets.symmetric( const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
horizontal: 12, vertical: 10),
border: InputBorder.none, border: InputBorder.none,
), ),
onChanged: (value) { onTapOutside: (_) {
context context
.read<RoutineBloc>() .read<RoutineBloc>()
.add(SetRoutineName(value)); .add(SetRoutineName(_nameController.text));
}, },
validator: (value) { validator: (value) {
if (value == null || value.isEmpty) { if (value == null || value.isEmpty) {
@ -130,18 +121,16 @@ class _RoutineSearchAndButtonsState extends State<RoutineSearchAndButtons> {
width: 200, width: 200,
child: Center( child: Center(
child: DefaultButton( child: DefaultButton(
onPressed: state.isAutomation || onPressed: state.isAutomation || state.isTabToRun
state.isTabToRun
? () async { ? () async {
final result = await SettingHelper final result = await SettingHelper.showSettingDialog(
.showSettingDialog(
context: context, context: context,
iconId: iconId: state.selectedIcon ?? '',
state.selectedIcon ?? '',
); );
if (result != null) { if (result != null) {
context.read<RoutineBloc>().add( context
AddSelectedIcon(result)); .read<RoutineBloc>()
.add(AddSelectedIcon(result));
} }
} }
: null, : null,
@ -197,12 +186,10 @@ class _RoutineSearchAndButtonsState extends State<RoutineSearchAndButtons> {
child: Center( child: Center(
child: DefaultButton( child: DefaultButton(
onPressed: () async { onPressed: () async {
if (state.routineName == null || if (state.routineName == null || state.routineName!.isEmpty) {
state.routineName!.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar( SnackBar(
content: const Text( content: const Text('Please enter the routine name'),
'Please enter the routine name'),
duration: const Duration(seconds: 2), duration: const Duration(seconds: 2),
backgroundColor: ColorsManager.red, backgroundColor: ColorsManager.red,
action: SnackBarAction( action: SnackBarAction(
@ -216,12 +203,10 @@ class _RoutineSearchAndButtonsState extends State<RoutineSearchAndButtons> {
return; return;
} }
if (state.ifItems.isEmpty || if (state.ifItems.isEmpty || state.thenItems.isEmpty) {
state.thenItems.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar( SnackBar(
content: const Text( content: const Text('Please add if and then condition'),
'Please add if and then condition'),
duration: const Duration(seconds: 2), duration: const Duration(seconds: 2),
backgroundColor: ColorsManager.red, backgroundColor: ColorsManager.red,
action: SnackBarAction( action: SnackBarAction(
@ -234,18 +219,18 @@ class _RoutineSearchAndButtonsState extends State<RoutineSearchAndButtons> {
); );
return; return;
} }
final result = await SaveRoutineHelper // final result =
.showSaveRoutineDialog(context); // await
if (result != null && result) { BlocProvider.of<RoutineBloc>(context).add(ResetErrorMessage());
BlocProvider.of<SwitchTabsBloc>(context) SaveRoutineHelper.showSaveRoutineDialog(context);
.add( // if (result != null && result) {
const CreateNewRoutineViewEvent(false), // BlocProvider.of<RoutineBloc>(context).add(
); // const CreateNewRoutineViewEvent(createRoutineView: false),
BlocProvider.of<SwitchTabsBloc>(context) // );
.add( // BlocProvider.of<RoutineBloc>(context).add(
const TriggerSwitchTabsEvent(true), // const TriggerSwitchTabsEvent(isRoutineTab: true),
); // );
} // }
}, },
borderRadius: 15, borderRadius: 15,
elevation: 0, elevation: 0,
@ -276,14 +261,10 @@ class _RoutineSearchAndButtonsState extends State<RoutineSearchAndButtons> {
child: DefaultButton( child: DefaultButton(
onPressed: state.isAutomation || state.isTabToRun onPressed: state.isAutomation || state.isTabToRun
? () async { ? () async {
final result = final result = await SettingHelper.showSettingDialog(
await SettingHelper.showSettingDialog( context: context, iconId: state.selectedIcon ?? '');
context: context,
iconId: state.selectedIcon ?? '');
if (result != null) { if (result != null) {
context context.read<RoutineBloc>().add(AddSelectedIcon(result));
.read<RoutineBloc>()
.add(AddSelectedIcon(result));
} }
} }
: null, : null,
@ -333,12 +314,10 @@ class _RoutineSearchAndButtonsState extends State<RoutineSearchAndButtons> {
child: Center( child: Center(
child: DefaultButton( child: DefaultButton(
onPressed: () async { onPressed: () async {
if (state.routineName == null || if (state.routineName == null || state.routineName!.isEmpty) {
state.routineName!.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar( SnackBar(
content: const Text( content: const Text('Please enter the routine name'),
'Please enter the routine name'),
duration: const Duration(seconds: 2), duration: const Duration(seconds: 2),
backgroundColor: ColorsManager.red, backgroundColor: ColorsManager.red,
action: SnackBarAction( action: SnackBarAction(
@ -352,12 +331,10 @@ class _RoutineSearchAndButtonsState extends State<RoutineSearchAndButtons> {
return; return;
} }
if (state.ifItems.isEmpty || if (state.ifItems.isEmpty || state.thenItems.isEmpty) {
state.thenItems.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar( SnackBar(
content: const Text( content: const Text('Please add if and then condition'),
'Please add if and then condition'),
duration: const Duration(seconds: 2), duration: const Duration(seconds: 2),
backgroundColor: ColorsManager.red, backgroundColor: ColorsManager.red,
action: SnackBarAction( action: SnackBarAction(
@ -370,17 +347,18 @@ class _RoutineSearchAndButtonsState extends State<RoutineSearchAndButtons> {
); );
return; return;
} }
final result = // final result =
await SaveRoutineHelper.showSaveRoutineDialog( // await
context); BlocProvider.of<RoutineBloc>(context).add(ResetErrorMessage());
if (result != null && result) { SaveRoutineHelper.showSaveRoutineDialog(context);
BlocProvider.of<SwitchTabsBloc>(context).add( // if (result != null && result) {
const CreateNewRoutineViewEvent(false), // BlocProvider.of<RoutineBloc>(context).add(
); // const CreateNewRoutineViewEvent(createRoutineView: false),
BlocProvider.of<SwitchTabsBloc>(context).add( // );
const TriggerSwitchTabsEvent(true), // BlocProvider.of<RoutineBloc>(context).add(
); // const TriggerSwitchTabsEvent(isRoutineTab: true),
} // );
// }
}, },
borderRadius: 15, borderRadius: 15,
elevation: 0, elevation: 0,

View File

@ -26,9 +26,7 @@ class ThenContainer extends StatelessWidget {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
const Text('THEN', const Text('THEN', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
style: TextStyle(
fontSize: 18, fontWeight: FontWeight.bold)),
const SizedBox(height: 16), const SizedBox(height: 16),
state.isLoading && state.isUpdate == true state.isLoading && state.isUpdate == true
? const Center( ? const Center(
@ -41,17 +39,12 @@ class ThenContainer extends StatelessWidget {
state.thenItems.length, state.thenItems.length,
(index) => GestureDetector( (index) => GestureDetector(
onTap: () async { onTap: () async {
if (state.thenItems[index] if (state.thenItems[index]['deviceId'] == 'delay') {
['deviceId'] == final result = await DelayHelper.showDelayPickerDialog(
'delay') { context, state.thenItems[index]);
final result = await DelayHelper
.showDelayPickerDialog(context,
state.thenItems[index]);
if (result != null) { if (result != null) {
context context.read<RoutineBloc>().add(AddToThenContainer({
.read<RoutineBloc>()
.add(AddToThenContainer({
...state.thenItems[index], ...state.thenItems[index],
'imagePath': Assets.delay, 'imagePath': Assets.delay,
'title': 'Delay', 'title': 'Delay',
@ -60,76 +53,58 @@ class ThenContainer extends StatelessWidget {
return; return;
} }
if (state.thenItems[index]['type'] == if (state.thenItems[index]['type'] == 'automation') {
'automation') {
final result = await showDialog<bool>( final result = await showDialog<bool>(
context: context, context: context,
builder: (BuildContext context) => builder: (BuildContext context) => AutomationDialog(
AutomationDialog(
automationName: automationName:
state.thenItems[index] state.thenItems[index]['name'] ?? 'Automation',
['name'] ??
'Automation',
automationId: automationId:
state.thenItems[index] state.thenItems[index]['deviceId'] ?? '',
['deviceId'] ?? uniqueCustomId: state.thenItems[index]
'', ['uniqueCustomId'],
uniqueCustomId:
state.thenItems[index]
['uniqueCustomId'],
), ),
); );
if (result != null) { if (result != null) {
context context.read<RoutineBloc>().add(AddToThenContainer({
.read<RoutineBloc>()
.add(AddToThenContainer({
...state.thenItems[index], ...state.thenItems[index],
'imagePath': 'imagePath': Assets.automation,
Assets.automation, 'title': state.thenItems[index]['name'] ??
'title': state state.thenItems[index]['title'],
.thenItems[index]['name'],
})); }));
} }
return; return;
} }
final result = await DeviceDialogHelper final result = await DeviceDialogHelper.showDeviceDialog(
.showDeviceDialog( context, state.thenItems[index],
context, state.thenItems[index], removeComparetors: true);
removeComparetors: true);
if (result != null) { if (result != null) {
context.read<RoutineBloc>().add( context
AddToThenContainer( .read<RoutineBloc>()
state.thenItems[index])); .add(AddToThenContainer(state.thenItems[index]));
} else if (!['AC', '1G', '2G', '3G'] } else if (!['AC', '1G', '2G', '3G']
.contains(state.thenItems[index] .contains(state.thenItems[index]['productType'])) {
['productType'])) { context
context.read<RoutineBloc>().add( .read<RoutineBloc>()
AddToThenContainer( .add(AddToThenContainer(state.thenItems[index]));
state.thenItems[index]));
} }
}, },
child: DraggableCard( child: DraggableCard(
imagePath: state.thenItems[index] imagePath: state.thenItems[index]['imagePath'] ?? '',
['imagePath'] ?? title: state.thenItems[index]['title'] ?? '',
'',
title: state.thenItems[index]
['title'] ??
'',
deviceData: state.thenItems[index], deviceData: state.thenItems[index],
padding: const EdgeInsets.symmetric( padding:
horizontal: 4, vertical: 8), const EdgeInsets.symmetric(horizontal: 4, vertical: 8),
isFromThen: true, isFromThen: true,
isFromIf: false, isFromIf: false,
onRemove: () { onRemove: () {
context.read<RoutineBloc>().add( context.read<RoutineBloc>().add(RemoveDragCard(
RemoveDragCard( index: index,
index: index, isFromThen: true,
isFromThen: true, key: state.thenItems[index]['uniqueCustomId']));
key: state.thenItems[index]
['uniqueCustomId']));
}, },
), ),
))), ))),
@ -148,7 +123,18 @@ class ThenContainer extends StatelessWidget {
return; return;
} }
if (state.automationId == mutableData['deviceId'] ||
state.sceneId == mutableData['deviceId']) {
return;
}
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(
@ -169,9 +155,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'],
})); }));
@ -183,8 +174,7 @@ class ThenContainer extends StatelessWidget {
} }
if (mutableData['deviceId'] == 'delay') { if (mutableData['deviceId'] == 'delay') {
final result = final result = await DelayHelper.showDelayPickerDialog(context, mutableData);
await DelayHelper.showDelayPickerDialog(context, mutableData);
if (result != null) { if (result != null) {
context.read<RoutineBloc>().add(AddToThenContainer({ context.read<RoutineBloc>().add(AddToThenContainer({
@ -196,13 +186,11 @@ class ThenContainer extends StatelessWidget {
return; return;
} }
final result = await DeviceDialogHelper.showDeviceDialog( final result = await DeviceDialogHelper.showDeviceDialog(context, mutableData,
context, mutableData,
removeComparetors: true); removeComparetors: true);
if (result != null) { if (result != null) {
context.read<RoutineBloc>().add(AddToThenContainer(mutableData)); context.read<RoutineBloc>().add(AddToThenContainer(mutableData));
} else if (!['AC', '1G', '2G', '3G'] } else if (!['AC', '1G', '2G', '3G'].contains(mutableData['productType'])) {
.contains(mutableData['productType'])) {
context.read<RoutineBloc>().add(AddToThenContainer(mutableData)); context.read<RoutineBloc>().add(AddToThenContainer(mutableData));
} }
}, },

View File

@ -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';

View File

@ -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();

View File

@ -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();

View File

@ -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;

View File

@ -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;

View File

@ -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';

View File

@ -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';

View File

@ -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';

View File

@ -1,9 +1,9 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/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> {
), ),
); );
} }
} }

View File

@ -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,
), ),

View File

@ -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,

View File

@ -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 {

View File

@ -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';

View File

@ -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;

View File

@ -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';

View File

@ -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,
));
});
}
}

View File

@ -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];
}

View File

@ -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];
}

View File

@ -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'),
),
),
],
),
],
);
},
),
),
),
],
),
),
);
}
}

View File

@ -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'),
),
),
],
),
],
),
),
],
),
);
}
}

View File

@ -22,16 +22,16 @@ class AuthenticationAPI {
}) async { }) async {
final response = await HTTPService().post( final response = await HTTPService().post(
path: ApiEndpoints.forgetPassword, path: ApiEndpoints.forgetPassword,
body: {"email": email, "password": password,"otpCode": otpCode}, body: {"email": email, "password": password, "otpCode": otpCode},
showServerMessage: true, showServerMessage: true,
expectedResponseModel: (json) {}); expectedResponseModel: (json) {});
return response; return response;
} }
static Future<int?> sendOtp({required String email, required String regionUuid}) async { static Future<int?> sendOtp({required String email}) async {
final response = await HTTPService().post( final response = await HTTPService().post(
path: ApiEndpoints.sendOtp, path: ApiEndpoints.sendOtp,
body: {"email": email, "type": "PASSWORD", "regionUuid": regionUuid}, body: {"email": email, "type": "PASSWORD"},
showServerMessage: true, showServerMessage: true,
expectedResponseModel: (json) { expectedResponseModel: (json) {
return json['data']['cooldown']; return json['data']['cooldown'];

View File

@ -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';

View File

@ -6,6 +6,7 @@ import 'package:syncrow_web/pages/routiens/models/routine_details_model.dart';
import 'package:syncrow_web/pages/routiens/models/routine_model.dart'; import 'package:syncrow_web/pages/routiens/models/routine_model.dart';
import 'package:syncrow_web/services/api/http_service.dart'; import 'package:syncrow_web/services/api/http_service.dart';
import 'package:syncrow_web/utils/constants/api_const.dart'; import 'package:syncrow_web/utils/constants/api_const.dart';
import 'package:syncrow_web/utils/constants/temp_const.dart';
class SceneApi { class SceneApi {
static final HTTPService _httpService = HTTPService(); static final HTTPService _httpService = HTTPService();
@ -76,7 +77,8 @@ class SceneApi {
final response = await _httpService.get( final response = await _httpService.get(
path: ApiEndpoints.getUnitScenes path: ApiEndpoints.getUnitScenes
.replaceAll('{spaceUuid}', unitId) .replaceAll('{spaceUuid}', unitId)
.replaceAll('{communityUuid}', communityId), .replaceAll('{communityUuid}', communityId)
.replaceAll('{projectId}', TempConst.projectId),
queryParameters: {'showInHomePage': showInDevice}, queryParameters: {'showInHomePage': showInDevice},
showServerMessage: false, showServerMessage: false,
expectedResponseModel: (json) { expectedResponseModel: (json) {

View File

@ -1,10 +1,11 @@
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';
import 'package:syncrow_web/utils/constants/temp_const.dart';
class CommunitySpaceManagementApi { class CommunitySpaceManagementApi {
// Community Management APIs // Community Management APIs
@ -15,7 +16,8 @@ class CommunitySpaceManagementApi {
while (hasNext) { while (hasNext) {
await HTTPService().get( await HTTPService().get(
path: ApiEndpoints.getCommunityList, path: ApiEndpoints.getCommunityList
.replaceAll('{projectId}', TempConst.projectId),
queryParameters: {'page': page}, queryParameters: {'page': page},
expectedResponseModel: (json) { expectedResponseModel: (json) {
List<dynamic> jsonData = json['data']; List<dynamic> jsonData = json['data'];
@ -59,7 +61,8 @@ class CommunitySpaceManagementApi {
String name, String description) async { String name, String description) async {
try { try {
final response = await HTTPService().post( final response = await HTTPService().post(
path: ApiEndpoints.createCommunity, path: ApiEndpoints.createCommunity
.replaceAll('{projectId}', TempConst.projectId),
body: { body: {
'name': name, 'name': name,
'description': description, 'description': description,
@ -79,7 +82,8 @@ class CommunitySpaceManagementApi {
try { try {
final response = await HTTPService().put( final response = await HTTPService().put(
path: ApiEndpoints.updateCommunity path: ApiEndpoints.updateCommunity
.replaceAll('{communityId}', communityId), .replaceAll('{communityId}', communityId)
.replaceAll('{projectId}', TempConst.projectId),
body: { body: {
'name': name, 'name': name,
}, },
@ -98,7 +102,8 @@ class CommunitySpaceManagementApi {
try { try {
final response = await HTTPService().delete( final response = await HTTPService().delete(
path: ApiEndpoints.deleteCommunity path: ApiEndpoints.deleteCommunity
.replaceAll('{communityId}', communityId), .replaceAll('{communityId}', communityId)
.replaceAll('{projectId}', TempConst.projectId),
expectedResponseModel: (json) { expectedResponseModel: (json) {
return json['success'] ?? false; return json['success'] ?? false;
}, },
@ -113,7 +118,9 @@ class CommunitySpaceManagementApi {
Future<SpacesResponse> fetchSpaces(String communityId) async { Future<SpacesResponse> fetchSpaces(String communityId) async {
try { try {
final response = await HTTPService().get( final response = await HTTPService().get(
path: ApiEndpoints.listSpaces.replaceAll('{communityId}', communityId), path: ApiEndpoints.listSpaces
.replaceAll('{communityId}', communityId)
.replaceAll('{projectId}', TempConst.projectId),
expectedResponseModel: (json) { expectedResponseModel: (json) {
return SpacesResponse.fromJson(json); return SpacesResponse.fromJson(json);
}, },
@ -139,7 +146,8 @@ class CommunitySpaceManagementApi {
final response = await HTTPService().get( final response = await HTTPService().get(
path: ApiEndpoints.getSpace path: ApiEndpoints.getSpace
.replaceAll('{communityId}', communityId) .replaceAll('{communityId}', communityId)
.replaceAll('{spaceId}', spaceId), .replaceAll('{spaceId}', spaceId)
.replaceAll('{projectId}', TempConst.projectId),
expectedResponseModel: (json) { expectedResponseModel: (json) {
return SpaceModel.fromJson(json); return SpaceModel.fromJson(json);
}, },
@ -175,7 +183,9 @@ class CommunitySpaceManagementApi {
body['parentUuid'] = parentId; body['parentUuid'] = parentId;
} }
final response = await HTTPService().post( final response = await HTTPService().post(
path: ApiEndpoints.createSpace.replaceAll('{communityId}', communityId), path: ApiEndpoints.createSpace
.replaceAll('{communityId}', communityId)
.replaceAll('{projectId}', TempConst.projectId),
body: body, body: body,
expectedResponseModel: (json) { expectedResponseModel: (json) {
return SpaceModel.fromJson(json['data']); return SpaceModel.fromJson(json['data']);
@ -216,7 +226,8 @@ class CommunitySpaceManagementApi {
final response = await HTTPService().put( final response = await HTTPService().put(
path: ApiEndpoints.updateSpace path: ApiEndpoints.updateSpace
.replaceAll('{communityId}', communityId) .replaceAll('{communityId}', communityId)
.replaceAll('{spaceId}', spaceId), .replaceAll('{spaceId}', spaceId)
.replaceAll('{projectId}', TempConst.projectId),
body: body, body: body,
expectedResponseModel: (json) { expectedResponseModel: (json) {
return SpaceModel.fromJson(json['data']); return SpaceModel.fromJson(json['data']);
@ -234,7 +245,8 @@ class CommunitySpaceManagementApi {
final response = await HTTPService().delete( final response = await HTTPService().delete(
path: ApiEndpoints.deleteSpace path: ApiEndpoints.deleteSpace
.replaceAll('{communityId}', communityId) .replaceAll('{communityId}', communityId)
.replaceAll('{spaceId}', spaceId), .replaceAll('{spaceId}', spaceId)
.replaceAll('{projectId}', TempConst.projectId),
expectedResponseModel: (json) { expectedResponseModel: (json) {
return json['success'] ?? false; return json['success'] ?? false;
}, },
@ -250,7 +262,8 @@ class CommunitySpaceManagementApi {
try { try {
final response = await HTTPService().get( final response = await HTTPService().get(
path: ApiEndpoints.getSpaceHierarchy path: ApiEndpoints.getSpaceHierarchy
.replaceAll('{communityId}', communityId), .replaceAll('{communityId}', communityId)
.replaceAll('{projectId}', TempConst.projectId),
expectedResponseModel: (json) { expectedResponseModel: (json) {
final spaceModels = (json['data'] as List) final spaceModels = (json['data'] as List)
.map((spaceJson) => SpaceModel.fromJson(spaceJson)) .map((spaceJson) => SpaceModel.fromJson(spaceJson))

View File

@ -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()),
]; ];
} }
} }

View File

@ -36,21 +36,21 @@ abstract class ApiEndpoints {
static const String getDeviceLogs = '/device/report-logs/{uuid}?code={code}'; static const String getDeviceLogs = '/device/report-logs/{uuid}?code={code}';
// Space Module // Space Module
static const String createSpace = '/communities/{communityId}/spaces'; static const String createSpace = '/projects/{projectId}/communities/{communityId}/spaces';
static const String listSpaces = '/communities/{communityId}/spaces'; static const String listSpaces = '/projects/{projectId}/communities/{communityId}/spaces';
static const String deleteSpace = '/communities/{communityId}/spaces/{spaceId}'; static const String deleteSpace = '/projects/{projectId}/communities/{communityId}/spaces/{spaceId}';
static const String updateSpace = '/communities/{communityId}/spaces/{spaceId}'; static const String updateSpace = '/projects/{projectId}/communities/{communityId}/spaces/{spaceId}';
static const String getSpace = '/communities/{communityId}/spaces/{spaceId}'; static const String getSpace = '/projects/{projectId}/communities/{communityId}/spaces/{spaceId}';
static const String getSpaceHierarchy = '/communities/{communityId}/spaces'; static const String getSpaceHierarchy = '/projects/{projectId}/communities/{communityId}/spaces';
// Community Module // Community Module
static const String createCommunity = '/communities'; static const String createCommunity = '/projects/{projectId}/communities';
static const String getCommunityList = '/communities'; static const String getCommunityList = '/projects/{projectId}/communities';
static const String getCommunityById = '/communities/{communityId}'; static const String getCommunityById = '/projects/{projectId}/communities/{communityId}';
static const String updateCommunity = '/communities/{communityId}'; static const String updateCommunity = '/projects/{projectId}/communities/{communityId}';
static const String deleteCommunity = '/communities/{communityId}'; static const String deleteCommunity = '/projects/{projectId}communities/{communityId}';
static const String getUserCommunities = '/communities/user/{userUuid}'; static const String getUserCommunities = '/projects/{projectId}/communities/user/{userUuid}';
static const String createUserCommunity = '/communities/user'; static const String createUserCommunity = '/projects/{projectId}/communities/user';
static const String getDeviceLogsByDate = static const String getDeviceLogsByDate =
'/device/report-logs/{uuid}?code={code}&startTime={startTime}&endTime={endTime}'; '/device/report-logs/{uuid}?code={code}&startTime={startTime}&endTime={endTime}';
@ -68,7 +68,7 @@ abstract class ApiEndpoints {
static const String getIconScene = '/scene/icon'; static const String getIconScene = '/scene/icon';
static const String createScene = '/scene/tap-to-run'; static const String createScene = '/scene/tap-to-run';
static const String createAutomation = '/automation'; static const String createAutomation = '/automation';
static const String getUnitScenes = '/communities/{communityUuid}/spaces/{spaceUuid}/scenes'; static const String getUnitScenes = '/projects/{projectId}/communities/{communityUuid}/spaces/{spaceUuid}/scenes';
static const String getAutomationDetails = '/automation/details/{automationId}'; static const String getAutomationDetails = '/automation/details/{automationId}';
static const String getScene = '/scene/tap-to-run/{sceneId}'; static const String getScene = '/scene/tap-to-run/{sceneId}';
static const String deleteScene = '/scene/tap-to-run/{sceneId}'; static const String deleteScene = '/scene/tap-to-run/{sceneId}';

View File

@ -0,0 +1,3 @@
class TempConst {
static const projectId = '0e62577c-06fa-41b9-8a92-99a21fbaf51c';
}

View File

@ -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),
) )
]), ]),
); );

View File

@ -75,26 +75,26 @@ class _UserDropdownMenuState extends State<UserDropdownMenu> {
), ),
), ),
items: <PopupMenuEntry>[ items: <PopupMenuEntry>[
PopupMenuItem( // PopupMenuItem(
onTap: () {}, // onTap: () {},
child: ListTile( // child: ListTile(
leading: SvgPicture.asset(Assets.accountSetting), // leading: SvgPicture.asset(Assets.accountSetting),
title: Text( // title: Text(
"Account Settings", // "Account Settings",
style: context.textTheme.bodyMedium, // style: context.textTheme.bodyMedium,
), // ),
), // ),
), // ),
PopupMenuItem( // PopupMenuItem(
onTap: () {}, // onTap: () {},
child: ListTile( // child: ListTile(
leading: SvgPicture.asset(Assets.settings), // leading: SvgPicture.asset(Assets.settings),
title: Text( // title: Text(
"Settings", // "Settings",
style: context.textTheme.bodyMedium, // style: context.textTheme.bodyMedium,
), // ),
), // ),
), // ),
PopupMenuItem( PopupMenuItem(
onTap: () { onTap: () {
showDialog( showDialog(
@ -211,8 +211,10 @@ class _UserDropdownMenuState extends State<UserDropdownMenu> {
elevation: 1, elevation: 1,
child: Text( child: Text(
'Logout', 'Logout',
style: style: Theme.of(context)
Theme.of(context).textTheme.bodyMedium!.copyWith(fontSize: 12, color: Colors.white), .textTheme
.bodyMedium!
.copyWith(fontSize: 12, color: Colors.white),
), ),
), ),
), ),