mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-09 22:57:21 +00:00
push fetch devices and connecting the filters
This commit is contained in:
@ -0,0 +1 @@
|
|||||||
|
|
||||||
|
@ -22,33 +22,36 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
|||||||
|
|
||||||
int? effectiveTimeTimeStamp;
|
int? effectiveTimeTimeStamp;
|
||||||
int? expirationTimeTimeStamp;
|
int? expirationTimeTimeStamp;
|
||||||
TextEditingController passwordName= TextEditingController();
|
TextEditingController passwordName = TextEditingController();
|
||||||
List<PasswordModel> filteredData = [];
|
List<PasswordModel> filteredData = [];
|
||||||
List<PasswordModel> data=[];
|
List<PasswordModel> data = [];
|
||||||
|
|
||||||
Future<void> _onFetchTableData(
|
Future<void> _onFetchTableData(
|
||||||
FetchTableData event, Emitter<AccessState> emit) async {
|
FetchTableData event, Emitter<AccessState> emit) async {
|
||||||
try {
|
try {
|
||||||
emit(AccessLoaded());
|
emit(AccessLoaded());
|
||||||
data = await AccessMangApi().fetchVisitorPassword();
|
data = await AccessMangApi().fetchVisitorPassword();
|
||||||
filteredData= data;
|
filteredData = data;
|
||||||
updateTabsCount();
|
updateTabsCount();
|
||||||
emit(TableLoaded(data));
|
emit(TableLoaded(data));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(FailedState(e.toString()));
|
emit(FailedState(e.toString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateTabsCount() {
|
void updateTabsCount() {
|
||||||
int toBeEffectiveCount = data.where((item) => item.passwordStatus.value== 'To Be Effective').length;
|
int toBeEffectiveCount = data
|
||||||
int effectiveCount = data.where((item) => item.passwordStatus.value == 'Effective').length;
|
.where((item) => item.passwordStatus.value == 'To Be Effective')
|
||||||
int expiredCount = data.where((item) => item.passwordStatus.value == 'Expired').length;
|
.length;
|
||||||
|
int effectiveCount =
|
||||||
|
data.where((item) => item.passwordStatus.value == 'Effective').length;
|
||||||
|
int expiredCount =
|
||||||
|
data.where((item) => item.passwordStatus.value == 'Expired').length;
|
||||||
tabs[1] = 'To Be Effective ($toBeEffectiveCount)';
|
tabs[1] = 'To Be Effective ($toBeEffectiveCount)';
|
||||||
tabs[2] = 'Effective ($effectiveCount)';
|
tabs[2] = 'Effective ($effectiveCount)';
|
||||||
tabs[3] = 'Expired ($expiredCount)';
|
tabs[3] = 'Expired ($expiredCount)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int selectedIndex = 0;
|
int selectedIndex = 0;
|
||||||
final List<String> tabs = [
|
final List<String> tabs = [
|
||||||
'All',
|
'All',
|
||||||
@ -57,20 +60,19 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
|||||||
'Expired'
|
'Expired'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
Future selectFilterTap(
|
||||||
Future selectFilterTap(TabChangedEvent event, Emitter<AccessState> emit) async {
|
TabChangedEvent event, Emitter<AccessState> emit) async {
|
||||||
try {
|
try {
|
||||||
emit(AccessLoaded());
|
emit(AccessLoaded());
|
||||||
selectedIndex= event.selectedIndex;
|
selectedIndex = event.selectedIndex;
|
||||||
emit(AccessInitial());
|
emit(AccessInitial());
|
||||||
emit(TableLoaded(data));
|
emit(TableLoaded(data));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(FailedState( e.toString()));
|
emit(FailedState(e.toString()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Future<void> selectTime(SelectTime event, Emitter<AccessState> emit) async {
|
Future<void> selectTime(SelectTime event, Emitter<AccessState> emit) async {
|
||||||
emit(AccessLoaded());
|
emit(AccessLoaded());
|
||||||
|
|
||||||
@ -84,7 +86,6 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
|||||||
final TimeOfDay? timePicked = await showTimePicker(
|
final TimeOfDay? timePicked = await showTimePicker(
|
||||||
context: event.context,
|
context: event.context,
|
||||||
initialTime: TimeOfDay.now(),
|
initialTime: TimeOfDay.now(),
|
||||||
|
|
||||||
builder: (context, child) {
|
builder: (context, child) {
|
||||||
return Theme(
|
return Theme(
|
||||||
data: ThemeData.light().copyWith(
|
data: ThemeData.light().copyWith(
|
||||||
@ -111,24 +112,35 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
|||||||
timePicked.minute,
|
timePicked.minute,
|
||||||
);
|
);
|
||||||
final selectedTimestamp = DateTime(
|
final selectedTimestamp = DateTime(
|
||||||
selectedDateTime.year,
|
selectedDateTime.year,
|
||||||
selectedDateTime.month,
|
selectedDateTime.month,
|
||||||
selectedDateTime.day,
|
selectedDateTime.day,
|
||||||
selectedDateTime.hour,
|
selectedDateTime.hour,
|
||||||
selectedDateTime.minute,
|
selectedDateTime.minute,
|
||||||
).millisecondsSinceEpoch ~/ 1000; // Divide by 1000 to remove milliseconds
|
).millisecondsSinceEpoch ~/
|
||||||
|
1000; // Divide by 1000 to remove milliseconds
|
||||||
if (event.isStart) {
|
if (event.isStart) {
|
||||||
if (expirationTimeTimeStamp != null && selectedTimestamp > expirationTimeTimeStamp!) {
|
if (expirationTimeTimeStamp != null &&
|
||||||
CustomSnackBar.displaySnackBar('Effective Time cannot be later than Expiration Time.');
|
selectedTimestamp > expirationTimeTimeStamp!) {
|
||||||
|
CustomSnackBar.displaySnackBar(
|
||||||
|
'Effective Time cannot be later than Expiration Time.');
|
||||||
} else {
|
} else {
|
||||||
startTime = selectedDateTime.toString().split('.').first; // Remove seconds and milliseconds
|
startTime = selectedDateTime
|
||||||
|
.toString()
|
||||||
|
.split('.')
|
||||||
|
.first; // Remove seconds and milliseconds
|
||||||
effectiveTimeTimeStamp = selectedTimestamp;
|
effectiveTimeTimeStamp = selectedTimestamp;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (effectiveTimeTimeStamp != null && selectedTimestamp < effectiveTimeTimeStamp!) {
|
if (effectiveTimeTimeStamp != null &&
|
||||||
CustomSnackBar.displaySnackBar('Expiration Time cannot be earlier than Effective Time.');
|
selectedTimestamp < effectiveTimeTimeStamp!) {
|
||||||
|
CustomSnackBar.displaySnackBar(
|
||||||
|
'Expiration Time cannot be earlier than Effective Time.');
|
||||||
} else {
|
} else {
|
||||||
endTime = selectedDateTime.toString().split('.').first; // Remove seconds and milliseconds
|
endTime = selectedDateTime
|
||||||
|
.toString()
|
||||||
|
.split('.')
|
||||||
|
.first; // Remove seconds and milliseconds
|
||||||
expirationTimeTimeStamp = selectedTimestamp;
|
expirationTimeTimeStamp = selectedTimestamp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -137,8 +149,8 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
|||||||
emit(ChangeTimeState());
|
emit(ChangeTimeState());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _filterData(
|
||||||
Future<void> _filterData(FilterDataEvent event, Emitter<AccessState> emit) async {
|
FilterDataEvent event, Emitter<AccessState> emit) async {
|
||||||
emit(AccessLoaded());
|
emit(AccessLoaded());
|
||||||
try {
|
try {
|
||||||
filteredData = data.where((item) {
|
filteredData = data.where((item) {
|
||||||
@ -151,7 +163,8 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (event.startTime != null && event.endTime != null) {
|
if (event.startTime != null && event.endTime != null) {
|
||||||
final int? effectiveTime = int.tryParse(item.effectiveTime.toString());
|
final int? effectiveTime =
|
||||||
|
int.tryParse(item.effectiveTime.toString());
|
||||||
final int? invalidTime = int.tryParse(item.invalidTime.toString());
|
final int? invalidTime = int.tryParse(item.invalidTime.toString());
|
||||||
if (effectiveTime == null || invalidTime == null) {
|
if (effectiveTime == null || invalidTime == null) {
|
||||||
matchesCriteria = false;
|
matchesCriteria = false;
|
||||||
@ -163,11 +176,14 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (event.selectedTabIndex == 1 && item.passwordStatus.value != 'To Be Effective') {
|
if (event.selectedTabIndex == 1 &&
|
||||||
|
item.passwordStatus.value != 'To Be Effective') {
|
||||||
matchesCriteria = false;
|
matchesCriteria = false;
|
||||||
} else if (event.selectedTabIndex == 2 && item.passwordStatus.value != 'Effective') {
|
} else if (event.selectedTabIndex == 2 &&
|
||||||
|
item.passwordStatus.value != 'Effective') {
|
||||||
matchesCriteria = false;
|
matchesCriteria = false;
|
||||||
} else if (event.selectedTabIndex == 3 && item.passwordStatus.value != 'Expired') {
|
} else if (event.selectedTabIndex == 3 &&
|
||||||
|
item.passwordStatus.value != 'Expired') {
|
||||||
matchesCriteria = false;
|
matchesCriteria = false;
|
||||||
}
|
}
|
||||||
return matchesCriteria;
|
return matchesCriteria;
|
||||||
@ -178,23 +194,25 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resetSearch(ResetSearch event, Emitter<AccessState> emit) async{
|
resetSearch(ResetSearch event, Emitter<AccessState> emit) async {
|
||||||
emit(AccessLoaded());
|
emit(AccessLoaded());
|
||||||
startTime = 'Start Time';
|
startTime = 'Start Time';
|
||||||
endTime = 'End Time';
|
endTime = 'End Time';
|
||||||
passwordName.clear();
|
passwordName.clear();
|
||||||
selectedIndex=0;
|
selectedIndex = 0;
|
||||||
effectiveTimeTimeStamp=null;
|
effectiveTimeTimeStamp = null;
|
||||||
expirationTimeTimeStamp=null;
|
expirationTimeTimeStamp = null;
|
||||||
add(FetchTableData());
|
add(FetchTableData());
|
||||||
}
|
}
|
||||||
|
|
||||||
String timestampToDate(dynamic timestamp) {
|
String timestampToDate(dynamic timestamp) {
|
||||||
DateTime dateTime = DateTime.fromMillisecondsSinceEpoch(int.parse(timestamp) * 1000);
|
DateTime dateTime =
|
||||||
|
DateTime.fromMillisecondsSinceEpoch(int.parse(timestamp) * 1000);
|
||||||
return "${dateTime.year}/${dateTime.month.toString().padLeft(2, '0')}/${dateTime.day.toString().padLeft(2, '0')}";
|
return "${dateTime.year}/${dateTime.month.toString().padLeft(2, '0')}/${dateTime.day.toString().padLeft(2, '0')}";
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> onTabChanged(TabChangedEvent event, Emitter<AccessState> emit) async {
|
Future<void> onTabChanged(
|
||||||
|
TabChangedEvent event, Emitter<AccessState> emit) async {
|
||||||
try {
|
try {
|
||||||
emit(AccessLoaded());
|
emit(AccessLoaded());
|
||||||
selectedIndex = event.selectedIndex;
|
selectedIndex = event.selectedIndex;
|
||||||
@ -203,13 +221,19 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
|||||||
filteredData = data;
|
filteredData = data;
|
||||||
break;
|
break;
|
||||||
case 1: // To Be Effective
|
case 1: // To Be Effective
|
||||||
filteredData = data.where((item) => item.passwordStatus.value == "To Be Effective").toList();
|
filteredData = data
|
||||||
|
.where((item) => item.passwordStatus.value == "To Be Effective")
|
||||||
|
.toList();
|
||||||
break;
|
break;
|
||||||
case 2: // Effective
|
case 2: // Effective
|
||||||
filteredData = data.where((item) => item.passwordStatus.value == "Effective").toList();
|
filteredData = data
|
||||||
|
.where((item) => item.passwordStatus.value == "Effective")
|
||||||
|
.toList();
|
||||||
break;
|
break;
|
||||||
case 3: // Expired
|
case 3: // Expired
|
||||||
filteredData = data.where((item) => item.passwordStatus.value == "Expired").toList();
|
filteredData = data
|
||||||
|
.where((item) => item.passwordStatus.value == "Expired")
|
||||||
|
.toList();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
filteredData = data;
|
filteredData = data;
|
||||||
@ -218,12 +242,10 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
|
|||||||
selectedTabIndex: selectedIndex,
|
selectedTabIndex: selectedIndex,
|
||||||
passwordName: passwordName.text.toLowerCase(),
|
passwordName: passwordName.text.toLowerCase(),
|
||||||
startTime: effectiveTimeTimeStamp,
|
startTime: effectiveTimeTimeStamp,
|
||||||
endTime: expirationTimeTimeStamp
|
endTime: expirationTimeTimeStamp));
|
||||||
));
|
|
||||||
emit(TableLoaded(filteredData));
|
emit(TableLoaded(filteredData));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(FailedState(e.toString()));
|
emit(FailedState(e.toString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
|
|
||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
abstract class AccessEvent extends Equatable {
|
abstract class AccessEvent extends Equatable {
|
||||||
const AccessEvent();
|
const AccessEvent();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [];
|
List<Object> get props => [];
|
||||||
}
|
}
|
||||||
|
|
||||||
class FetchTableData extends AccessEvent {}
|
class FetchTableData extends AccessEvent {}
|
||||||
|
|
||||||
class ResetSearch extends AccessEvent {}
|
class ResetSearch extends AccessEvent {}
|
||||||
|
|
||||||
class TabChangedEvent extends AccessEvent {
|
class TabChangedEvent extends AccessEvent {
|
||||||
@ -17,16 +18,14 @@ class TabChangedEvent extends AccessEvent {
|
|||||||
const TabChangedEvent(this.selectedIndex);
|
const TabChangedEvent(this.selectedIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class SelectTime extends AccessEvent {
|
class SelectTime extends AccessEvent {
|
||||||
final BuildContext context;
|
final BuildContext context;
|
||||||
final bool isStart;
|
final bool isStart;
|
||||||
const SelectTime({required this.context,required this.isStart});
|
const SelectTime({required this.context, required this.isStart});
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [context,isStart];
|
List<Object> get props => [context, isStart];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class FilterDataEvent extends AccessEvent {
|
class FilterDataEvent extends AccessEvent {
|
||||||
final String? passwordName;
|
final String? passwordName;
|
||||||
final int? startTime;
|
final int? startTime;
|
||||||
@ -34,13 +33,9 @@ class FilterDataEvent extends AccessEvent {
|
|||||||
final int selectedTabIndex; // Add this field
|
final int selectedTabIndex; // Add this field
|
||||||
|
|
||||||
const FilterDataEvent({
|
const FilterDataEvent({
|
||||||
this.passwordName,
|
this.passwordName,
|
||||||
this.startTime,
|
this.startTime,
|
||||||
this.endTime,
|
this.endTime,
|
||||||
required this.selectedTabIndex, // Initialize this field
|
required this.selectedTabIndex, // Initialize this field
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ abstract class AccessState extends Equatable {
|
|||||||
class AccessInitial extends AccessState {}
|
class AccessInitial extends AccessState {}
|
||||||
|
|
||||||
class AccessLoaded extends AccessState {}
|
class AccessLoaded extends AccessState {}
|
||||||
|
|
||||||
class FailedState extends AccessState {
|
class FailedState extends AccessState {
|
||||||
final String message;
|
final String message;
|
||||||
|
|
||||||
@ -29,7 +30,7 @@ class TableLoaded extends AccessState {
|
|||||||
List<Object> get props => [data];
|
List<Object> get props => [data];
|
||||||
}
|
}
|
||||||
|
|
||||||
class TabState extends AccessState {
|
class TabState extends AccessState {
|
||||||
final int selectedIndex;
|
final int selectedIndex;
|
||||||
|
|
||||||
const TabState({required this.selectedIndex});
|
const TabState({required this.selectedIndex});
|
||||||
|
@ -30,9 +30,9 @@ class PasswordModel {
|
|||||||
effectiveTime: json['effectiveTime'],
|
effectiveTime: json['effectiveTime'],
|
||||||
passwordCreated: json['passwordCreated'],
|
passwordCreated: json['passwordCreated'],
|
||||||
createdTime: json['createdTime'],
|
createdTime: json['createdTime'],
|
||||||
passwordName: json['passwordName']??'No name', // New field
|
passwordName: json['passwordName'] ?? 'No name', // New field
|
||||||
passwordStatus:AccessStatusExtension.fromString(json['passwordStatus']),
|
passwordStatus: AccessStatusExtension.fromString(json['passwordStatus']),
|
||||||
passwordType:AccessTypeExtension.fromString(json['passwordType']),
|
passwordType: AccessTypeExtension.fromString(json['passwordType']),
|
||||||
deviceUuid: json['deviceUuid'],
|
deviceUuid: json['deviceUuid'],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -50,5 +50,4 @@ class PasswordModel {
|
|||||||
'deviceUuid': deviceUuid,
|
'deviceUuid': deviceUuid,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@ import 'package:syncrow_web/pages/access_management/bloc/access_state.dart';
|
|||||||
import 'package:syncrow_web/pages/common/custom_table.dart';
|
import 'package:syncrow_web/pages/common/custom_table.dart';
|
||||||
import 'package:syncrow_web/pages/common/date_time_widget.dart';
|
import 'package:syncrow_web/pages/common/date_time_widget.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/common/filter/filter_widget.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/assets.dart';
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
|
@ -84,7 +84,7 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
|||||||
} else if (response == "You entered wrong otp") {
|
} else if (response == "You entered wrong otp") {
|
||||||
forgetValidate = 'Wrong one time password.';
|
forgetValidate = 'Wrong one time password.';
|
||||||
emit(AuthInitialState());
|
emit(AuthInitialState());
|
||||||
}else if (response == "OTP expired") {
|
} else if (response == "OTP expired") {
|
||||||
forgetValidate = 'One time password has been expired.';
|
forgetValidate = 'One time password has been expired.';
|
||||||
emit(AuthInitialState());
|
emit(AuthInitialState());
|
||||||
}
|
}
|
||||||
@ -94,6 +94,7 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
|||||||
// emit(FailureForgetState(error: failure.toString()));
|
// emit(FailureForgetState(error: failure.toString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//925207
|
//925207
|
||||||
String? validateCode(String? value) {
|
String? validateCode(String? value) {
|
||||||
if (value == null || value.isEmpty) {
|
if (value == null || value.isEmpty) {
|
||||||
|
@ -13,47 +13,60 @@ class LoginButtonPressed extends AuthEvent {
|
|||||||
final String password;
|
final String password;
|
||||||
final String regionUuid;
|
final String regionUuid;
|
||||||
|
|
||||||
const LoginButtonPressed({required this.username, required this.password, required this.regionUuid, });
|
const LoginButtonPressed({
|
||||||
|
required this.username,
|
||||||
|
required this.password,
|
||||||
|
required this.regionUuid,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [username, password,regionUuid];
|
List<Object> get props => [username, password, regionUuid];
|
||||||
}
|
}
|
||||||
|
|
||||||
class CheckBoxEvent extends AuthEvent {
|
class CheckBoxEvent extends AuthEvent {
|
||||||
final bool? newValue;
|
final bool? newValue;
|
||||||
|
|
||||||
const CheckBoxEvent({required this.newValue,});
|
const CheckBoxEvent({
|
||||||
|
required this.newValue,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [newValue!,];
|
List<Object> get props => [
|
||||||
|
newValue!,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
class GetCodeEvent extends AuthEvent{}
|
class GetCodeEvent extends AuthEvent {}
|
||||||
|
|
||||||
class SubmitEvent extends AuthEvent{}
|
class SubmitEvent extends AuthEvent {}
|
||||||
|
|
||||||
class StartTimerEvent extends AuthEvent{}
|
class StartTimerEvent extends AuthEvent {}
|
||||||
|
|
||||||
class StopTimerEvent extends AuthEvent{}
|
class StopTimerEvent extends AuthEvent {}
|
||||||
|
|
||||||
class UpdateTimerEvent extends AuthEvent {
|
class UpdateTimerEvent extends AuthEvent {
|
||||||
final int remainingTime;
|
final int remainingTime;
|
||||||
final bool isButtonEnabled;
|
final bool isButtonEnabled;
|
||||||
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;
|
||||||
|
|
||||||
const PasswordVisibleEvent({required this.newValue,});
|
const PasswordVisibleEvent({
|
||||||
|
required this.newValue,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
class RegionInitialEvent extends AuthEvent {}
|
class RegionInitialEvent extends AuthEvent {}
|
||||||
|
|
||||||
class CheckEnableEvent extends AuthEvent {}
|
class CheckEnableEvent extends AuthEvent {}
|
||||||
|
|
||||||
class ChangeValidateEvent extends AuthEvent {}
|
class ChangeValidateEvent extends AuthEvent {}
|
||||||
|
|
||||||
class SelectRegionEvent extends AuthEvent {
|
class SelectRegionEvent extends AuthEvent {
|
||||||
@ -62,4 +75,3 @@ class SelectRegionEvent extends AuthEvent {
|
|||||||
@override
|
@override
|
||||||
List<Object> get props => [val];
|
List<Object> get props => [val];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ class LoginInitial extends AuthState {}
|
|||||||
class AuthTokenLoading extends AuthState {}
|
class AuthTokenLoading extends AuthState {}
|
||||||
|
|
||||||
class AuthLoading extends AuthState {}
|
class AuthLoading extends AuthState {}
|
||||||
|
|
||||||
class AuthInitialState extends AuthState {}
|
class AuthInitialState extends AuthState {}
|
||||||
|
|
||||||
class LoginSuccess extends AuthState {}
|
class LoginSuccess extends AuthState {}
|
||||||
@ -55,7 +56,8 @@ class TimerState extends AuthState {
|
|||||||
final bool isButtonEnabled;
|
final bool isButtonEnabled;
|
||||||
final int remainingTime;
|
final int remainingTime;
|
||||||
|
|
||||||
const TimerState({required this.isButtonEnabled, required this.remainingTime});
|
const TimerState(
|
||||||
|
{required this.isButtonEnabled, required this.remainingTime});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [isButtonEnabled, remainingTime];
|
List<Object> get props => [isButtonEnabled, remainingTime];
|
||||||
@ -74,6 +76,7 @@ class AuthTokenError extends AuthError {
|
|||||||
class AuthSuccess extends AuthState {}
|
class AuthSuccess extends AuthState {}
|
||||||
|
|
||||||
class AuthTokenSuccess extends AuthSuccess {}
|
class AuthTokenSuccess extends AuthSuccess {}
|
||||||
|
|
||||||
class TimerUpdated extends AuthState {
|
class TimerUpdated extends AuthState {
|
||||||
final String formattedTime;
|
final String formattedTime;
|
||||||
final bool isButtonEnabled;
|
final bool isButtonEnabled;
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
|
|
||||||
|
|
||||||
class RegionModel {
|
class RegionModel {
|
||||||
final String name;
|
final String name;
|
||||||
final String id;
|
final String id;
|
||||||
|
@ -42,14 +42,11 @@ class Token {
|
|||||||
//save token to secure storage
|
//save token to secure storage
|
||||||
var storage = const FlutterSecureStorage();
|
var storage = const FlutterSecureStorage();
|
||||||
storage.write(
|
storage.write(
|
||||||
key: loginAccessTokenKey,
|
key: loginAccessTokenKey, value: json[loginAccessTokenKey] ?? '');
|
||||||
value: json[loginAccessTokenKey] ?? '');
|
|
||||||
storage.write(
|
storage.write(
|
||||||
key: loginRefreshTokenKey,
|
key: loginRefreshTokenKey, value: json[loginRefreshTokenKey] ?? '');
|
||||||
value: json[loginRefreshTokenKey] ?? '');
|
|
||||||
//create token object ?
|
//create token object ?
|
||||||
return Token(
|
return Token(json[loginAccessTokenKey] ?? '',
|
||||||
json[loginAccessTokenKey] ?? '',
|
|
||||||
json[loginRefreshTokenKey] ?? '', '', 0, 0);
|
json[loginRefreshTokenKey] ?? '', '', 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
|
|
||||||
|
|
||||||
import 'package:syncrow_web/pages/auth/model/token.dart';
|
import 'package:syncrow_web/pages/auth/model/token.dart';
|
||||||
|
|
||||||
class UserModel {
|
class UserModel {
|
||||||
|
@ -10,7 +10,10 @@ class VerifyPassCode {
|
|||||||
final String deviceId;
|
final String deviceId;
|
||||||
|
|
||||||
VerifyPassCode(
|
VerifyPassCode(
|
||||||
{required this.phone, required this.passCode, required this.agent, required this.deviceId});
|
{required this.phone,
|
||||||
|
required this.passCode,
|
||||||
|
required this.agent,
|
||||||
|
required this.deviceId});
|
||||||
|
|
||||||
factory VerifyPassCode.fromJson(Map<String, dynamic> json) => VerifyPassCode(
|
factory VerifyPassCode.fromJson(Map<String, dynamic> json) => VerifyPassCode(
|
||||||
phone: json[verificationPhone],
|
phone: json[verificationPhone],
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class ForgetPasswordMobilePage extends StatelessWidget {
|
class ForgetPasswordMobilePage extends StatelessWidget {
|
||||||
|
@ -1,19 +1,15 @@
|
|||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:syncrow_web/pages/auth/view/forget_password_mobile_page.dart';
|
import 'package:syncrow_web/pages/auth/view/forget_password_mobile_page.dart';
|
||||||
import 'package:syncrow_web/pages/auth/view/forget_password_web_page.dart';
|
import 'package:syncrow_web/pages/auth/view/forget_password_web_page.dart';
|
||||||
import 'package:syncrow_web/utils/responsive_layout.dart';
|
import 'package:syncrow_web/utils/responsive_layout.dart';
|
||||||
|
|
||||||
|
|
||||||
class ForgetPasswordPage extends StatelessWidget {
|
class ForgetPasswordPage extends StatelessWidget {
|
||||||
const ForgetPasswordPage({super.key});
|
const ForgetPasswordPage({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return const ResponsiveLayout(
|
return const ResponsiveLayout(
|
||||||
desktopBody: ForgetPasswordWebPage(),
|
desktopBody: ForgetPasswordWebPage(),
|
||||||
mobileBody:ForgetPasswordWebPage()
|
mobileBody: ForgetPasswordWebPage());
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ class ForgetPasswordWebPage extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
return _buildForm(context, state);
|
return _buildForm(context, state);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -66,7 +66,7 @@ class ForgetPasswordWebPage extends StatelessWidget {
|
|||||||
child: Stack(
|
child: Stack(
|
||||||
children: [
|
children: [
|
||||||
if (state is AuthLoading)
|
if (state is AuthLoading)
|
||||||
const Center(child: CircularProgressIndicator()),
|
const Center(child: CircularProgressIndicator()),
|
||||||
ListView(
|
ListView(
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
controller: _scrollController,
|
controller: _scrollController,
|
||||||
@ -99,7 +99,8 @@ class ForgetPasswordWebPage extends StatelessWidget {
|
|||||||
borderRadius:
|
borderRadius:
|
||||||
const BorderRadius.all(Radius.circular(30)),
|
const BorderRadius.all(Radius.circular(30)),
|
||||||
border: Border.all(
|
border: Border.all(
|
||||||
color: ColorsManager.graysColor.withOpacity(0.2)),
|
color:
|
||||||
|
ColorsManager.graysColor.withOpacity(0.2)),
|
||||||
),
|
),
|
||||||
child: Form(
|
child: Form(
|
||||||
key: forgetBloc.forgetFormKey,
|
key: forgetBloc.forgetFormKey,
|
||||||
@ -108,7 +109,8 @@ class ForgetPasswordWebPage extends StatelessWidget {
|
|||||||
horizontal: size.width * 0.02,
|
horizontal: size.width * 0.02,
|
||||||
vertical: size.width * 0.003),
|
vertical: size.width * 0.003),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.spaceEvenly,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
@ -122,21 +124,27 @@ class ForgetPasswordWebPage extends StatelessWidget {
|
|||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
Text(
|
Text(
|
||||||
'Please fill in your account information to\nretrieve your password',
|
'Please fill in your account information to\nretrieve your password',
|
||||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
style: Theme.of(context)
|
||||||
fontSize: 14,
|
.textTheme
|
||||||
fontWeight: FontWeight.w400),
|
.bodySmall!
|
||||||
|
.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: [
|
||||||
Text(
|
Text(
|
||||||
"Country/Region",
|
"Country/Region",
|
||||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
style: Theme.of(context)
|
||||||
fontSize: 14,
|
.textTheme
|
||||||
fontWeight: FontWeight.w400),
|
.bodySmall!
|
||||||
|
.copyWith(
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w400),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
@ -145,7 +153,8 @@ class ForgetPasswordWebPage extends StatelessWidget {
|
|||||||
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: SizedBox(
|
hint: SizedBox(
|
||||||
@ -160,15 +169,14 @@ class ForgetPasswordWebPage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
isDense: true,
|
isDense: true,
|
||||||
style:
|
style: const TextStyle(
|
||||||
const TextStyle(color: Colors.black),
|
color: Colors.black),
|
||||||
items: forgetBloc.regionList!
|
items: forgetBloc.regionList!
|
||||||
.map((RegionModel region) {
|
.map((RegionModel region) {
|
||||||
return DropdownMenuItem<String>(
|
return DropdownMenuItem<String>(
|
||||||
value: region.id,
|
value: region.id,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width: size.width*0.06,
|
width: size.width * 0.06,
|
||||||
|
|
||||||
child: Text(region.name)),
|
child: Text(region.name)),
|
||||||
);
|
);
|
||||||
}).toList(),
|
}).toList(),
|
||||||
@ -183,13 +191,18 @@ class ForgetPasswordWebPage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment:
|
||||||
|
CrossAxisAlignment.start,
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Account",
|
"Account",
|
||||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(fontSize: 14,fontWeight: FontWeight.w400),
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodySmall!
|
||||||
|
.copyWith(
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w400),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
@ -197,22 +210,29 @@ class ForgetPasswordWebPage extends StatelessWidget {
|
|||||||
validator: forgetBloc.validateEmail,
|
validator: forgetBloc.validateEmail,
|
||||||
controller:
|
controller:
|
||||||
forgetBloc.forgetEmailController,
|
forgetBloc.forgetEmailController,
|
||||||
decoration: textBoxDecoration()!.copyWith(
|
decoration: textBoxDecoration()!
|
||||||
hintText: 'Enter your email'),
|
.copyWith(
|
||||||
style:
|
hintText: 'Enter your email'),
|
||||||
const TextStyle(color: Colors.black),
|
style: const TextStyle(
|
||||||
|
color: Colors.black),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20.0),
|
const SizedBox(height: 20.0),
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment:
|
||||||
|
CrossAxisAlignment.start,
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"One Time Password",
|
"One Time Password",
|
||||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(fontSize: 14,fontWeight: FontWeight.w400),
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodySmall!
|
||||||
|
.copyWith(
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w400),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
@ -221,65 +241,88 @@ class ForgetPasswordWebPage extends StatelessWidget {
|
|||||||
keyboardType:
|
keyboardType:
|
||||||
TextInputType.visiblePassword,
|
TextInputType.visiblePassword,
|
||||||
controller: forgetBloc.forgetOtp,
|
controller: forgetBloc.forgetOtp,
|
||||||
decoration: textBoxDecoration()!.copyWith(
|
decoration:
|
||||||
|
textBoxDecoration()!.copyWith(
|
||||||
hintText: 'Enter Code',
|
hintText: 'Enter Code',
|
||||||
suffixIcon: SizedBox(
|
suffixIcon: SizedBox(
|
||||||
width: 100,
|
width: 100,
|
||||||
child: Center(
|
child: Center(
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap:state is TimerState && !state.isButtonEnabled && state.remainingTime!=1?null: () {
|
onTap: state is TimerState &&
|
||||||
forgetBloc.add(StartTimerEvent());
|
!state
|
||||||
},
|
.isButtonEnabled &&
|
||||||
|
state.remainingTime !=
|
||||||
|
1
|
||||||
|
? null
|
||||||
|
: () {
|
||||||
|
forgetBloc.add(
|
||||||
|
StartTimerEvent());
|
||||||
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
'Get Code ${state is TimerState && !state.isButtonEnabled && state.remainingTime!=1? "(${forgetBloc.formattedTime(state.remainingTime)}) " : ""}',
|
'Get Code ${state is TimerState && !state.isButtonEnabled && state.remainingTime != 1 ? "(${forgetBloc.formattedTime(state.remainingTime)}) " : ""}',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: state is TimerState &&
|
color: state
|
||||||
!state.isButtonEnabled
|
is TimerState &&
|
||||||
|
!state
|
||||||
|
.isButtonEnabled
|
||||||
? Colors.grey
|
? Colors.grey
|
||||||
: ColorsManager.btnColor,
|
: ColorsManager
|
||||||
|
.btnColor,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
style:
|
style: const TextStyle(
|
||||||
const TextStyle(color: Colors.black),
|
color: Colors.black),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (forgetBloc.forgetValidate != '') // Check if there is a validation message
|
if (forgetBloc.forgetValidate !=
|
||||||
|
'') // Check if there is a validation message
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(top: 8.0),
|
padding:
|
||||||
|
const EdgeInsets.only(top: 8.0),
|
||||||
child: Text(
|
child: Text(
|
||||||
forgetBloc.forgetValidate,
|
forgetBloc.forgetValidate,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
color: ColorsManager.red,
|
color: ColorsManager.red,
|
||||||
fontSize: 10,
|
fontSize: 10,
|
||||||
fontWeight: FontWeight.w700
|
fontWeight: FontWeight.w700),
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20.0),
|
const SizedBox(height: 20.0),
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment:
|
||||||
|
CrossAxisAlignment.start,
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Password",
|
"Password",
|
||||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(fontSize: 14,fontWeight: FontWeight.w400),
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodySmall!
|
||||||
|
.copyWith(
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w400),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
child: TextFormField(
|
child: TextFormField(
|
||||||
validator: forgetBloc.passwordValidator,
|
validator:
|
||||||
keyboardType: TextInputType.visiblePassword,
|
forgetBloc.passwordValidator,
|
||||||
controller: forgetBloc.forgetPasswordController,
|
keyboardType:
|
||||||
decoration: textBoxDecoration()!.copyWith(
|
TextInputType.visiblePassword,
|
||||||
|
controller: forgetBloc
|
||||||
|
.forgetPasswordController,
|
||||||
|
decoration:
|
||||||
|
textBoxDecoration()!.copyWith(
|
||||||
hintText: 'At least 8 characters',
|
hintText: 'At least 8 characters',
|
||||||
),
|
),
|
||||||
style: const TextStyle(color: Colors.black),
|
style: const TextStyle(
|
||||||
|
color: Colors.black),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -289,17 +332,22 @@ class ForgetPasswordWebPage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
const SizedBox(height: 20.0),
|
const SizedBox(height: 20.0),
|
||||||
Row(
|
Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment:
|
||||||
|
CrossAxisAlignment.center,
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: size.width * 0.2,
|
width: size.width * 0.2,
|
||||||
child: DefaultButton(
|
child: DefaultButton(
|
||||||
backgroundColor: ColorsManager.btnColor,
|
backgroundColor:
|
||||||
|
ColorsManager.btnColor,
|
||||||
child: const Text('Submit'),
|
child: const Text('Submit'),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
if (forgetBloc.forgetFormKey.currentState!.validate()) {
|
if (forgetBloc
|
||||||
forgetBloc.add(ChangePasswordEvent());
|
.forgetFormKey.currentState!
|
||||||
|
.validate()) {
|
||||||
|
forgetBloc
|
||||||
|
.add(ChangePasswordEvent());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -321,8 +369,10 @@ class ForgetPasswordWebPage extends StatelessWidget {
|
|||||||
SizedBox(
|
SizedBox(
|
||||||
width: size.width * 0.2,
|
width: size.width * 0.2,
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment:
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment:
|
||||||
|
CrossAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
const Flexible(
|
const Flexible(
|
||||||
child: Text(
|
child: Text(
|
||||||
|
@ -27,7 +27,7 @@ class LoginMobilePage extends StatelessWidget {
|
|||||||
// Navigate to home screen after successful login
|
// Navigate to home screen after successful login
|
||||||
Navigator.pushReplacement(
|
Navigator.pushReplacement(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(builder: (context) => HomePage()),
|
MaterialPageRoute(builder: (context) => HomePage()),
|
||||||
);
|
);
|
||||||
} else if (state is LoginFailure) {
|
} else if (state is LoginFailure) {
|
||||||
// Show error message
|
// Show error message
|
||||||
@ -148,14 +148,14 @@ class LoginMobilePage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
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) {},
|
||||||
},
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
@ -194,7 +194,8 @@ class LoginMobilePage extends StatelessWidget {
|
|||||||
validator: loginBloc.validatePassword,
|
validator: loginBloc.validatePassword,
|
||||||
obscureText: loginBloc.obscureText,
|
obscureText: loginBloc.obscureText,
|
||||||
keyboardType: TextInputType.visiblePassword,
|
keyboardType: TextInputType.visiblePassword,
|
||||||
controller: loginBloc.loginPasswordController,
|
controller:
|
||||||
|
loginBloc.loginPasswordController,
|
||||||
decoration: textBoxDecoration()!.copyWith(
|
decoration: textBoxDecoration()!.copyWith(
|
||||||
hintText: 'At least 8 characters',
|
hintText: 'At least 8 characters',
|
||||||
),
|
),
|
||||||
@ -220,7 +221,8 @@ class LoginMobilePage extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
"Forgot Password?",
|
"Forgot Password?",
|
||||||
style: Theme.of(context).textTheme.bodySmall,
|
style:
|
||||||
|
Theme.of(context).textTheme.bodySmall,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -295,12 +297,15 @@ class LoginMobilePage extends StatelessWidget {
|
|||||||
: ColorsManager.grayColor,
|
: ColorsManager.grayColor,
|
||||||
child: const Text('Sign in'),
|
child: const Text('Sign in'),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
if (loginBloc.loginFormKey.currentState!.validate()) {
|
if (loginBloc.loginFormKey.currentState!
|
||||||
|
.validate()) {
|
||||||
loginBloc.add(
|
loginBloc.add(
|
||||||
LoginButtonPressed(
|
LoginButtonPressed(
|
||||||
regionUuid:'' ,
|
regionUuid: '',
|
||||||
username: loginBloc.loginEmailController.text,
|
username:
|
||||||
password: loginBloc.loginPasswordController.text,
|
loginBloc.loginEmailController.text,
|
||||||
|
password: loginBloc
|
||||||
|
.loginPasswordController.text,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -9,8 +9,6 @@ class LoginPage extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return const ResponsiveLayout(
|
return const ResponsiveLayout(
|
||||||
desktopBody: LoginWebPage(),
|
desktopBody: LoginWebPage(), mobileBody: LoginWebPage());
|
||||||
mobileBody:LoginWebPage()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,6 @@ class LoginWebPage extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _LoginWebPageState extends State<LoginWebPage> {
|
class _LoginWebPageState extends State<LoginWebPage> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
@ -36,7 +35,7 @@ class _LoginWebPageState extends State<LoginWebPage> {
|
|||||||
// Navigate to home screen after successful login
|
// Navigate to home screen after successful login
|
||||||
Navigator.pushReplacement(
|
Navigator.pushReplacement(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(builder: (context) => HomePage()),
|
MaterialPageRoute(builder: (context) => HomePage()),
|
||||||
);
|
);
|
||||||
} else if (state is LoginFailure) {
|
} else if (state is LoginFailure) {
|
||||||
// Show error message
|
// Show error message
|
||||||
@ -48,26 +47,28 @@ class _LoginWebPageState extends State<LoginWebPage> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
return _buildLoginForm(context,state);
|
return _buildLoginForm(context, state);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildLoginForm(BuildContext context,AuthState state) {
|
Widget _buildLoginForm(BuildContext context, AuthState state) {
|
||||||
final loginBloc = BlocProvider.of<AuthBloc>(context);
|
final loginBloc = BlocProvider.of<AuthBloc>(context);
|
||||||
Size size = MediaQuery.of(context).size;
|
Size size = MediaQuery.of(context).size;
|
||||||
late ScrollController _scrollController;
|
late ScrollController _scrollController;
|
||||||
_scrollController = ScrollController();
|
_scrollController = ScrollController();
|
||||||
void _scrollToCenter() {
|
void _scrollToCenter() {
|
||||||
final double middlePosition = _scrollController.position.maxScrollExtent / 2;
|
final double middlePosition =
|
||||||
|
_scrollController.position.maxScrollExtent / 2;
|
||||||
_scrollController.animateTo(
|
_scrollController.animateTo(
|
||||||
middlePosition,
|
middlePosition,
|
||||||
duration: const Duration(seconds: 1),
|
duration: const Duration(seconds: 1),
|
||||||
curve: Curves.easeInOut,
|
curve: Curves.easeInOut,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
_scrollToCenter();
|
_scrollToCenter();
|
||||||
});
|
});
|
||||||
@ -80,14 +81,14 @@ class _LoginWebPageState extends State<LoginWebPage> {
|
|||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
padding: EdgeInsets.all(size.width*0.02) ,
|
padding: EdgeInsets.all(size.width * 0.02),
|
||||||
margin: EdgeInsets.all(size.width*0.09),
|
margin: EdgeInsets.all(size.width * 0.09),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.black.withOpacity(0.3),
|
color: Colors.black.withOpacity(0.3),
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(20)),
|
borderRadius: const BorderRadius.all(Radius.circular(20)),
|
||||||
),
|
),
|
||||||
child: Center(
|
child: Center(
|
||||||
child:Row(
|
child: Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
@ -101,92 +102,140 @@ class _LoginWebPageState extends State<LoginWebPage> {
|
|||||||
const Spacer(),
|
const Spacer(),
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 3,
|
flex: 3,
|
||||||
child: Container(
|
child: Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.white.withOpacity(0.1),
|
color: Colors.white.withOpacity(0.1),
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(30)),
|
borderRadius: const BorderRadius.all(
|
||||||
border: Border.all(color: ColorsManager.graysColor.withOpacity(0.2))),
|
Radius.circular(30)),
|
||||||
|
border: Border.all(
|
||||||
|
color: ColorsManager.graysColor
|
||||||
|
.withOpacity(0.2))),
|
||||||
child: Form(
|
child: Form(
|
||||||
key: loginBloc.loginFormKey,
|
key: loginBloc.loginFormKey,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: EdgeInsets.symmetric(
|
padding: EdgeInsets.symmetric(
|
||||||
horizontal: size.width*0.02,
|
horizontal: size.width * 0.02,
|
||||||
vertical: size.width*0.003),
|
vertical: size.width * 0.003),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
mainAxisAlignment:
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
MainAxisAlignment.spaceEvenly,
|
||||||
|
crossAxisAlignment:
|
||||||
|
CrossAxisAlignment.start,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
const SizedBox(height: 40),
|
const SizedBox(height: 40),
|
||||||
Text(
|
Text('Login',
|
||||||
'Login',
|
style: Theme.of(context)
|
||||||
style:Theme.of(context).textTheme.headlineLarge),
|
.textTheme
|
||||||
SizedBox(height: size.height*0.03),
|
.headlineLarge),
|
||||||
|
SizedBox(height: size.height * 0.03),
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment:
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
CrossAxisAlignment.start,
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Country/Region",
|
"Country/Region",
|
||||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(fontSize: 14,fontWeight: FontWeight.w400),
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodySmall!
|
||||||
|
.copyWith(
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight:
|
||||||
|
FontWeight.w400),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 10,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 10,),
|
|
||||||
|
|
||||||
SizedBox(
|
SizedBox(
|
||||||
child: DropdownButtonFormField<String>(
|
child: DropdownButtonFormField<
|
||||||
|
String>(
|
||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
value: loginBloc.regionList!.any((region) => region.id == loginBloc.regionUuid)
|
value: loginBloc.regionList!
|
||||||
|
.any((region) =>
|
||||||
|
region.id ==
|
||||||
|
loginBloc
|
||||||
|
.regionUuid)
|
||||||
? loginBloc.regionUuid
|
? loginBloc.regionUuid
|
||||||
: null,
|
: null,
|
||||||
|
validator:
|
||||||
validator: loginBloc.validateRegion,
|
loginBloc.validateRegion,
|
||||||
icon: const Icon(
|
icon: const Icon(
|
||||||
Icons.keyboard_arrow_down_outlined,
|
Icons
|
||||||
|
.keyboard_arrow_down_outlined,
|
||||||
),
|
),
|
||||||
decoration: textBoxDecoration()!.copyWith(
|
decoration: textBoxDecoration()!
|
||||||
errorStyle: const TextStyle(height: 0),
|
.copyWith(
|
||||||
|
errorStyle: const TextStyle(
|
||||||
|
height: 0),
|
||||||
hintText: null,
|
hintText: null,
|
||||||
),
|
),
|
||||||
hint: SizedBox(
|
hint: SizedBox(
|
||||||
width: size.width * 0.12,
|
width: size.width * 0.12,
|
||||||
child: Align(
|
child: Align(
|
||||||
alignment: Alignment.centerLeft,
|
alignment:
|
||||||
|
Alignment.centerLeft,
|
||||||
child: Text(
|
child: Text(
|
||||||
'Select your region/country',
|
'Select your region/country',
|
||||||
textAlign: TextAlign.center,
|
textAlign:
|
||||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
TextAlign.center,
|
||||||
color: ColorsManager.grayColor,
|
style: Theme.of(context)
|
||||||
fontWeight: FontWeight.w400),
|
.textTheme
|
||||||
overflow: TextOverflow.ellipsis,
|
.bodySmall!
|
||||||
|
.copyWith(
|
||||||
|
color:
|
||||||
|
ColorsManager
|
||||||
|
.grayColor,
|
||||||
|
fontWeight:
|
||||||
|
FontWeight
|
||||||
|
.w400),
|
||||||
|
overflow:
|
||||||
|
TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
isDense: true,
|
isDense: true,
|
||||||
style: const TextStyle(color: Colors.black),
|
style: const TextStyle(
|
||||||
items: loginBloc.regionList!.map((RegionModel region) {
|
color: Colors.black),
|
||||||
return DropdownMenuItem<String>(
|
items: loginBloc.regionList!
|
||||||
|
.map((RegionModel region) {
|
||||||
|
return DropdownMenuItem<
|
||||||
|
String>(
|
||||||
value: region.id,
|
value: region.id,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width: size.width*0.08,
|
width:
|
||||||
child: Text(region.name)),
|
size.width * 0.08,
|
||||||
|
child:
|
||||||
|
Text(region.name)),
|
||||||
);
|
);
|
||||||
}).toList(),
|
}).toList(),
|
||||||
onChanged: (String? value) {
|
onChanged: (String? value) {
|
||||||
loginBloc.add(CheckEnableEvent());
|
loginBloc
|
||||||
loginBloc.add(SelectRegionEvent(val: value!));
|
.add(CheckEnableEvent());
|
||||||
|
loginBloc.add(
|
||||||
|
SelectRegionEvent(
|
||||||
|
val: value!));
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20.0),
|
const SizedBox(height: 20.0),
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment:
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
CrossAxisAlignment.start,
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text("Email",
|
Text(
|
||||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(fontSize: 14,fontWeight: FontWeight.w400),
|
"Email",
|
||||||
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodySmall!
|
||||||
|
.copyWith(
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight:
|
||||||
|
FontWeight.w400),
|
||||||
),
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 10,
|
height: 10,
|
||||||
@ -194,30 +243,53 @@ class _LoginWebPageState extends State<LoginWebPage> {
|
|||||||
SizedBox(
|
SizedBox(
|
||||||
child: TextFormField(
|
child: TextFormField(
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
loginBloc.add(CheckEnableEvent());
|
loginBloc
|
||||||
// print(loginBloc.checkEnable());
|
.add(CheckEnableEvent());
|
||||||
|
// print(loginBloc.checkEnable());
|
||||||
},
|
},
|
||||||
validator:loginBloc.loginValidateEmail ,
|
validator: loginBloc
|
||||||
controller:loginBloc.loginEmailController,
|
.loginValidateEmail,
|
||||||
decoration: textBoxDecoration()!.copyWith(
|
controller: loginBloc
|
||||||
errorStyle: const TextStyle(height: 0), // Hide the error text space
|
.loginEmailController,
|
||||||
hintText: 'Enter your email address',
|
decoration: textBoxDecoration()!
|
||||||
hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith(
|
.copyWith(
|
||||||
color: ColorsManager.grayColor,
|
errorStyle: const TextStyle(
|
||||||
fontWeight: FontWeight.w400)
|
height:
|
||||||
),
|
0), // Hide the error text space
|
||||||
style: const TextStyle(color: Colors.black),
|
hintText:
|
||||||
|
'Enter your email address',
|
||||||
|
hintStyle: Theme.of(
|
||||||
|
context)
|
||||||
|
.textTheme
|
||||||
|
.bodySmall!
|
||||||
|
.copyWith(
|
||||||
|
color: ColorsManager
|
||||||
|
.grayColor,
|
||||||
|
fontWeight:
|
||||||
|
FontWeight
|
||||||
|
.w400)),
|
||||||
|
style: const TextStyle(
|
||||||
|
color: Colors.black),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20.0),
|
const SizedBox(height: 20.0),
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment:
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
CrossAxisAlignment.start,
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text("Password",
|
Text(
|
||||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(fontSize: 14,fontWeight: FontWeight.w400),
|
"Password",
|
||||||
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodySmall!
|
||||||
|
.copyWith(
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight:
|
||||||
|
FontWeight.w400),
|
||||||
),
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 10,
|
height: 10,
|
||||||
@ -225,33 +297,54 @@ class _LoginWebPageState extends State<LoginWebPage> {
|
|||||||
SizedBox(
|
SizedBox(
|
||||||
child: TextFormField(
|
child: TextFormField(
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
loginBloc.add(CheckEnableEvent());
|
loginBloc
|
||||||
},
|
.add(CheckEnableEvent());
|
||||||
validator:loginBloc.validatePassword,
|
},
|
||||||
obscureText:loginBloc.obscureText,
|
validator:
|
||||||
keyboardType: TextInputType.visiblePassword,
|
loginBloc.validatePassword,
|
||||||
controller:loginBloc.loginPasswordController,
|
obscureText:
|
||||||
decoration: textBoxDecoration()!.copyWith(
|
loginBloc.obscureText,
|
||||||
hintText: 'At least 8 characters',
|
keyboardType: TextInputType
|
||||||
hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith(
|
.visiblePassword,
|
||||||
color: ColorsManager.grayColor,
|
controller: loginBloc
|
||||||
fontWeight: FontWeight.w400),
|
.loginPasswordController,
|
||||||
suffixIcon: IconButton(onPressed: () {
|
decoration: textBoxDecoration()!
|
||||||
loginBloc.add(PasswordVisibleEvent(newValue: loginBloc.obscureText));
|
.copyWith(
|
||||||
|
hintText:
|
||||||
|
'At least 8 characters',
|
||||||
|
hintStyle: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodySmall!
|
||||||
|
.copyWith(
|
||||||
|
color: ColorsManager
|
||||||
|
.grayColor,
|
||||||
|
fontWeight:
|
||||||
|
FontWeight.w400),
|
||||||
|
suffixIcon: IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
loginBloc.add(
|
||||||
|
PasswordVisibleEvent(
|
||||||
|
newValue: loginBloc
|
||||||
|
.obscureText));
|
||||||
},
|
},
|
||||||
icon: SizedBox(
|
icon: SizedBox(
|
||||||
child: SvgPicture.asset(
|
child: SvgPicture.asset(
|
||||||
loginBloc.obscureText?
|
loginBloc.obscureText
|
||||||
Assets.visiblePassword :
|
? Assets
|
||||||
Assets.invisiblePassword,
|
.visiblePassword
|
||||||
height: 15,
|
: Assets
|
||||||
width: 15,
|
.invisiblePassword,
|
||||||
),
|
height: 15,
|
||||||
|
width: 15,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
errorStyle: const TextStyle(height: 0), // Hide the error text space
|
),
|
||||||
|
errorStyle: const TextStyle(
|
||||||
|
height:
|
||||||
|
0), // Hide the error text space
|
||||||
),
|
),
|
||||||
style: const TextStyle(color: Colors.black),
|
style: const TextStyle(
|
||||||
|
color: Colors.black),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -261,15 +354,27 @@ class _LoginWebPageState extends State<LoginWebPage> {
|
|||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
InkWell(
|
InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.of(context).push(MaterialPageRoute(builder: (context) => const ForgetPasswordPage(),));
|
Navigator.of(context)
|
||||||
|
.push(MaterialPageRoute(
|
||||||
|
builder: (context) =>
|
||||||
|
const ForgetPasswordPage(),
|
||||||
|
));
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
"Forgot Password?",
|
"Forgot Password?",
|
||||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(color: Colors.black,fontSize: 14,fontWeight: FontWeight.w400),
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodySmall!
|
||||||
|
.copyWith(
|
||||||
|
color: Colors.black,
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight:
|
||||||
|
FontWeight.w400),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -281,53 +386,65 @@ class _LoginWebPageState extends State<LoginWebPage> {
|
|||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Transform.scale(
|
Transform.scale(
|
||||||
scale: 1.2, // Adjust the scale as needed
|
scale:
|
||||||
|
1.2, // Adjust the scale as needed
|
||||||
child: Checkbox(
|
child: Checkbox(
|
||||||
fillColor: MaterialStateProperty.all<Color>(Colors.white),
|
fillColor: MaterialStateProperty
|
||||||
|
.all<Color>(Colors.white),
|
||||||
activeColor: Colors.white,
|
activeColor: Colors.white,
|
||||||
value:loginBloc.isChecked,
|
value: loginBloc.isChecked,
|
||||||
checkColor: Colors.black,
|
checkColor: Colors.black,
|
||||||
shape: const CircleBorder(),
|
shape: const CircleBorder(),
|
||||||
onChanged: (bool? newValue) {
|
onChanged: (bool? newValue) {
|
||||||
loginBloc.add(CheckBoxEvent(newValue: newValue));
|
loginBloc.add(CheckBoxEvent(
|
||||||
|
newValue: newValue));
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width:size.width * 0.14,
|
width: size.width * 0.14,
|
||||||
child: RichText(
|
child: RichText(
|
||||||
text: TextSpan(
|
text: TextSpan(
|
||||||
text: 'Agree to ',
|
text: 'Agree to ',
|
||||||
style: const TextStyle(color: Colors.white),
|
style: const TextStyle(
|
||||||
|
color: Colors.white),
|
||||||
children: [
|
children: [
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: '(Terms of Service)',
|
text:
|
||||||
|
'(Terms of Service)',
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
color: Colors.black,),
|
color: Colors.black,
|
||||||
recognizer: TapGestureRecognizer()
|
),
|
||||||
..onTap = () {
|
recognizer:
|
||||||
loginBloc.launchURL(
|
TapGestureRecognizer()
|
||||||
'https://example.com/terms');
|
..onTap = () {
|
||||||
},
|
loginBloc.launchURL(
|
||||||
|
'https://example.com/terms');
|
||||||
|
},
|
||||||
),
|
),
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: ' (Legal Statement)',
|
text:
|
||||||
style: const TextStyle(color: Colors.black),
|
' (Legal Statement)',
|
||||||
recognizer: TapGestureRecognizer()
|
|
||||||
..onTap = () {
|
|
||||||
loginBloc.launchURL(
|
|
||||||
'https://example.com/legal');
|
|
||||||
},
|
|
||||||
),
|
|
||||||
TextSpan(
|
|
||||||
text: ' (Privacy Statement)',
|
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
color: Colors.black),
|
color: Colors.black),
|
||||||
recognizer: TapGestureRecognizer()
|
recognizer:
|
||||||
..onTap = () {
|
TapGestureRecognizer()
|
||||||
loginBloc.launchURL(
|
..onTap = () {
|
||||||
'https://example.com/privacy');
|
loginBloc.launchURL(
|
||||||
},
|
'https://example.com/legal');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
TextSpan(
|
||||||
|
text:
|
||||||
|
' (Privacy Statement)',
|
||||||
|
style: const TextStyle(
|
||||||
|
color: Colors.black),
|
||||||
|
recognizer:
|
||||||
|
TapGestureRecognizer()
|
||||||
|
..onTap = () {
|
||||||
|
loginBloc.launchURL(
|
||||||
|
'https://example.com/privacy');
|
||||||
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -337,57 +454,87 @@ class _LoginWebPageState extends State<LoginWebPage> {
|
|||||||
),
|
),
|
||||||
const SizedBox(height: 20.0),
|
const SizedBox(height: 20.0),
|
||||||
Row(
|
Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment:
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
CrossAxisAlignment.center,
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width:size.width * 0.2,
|
width: size.width * 0.2,
|
||||||
child: DefaultButton(
|
child: DefaultButton(
|
||||||
enabled: loginBloc.checkValidate,
|
enabled:
|
||||||
child:Text('Sign in',
|
loginBloc.checkValidate,
|
||||||
style: Theme.of(context).textTheme.labelLarge !.copyWith(
|
child: Text('Sign in',
|
||||||
fontSize: 14,
|
style: Theme.of(context)
|
||||||
color:
|
.textTheme
|
||||||
loginBloc.checkValidate ?
|
.labelLarge!
|
||||||
ColorsManager.whiteColors:ColorsManager.whiteColors.withOpacity(0.2),
|
.copyWith(
|
||||||
)
|
fontSize: 14,
|
||||||
),
|
color: loginBloc
|
||||||
|
.checkValidate
|
||||||
|
? ColorsManager
|
||||||
|
.whiteColors
|
||||||
|
: ColorsManager
|
||||||
|
.whiteColors
|
||||||
|
.withOpacity(
|
||||||
|
0.2),
|
||||||
|
)),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
if(loginBloc.loginFormKey.currentState!.validate() ){
|
if (loginBloc.loginFormKey
|
||||||
loginBloc.add(LoginButtonPressed(
|
.currentState!
|
||||||
regionUuid:loginBloc.regionUuid,
|
.validate()) {
|
||||||
username: loginBloc.loginEmailController.text,
|
loginBloc
|
||||||
password: loginBloc.loginPasswordController.text,
|
.add(LoginButtonPressed(
|
||||||
|
regionUuid:
|
||||||
|
loginBloc.regionUuid,
|
||||||
|
username: loginBloc
|
||||||
|
.loginEmailController
|
||||||
|
.text,
|
||||||
|
password: loginBloc
|
||||||
|
.loginPasswordController
|
||||||
|
.text,
|
||||||
));
|
));
|
||||||
}else{
|
} else {
|
||||||
loginBloc.add(ChangeValidateEvent());
|
loginBloc.add(
|
||||||
|
ChangeValidateEvent());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 15.0),
|
const SizedBox(height: 15.0),
|
||||||
Row(
|
Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment:
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
CrossAxisAlignment.center,
|
||||||
children: [ SizedBox(child: Text(loginBloc.validate,
|
mainAxisAlignment:
|
||||||
style: const TextStyle(fontWeight: FontWeight.w700,color: ColorsManager.red ),),)],)
|
MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
child: Text(
|
||||||
|
loginBloc.validate,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
color: ColorsManager.red),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
))),
|
||||||
)),
|
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
],
|
],
|
||||||
),),
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (state is AuthLoading)
|
if (state is AuthLoading)
|
||||||
const Center(child: CircularProgressIndicator())
|
const Center(child: CircularProgressIndicator())
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -38,60 +38,58 @@ class DefaultButton extends StatelessWidget {
|
|||||||
style: isSecondary
|
style: isSecondary
|
||||||
? null
|
? null
|
||||||
: customButtonStyle ??
|
: customButtonStyle ??
|
||||||
ButtonStyle(
|
ButtonStyle(
|
||||||
textStyle: MaterialStateProperty.all(
|
textStyle: MaterialStateProperty.all(
|
||||||
customTextStyle
|
customTextStyle ??
|
||||||
?? Theme.of(context).textTheme.bodySmall!.copyWith(
|
Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
color: foregroundColor,
|
color: foregroundColor,
|
||||||
fontWeight: FontWeight.normal
|
fontWeight: FontWeight.normal),
|
||||||
),
|
),
|
||||||
),
|
foregroundColor: MaterialStateProperty.all(
|
||||||
|
isSecondary
|
||||||
foregroundColor: MaterialStateProperty.all(
|
? Colors.black
|
||||||
isSecondary
|
: enabled
|
||||||
? Colors.black
|
? foregroundColor ?? Colors.white
|
||||||
: enabled
|
: Colors.black,
|
||||||
? foregroundColor ?? Colors.white
|
),
|
||||||
: Colors.black,
|
backgroundColor: MaterialStateProperty.resolveWith<Color>(
|
||||||
),
|
|
||||||
backgroundColor: MaterialStateProperty.resolveWith<Color>(
|
|
||||||
(Set<MaterialState> states) {
|
(Set<MaterialState> states) {
|
||||||
return enabled
|
return enabled
|
||||||
? backgroundColor ?? ColorsManager.primaryColor
|
? backgroundColor ?? ColorsManager.primaryColor
|
||||||
: Colors.black.withOpacity(0.2);
|
: Colors.black.withOpacity(0.2);
|
||||||
}),
|
}),
|
||||||
shape: MaterialStateProperty.all(
|
shape: MaterialStateProperty.all(
|
||||||
RoundedRectangleBorder(
|
RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(borderRadius ?? 20),
|
borderRadius: BorderRadius.circular(borderRadius ?? 20),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
fixedSize: MaterialStateProperty.all(
|
||||||
|
const Size.fromHeight(50),
|
||||||
|
),
|
||||||
|
padding: MaterialStateProperty.all(
|
||||||
|
EdgeInsets.all(padding ?? 10),
|
||||||
|
),
|
||||||
|
minimumSize: MaterialStateProperty.all(
|
||||||
|
const Size.fromHeight(50),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
fixedSize: MaterialStateProperty.all(
|
|
||||||
const Size.fromHeight(50),
|
|
||||||
),
|
|
||||||
padding: MaterialStateProperty.all(
|
|
||||||
EdgeInsets.all(padding ?? 10),
|
|
||||||
),
|
|
||||||
minimumSize: MaterialStateProperty.all(
|
|
||||||
const Size.fromHeight(50),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: height ?? 50,
|
height: height ?? 50,
|
||||||
child: Center(
|
child: Center(
|
||||||
child: isLoading
|
child: isLoading
|
||||||
? const SizedBox.square(
|
? const SizedBox.square(
|
||||||
dimension: 24,
|
dimension: 24,
|
||||||
child: CircularProgressIndicator(
|
child: CircularProgressIndicator(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: isDone
|
: isDone
|
||||||
? const Icon(
|
? const Icon(
|
||||||
Icons.check_circle_outline,
|
Icons.check_circle_outline,
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
)
|
)
|
||||||
: child,
|
: child,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -11,7 +11,8 @@ Future<void> showCustomDialog({
|
|||||||
double? iconHeight,
|
double? iconHeight,
|
||||||
double? iconWidth,
|
double? iconWidth,
|
||||||
VoidCallback? onOkPressed,
|
VoidCallback? onOkPressed,
|
||||||
bool barrierDismissible = false, required actions,
|
bool barrierDismissible = false,
|
||||||
|
required actions,
|
||||||
}) {
|
}) {
|
||||||
return showDialog(
|
return showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
|
@ -224,8 +224,14 @@ class _DynamicTableState extends State<DynamicTable> {
|
|||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: Text(
|
child: Text(
|
||||||
content,
|
content,
|
||||||
style: const TextStyle(
|
style: TextStyle(
|
||||||
color: Colors.black, fontSize: 10, fontWeight: FontWeight.w400),
|
color: content == 'Online'
|
||||||
|
? ColorsManager.green
|
||||||
|
: content == 'Offline'
|
||||||
|
? ColorsManager.red
|
||||||
|
: Colors.black,
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: FontWeight.w400),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
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/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/style.dart';
|
import 'package:syncrow_web/utils/style.dart';
|
||||||
|
|
||||||
class DateTimeWebWidget extends StatelessWidget {
|
class DateTimeWebWidget extends StatelessWidget {
|
||||||
@ -23,8 +22,8 @@ class DateTimeWebWidget extends StatelessWidget {
|
|||||||
final String firstString;
|
final String firstString;
|
||||||
final String secondString;
|
final String secondString;
|
||||||
final String icon;
|
final String icon;
|
||||||
final Function()? startTime;
|
final Function()? startTime;
|
||||||
final Function()? endTime;
|
final Function()? endTime;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -32,61 +31,84 @@ class DateTimeWebWidget extends StatelessWidget {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
if(isRequired)
|
if (isRequired)
|
||||||
Text(
|
Text(
|
||||||
'* ',
|
'* ',
|
||||||
style: Theme.of(context)
|
style: Theme.of(context)
|
||||||
.textTheme
|
.textTheme
|
||||||
.bodyMedium!
|
.bodyMedium!
|
||||||
.copyWith(color: Colors.red),
|
.copyWith(color: Colors.red),
|
||||||
),
|
),
|
||||||
Text(title??'' ,
|
Text(
|
||||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
title,
|
||||||
color: Colors.black,fontSize: 13),),
|
style: Theme.of(context)
|
||||||
],
|
.textTheme
|
||||||
),
|
.bodySmall!
|
||||||
const SizedBox(height: 8,),
|
.copyWith(color: Colors.black, fontSize: 13),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 8,
|
||||||
|
),
|
||||||
Container(
|
Container(
|
||||||
height:size.height * 0.055 ,
|
height: size.height * 0.055,
|
||||||
padding: EdgeInsets.only(top: 10,bottom: 10,right: 30,left: 10),
|
padding:
|
||||||
|
const EdgeInsets.only(top: 10, bottom: 10, right: 30, left: 10),
|
||||||
decoration: containerDecoration,
|
decoration: containerDecoration,
|
||||||
child: FittedBox(
|
child: FittedBox(
|
||||||
child: Column(
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Row(
|
InkWell(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
onTap: startTime,
|
||||||
children: [
|
child: FittedBox(
|
||||||
InkWell(
|
child: Text(
|
||||||
onTap: startTime,
|
firstString,
|
||||||
child: FittedBox(
|
style: Theme.of(context)
|
||||||
child: Text(firstString,
|
.textTheme
|
||||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
.bodySmall!
|
||||||
color: ColorsManager.grayColor,fontSize: 12,fontWeight: FontWeight.w400),),
|
.copyWith(
|
||||||
)
|
color: ColorsManager.grayColor,
|
||||||
),
|
fontSize: 12,
|
||||||
SizedBox(width: 30,),
|
fontWeight: FontWeight.w400),
|
||||||
const Icon(Icons.arrow_right_alt),
|
),
|
||||||
SizedBox(width: 30,),
|
)),
|
||||||
|
const SizedBox(
|
||||||
InkWell(
|
width: 30,
|
||||||
onTap:endTime,
|
),
|
||||||
child: FittedBox(
|
const Icon(Icons.arrow_right_alt),
|
||||||
child: Text(secondString,
|
const SizedBox(
|
||||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
width: 30,
|
||||||
color: ColorsManager.grayColor,fontSize: 12,fontWeight: FontWeight.w400),
|
),
|
||||||
),
|
InkWell(
|
||||||
)),
|
onTap: endTime,
|
||||||
SizedBox(width: 30,),
|
child: FittedBox(
|
||||||
|
child: Text(
|
||||||
SvgPicture.asset(
|
secondString,
|
||||||
icon,
|
style: Theme.of(context)
|
||||||
),
|
.textTheme
|
||||||
],
|
.bodySmall!
|
||||||
|
.copyWith(
|
||||||
|
color: ColorsManager.grayColor,
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: FontWeight.w400),
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
const SizedBox(
|
||||||
|
width: 30,
|
||||||
|
),
|
||||||
|
SvgPicture.asset(
|
||||||
|
icon,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)),
|
),
|
||||||
|
],
|
||||||
|
)),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
@ -4,7 +4,7 @@ import 'package:syncrow_web/utils/constants/assets.dart';
|
|||||||
|
|
||||||
class FirstLayer extends StatelessWidget {
|
class FirstLayer extends StatelessWidget {
|
||||||
final Widget? second;
|
final Widget? second;
|
||||||
const FirstLayer({super.key,this.second});
|
const FirstLayer({super.key, this.second});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class HourPickerDialog extends StatefulWidget {
|
class HourPickerDialog extends StatefulWidget {
|
||||||
@ -17,7 +15,9 @@ class _HourPickerDialogState extends State<HourPickerDialog> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_selectedHour = widget.initialTime.hour > 12 ? widget.initialTime.hour - 12 : widget.initialTime.hour;
|
_selectedHour = widget.initialTime.hour > 12
|
||||||
|
? widget.initialTime.hour - 12
|
||||||
|
: widget.initialTime.hour;
|
||||||
_isPm = widget.initialTime.period == DayPeriod.pm;
|
_isPm = widget.initialTime.period == DayPeriod.pm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,7 +35,6 @@ class InfoDialog extends StatelessWidget {
|
|||||||
width: 35,
|
width: 35,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
title,
|
title,
|
||||||
style: Theme.of(context).textTheme.headlineLarge!.copyWith(
|
style: Theme.of(context).textTheme.headlineLarge!.copyWith(
|
||||||
|
@ -8,37 +8,25 @@ class StatefulTextField extends StatefulWidget {
|
|||||||
this.hintText = 'Please enter',
|
this.hintText = 'Please enter',
|
||||||
required this.width,
|
required this.width,
|
||||||
this.elevation = 0,
|
this.elevation = 0,
|
||||||
|
required this.controller, // Add the controller
|
||||||
});
|
});
|
||||||
|
|
||||||
final String title;
|
final String title;
|
||||||
final String hintText;
|
final String hintText;
|
||||||
final double width;
|
final double width;
|
||||||
final double elevation;
|
final double elevation;
|
||||||
|
final TextEditingController controller;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<StatefulTextField> createState() => _StatefulTextFieldState();
|
State<StatefulTextField> createState() => _StatefulTextFieldState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _StatefulTextFieldState extends State<StatefulTextField> {
|
class _StatefulTextFieldState extends State<StatefulTextField> {
|
||||||
late TextEditingController _controller;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
_controller = TextEditingController();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
_controller.dispose();
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return CustomTextField(
|
return CustomTextField(
|
||||||
title: widget.title,
|
title: widget.title,
|
||||||
controller: _controller,
|
controller: widget.controller,
|
||||||
hintText: widget.hintText,
|
hintText: widget.hintText,
|
||||||
width: widget.width,
|
width: widget.width,
|
||||||
elevation: widget.elevation,
|
elevation: widget.elevation,
|
||||||
|
@ -1,23 +1,22 @@
|
|||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
import 'package:syncrow_web/utils/style.dart';
|
import 'package:syncrow_web/utils/style.dart';
|
||||||
|
|
||||||
class CustomWebTextField extends StatelessWidget {
|
class CustomWebTextField extends StatelessWidget {
|
||||||
const CustomWebTextField({
|
const CustomWebTextField({
|
||||||
super.key,
|
super.key,
|
||||||
required this.isRequired,
|
required this.isRequired,
|
||||||
required this.textFieldName,
|
required this.textFieldName,
|
||||||
required this.controller,
|
required this.controller,
|
||||||
this.description,
|
this.description,
|
||||||
this.validator,
|
this.validator,
|
||||||
});
|
});
|
||||||
|
|
||||||
final bool isRequired;
|
final bool isRequired;
|
||||||
final String textFieldName;
|
final String textFieldName;
|
||||||
final String? description;
|
final String? description;
|
||||||
final TextEditingController? controller;
|
final TextEditingController? controller;
|
||||||
final String? Function(String?)? validator;
|
final String? Function(String?)? validator;
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -28,51 +27,59 @@ class CustomWebTextField extends StatelessWidget {
|
|||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
if(isRequired)
|
if (isRequired)
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Text('* ',
|
Text(
|
||||||
style: Theme.of(context)
|
'* ',
|
||||||
.textTheme.bodyMedium!
|
style: Theme.of(context)
|
||||||
.copyWith(color: Colors.red),
|
.textTheme
|
||||||
),
|
.bodyMedium!
|
||||||
Text(textFieldName, style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
.copyWith(color: Colors.red),
|
||||||
color: Colors.black,fontSize: 13),),
|
),
|
||||||
],
|
Text(
|
||||||
|
textFieldName,
|
||||||
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodySmall!
|
||||||
|
.copyWith(color: Colors.black, fontSize: 13),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
width: 10,
|
||||||
),
|
),
|
||||||
const SizedBox(width: 10,),
|
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text(
|
child: Text(
|
||||||
description??'',
|
description ?? '',
|
||||||
style: Theme.of(context)
|
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||||
.textTheme.bodySmall!
|
fontSize: 9,
|
||||||
.copyWith(fontSize: 9,
|
|
||||||
fontWeight: FontWeight.w400,
|
fontWeight: FontWeight.w400,
|
||||||
color: ColorsManager.textGray),
|
color: ColorsManager.textGray),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 7,),
|
const SizedBox(
|
||||||
|
height: 7,
|
||||||
|
),
|
||||||
Container(
|
Container(
|
||||||
decoration: containerDecoration.copyWith(
|
decoration: containerDecoration
|
||||||
color: const Color(0xFFF5F6F7),
|
.copyWith(color: const Color(0xFFF5F6F7), boxShadow: [
|
||||||
boxShadow: [
|
BoxShadow(
|
||||||
BoxShadow(
|
color: Colors.grey.withOpacity(0.3),
|
||||||
color: Colors.grey.withOpacity(0.3),
|
spreadRadius: 2,
|
||||||
spreadRadius:2,
|
blurRadius: 3,
|
||||||
blurRadius: 3,
|
offset: const Offset(1, 1), // changes position of shadow
|
||||||
offset: const Offset(1, 1), // changes position of shadow
|
),
|
||||||
),
|
]),
|
||||||
]
|
|
||||||
),
|
|
||||||
child: TextFormField(
|
child: TextFormField(
|
||||||
validator: validator,
|
validator: validator,
|
||||||
controller: controller,
|
controller: controller,
|
||||||
style: const TextStyle(color: Colors.black),
|
style: const TextStyle(color: Colors.black),
|
||||||
decoration: textBoxDecoration()!
|
decoration: textBoxDecoration()!.copyWith(
|
||||||
.copyWith(
|
errorStyle:
|
||||||
errorStyle: const TextStyle(height: 0), // Hide the error text space
|
const TextStyle(height: 0), // Hide the error text space
|
||||||
|
|
||||||
hintText: 'Please enter'),
|
hintText: 'Please enter'),
|
||||||
),
|
),
|
||||||
|
@ -1,13 +1,130 @@
|
|||||||
import 'package:bloc/bloc.dart';
|
import 'package:bloc/bloc.dart';
|
||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:syncrow_web/pages/device_managment/models/devices_model.dart';
|
||||||
|
import 'package:syncrow_web/services/devices_mang_api.dart';
|
||||||
|
|
||||||
part 'device_managment_event.dart';
|
part 'device_managment_event.dart';
|
||||||
part 'device_managment_state.dart';
|
part 'device_managment_state.dart';
|
||||||
|
|
||||||
class DeviceManagmentBloc extends Bloc<DeviceManagmentEvent, DeviceManagmentState> {
|
class DeviceManagementBloc
|
||||||
DeviceManagmentBloc() : super(DeviceManagmentInitial()) {
|
extends Bloc<DeviceManagementEvent, DeviceManagementState> {
|
||||||
on<DeviceManagmentEvent>((event, emit) {
|
int _selectedIndex = 0;
|
||||||
// TODO: implement event handler
|
List<AllDevicesModel> _devices = [];
|
||||||
});
|
int _onlineCount = 0;
|
||||||
|
int _offlineCount = 0;
|
||||||
|
int _lowBatteryCount = 0;
|
||||||
|
|
||||||
|
DeviceManagementBloc() : super(DeviceManagementInitial()) {
|
||||||
|
on<FetchDevices>(_onFetchDevices);
|
||||||
|
on<FilterDevices>(_onFilterDevices);
|
||||||
|
on<SelectedFilterChanged>(_onSelectedFilterChanged);
|
||||||
|
on<SearchDevices>(_onSearchDevices);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _onFetchDevices(
|
||||||
|
FetchDevices event, Emitter<DeviceManagementState> emit) async {
|
||||||
|
emit(DeviceManagementLoading());
|
||||||
|
try {
|
||||||
|
final devices = await DevicesManagementApi().fetchDevices();
|
||||||
|
_devices = devices;
|
||||||
|
_calculateDeviceCounts();
|
||||||
|
emit(DeviceManagementLoaded(
|
||||||
|
devices: devices,
|
||||||
|
selectedIndex: _selectedIndex,
|
||||||
|
onlineCount: _onlineCount,
|
||||||
|
offlineCount: _offlineCount,
|
||||||
|
lowBatteryCount: _lowBatteryCount,
|
||||||
|
));
|
||||||
|
} catch (e) {
|
||||||
|
emit(DeviceManagementInitial());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onFilterDevices(
|
||||||
|
FilterDevices event, Emitter<DeviceManagementState> emit) {
|
||||||
|
if (_devices.isNotEmpty) {
|
||||||
|
final filteredDevices = _devices.where((device) {
|
||||||
|
switch (event.filter) {
|
||||||
|
case 'Online':
|
||||||
|
return device.online == true;
|
||||||
|
case 'Offline':
|
||||||
|
return device.online == false;
|
||||||
|
case 'Low Battery':
|
||||||
|
return device.batteryLevel != null && device.batteryLevel! < 20;
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}).toList();
|
||||||
|
emit(DeviceManagementFiltered(
|
||||||
|
filteredDevices: filteredDevices,
|
||||||
|
selectedIndex: _selectedIndex,
|
||||||
|
onlineCount: _onlineCount,
|
||||||
|
offlineCount: _offlineCount,
|
||||||
|
lowBatteryCount: _lowBatteryCount,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onSelectedFilterChanged(
|
||||||
|
SelectedFilterChanged event, Emitter<DeviceManagementState> emit) {
|
||||||
|
_selectedIndex = event.selectedIndex;
|
||||||
|
add(FilterDevices(_getFilterFromIndex(_selectedIndex)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void _calculateDeviceCounts() {
|
||||||
|
_onlineCount = _devices.where((device) => device.online == true).length;
|
||||||
|
_offlineCount = _devices.where((device) => device.online == false).length;
|
||||||
|
_lowBatteryCount = _devices
|
||||||
|
.where((device) =>
|
||||||
|
device.batteryLevel != null && device.batteryLevel! < 20)
|
||||||
|
.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
String _getFilterFromIndex(int index) {
|
||||||
|
switch (index) {
|
||||||
|
case 1:
|
||||||
|
return 'Online';
|
||||||
|
case 2:
|
||||||
|
return 'Offline';
|
||||||
|
case 3:
|
||||||
|
return 'Low Battery';
|
||||||
|
default:
|
||||||
|
return 'All';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onSearchDevices(
|
||||||
|
SearchDevices event, Emitter<DeviceManagementState> emit) {
|
||||||
|
if (_devices.isNotEmpty) {
|
||||||
|
final filteredDevices = _devices.where((device) {
|
||||||
|
final matchesCommunity = event.community == null ||
|
||||||
|
event.community!.isEmpty ||
|
||||||
|
(device.room?.name
|
||||||
|
?.toLowerCase()
|
||||||
|
.contains(event.community!.toLowerCase()) ??
|
||||||
|
false);
|
||||||
|
final matchesUnit = event.unitName == null ||
|
||||||
|
event.unitName!.isEmpty ||
|
||||||
|
(device.unit?.name
|
||||||
|
?.toLowerCase()
|
||||||
|
.contains(event.unitName!.toLowerCase()) ??
|
||||||
|
false);
|
||||||
|
final matchesProductName = event.productName == null ||
|
||||||
|
event.productName!.isEmpty ||
|
||||||
|
(device.name
|
||||||
|
?.toLowerCase()
|
||||||
|
.contains(event.productName!.toLowerCase()) ??
|
||||||
|
false);
|
||||||
|
return matchesCommunity && matchesUnit && matchesProductName;
|
||||||
|
}).toList();
|
||||||
|
|
||||||
|
emit(DeviceManagementFiltered(
|
||||||
|
filteredDevices: filteredDevices,
|
||||||
|
selectedIndex: _selectedIndex,
|
||||||
|
onlineCount: _onlineCount,
|
||||||
|
offlineCount: _offlineCount,
|
||||||
|
lowBatteryCount: _lowBatteryCount,
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,43 @@
|
|||||||
part of 'device_managment_bloc.dart';
|
part of 'device_managment_bloc.dart';
|
||||||
|
|
||||||
sealed class DeviceManagmentEvent extends Equatable {
|
abstract class DeviceManagementEvent extends Equatable {
|
||||||
const DeviceManagmentEvent();
|
const DeviceManagementEvent();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [];
|
List<Object?> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
class FetchDevices extends DeviceManagementEvent {}
|
||||||
|
|
||||||
|
class FilterDevices extends DeviceManagementEvent {
|
||||||
|
final String filter;
|
||||||
|
|
||||||
|
const FilterDevices(this.filter);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [filter];
|
||||||
|
}
|
||||||
|
|
||||||
|
class SelectedFilterChanged extends DeviceManagementEvent {
|
||||||
|
final int selectedIndex;
|
||||||
|
|
||||||
|
const SelectedFilterChanged(this.selectedIndex);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [selectedIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
class SearchDevices extends DeviceManagementEvent {
|
||||||
|
final String? community;
|
||||||
|
final String? unitName;
|
||||||
|
final String? productName;
|
||||||
|
|
||||||
|
const SearchDevices({
|
||||||
|
this.community,
|
||||||
|
this.unitName,
|
||||||
|
this.productName,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [community, unitName, productName];
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,57 @@
|
|||||||
part of 'device_managment_bloc.dart';
|
part of 'device_managment_bloc.dart';
|
||||||
|
|
||||||
sealed class DeviceManagmentState extends Equatable {
|
abstract class DeviceManagementState extends Equatable {
|
||||||
const DeviceManagmentState();
|
const DeviceManagementState();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [];
|
List<Object?> get props => [];
|
||||||
}
|
}
|
||||||
|
|
||||||
final class DeviceManagmentInitial extends DeviceManagmentState {}
|
class DeviceManagementInitial extends DeviceManagementState {}
|
||||||
|
|
||||||
|
class DeviceManagementLoading extends DeviceManagementState {}
|
||||||
|
|
||||||
|
class DeviceManagementLoaded extends DeviceManagementState {
|
||||||
|
final List<AllDevicesModel> devices;
|
||||||
|
final int selectedIndex;
|
||||||
|
final int onlineCount;
|
||||||
|
final int offlineCount;
|
||||||
|
final int lowBatteryCount;
|
||||||
|
|
||||||
|
const DeviceManagementLoaded({
|
||||||
|
required this.devices,
|
||||||
|
required this.selectedIndex,
|
||||||
|
required this.onlineCount,
|
||||||
|
required this.offlineCount,
|
||||||
|
required this.lowBatteryCount,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props =>
|
||||||
|
[devices, selectedIndex, onlineCount, offlineCount, lowBatteryCount];
|
||||||
|
}
|
||||||
|
|
||||||
|
class DeviceManagementFiltered extends DeviceManagementState {
|
||||||
|
final List<AllDevicesModel> filteredDevices;
|
||||||
|
final int selectedIndex;
|
||||||
|
final int onlineCount;
|
||||||
|
final int offlineCount;
|
||||||
|
final int lowBatteryCount;
|
||||||
|
|
||||||
|
const DeviceManagementFiltered({
|
||||||
|
required this.filteredDevices,
|
||||||
|
required this.selectedIndex,
|
||||||
|
required this.onlineCount,
|
||||||
|
required this.offlineCount,
|
||||||
|
required this.lowBatteryCount,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [
|
||||||
|
filteredDevices,
|
||||||
|
selectedIndex,
|
||||||
|
onlineCount,
|
||||||
|
offlineCount,
|
||||||
|
lowBatteryCount
|
||||||
|
];
|
||||||
|
}
|
||||||
|
157
lib/pages/device_managment/models/devices_model.dart
Normal file
157
lib/pages/device_managment/models/devices_model.dart
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
import 'package:syncrow_web/pages/device_managment/models/room.dart';
|
||||||
|
import 'package:syncrow_web/pages/device_managment/models/unit.dart';
|
||||||
|
|
||||||
|
class AllDevicesModel {
|
||||||
|
/*
|
||||||
|
{
|
||||||
|
"room": {
|
||||||
|
"uuid": "75ea7d60-5104-4726-b5f8-ea426c0c6a1b",
|
||||||
|
"name": "Room 1"
|
||||||
|
},
|
||||||
|
"unit": {
|
||||||
|
"uuid": "04fd1dcf-f24a-40db-970d-d0be884ed30f",
|
||||||
|
"name": "unit 1"
|
||||||
|
},
|
||||||
|
"productUuid": "894aad5c-ce03-423a-9d61-2fd0c3f67ebf",
|
||||||
|
"productType": "3G",
|
||||||
|
"permissionType": "CONTROLLABLE",
|
||||||
|
"activeTime": 1722173778,
|
||||||
|
"category": "kg",
|
||||||
|
"categoryName": "Switch",
|
||||||
|
"createTime": 1722173778,
|
||||||
|
"gatewayId": "bf0294123ed2c19067skrk",
|
||||||
|
"icon": "smart/icon/bay1642572935385vcsA/2b1f5efbaa5bbf81c3164fa312cf2032.png",
|
||||||
|
"ip": "",
|
||||||
|
"lat": "31.97",
|
||||||
|
"localKey": "T/39+<l/![iv>:9M",
|
||||||
|
"lon": "35.89",
|
||||||
|
"model": "S01ZLSWBSA3",
|
||||||
|
"name": "3 Gang Button Switch L-L",
|
||||||
|
"nodeId": "60a423fffed5a7f6",
|
||||||
|
"online": true,
|
||||||
|
"ownerId": "199200732",
|
||||||
|
"sub": true,
|
||||||
|
"timeZone": "+03:00",
|
||||||
|
"updateTime": 1723626515,
|
||||||
|
"uuid": "5b31dae4-ce9c-4c70-b52b-7e15011163bf"
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
DevicesModelRoom? room;
|
||||||
|
DevicesModelUnit? unit;
|
||||||
|
String? productUuid;
|
||||||
|
String? productType;
|
||||||
|
String? permissionType;
|
||||||
|
int? activeTime;
|
||||||
|
String? category;
|
||||||
|
String? categoryName;
|
||||||
|
int? createTime;
|
||||||
|
String? gatewayId;
|
||||||
|
String? icon;
|
||||||
|
String? ip;
|
||||||
|
String? lat;
|
||||||
|
String? localKey;
|
||||||
|
String? lon;
|
||||||
|
String? model;
|
||||||
|
String? name;
|
||||||
|
String? nodeId;
|
||||||
|
bool? online;
|
||||||
|
String? ownerId;
|
||||||
|
bool? sub;
|
||||||
|
String? timeZone;
|
||||||
|
int? updateTime;
|
||||||
|
String? uuid;
|
||||||
|
int? batteryLevel;
|
||||||
|
|
||||||
|
AllDevicesModel({
|
||||||
|
this.room,
|
||||||
|
this.unit,
|
||||||
|
this.productUuid,
|
||||||
|
this.productType,
|
||||||
|
this.permissionType,
|
||||||
|
this.activeTime,
|
||||||
|
this.category,
|
||||||
|
this.categoryName,
|
||||||
|
this.createTime,
|
||||||
|
this.gatewayId,
|
||||||
|
this.icon,
|
||||||
|
this.ip,
|
||||||
|
this.lat,
|
||||||
|
this.localKey,
|
||||||
|
this.lon,
|
||||||
|
this.model,
|
||||||
|
this.name,
|
||||||
|
this.nodeId,
|
||||||
|
this.online,
|
||||||
|
this.ownerId,
|
||||||
|
this.sub,
|
||||||
|
this.timeZone,
|
||||||
|
this.updateTime,
|
||||||
|
this.uuid,
|
||||||
|
this.batteryLevel,
|
||||||
|
});
|
||||||
|
AllDevicesModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
room = (json['room'] != null && (json['room'] is Map))
|
||||||
|
? DevicesModelRoom.fromJson(json['room'])
|
||||||
|
: null;
|
||||||
|
unit = (json['unit'] != null && (json['unit'] is Map))
|
||||||
|
? DevicesModelUnit.fromJson(json['unit'])
|
||||||
|
: null;
|
||||||
|
productUuid = json['productUuid']?.toString();
|
||||||
|
productType = json['productType']?.toString();
|
||||||
|
permissionType = json['permissionType']?.toString();
|
||||||
|
activeTime = int.tryParse(json['activeTime']?.toString() ?? '');
|
||||||
|
category = json['category']?.toString();
|
||||||
|
categoryName = json['categoryName']?.toString();
|
||||||
|
createTime = int.tryParse(json['createTime']?.toString() ?? '');
|
||||||
|
gatewayId = json['gatewayId']?.toString();
|
||||||
|
icon = json['icon']?.toString();
|
||||||
|
ip = json['ip']?.toString();
|
||||||
|
lat = json['lat']?.toString();
|
||||||
|
localKey = json['localKey']?.toString();
|
||||||
|
lon = json['lon']?.toString();
|
||||||
|
model = json['model']?.toString();
|
||||||
|
name = json['name']?.toString();
|
||||||
|
nodeId = json['nodeId']?.toString();
|
||||||
|
online = json['online'];
|
||||||
|
ownerId = json['ownerId']?.toString();
|
||||||
|
sub = json['sub'];
|
||||||
|
timeZone = json['timeZone']?.toString();
|
||||||
|
updateTime = int.tryParse(json['updateTime']?.toString() ?? '');
|
||||||
|
uuid = json['uuid']?.toString();
|
||||||
|
batteryLevel = int.tryParse(json['batteryLevel']?.toString() ?? '');
|
||||||
|
}
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final data = <String, dynamic>{};
|
||||||
|
if (room != null) {
|
||||||
|
data['room'] = room!.toJson();
|
||||||
|
}
|
||||||
|
if (unit != null) {
|
||||||
|
data['unit'] = unit!.toJson();
|
||||||
|
}
|
||||||
|
data['productUuid'] = productUuid;
|
||||||
|
data['productType'] = productType;
|
||||||
|
data['permissionType'] = permissionType;
|
||||||
|
data['activeTime'] = activeTime;
|
||||||
|
data['category'] = category;
|
||||||
|
data['categoryName'] = categoryName;
|
||||||
|
data['createTime'] = createTime;
|
||||||
|
data['gatewayId'] = gatewayId;
|
||||||
|
data['icon'] = icon;
|
||||||
|
data['ip'] = ip;
|
||||||
|
data['lat'] = lat;
|
||||||
|
data['localKey'] = localKey;
|
||||||
|
data['lon'] = lon;
|
||||||
|
data['model'] = model;
|
||||||
|
data['name'] = name;
|
||||||
|
data['nodeId'] = nodeId;
|
||||||
|
data['online'] = online;
|
||||||
|
data['ownerId'] = ownerId;
|
||||||
|
data['sub'] = sub;
|
||||||
|
data['timeZone'] = timeZone;
|
||||||
|
data['updateTime'] = updateTime;
|
||||||
|
data['uuid'] = uuid;
|
||||||
|
data['batteryLevel'] = batteryLevel;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
26
lib/pages/device_managment/models/room.dart
Normal file
26
lib/pages/device_managment/models/room.dart
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
class DevicesModelRoom {
|
||||||
|
/*
|
||||||
|
{
|
||||||
|
"uuid": "75ea7d60-5104-4726-b5f8-ea426c0c6a1b",
|
||||||
|
"name": "Room 1"
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
String? uuid;
|
||||||
|
String? name;
|
||||||
|
|
||||||
|
DevicesModelRoom({
|
||||||
|
this.uuid,
|
||||||
|
this.name,
|
||||||
|
});
|
||||||
|
DevicesModelRoom.fromJson(Map<String, dynamic> json) {
|
||||||
|
uuid = json['uuid']?.toString();
|
||||||
|
name = json['name']?.toString();
|
||||||
|
}
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final data = <String, dynamic>{};
|
||||||
|
data['uuid'] = uuid;
|
||||||
|
data['name'] = name;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
26
lib/pages/device_managment/models/unit.dart
Normal file
26
lib/pages/device_managment/models/unit.dart
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
class DevicesModelUnit {
|
||||||
|
/*
|
||||||
|
{
|
||||||
|
"uuid": "04fd1dcf-f24a-40db-970d-d0be884ed30f",
|
||||||
|
"name": "unit 1"
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
String? uuid;
|
||||||
|
String? name;
|
||||||
|
|
||||||
|
DevicesModelUnit({
|
||||||
|
this.uuid,
|
||||||
|
this.name,
|
||||||
|
});
|
||||||
|
DevicesModelUnit.fromJson(Map<String, dynamic> json) {
|
||||||
|
uuid = json['uuid']?.toString();
|
||||||
|
name = json['name']?.toString();
|
||||||
|
}
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final data = <String, dynamic>{};
|
||||||
|
data['uuid'] = uuid;
|
||||||
|
data['name'] = name;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/device_managment/bloc/device_managment_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/widgets/device_managment_body.dart';
|
import 'package:syncrow_web/pages/device_managment/widgets/device_managment_body.dart';
|
||||||
import 'package:syncrow_web/web_layout/web_scaffold.dart';
|
import 'package:syncrow_web/web_layout/web_scaffold.dart';
|
||||||
|
|
||||||
@ -7,17 +9,31 @@ class DeviceManagementPage extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return WebScaffold(
|
return BlocProvider(
|
||||||
enableMenuSideba: true,
|
create: (context) => DeviceManagementBloc()..add(FetchDevices()),
|
||||||
appBarTitle: Row(
|
child: WebScaffold(
|
||||||
children: [
|
appBarTitle: Text(
|
||||||
Text(
|
'Device Management',
|
||||||
'Device Management',
|
style: Theme.of(context).textTheme.headlineLarge,
|
||||||
style: Theme.of(context).textTheme.headlineLarge,
|
),
|
||||||
)
|
enableMenuSideba: true,
|
||||||
],
|
scaffoldBody: BlocBuilder<DeviceManagementBloc, DeviceManagementState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
if (state is DeviceManagementLoading) {
|
||||||
|
return const Center(child: CircularProgressIndicator());
|
||||||
|
} else if (state is DeviceManagementLoaded ||
|
||||||
|
state is DeviceManagementFiltered) {
|
||||||
|
final devices = state is DeviceManagementLoaded
|
||||||
|
? state.devices
|
||||||
|
: (state as DeviceManagementFiltered).filteredDevices;
|
||||||
|
|
||||||
|
return DeviceManagementBody(devices: devices);
|
||||||
|
} else {
|
||||||
|
return const Center(child: Text('No Devices Found'));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
scaffoldBody: const DeviceManagementBody(),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,92 +1,94 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:syncrow_web/core/extension/build_context_x.dart';
|
import 'package:syncrow_web/core/extension/build_context_x.dart';
|
||||||
import 'package:syncrow_web/pages/common/buttons/search_reset_buttons.dart';
|
import 'package:syncrow_web/pages/common/buttons/default_button.dart';
|
||||||
import 'package:syncrow_web/pages/common/custom_table.dart';
|
import 'package:syncrow_web/pages/common/custom_table.dart';
|
||||||
import 'package:syncrow_web/pages/common/filter/filter_widget.dart';
|
import 'package:syncrow_web/pages/common/filter/filter_widget.dart';
|
||||||
import 'package:syncrow_web/pages/common/text_field/custom_text_field.dart';
|
import 'package:syncrow_web/pages/device_managment/bloc/device_managment_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/device_managment/models/devices_model.dart';
|
||||||
|
import 'package:syncrow_web/pages/device_managment/widgets/device_search_filters.dart';
|
||||||
|
import 'package:syncrow_web/utils/format_date_time.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';
|
||||||
import 'package:syncrow_web/utils/style.dart';
|
import 'package:syncrow_web/utils/style.dart';
|
||||||
|
|
||||||
class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
|
class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
|
||||||
const DeviceManagementBody({super.key});
|
const DeviceManagementBody({super.key, required this.devices});
|
||||||
|
|
||||||
|
final List<AllDevicesModel> devices;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return BlocBuilder<DeviceManagementBloc, DeviceManagementState>(
|
||||||
padding: const EdgeInsets.all(30),
|
builder: (context, state) {
|
||||||
height: context.screenHeight,
|
List<AllDevicesModel> devicesToShow = [];
|
||||||
width: context.screenWidth,
|
int selectedIndex = 0;
|
||||||
child: Column(
|
int onlineCount = 0;
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
int offlineCount = 0;
|
||||||
children: [
|
int lowBatteryCount = 0;
|
||||||
FilterWidget(
|
|
||||||
size: context.screenSize,
|
if (state is DeviceManagementLoaded) {
|
||||||
tabs: ['All', 'Online', 'Offline', 'Low Battery'],
|
devicesToShow = state.devices;
|
||||||
selectedIndex: 0,
|
selectedIndex = state.selectedIndex;
|
||||||
onTabChanged: (index) {},
|
onlineCount = state.onlineCount;
|
||||||
),
|
offlineCount = state.offlineCount;
|
||||||
const SizedBox(
|
lowBatteryCount = state.lowBatteryCount;
|
||||||
height: 20,
|
} else if (state is DeviceManagementFiltered) {
|
||||||
),
|
devicesToShow = state.filteredDevices;
|
||||||
if (isLargeScreenSize(context)) ...[
|
selectedIndex = state.selectedIndex;
|
||||||
Row(
|
onlineCount = state.onlineCount;
|
||||||
children: [
|
offlineCount = state.offlineCount;
|
||||||
const StatefulTextField(
|
lowBatteryCount = state.lowBatteryCount;
|
||||||
title: "Community",
|
}
|
||||||
width: 200,
|
|
||||||
elevation: 2,
|
// Create tab labels with counts
|
||||||
|
final tabs = [
|
||||||
|
'All (${devices.length})',
|
||||||
|
'Online ($onlineCount)',
|
||||||
|
'Offline ($offlineCount)',
|
||||||
|
'Low Battery ($lowBatteryCount)',
|
||||||
|
];
|
||||||
|
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.all(30),
|
||||||
|
height: context.screenHeight,
|
||||||
|
width: context.screenWidth,
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
FilterWidget(
|
||||||
|
size: MediaQuery.of(context).size,
|
||||||
|
tabs: tabs,
|
||||||
|
selectedIndex: selectedIndex,
|
||||||
|
onTabChanged: (index) {
|
||||||
|
context
|
||||||
|
.read<DeviceManagementBloc>()
|
||||||
|
.add(SelectedFilterChanged(index));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 20,
|
||||||
|
),
|
||||||
|
const DeviceSearchFilters(),
|
||||||
|
const SizedBox(
|
||||||
|
height: 12,
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
height: 43,
|
||||||
|
width: 100,
|
||||||
|
decoration: containerDecoration,
|
||||||
|
child: Center(
|
||||||
|
child: DefaultButton(
|
||||||
|
onPressed: () {},
|
||||||
|
borderRadius: 9,
|
||||||
|
child: const Text('Control'),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 20),
|
),
|
||||||
const StatefulTextField(
|
const SizedBox(
|
||||||
title: "Unit Name",
|
height: 12,
|
||||||
width: 200,
|
),
|
||||||
elevation: 2,
|
Expanded(
|
||||||
),
|
child: DynamicTable(
|
||||||
const SizedBox(width: 20),
|
|
||||||
const StatefulTextField(
|
|
||||||
title: "Device Name / Product Name",
|
|
||||||
width: 300,
|
|
||||||
elevation: 2,
|
|
||||||
),
|
|
||||||
const SizedBox(width: 20),
|
|
||||||
SearchResetButtons(
|
|
||||||
onSearch: () {},
|
|
||||||
onReset: () {},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
] else ...[
|
|
||||||
Wrap(
|
|
||||||
spacing: 20,
|
|
||||||
runSpacing: 10,
|
|
||||||
children: [
|
|
||||||
const StatefulTextField(
|
|
||||||
title: "Community",
|
|
||||||
width: 200,
|
|
||||||
elevation: 2,
|
|
||||||
),
|
|
||||||
const StatefulTextField(
|
|
||||||
title: "Unit Name",
|
|
||||||
width: 200,
|
|
||||||
elevation: 2,
|
|
||||||
),
|
|
||||||
const StatefulTextField(
|
|
||||||
title: "Device Name / Product Name",
|
|
||||||
width: 300,
|
|
||||||
elevation: 2,
|
|
||||||
),
|
|
||||||
SearchResetButtons(
|
|
||||||
onSearch: () {},
|
|
||||||
onReset: () {},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
const SizedBox(
|
|
||||||
height: 12,
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: DynamicTable(
|
|
||||||
cellDecoration: containerDecoration,
|
cellDecoration: containerDecoration,
|
||||||
selectAll: (p0) {
|
selectAll: (p0) {
|
||||||
// visitorBloc.selectedDeviceIds.clear();
|
// visitorBloc.selectedDeviceIds.clear();
|
||||||
@ -101,29 +103,38 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
|
|||||||
withCheckBox: true,
|
withCheckBox: true,
|
||||||
size: context.screenSize,
|
size: context.screenSize,
|
||||||
headers: const [
|
headers: const [
|
||||||
'Device Name',
|
'Device Name',
|
||||||
'Product Name',
|
'Product Name',
|
||||||
'Device ID',
|
'Device ID',
|
||||||
'Unit Name',
|
'Unit Name',
|
||||||
'Room',
|
'Room',
|
||||||
'Battery Level',
|
'Battery Level',
|
||||||
'Installation Date and Time',
|
'Installation Date and Time',
|
||||||
'Status',
|
'Status',
|
||||||
'Last Offline Date and Time',
|
'Last Offline Date and Time',
|
||||||
],
|
],
|
||||||
data: []
|
data: devicesToShow.map((device) {
|
||||||
// state.data.map((item) {
|
return [
|
||||||
// return [
|
device.categoryName ?? '',
|
||||||
// item.name.toString(),
|
device.name ?? '',
|
||||||
// item.uuid.toString(),
|
device.uuid ?? '',
|
||||||
// item.productType.toString(),
|
device.unit?.name ?? '',
|
||||||
// '',
|
device.room?.name ?? '',
|
||||||
// item.online.value.toString(),
|
device.batteryLevel?.toString() ?? '',
|
||||||
// ];
|
formatDateTime(DateTime.fromMillisecondsSinceEpoch(
|
||||||
// }).toList(),
|
device.createTime ?? 0)),
|
||||||
)),
|
device.online == true ? 'Online' : 'Offline',
|
||||||
],
|
formatDateTime(DateTime.fromMillisecondsSinceEpoch(
|
||||||
),
|
device.updateTime ?? 0)),
|
||||||
|
];
|
||||||
|
}).toList(),
|
||||||
|
isEmpty: devicesToShow.isEmpty,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,84 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/common/text_field/custom_text_field.dart';
|
||||||
|
import 'package:syncrow_web/pages/device_managment/bloc/device_managment_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/common/buttons/search_reset_buttons.dart';
|
||||||
|
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
|
||||||
|
|
||||||
|
class DeviceSearchFilters extends StatefulWidget {
|
||||||
|
const DeviceSearchFilters({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<DeviceSearchFilters> createState() => _DeviceSearchFiltersState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _DeviceSearchFiltersState extends State<DeviceSearchFilters>
|
||||||
|
with HelperResponsiveLayout {
|
||||||
|
final TextEditingController communityController = TextEditingController();
|
||||||
|
final TextEditingController unitNameController = TextEditingController();
|
||||||
|
final TextEditingController productNameController = TextEditingController();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
communityController.dispose();
|
||||||
|
unitNameController.dispose();
|
||||||
|
productNameController.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return isLargeScreenSize(context)
|
||||||
|
? Row(
|
||||||
|
children: [
|
||||||
|
_buildSearchField("Community", communityController, 200),
|
||||||
|
const SizedBox(width: 20),
|
||||||
|
_buildSearchField("Unit Name", unitNameController, 200),
|
||||||
|
const SizedBox(width: 20),
|
||||||
|
_buildSearchField(
|
||||||
|
"Device Name / Product Name", productNameController, 300),
|
||||||
|
const SizedBox(width: 20),
|
||||||
|
_buildSearchResetButtons(),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
: Wrap(
|
||||||
|
spacing: 20,
|
||||||
|
runSpacing: 10,
|
||||||
|
children: [
|
||||||
|
_buildSearchField("Community", communityController, 200),
|
||||||
|
_buildSearchField("Unit Name", unitNameController, 200),
|
||||||
|
_buildSearchField(
|
||||||
|
"Device Name / Product Name", productNameController, 300),
|
||||||
|
_buildSearchResetButtons(),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildSearchField(
|
||||||
|
String title, TextEditingController controller, double width) {
|
||||||
|
return StatefulTextField(
|
||||||
|
title: title,
|
||||||
|
width: width,
|
||||||
|
elevation: 2,
|
||||||
|
controller: controller,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildSearchResetButtons() {
|
||||||
|
return SearchResetButtons(
|
||||||
|
onSearch: () {
|
||||||
|
context.read<DeviceManagementBloc>().add(SearchDevices(
|
||||||
|
community: communityController.text,
|
||||||
|
unitName: unitNameController.text,
|
||||||
|
productName: productNameController.text,
|
||||||
|
));
|
||||||
|
},
|
||||||
|
onReset: () {
|
||||||
|
communityController.clear();
|
||||||
|
unitNameController.clear();
|
||||||
|
productNameController.clear();
|
||||||
|
context.read<DeviceManagementBloc>().add(FetchDevices());
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -25,6 +25,7 @@ class HomeUpdateTree extends HomeState {
|
|||||||
@override
|
@override
|
||||||
List<Object> get props => [graph, builder];
|
List<Object> get props => [graph, builder];
|
||||||
}
|
}
|
||||||
|
|
||||||
class HomeUserInfoLoaded extends HomeState {
|
class HomeUserInfoLoaded extends HomeState {
|
||||||
final UserModel user;
|
final UserModel user;
|
||||||
|
|
||||||
|
@ -1,7 +1,3 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
|
|
||||||
class HomeItemModel {
|
class HomeItemModel {
|
||||||
@ -11,12 +7,11 @@ class HomeItemModel {
|
|||||||
final bool? active;
|
final bool? active;
|
||||||
final void Function(BuildContext context) onPress;
|
final void Function(BuildContext context) onPress;
|
||||||
|
|
||||||
|
|
||||||
HomeItemModel({
|
HomeItemModel({
|
||||||
this.title,
|
this.title,
|
||||||
this.icon,
|
this.icon,
|
||||||
this.color,
|
this.color,
|
||||||
this.active,
|
this.active,
|
||||||
required this.onPress,
|
required this.onPress,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -22,11 +22,12 @@ class HomeCard extends StatelessWidget {
|
|||||||
return InkWell(
|
return InkWell(
|
||||||
onTap: active ? onTap : null,
|
onTap: active ? onTap : null,
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: const EdgeInsets.only(left: 10,right: 10,bottom: 10),
|
padding: const EdgeInsets.only(left: 10, right: 10, bottom: 10),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: evenNumbers && active?
|
color: evenNumbers && active
|
||||||
ColorsManager.blueColor.withOpacity(0.8) :
|
? ColorsManager.blueColor.withOpacity(0.8)
|
||||||
(active ?ColorsManager.blueColor
|
: (active
|
||||||
|
? ColorsManager.blueColor
|
||||||
: ColorsManager.blueColor.withOpacity(0.2)),
|
: ColorsManager.blueColor.withOpacity(0.2)),
|
||||||
borderRadius: BorderRadius.circular(30),
|
borderRadius: BorderRadius.circular(30),
|
||||||
),
|
),
|
||||||
|
@ -8,9 +8,7 @@ class HomePage extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ResponsiveLayout(
|
return ResponsiveLayout(
|
||||||
desktopBody: HomeWebPage(),
|
desktopBody: HomeWebPage(), mobileBody: HomeMobilePage());
|
||||||
mobileBody:HomeMobilePage()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,8 @@ class HomeMobilePage extends StatelessWidget {
|
|||||||
width: size.width * 0.68,
|
width: size.width * 0.68,
|
||||||
child: GridView.builder(
|
child: GridView.builder(
|
||||||
itemCount: 8,
|
itemCount: 8,
|
||||||
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
gridDelegate:
|
||||||
|
const SliverGridDelegateWithFixedCrossAxisCount(
|
||||||
crossAxisCount: 2,
|
crossAxisCount: 2,
|
||||||
crossAxisSpacing: 20.0,
|
crossAxisSpacing: 20.0,
|
||||||
mainAxisSpacing: 20.0,
|
mainAxisSpacing: 20.0,
|
||||||
|
@ -39,7 +39,8 @@ class HomeWebPage extends StatelessWidget {
|
|||||||
Text(
|
Text(
|
||||||
'ACCESS YOUR APPS',
|
'ACCESS YOUR APPS',
|
||||||
style: Theme.of(context)
|
style: Theme.of(context)
|
||||||
.textTheme.headlineLarge!
|
.textTheme
|
||||||
|
.headlineLarge!
|
||||||
.copyWith(color: Colors.black, fontSize: 40),
|
.copyWith(color: Colors.black, fontSize: 40),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 30),
|
const SizedBox(height: 30),
|
||||||
@ -63,7 +64,8 @@ class HomeWebPage extends StatelessWidget {
|
|||||||
active: homeBloc.homeItems[index].active!,
|
active: homeBloc.homeItems[index].active!,
|
||||||
name: homeBloc.homeItems[index].title!,
|
name: homeBloc.homeItems[index].title!,
|
||||||
img: homeBloc.homeItems[index].icon!,
|
img: homeBloc.homeItems[index].icon!,
|
||||||
onTap: () => homeBloc.homeItems[index].onPress(context),
|
onTap: () =>
|
||||||
|
homeBloc.homeItems[index].onPress(context),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -32,8 +32,8 @@ class TreeWidget extends StatelessWidget {
|
|||||||
SizedBox(
|
SizedBox(
|
||||||
width: 100,
|
width: 100,
|
||||||
child: TextFormField(
|
child: TextFormField(
|
||||||
decoration:
|
decoration: const InputDecoration(
|
||||||
const InputDecoration(labelText: "Subtree separation"),
|
labelText: "Subtree separation"),
|
||||||
onChanged: (text) {
|
onChanged: (text) {
|
||||||
firstNodeName = text;
|
firstNodeName = text;
|
||||||
},
|
},
|
||||||
@ -73,9 +73,7 @@ class TreeWidget extends StatelessWidget {
|
|||||||
child: GraphView(
|
child: GraphView(
|
||||||
graph: state.graph,
|
graph: state.graph,
|
||||||
algorithm: BuchheimWalkerAlgorithm(
|
algorithm: BuchheimWalkerAlgorithm(
|
||||||
state.builder,
|
state.builder, TreeEdgeRenderer(state.builder)),
|
||||||
TreeEdgeRenderer(state.builder)
|
|
||||||
),
|
|
||||||
paint: Paint()
|
paint: Paint()
|
||||||
..color = Colors.green
|
..color = Colors.green
|
||||||
..strokeWidth = 1
|
..strokeWidth = 1
|
||||||
@ -138,7 +136,7 @@ Widget rectangleWidget(String text, Node node, BuildContext blocContext) {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
width: MediaQuery.of(blocContext).size.width*0.2,
|
width: MediaQuery.of(blocContext).size.width * 0.2,
|
||||||
margin: EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0),
|
margin: EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0),
|
||||||
padding: EdgeInsets.all(20.0),
|
padding: EdgeInsets.all(20.0),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
@ -163,7 +161,7 @@ Widget rectangleWidget(String text, Node node, BuildContext blocContext) {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 10.0),
|
const SizedBox(width: 10.0),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
child: Text(
|
child: Text(
|
||||||
text,
|
text,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
|
@ -220,7 +220,6 @@ class VisitorPasswordBloc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Future<void> postOnlineMultipleTimePassword(
|
Future<void> postOnlineMultipleTimePassword(
|
||||||
OnlineMultipleTimePasswordEvent event,
|
OnlineMultipleTimePasswordEvent event,
|
||||||
Emitter<VisitorPasswordState> emit) async {
|
Emitter<VisitorPasswordState> emit) async {
|
||||||
@ -246,11 +245,10 @@ class VisitorPasswordBloc
|
|||||||
passwordName: event.passwordName);
|
passwordName: event.passwordName);
|
||||||
if (res == true) {
|
if (res == true) {
|
||||||
emit(SuccessState());
|
emit(SuccessState());
|
||||||
}else {
|
} else {
|
||||||
throw Exception('Failed to create password');
|
throw Exception('Failed to create password');
|
||||||
}
|
}
|
||||||
emit(TableLoaded(data));
|
emit(TableLoaded(data));
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(FailedState(e.toString()));
|
emit(FailedState(e.toString()));
|
||||||
Navigator.pop(event.context!);
|
Navigator.pop(event.context!);
|
||||||
@ -267,17 +265,16 @@ class VisitorPasswordBloc
|
|||||||
try {
|
try {
|
||||||
emit(LoadingInitialState());
|
emit(LoadingInitialState());
|
||||||
await generate7DigitNumber();
|
await generate7DigitNumber();
|
||||||
bool res = await AccessMangApi().postOffLineOneTime(
|
bool res = await AccessMangApi().postOffLineOneTime(
|
||||||
email: event.email,
|
email: event.email,
|
||||||
devicesUuid: selectedDevices,
|
devicesUuid: selectedDevices,
|
||||||
passwordName: event.passwordName);
|
passwordName: event.passwordName);
|
||||||
if (res == true) {
|
if (res == true) {
|
||||||
emit(SuccessState());
|
emit(SuccessState());
|
||||||
}else {
|
} else {
|
||||||
throw Exception('Failed to create password');
|
throw Exception('Failed to create password');
|
||||||
}
|
}
|
||||||
emit(TableLoaded(data));
|
emit(TableLoaded(data));
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(FailedState(e.toString()));
|
emit(FailedState(e.toString()));
|
||||||
Navigator.pop(event.context!);
|
Navigator.pop(event.context!);
|
||||||
@ -294,7 +291,7 @@ class VisitorPasswordBloc
|
|||||||
try {
|
try {
|
||||||
emit(LoadingInitialState());
|
emit(LoadingInitialState());
|
||||||
await generate7DigitNumber();
|
await generate7DigitNumber();
|
||||||
bool res = await AccessMangApi().postOffLineMultipleTime(
|
bool res = await AccessMangApi().postOffLineMultipleTime(
|
||||||
email: event.email,
|
email: event.email,
|
||||||
devicesUuid: selectedDevices,
|
devicesUuid: selectedDevices,
|
||||||
passwordName: event.passwordName,
|
passwordName: event.passwordName,
|
||||||
@ -303,18 +300,18 @@ class VisitorPasswordBloc
|
|||||||
);
|
);
|
||||||
if (res == true) {
|
if (res == true) {
|
||||||
emit(SuccessState());
|
emit(SuccessState());
|
||||||
}else {
|
} else {
|
||||||
throw Exception('Failed to create password');
|
throw Exception('Failed to create password');
|
||||||
}
|
}
|
||||||
emit(TableLoaded(data));
|
emit(TableLoaded(data));
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(FailedState(e.toString()));
|
emit(FailedState(e.toString()));
|
||||||
Navigator.pop(event.context!);
|
Navigator.pop(event.context!);
|
||||||
stateDialog(
|
stateDialog(
|
||||||
context: event.context!,
|
context: event.context!,
|
||||||
message: e.toString(),
|
message: e.toString(),
|
||||||
title: 'Something Wrong'); }
|
title: 'Something Wrong');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void selectDevice(
|
void selectDevice(
|
||||||
|
@ -26,33 +26,32 @@ class SelectUsageFrequency extends VisitorPasswordEvent {
|
|||||||
@override
|
@override
|
||||||
List<Object> get props => [usageType];
|
List<Object> get props => [usageType];
|
||||||
}
|
}
|
||||||
|
|
||||||
class SelectTimeVisitorPassword extends VisitorPasswordEvent {
|
class SelectTimeVisitorPassword extends VisitorPasswordEvent {
|
||||||
final BuildContext context;
|
final BuildContext context;
|
||||||
final bool isStart;
|
final bool isStart;
|
||||||
final bool isRepeat;
|
final bool isRepeat;
|
||||||
|
|
||||||
const SelectTimeVisitorPassword({ required this.context,required this.isStart,required this.isRepeat});
|
const SelectTimeVisitorPassword(
|
||||||
|
{required this.context, required this.isStart, required this.isRepeat});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [context,isStart,isRepeat];
|
List<Object> get props => [context, isStart, isRepeat];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class ToggleDaySelectionEvent extends VisitorPasswordEvent {
|
class ToggleDaySelectionEvent extends VisitorPasswordEvent {
|
||||||
final String key;
|
final String key;
|
||||||
|
|
||||||
const ToggleDaySelectionEvent({required this.key});
|
const ToggleDaySelectionEvent({required this.key});
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [key];
|
List<Object> get props => [key];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class ToggleRepeatEvent extends VisitorPasswordEvent {}
|
class ToggleRepeatEvent extends VisitorPasswordEvent {}
|
||||||
|
|
||||||
class GeneratePasswordEvent extends VisitorPasswordEvent {}
|
class GeneratePasswordEvent extends VisitorPasswordEvent {}
|
||||||
|
|
||||||
class FetchDevice extends VisitorPasswordEvent {
|
class FetchDevice extends VisitorPasswordEvent {}
|
||||||
}
|
|
||||||
|
|
||||||
//online password
|
//online password
|
||||||
class OnlineOneTimePasswordEvent extends VisitorPasswordEvent {
|
class OnlineOneTimePasswordEvent extends VisitorPasswordEvent {
|
||||||
@ -60,20 +59,31 @@ class OnlineOneTimePasswordEvent extends VisitorPasswordEvent {
|
|||||||
final String? passwordName;
|
final String? passwordName;
|
||||||
final BuildContext? context;
|
final BuildContext? context;
|
||||||
|
|
||||||
const OnlineOneTimePasswordEvent({this.email,this.passwordName,this.context});
|
const OnlineOneTimePasswordEvent(
|
||||||
|
{this.email, this.passwordName, this.context});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [email!,passwordName!,];
|
List<Object> get props => [
|
||||||
|
email!,
|
||||||
|
passwordName!,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
class OnlineMultipleTimePasswordEvent extends VisitorPasswordEvent {
|
class OnlineMultipleTimePasswordEvent extends VisitorPasswordEvent {
|
||||||
final String? email;
|
final String? email;
|
||||||
final String? passwordName;
|
final String? passwordName;
|
||||||
final String? invalidTime;
|
final String? invalidTime;
|
||||||
final String? effectiveTime;
|
final String? effectiveTime;
|
||||||
final BuildContext? context;
|
final BuildContext? context;
|
||||||
const OnlineMultipleTimePasswordEvent({this.email,this.passwordName,this.invalidTime,this.effectiveTime,this.context});
|
const OnlineMultipleTimePasswordEvent(
|
||||||
|
{this.email,
|
||||||
|
this.passwordName,
|
||||||
|
this.invalidTime,
|
||||||
|
this.effectiveTime,
|
||||||
|
this.context});
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [email!,passwordName!,invalidTime!,effectiveTime!,context!];
|
List<Object> get props =>
|
||||||
|
[email!, passwordName!, invalidTime!, effectiveTime!, context!];
|
||||||
}
|
}
|
||||||
|
|
||||||
//offline password
|
//offline password
|
||||||
@ -81,9 +91,14 @@ class OfflineOneTimePasswordEvent extends VisitorPasswordEvent {
|
|||||||
final BuildContext? context;
|
final BuildContext? context;
|
||||||
final String? email;
|
final String? email;
|
||||||
final String? passwordName;
|
final String? passwordName;
|
||||||
const OfflineOneTimePasswordEvent({this.email,this.passwordName,this.context});
|
const OfflineOneTimePasswordEvent(
|
||||||
|
{this.email, this.passwordName, this.context});
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [email!,passwordName!,context!,];
|
List<Object> get props => [
|
||||||
|
email!,
|
||||||
|
passwordName!,
|
||||||
|
context!,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
class OfflineMultipleTimePasswordEvent extends VisitorPasswordEvent {
|
class OfflineMultipleTimePasswordEvent extends VisitorPasswordEvent {
|
||||||
@ -93,13 +108,18 @@ class OfflineMultipleTimePasswordEvent extends VisitorPasswordEvent {
|
|||||||
final String? effectiveTime;
|
final String? effectiveTime;
|
||||||
final BuildContext? context;
|
final BuildContext? context;
|
||||||
|
|
||||||
const OfflineMultipleTimePasswordEvent({this.context,this.email,this.passwordName,this.invalidTime,this.effectiveTime});
|
const OfflineMultipleTimePasswordEvent(
|
||||||
|
{this.context,
|
||||||
|
this.email,
|
||||||
|
this.passwordName,
|
||||||
|
this.invalidTime,
|
||||||
|
this.effectiveTime});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [email!,passwordName!,invalidTime!,effectiveTime!,context!];
|
List<Object> get props =>
|
||||||
|
[email!, passwordName!, invalidTime!, effectiveTime!, context!];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class SelectDeviceEvent extends VisitorPasswordEvent {
|
class SelectDeviceEvent extends VisitorPasswordEvent {
|
||||||
final String deviceId;
|
final String deviceId;
|
||||||
const SelectDeviceEvent(this.deviceId);
|
const SelectDeviceEvent(this.deviceId);
|
||||||
@ -116,22 +136,26 @@ class FilterDataEvent extends VisitorPasswordEvent {
|
|||||||
this.endTime,
|
this.endTime,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
class UpdateFilteredDevicesEvent extends VisitorPasswordEvent {
|
class UpdateFilteredDevicesEvent extends VisitorPasswordEvent {
|
||||||
final List<DeviceModel> filteredData;
|
final List<DeviceModel> filteredData;
|
||||||
|
|
||||||
UpdateFilteredDevicesEvent(this.filteredData);
|
UpdateFilteredDevicesEvent(this.filteredData);
|
||||||
}class SelectTimeEvent extends VisitorPasswordEvent {
|
|
||||||
final BuildContext context;
|
|
||||||
final bool isEffective;
|
|
||||||
const SelectTimeEvent({required this.context,required this.isEffective});
|
|
||||||
@override
|
|
||||||
List<Object> get props => [context,isEffective];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class SelectTimeEvent extends VisitorPasswordEvent {
|
||||||
|
final BuildContext context;
|
||||||
|
final bool isEffective;
|
||||||
|
const SelectTimeEvent({required this.context, required this.isEffective});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [context, isEffective];
|
||||||
|
}
|
||||||
|
|
||||||
class ChangeTimeEvent extends VisitorPasswordEvent {
|
class ChangeTimeEvent extends VisitorPasswordEvent {
|
||||||
final dynamic val;
|
final dynamic val;
|
||||||
final bool isStartEndTime;
|
final bool isStartEndTime;
|
||||||
|
|
||||||
const ChangeTimeEvent({required this.val,required this.isStartEndTime});
|
const ChangeTimeEvent({required this.val, required this.isStartEndTime});
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [val,isStartEndTime];
|
List<Object> get props => [val, isStartEndTime];
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
|
|
||||||
|
|
||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
import 'package:syncrow_web/pages/visitor_password/model/device_model.dart';
|
import 'package:syncrow_web/pages/visitor_password/model/device_model.dart';
|
||||||
|
|
||||||
@ -12,8 +10,6 @@ abstract class VisitorPasswordState extends Equatable {
|
|||||||
|
|
||||||
class VisitorPasswordInitial extends VisitorPasswordState {}
|
class VisitorPasswordInitial extends VisitorPasswordState {}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class PasswordTypeSelected extends VisitorPasswordState {
|
class PasswordTypeSelected extends VisitorPasswordState {
|
||||||
final String selectedType;
|
final String selectedType;
|
||||||
const PasswordTypeSelected(this.selectedType);
|
const PasswordTypeSelected(this.selectedType);
|
||||||
@ -36,13 +32,16 @@ class IsRepeatState extends VisitorPasswordState {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [repeat];
|
List<Object> get props => [repeat];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class LoadingInitialState extends VisitorPasswordState {}
|
class LoadingInitialState extends VisitorPasswordState {}
|
||||||
|
|
||||||
class ChangeTimeState extends VisitorPasswordState {}
|
class ChangeTimeState extends VisitorPasswordState {}
|
||||||
|
|
||||||
class TimeSelectedState extends VisitorPasswordState {}
|
class TimeSelectedState extends VisitorPasswordState {}
|
||||||
|
|
||||||
class DeviceLoaded extends VisitorPasswordState {}
|
class DeviceLoaded extends VisitorPasswordState {}
|
||||||
|
|
||||||
class SuccessState extends VisitorPasswordState {}
|
class SuccessState extends VisitorPasswordState {}
|
||||||
|
|
||||||
class FailedState extends VisitorPasswordState {
|
class FailedState extends VisitorPasswordState {
|
||||||
@ -62,4 +61,4 @@ class TableLoaded extends VisitorPasswordState {
|
|||||||
class DeviceSelectionUpdated extends VisitorPasswordState {
|
class DeviceSelectionUpdated extends VisitorPasswordState {
|
||||||
final List<String> selectedDeviceIds;
|
final List<String> selectedDeviceIds;
|
||||||
const DeviceSelectionUpdated(this.selectedDeviceIds);
|
const DeviceSelectionUpdated(this.selectedDeviceIds);
|
||||||
}
|
}
|
||||||
|
@ -1,28 +1,26 @@
|
|||||||
|
|
||||||
|
|
||||||
import 'package:syncrow_web/utils/constants/const.dart';
|
import 'package:syncrow_web/utils/constants/const.dart';
|
||||||
|
|
||||||
class DeviceModel {
|
class DeviceModel {
|
||||||
dynamic productUuid;
|
dynamic productUuid;
|
||||||
dynamic productType;
|
dynamic productType;
|
||||||
dynamic activeTime;
|
dynamic activeTime;
|
||||||
dynamic category;
|
dynamic category;
|
||||||
dynamic categoryName;
|
dynamic categoryName;
|
||||||
dynamic createTime;
|
dynamic createTime;
|
||||||
dynamic gatewayId;
|
dynamic gatewayId;
|
||||||
dynamic icon;
|
dynamic icon;
|
||||||
dynamic ip;
|
dynamic ip;
|
||||||
dynamic lat;
|
dynamic lat;
|
||||||
dynamic localKey;
|
dynamic localKey;
|
||||||
dynamic lon;
|
dynamic lon;
|
||||||
dynamic model;
|
dynamic model;
|
||||||
dynamic name;
|
dynamic name;
|
||||||
DeviseStatus online;
|
DeviseStatus online;
|
||||||
dynamic ownerId;
|
dynamic ownerId;
|
||||||
dynamic sub;
|
dynamic sub;
|
||||||
dynamic timeZone;
|
dynamic timeZone;
|
||||||
dynamic updateTime;
|
dynamic updateTime;
|
||||||
dynamic uuid;
|
dynamic uuid;
|
||||||
|
|
||||||
DeviceModel({
|
DeviceModel({
|
||||||
required this.productUuid,
|
required this.productUuid,
|
||||||
@ -50,25 +48,25 @@ class DeviceModel {
|
|||||||
// Deserialize from JSON
|
// Deserialize from JSON
|
||||||
factory DeviceModel.fromJson(Map<String, dynamic> json) {
|
factory DeviceModel.fromJson(Map<String, dynamic> json) {
|
||||||
return DeviceModel(
|
return DeviceModel(
|
||||||
productUuid: json['productUuid'] ,
|
productUuid: json['productUuid'],
|
||||||
productType: json['productType'],
|
productType: json['productType'],
|
||||||
activeTime: json['activeTime'],
|
activeTime: json['activeTime'],
|
||||||
category: json['category'] ,
|
category: json['category'],
|
||||||
categoryName: json['categoryName'] ,
|
categoryName: json['categoryName'],
|
||||||
createTime: json['createTime'] ,
|
createTime: json['createTime'],
|
||||||
gatewayId: json['gatewayId'],
|
gatewayId: json['gatewayId'],
|
||||||
icon: json['icon'],
|
icon: json['icon'],
|
||||||
ip: json['ip'] ,
|
ip: json['ip'],
|
||||||
lat: json['lat'] ,
|
lat: json['lat'],
|
||||||
localKey: json['localKey'] ,
|
localKey: json['localKey'],
|
||||||
lon: json['lon'] ,
|
lon: json['lon'],
|
||||||
model: json['model'] ,
|
model: json['model'],
|
||||||
name: json['name'],
|
name: json['name'],
|
||||||
online: OnlineTypeExtension.fromString(json['online']),
|
online: OnlineTypeExtension.fromString(json['online']),
|
||||||
ownerId: json['ownerId'] ,
|
ownerId: json['ownerId'],
|
||||||
sub: json['sub'],
|
sub: json['sub'],
|
||||||
timeZone: json['timeZone'],
|
timeZone: json['timeZone'],
|
||||||
updateTime: json['updateTime'] ,
|
updateTime: json['updateTime'],
|
||||||
uuid: json['uuid'],
|
uuid: json['uuid'],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -24,4 +24,4 @@ class Schedule {
|
|||||||
'workingDay': workingDay,
|
'workingDay': workingDay,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,70 +17,72 @@ class RepeatWidget extends StatelessWidget {
|
|||||||
Size size = MediaQuery.of(context).size;
|
Size size = MediaQuery.of(context).size;
|
||||||
return BlocBuilder<VisitorPasswordBloc, VisitorPasswordState>(
|
return BlocBuilder<VisitorPasswordBloc, VisitorPasswordState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
final visitorBloc = BlocProvider.of<VisitorPasswordBloc>(context);
|
final visitorBloc = BlocProvider.of<VisitorPasswordBloc>(context);
|
||||||
return Column(
|
return Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
// Wrap the Row in a SingleChildScrollView to handle overflow
|
// Wrap the Row in a SingleChildScrollView to handle overflow
|
||||||
SingleChildScrollView(
|
SingleChildScrollView(
|
||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.horizontal,
|
||||||
child: Row(
|
child: Row(
|
||||||
children: visitorBloc.days.map((day) {
|
children: visitorBloc.days.map((day) {
|
||||||
return Container(
|
return Container(
|
||||||
width: 70, // Adjust width as needed
|
width: 70, // Adjust width as needed
|
||||||
margin: EdgeInsets.all(5),
|
margin: EdgeInsets.all(5),
|
||||||
child: CheckboxListTile(
|
child: CheckboxListTile(
|
||||||
contentPadding: EdgeInsets.zero,
|
contentPadding: EdgeInsets.zero,
|
||||||
title: Text(
|
title: Text(
|
||||||
day['day']!,
|
day['day']!,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 10,
|
fontSize: 10,
|
||||||
color: visitorBloc.selectedDays.contains(day['key'])
|
color: visitorBloc.selectedDays.contains(day['key'])
|
||||||
? Colors.black
|
? Colors.black
|
||||||
: ColorsManager.blackColor,
|
: ColorsManager.blackColor,
|
||||||
),
|
|
||||||
),
|
|
||||||
value: visitorBloc.selectedDays.contains(day['key']),
|
|
||||||
onChanged: (bool? value) {
|
|
||||||
if (value != null) {
|
|
||||||
visitorBloc.add(ToggleDaySelectionEvent(key: day['key']!));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
);
|
),
|
||||||
}).toList(),
|
value: visitorBloc.selectedDays.contains(day['key']),
|
||||||
),
|
onChanged: (bool? value) {
|
||||||
),
|
if (value != null) {
|
||||||
Padding(
|
visitorBloc
|
||||||
padding: const EdgeInsets.all(8.0),
|
.add(ToggleDaySelectionEvent(key: day['key']!));
|
||||||
child: DateTimeWebWidget(
|
}
|
||||||
icon: Assets.timeIcon,
|
},
|
||||||
isRequired: false,
|
),
|
||||||
title: '',
|
);
|
||||||
size: size,
|
}).toList(),
|
||||||
endTime: () {
|
),
|
||||||
visitorBloc.add(SelectTimeEvent(
|
),
|
||||||
context: context,
|
Padding(
|
||||||
isEffective: false));
|
padding: const EdgeInsets.all(8.0),
|
||||||
Future.delayed(const Duration(milliseconds: 500), () {
|
child: DateTimeWebWidget(
|
||||||
visitorBloc.add(ChangeTimeEvent(val: visitorBloc.endTime, isStartEndTime: true));
|
icon: Assets.timeIcon,
|
||||||
});
|
isRequired: false,
|
||||||
},
|
title: '',
|
||||||
startTime: () {
|
size: size,
|
||||||
Future.delayed(const Duration(milliseconds: 500), () {
|
endTime: () {
|
||||||
visitorBloc.add(ChangeTimeEvent(val: visitorBloc.endTime, isStartEndTime: true));
|
visitorBloc
|
||||||
});
|
.add(SelectTimeEvent(context: context, isEffective: false));
|
||||||
visitorBloc.add(SelectTimeEvent(context: context, isEffective: true));
|
Future.delayed(const Duration(milliseconds: 500), () {
|
||||||
},
|
visitorBloc.add(ChangeTimeEvent(
|
||||||
firstString: visitorBloc.effectiveTime,
|
val: visitorBloc.endTime, isStartEndTime: true));
|
||||||
secondString: visitorBloc.expirationTime,
|
});
|
||||||
),
|
},
|
||||||
),
|
startTime: () {
|
||||||
const SizedBox(height: 20),
|
Future.delayed(const Duration(milliseconds: 500), () {
|
||||||
],
|
visitorBloc.add(ChangeTimeEvent(
|
||||||
);
|
val: visitorBloc.endTime, isStartEndTime: true));
|
||||||
}
|
});
|
||||||
);
|
visitorBloc
|
||||||
|
.add(SelectTimeEvent(context: context, isEffective: true));
|
||||||
|
},
|
||||||
|
firstString: visitorBloc.effectiveTime,
|
||||||
|
secondString: visitorBloc.expirationTime,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,7 @@ import 'package:syncrow_web/pages/visitor_password/model/schedule_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';
|
||||||
|
|
||||||
class AccessMangApi{
|
class AccessMangApi {
|
||||||
|
|
||||||
Future<List<PasswordModel>> fetchVisitorPassword() async {
|
Future<List<PasswordModel>> fetchVisitorPassword() async {
|
||||||
try {
|
try {
|
||||||
final response = await HTTPService().get(
|
final response = await HTTPService().get(
|
||||||
@ -23,7 +22,7 @@ class AccessMangApi{
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
return response;
|
return response;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
debugPrint('Error fetching visitor passwords: $e');
|
debugPrint('Error fetching visitor passwords: $e');
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
@ -43,19 +42,19 @@ class AccessMangApi{
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
return response;
|
return response;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
debugPrint('Error fetching $e');
|
debugPrint('Error fetching $e');
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> postOnlineOneTime({
|
Future<bool> postOnlineOneTime(
|
||||||
String? email,
|
{String? email,
|
||||||
String? passwordName,
|
String? passwordName,
|
||||||
String? password,
|
String? password,
|
||||||
String? effectiveTime,
|
String? effectiveTime,
|
||||||
String? invalidTime,
|
String? invalidTime,
|
||||||
List<String>? devicesUuid}) async {
|
List<String>? devicesUuid}) async {
|
||||||
try {
|
try {
|
||||||
final response = await HTTPService().post(
|
final response = await HTTPService().post(
|
||||||
path: ApiEndpoints.sendOnlineOneTime,
|
path: ApiEndpoints.sendOnlineOneTime,
|
||||||
@ -64,34 +63,34 @@ class AccessMangApi{
|
|||||||
"passwordName": passwordName,
|
"passwordName": passwordName,
|
||||||
"password": password,
|
"password": password,
|
||||||
"devicesUuid": devicesUuid,
|
"devicesUuid": devicesUuid,
|
||||||
"effectiveTime":effectiveTime ,
|
"effectiveTime": effectiveTime,
|
||||||
"invalidTime": invalidTime
|
"invalidTime": invalidTime
|
||||||
}),
|
}),
|
||||||
showServerMessage: true,
|
showServerMessage: true,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
if(json['statusCode'].toString()=='201'){
|
if (json['statusCode'].toString() == '201') {
|
||||||
return true;
|
return true;
|
||||||
}else{
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
return response;
|
return response;
|
||||||
} on DioException catch (e) {
|
} on DioException catch (e) {
|
||||||
debugPrint('Error: ${e.message}');
|
debugPrint('Error: ${e.message}');
|
||||||
debugPrint('Error fetching ${e.response!.statusMessage}');
|
debugPrint('Error fetching ${e.response!.statusMessage}');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future postOnlineMultipleTime({
|
Future postOnlineMultipleTime(
|
||||||
String? effectiveTime,
|
{String? effectiveTime,
|
||||||
String? invalidTime,
|
String? invalidTime,
|
||||||
String? email,
|
String? email,
|
||||||
String? password,
|
String? password,
|
||||||
String? passwordName,
|
String? passwordName,
|
||||||
List<Schedule>? scheduleList,
|
List<Schedule>? scheduleList,
|
||||||
List<String>? devicesUuid}) async {
|
List<String>? devicesUuid}) async {
|
||||||
try {
|
try {
|
||||||
Map<String, dynamic> body = {
|
Map<String, dynamic> body = {
|
||||||
"email": email,
|
"email": email,
|
||||||
@ -102,22 +101,24 @@ class AccessMangApi{
|
|||||||
"invalidTime": invalidTime,
|
"invalidTime": invalidTime,
|
||||||
};
|
};
|
||||||
if (scheduleList != null) {
|
if (scheduleList != null) {
|
||||||
body["scheduleList"] = scheduleList.map((schedule) => schedule.toJson()).toList();
|
body["scheduleList"] =
|
||||||
|
scheduleList.map((schedule) => schedule.toJson()).toList();
|
||||||
}
|
}
|
||||||
final response = await HTTPService().post(
|
final response = await HTTPService().post(
|
||||||
path: ApiEndpoints.sendOnlineMultipleTime,
|
path: ApiEndpoints.sendOnlineMultipleTime,
|
||||||
body: jsonEncode(body),
|
body: jsonEncode(body),
|
||||||
showServerMessage: true,
|
showServerMessage: true,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
if(json['data']['successOperations'][0]['success'].toString()=='true'){
|
if (json['data']['successOperations'][0]['success'].toString() ==
|
||||||
|
'true') {
|
||||||
return true;
|
return true;
|
||||||
}else{
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
return response;
|
return response;
|
||||||
} on DioException catch (e){
|
} on DioException catch (e) {
|
||||||
debugPrint('Error fetching ${e.type.name}');
|
debugPrint('Error fetching ${e.type.name}');
|
||||||
debugPrint('Error fetching ${e.response!.statusMessage}');
|
debugPrint('Error fetching ${e.response!.statusMessage}');
|
||||||
return false;
|
return false;
|
||||||
@ -126,16 +127,17 @@ class AccessMangApi{
|
|||||||
|
|
||||||
// OffLine One Time Password
|
// OffLine One Time Password
|
||||||
|
|
||||||
Future postOffLineOneTime({String? email,String? passwordName,List<String>? devicesUuid}) async {
|
Future postOffLineOneTime(
|
||||||
|
{String? email, String? passwordName, List<String>? devicesUuid}) async {
|
||||||
try {
|
try {
|
||||||
final response = await HTTPService().post(
|
final response = await HTTPService().post(
|
||||||
path: ApiEndpoints.sendOffLineOneTime,
|
path: ApiEndpoints.sendOffLineOneTime,
|
||||||
body: jsonEncode({
|
body: jsonEncode({
|
||||||
"email": email,
|
"email": email,
|
||||||
"passwordName": passwordName,
|
"passwordName": passwordName,
|
||||||
"devicesUuid": devicesUuid
|
"devicesUuid": devicesUuid
|
||||||
}),
|
}),
|
||||||
showServerMessage: true,
|
showServerMessage: true,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
if (json['data']['successOperations'][0]['success'].toString() ==
|
if (json['data']['successOperations'][0]['success'].toString() ==
|
||||||
'true') {
|
'true') {
|
||||||
@ -143,8 +145,7 @@ class AccessMangApi{
|
|||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
);
|
|
||||||
return response;
|
return response;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
debugPrint('Error fetching $e');
|
debugPrint('Error fetching $e');
|
||||||
@ -152,25 +153,23 @@ class AccessMangApi{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future postOffLineMultipleTime({
|
Future postOffLineMultipleTime(
|
||||||
String? email,
|
{String? email,
|
||||||
String? passwordName,
|
String? passwordName,
|
||||||
String? effectiveTime,
|
String? effectiveTime,
|
||||||
String? invalidTime,
|
String? invalidTime,
|
||||||
List<String>? devicesUuid
|
List<String>? devicesUuid}) async {
|
||||||
|
|
||||||
}) async {
|
|
||||||
try {
|
try {
|
||||||
final response = await HTTPService().post(
|
final response = await HTTPService().post(
|
||||||
path: ApiEndpoints.sendOffLineOneTime,
|
path: ApiEndpoints.sendOffLineOneTime,
|
||||||
body: jsonEncode({
|
body: jsonEncode({
|
||||||
"email": email,
|
"email": email,
|
||||||
"devicesUuid":devicesUuid,
|
"devicesUuid": devicesUuid,
|
||||||
"passwordName": passwordName,
|
"passwordName": passwordName,
|
||||||
"effectiveTime": effectiveTime,
|
"effectiveTime": effectiveTime,
|
||||||
"invalidTime": invalidTime
|
"invalidTime": invalidTime
|
||||||
}),
|
}),
|
||||||
showServerMessage: true,
|
showServerMessage: true,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
if (json['data']['successOperations'][0]['success'].toString() ==
|
if (json['data']['successOperations'][0]['success'].toString() ==
|
||||||
'true') {
|
'true') {
|
||||||
@ -178,12 +177,11 @@ class AccessMangApi{
|
|||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
);
|
|
||||||
return response;
|
return response;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
debugPrint('Error fetching $e');
|
debugPrint('Error fetching $e');
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,16 +22,19 @@ class HTTPInterceptor extends InterceptorsWrapper {
|
|||||||
if (await validateResponse(response)) {
|
if (await validateResponse(response)) {
|
||||||
super.onResponse(response, handler);
|
super.onResponse(response, handler);
|
||||||
} else {
|
} else {
|
||||||
handler.reject(DioException(requestOptions: response.requestOptions, response: response));
|
handler.reject(DioException(
|
||||||
|
requestOptions: response.requestOptions, response: response));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onRequest(RequestOptions options, RequestInterceptorHandler handler) async {
|
void onRequest(
|
||||||
|
RequestOptions options, RequestInterceptorHandler handler) async {
|
||||||
var storage = const FlutterSecureStorage();
|
var storage = const FlutterSecureStorage();
|
||||||
var token = await storage.read(key: Token.loginAccessTokenKey);
|
var token = await storage.read(key: Token.loginAccessTokenKey);
|
||||||
if (checkHeaderExclusionListOfAddedParameters(options.path)) {
|
if (checkHeaderExclusionListOfAddedParameters(options.path)) {
|
||||||
options.headers.putIfAbsent(HttpHeaders.authorizationHeader, () => "Bearer $token");
|
options.headers
|
||||||
|
.putIfAbsent(HttpHeaders.authorizationHeader, () => "Bearer $token");
|
||||||
}
|
}
|
||||||
// options.headers['Authorization'] = 'Bearer ${'${token!}123'}';
|
// options.headers['Authorization'] = 'Bearer ${'${token!}123'}';
|
||||||
super.onRequest(options, handler);
|
super.onRequest(options, handler);
|
||||||
|
@ -31,8 +31,7 @@ class ServerFailure extends Failure {
|
|||||||
{
|
{
|
||||||
// var document = parser.parse(dioError.response!.data.toString());
|
// var document = parser.parse(dioError.response!.data.toString());
|
||||||
// var message = document.body!.text;
|
// var message = document.body!.text;
|
||||||
return ServerFailure.fromResponse(
|
return ServerFailure.fromResponse(dioError.response!.statusCode!,
|
||||||
dioError.response!.statusCode!,
|
|
||||||
dioError.response?.data['message'] ?? "Error");
|
dioError.response?.data['message'] ?? "Error");
|
||||||
}
|
}
|
||||||
case DioExceptionType.cancel:
|
case DioExceptionType.cancel:
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:syncrow_web/pages/auth/model/region_model.dart';
|
import 'package:syncrow_web/pages/auth/model/region_model.dart';
|
||||||
@ -18,48 +17,43 @@ class AuthenticationAPI {
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future forgetPassword(
|
static Future forgetPassword({
|
||||||
{required var email, required var password,}) async {
|
required var email,
|
||||||
|
required var password,
|
||||||
|
}) async {
|
||||||
final response = await HTTPService().post(
|
final response = await HTTPService().post(
|
||||||
path: ApiEndpoints.forgetPassword,
|
path: ApiEndpoints.forgetPassword,
|
||||||
body: {
|
body: {"email": email, "password": password},
|
||||||
"email": email,
|
|
||||||
"password": password
|
|
||||||
},
|
|
||||||
showServerMessage: true,
|
showServerMessage: true,
|
||||||
expectedResponseModel: (json) {});
|
expectedResponseModel: (json) {});
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Future<int?> sendOtp(
|
||||||
static Future<int?> sendOtp({required String email, required String regionUuid}) async {
|
{required String email, required String regionUuid}) async {
|
||||||
try {
|
try {
|
||||||
final response = await HTTPService().post(
|
final response = await HTTPService().post(
|
||||||
path: ApiEndpoints.sendOtp,
|
path: ApiEndpoints.sendOtp,
|
||||||
body: {
|
body: {"email": email, "type": "PASSWORD", "regionUuid": regionUuid},
|
||||||
"email": email,
|
|
||||||
"type": "PASSWORD",
|
|
||||||
"regionUuid": regionUuid
|
|
||||||
},
|
|
||||||
showServerMessage: true,
|
showServerMessage: true,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
return 30;
|
return 30;
|
||||||
}
|
});
|
||||||
);
|
|
||||||
return 30;
|
return 30;
|
||||||
} on DioException catch (e) {
|
} on DioException catch (e) {
|
||||||
if (e.response != null) {
|
if (e.response != null) {
|
||||||
if (e.response!.statusCode == 400) {
|
if (e.response!.statusCode == 400) {
|
||||||
final errorData = e.response!.data;
|
final errorData = e.response!.data;
|
||||||
String errorMessage = errorData['message'];
|
String errorMessage = errorData['message'];
|
||||||
if(errorMessage=='User not found'){
|
if (errorMessage == 'User not found') {
|
||||||
return 1;
|
return 1;
|
||||||
}else{
|
} else {
|
||||||
int cooldown = errorData['data']['cooldown'] ?? 1;
|
int cooldown = errorData['data']['cooldown'] ?? 1;
|
||||||
return cooldown;
|
return cooldown;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
debugPrint('Error: ${e.response!.statusCode} - ${e.response!.statusMessage}');
|
debugPrint(
|
||||||
|
'Error: ${e.response!.statusCode} - ${e.response!.statusMessage}');
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -74,7 +68,7 @@ class AuthenticationAPI {
|
|||||||
|
|
||||||
static Future verifyOtp(
|
static Future verifyOtp(
|
||||||
{required String email, required String otpCode}) async {
|
{required String email, required String otpCode}) async {
|
||||||
try{
|
try {
|
||||||
final response = await HTTPService().post(
|
final response = await HTTPService().post(
|
||||||
path: ApiEndpoints.verifyOtp,
|
path: ApiEndpoints.verifyOtp,
|
||||||
body: {"email": email, "type": "PASSWORD", "otpCode": otpCode},
|
body: {"email": email, "type": "PASSWORD", "otpCode": otpCode},
|
||||||
@ -87,12 +81,12 @@ class AuthenticationAPI {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
return response;
|
return response;
|
||||||
}on DioException catch (e){
|
} on DioException catch (e) {
|
||||||
if (e.response != null) {
|
if (e.response != null) {
|
||||||
if (e.response!.statusCode == 400) {
|
if (e.response!.statusCode == 400) {
|
||||||
final errorData = e.response!.data;
|
final errorData = e.response!.data;
|
||||||
String errorMessage = errorData['message'];
|
String errorMessage = errorData['message'];
|
||||||
return errorMessage;
|
return errorMessage;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
debugPrint('Error: ${e.message}');
|
debugPrint('Error: ${e.message}');
|
||||||
@ -105,10 +99,10 @@ class AuthenticationAPI {
|
|||||||
path: ApiEndpoints.getRegion,
|
path: ApiEndpoints.getRegion,
|
||||||
showServerMessage: true,
|
showServerMessage: true,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
return (json as List).map((zone) => RegionModel.fromJson(zone)).toList();
|
return (json as List)
|
||||||
}
|
.map((zone) => RegionModel.fromJson(zone))
|
||||||
);
|
.toList();
|
||||||
|
});
|
||||||
return response as List<RegionModel>;
|
return response as List<RegionModel>;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
26
lib/services/devices_mang_api.dart
Normal file
26
lib/services/devices_mang_api.dart
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:syncrow_web/pages/device_managment/models/devices_model.dart';
|
||||||
|
import 'package:syncrow_web/services/api/http_service.dart';
|
||||||
|
import 'package:syncrow_web/utils/constants/api_const.dart';
|
||||||
|
|
||||||
|
class DevicesManagementApi {
|
||||||
|
Future<List<AllDevicesModel>> fetchDevices() async {
|
||||||
|
try {
|
||||||
|
final response = await HTTPService().get(
|
||||||
|
path: ApiEndpoints.getAllDevices,
|
||||||
|
showServerMessage: true,
|
||||||
|
expectedResponseModel: (json) {
|
||||||
|
List<dynamic> jsonData = json;
|
||||||
|
List<AllDevicesModel> devicesList = jsonData.map((jsonItem) {
|
||||||
|
return AllDevicesModel.fromJson(jsonItem);
|
||||||
|
}).toList();
|
||||||
|
return devicesList;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
return response;
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint('Error fetching $e');
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,16 +1,15 @@
|
|||||||
import 'package:syncrow_web/pages/auth/model/user_model.dart';
|
import 'package:syncrow_web/pages/auth/model/user_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';
|
||||||
|
|
||||||
class HomeApi{
|
class HomeApi {
|
||||||
Future fetchUserInfo(userId) async {
|
Future fetchUserInfo(userId) async {
|
||||||
final response = await HTTPService().get(
|
final response = await HTTPService().get(
|
||||||
path: ApiEndpoints.getUser.replaceAll('{userUuid}', userId!),
|
path: ApiEndpoints.getUser.replaceAll('{userUuid}', userId!),
|
||||||
showServerMessage: true,
|
showServerMessage: true,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
return UserModel.fromJson(json);
|
return UserModel.fromJson(json);
|
||||||
}
|
});
|
||||||
);
|
return response;
|
||||||
return response;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@ -4,7 +4,7 @@ import 'package:syncrow_web/services/api/http_interceptor.dart';
|
|||||||
import 'package:syncrow_web/services/api/http_service.dart';
|
import 'package:syncrow_web/services/api/http_service.dart';
|
||||||
|
|
||||||
final GetIt serviceLocator = GetIt.instance;
|
final GetIt serviceLocator = GetIt.instance;
|
||||||
//setupLocator() // to search for dependency injection in flutter
|
//setupLocator() // to search for dependency injection in flutter
|
||||||
initialSetup() {
|
initialSetup() {
|
||||||
serviceLocator.registerSingleton<HTTPInterceptor>(HTTPInterceptor());
|
serviceLocator.registerSingleton<HTTPInterceptor>(HTTPInterceptor());
|
||||||
//Base classes
|
//Base classes
|
||||||
|
@ -25,6 +25,7 @@ abstract class ColorsManager {
|
|||||||
static const Color slidingBlueColor = Color(0x99023DFE);
|
static const Color slidingBlueColor = Color(0x99023DFE);
|
||||||
static const Color blackColor = Color(0xFF000000);
|
static const Color blackColor = Color(0xFF000000);
|
||||||
static const Color lightGreen = Color(0xFF00FF0A);
|
static const Color lightGreen = Color(0xFF00FF0A);
|
||||||
|
static const Color green = Color(0xFF008905);
|
||||||
static const Color grayColor = Color(0xFF999999);
|
static const Color grayColor = Color(0xFF999999);
|
||||||
static const Color red = Color(0xFFFF0000);
|
static const Color red = Color(0xFFFF0000);
|
||||||
static const Color graysColor = Color(0xffEBEBEB);
|
static const Color graysColor = Color(0xffEBEBEB);
|
||||||
|
@ -5,21 +5,28 @@ abstract class ApiEndpoints {
|
|||||||
////////////////////////////////////// Authentication ///////////////////////////////
|
////////////////////////////////////// Authentication ///////////////////////////////
|
||||||
static const String signUp = '$baseUrl/authentication/user/signup';
|
static const String signUp = '$baseUrl/authentication/user/signup';
|
||||||
static const String login = '$baseUrl/authentication/user/login';
|
static const String login = '$baseUrl/authentication/user/login';
|
||||||
static const String forgetPassword = '$baseUrl/authentication/user/forget-password';
|
static const String forgetPassword =
|
||||||
|
'$baseUrl/authentication/user/forget-password';
|
||||||
static const String sendOtp = '$baseUrl/authentication/user/send-otp';
|
static const String sendOtp = '$baseUrl/authentication/user/send-otp';
|
||||||
static const String verifyOtp = '$baseUrl/authentication/user/verify-otp';
|
static const String verifyOtp = '$baseUrl/authentication/user/verify-otp';
|
||||||
static const String getRegion = '$baseUrl/region';
|
static const String getRegion = '$baseUrl/region';
|
||||||
static const String visitorPassword = '$baseUrl/visitor-password';
|
static const String visitorPassword = '$baseUrl/visitor-password';
|
||||||
static const String getDevices = '$baseUrl/visitor-password/devices';
|
static const String getDevices = '$baseUrl/visitor-password/devices';
|
||||||
|
|
||||||
|
static const String sendOnlineOneTime =
|
||||||
static const String sendOnlineOneTime = '$baseUrl/visitor-password/temporary-password/online/one-time';
|
'$baseUrl/visitor-password/temporary-password/online/one-time';
|
||||||
static const String sendOnlineMultipleTime = '$baseUrl/visitor-password/temporary-password/online/multiple-time';
|
static const String sendOnlineMultipleTime =
|
||||||
|
'$baseUrl/visitor-password/temporary-password/online/multiple-time';
|
||||||
|
|
||||||
//offline Password
|
//offline Password
|
||||||
static const String sendOffLineOneTime = '$baseUrl/visitor-password/temporary-password/offline/one-time';
|
static const String sendOffLineOneTime =
|
||||||
static const String sendOffLineMultipleTime = '$baseUrl/visitor-password/temporary-password/offline/multiple-time';
|
'$baseUrl/visitor-password/temporary-password/offline/one-time';
|
||||||
|
static const String sendOffLineMultipleTime =
|
||||||
|
'$baseUrl/visitor-password/temporary-password/offline/multiple-time';
|
||||||
|
|
||||||
static const String getUser = '$baseUrl/user/{userUuid}';
|
static const String getUser = '$baseUrl/user/{userUuid}';
|
||||||
|
|
||||||
|
////// Devices Management ////////////////
|
||||||
|
|
||||||
|
static const String getAllDevices = '$baseUrl/device';
|
||||||
}
|
}
|
||||||
|
@ -13,10 +13,12 @@ class Assets {
|
|||||||
static const String rightLine = "assets/images/right_line.png";
|
static const String rightLine = "assets/images/right_line.png";
|
||||||
static const String google = "assets/images/google.svg";
|
static const String google = "assets/images/google.svg";
|
||||||
static const String facebook = "assets/images/facebook.svg";
|
static const String facebook = "assets/images/facebook.svg";
|
||||||
static const String invisiblePassword = "assets/images/Password_invisible.svg";
|
static const String invisiblePassword =
|
||||||
|
"assets/images/Password_invisible.svg";
|
||||||
static const String visiblePassword = "assets/images/Password_visible.svg";
|
static const String visiblePassword = "assets/images/Password_visible.svg";
|
||||||
static const String accessIcon = "assets/images/access_icon.svg";
|
static const String accessIcon = "assets/images/access_icon.svg";
|
||||||
static const String spaseManagementIcon = "assets/images/spase_management_icon.svg";
|
static const String spaseManagementIcon =
|
||||||
|
"assets/images/spase_management_icon.svg";
|
||||||
static const String devicesIcon = "assets/images/devices_icon.svg";
|
static const String devicesIcon = "assets/images/devices_icon.svg";
|
||||||
static const String moveinIcon = "assets/images/movein_icon.svg";
|
static const String moveinIcon = "assets/images/movein_icon.svg";
|
||||||
static const String constructionIcon = "assets/images/construction_icon.svg";
|
static const String constructionIcon = "assets/images/construction_icon.svg";
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
enum AccessType {
|
enum AccessType {
|
||||||
onlineOnetime,
|
onlineOnetime,
|
||||||
onlineMultiple,
|
onlineMultiple,
|
||||||
@ -36,11 +35,6 @@ extension AccessTypeExtension on AccessType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
enum DeviseStatus {
|
enum DeviseStatus {
|
||||||
online,
|
online,
|
||||||
offline,
|
offline,
|
||||||
@ -53,7 +47,6 @@ extension OnlineTypeExtension on DeviseStatus {
|
|||||||
return "Online";
|
return "Online";
|
||||||
case DeviseStatus.offline:
|
case DeviseStatus.offline:
|
||||||
return "Offline";
|
return "Offline";
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,10 +62,9 @@ extension OnlineTypeExtension on DeviseStatus {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
enum AccessStatus {
|
enum AccessStatus {
|
||||||
expired ,
|
expired,
|
||||||
effective ,
|
effective,
|
||||||
toBeEffective,
|
toBeEffective,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,28 +74,22 @@ extension AccessStatusExtension on AccessStatus {
|
|||||||
case AccessStatus.expired:
|
case AccessStatus.expired:
|
||||||
return "Expired";
|
return "Expired";
|
||||||
case AccessStatus.effective:
|
case AccessStatus.effective:
|
||||||
return "Effective" ;
|
return "Effective";
|
||||||
case AccessStatus.toBeEffective:
|
case AccessStatus.toBeEffective:
|
||||||
return "To be effective";
|
return "To be effective";
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static AccessStatus fromString(String value) {
|
static AccessStatus fromString(String value) {
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case "EXPIRED" :
|
case "EXPIRED":
|
||||||
return AccessStatus.expired;
|
return AccessStatus.expired;
|
||||||
case "EFFECTIVE" :
|
case "EFFECTIVE":
|
||||||
return AccessStatus.effective;
|
return AccessStatus.effective;
|
||||||
case "TO_BE_EFFECTIVE":
|
case "TO_BE_EFFECTIVE":
|
||||||
return AccessStatus.toBeEffective;
|
return AccessStatus.toBeEffective;
|
||||||
default:
|
default:
|
||||||
throw ArgumentError("Invalid access type: $value");
|
throw ArgumentError("Invalid access type: $value");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
11
lib/utils/format_date_time.dart
Normal file
11
lib/utils/format_date_time.dart
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
|
String formatDateTime(DateTime? dateTime) {
|
||||||
|
if (dateTime == null) {
|
||||||
|
return '-';
|
||||||
|
}
|
||||||
|
final DateFormat dateFormatter = DateFormat('dd/MM/yyyy');
|
||||||
|
final DateFormat timeFormatter = DateFormat('HH:mm');
|
||||||
|
|
||||||
|
return '${dateFormatter.format(dateTime)} ${timeFormatter.format(dateTime)}';
|
||||||
|
}
|
@ -4,7 +4,7 @@ String decodeBase64(String str) {
|
|||||||
//'-', '+' 62nd char of encoding, '_', '/' 63rd char of encoding
|
//'-', '+' 62nd char of encoding, '_', '/' 63rd char of encoding
|
||||||
String output = str.replaceAll('-', '+').replaceAll('_', '/');
|
String output = str.replaceAll('-', '+').replaceAll('_', '/');
|
||||||
switch (output.length % 4) {
|
switch (output.length % 4) {
|
||||||
// Pad with trailing '='
|
// Pad with trailing '='
|
||||||
case 0: // No pad chars in this case
|
case 0: // No pad chars in this case
|
||||||
break;
|
break;
|
||||||
case 2: // Two pad chars
|
case 2: // Two pad chars
|
||||||
|
@ -1,19 +1,20 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
|
||||||
class ResponsiveLayout extends StatelessWidget {
|
class ResponsiveLayout extends StatelessWidget {
|
||||||
final Widget desktopBody;
|
final Widget desktopBody;
|
||||||
final Widget mobileBody;
|
final Widget mobileBody;
|
||||||
const ResponsiveLayout({super.key,required this.desktopBody,required this.mobileBody});
|
const ResponsiveLayout(
|
||||||
|
{super.key, required this.desktopBody, required this.mobileBody});
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return LayoutBuilder(builder: (context, constraints) {
|
return LayoutBuilder(
|
||||||
if(constraints.maxWidth<600){
|
builder: (context, constraints) {
|
||||||
return mobileBody;
|
if (constraints.maxWidth < 600) {
|
||||||
}else{
|
return mobileBody;
|
||||||
return desktopBody;
|
} else {
|
||||||
}
|
return desktopBody;
|
||||||
},
|
}
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,6 @@ class CustomSnackBar {
|
|||||||
BuildContext? currentContext = key?.currentContext;
|
BuildContext? currentContext = key?.currentContext;
|
||||||
if (key != null && currentContext != null) {
|
if (key != null && currentContext != null) {
|
||||||
final snackBar = SnackBar(
|
final snackBar = SnackBar(
|
||||||
|
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
backgroundColor: Colors.green,
|
backgroundColor: Colors.green,
|
||||||
content: Row(mainAxisAlignment: MainAxisAlignment.center, children: [
|
content: Row(mainAxisAlignment: MainAxisAlignment.center, children: [
|
||||||
|
@ -1,46 +1,43 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'color_manager.dart';
|
import 'color_manager.dart';
|
||||||
|
|
||||||
InputDecoration? textBoxDecoration({bool suffixIcon = false}) => InputDecoration(
|
InputDecoration? textBoxDecoration({bool suffixIcon = false}) =>
|
||||||
focusColor: ColorsManager.grayColor,
|
InputDecoration(
|
||||||
suffixIcon:suffixIcon? const Icon(Icons.search):null,
|
focusColor: ColorsManager.grayColor,
|
||||||
hintText: 'Search',
|
suffixIcon: suffixIcon ? const Icon(Icons.search) : null,
|
||||||
filled: true, // Enable background filling
|
hintText: 'Search',
|
||||||
fillColor: const Color(0xffF5F6F7), // Set the background color
|
filled: true, // Enable background filling
|
||||||
border: OutlineInputBorder(
|
fillColor: const Color(0xffF5F6F7), // Set the background color
|
||||||
borderRadius: BorderRadius.circular(8), // Add border radius
|
border: OutlineInputBorder(
|
||||||
borderSide: BorderSide.none, // Remove the underline
|
borderRadius: BorderRadius.circular(8), // Add border radius
|
||||||
),
|
borderSide: BorderSide.none, // Remove the underline
|
||||||
enabledBorder: OutlineInputBorder(
|
),
|
||||||
borderRadius: BorderRadius.circular(8), // Add border radius
|
enabledBorder: OutlineInputBorder(
|
||||||
borderSide: BorderSide.none, // Remove the underline
|
borderRadius: BorderRadius.circular(8), // Add border radius
|
||||||
),
|
borderSide: BorderSide.none, // Remove the underline
|
||||||
focusedBorder: OutlineInputBorder(
|
),
|
||||||
borderRadius: BorderRadius.circular(8), // Add border radius
|
focusedBorder: OutlineInputBorder(
|
||||||
borderSide: BorderSide.none, // Remove the underline
|
borderRadius: BorderRadius.circular(8), // Add border radius
|
||||||
),
|
borderSide: BorderSide.none, // Remove the underline
|
||||||
errorBorder: OutlineInputBorder(
|
),
|
||||||
borderSide: BorderSide(color: Colors.red, width: 2),
|
errorBorder: OutlineInputBorder(
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderSide: BorderSide(color: Colors.red, width: 2),
|
||||||
),
|
borderRadius: BorderRadius.circular(8),
|
||||||
focusedErrorBorder: OutlineInputBorder(
|
),
|
||||||
borderSide: BorderSide(color: Colors.red, width: 2),
|
focusedErrorBorder: OutlineInputBorder(
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderSide: BorderSide(color: Colors.red, width: 2),
|
||||||
),
|
borderRadius: BorderRadius.circular(8),
|
||||||
);
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
BoxDecoration containerDecoration = BoxDecoration(
|
||||||
BoxDecoration containerDecoration = BoxDecoration(
|
|
||||||
boxShadow: [
|
boxShadow: [
|
||||||
BoxShadow(
|
BoxShadow(
|
||||||
color: Colors.grey.withOpacity(0.5),
|
color: Colors.grey.withOpacity(0.5),
|
||||||
spreadRadius: 5,
|
spreadRadius: 5,
|
||||||
blurRadius: 8,
|
blurRadius: 8,
|
||||||
offset: const Offset(0,
|
offset: const Offset(0, 3), // changes position of shadow
|
||||||
3), // changes position of shadow
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
color: ColorsManager.boxColor,
|
color: ColorsManager.boxColor,
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(10)));
|
borderRadius: const BorderRadius.all(Radius.circular(10)));
|
||||||
|
|
||||||
|
|
||||||
|
@ -21,30 +21,35 @@ class MenuSidebar extends StatelessWidget {
|
|||||||
color: ColorsManager.whiteColors,
|
color: ColorsManager.whiteColors,
|
||||||
),
|
),
|
||||||
width: 200,
|
width: 200,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(15.0),
|
padding: const EdgeInsets.all(15.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
const Text('Community',style: TextStyle(fontSize: 20),),
|
const Text(
|
||||||
|
'Community',
|
||||||
|
style: TextStyle(fontSize: 20),
|
||||||
|
),
|
||||||
CircleAvatar(
|
CircleAvatar(
|
||||||
backgroundColor: Colors.grey.shade200,
|
backgroundColor: Colors.grey.shade200,
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
color: ColorsManager.onSecondaryColor,
|
color: ColorsManager.onSecondaryColor,
|
||||||
onPressed: () {},
|
onPressed: () {},
|
||||||
icon: const Icon(Icons.add)
|
icon: const Icon(Icons.add)),
|
||||||
),
|
)
|
||||||
)
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20,),
|
const SizedBox(
|
||||||
TextFormField(
|
height: 20,
|
||||||
controller: TextEditingController(),
|
|
||||||
decoration:textBoxDecoration(suffixIcon: true)
|
|
||||||
),
|
),
|
||||||
Container(height: 100,)
|
TextFormField(
|
||||||
|
controller: TextEditingController(),
|
||||||
|
decoration: textBoxDecoration(suffixIcon: true)),
|
||||||
|
Container(
|
||||||
|
height: 100,
|
||||||
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -3,51 +3,54 @@ import 'package:flutter_svg/svg.dart';
|
|||||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
import 'package:syncrow_web/web_layout/web_app_bar.dart';
|
import 'package:syncrow_web/web_layout/web_app_bar.dart';
|
||||||
import 'menu_sidebar.dart';
|
import 'menu_sidebar.dart';
|
||||||
|
|
||||||
class WebScaffold extends StatelessWidget {
|
class WebScaffold extends StatelessWidget {
|
||||||
final bool enableMenuSideba;
|
final bool enableMenuSideba;
|
||||||
final Widget? appBarTitle;
|
final Widget? appBarTitle;
|
||||||
final List<Widget>? appBarBody;
|
final List<Widget>? appBarBody;
|
||||||
final Widget? scaffoldBody;
|
final Widget? scaffoldBody;
|
||||||
const WebScaffold({super.key,this.appBarTitle,this.appBarBody,this.scaffoldBody,this.enableMenuSideba=true});
|
const WebScaffold(
|
||||||
|
{super.key,
|
||||||
|
this.appBarTitle,
|
||||||
|
this.appBarBody,
|
||||||
|
this.scaffoldBody,
|
||||||
|
this.enableMenuSideba = true});
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
body: Stack(
|
body: Stack(
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
width: MediaQuery.sizeOf(context).width,
|
||||||
|
height: MediaQuery.sizeOf(context).height,
|
||||||
|
child: SvgPicture.asset(
|
||||||
|
Assets.webBackground,
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
color: Colors.white.withOpacity(0.7),
|
||||||
|
),
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
children: [
|
children: [
|
||||||
SizedBox(
|
Opacity(
|
||||||
width: MediaQuery.sizeOf(context).width,
|
opacity: 0.7,
|
||||||
height: MediaQuery.sizeOf(context).height,
|
child: WebAppBar(
|
||||||
child: SvgPicture.asset(
|
title: appBarTitle,
|
||||||
Assets.webBackground,
|
body: appBarBody,
|
||||||
fit: BoxFit.cover,
|
)),
|
||||||
|
Expanded(
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
if (enableMenuSideba) const MenuSidebar(),
|
||||||
|
Expanded(flex: 5, child: scaffoldBody!)
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
)
|
||||||
Container(color: Colors.white.withOpacity(0.7),),
|
|
||||||
Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
||||||
children: [
|
|
||||||
Opacity(
|
|
||||||
opacity: 0.7,
|
|
||||||
child: WebAppBar(
|
|
||||||
title: appBarTitle,
|
|
||||||
body: appBarBody,
|
|
||||||
)
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
if(enableMenuSideba)
|
|
||||||
const MenuSidebar(),
|
|
||||||
Expanded(
|
|
||||||
flex: 5,
|
|
||||||
child: scaffoldBody!
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
));
|
),
|
||||||
|
],
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user