visitor password

This commit is contained in:
mohammad
2024-08-13 17:08:18 +03:00
parent 350888c9da
commit 2d0f85bded
15 changed files with 920 additions and 282 deletions

View File

@ -2,7 +2,8 @@
{
"accessUser": "Ali Doe",
"accessType": "Admin",
"accessPeriod": "2023-08-01",
"startTime": "2023-08-01",
"endTime": "2023-08-02",
"accessibleDevice": "Smart Door",
"authorizationSource": "System",
"authorizer": "Jane Smith",
@ -12,8 +13,9 @@
}, {
"accessUser": "oamr Doe",
"accessType": "Admin",
"accessPeriod": "2023-08-01",
"accessibleDevice": "Smart Door",
"startTime": "2023-08-01",
"endTime": "2023-08-05",
"accessibleDevice": "Smart Door",
"authorizationSource": "System",
"authorizer": "Jane Smith",
"authorizationTime": "2023-08-01 10:00 AM",
@ -22,7 +24,8 @@
}, {
"accessUser": "John Doe",
"accessType": "Admin",
"accessPeriod": "2023-08-01",
"startTime": "2023-08-01",
"endTime": "2023-08-10",
"accessibleDevice": "Smart Door",
"authorizationSource": "System",
"authorizer": "Jane Smith",
@ -34,7 +37,8 @@
{
"accessUser": "John Doe",
"accessType": "Admin",
"accessPeriod": "2023-08-01",
"startTime": "2023-08-01",
"endTime": "2023-10-10",
"accessibleDevice": "Smart Door",
"authorizationSource": "System",
"authorizer": "Jane Smith",
@ -45,7 +49,8 @@
{
"accessUser": "John Doe",
"accessType": "Admin",
"accessPeriod": "2023-08-01",
"startTime": "2023-03-01",
"endTime": "2023-05-10",
"accessibleDevice": "Smart Door",
"authorizationSource": "System",
"authorizer": "Jane Smith",
@ -56,7 +61,8 @@
{
"accessUser": "John Doe",
"accessType": "Admin",
"accessPeriod": "2023-08-01 ",
"startTime": "2023-07-01",
"endTime": "2023-08-10",
"accessibleDevice": "Smart Door",
"authorizationSource": "System",
"authorizer": "Jane Smith",
@ -66,7 +72,8 @@
}, {
"accessUser": "John Doe",
"accessType": "Admin",
"accessPeriod": "2023-08-01 ",
"startTime": "2023-01-01",
"endTime": "2023-09-05",
"accessibleDevice": "Smart Door",
"authorizationSource": "System",
"authorizer": "Jane Smith",
@ -77,7 +84,8 @@
{
"accessUser": "Alice Johnson",
"accessType": "User",
"accessPeriod": "2023-08-01 to 2023-08-31",
"startTime": "2023-08-01",
"endTime": "2023-08-10",
"accessibleDevice": "Smart Lock",
"authorizationSource": "Admin",
"authorizer": "John Doe",

View File

@ -1,10 +1,12 @@
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/access_management/view/access_management.dart';
import 'package:syncrow_web/pages/auth/bloc/auth_bloc.dart';
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/view/visitor_password_dialog.dart';
import 'package:syncrow_web/services/locator.dart';
import 'package:syncrow_web/utils/color_manager.dart';
@ -56,7 +58,8 @@ class MyApp extends StatelessWidget {
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), // Set up color scheme
useMaterial3: true, // Enable Material 3
),
home: isLoggedIn == 'Success' ? const HomePage() : const LoginPage(),
home: VisitorPasswordDialog()
// isLoggedIn == 'Success' ? const HomePage() : const LoginPage(),
));
}
}

View File

@ -1,26 +1,181 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_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/access_management/model/access_manag_model.dart';
import 'package:syncrow_web/pages/access_management/model/password_model.dart';
import 'package:syncrow_web/services/access_mang_api.dart';
import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/snack_bar.dart';
class AccessBloc extends Bloc<AccessEvent, AccessState> {
AccessBloc() : super((AccessInitial())) {
on<FetchTableData>(_onFetchTableData);
on<TabChangedEvent>(selectFilterTap);
on<SelectTime>(selectTime);
on<FilterDataEvent>(_filterData);
on<ResetSearch>(resetSearch);
}
String startTime = 'Start Time';
String endTime = 'End Time';
int? effectiveTimeTimeStamp;
int? expirationTimeTimeStamp;
TextEditingController passwordName= TextEditingController();
List<PasswordModel> filteredData = []; // To store filtered data
List<PasswordModel> data=[];
Future<void> _onFetchTableData(
FetchTableData event, Emitter<AccessState> emit) async {
try {
emit(AccessLoaded());
List<AccessManagModel> data = await AccessMangApi().fetchInfo();
print('objectwww888888${data[0].accessPeriod}');
emit(TableLoaded(data));
data = await AccessMangApi().fetchVisitorPassword();
emit(TableLoaded(data));
} catch (e) {
emit(FailedState(e.toString()));
}
}
int selectedIndex = 0;
final List<String> tabs = [
'All',
'To Be Effective (0)',
'Effective (0)',
'Expired'
];
Future selectFilterTap(TabChangedEvent event, Emitter<AccessState> emit) async {
try {
emit(AccessLoaded());
selectedIndex= event.selectedIndex;
emit(AccessInitial());
emit(TableLoaded(data));
} catch (e) {
emit(FailedState( e.toString()));
return;
}
}
Future<void> selectTime(SelectTime event, Emitter<AccessState> emit) async {
final DateTime? picked = await showDatePicker(
context: event.context,
initialDate: DateTime.now(),
firstDate: DateTime(2015, 8),
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,
selectedDateTime.month,
selectedDateTime.day,
selectedDateTime.hour,
selectedDateTime.minute,
).millisecondsSinceEpoch ~/ 1000; // Divide by 1000 to remove milliseconds
if (event.isStart) {
if (expirationTimeTimeStamp != null && selectedTimestamp > expirationTimeTimeStamp!) {
CustomSnackBar.displaySnackBar('Effective Time cannot be later than Expiration Time.');
} else {
startTime = selectedDateTime.toString().split('.').first; // Remove seconds and milliseconds
effectiveTimeTimeStamp = selectedTimestamp;
}
} else {
if (effectiveTimeTimeStamp != null && selectedTimestamp < effectiveTimeTimeStamp!) {
CustomSnackBar.displaySnackBar('Expiration Time cannot be earlier than Effective Time.');
} else {
endTime = selectedDateTime.toString().split('.').first; // Remove seconds and milliseconds
expirationTimeTimeStamp = selectedTimestamp;
}
}
}
}
emit(AccessInitial());
emit(TableLoaded(data));
}
Future<void> _filterData(FilterDataEvent event, Emitter<AccessState> emit) async {
emit(AccessLoaded());
try {
// Filter the data based on the provided criteria
filteredData = data.where((item) {
bool matchesCriteria = true;
// Check if the password name should be used for filtering
if (event.passwordName != null && event.passwordName!.isNotEmpty) {
final bool matchesName = item.passwodName != null &&
item.passwodName.contains(event.passwordName!);
if (!matchesName) {
matchesCriteria = false;
}
}
// Check if the time range should be used for filtering
if (event.startTime != null && event.endTime != null) {
// Ensure effectiveTime and invalidTime are treated as integers
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;
}
}
}
return matchesCriteria;
}).toList();
print('Filtered data: $filteredData'); // Print to debug filtered data
emit(TableLoaded(filteredData));
} catch (e) {
print('Error occurred during filtering: $e');
}
}
// ResetSearch
resetSearch(ResetSearch event, Emitter<AccessState> emit) async{
emit(AccessLoaded());
startTime = 'Start Time';
endTime = 'End Time';
passwordName.clear();
add(FetchTableData());
}
DateTime timestampToDateTime(dynamic timestamp) {
return DateTime.fromMillisecondsSinceEpoch(int.parse(timestamp) * 1000);
}
}

View File

@ -1,5 +1,6 @@
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
abstract class AccessEvent extends Equatable {
const AccessEvent();
@ -8,4 +9,32 @@ abstract class AccessEvent extends Equatable {
List<Object> get props => [];
}
class FetchTableData extends AccessEvent {}
class ResetSearch extends AccessEvent {}
class TabChangedEvent extends AccessEvent {
final int selectedIndex;
const TabChangedEvent(this.selectedIndex);
}
class SelectTime extends AccessEvent {
final BuildContext context;
final bool isStart;
const SelectTime({required this.context,required this.isStart});
@override
List<Object> get props => [context,isStart];
}
class FilterDataEvent extends AccessEvent {
final String? passwordName;
final int? startTime;
final int? endTime;
const FilterDataEvent({
this.passwordName,
this.startTime,
this.endTime,
});
}

View File

@ -1,5 +1,5 @@
import 'package:equatable/equatable.dart';
import 'package:syncrow_web/pages/access_management/model/access_manag_model.dart';
import 'package:syncrow_web/pages/access_management/model/password_model.dart';
abstract class AccessState extends Equatable {
const AccessState();
@ -21,7 +21,7 @@ class FailedState extends AccessState {
}
class TableLoaded extends AccessState {
final List<AccessManagModel> data;
final List<PasswordModel> data;
const TableLoaded(this.data);
@ -29,3 +29,12 @@ class TableLoaded extends AccessState {
List<Object> get props => [data];
}
class TabState extends AccessState {
final int selectedIndex;
const TabState({required this.selectedIndex});
}
class ChangeTimeState extends AccessState {}
class TimeSelectedState extends AccessState {}

View File

@ -1,37 +0,0 @@
class AccessManagModel {
final String accessUser;
final String accessType;
final String accessPeriod;
final String accessibleDevice;
final String authorizationSource;
final String authorizer;
final String authorizationTime;
final String accessStatus;
final String actions;
AccessManagModel({
required this.accessUser,
required this.accessType,
required this.accessPeriod,
required this.accessibleDevice,
required this.authorizationSource,
required this.authorizer,
required this.authorizationTime,
required this.accessStatus,
required this.actions,
});
factory AccessManagModel.fromJson(Map<String, dynamic> json) {
return AccessManagModel(
accessUser: json['accessUser'],
accessType: json['accessType'],
accessPeriod: json['accessPeriod'],
accessibleDevice: json['accessibleDevice'],
authorizationSource: json['authorizationSource'],
authorizer: json['authorizer'],
authorizationTime: json['authorizationTime'],
accessStatus: json['accessStatus'],
actions: json['actions'],
);
}
}

View File

@ -0,0 +1,54 @@
class PasswordModel {
final dynamic passwordId;
final dynamic invalidTime;
final dynamic effectiveTime;
final dynamic passwordCreated;
final dynamic createdTime;
final dynamic passwodName; // New field
final dynamic passwordStatus;
final dynamic passwordType;
final dynamic deviceUuid;
PasswordModel({
this.passwordId,
this.invalidTime,
this.effectiveTime,
this.passwordCreated,
this.createdTime,
this.passwodName, // New field
this.passwordStatus,
this.passwordType,
this.deviceUuid,
});
factory PasswordModel.fromJson(Map<String, dynamic> json) {
return PasswordModel(
passwordId: json['passwordId'],
invalidTime: json['invalidTime'],
effectiveTime: json['effectiveTime'],
passwordCreated: json['passwordCreated'],
createdTime: json['createdTime'],
passwodName: json['passwodName']??'No name', // New field
passwordStatus: json['passwordStatus'],
passwordType: json['passwordType'],
deviceUuid: json['deviceUuid'],
);
}
Map<String, dynamic> toJson() {
return {
'passwordId': passwordId,
'invalidTime': invalidTime,
'effectiveTime': effectiveTime,
'passwordCreated': passwordCreated,
'createdTime': createdTime,
'passwodName': passwodName, // New field
'passwordStatus': passwordStatus,
'passwordType': passwordType,
'deviceUuid': deviceUuid,
};
}
List<PasswordModel> parsePasswordList(List<dynamic> jsonList) {
return jsonList.map((json) => PasswordModel.fromJson(json)).toList();
}
}

View File

@ -5,9 +5,9 @@ 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/default_button.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/constants/assets.dart';
import 'package:syncrow_web/utils/snack_bar.dart';
import 'package:syncrow_web/utils/style.dart';
import 'package:syncrow_web/web_layout/web_scaffold.dart';
@ -35,16 +35,15 @@ class AccessManagementPage extends StatelessWidget {
.copyWith(color: Colors.white),
),
],
scaffoldBody: BlocProvider(
create: (BuildContext context) => AccessBloc()..add(FetchTableData() ),
child: BlocConsumer<AccessBloc, AccessState>(
listener: (context, state) {
scaffoldBody: BlocProvider(create: (BuildContext context) => AccessBloc()..add(FetchTableData()),
child: BlocConsumer<AccessBloc, AccessState>(listener: (context, state) {
if (state is FailedState) {
// CustomSnackBar.displaySnackBar(
// state.errorMessage
// );
}
}, builder: (context, state) {
final accessBloc = BlocProvider.of<AccessBloc>(context);
return Container(
padding: EdgeInsets.all(30),
height: size.height,
@ -53,233 +52,294 @@ class AccessManagementPage extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: size.width * 0.3,
height: size.height * 0.05,
width:size.width * 0.26 ,
decoration: containerDecoration,
child: const Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Text('All'),
Text('To Be Effective (0)'),
Text('Effective (0)'),
Text('Expired'),
],
child: Center(
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: BlocProvider.of<AccessBloc>(context).tabs.length,
itemBuilder: (context, index) {
final isSelected = index ==
BlocProvider.of<AccessBloc>(context).selectedIndex;
return InkWell(
onTap: () {
BlocProvider.of<AccessBloc>(context).add(TabChangedEvent(index));
},
child: Container(
decoration: BoxDecoration(
color: ColorsManager.boxColor,
border: Border.all(
color: isSelected ? Colors.blue : Colors.transparent,
width: 2.0,),
borderRadius: index == 0
? const BorderRadius.only(
topLeft: Radius.circular(10),
bottomLeft: Radius.circular(10))
: index == 3
? const BorderRadius.only(
topRight: Radius.circular(10),
bottomRight: Radius.circular(10))
: null),
padding: const EdgeInsets.only(left: 10,right: 10),
child: Center(
child: Text(
BlocProvider.of<AccessBloc>(context).tabs[index],
style: TextStyle(
color: isSelected
? Colors.blue
: Colors.black,
),
),
),
),
);
},
),
),
),
const SizedBox(
height: 20,
),
Wrap(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text('User Name'),
Container(
width: size.width*0.15,
decoration: containerDecoration,
child: TextFormField(
decoration: textBoxDecoration()!
.copyWith(hintText: 'Please enter'),
)),
],
),
const SizedBox(width: 15,),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
const Text('Email Address'),
Container(
width: size.width*0.15,
decoration: containerDecoration,
child: TextFormField(
decoration: textBoxDecoration()!
.copyWith(hintText: 'Please enter'),
)),
],
),
const SizedBox(width: 15,),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
const Text('Access Time'),
Container(
width: size.width*0.18,
padding: EdgeInsets.all(10),
decoration: containerDecoration,
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
InkWell(child: Text(BlocProvider.of<AccessBloc>(context).startTime)),
const Icon(Icons.arrow_right_alt),
InkWell(child: Text(BlocProvider.of<AccessBloc>(context).endTime)),
SvgPicture.asset(
Assets.calendarIcon,
),
],
),
],
)),
],
),
const SizedBox(width: 15,),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
const Text('Authorization Source'),
Container(
width: size.width*0.18,
decoration: containerDecoration,
child: TextFormField(
decoration: textBoxDecoration(),
)),
],
),
const SizedBox(width: 15,),
SizedBox(
width: size.width*0.06,
child: Column(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(''),
const Text('Password Name'),
Container(
width: size.width * 0.15,
decoration: containerDecoration,
child: DefaultButton(child: Text('Search'),borderRadius: 9)),
child: TextFormField(
controller: accessBloc.passwordName,
style: TextStyle(color: Colors.black),
decoration: textBoxDecoration()!
.copyWith(hintText: 'Please enter'),
)),
],
),
),
const SizedBox(width: 10,),
SizedBox(
width: size.width*0.06,
child: Column(
const SizedBox(
width: 15,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(''),
const Text('Access Time'),
Container(
decoration: containerDecoration,
child: DefaultButton(
backgroundColor: ColorsManager.whiteColors,borderRadius: 9,
child: Text('Reset'
,style: Theme.of(context).textTheme.bodySmall!.copyWith(color: Colors.black),)
,),
),
],
),
),
],
),
const SizedBox(
height: 20,
),
Wrap(children: [
Container(
width: size.width*0.15,
decoration: containerDecoration,
child: const DefaultButton(
borderRadius: 8,
child: Text('+ Create Visitor Password ')),
),
const SizedBox(width: 10,),
Container(
width: size.width*0.12,
decoration: containerDecoration,
child: DefaultButton(
borderRadius: 8,
backgroundColor: ColorsManager.whiteColors,
child: Text('Admin Password'
,style: Theme.of(context).textTheme.bodySmall!.copyWith(color: Colors.black),)
))
],),
const SizedBox(
height: 20,
),
Expanded(
child:state is TableLoaded?
Container(
decoration: containerDecoration,
width: size.width,
child: Padding(
padding: const EdgeInsets.all(10.0),
child: ListView(
scrollDirection: Axis.horizontal,
children: [
Container(
width: size.width,
height:size.height ,
width: size.width * 0.25,
padding: EdgeInsets.all(10),
decoration: containerDecoration,
child: Column(
children: [
Container(
color: ColorsManager.boxColor,
child: Row(
children: [
_buildTableHeaderCell('Access User'),
_buildTableHeaderCell('Access Type'),
_buildTableHeaderCell('Access Period'),
_buildTableHeaderCell('Accessible Device'),
_buildTableHeaderCell('Authorization Source'),
_buildTableHeaderCell('Authorizer'),
_buildTableHeaderCell('Authorization Time'),
_buildTableHeaderCell('Access Status'),
_buildTableHeaderCell('Actions'),
],
),
),
Expanded(
child: Container(
width: size.width,
color: ColorsManager.whiteColors,
child: ListView(
shrinkWrap: true,
children: [
Column(
children: state.data.map((item) {
return Row(
children: [
_buildTableCell(item.accessUser),
_buildTableCell(item.accessType),
_buildTableCell(item.accessPeriod),
_buildTableCell(item.accessibleDevice),
_buildTableCell(item.authorizationSource),
_buildTableCell(item.authorizer),
_buildTableCell(item.authorizationTime),
_buildTableCell(item.accessStatus),
_buildTableCell(item.actions),
],
);
}).toList(),
),
],
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
InkWell(
onTap: () {
accessBloc.add(SelectTime(context: context, isStart: true));
},
child: Text(BlocProvider.of<AccessBloc>(context).startTime)
),
),
const Icon(Icons.arrow_right_alt),
InkWell(
onTap: () {
accessBloc.add(SelectTime(context: context, isStart: false));
},
child: Text(BlocProvider.of<AccessBloc>(context).endTime)),
SvgPicture.asset(
Assets.calendarIcon,
),
],
),
],
)),
],
),
const SizedBox(
width: 15,
),
SizedBox(
width: size.width * 0.06,
child: Column(
children: [
Text(''),
Container(
decoration: containerDecoration,
child: DefaultButton(
onPressed: () {
accessBloc.add(FilterDataEvent(
passwordName: accessBloc.passwordName.text,
startTime: accessBloc.effectiveTimeTimeStamp,
endTime: accessBloc.expirationTimeTimeStamp
));
}, borderRadius: 9,
child: const Text('Search'))),
],
),
),
const SizedBox(
width: 10,
),
SizedBox(
width: size.width * 0.06,
child: Column(
children: [
Text(''),
Container(
decoration: containerDecoration,
child: DefaultButton(
onPressed: () {
accessBloc.add(ResetSearch());
},
backgroundColor: ColorsManager.whiteColors,
borderRadius: 9,
child: Text(
'Reset',
style: Theme.of(context)
.textTheme
.bodySmall!
.copyWith(color: Colors.black),
),
),
),
],
),
),
):const Center(child: CircularProgressIndicator())
)
],
),
const SizedBox(
height: 20,
),
Wrap(
children: [
Container(
width: size.width * 0.15,
decoration: containerDecoration,
child: DefaultButton(
onPressed: () {
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return const VisitorPasswordDialog();
},
);
},
borderRadius: 8,
child: Text('+ Create Visitor Password ')),
),
const SizedBox(
width: 10,
),
Container(
width: size.width * 0.12,
decoration: containerDecoration,
child: DefaultButton(
borderRadius: 8,
backgroundColor: ColorsManager.whiteColors,
child: Text(
'Admin Password',
style: Theme.of(context)
.textTheme
.bodySmall!
.copyWith(color: Colors.black),
)))
],
),
const SizedBox(
height: 20,
),
Expanded(
child: state is TableLoaded
? TableWidget(size, state,accessBloc)
: const Center(child: CircularProgressIndicator()))
],
),
);
})));
}
Container TableWidget(Size size, TableLoaded state,AccessBloc accessBloc) {
return Container(
decoration: containerDecoration,
width: size.width,
child: Padding(
padding: const EdgeInsets.all(10.0),
child: ListView(
scrollDirection: Axis.horizontal,
children: [
Container(
width: size.width,
height: size.height,
child: Column(
children: [
Container(
color: ColorsManager.boxColor,
child: Row(
children: [
_buildTableHeaderCell('Password name'),
_buildTableHeaderCell(' Password Type'),
_buildTableHeaderCell('Start Time'),
_buildTableHeaderCell('End Time'),
_buildTableHeaderCell('Device Id'),
// _buildTableHeaderCell('Authorization Source'),
// _buildTableHeaderCell('Authorizer'),
_buildTableHeaderCell('Password Created'),
// _buildTableHeaderCell('Access Status'),
_buildTableHeaderCell('Password Status'),
],
),
),
Expanded(
child: Container(
width: size.width,
color: ColorsManager.whiteColors,
child: ListView(
shrinkWrap: true,
children: [
Column(
children: state.data.map((item) {
return Row(
children: [
_buildTableCell(item.passwodName),
_buildTableCell(item.passwordType),
_buildTableCell(accessBloc.timestampToDateTime(item.effectiveTime).toString()),
_buildTableCell(accessBloc.timestampToDateTime(item.invalidTime).toString()),
_buildTableCell(item.deviceUuid.toString()),
// _buildTableCell(item.authorizationSource),
// _buildTableCell(item.authorizer),
_buildTableCell(item.passwordCreated!=null?accessBloc.timestampToDateTime(item.passwordCreated).toString():'no data'),
// _buildTableCell(item.accessStatus),
_buildTableCell(item.passwordStatus.toString()),
],
);
}).toList(),
),
],
),
),
),
],
),
),
],
),
),
);
}
}
Widget _buildTableHeaderCell(String title) {
return Expanded(
child: Container(
decoration: const BoxDecoration(
border: Border.symmetric(vertical: BorderSide(color: ColorsManager.boxDivider))
),
border: Border.symmetric(
vertical: BorderSide(color: ColorsManager.boxDivider))),
alignment: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.all(8.0),
@ -292,12 +352,21 @@ Widget _buildTableHeaderCell(String title) {
Widget _buildTableCell(String content) {
return Expanded(
child: Container(
height: 80,
padding: const EdgeInsets.all(20.0),
decoration: const BoxDecoration(
border: Border.symmetric(horizontal: BorderSide(color: ColorsManager.boxDivider))
decoration: BoxDecoration(
border: Border(
bottom: BorderSide( // <--- right side
color: ColorsManager.boxDivider,
width: 1.0,
),
)
),
alignment: Alignment.centerLeft,
child: Text(content,style: TextStyle(color: Colors.black,fontSize: 12),),
child: Text(
content,
style: TextStyle(color: Colors.black, fontSize: 12),
),
),
);
}

View File

@ -0,0 +1,13 @@
import 'package:flutter_bloc/flutter_bloc.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';
// Define the BLoC
class VisitorPasswordBloc extends Bloc<VisitorPasswordEvent, VisitorPasswordState> {
VisitorPasswordBloc() : super(VisitorPasswordInitial()) {
on<SelectPasswordType>((event, emit) {
// Handle the event and emit the new state
emit(PasswordTypeSelected(event.type));
});
}
}

View File

@ -0,0 +1,23 @@
import 'package:equatable/equatable.dart';
abstract class VisitorPasswordEvent extends Equatable {
const VisitorPasswordEvent(
);
@override
List<Object> get props => [];
}
class SelectPasswordType extends VisitorPasswordEvent {
final String type;
const SelectPasswordType(this.type);
@override
List<Object> get props => [type];
}

View File

@ -0,0 +1,23 @@
import 'package:equatable/equatable.dart';
abstract class VisitorPasswordState extends Equatable {
const VisitorPasswordState();
@override
List<Object> get props => [];
}
class VisitorPasswordInitial extends VisitorPasswordState {}
class PasswordTypeSelected extends VisitorPasswordState {
final String selectedType;
PasswordTypeSelected(this.selectedType);
@override
List<Object> get props => [selectedType];
}

View File

@ -0,0 +1,290 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_bloc.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/utils/color_manager.dart';
import 'package:syncrow_web/utils/style.dart';
class VisitorPasswordDialog extends StatelessWidget {
const VisitorPasswordDialog({super.key});
@override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return BlocProvider(
create: (context) => VisitorPasswordBloc(),
child: BlocBuilder<VisitorPasswordBloc, VisitorPasswordState>(
builder: (context, state) {
return AlertDialog(
title: const Text('Create visitor password'),
content: SingleChildScrollView(
child: ListBody(
children: <Widget>[
Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Row(
children: [
Text(
'* ',
style: Theme.of(context)
.textTheme
.bodyMedium!
.copyWith(color: Colors.red),
),
const Text('User Name'),
],
),
Container(
width: size.width * 0.15,
decoration: containerDecoration,
child: TextFormField(
style: TextStyle(color: Colors.black),
decoration: textBoxDecoration()!
.copyWith(hintText: 'Please enter'),
),
),
],
),
SizedBox(width: size.width * 0.05), // Add spacing between columns
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Row(
children: [
Text(
'* ',
style: Theme.of(context)
.textTheme
.bodyMedium!
.copyWith(color: Colors.red),
),
const Text('Email Address'),
],
),
Container(
width: size.width * 0.15,
decoration: containerDecoration,
child: TextFormField(
style: TextStyle(color: Colors.black),
decoration: textBoxDecoration()!
.copyWith(hintText: 'Please enter'),
),
),
],
),
],
),
SizedBox(height: size.height * 0.02), // Add spacing
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Row(
children: [
Text(
'* ',
style: Theme.of(context)
.textTheme
.bodyMedium!
.copyWith(color: Colors.red),
),
const Text('Access Type'),
],
),
Row(
children: <Widget>[
SizedBox(
width: 200,
child: RadioListTile<String>(
title: Text('Offline Password'),
value: 'Offline Password',
groupValue: (state is PasswordTypeSelected)
? state.selectedType
: 'Offline Password',
onChanged: (String? value) {
if (value != null) {
context
.read<VisitorPasswordBloc>()
.add(SelectPasswordType(value));
}
},
),
),
SizedBox(
width: 200,
child: RadioListTile<String>(
title: Text('Online Password'),
value: 'Online Password',
groupValue: (state is PasswordTypeSelected)
? state.selectedType
: 'Offline Password',
onChanged: (String? value) {
if (value != null) {
context
.read<VisitorPasswordBloc>()
.add(SelectPasswordType(value));
}
},
),
),
SizedBox(
width: 200,
child: RadioListTile<String>(
title: Text('Dynamic Password'),
value: 'Dynamic Password',
groupValue: (state is PasswordTypeSelected)
? state.selectedType
: 'Offline Password',
onChanged: (String? value) {
if (value != null) {
context
.read<VisitorPasswordBloc>()
.add(SelectPasswordType(value));
}
},
),
),
],
)
],
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Row(
children: [
Text(
'* ',
style: Theme.of(context)
.textTheme
.bodyMedium!
.copyWith(color: Colors.red),
),
const Text('Usage Frequency'),
],
),
Row(
children: <Widget>[
SizedBox(
width: 200,
child: RadioListTile<String>(
title: const Text('One-Time'),
value: 'One-Time',
groupValue: (state is PasswordTypeSelected)
? state.selectedType
: 'One-Time',
onChanged: (String? value) {
if (value != null) {
context
.read<VisitorPasswordBloc>()
.add(SelectPasswordType(value));
}
},
),
),
SizedBox(
width: 200,
child: RadioListTile<String>(
title: Text('Periodic'),
value: 'Periodic',
groupValue: (state is PasswordTypeSelected)
? state.selectedType
: 'Periodic',
onChanged: (String? value) {
if (value != null) {
context
.read<VisitorPasswordBloc>()
.add(SelectPasswordType(value));
}
},
),
),
],
)
],
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Row(
children: [
Text(
'* ',
style: Theme.of(context)
.textTheme
.bodyMedium!
.copyWith(color: Colors.red),
),
const Text('Access Period'),
],
),
Row(
children: <Widget>[
SizedBox(
width: 200,
child: RadioListTile<String>(
title: const Text('One-Time'),
value: 'One-Time',
groupValue: (state is PasswordTypeSelected)
? state.selectedType
: 'One-Time',
onChanged: (String? value) {
if (value != null) {
context
.read<VisitorPasswordBloc>()
.add(SelectPasswordType(value));
}
},
),
),
SizedBox(
width: 200,
child: RadioListTile<String>(
title: Text('Periodic'),
value: 'Periodic',
groupValue: (state is PasswordTypeSelected)
? state.selectedType
: 'Periodic',
onChanged: (String? value) {
if (value != null) {
context
.read<VisitorPasswordBloc>()
.add(SelectPasswordType(value));
}
},
),
),
],
)
],
),
],
),
),
actions: <Widget>[
TextButton(
child: const Text('Approve'),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
),
);
}
}

View File

@ -1,36 +1,37 @@
import 'dart:convert';
import 'package:flutter/services.dart';
import 'package:syncrow_web/pages/access_management/model/access_manag_model.dart';
import 'package:syncrow_web/pages/auth/model/user_model.dart';
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/services/api/http_service.dart';
import 'package:syncrow_web/utils/constants/api_const.dart';
class AccessMangApi{
// Future<List<AccessManagModel>> fetchInfo() async {
// final response = await HTTPService().get(
// path: '/Users/mohammad/StudioProjects/web_auth/assets/demo.json',
// showServerMessage: true,
// expectedResponseModel: (json) {
// print('fetchInfo=$json');
// return (json as List).map((item) => AccessManagModel.fromJson(item)).toList();
// },
// );
// return response;
// }
Future<List<AccessManagModel>> fetchInfo() async {
// Load the JSON file
final jsonString = await rootBundle.loadString('assets/dome.json');
// Parse the JSON string
final List<dynamic> jsonList = json.decode(jsonString);
print('jsonList=${jsonList.runtimeType}');
print('jsonList=${jsonList}');
// Convert the list of JSON objects to a list of AccessManagModel instances
final List<AccessManagModel> accessList = jsonList.map((item) => AccessManagModel.fromJson(item)).toList();
return accessList;
Future<List<PasswordModel>> fetchVisitorPassword() async {
try {
final response = await HTTPService().get(
path: ApiEndpoints.visitorPassword,
showServerMessage: true,
expectedResponseModel: (json) {
List<dynamic> jsonData = json;
print('Password List: $json');
List<PasswordModel> passwordList = jsonData.map((jsonItem) {
return PasswordModel.fromJson(jsonItem);
}).toList();
return passwordList;
},
);
return response;
} catch (e) {
debugPrint('Error fetching visitor passwords: $e');
return [];
}
}
}

View File

@ -50,8 +50,7 @@ class AuthenticationAPI {
}
);
return 30;
} on DioError catch (e) {
} on DioException catch (e) {
if (e.response != null) {
if (e.response!.statusCode == 400) {
// Handle 400 Bad Request
@ -64,7 +63,6 @@ class AuthenticationAPI {
int cooldown = errorData['data']['cooldown'] ?? 1;
return cooldown;
}
} else {
debugPrint('Error: ${e.response!.statusCode} - ${e.response!.statusMessage}');
return 1;
@ -73,7 +71,6 @@ class AuthenticationAPI {
debugPrint('Error: ${e.message}');
return 1;
}
return 1;
} catch (e) {
debugPrint('Unexpected Error: $e');
return 1;

View File

@ -9,5 +9,6 @@ abstract class ApiEndpoints {
static const String sendOtp = '$baseUrl/authentication/user/send-otp';
static const String verifyOtp = '$baseUrl/authentication/user/verify-otp';
static const String getRegion = '$baseUrl/region';
static const String visitorPassword = '$baseUrl/visitor-password';
static const String getUser = '$baseUrl/user/{userUuid}';
}