This commit is contained in:
mohammad
2024-08-26 19:44:55 +03:00
parent e331d35a6c
commit 2e3f130071
14 changed files with 674 additions and 258 deletions

View File

@ -6,6 +6,7 @@ import 'package:syncrow_web/pages/auth/view/login_page.dart';
import 'package:syncrow_web/pages/home/bloc/home_bloc.dart';
import 'package:syncrow_web/pages/home/view/home_page.dart';
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_bloc.dart';
import 'package:syncrow_web/pages/visitor_password/view/visitor_password_dialog.dart';
import 'package:syncrow_web/services/locator.dart';
import 'package:syncrow_web/utils/color_manager.dart';
@ -56,10 +57,10 @@ class MyApp extends StatelessWidget {
fontWeight: FontWeight.bold,
),
),
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), // Set up color scheme
useMaterial3: true, // Enable Material 3
),
// home:VisitorPasswordDialog(),
home:isLoggedIn == 'Success' ? const HomePage() : const LoginPage(),
));
}

View File

@ -81,34 +81,12 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
lastDate: DateTime(2101),
);
if (picked != null) {
final TimeOfDay? timePicked = await showTimePicker(
context: event.context,
initialTime: TimeOfDay.now(),
builder: (context, child) {
return Theme(
data: ThemeData.light().copyWith(
colorScheme: const ColorScheme.light(
primary: ColorsManager.primaryColor,
onSurface: Colors.black,
),
buttonTheme: const ButtonThemeData(
colorScheme: ColorScheme.light(
primary: Colors.green,
),
),
),
child: child!,
);
},
);
if (timePicked != null) {
final selectedDateTime = DateTime(
picked.year,
picked.month,
picked.day,
timePicked.hour,
timePicked.minute,
);
final selectedTimestamp = DateTime(
selectedDateTime.year,
@ -132,17 +110,23 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
expirationTimeTimeStamp = selectedTimestamp;
}
}
}
}
emit(ChangeTimeState());
}
Future<void> _filterData(FilterDataEvent event, Emitter<AccessState> emit) async {
emit(AccessLoaded());
try {
filteredData = data.where((item) {
bool matchesCriteria = true;
// Convert timestamp to DateTime and extract date component
DateTime effectiveDate = DateTime.fromMillisecondsSinceEpoch(int.parse(item.effectiveTime.toString()) * 1000).toUtc().toLocal();
DateTime invalidDate = DateTime.fromMillisecondsSinceEpoch(int.parse(item.invalidTime.toString()) * 1000).toUtc().toLocal();
DateTime effectiveDateOnly = DateTime(effectiveDate.year, effectiveDate.month, effectiveDate.day);
DateTime invalidDateOnly = DateTime(invalidDate.year, invalidDate.month, invalidDate.day);
// Filter by password name
if (event.passwordName != null && event.passwordName!.isNotEmpty) {
final bool matchesName = item.passwordName != null &&
item.passwordName.contains(event.passwordName);
@ -150,19 +134,37 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
matchesCriteria = false;
}
}
if (event.startTime != null && event.endTime != null) {
final int? effectiveTime = int.tryParse(item.effectiveTime.toString());
final int? invalidTime = int.tryParse(item.invalidTime.toString());
if (effectiveTime == null || invalidTime == null) {
// Filter by start date only
if (event.startTime != null && event.endTime == null) {
DateTime startDateOnly = DateTime.fromMillisecondsSinceEpoch(event.startTime! * 1000).toUtc().toLocal();
startDateOnly = DateTime(startDateOnly.year, startDateOnly.month, startDateOnly.day);
if (effectiveDateOnly.isBefore(startDateOnly)) {
matchesCriteria = false;
} else {
final bool matchesStartTime = effectiveTime >= event.startTime!;
final bool matchesEndTime = invalidTime <= event.endTime!;
if (!matchesStartTime || !matchesEndTime) {
matchesCriteria = false;
}
}
}
// Filter by end date only
if (event.endTime != null && event.startTime == null) {
DateTime endDateOnly = DateTime.fromMillisecondsSinceEpoch(event.endTime! * 1000).toUtc().toLocal();
endDateOnly = DateTime(endDateOnly.year, endDateOnly.month, endDateOnly.day);
if (invalidDateOnly.isAfter(endDateOnly)) {
matchesCriteria = false;
}
}
// Filter by both start date and end date
if (event.startTime != null && event.endTime != null) {
DateTime startDateOnly = DateTime.fromMillisecondsSinceEpoch(event.startTime! * 1000).toUtc().toLocal();
DateTime endDateOnly = DateTime.fromMillisecondsSinceEpoch(event.endTime! * 1000).toUtc().toLocal();
startDateOnly = DateTime(startDateOnly.year, startDateOnly.month, startDateOnly.day);
endDateOnly = DateTime(endDateOnly.year, endDateOnly.month, endDateOnly.day);
if (effectiveDateOnly.isBefore(startDateOnly) || invalidDateOnly.isAfter(endDateOnly)) {
matchesCriteria = false;
}
}
// Filter by selected tab index
if (event.selectedTabIndex == 1 && item.passwordStatus.value != 'To Be Effective') {
matchesCriteria = false;
} else if (event.selectedTabIndex == 2 && item.passwordStatus.value != 'Effective') {
@ -170,14 +172,122 @@ class AccessBloc extends Bloc<AccessEvent, AccessState> {
} else if (event.selectedTabIndex == 3 && item.passwordStatus.value != 'Expired') {
matchesCriteria = false;
}
return matchesCriteria;
}).toList();
emit(TableLoaded(filteredData));
} catch (e) {
emit(FailedState(e.toString()));
}
}
// Future<void> _filterData(FilterDataEvent event, Emitter<AccessState> emit) async {
// emit(AccessLoaded());
// try {
// filteredData = data.where((item) {
// bool matchesCriteria = true;
//
// // Filter by password name
// if (event.passwordName != null && event.passwordName!.isNotEmpty) {
// final bool matchesName = item.passwordName != null &&
// item.passwordName.contains(event.passwordName);
// if (!matchesName) {
// matchesCriteria = false;
// }
// }
//
// // Filter by start time only
// if (event.startTime != null && event.endTime == null) {
// final int? effectiveTime = int.tryParse(item.effectiveTime.toString());
// if (effectiveTime == null || effectiveTime < event.startTime!) {
// matchesCriteria = false;
// }
// }
//
// // Filter by end time only
// if (event.endTime != null && event.startTime == null) {
// final int? invalidTime = int.tryParse(item.invalidTime.toString());
// if (invalidTime == null || invalidTime > event.endTime!) {
// matchesCriteria = false;
// }
// }
//
// // Filter by both start time and end time
// if (event.startTime != null && event.endTime != null) {
// final int? effectiveTime = int.tryParse(item.effectiveTime.toString());
// final int? invalidTime = int.tryParse(item.invalidTime.toString());
// if (effectiveTime == null || invalidTime == null) {
// matchesCriteria = false;
// } else {
// final bool matchesStartTime = effectiveTime >= event.startTime!;
// final bool matchesEndTime = invalidTime <= event.endTime!;
// if (!matchesStartTime || !matchesEndTime) {
// matchesCriteria = false;
// }
// }
// }
//
// // Filter by selected tab index
// if (event.selectedTabIndex == 1 && item.passwordStatus.value != 'To Be Effective') {
// matchesCriteria = false;
// } else if (event.selectedTabIndex == 2 && item.passwordStatus.value != 'Effective') {
// matchesCriteria = false;
// } else if (event.selectedTabIndex == 3 && item.passwordStatus.value != 'Expired') {
// matchesCriteria = false;
// }
//
// return matchesCriteria;
// }).toList();
//
// emit(TableLoaded(filteredData));
// } catch (e) {
// emit(FailedState(e.toString()));
// }
// }
// Future<void> _filterData(FilterDataEvent event, Emitter<AccessState> emit) async {
// emit(AccessLoaded());
// try {
// filteredData = data.where((item) {
// bool matchesCriteria = true;
// if (event.passwordName != null && event.passwordName!.isNotEmpty) {
// final bool matchesName = item.passwordName != null &&
// item.passwordName.contains(event.passwordName);
// if (!matchesName) {
// matchesCriteria = false;
// }
// }
// if (event.startTime != null || event.endTime != null) {
// final int? effectiveTime = int.tryParse(item.effectiveTime.toString());
// final int? invalidTime = int.tryParse(item.invalidTime.toString());
// if (effectiveTime == null || invalidTime == null) {
// matchesCriteria = false;
// } else {
// final bool matchesStartTime = effectiveTime >= event.startTime!;
// final bool matchesEndTime = invalidTime <= event.endTime!;
// if (!matchesStartTime || !matchesEndTime) {
// matchesCriteria = false;
// }
// }
// }
// if (event.selectedTabIndex == 1 && item.passwordStatus.value != 'To Be Effective') {
// matchesCriteria = false;
// } else if (event.selectedTabIndex == 2 && item.passwordStatus.value != 'Effective') {
// matchesCriteria = false;
// } else if (event.selectedTabIndex == 3 && item.passwordStatus.value != 'Expired') {
// matchesCriteria = false;
// }
// return matchesCriteria;
// }).toList();
// emit(TableLoaded(filteredData));
// } catch (e) {
// emit(FailedState(e.toString()));
// }
// }
resetSearch(ResetSearch event, Emitter<AccessState> emit) async{
emit(AccessLoaded());
startTime = 'Start Time';

View File

@ -4,6 +4,7 @@ import 'package:syncrow_web/pages/access_management/bloc/access_bloc.dart';
import 'package:syncrow_web/pages/access_management/bloc/access_event.dart';
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_web_textfield.dart';
import 'package:syncrow_web/pages/common/date_time_widget.dart';
import 'package:syncrow_web/pages/common/default_button.dart';
import 'package:syncrow_web/pages/visitor_password/view/visitor_password_dialog.dart';
@ -101,27 +102,15 @@ class AccessManagementPage extends StatelessWidget {
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end,
textBaseline: TextBaseline.ideographic, children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('Name',
style: Theme.of(context).textTheme.bodySmall!.copyWith(
color: Colors.black,fontSize: 13),),
const SizedBox(height: 5,),
Container(
height:43,
width: size.width * 0.15,
decoration: containerDecoration,
child: TextFormField(
controller: accessBloc.passwordName,
style: const TextStyle(color: Colors.black),
decoration: textBoxDecoration()!
.copyWith(hintText: 'Please enter'),
)
),
],
Container(
width: size.width * 0.15,
child: CustomWebTextField(
controller: accessBloc.passwordName,
isRequired: true,
textFieldName: 'Name',
description: '',
),
),
const SizedBox(
width: 15,
),

View File

@ -7,6 +7,7 @@ Future<void> showCustomDialog({
required String message,
String? title,
String? iconPath,
Widget? widget,
double? dialogHeight,
double? iconHeight,
double? iconWidth,
@ -53,6 +54,8 @@ Future<void> showCustomDialog({
textAlign: TextAlign.center,
),
),
if(widget!=null)
Expanded(child:widget)
],
),
),

View File

@ -73,7 +73,7 @@ class CustomWebTextField extends StatelessWidget {
decoration: textBoxDecoration()!
.copyWith(
errorStyle: const TextStyle(height: 0), // Hide the error text space
hintStyle: TextStyle(color: ColorsManager.grayColor),
hintText: 'Please enter'),
),
),

View File

@ -49,7 +49,7 @@ class DateTimeWebWidget extends StatelessWidget {
),
const SizedBox(height: 8,),
Container(
height:size.height * 0.055 ,
height:50 ,
padding: EdgeInsets.only(top: 10,bottom: 10,right: 30,left: 10),
decoration: containerDecoration,
child: FittedBox(
@ -69,7 +69,6 @@ class DateTimeWebWidget extends StatelessWidget {
SizedBox(width: 30,),
const Icon(Icons.arrow_right_alt),
SizedBox(width: 30,),
InkWell(
onTap:endTime,
child: FittedBox(

View File

@ -18,16 +18,25 @@ class HomeCard extends StatelessWidget {
});
@override
Widget build(BuildContext context) {
bool evenNumbers = index % 2 == 0;
// bool evenNumbers = index % 2 == 0;
return InkWell(
onTap: active ? onTap : null,
child: Container(
padding: const EdgeInsets.only(left: 10,right: 10,bottom: 10),
decoration: BoxDecoration(
color: evenNumbers && active?
ColorsManager.blueColor.withOpacity(0.8) :
(active ?ColorsManager.blueColor
: ColorsManager.blueColor.withOpacity(0.2)),
color: index==0&&active?
ColorsManager.blue1.withOpacity(0.9):
index==1&&active?
ColorsManager.blue2.withOpacity(0.9) :
index==2&&active?
ColorsManager.blue3:
index==4&&active==false?
ColorsManager.blue4.withOpacity(0.2):
index==7&&active==false?
ColorsManager.blue4.withOpacity(0.2):
ColorsManager.blueColor.withOpacity(0.2),
// (active ?ColorsManager.blueColor
// : ColorsManager.blueColor.withOpacity(0.2)),
borderRadius: BorderRadius.circular(30),
),
child: Column(

View File

@ -1,4 +1,5 @@
import 'dart:math';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:intl/intl.dart';
@ -7,6 +8,7 @@ import 'package:syncrow_web/pages/common/hour_picker_dialog.dart';
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_event.dart';
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_state.dart';
import 'package:syncrow_web/pages/visitor_password/model/device_model.dart';
import 'package:syncrow_web/pages/visitor_password/model/failed_operation.dart';
import 'package:syncrow_web/pages/visitor_password/model/schedule_model.dart';
import 'package:syncrow_web/services/access_mang_api.dart';
import 'package:syncrow_web/utils/color_manager.dart';
@ -62,7 +64,7 @@ class VisitorPasswordBloc
String startTimeAccess = 'Start Time';
String endTimeAccess = 'End Time';
PasswordStatus? passwordStatus;
selectAccessType(
SelectPasswordType event, Emitter<VisitorPasswordState> emit) {
accessTypeSelected = event.type;
@ -197,26 +199,23 @@ class VisitorPasswordBloc
try {
emit(LoadingInitialState());
generate7DigitNumber();
bool res = await AccessMangApi().postOnlineOneTime(
var res = await AccessMangApi().postOnlineOneTime(
email: event.email,
password: passwordController,
devicesUuid: selectedDevices,
passwordName: event.passwordName,
effectiveTime: effectiveTimeTimeStamp.toString(),
invalidTime: expirationTimeTimeStamp.toString());
if (res == true) {
if(res['statusCode']==201){
passwordStatus= PasswordStatus.fromJson(res['data']);
emit(SuccessState());
} else {
throw Exception('Failed to create password');
}
emit(TableLoaded(data));
} catch (e) {
emit(FailedState(e.toString()));
Navigator.pop(event.context!);
stateDialog(
context: event.context!,
message: e.toString(),
title: 'Something Wrong');
} on DioException catch (e){
final errorData = e.response!.data;
String errorMessage = errorData['message'];
print('errorMessage==$errorData');
emit(FailedState(errorMessage.toString()));
}
}
@ -228,13 +227,12 @@ class VisitorPasswordBloc
emit(LoadingInitialState());
await generate7DigitNumber();
bool res = await AccessMangApi().postOnlineMultipleTime(
var res = await AccessMangApi().postOnlineMultipleTime(
scheduleList: [
if (repeat)
Schedule(
effectiveTime: getTimeFromDateTimeString(expirationTime),
invalidTime:
getTimeFromDateTimeString(effectiveTime).toString(),
invalidTime: getTimeFromDateTimeString(effectiveTime).toString(),
workingDay: selectedDays,
),
],
@ -244,47 +242,42 @@ class VisitorPasswordBloc
email: event.email,
devicesUuid: selectedDevices,
passwordName: event.passwordName);
if (res == true) {
if(res['statusCode']==201){
passwordStatus= PasswordStatus.fromJson(res['data']);
emit(SuccessState());
}else {
throw Exception('Failed to create password');
}
emit(TableLoaded(data));
} catch (e) {
emit(FailedState(e.toString()));
Navigator.pop(event.context!);
stateDialog(
context: event.context!,
message: e.toString(),
title: 'Something Wrong');
} on DioException catch (e){
final errorData = e.response!.data;
String errorMessage = errorData['message'];
print('errorMessage==$errorData');
emit(FailedState(errorMessage.toString()));
}
}
//offline password
Future<void> postOfflineOneTimePassword(OfflineOneTimePasswordEvent event,
Future<void> postOfflineOneTimePassword(
OfflineOneTimePasswordEvent event,
Emitter<VisitorPasswordState> emit) async {
try {
emit(LoadingInitialState());
await generate7DigitNumber();
bool res = await AccessMangApi().postOffLineOneTime(
var res = await AccessMangApi().postOffLineOneTime(
email: event.email,
devicesUuid: selectedDevices,
passwordName: event.passwordName);
if (res == true) {
if(res['statusCode']==201){
passwordStatus= PasswordStatus.fromJson(res['data']);
emit(SuccessState());
}else {
throw Exception('Failed to create password');
}
emit(TableLoaded(data));
} catch (e) {
emit(FailedState(e.toString()));
Navigator.pop(event.context!);
stateDialog(
context: event.context!,
message: e.toString(),
title: 'Something Wrong');
} on DioException catch (e){
final errorData = e.response!.data;
String errorMessage = errorData['message'];
print('errorMessage==$errorData');
emit(FailedState(errorMessage.toString()));
}
}
@ -294,27 +287,24 @@ class VisitorPasswordBloc
try {
emit(LoadingInitialState());
await generate7DigitNumber();
bool res = await AccessMangApi().postOffLineMultipleTime(
var res = await AccessMangApi().postOffLineMultipleTime(
email: event.email,
devicesUuid: selectedDevices,
passwordName: event.passwordName,
invalidTime: expirationTimeTimeStamp.toString(),
effectiveTime: effectiveTimeTimeStamp.toString(),
);
if (res == true) {
if(res['statusCode']==201){
passwordStatus= PasswordStatus.fromJson(res['data']);
emit(SuccessState());
}else {
throw Exception('Failed to create password');
}
emit(TableLoaded(data));
} catch (e) {
emit(FailedState(e.toString()));
Navigator.pop(event.context!);
stateDialog(
context: event.context!,
message: e.toString(),
title: 'Something Wrong'); }
} on DioException catch (e){
final errorData = e.response!.data;
String errorMessage = errorData['message'];
print('errorMessage==$errorData');
emit(FailedState(errorMessage.toString()));
}
}
void selectDevice(
@ -476,13 +466,15 @@ class VisitorPasswordBloc
String? message,
String? title,
dynamic actions,
Widget? widgeta,
}) {
return showCustomDialog(
context: context!,
message: message!,
iconPath: Assets.deviceNoteIcon,
title: title,
dialogHeight: 150,
widget: widgeta,
dialogHeight: MediaQuery.of(context).size.height*0.3,
actions: actions ??
<Widget>[
TextButton(
@ -494,4 +486,31 @@ class VisitorPasswordBloc
],
);
}
//
// Future<void> stateAndDeviseDialog({
// BuildContext? context,
// String? message,
// String? title,
// dynamic actions,
// }) {
// return showCustomDialog(
// context: context!,
// message: message!,
// iconPath: Assets.deviceNoteIcon,
// title: title,
// dialogHeight: 150,
// actions: actions ??
// <Widget>[
// TextButton(
// onPressed: () {
// Navigator.of(context).pop();
// },
// child: const Text('OK'),
// ),
// ],
// );
// }
}

View File

@ -0,0 +1,124 @@
class FailedOperation {
final bool success;
final dynamic deviceUuid;
final dynamic error;
FailedOperation({
required this.success,
required this.deviceUuid,
required this.error,
});
factory FailedOperation.fromJson(Map<String, dynamic> json) {
return FailedOperation(
success: json['success'],
deviceUuid: json['deviceUuid'],
error: json['error'],
);
}
Map<String, dynamic> toJson() {
return {
'success': success,
'deviceUuid': deviceUuid,
'error': error,
};
}
}
class SuccessOperation {
final bool success;
// final Result result;
final String deviceUuid;
SuccessOperation({
required this.success,
// required this.result,
required this.deviceUuid,
});
factory SuccessOperation.fromJson(Map<String, dynamic> json) {
return SuccessOperation(
success: json['success'],
// result: Result.fromJson(json['result']),
deviceUuid: json['deviceUuid'],
);
}
Map<String, dynamic> toJson() {
return {
'success': success,
// 'result': result.toJson(),
'deviceUuid': deviceUuid,
};
}
}
// class Result {
// final dynamic effectiveTime;
// final dynamic invalidTime;
// final dynamic offlineTempPassword;
// final dynamic offlineTempPasswordId;
// final dynamic offlineTempPasswordName;
//
// Result({
// required this.effectiveTime,
// required this.invalidTime,
// required this.offlineTempPassword,
// required this.offlineTempPasswordId,
// required this.offlineTempPasswordName,
// });
//
// factory Result.fromJson(Map<String, dynamic> json) {
// return Result(
// effectiveTime: json['effective_time'],
// invalidTime: json['invalid_time'],
// offlineTempPassword: json['offline_temp_password'].toString(),
// offlineTempPasswordId: json['offline_temp_password_id'],
// offlineTempPasswordName: json['offline_temp_password_name'],
// );
// }
//
// Map<String, dynamic> toJson() {
// return {
// 'effective_time': effectiveTime,
// 'invalid_time': invalidTime,
// 'offline_temp_password': offlineTempPassword,
// 'offline_temp_password_id': offlineTempPasswordId,
// 'offline_temp_password_name': offlineTempPasswordName,
// };
// }
// }
class PasswordStatus {
final List<SuccessOperation> successOperations;
final List<FailedOperation> failedOperations;
PasswordStatus({
required this.successOperations,
required this.failedOperations,
});
factory PasswordStatus.fromJson(Map<String, dynamic> json) {
return PasswordStatus(
successOperations: (json['successOperations'] as List)
.map((i) => SuccessOperation.fromJson(i))
.toList(),
failedOperations: (json['failedOperations'] as List)
.map((i) => FailedOperation.fromJson(i))
.toList(),
);
}
Map<String, dynamic> toJson() {
return {
'successOperations': successOperations.map((e) => e.toJson()).toList(),
'failedOperations': failedOperations.map((e) => e.toJson()).toList(),
};
}
}

View File

@ -32,6 +32,56 @@ class VisitorPasswordDialog extends StatelessWidget {
context: context,
message: 'Password Created Successfully',
title: 'Send Success',
widgeta:Column(
children: [
if(visitorBloc.passwordStatus!.failedOperations.isNotEmpty)
Column(
children: [
const Text('Failed Devises'),
SizedBox(
width: 200,
height: 50,
child: ListView.builder(
scrollDirection: Axis.horizontal,
shrinkWrap: true,
itemCount:visitorBloc.passwordStatus!.failedOperations.length ,
itemBuilder: (context, index) {
return Container(
margin: EdgeInsets.all(5),
decoration: containerDecoration,
height: 45,
child: Center(child: Text(visitorBloc.passwordStatus!.failedOperations[index].deviceUuid)),
);
},),
),
],
),
if(visitorBloc.passwordStatus!.successOperations.isNotEmpty)
Column(
children: [
const Text('Success Devises'),
SizedBox(
width: 200,
height: 50,
child: ListView.builder(
scrollDirection: Axis.horizontal,
shrinkWrap: true,
itemCount:visitorBloc.passwordStatus!.successOperations.length ,
itemBuilder: (context, index) {
return Container(
margin: EdgeInsets.all(5),
decoration: containerDecoration,
height: 45,
child: Center(child: Text(visitorBloc.passwordStatus!.successOperations[index].deviceUuid)),
);
},),
),
],
),
],
)
);
} else if (state is FailedState) {
visitorBloc.stateDialog(
@ -110,68 +160,92 @@ class VisitorPasswordDialog extends StatelessWidget {
),
Row(
children: <Widget>[
Flexible(
child: RadioListTile<String>(
contentPadding: EdgeInsets.zero,
title: Text('Online Password',
style: text,
),
value: 'Online Password',
groupValue: (state is PasswordTypeSelected)
? state.selectedType
: visitorBloc.accessTypeSelected,
onChanged: (String? value) {
if (value != null) {
context.read<VisitorPasswordBloc>()
.add(SelectPasswordType(value));
}
},
),
),
Flexible(
child: RadioListTile<String>(
contentPadding: EdgeInsets.zero,
title: Text('Offline Password',
style:text ),
value: 'Offline Password',
groupValue: (state is PasswordTypeSelected)
? state.selectedType
: visitorBloc.accessTypeSelected,
onChanged: (String? value) {
if (value != null) {
context.read<VisitorPasswordBloc>().add(SelectPasswordType(value));
}
},
),
),
Flexible(
child: RadioListTile<String>(
contentPadding: EdgeInsets.zero,
title: Text('Dynamic Password',
style: text,),
value: 'Dynamic Password',
groupValue: (state is PasswordTypeSelected)
? state.selectedType
: visitorBloc.accessTypeSelected,
onChanged: (String? value) {
if (value != null) {
context.read<VisitorPasswordBloc>()
.add(SelectPasswordType(value));
visitorBloc.usageFrequencySelected = '';
}
},
),
),
children: <Widget>[
Expanded(
flex: 2,
child: Row(
children: [
SizedBox(
width: size.width*0.12,
child: RadioListTile<String>(
contentPadding: EdgeInsets.zero,
title: Text('Online Password',
style: text,
),
value: 'Online Password',
groupValue: (state is PasswordTypeSelected)
? state.selectedType
: visitorBloc.accessTypeSelected,
onChanged: (String? value) {
if (value != null) {
context.read<VisitorPasswordBloc>()
.add(SelectPasswordType(value));
}
},
),
),
SizedBox(
width: size.width*0.12,
child: RadioListTile<String>(
contentPadding: EdgeInsets.zero,
title: Text('Offline Password',
style:text ),
value: 'Offline Password',
groupValue: (state is PasswordTypeSelected)
? state.selectedType
: visitorBloc.accessTypeSelected,
onChanged: (String? value) {
if (value != null) {
context.read<VisitorPasswordBloc>().add(SelectPasswordType(value));
}
},
),
),
SizedBox(
width: size.width*0.12,
child: RadioListTile<String>(
contentPadding: EdgeInsets.zero,
title: Text('Dynamic Password',
style: text,),
value: 'Dynamic Password',
groupValue: (state is PasswordTypeSelected)
? state.selectedType
: visitorBloc.accessTypeSelected,
onChanged: (String? value) {
if (value != null) {
context.read<VisitorPasswordBloc>()
.add(SelectPasswordType(value));
visitorBloc.usageFrequencySelected = '';
}
},
),
),
],
)),
const Spacer(flex: 2,),
],
),
if(visitorBloc.accessTypeSelected == 'Online Password')
Text(
'Only currently online devices can be selected. It is recommended to use when the device network is stable, and the system randomly generates a digital password',
style: Theme.of(context).textTheme.bodySmall!.copyWith(
fontWeight: FontWeight.w400,
color: ColorsManager.grayColor,fontSize: 9),
),
if(visitorBloc.accessTypeSelected == 'Offline Password')
Text(
'Unaffected by the online status of the device, you can select online or offline device, and the system randomly generates a digital password',
style: Theme.of(context).textTheme.bodySmall!.copyWith(
fontWeight: FontWeight.w400,
color: ColorsManager.grayColor,fontSize: 9),),
if(visitorBloc.accessTypeSelected == 'Dynamic Password')
Text(
'Quick and short-acting password, only valid within 5 minutes after creation, the system randomly generates a digital password.',
style: Theme.of(context).textTheme.bodySmall!.copyWith(
fontWeight: FontWeight.w400,
color: ColorsManager.grayColor,fontSize: 9),),
const SizedBox(
height: 20,
)
@ -179,7 +253,7 @@ class VisitorPasswordDialog extends StatelessWidget {
),
visitorBloc.accessTypeSelected == 'Dynamic Password'
? const SizedBox()
: Column(
: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
@ -193,7 +267,8 @@ class VisitorPasswordDialog extends StatelessWidget {
),
Row(
children: <Widget>[
Flexible(
SizedBox(
width: size.width*0.12,
child: RadioListTile<String>(
contentPadding: EdgeInsets.zero,
title: Text('One-Time',
@ -205,13 +280,13 @@ class VisitorPasswordDialog extends StatelessWidget {
: visitorBloc.usageFrequencySelected,
onChanged: (String? value) {
if (value != null) {
context.read<VisitorPasswordBloc>()
.add(SelectUsageFrequency(value));
context.read<VisitorPasswordBloc>().add(SelectUsageFrequency(value));
}
},
),
),
Flexible(
SizedBox(
width: size.width*0.12,
child: RadioListTile<String>(
contentPadding: EdgeInsets.zero,
title: Text('Periodic',
@ -230,10 +305,35 @@ class VisitorPasswordDialog extends StatelessWidget {
),
],
),
//One-Time
if (visitorBloc.usageFrequencySelected == 'One-Time' &&
visitorBloc.accessTypeSelected == 'Online Password')
Text('Within the validity period, each device can be unlocked only once.',
style: Theme.of(context).textTheme.bodySmall!.copyWith(
color: ColorsManager.grayColor,fontSize: 9),
)
),
if (visitorBloc.usageFrequencySelected == 'One-Time' &&
visitorBloc.accessTypeSelected == 'Offline Password')
Text('Within the validity period, there is no limit to the number of times each device can be unlocked.',
style: Theme.of(context).textTheme.bodySmall!.copyWith(
color: ColorsManager.grayColor,fontSize: 9),
),
// Periodic
if (visitorBloc.usageFrequencySelected == 'Periodic' &&
visitorBloc.accessTypeSelected == 'Offline Password')
Text('Within the validity period, there is no limit to the number of times each device can be unlocked, and it should be used at least once within 24 hours after the entry into force.',
style: Theme.of(context).textTheme.bodySmall!.copyWith(
color: ColorsManager.grayColor,fontSize: 9),
),
if (visitorBloc.usageFrequencySelected == 'Periodic' &&
visitorBloc.accessTypeSelected == 'Online Password')
Text('Within the validity period, there is no limit to the number of times each device can be unlocked.',
style: Theme.of(context).textTheme.bodySmall!.copyWith(
color: ColorsManager.grayColor,fontSize: 9),
),
],
),
const SizedBox(
@ -247,19 +347,37 @@ class VisitorPasswordDialog extends StatelessWidget {
title: 'Access Period',
size: size,
endTime: () {
visitorBloc.add(SelectTimeVisitorPassword(
context: context,
isStart: false,
isRepeat: false));
if (visitorBloc.usageFrequencySelected == 'Periodic' &&
visitorBloc.accessTypeSelected == 'Offline Password'){
visitorBloc.add(SelectTimeEvent(
context: context,
isEffective: false));
}else{
visitorBloc.add(SelectTimeVisitorPassword(
context: context,
isStart: false,
isRepeat: false));
}
},
startTime: () {
visitorBloc.add(SelectTimeVisitorPassword(
context: context,
isStart: true,
isRepeat: false));
if (visitorBloc.usageFrequencySelected == 'Periodic' &&
visitorBloc.accessTypeSelected == 'Offline Password'){
visitorBloc.add(SelectTimeEvent(context: context, isEffective: true));
}else{
visitorBloc.add(SelectTimeVisitorPassword(
context: context,
isStart: true,
isRepeat: false));
}
},
firstString: visitorBloc.startTimeAccess.toString(),
secondString: visitorBloc.endTimeAccess.toString(),
firstString:
(visitorBloc.usageFrequencySelected == 'Periodic' &&
visitorBloc.accessTypeSelected == 'Offline Password')?
visitorBloc.effectiveTime:visitorBloc.startTimeAccess.toString(),
secondString: (visitorBloc.usageFrequencySelected == 'Periodic' &&
visitorBloc.accessTypeSelected == 'Offline Password')?
visitorBloc.expirationTime:visitorBloc.endTimeAccess.toString(),
icon: Assets.calendarIcon
),
const SizedBox(
@ -367,12 +485,26 @@ class VisitorPasswordDialog extends StatelessWidget {
onPressed: () {
if (visitorBloc.forgetFormKey.currentState!.validate()) {
if(visitorBloc.selectedDevices.isNotEmpty){
if(visitorBloc.effectiveTimeTimeStamp!=null&&visitorBloc.expirationTimeTimeStamp!=null) {
if(visitorBloc.usageFrequencySelected == 'One-Time' && visitorBloc.accessTypeSelected == 'Offline Password'){
setPasswordFunction(context, size, visitorBloc);
}
else{
visitorBloc.stateDialog(context:
context,message: 'Please select Access Period to continue',title: 'Access Period');
}else{
if(visitorBloc.effectiveTimeTimeStamp!=null&&visitorBloc.expirationTimeTimeStamp!=null) {
if(isRepeat==true){
if(visitorBloc.expirationTime!='End Time'&&visitorBloc.effectiveTime!='Start Time'&&visitorBloc.selectedDays.isNotEmpty){
setPasswordFunction(context, size, visitorBloc);
}
else{
visitorBloc.stateDialog(context:
context,message: 'Please select days and fill start time and end time to continue',title: 'Access Period');
}
}else{
setPasswordFunction(context, size, visitorBloc);
}
}
else{
visitorBloc.stateDialog(context:
context,message: 'Please select Access Period to continue',title: 'Access Period');
}
}
}else{
visitorBloc.stateDialog(context:
@ -380,6 +512,57 @@ class VisitorPasswordDialog extends StatelessWidget {
}
}
},
// onPressed: () {
// if (visitorBloc.forgetFormKey.currentState!.validate()) {
// if (visitorBloc.selectedDevices.isNotEmpty) {
// switch (visitorBloc.usageFrequencySelected) {
// case 'One-Time':
// if (visitorBloc.accessTypeSelected == 'Offline Password') {
// setPasswordFunction(context, size, visitorBloc);
// } else {
// visitorBloc.stateDialog(
// context: context,
// message: 'Invalid combination of Access Type and Usage Frequency.',
// title: 'Error',
// );
// }
// break;
// default:
// if (visitorBloc.effectiveTimeTimeStamp != null && visitorBloc.expirationTimeTimeStamp != null) {
// if (isRepeat) {
// if (visitorBloc.expirationTime != 'End Time' &&
// visitorBloc.effectiveTime != 'Start Time' &&
// visitorBloc.selectedDays.isNotEmpty) {
// setPasswordFunction(context, size, visitorBloc);
// } else {
// visitorBloc.stateDialog(
// context: context,
// message: 'Please select days and fill start time and end time to continue',
// title: 'Access Period',
// );
// }
// } else {
// setPasswordFunction(context, size, visitorBloc);
// }
// } else {
// visitorBloc.stateDialog(
// context: context,
// message: 'Please select Access Period to continue',
// title: 'Access Period',
// );
// }
// break;
// }
// } else {
// visitorBloc.stateDialog(
// context: context,
// message: 'Please select devices to continue',
// title: 'Select Devices',
// );
// }
// }
// },
borderRadius: 8,
child: Text('Ok', style: Theme.of(context).textTheme.bodySmall!.copyWith(
fontWeight: FontWeight.w400,

View File

@ -3,6 +3,7 @@ import 'package:dio/dio.dart';
import 'package:flutter/cupertino.dart';
import 'package:syncrow_web/pages/access_management/model/password_model.dart';
import 'package:syncrow_web/pages/visitor_password/model/device_model.dart';
import 'package:syncrow_web/pages/visitor_password/model/failed_operation.dart';
import 'package:syncrow_web/pages/visitor_password/model/schedule_model.dart';
import 'package:syncrow_web/services/api/http_service.dart';
import 'package:syncrow_web/utils/constants/api_const.dart';
@ -49,14 +50,13 @@ class AccessMangApi{
}
}
Future<bool> postOnlineOneTime({
Future postOnlineOneTime({
String? email,
String? passwordName,
String? password,
String? effectiveTime,
String? invalidTime,
List<String>? devicesUuid}) async {
try {
final response = await HTTPService().post(
path: ApiEndpoints.sendOnlineOneTime,
body: jsonEncode({
@ -69,19 +69,11 @@ class AccessMangApi{
}),
showServerMessage: true,
expectedResponseModel: (json) {
if(json['statusCode'].toString()=='201'){
return true;
}else{
return false;
}
return json;
},
);
return response;
} on DioException catch (e) {
debugPrint('Error: ${e.message}');
debugPrint('Error fetching ${e.response!.statusMessage}');
return false;
}
}
Future postOnlineMultipleTime({
@ -92,7 +84,6 @@ class AccessMangApi{
String? passwordName,
List<Schedule>? scheduleList,
List<String>? devicesUuid}) async {
try {
Map<String, dynamic> body = {
"email": email,
"devicesUuid": devicesUuid,
@ -109,25 +100,16 @@ class AccessMangApi{
body: jsonEncode(body),
showServerMessage: true,
expectedResponseModel: (json) {
if(json['data']['successOperations'][0]['success'].toString()=='true'){
return true;
}else{
return false;
}
return json;
},
);
return response;
} on DioException catch (e){
debugPrint('Error fetching ${e.type.name}');
debugPrint('Error fetching ${e.response!.statusMessage}');
return false;
}
}
// OffLine One Time Password
Future postOffLineOneTime({String? email,String? passwordName,List<String>? devicesUuid}) async {
try {
final response = await HTTPService().post(
path: ApiEndpoints.sendOffLineOneTime,
body: jsonEncode({
@ -136,20 +118,12 @@ class AccessMangApi{
"devicesUuid": devicesUuid
}),
showServerMessage: true,
expectedResponseModel: (json) {
if (json['data']['successOperations'][0]['success'].toString() ==
'true') {
return true;
} else {
return false;
}
}
expectedResponseModel: (json) {
return json;
},
);
return response;
} catch (e) {
debugPrint('Error fetching $e');
return [];
}
}
Future postOffLineMultipleTime({
@ -158,32 +132,31 @@ class AccessMangApi{
String? effectiveTime,
String? invalidTime,
List<String>? devicesUuid
}) async {
try {
print(jsonEncode({
"email": email,
"devicesUuid": devicesUuid,
"passwordName": passwordName,
"effectiveTime": effectiveTime,
"invalidTime": invalidTime,
}));
final response = await HTTPService().post(
path: ApiEndpoints.sendOffLineOneTime,
path: ApiEndpoints.sendOffLineMultipleTime,
body: jsonEncode({
"email": email,
"devicesUuid":devicesUuid,
"devicesUuid": devicesUuid,
"passwordName": passwordName,
"effectiveTime": effectiveTime,
"invalidTime": invalidTime
"invalidTime": invalidTime,
}),
showServerMessage: true,
expectedResponseModel: (json) {
if (json['data']['successOperations'][0]['success'].toString() ==
'true') {
return true;
} else {
return false;
}
}
expectedResponseModel: (json) {
return json;
},
);
return response;
} catch (e) {
debugPrint('Error fetching $e');
return [];
}
}
}
}

View File

@ -62,7 +62,8 @@ class AuthenticationAPI {
debugPrint('Error: ${e.response!.statusCode} - ${e.response!.statusMessage}');
return 1;
}
} else {
}
else {
debugPrint('Error: ${e.message}');
return 1;
}

View File

@ -32,4 +32,9 @@ abstract class ColorsManager {
static const Color blueColor = Color(0xFF0036E6);
static const Color boxColor = Color(0xFFF5F6F7);
static const Color boxDivider = Color(0xFFE0E0E0);
static const Color blue1 = Color(0xFF0036E6);
static const Color blue2 = Color(0xFF0026A2);
static const Color blue3 = Color(0xFF00165E);
static const Color blue4 = Color(0xFF001E7E);
}
//0036E6

View File

@ -260,18 +260,18 @@ packages:
dependency: transitive
description:
name: leak_tracker
sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05"
sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a"
url: "https://pub.dev"
source: hosted
version: "10.0.5"
version: "10.0.4"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806"
sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8"
url: "https://pub.dev"
source: hosted
version: "3.0.5"
version: "3.0.3"
leak_tracker_testing:
dependency: transitive
description:
@ -300,18 +300,18 @@ packages:
dependency: transitive
description:
name: material_color_utilities
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a"
url: "https://pub.dev"
source: hosted
version: "0.11.1"
version: "0.8.0"
meta:
dependency: transitive
description:
name: meta
sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7
sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
url: "https://pub.dev"
source: hosted
version: "1.15.0"
version: "1.12.0"
nested:
dependency: transitive
description:
@ -521,10 +521,10 @@ packages:
dependency: transitive
description:
name: test_api
sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb"
sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f"
url: "https://pub.dev"
source: hosted
version: "0.7.2"
version: "0.7.0"
typed_data:
dependency: transitive
description:
@ -569,10 +569,10 @@ packages:
dependency: transitive
description:
name: vm_service
sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d"
sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec"
url: "https://pub.dev"
source: hosted
version: "14.2.5"
version: "14.2.1"
web:
dependency: transitive
description: