Merge branch 'dev' into Roles_&_Permissions

This commit is contained in:
mohammad
2025-01-06 15:32:38 +03:00
77 changed files with 1012 additions and 934 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;
@ -165,7 +159,7 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
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

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

@ -91,40 +91,40 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
}, },
color: ColorsManager.primaryColor, color: ColorsManager.primaryColor,
), ),
HomeItemModel( // HomeItemModel(
title: 'Move in', // title: 'Move in',
icon: Assets.moveinIcon, // icon: Assets.moveinIcon,
active: true, // 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,

View File

@ -758,6 +758,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
thenItems: [], thenItems: [],
selectedFunctions: {}, selectedFunctions: {},
scenes: [], scenes: [],
sceneId: '',
automationId: '',
automations: [], automations: [],
isLoading: false, isLoading: false,
errorMessage: '', errorMessage: '',
@ -1050,7 +1052,9 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
final automationDetails = await SceneApi.getAutomationDetails(event.automationId); final automationDetails = await SceneApi.getAutomationDetails(event.automationId);
final Map<String, Map<String, dynamic>> deviceCards = {}; final Map<String, Map<String, dynamic>> deviceIfCards = {};
final Map<String, Map<String, dynamic>> deviceThenCards = {};
final Map<String, List<DeviceFunctionData>> updatedFunctions = final Map<String, List<DeviceFunctionData>> updatedFunctions =
Map<String, List<DeviceFunctionData>>.from(state.selectedFunctions); Map<String, List<DeviceFunctionData>>.from(state.selectedFunctions);
@ -1066,8 +1070,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
final deviceId = condition.entityId; final deviceId = condition.entityId;
if (!deviceCards.containsKey(deviceId)) { if (!deviceIfCards.containsKey(deviceId)) {
deviceCards[deviceId] = { deviceIfCards[deviceId] = {
'entityId': condition.entityId, 'entityId': condition.entityId,
'deviceId': condition.entityId, 'deviceId': condition.entityId,
'uniqueCustomId': const Uuid().v4(), 'uniqueCustomId': const Uuid().v4(),
@ -1080,7 +1084,7 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
}; };
} }
final cardData = deviceCards[deviceId]!; final cardData = deviceIfCards[deviceId]!;
final uniqueCustomId = cardData['uniqueCustomId'].toString(); final uniqueCustomId = cardData['uniqueCustomId'].toString();
if (!updatedFunctions.containsKey(uniqueCustomId)) { if (!updatedFunctions.containsKey(uniqueCustomId)) {
@ -1117,8 +1121,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
final deviceId = final deviceId =
action.actionExecutor == 'delay' ? '${action.entityId}_delay' : action.entityId; action.actionExecutor == 'delay' ? '${action.entityId}_delay' : action.entityId;
if (!deviceCards.containsKey(deviceId)) { if (!deviceThenCards.containsKey(deviceId)) {
deviceCards[deviceId] = { deviceThenCards[deviceId] = {
'entityId': action.entityId, 'entityId': action.entityId,
'deviceId': action.actionExecutor == 'delay' ? 'delay' : action.entityId, 'deviceId': action.actionExecutor == 'delay' ? 'delay' : action.entityId,
'uniqueCustomId': const Uuid().v4(), 'uniqueCustomId': const Uuid().v4(),
@ -1140,10 +1144,11 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
: action.type == 'automation' : action.type == 'automation'
? 'automation' ? 'automation'
: 'action', : 'action',
'icon': action.icon ?? ''
}; };
} }
final cardData = deviceCards[deviceId]!; final cardData = deviceThenCards[deviceId]!;
final uniqueCustomId = cardData['uniqueCustomId'].toString(); final uniqueCustomId = cardData['uniqueCustomId'].toString();
if (!updatedFunctions.containsKey(uniqueCustomId)) { if (!updatedFunctions.containsKey(uniqueCustomId)) {
@ -1192,8 +1197,8 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
} }
} }
final ifItems = deviceCards.values.where((card) => card['type'] == 'condition').toList(); final ifItems = deviceIfCards.values.where((card) => card['type'] == 'condition').toList();
final thenItems = deviceCards.values final thenItems = deviceThenCards.values
.where((card) => .where((card) =>
card['type'] == 'action' || card['type'] == 'automation' || card['type'] == 'scene') card['type'] == 'action' || card['type'] == 'automation' || card['type'] == 'scene')
.toList(); .toList();

View File

@ -101,7 +101,7 @@ class SaveRoutineHelper {
final functions = final functions =
state.selectedFunctions[item['uniqueCustomId']] ?? []; state.selectedFunctions[item['uniqueCustomId']] ?? [];
return ListTile( return ListTile(
leading: item['type'] == 'tap_to_run' leading: item['type'] == 'tap_to_run' || item['type'] == 'scene'
? Image.memory( ? Image.memory(
base64Decode(item['icon']), base64Decode(item['icon']),
width: 22, width: 22,

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,8 +137,7 @@ 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(),
}; };
} }
@ -155,7 +151,7 @@ class RoutineAction {
executorProperty: map['executorProperty'] != null executorProperty: map['executorProperty'] != null
? RoutineExecutorProperty.fromMap(map['executorProperty']) ? RoutineExecutorProperty.fromMap(map['executorProperty'])
: null, : null,
); icon: map['icon']);
} }
} }

View File

@ -32,18 +32,17 @@ 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( int index = state.thenItems
(item) => item['uniqueCustomId'] == deviceData['uniqueCustomId']); .indexWhere((item) => item['uniqueCustomId'] == deviceData['uniqueCustomId']);
if (index != -1) { if (index != -1) {
return _buildCardContent(context, deviceFunctions, padding: padding); return _buildCardContent(context, deviceFunctions, padding: padding);
} }
int ifIndex = state.ifItems.indexWhere( int ifIndex = state.ifItems
(item) => item['uniqueCustomId'] == deviceData['uniqueCustomId']); .indexWhere((item) => item['uniqueCustomId'] == deviceData['uniqueCustomId']);
if (ifIndex != -1) { if (ifIndex != -1) {
return _buildCardContent(context, deviceFunctions, padding: padding); return _buildCardContent(context, deviceFunctions, padding: padding);
@ -53,8 +52,7 @@ class DraggableCard extends StatelessWidget {
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),
@ -63,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: [
@ -93,7 +90,7 @@ class DraggableCard extends StatelessWidget {
), ),
), ),
padding: const EdgeInsets.all(8), padding: const EdgeInsets.all(8),
child: deviceData['type'] == 'tap_to_run' child: deviceData['type'] == 'tap_to_run' || deviceData['type'] == 'scene'
? Image.memory( ? Image.memory(
base64Decode(deviceData['icon']), base64Decode(deviceData['icon']),
) )
@ -162,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

@ -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,79 +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:
state.thenItems[index]
['uniqueCustomId'], ['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.thenItems[index]['title'],
state.thenItems[index]
['name'] ??
state.thenItems[index]
['title'],
})); }));
} }
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] key: state.thenItems[index]['uniqueCustomId']));
['uniqueCustomId']));
}, },
), ),
))), ))),
@ -151,9 +123,14 @@ 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( int index =
(item) => item['deviceId'] == mutableData['deviceId']); state.thenItems.indexWhere((item) => item['deviceId'] == mutableData['deviceId']);
if (index != -1) { if (index != -1) {
return; return;
} }
@ -178,8 +155,8 @@ 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( int index =
(item) => item['deviceId'] == mutableData['deviceId']); state.thenItems.indexWhere((item) => item['deviceId'] == mutableData['deviceId']);
if (index != -1) { if (index != -1) {
return; return;
} }
@ -197,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({
@ -210,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';
@ -309,8 +309,6 @@ class SpaceManagementBloc
await _api.deleteSpace(communityUuid, parent.uuid!); await _api.deleteSpace(communityUuid, parent.uuid!);
} }
} catch (e) { } catch (e) {
print(
'Error deleting space ${parent.name} (UUID: ${parent.uuid}, Community UUID: $communityUuid): $e');
rethrow; // Decide whether to stop execution or continue rethrow; // Decide whether to stop execution or continue
} }
} }
@ -342,7 +340,6 @@ class SpaceManagementBloc
space.uuid = response?.uuid; space.uuid = response?.uuid;
} }
} catch (e) { } catch (e) {
print('Error creating space ${space.name}: $e');
rethrow; // Stop further execution on failure rethrow; // Stop further execution on failure
} }
} }

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,9 +15,11 @@ 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,
@ -24,8 +28,15 @@ class CommunityStructureHeader extends StatelessWidget {
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';
@ -133,13 +133,7 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
isNameFieldInvalid = value.isEmpty; isNameFieldInvalid = value.isEmpty;
if (!isNameFieldInvalid) { if (!isNameFieldInvalid) {
if ((widget.parentSpace?.children.any( if (_isNameConflict(value)) {
(child) => child.name == value) ??
false) ||
(widget.parentSpace?.name == value) ||
(widget.editSpace?.children.any(
(child) => child.name == value) ??
false)) {
isNameFieldExist = true; isNameFieldExist = true;
isOkButtonEnabled = false; isOkButtonEnabled = false;
} else { } else {
@ -387,7 +381,14 @@ class CreateSpaceDialogState extends State<CreateSpaceDialog> {
); );
} }
bool _isNameConflict(String value) {
return (widget.parentSpace?.children.any((child) => child.name == value) ??
false) ||
(widget.parentSpace?.name == value) ||
(widget.editSpace?.parent?.name == value) ||
(widget.editSpace?.children.any((child) => child.name == value) ??
false);
}
String _mapIconToProduct(String uuid, List<ProductModel> products) { String _mapIconToProduct(String uuid, List<ProductModel> products) {
// Find the product with the matching UUID // Find the product with the matching UUID

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) {
print(json); print(json);
final spaceModels = (json['data'] as List) final spaceModels = (json['data'] as List)

View File

@ -4,7 +4,7 @@ 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/roles_and_permission/view/roles_and_permission_page.dart'; import 'package:syncrow_web/pages/roles_and_permission/view/roles_and_permission_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';

View File

@ -40,31 +40,31 @@ abstract class ApiEndpoints {
// Space Module // Space Module
static const String createSpace = static const String createSpace =
'/projects/${projectUuid}/communities/{communityId}/spaces'; '/projects/{projectId}/communities/{communityId}/spaces';
static const String listSpaces = static const String listSpaces =
'/projects/${projectUuid}/communities/{communityId}/spaces'; '/projects/{projectId}/communities/{communityId}/spaces';
static const String deleteSpace = static const String deleteSpace =
'/projects/${projectUuid}/communities/{communityId}/spaces/{spaceId}'; '/projects/{projectId}/communities/{communityId}/spaces/{spaceId}';
static const String updateSpace = static const String updateSpace =
'/projects/${projectUuid}/communities/{communityId}/spaces/{spaceId}'; '/projects/{projectId}/communities/{communityId}/spaces/{spaceId}';
static const String getSpace = static const String getSpace =
'/projects/${projectUuid}/communities/{communityId}/spaces/{spaceId}'; '/projects/{projectId}/communities/{communityId}/spaces/{spaceId}';
static const String getSpaceHierarchy = static const String getSpaceHierarchy =
'/projects/${projectUuid}/communities/{communityId}/spaces'; '/projects/{projectId}/communities/{communityId}/spaces';
// Community Module // Community Module
static const String createCommunity = '/projects/${projectUuid}/communities'; static const String createCommunity = '/projects/{projectId}/communities';
static const String getCommunityList = '/projects/${projectUuid}/communities'; static const String getCommunityList = '/projects/{projectId}/communities';
static const String getCommunityById = static const String getCommunityById =
'/projects/${projectUuid}/communities/{communityId}'; '/projects/{projectId}/communities/{communityId}';
static const String updateCommunity = static const String updateCommunity =
'/projects/${projectUuid}/communities/{communityId}'; '/projects/{projectId}/communities/{communityId}';
static const String deleteCommunity = static const String deleteCommunity =
'/projects/${projectUuid}/communities/{communityId}'; '/projects/{projectId}communities/{communityId}';
static const String getUserCommunities = static const String getUserCommunities =
'/projects/${projectUuid}/communities/user/{userUuid}'; '/projects/{projectId}/communities/user/{userUuid}';
static const String createUserCommunity = static const String createUserCommunity =
'/projects/${projectUuid}/communities/user'; '/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}';
@ -87,7 +87,7 @@ abstract class ApiEndpoints {
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 = static const String getUnitScenes =
'/communities/{communityUuid}/spaces/{spaceUuid}/scenes'; '/projects/{projectId}/communities/{communityUuid}/spaces/{spaceUuid}/scenes';
static const String getAutomationDetails = static const String getAutomationDetails =
'/automation/details/{automationId}'; '/automation/details/{automationId}';
static const String getScene = '/scene/tap-to-run/{sceneId}'; static const String getScene = '/scene/tap-to-run/{sceneId}';
@ -106,7 +106,8 @@ abstract class ApiEndpoints {
static const String getUserById = '/projects/${projectUuid}/user/{userUuid}'; static const String getUserById = '/projects/${projectUuid}/user/{userUuid}';
static const String editUser = '/invite-user/{inviteUserUuid}'; static const String editUser = '/invite-user/{inviteUserUuid}';
static const String deleteUser = '/invite-user/{inviteUserUuid}'; static const String deleteUser = '/invite-user/{inviteUserUuid}';
static const String changeUserStatus = '/invite-user/{invitedUserUuid}/disable'; static const String changeUserStatus =
'/invite-user/{invitedUserUuid}/disable';
// static const String updateAutomation = '/automation/{automationId}'; // static const String updateAutomation = '/automation/{automationId}';
} }

View File

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

View File

@ -76,16 +76,16 @@ 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: () {
context.go(RoutesConst.rolesAndPermissions); context.go(RoutesConst.rolesAndPermissions);
@ -103,7 +103,6 @@ class _UserDropdownMenuState extends State<UserDropdownMenu> {
showDialog( showDialog(
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
final size = MediaQuery.of(context).size;
return AlertDialog( return AlertDialog(
alignment: Alignment.center, alignment: Alignment.center,
content: SizedBox( content: SizedBox(